core_proxy: prepare to rename pw_remote -> pw_core_proxy

The pw_remote object is really a wrapper around the pw_core_proxy.
The events it emits are also available in the core proxy and are
generally awkward to use.

With some clever new pw_core_proxy_* methods and a pw_core_connect
to create the core_proxy, we can convert all code away from pw_remote.

This is a first step in this conversion, using the pw_remote behind
the scenes. It leaks into some places because it really needs to become
its own struct in a next step.
This commit is contained in:
Wim Taymans 2019-12-06 11:48:40 +01:00
parent f8aabe69fe
commit 8a959ea7a1
37 changed files with 919 additions and 1185 deletions

View file

@ -70,8 +70,8 @@ typedef struct {
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;
uint32_t flags;
struct pw_stream *stream;
@ -410,7 +410,7 @@ static int snd_pcm_pipewire_prepare(snd_pcm_ioplug_t *io)
"Playback" : "Capture");
pw_properties_set(props, PW_KEY_MEDIA_ROLE, "Music");
pw->stream = pw_stream_new(pw->remote, pw->node_name, props);
pw->stream = pw_stream_new(pw->core_proxy, pw->node_name, props);
if (pw->stream == NULL)
goto error;
@ -750,66 +750,26 @@ static int pipewire_set_hw_constraint(snd_pcm_pipewire_t *pw)
return 0;
}
static void on_remote_state_changed(void *data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
static void on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
{
snd_pcm_pipewire_t *pw = data;
switch (state) {
case PW_REMOTE_STATE_ERROR:
pw_log_error(NAME" %p: error %s", pw, error);
/* fallthrough */
case PW_REMOTE_STATE_UNCONNECTED:
pw_log_error(NAME" %p: error id:%u seq:%d res:%d (%s): %s", pw,
id, seq, res, spa_strerror(res), message);
if (id == 0) {
pw->error = true;
if (pw->fd != -1)
pcm_poll_unblock_check(&pw->io);
/* fallthrough */
case PW_REMOTE_STATE_CONNECTED:
pw_thread_loop_signal(pw->main_loop, false);
break;
default:
break;
}
}
pw_thread_loop_signal(pw->main_loop, false);
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_remote_state_changed,
static const struct pw_core_proxy_events core_proxy_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.error = on_core_error,
};
static int remote_connect_sync(snd_pcm_pipewire_t *pw)
{
const char *error = NULL;
enum pw_remote_state state;
int res;
pw_thread_loop_lock(pw->main_loop);
if ((res = pw_remote_connect(pw->remote)) < 0) {
error = spa_strerror(res);
goto error;
}
while (true) {
state = pw_remote_get_state(pw->remote, &error);
if (state == PW_REMOTE_STATE_ERROR)
goto error;
if (state == PW_REMOTE_STATE_CONNECTED)
break;
pw_thread_loop_wait(pw->main_loop);
}
exit:
pw_thread_loop_unlock(pw->main_loop);
return res;
error:
SNDERR("PipeWire: Unable to connect: %s\n", error);
goto exit;
}
static int snd_pcm_pipewire_open(snd_pcm_t **pcmp, const char *name,
const char *node_name,
const char *playback_node,
@ -863,14 +823,18 @@ static int snd_pcm_pipewire_open(snd_pcm_t **pcmp, const char *name,
else
pw_properties_set(props, PW_KEY_APP_NAME, "ALSA plug-in");
pw->remote = pw_remote_new(pw->core, props, 0);
pw_remote_add_listener(pw->remote, &pw->remote_listener, &remote_events, pw);
if ((err = pw_thread_loop_start(pw->main_loop)) < 0)
goto error;
if ((err = remote_connect_sync(pw)) < 0)
pw_thread_loop_lock(pw->main_loop);
pw->core_proxy = pw_core_connect(pw->core, props, 0);
if (pw->core_proxy == NULL) {
err = -errno;
pw_thread_loop_unlock(pw->main_loop);
goto error;
}
pw_core_proxy_add_listener(pw->core_proxy, &pw->core_listener, &core_proxy_events, pw);
pw_thread_loop_unlock(pw->main_loop);
pw->fd = spa_system_eventfd_create(pw->loop->system, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK);

View file

@ -230,11 +230,9 @@ struct client {
struct pw_data_loop *loop;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;
struct pw_mempool *pool;
int last_sync;
bool error;
@ -536,35 +534,6 @@ jack_get_version_string(void)
return "0.0.0.0";
}
static void on_state_changed(void *data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
{
struct client *client = data;
pw_log_debug(NAME" %p: state %s", client, pw_remote_state_as_string(state));
switch (state) {
case PW_REMOTE_STATE_ERROR:
client->error = true;
/* fallthrough*/
case PW_REMOTE_STATE_UNCONNECTED:
/* don't call shutdown when we do client_close, only
* on unexpected errors */
if (client->shutdown_callback && !client->destroyed)
client->shutdown_callback(client->shutdown_arg);
/* fallthrough*/
case PW_REMOTE_STATE_CONNECTED:
pw_thread_loop_signal(client->context.loop, false);
break;
default:
break;
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
};
static void on_sync_reply(void *data, uint32_t id, int seq)
{
struct client *client = data;
@ -574,9 +543,26 @@ static void on_sync_reply(void *data, uint32_t id, int seq)
pw_thread_loop_signal(client->context.loop, false);
}
static void on_error(void *data, uint32_t id, int seq, int res, const char *message)
{
struct client *client = data;
pw_log_error(NAME" %p: error id:%u seq:%d res:%d (%s): %s", client,
id, seq, res, spa_strerror(res), message);
if (id == 0) {
client->error = true;
if (client->shutdown_callback && !client->destroyed)
client->shutdown_callback(client->shutdown_arg);
}
pw_thread_loop_signal(client->context.loop, false);
}
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_EVENTS,
PW_VERSION_CORE_PROXY_EVENTS,
.done = on_sync_reply,
.error = on_error,
};
static int do_sync(struct client *client)
@ -1108,7 +1094,7 @@ static int client_node_transport(void *object,
clean_transport(c);
c->mem = pw_mempool_map_id(c->remote->pool, mem_id,
c->mem = pw_mempool_map_id(c->pool, mem_id,
PW_MEMMAP_FLAG_READWRITE, offset, size, NULL);
if (c->mem == NULL) {
pw_log_debug(NAME" %p: can't map activation: %m", c);
@ -1160,7 +1146,7 @@ static int client_node_set_io(void *object,
void *ptr;
uint32_t tag[5] = { c->node_id, id, };
if ((mm = pw_mempool_find_tag(c->remote->pool, tag, sizeof(tag))) != NULL)
if ((mm = pw_mempool_find_tag(c->pool, tag, sizeof(tag))) != NULL)
pw_memmap_free(mm);
if (mem_id == SPA_ID_INVALID) {
@ -1168,7 +1154,7 @@ static int client_node_set_io(void *object,
size = 0;
}
else {
mm = pw_mempool_map_id(c->remote->pool, mem_id,
mm = pw_mempool_map_id(c->pool, mem_id,
PW_MEMMAP_FLAG_READWRITE, offset, size, tag);
if (mm == NULL) {
pw_log_warn(NAME" %p: can't map memory id %u", c, mem_id);
@ -1549,7 +1535,7 @@ static int client_node_port_use_buffers(void *object,
struct spa_buffer *buf;
struct pw_memmap *mm;
mm = pw_mempool_map_id(c->remote->pool, buffers[i].mem_id,
mm = pw_mempool_map_id(c->pool, buffers[i].mem_id,
fl, buffers[i].offset, buffers[i].size, NULL);
if (mm == NULL) {
pw_log_warn(NAME" %p: can't map memory id %u: %m", c, buffers[i].mem_id);
@ -1589,7 +1575,7 @@ static int client_node_port_use_buffers(void *object,
struct pw_memblock *bm;
struct pw_memmap *bmm;
bm = pw_mempool_find_id(c->remote->pool, mem_id);
bm = pw_mempool_find_id(c->pool, mem_id);
if (bm == NULL) {
pw_log_error(NAME" %p: unknown buffer mem %u", c, mem_id);
res = -ENODEV;
@ -1667,7 +1653,7 @@ static int client_node_port_set_io(void *object,
goto exit;
}
if ((mm = pw_mempool_find_tag(c->remote->pool, tag, sizeof(tag))) != NULL)
if ((mm = pw_mempool_find_tag(c->pool, tag, sizeof(tag))) != NULL)
pw_memmap_free(mm);
if (mem_id == SPA_ID_INVALID) {
@ -1675,7 +1661,7 @@ static int client_node_port_set_io(void *object,
size = 0;
}
else {
mm = pw_mempool_map_id(c->remote->pool, mem_id,
mm = pw_mempool_map_id(c->pool, mem_id,
PW_MEMMAP_FLAG_READWRITE, offset, size, tag);
if (mm == NULL) {
pw_log_warn(NAME" %p: can't map memory id %u", c, mem_id);
@ -1727,7 +1713,7 @@ static int client_node_set_activation(void *object,
size = 0;
}
else {
mm = pw_mempool_map_id(c->remote->pool, mem_id,
mm = pw_mempool_map_id(c->pool, mem_id,
PW_MEMMAP_FLAG_READWRITE, offset, size, NULL);
if (mm == NULL) {
pw_log_warn(NAME" %p: can't map memory id %u", c, mem_id);
@ -2094,7 +2080,6 @@ jack_client_t * jack_client_open (const char *client_name,
jack_status_t *status, ...)
{
struct client *client;
bool busy = true;
struct spa_dict props;
struct spa_dict_item items[6];
const struct spa_support *support;
@ -2156,37 +2141,18 @@ jack_client_t * jack_client_open (const char *client_name,
pw_thread_loop_start(client->context.loop);
pw_thread_loop_lock(client->context.loop);
client->remote = pw_remote_new(client->context.core,
client->core_proxy = pw_core_connect(client->context.core,
pw_properties_new(
PW_KEY_CLIENT_NAME, client_name,
PW_KEY_CLIENT_API, "jack",
NULL),
0);
pw_remote_add_listener(client->remote, &client->remote_listener, &remote_events, client);
if (pw_remote_connect(client->remote) < 0)
if (client->core_proxy == NULL)
goto server_failed;
while (busy) {
const char *error = NULL;
client->pool = pw_core_proxy_get_mempool(client->core_proxy);
switch (pw_remote_get_state(client->remote, &error)) {
case PW_REMOTE_STATE_ERROR:
goto server_failed;
case PW_REMOTE_STATE_CONNECTED:
busy = false;
break;
default:
break;
}
if (busy)
pw_thread_loop_wait(client->context.loop);
}
client->core_proxy = pw_remote_get_core_proxy(client->remote);
pw_core_proxy_add_listener(client->core_proxy,
&client->core_listener,
&core_events, client);
@ -2196,7 +2162,6 @@ jack_client_t * jack_client_open (const char *client_name,
&client->registry_listener,
&registry_events, client);
props = SPA_DICT_INIT(items, 0);
items[props.n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_NAME, client_name);
items[props.n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_MEDIA_TYPE, "Audio");

View file

@ -19,6 +19,7 @@
#include <errno.h>
#include <spa/utils/result.h>
#include <spa/param/props.h>
#include <pipewire/pipewire.h>
@ -808,7 +809,32 @@ static void complete_operations(pa_context *c, int seq)
static void core_info(void *data, const struct pw_core_info *info)
{
pa_context *c = data;
bool first = c->core_info == NULL;
pw_log_debug("context %p: info", c);
if (first) {
pa_context_set_state(c, PA_CONTEXT_AUTHORIZING);
pa_context_set_state(c, PA_CONTEXT_SETTING_NAME);
}
c->core_info = pw_core_info_update(c->core_info, info);
if (first)
pa_context_set_state(c, PA_CONTEXT_READY);
}
static void core_error(void *data, uint32_t id, int seq, int res, const char *message)
{
pa_context *c = data;
pw_log_error("context %p: error id:%u seq:%d res:%d (%s): %s", c,
id, seq, res, spa_strerror(res), message);
if (id == 0) {
if (!c->disconnect)
context_fail(c, PA_ERR_CONNECTIONTERMINATED);
}
}
static void core_done(void *data, uint32_t id, int seq)
@ -819,50 +845,10 @@ static void core_done(void *data, uint32_t id, int seq)
}
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_EVENTS,
PW_VERSION_CORE_PROXY_EVENTS,
.info = core_info,
.done = core_done
};
static void remote_state_changed(void *data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
{
pa_context *c = data;
switch(state) {
case PW_REMOTE_STATE_ERROR:
if (c->core_proxy) {
spa_hook_remove(&c->core_listener);
c->core_proxy = NULL;
}
context_fail(c, PA_ERR_CONNECTIONTERMINATED);
break;
case PW_REMOTE_STATE_UNCONNECTED:
if (c->core_proxy) {
spa_hook_remove(&c->core_listener);
c->core_proxy = NULL;
}
if (!c->disconnect)
context_fail(c, PA_ERR_CONNECTIONTERMINATED);
break;
case PW_REMOTE_STATE_CONNECTING:
pa_context_set_state(c, PA_CONTEXT_CONNECTING);
break;
case PW_REMOTE_STATE_CONNECTED:
pa_context_set_state(c, PA_CONTEXT_AUTHORIZING);
pa_context_set_state(c, PA_CONTEXT_SETTING_NAME);
c->core_proxy = pw_remote_get_core_proxy(c->remote);
pw_core_proxy_add_listener(c->core_proxy, &c->core_listener, &core_events, c);
pa_context_set_state(c, PA_CONTEXT_READY);
break;
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = remote_state_changed,
.done = core_done,
.error = core_error
};
struct success_data {
@ -916,7 +902,6 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
{
struct pw_core *core;
struct pw_loop *loop;
struct pw_remote *r;
struct pw_properties *props;
pa_context *c;
@ -930,19 +915,14 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
pw_properties_update(props, &p->props->dict);
loop = mainloop->userdata;
core = pw_core_new(loop, NULL, 0);
r = pw_remote_new(core, props, sizeof(struct pa_context));
if (r == NULL)
core = pw_core_new(loop, NULL, sizeof(struct pa_context));
if (core == NULL)
return NULL;
c = pw_remote_get_user_data(r);
c = pw_core_get_user_data(core);
c->props = props;
c->loop = loop;
c->core = core;
c->remote = r;
pw_remote_add_listener(r, &c->remote_listener, &remote_events, c);
c->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
c->refcount = 1;
c->client_index = PA_INVALID_INDEX;
@ -974,6 +954,7 @@ static void context_free(pa_context *c)
context_unlink(c);
pw_properties_free(c->props);
if (c->proplist)
pa_proplist_free(c->proplist);
if (c->core_info)
@ -1060,7 +1041,7 @@ pa_context_state_t pa_context_get_state(PA_CONST pa_context *c)
SPA_EXPORT
int pa_context_connect(pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api)
{
int res;
int res = 0;
pa_assert(c);
pa_assert(c->refcount >= 1);
@ -1073,7 +1054,14 @@ int pa_context_connect(pa_context *c, const char *server, pa_context_flags_t fla
c->no_fail = !!(flags & PA_CONTEXT_NOFAIL);
res = pw_remote_connect(c->remote);
pa_context_set_state(c, PA_CONTEXT_CONNECTING);
c->core_proxy = pw_core_connect(c->core, pw_properties_copy(c->props), 0);
if (c->core_proxy == NULL) {
context_fail(c, PA_ERR_CONNECTIONREFUSED);
res = -1;
}
pw_core_proxy_add_listener(c->core_proxy, &c->core_listener, &core_events, c);
pa_context_unref(c);
@ -1087,8 +1075,10 @@ void pa_context_disconnect(pa_context *c)
pa_assert(c->refcount >= 1);
c->disconnect = true;
pw_remote_disconnect(c->remote);
if (c->core_proxy) {
pw_core_proxy_disconnect(c->core_proxy);
c->core_proxy = NULL;
}
if (PA_CONTEXT_IS_GOOD(c->state))
pa_context_set_state(c, PA_CONTEXT_TERMINATED);
}
@ -1191,6 +1181,7 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su
struct spa_dict_item items[1];
pa_operation *o;
struct success_data *d;
int changed;
pa_assert(c);
pa_assert(c->refcount >= 1);
@ -1200,7 +1191,14 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su
items[0] = SPA_DICT_ITEM_INIT(PA_PROP_APPLICATION_NAME, name);
dict = SPA_DICT_INIT(items, 1);
pw_remote_update_properties(c->remote, &dict);
changed = pw_properties_update(c->props, &dict);
if (changed) {
struct pw_client_proxy *client_proxy;
client_proxy = pw_core_proxy_get_client_proxy(c->core_proxy);
pw_client_proxy_update_properties(client_proxy, &c->props->dict);
}
o = pa_operation_new(c, NULL, on_success, sizeof(struct success_data));
d = o->userdata;

View file

@ -283,8 +283,8 @@ struct pa_context {
struct pw_loop *loop;
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_properties *props;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;

View file

@ -554,13 +554,10 @@ static pa_stream* stream_new(pa_context *c, const char *name,
NULL);
pw_properties_update(props, &s->proplist->props->dict);
s->stream = pw_stream_new(c->remote, name, props);
s->refcount = 1;
s->context = c;
spa_list_init(&s->pending);
pw_stream_add_listener(s->stream, &s->stream_listener, &stream_events, s);
s->endpoint_id = SPA_ID_INVALID;
s->direction = PA_STREAM_NODIRECTION;
s->state = PA_STREAM_UNCONNECTED;
@ -858,12 +855,20 @@ static int create_stream(pa_stream_direction_t direction,
struct spa_dict_item items[5];
char latency[64];
bool monitor;
const char *name;
pa_context *c = s->context;
spa_assert(s);
spa_assert(s->refcount >= 1);
pw_log_debug("stream %p: connect %s %08x", s, dev, flags);
name = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME);
s->stream = pw_stream_new(c->core_proxy,
name, pw_properties_copy(c->props));
pw_stream_add_listener(s->stream, &s->stream_listener, &stream_events, s);
s->direction = direction;
s->timing_info_valid = false;
s->disconnecting = false;

View file

@ -75,8 +75,8 @@ struct impl {
struct pw_main_loop *loop;
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;
struct spa_handle *handle;
struct spa_device *device;
@ -140,7 +140,7 @@ static struct node *create_node(struct object *obj, uint32_t id,
node->id = id;
node->handle = handle;
node->node = iface;
node->proxy = pw_remote_export(impl->remote,
node->proxy = pw_core_proxy_export(impl->core_proxy,
info->type, pw_properties_new_dict(info->props), node->node, 0);
if (node->proxy == NULL)
goto clean_node;
@ -248,7 +248,7 @@ static struct object *create_object(struct impl *impl, uint32_t id,
obj->id = id;
obj->handle = handle;
obj->device = iface;
obj->proxy = pw_remote_export(impl->remote,
obj->proxy = pw_core_proxy_export(impl->core_proxy,
info->type, pw_properties_new_dict(info->props), obj->device, 0);
if (obj->proxy == NULL)
goto clean_object;
@ -338,50 +338,32 @@ static int start_monitor(struct impl *impl)
return res;
}
static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
static void on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
{
struct impl *impl = _data;
int res;
struct impl *impl = data;
switch (state) {
case PW_REMOTE_STATE_ERROR:
pw_log_error(NAME" %p: remote error: %s", impl, error);
pw_log_error("error id:%u seq:%d res:%d (%s): %s",
id, seq, res, spa_strerror(res), message);
if (id == 0) {
pw_main_loop_quit(impl->loop);
break;
case PW_REMOTE_STATE_CONNECTED:
pw_log_info(NAME" %p: connected", impl);
if ((res = start_monitor(impl)) < 0) {
pw_log_debug("error starting monitor: %s", spa_strerror(res));
pw_main_loop_quit(impl->loop);
}
break;
case PW_REMOTE_STATE_UNCONNECTED:
pw_log_info(NAME" %p: disconnected", impl);
pw_main_loop_quit(impl->loop);
break;
default:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
break;
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.error = on_core_error,
};
int main(int argc, char *argv[])
{
struct impl impl = { 0, };
int res;
pw_init(&argc, &argv);
impl.loop = pw_main_loop_new(NULL);
impl.core = pw_core_new(pw_main_loop_get_loop(impl.loop), NULL, 0);
impl.remote = pw_remote_new(impl.core, NULL, 0);
pw_core_add_spa_lib(impl.core, "api.bluez5.*", "bluez5/libspa-bluez5");
@ -389,12 +371,20 @@ int main(int argc, char *argv[])
spa_list_init(&impl.device_list);
pw_remote_add_listener(impl.remote,
&impl.remote_listener,
&remote_events, &impl);
if (pw_remote_connect(impl.remote) < 0)
impl.core_proxy = pw_core_connect(impl.core, NULL, 0);
if (impl.core_proxy == NULL) {
pw_log_error(NAME" %p: can't connect %m", &impl);
return -1;
}
pw_core_proxy_add_listener(impl.core_proxy,
&impl.core_listener,
&core_events, &impl);
if ((res = start_monitor(&impl)) < 0) {
pw_log_error(NAME" %p: error starting monitor: %s", &impl, spa_strerror(res));
return -1;
}
pw_main_loop_run(impl.loop);

View file

@ -26,6 +26,7 @@
#include <stdio.h>
#include <sys/mman.h>
#include <spa/utils/result.h>
#include <spa/param/video/format-utils.h>
#include <spa/param/props.h>
#include <spa/node/utils.h>
@ -70,8 +71,8 @@ struct data {
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;
struct spa_node impl_node;
struct spa_hook_list hooks;
@ -473,47 +474,41 @@ static void make_node(struct data *data)
SPA_TYPE_INTERFACE_Node,
SPA_VERSION_NODE,
&impl_node, data);
pw_remote_export(data->remote, SPA_TYPE_INTERFACE_Node, props, &data->impl_node, 0);
pw_core_proxy_export(data->core_proxy, SPA_TYPE_INTERFACE_Node, props, &data->impl_node, 0);
}
static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
static void set_permissions(struct data *data)
{
struct data *data = _data;
struct pw_permission permissions[2];
switch (state) {
case PW_REMOTE_STATE_ERROR:
printf("remote error: %s\n", error);
pw_main_loop_quit(data->loop);
break;
/* an example, set specific permissions on one object, this is the
* core object. */
permissions[0].id = 0;
permissions[0].permissions = PW_PERM_R | PW_PERM_X;
/* remove WX from all other objects */
permissions[1].id = SPA_ID_INVALID;
permissions[1].permissions = PW_PERM_R;
case PW_REMOTE_STATE_CONNECTED:
{
struct pw_permission permissions[2];
pw_client_proxy_update_permissions(
pw_core_proxy_get_client_proxy(data->core_proxy),
2, permissions);
}
/* an example, set specific permissions on one object, this is the
* core object. */
permissions[0].id = 0;
permissions[0].permissions = PW_PERM_R | PW_PERM_X;
/* remove WX from all other objects */
permissions[1].id = SPA_ID_INVALID;
permissions[1].permissions = PW_PERM_R;
static void on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
{
struct data *d = data;
pw_client_proxy_update_permissions(
pw_remote_get_client_proxy(data->remote),
2, permissions);
pw_log_error("error id:%u seq:%d res:%d (%s): %s",
id, seq, res, spa_strerror(res), message);
make_node(data);
break;
}
default:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
break;
if (id == 0) {
pw_main_loop_quit(d->loop);
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.error = on_core_error,
};
int main(int argc, char *argv[])
@ -524,7 +519,6 @@ int main(int argc, char *argv[])
data.loop = pw_main_loop_new(NULL);
data.core = pw_core_new(pw_main_loop_get_loop(data.loop), NULL, 0);
data.remote = pw_remote_new(data.core, NULL, 0);
data.path = argc > 1 ? argv[1] : NULL;
spa_hook_list_init(&data.hooks);
@ -554,10 +548,16 @@ int main(int argc, char *argv[])
return -1;
}
pw_remote_add_listener(data.remote, &data.remote_listener, &remote_events, &data);
if (pw_remote_connect(data.remote) < 0)
data.core_proxy = pw_core_connect(data.core, NULL, 0);
if (data.core_proxy == NULL) {
printf("can't connect: %m\n");
return -1;
}
pw_core_proxy_add_listener(data.core_proxy, &data.core_listener, &core_events, &data);
set_permissions(&data);
make_node(&data);
pw_main_loop_run(data.loop);

View file

@ -27,6 +27,7 @@
#include <math.h>
#include <sys/mman.h>
#include <spa/utils/result.h>
#include <spa/param/audio/format-utils.h>
#include <spa/param/props.h>
#include <spa/node/io.h>
@ -55,8 +56,8 @@ struct data {
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;
uint64_t info_all;
struct spa_port_info info;
@ -481,33 +482,24 @@ static void make_node(struct data *data)
SPA_TYPE_INTERFACE_Node,
SPA_VERSION_NODE,
&impl_node, data);
pw_remote_export(data->remote, SPA_TYPE_INTERFACE_Node, props, &data->impl_node, 0);
pw_core_proxy_export(data->core_proxy, SPA_TYPE_INTERFACE_Node, props, &data->impl_node, 0);
}
static void on_state_changed(void *_data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
static void on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
{
struct data *data = _data;
struct data *d = data;
switch (state) {
case PW_REMOTE_STATE_ERROR:
printf("remote error: %s\n", error);
pw_main_loop_quit(data->loop);
break;
pw_log_error("error id:%u seq:%d res:%d (%s): %s",
id, seq, res, spa_strerror(res), message);
case PW_REMOTE_STATE_CONNECTED:
make_node(data);
break;
default:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
break;
if (id == 0) {
pw_main_loop_quit(d->loop);
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.error = on_core_error,
};
int main(int argc, char *argv[])
@ -518,7 +510,6 @@ int main(int argc, char *argv[])
data.loop = pw_main_loop_new(NULL);
data.core = pw_core_new(pw_main_loop_get_loop(data.loop), NULL, 0);
data.remote = pw_remote_new(data.core, NULL, 0);
data.path = argc > 1 ? argv[1] : NULL;
data.info_all = SPA_PORT_CHANGE_MASK_FLAGS |
@ -540,9 +531,14 @@ int main(int argc, char *argv[])
spa_list_init(&data.empty);
spa_hook_list_init(&data.hooks);
pw_remote_add_listener(data.remote, &data.remote_listener, &remote_events, &data);
if ((data.core_proxy = pw_core_connect(data.core, NULL, 0)) == NULL) {
printf("can't connect: %m\n");
return -1;
}
pw_remote_connect(data.remote);
pw_core_proxy_add_listener(data.core_proxy, &data.core_listener, &core_events, &data);
make_node(&data);
pw_main_loop_run(data.loop);

View file

@ -26,6 +26,7 @@
#include <sys/mman.h>
#include <signal.h>
#include <spa/utils/result.h>
#include <spa/param/video/format-utils.h>
#include <spa/param/props.h>
@ -36,8 +37,8 @@ struct data {
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;
struct pw_device *device;
const char *library;
@ -63,39 +64,27 @@ static int make_device(struct data *data)
PW_VERSION_DEVICE_PROXY,
props, SPA_ID_INVALID);
pw_remote_export(data->remote, SPA_TYPE_INTERFACE_Device, NULL,
pw_core_proxy_export(data->core_proxy, SPA_TYPE_INTERFACE_Device, NULL,
pw_device_get_implementation(data->device), 0);
return 0;
}
static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
static void on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
{
struct data *data = _data;
struct data *d = data;
switch (state) {
case PW_REMOTE_STATE_ERROR:
printf("remote error: %s\n", error);
pw_main_loop_quit(data->loop);
break;
pw_log_error("error id:%u seq:%d res:%d (%s): %s",
id, seq, res, spa_strerror(res), message);
case PW_REMOTE_STATE_CONNECTED:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
if (make_device(data) < 0) {
pw_log_error("can't make device");
pw_main_loop_quit(data->loop);
}
break;
default:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
break;
if (id == 0) {
pw_main_loop_quit(d->loop);
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.error = on_core_error,
};
static void do_quit(void *data, int signal_number)
@ -123,15 +112,23 @@ int main(int argc, char *argv[])
pw_loop_add_signal(l, SIGINT, do_quit, &data);
pw_loop_add_signal(l, SIGTERM, do_quit, &data);
data.core = pw_core_new(l, NULL, 0);
data.remote = pw_remote_new(data.core, NULL, 0);
data.library = argv[1];
data.factory = argv[2];
pw_module_load(data.core, "libpipewire-module-spa-device-factory", NULL, NULL);
pw_remote_add_listener(data.remote, &data.remote_listener, &remote_events, &data);
data.core_proxy = pw_core_connect(data.core, NULL, 0);
if (data.core_proxy == NULL) {
pw_log_error("can't connect %m");
return -1;
}
pw_remote_connect(data.remote);
pw_core_proxy_add_listener(data.core_proxy, &data.core_listener, &core_events, &data);
if (make_device(&data) < 0) {
pw_log_error("can't make device");
return -1;
}
pw_main_loop_run(data.loop);

View file

@ -26,6 +26,7 @@
#include <sys/mman.h>
#include <signal.h>
#include <spa/utils/result.h>
#include <spa/param/video/format-utils.h>
#include <spa/param/props.h>
@ -36,8 +37,8 @@ struct data {
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;
struct pw_node *node;
const char *library;
@ -91,7 +92,7 @@ static int make_node(struct data *data)
pw_node_set_active(data->node, true);
data->proxy = pw_remote_export(data->remote, PW_TYPE_INTERFACE_Node, NULL, data->node, 0);
data->proxy = pw_core_proxy_export(data->core_proxy, PW_TYPE_INTERFACE_Node, NULL, data->node, 0);
if (data->proxy == NULL)
return -errno;
@ -101,33 +102,21 @@ static int make_node(struct data *data)
return 0;
}
static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
static void on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
{
struct data *data = _data;
struct data *d = data;
switch (state) {
case PW_REMOTE_STATE_ERROR:
printf("remote error: %s\n", error);
pw_main_loop_quit(data->loop);
break;
pw_log_error("error id:%u seq:%d res:%d (%s): %s",
id, seq, res, spa_strerror(res), message);
case PW_REMOTE_STATE_CONNECTED:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
if (make_node(data) < 0) {
pw_log_error("can't make node");
pw_main_loop_quit(data->loop);
}
break;
default:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
break;
if (id == 0) {
pw_main_loop_quit(d->loop);
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.error = on_core_error,
};
static void do_quit(void *data, int signal_number)
@ -155,7 +144,6 @@ int main(int argc, char *argv[])
pw_loop_add_signal(l, SIGINT, do_quit, &data);
pw_loop_add_signal(l, SIGTERM, do_quit, &data);
data.core = pw_core_new(l, NULL, 0);
data.remote = pw_remote_new(data.core, NULL, 0);
data.library = argv[1];
data.factory = argv[2];
if (argc > 3)
@ -163,9 +151,19 @@ int main(int argc, char *argv[])
pw_module_load(data.core, "libpipewire-module-spa-node-factory", NULL, NULL);
pw_remote_add_listener(data.remote, &data.remote_listener, &remote_events, &data);
data.core_proxy = pw_core_connect(data.core, NULL, 0);
if (data.core_proxy == NULL) {
printf("can't connect: %m\n");
return -1;
}
pw_core_proxy_add_listener(data.core_proxy,
&data.core_listener,
&core_events, &data);
pw_remote_connect(data.remote);
if (make_node(&data) < 0) {
pw_log_error("can't make node");
return -1;
}
pw_main_loop_run(data.loop);

View file

@ -91,14 +91,11 @@ struct impl {
struct pw_main_loop *loop;
struct spa_dbus *dbus;
struct pw_remote *monitor_remote;
struct spa_hook monitor_listener;
struct pw_core_proxy *monitor_core;
struct spa_hook monitor_listener;
struct pw_remote *policy_remote;
struct spa_hook policy_listener;
struct pw_core_proxy *policy_core;
struct spa_hook core_listener;
struct spa_hook policy_listener;
struct pw_registry_proxy *registry_proxy;
struct spa_hook registry_listener;
@ -1216,7 +1213,7 @@ struct pw_proxy *sm_media_session_export(struct sm_media_session *sess,
void *object, size_t user_data_size)
{
struct impl *impl = SPA_CONTAINER_OF(sess, struct impl, this);
return pw_remote_export(impl->monitor_remote, type,
return pw_core_proxy_export(impl->monitor_core, type,
properties, object, user_data_size);
}
@ -1229,7 +1226,7 @@ struct sm_device *sm_media_session_export_device(struct sm_media_session *sess,
pw_log_debug(NAME " %p: device %p", impl, object);
proxy = pw_remote_export(impl->monitor_remote, SPA_TYPE_INTERFACE_Device,
proxy = pw_core_proxy_export(impl->monitor_core, SPA_TYPE_INTERFACE_Device,
properties, object, sizeof(struct sm_device));
device = (struct sm_device *) create_object(impl, proxy, &properties->dict);
@ -1526,6 +1523,12 @@ static const struct pw_proxy_events client_session_proxy_events = {
static int start_session(struct impl *impl)
{
impl->monitor_core = pw_core_connect(impl->this.core, NULL, 0);
if (impl->monitor_core == NULL) {
pw_log_error("can't start monitor: %m");
return -errno;
}
impl->client_session = pw_core_proxy_create_object(impl->monitor_core,
"client-session",
PW_TYPE_INTERFACE_ClientSession,
@ -1543,11 +1546,6 @@ static int start_session(struct impl *impl)
return 0;
}
static int start_policy(struct impl *impl)
{
return sm_policy_ep_start(&impl->this);
}
static void core_done(void *data, uint32_t id, int seq)
{
struct impl *impl = data;
@ -1567,91 +1565,50 @@ static void core_done(void *data, uint32_t id, int seq)
}
}
static void on_monitor_state_changed(void *_data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
static void core_error(void *data, uint32_t id, int seq, int res, const char *message)
{
struct impl *impl = _data;
struct impl *impl = data;
switch (state) {
case PW_REMOTE_STATE_ERROR:
pw_log_error(NAME" %p: remote error: %s", impl, error);
pw_log_error("error id:%u seq:%d res:%d (%s): %s",
id, seq, res, spa_strerror(res), message);
if (id == 0) {
pw_main_loop_quit(impl->loop);
break;
case PW_REMOTE_STATE_CONNECTED:
pw_log_info(NAME" %p: connected", impl);
impl->monitor_core = pw_remote_get_core_proxy(impl->monitor_remote);
start_session(impl);
break;
case PW_REMOTE_STATE_UNCONNECTED:
pw_log_info(NAME" %p: disconnected", impl);
pw_main_loop_quit(impl->loop);
break;
default:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
break;
}
}
static const struct pw_remote_events monitor_remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_monitor_state_changed,
};
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_EVENTS,
.done = core_done
.done = core_done,
.error = core_error
};
static void on_policy_state_changed(void *_data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
static int start_policy(struct impl *impl)
{
struct impl *impl = _data;
switch (state) {
case PW_REMOTE_STATE_ERROR:
pw_log_error(NAME" %p: remote error: %s", impl, error);
pw_main_loop_quit(impl->loop);
break;
case PW_REMOTE_STATE_CONNECTED:
pw_log_info(NAME" %p: connected", impl);
impl->policy_core = pw_remote_get_core_proxy(impl->policy_remote);
pw_core_proxy_add_listener(impl->policy_core,
&impl->core_listener,
&core_events, impl);
impl->registry_proxy = pw_core_proxy_get_registry(impl->policy_core,
PW_VERSION_REGISTRY_PROXY, 0);
pw_registry_proxy_add_listener(impl->registry_proxy,
&impl->registry_listener,
&registry_events, impl);
start_policy(impl);
break;
case PW_REMOTE_STATE_UNCONNECTED:
pw_log_info(NAME" %p: disconnected", impl);
pw_main_loop_quit(impl->loop);
break;
default:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
break;
impl->policy_core = pw_core_connect(impl->this.core, NULL, 0);
if (impl->policy_core == NULL) {
pw_log_error("can't start policy: %m");
return -errno;
}
}
static const struct pw_remote_events policy_remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_policy_state_changed,
};
pw_core_proxy_add_listener(impl->policy_core,
&impl->policy_listener,
&core_events, impl);
impl->registry_proxy = pw_core_proxy_get_registry(impl->policy_core,
PW_VERSION_REGISTRY_PROXY, 0);
pw_registry_proxy_add_listener(impl->registry_proxy,
&impl->registry_listener,
&registry_events, impl);
return sm_policy_ep_start(&impl->this);
}
int main(int argc, char *argv[])
{
struct impl impl = { 0, };
const struct spa_support *support;
uint32_t n_support;
int res;
pw_init(&argc, &argv);
@ -1663,12 +1620,6 @@ int main(int argc, char *argv[])
pw_core_add_spa_lib(impl.this.core, "api.alsa.*", "alsa/libspa-alsa");
pw_core_add_spa_lib(impl.this.core, "api.v4l2.*", "v4l2/libspa-v4l2");
impl.monitor_remote = pw_remote_new(impl.this.core, NULL, 0);
pw_remote_add_listener(impl.monitor_remote, &impl.monitor_listener, &monitor_remote_events, &impl);
impl.policy_remote = pw_remote_new(impl.this.core, NULL, 0);
pw_remote_add_listener(impl.policy_remote, &impl.policy_listener, &policy_remote_events, &impl);
pw_map_init(&impl.globals, 64, 64);
spa_list_init(&impl.global_list);
pw_map_init(&impl.endpoint_links, 64, 64);
@ -1686,10 +1637,10 @@ int main(int argc, char *argv[])
else
pw_log_debug("got dbus connection %p", impl.this.dbus_connection);
if ((res = pw_remote_connect(impl.monitor_remote)) < 0)
return res;
if ((res = pw_remote_connect(impl.policy_remote)) < 0)
return res;
if (start_session(&impl) < 0)
return -1;
if (start_policy(&impl) < 0)
return -1;
pw_main_loop_run(impl.loop);

View file

@ -47,8 +47,7 @@ struct data {
struct spa_source *timer;
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct pw_stream *stream;
struct spa_hook stream_listener;
@ -186,6 +185,11 @@ static void on_stream_state_changed(void *_data, enum pw_stream_state old, enum
printf("stream state: \"%s\"\n", pw_stream_state_as_string(state));
switch (state) {
case PW_STREAM_STATE_ERROR:
case PW_STREAM_STATE_UNCONNECTED:
pw_main_loop_quit(data->loop);
break;
case PW_STREAM_STATE_PAUSED:
printf("node id: %d\n", pw_stream_get_node_id(data->stream));
break;
@ -266,81 +270,51 @@ static const struct pw_stream_events stream_events = {
.param_changed = on_stream_param_changed,
};
static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
{
struct data *data = _data;
struct pw_remote *remote = data->remote;
switch (state) {
case PW_REMOTE_STATE_ERROR:
printf("remote error: %s\n", error);
pw_main_loop_quit(data->loop);
break;
case PW_REMOTE_STATE_CONNECTED:
{
const struct spa_pod *params[1];
uint8_t buffer[1024];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
printf("remote state: \"%s\"\n",
pw_remote_state_as_string(state));
data->stream = pw_stream_new(remote, "video-src",
pw_properties_new(
PW_KEY_MEDIA_CLASS, "Video/Source",
NULL));
params[0] = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_RGB),
SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(
&SPA_RECTANGLE(320, 240),
&SPA_RECTANGLE(1, 1),
&SPA_RECTANGLE(4096, 4096)),
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&SPA_FRACTION(25, 1)));
pw_stream_add_listener(data->stream,
&data->stream_listener,
&stream_events,
data);
pw_stream_connect(data->stream,
PW_DIRECTION_OUTPUT,
SPA_ID_INVALID,
PW_STREAM_FLAG_DRIVER |
PW_STREAM_FLAG_MAP_BUFFERS,
params, 1);
break;
}
default:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
break;
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
};
int main(int argc, char *argv[])
{
struct data data = { 0, };
const struct spa_pod *params[1];
uint8_t buffer[1024];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
pw_init(&argc, &argv);
data.loop = pw_main_loop_new(NULL);
data.core = pw_core_new(pw_main_loop_get_loop(data.loop), NULL, 0);
data.remote = pw_remote_new(data.core, NULL, 0);
data.timer = pw_loop_add_timer(pw_main_loop_get_loop(data.loop), on_timeout, &data);
pw_remote_add_listener(data.remote, &data.remote_listener, &remote_events, &data);
data.core_proxy = pw_core_connect(data.core, NULL, 0);
if (data.core_proxy == NULL)
return -1;
pw_remote_connect(data.remote);
data.stream = pw_stream_new(data.core_proxy, "video-src",
pw_properties_new(
PW_KEY_MEDIA_CLASS, "Video/Source",
NULL));
params[0] = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_RGB),
SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(
&SPA_RECTANGLE(320, 240),
&SPA_RECTANGLE(1, 1),
&SPA_RECTANGLE(4096, 4096)),
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&SPA_FRACTION(25, 1)));
pw_stream_add_listener(data.stream,
&data.stream_listener,
&stream_events,
&data);
pw_stream_connect(data.stream,
PW_DIRECTION_OUTPUT,
SPA_ID_INVALID,
PW_STREAM_FLAG_DRIVER |
PW_STREAM_FLAG_MAP_BUFFERS,
params, 1);
pw_main_loop_run(data.loop);

View file

@ -28,6 +28,8 @@
#include <string.h>
#include <spa/utils/result.h>
#include <gst/gst.h>
#include "gstpipewireformat.h"
@ -167,7 +169,7 @@ struct pending {
void *data;
};
struct remote_data {
struct core_data {
int seq;
GstPipeWireDeviceProvider *self;
struct spa_hook core_listener;
@ -200,7 +202,7 @@ struct port_data {
struct pending pending;
};
static struct node_data *find_node_data(struct remote_data *rd, uint32_t id)
static struct node_data *find_node_data(struct core_data *rd, uint32_t id)
{
struct node_data *n;
spa_list_for_each(n, &rd->nodes, link) {
@ -343,36 +345,28 @@ on_core_done (void *data, uint32_t id, int seq)
}
}
static void
on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
{
GstPipeWireDeviceProvider *self = data;
pw_log_error("error id:%u seq:%d res:%d (%s): %s",
id, seq, res, spa_strerror(res), message);
if (id == 0) {
self->error = res;
}
pw_thread_loop_signal(self->main_loop, FALSE);
}
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_EVENTS,
.info = on_core_info,
.done = on_core_done,
.error = on_core_error,
};
static void
on_state_changed (void *data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
{
struct remote_data *rd = data;
GstPipeWireDeviceProvider *self = rd->self;
GST_DEBUG ("got remote state %d", state);
switch (state) {
case PW_REMOTE_STATE_CONNECTING:
case PW_REMOTE_STATE_UNCONNECTED:
break;
case PW_REMOTE_STATE_CONNECTED:
self->core_proxy = pw_remote_get_core_proxy(self->remote);
pw_core_proxy_add_listener(self->core_proxy, &rd->core_listener, &core_events, self);
break;
case PW_REMOTE_STATE_ERROR:
GST_ERROR_OBJECT (self, "remote error: %s", error);
break;
}
if (self->main_loop)
pw_thread_loop_signal (self->main_loop, FALSE);
}
static void port_event_info(void *data, const struct pw_port_info *info)
{
struct port_data *port_data = data;
@ -456,7 +450,7 @@ static void registry_event_global(void *data, uint32_t id, uint32_t permissions,
uint32_t type, uint32_t version,
const struct spa_dict *props)
{
struct remote_data *rd = data;
struct core_data *rd = data;
GstPipeWireDeviceProvider *self = rd->self;
struct node_data *nd;
@ -525,62 +519,34 @@ static const struct pw_registry_proxy_events registry_events = {
.global_remove = registry_event_global_remove,
};
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
};
static GList *
gst_pipewire_device_provider_probe (GstDeviceProvider * provider)
{
GstPipeWireDeviceProvider *self = GST_PIPEWIRE_DEVICE_PROVIDER (provider);
struct pw_loop *l = NULL;
struct pw_core *c = NULL;
struct pw_remote *r = NULL;
struct remote_data *data;
struct spa_hook listener;
struct core_data *data;
GST_DEBUG_OBJECT (self, "starting probe");
if (!(l = pw_loop_new (NULL)))
return NULL;
if (!(c = pw_core_new (l, NULL, 0)))
if (!(c = pw_core_new (l, NULL, sizeof(*data))))
return NULL;
if (!(r = pw_remote_new (c, NULL, sizeof(*data))))
goto failed;
data = pw_remote_get_user_data(r);
data = pw_core_get_user_data(c);
data->self = self;
spa_list_init(&data->nodes);
spa_list_init(&data->ports);
spa_list_init(&self->pending);
pw_remote_add_listener(r, &listener, &remote_events, data);
if (pw_remote_connect (r) < 0)
self->core_proxy = pw_core_connect (c, NULL, 0);
if (self->core_proxy == NULL)
goto failed;
for (;;) {
enum pw_remote_state state;
const char *error = NULL;
state = pw_remote_get_state(r, &error);
if (state <= 0) {
GST_ERROR_OBJECT (self, "Failed to connect: %s", error);
goto failed;
}
if (state == PW_REMOTE_STATE_CONNECTED)
break;
/* Wait until something happens */
pw_loop_iterate (l, -1);
}
GST_DEBUG_OBJECT (self, "connected");
pw_core_proxy_add_listener(self->core_proxy, &data->core_listener, &core_events, self);
self->end = FALSE;
self->list_only = TRUE;
@ -588,18 +554,19 @@ gst_pipewire_device_provider_probe (GstDeviceProvider * provider)
data->registry = pw_core_proxy_get_registry(self->core_proxy, PW_VERSION_REGISTRY_PROXY, 0);
pw_registry_proxy_add_listener(data->registry, &data->registry_listener, &registry_events, data);
pw_core_proxy_sync(self->core_proxy, 0, self->seq++);
for (;;) {
if (pw_remote_get_state(r, NULL) <= 0)
if (self->error < 0)
break;
if (self->end)
break;
pw_loop_iterate (l, -1);
}
pw_remote_disconnect (r);
pw_remote_destroy (r);
GST_DEBUG_OBJECT (self, "disconnect");
pw_core_proxy_disconnect (self->core_proxy);
pw_core_destroy (c);
pw_loop_destroy (l);
@ -614,7 +581,7 @@ static gboolean
gst_pipewire_device_provider_start (GstDeviceProvider * provider)
{
GstPipeWireDeviceProvider *self = GST_PIPEWIRE_DEVICE_PROVIDER (provider);
struct remote_data *data;
struct core_data *data;
GST_DEBUG_OBJECT (self, "starting provider");
@ -627,7 +594,7 @@ gst_pipewire_device_provider_start (GstDeviceProvider * provider)
goto failed_main_loop;
}
if (!(self->core = pw_core_new (self->loop, NULL, 0))) {
if (!(self->core = pw_core_new (self->loop, NULL, sizeof(*data)))) {
GST_ERROR_OBJECT (self, "Could not create PipeWire core");
goto failed_core;
}
@ -639,60 +606,41 @@ gst_pipewire_device_provider_start (GstDeviceProvider * provider)
pw_thread_loop_lock (self->main_loop);
if (!(self->remote = pw_remote_new (self->core, NULL, sizeof(*data)))) {
GST_ERROR_OBJECT (self, "Failed to create remote");
goto failed_remote;
if ((self->core_proxy = pw_core_connect (self->core, NULL, 0)) == NULL) {
GST_ERROR_OBJECT (self, "Failed to connect");
goto failed_connect;
}
data = pw_remote_get_user_data(self->remote);
GST_DEBUG_OBJECT (self, "connected");
data = pw_core_get_user_data(self->core);
data->self = self;
spa_list_init(&data->nodes);
spa_list_init(&data->ports);
pw_remote_add_listener (self->remote, &self->remote_listener, &remote_events, data);
if (pw_remote_connect (self->remote) < 0)
goto not_running;
for (;;) {
enum pw_remote_state state;
const char *error = NULL;
state = pw_remote_get_state(self->remote, &error);
if (state <= 0) {
GST_WARNING_OBJECT (self, "Failed to connect: %s", error);
goto not_running;
}
if (state == PW_REMOTE_STATE_CONNECTED)
break;
/* Wait until something happens */
pw_thread_loop_wait (self->main_loop);
}
GST_DEBUG_OBJECT (self, "connected");
pw_core_proxy_add_listener(self->core_proxy, &data->core_listener, &core_events, self);
self->registry = pw_core_proxy_get_registry(self->core_proxy, PW_VERSION_REGISTRY_PROXY, 0);
data->registry = self->registry;
pw_registry_proxy_add_listener(self->registry, &data->registry_listener, &registry_events, data);
pw_core_proxy_sync(self->core_proxy, 0, self->seq++);
for (;;) {
if (self->error < 0)
break;
if (self->end)
break;
pw_thread_loop_wait (self->main_loop);
}
GST_DEBUG_OBJECT (self, "started");
pw_thread_loop_unlock (self->main_loop);
return TRUE;
not_running:
pw_remote_destroy (self->remote);
self->remote = NULL;
failed_remote:
failed_connect:
pw_thread_loop_unlock (self->main_loop);
failed_start:
pw_core_destroy (self->core);
@ -713,10 +661,9 @@ gst_pipewire_device_provider_stop (GstDeviceProvider * provider)
GST_DEBUG_OBJECT (self, "stopping provider");
if (self->remote) {
pw_remote_disconnect (self->remote);
pw_remote_destroy (self->remote);
self->remote = NULL;
if (self->core_proxy) {
pw_core_proxy_disconnect (self->core_proxy);
self->core_proxy = NULL;
}
if (self->core) {
pw_core_destroy (self->core);

View file

@ -88,15 +88,13 @@ struct _GstPipeWireDeviceProvider {
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_list pending;
int seq;
struct pw_registry_proxy *registry;
int error;
gboolean end;
gboolean list_only;
GList **devices;

View file

@ -665,7 +665,7 @@ gst_pipewire_sink_start (GstBaseSink * basesink)
}
pw_thread_loop_lock (pwsink->main_loop);
pwsink->stream = pw_stream_new (pwsink->remote, pwsink->client_name, props);
pwsink->stream = pw_stream_new (pwsink->core_proxy, pwsink->client_name, props);
pwsink->pool->stream = pwsink->stream;
pw_stream_add_listener(pwsink->stream,
@ -697,62 +697,22 @@ gst_pipewire_sink_stop (GstBaseSink * basesink)
return TRUE;
}
static void
on_remote_state_changed (void *data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
{
GstPipeWireSink *pwsink = data;
GST_DEBUG ("got remote state %d", state);
switch (state) {
case PW_REMOTE_STATE_UNCONNECTED:
case PW_REMOTE_STATE_CONNECTING:
case PW_REMOTE_STATE_CONNECTED:
break;
case PW_REMOTE_STATE_ERROR:
GST_ELEMENT_ERROR (pwsink, RESOURCE, FAILED,
("remote error: %s", error), (NULL));
break;
}
pw_thread_loop_signal (pwsink->main_loop, FALSE);
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_remote_state_changed,
};
static gboolean
gst_pipewire_sink_open (GstPipeWireSink * pwsink)
{
const char *error = NULL;
if (pw_thread_loop_start (pwsink->main_loop) < 0)
goto mainloop_error;
pw_thread_loop_lock (pwsink->main_loop);
pwsink->remote = pw_remote_new (pwsink->core, NULL, 0);
pw_remote_add_listener (pwsink->remote,
&pwsink->remote_listener,
&remote_events, pwsink);
if (pwsink->fd == -1)
pw_remote_connect (pwsink->remote);
pwsink->core_proxy = pw_core_connect (pwsink->core, NULL, 0);
else
pw_remote_connect_fd (pwsink->remote, dup(pwsink->fd));
pwsink->core_proxy = pw_core_connect_fd (pwsink->core, dup(pwsink->fd), NULL, 0);
while (TRUE) {
enum pw_remote_state state = pw_remote_get_state (pwsink->remote, &error);
if (pwsink->core_proxy == NULL)
goto connect_error;
if (state == PW_REMOTE_STATE_CONNECTED)
break;
if (state == PW_REMOTE_STATE_ERROR)
goto connect_error;
pw_thread_loop_wait (pwsink->main_loop);
}
pw_thread_loop_unlock (pwsink->main_loop);
return TRUE;
@ -766,6 +726,8 @@ mainloop_error:
}
connect_error:
{
GST_ELEMENT_ERROR (pwsink, RESOURCE, FAILED,
("Failed to connect"), (NULL));
pw_thread_loop_unlock (pwsink->main_loop);
return FALSE;
}
@ -774,26 +736,13 @@ connect_error:
static gboolean
gst_pipewire_sink_close (GstPipeWireSink * pwsink)
{
const char *error = NULL;
pw_thread_loop_lock (pwsink->main_loop);
if (pwsink->stream) {
pw_stream_disconnect (pwsink->stream);
}
if (pwsink->remote) {
pw_remote_disconnect (pwsink->remote);
while (TRUE) {
enum pw_remote_state state = pw_remote_get_state (pwsink->remote, &error);
if (state == PW_REMOTE_STATE_UNCONNECTED)
break;
if (state == PW_REMOTE_STATE_ERROR)
break;
pw_thread_loop_wait (pwsink->main_loop);
}
if (pwsink->core_proxy) {
pw_core_proxy_disconnect (pwsink->core_proxy);
pwsink->core_proxy = NULL;
}
pw_thread_loop_unlock (pwsink->main_loop);
@ -803,12 +752,6 @@ gst_pipewire_sink_close (GstPipeWireSink * pwsink)
pw_stream_destroy (pwsink->stream);
pwsink->stream = NULL;
}
if (pwsink->remote) {
pw_remote_destroy (pwsink->remote);
pwsink->remote = NULL;
}
return TRUE;
}

View file

@ -87,8 +87,7 @@ struct _GstPipeWireSink {
struct pw_thread_loop *main_loop;
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct pw_stream *stream;
struct spa_hook stream_listener;

View file

@ -504,9 +504,6 @@ gst_pipewire_src_stream_start (GstPipeWireSrc *pwsrc)
if (state == PW_STREAM_STATE_ERROR)
goto start_error;
if (pw_remote_get_state(pwsrc->remote, &error) == PW_REMOTE_STATE_ERROR)
goto start_error;
pw_thread_loop_wait (pwsrc->main_loop);
}
@ -542,9 +539,6 @@ wait_negotiated (GstPipeWireSrc *this)
if (state == PW_STREAM_STATE_ERROR)
break;
if (pw_remote_get_state(this->remote, &error) == PW_REMOTE_STATE_ERROR)
break;
if (this->started)
break;
@ -638,9 +632,6 @@ gst_pipewire_src_negotiate (GstBaseSrc * basesrc)
if (state == PW_STREAM_STATE_ERROR)
goto connect_error;
if (pw_remote_get_state(pwsrc->remote, &error) == PW_REMOTE_STATE_ERROR)
goto connect_error;
pw_thread_loop_wait (pwsrc->main_loop);
}
pw_thread_loop_unlock (pwsrc->main_loop);
@ -915,26 +906,6 @@ gst_pipewire_src_stop (GstBaseSrc * basesrc)
return TRUE;
}
static void
on_remote_state_changed (void *data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
{
GstPipeWireSrc *pwsrc = data;
GST_DEBUG ("got remote state %s", pw_remote_state_as_string (state));
switch (state) {
case PW_REMOTE_STATE_UNCONNECTED:
case PW_REMOTE_STATE_CONNECTING:
case PW_REMOTE_STATE_CONNECTED:
break;
case PW_REMOTE_STATE_ERROR:
GST_ELEMENT_ERROR (pwsrc, RESOURCE, FAILED,
("remote error: %s", error), (NULL));
break;
}
pw_thread_loop_signal (pwsrc->main_loop, FALSE);
}
static gboolean
copy_properties (GQuark field_id,
const GValue *value,
@ -949,11 +920,6 @@ copy_properties (GQuark field_id,
return TRUE;
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_remote_state_changed,
};
static const struct pw_stream_events stream_events = {
PW_VERSION_STREAM_EVENTS,
.state_changed = on_state_changed,
@ -967,37 +933,20 @@ static gboolean
gst_pipewire_src_open (GstPipeWireSrc * pwsrc)
{
struct pw_properties *props;
const char *error = NULL;
if (pw_thread_loop_start (pwsrc->main_loop) < 0)
goto mainloop_failed;
pw_thread_loop_lock (pwsrc->main_loop);
if ((pwsrc->remote = pw_remote_new (pwsrc->core, NULL, 0)) == NULL)
goto no_remote;
pw_remote_add_listener (pwsrc->remote,
&pwsrc->remote_listener,
&remote_events, pwsrc);
if (pwsrc->fd == -1)
pw_remote_connect (pwsrc->remote);
pwsrc->core_proxy = pw_core_connect (pwsrc->core, NULL, 0);
else
pw_remote_connect_fd (pwsrc->remote, dup(pwsrc->fd));
pwsrc->core_proxy = pw_core_connect_fd (pwsrc->core, dup(pwsrc->fd), NULL, 0);
while (TRUE) {
enum pw_remote_state state = pw_remote_get_state(pwsrc->remote, &error);
GST_DEBUG ("waiting for CONNECTED, now %s", pw_remote_state_as_string (state));
if (state == PW_REMOTE_STATE_CONNECTED)
break;
if (state == PW_REMOTE_STATE_ERROR)
if (pwsrc->core_proxy == NULL)
goto connect_error;
pw_thread_loop_wait (pwsrc->main_loop);
}
if (pwsrc->properties) {
props = pw_properties_new (NULL, NULL);
gst_structure_foreach (pwsrc->properties, copy_properties, props);
@ -1005,7 +954,8 @@ gst_pipewire_src_open (GstPipeWireSrc * pwsrc)
props = NULL;
}
if ((pwsrc->stream = pw_stream_new (pwsrc->remote, pwsrc->client_name, props)) == NULL)
if ((pwsrc->stream = pw_stream_new (pwsrc->core_proxy,
pwsrc->client_name, props)) == NULL)
goto no_stream;
@ -1026,14 +976,9 @@ mainloop_failed:
GST_ELEMENT_ERROR (pwsrc, RESOURCE, FAILED, ("error starting mainloop"), (NULL));
return FALSE;
}
no_remote:
{
GST_ELEMENT_ERROR (pwsrc, RESOURCE, FAILED, ("can't create remote"), (NULL));
pw_thread_loop_unlock (pwsrc->main_loop);
return FALSE;
}
connect_error:
{
GST_ELEMENT_ERROR (pwsrc, RESOURCE, FAILED, ("can't connect"), (NULL));
pw_thread_loop_unlock (pwsrc->main_loop);
return FALSE;
}
@ -1065,8 +1010,8 @@ gst_pipewire_src_close (GstPipeWireSrc * pwsrc)
pw_stream_destroy (pwsrc->stream);
pwsrc->stream = NULL;
pw_remote_destroy (pwsrc->remote);
pwsrc->remote = NULL;
pw_core_proxy_disconnect (pwsrc->core_proxy);
pwsrc->core_proxy = NULL;
}
static GstStateChangeReturn

View file

@ -75,8 +75,7 @@ struct _GstPipeWireSrc {
struct pw_thread_loop *main_loop;
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct pw_stream *stream;
struct spa_hook stream_listener;

View file

@ -43,7 +43,7 @@ static const struct spa_dict_item module_props[] = {
{ PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
};
struct pw_proxy *pw_remote_spa_device_export(struct pw_core_proxy *core_proxy,
struct pw_proxy *pw_core_proxy_spa_device_export(struct pw_core_proxy *core_proxy,
uint32_t type, struct pw_properties *props, void *object,
size_t user_data_size);
@ -188,7 +188,7 @@ int pipewire__module_init(struct pw_module *module, const char *args)
pw_protocol_native_ext_client_device_init(core);
data->export_spadevice.type = SPA_TYPE_INTERFACE_Device;
data->export_spadevice.func = pw_remote_spa_device_export;
data->export_spadevice.func = pw_core_proxy_spa_device_export;
pw_core_register_export_type(core, &data->export_spadevice);
pw_module_add_listener(module, &data->module_listener, &module_events, data);

View file

@ -52,7 +52,7 @@ static const struct pw_proxy_events proxy_events = {
.destroy = device_proxy_destroy,
};
struct pw_proxy *pw_remote_spa_device_export(struct pw_core_proxy *core_proxy,
struct pw_proxy *pw_core_proxy_spa_device_export(struct pw_core_proxy *core_proxy,
uint32_t type, struct pw_properties *props, void *object,
size_t user_data_size)
{

View file

@ -68,9 +68,10 @@ struct link {
};
struct node_data {
struct pw_remote *remote;
struct pw_core *core;
struct pw_mempool *pool;
uint32_t remote_id;
int rtwritefd;
struct pw_memmap *activation;
@ -133,7 +134,7 @@ static void clean_transport(struct node_data *data)
}
pw_array_clear(&data->links);
while ((mm = pw_mempool_find_tag(data->remote->pool, tag, sizeof(uint32_t))) != NULL)
while ((mm = pw_mempool_find_tag(data->pool, tag, sizeof(uint32_t))) != NULL)
pw_memmap_free(mm);
pw_memmap_free(data->activation);
@ -241,7 +242,7 @@ static int client_node_transport(void *object,
clean_transport(data);
data->activation = pw_mempool_map_id(data->remote->pool, mem_id,
data->activation = pw_mempool_map_id(data->pool, mem_id,
PW_MEMMAP_FLAG_READWRITE, offset, size, NULL);
if (data->activation == NULL) {
pw_log_debug("remote-node %p: can't map activation: %m", proxy);
@ -408,7 +409,7 @@ client_node_set_io(void *object,
void *ptr;
uint32_t tag[5] = { data->remote_id, id, };
if ((mm = pw_mempool_find_tag(data->remote->pool, tag, sizeof(tag))) != NULL)
if ((mm = pw_mempool_find_tag(data->pool, tag, sizeof(tag))) != NULL)
pw_memmap_free(mm);
if (memid == SPA_ID_INVALID) {
@ -416,7 +417,7 @@ client_node_set_io(void *object,
size = 0;
}
else {
mm = pw_mempool_map_id(data->remote->pool, memid,
mm = pw_mempool_map_id(data->pool, memid,
PW_MEMMAP_FLAG_READWRITE, offset, size, tag);
if (mm == NULL) {
pw_log_warn("can't map memory id %u: %m", memid);
@ -599,7 +600,7 @@ client_node_port_use_buffers(void *object,
off_t offset;
struct pw_memmap *mm;
mm = pw_mempool_map_id(data->remote->pool, buffers[i].mem_id,
mm = pw_mempool_map_id(data->pool, buffers[i].mem_id,
prot, buffers[i].offset, buffers[i].size, NULL);
if (mm == NULL) {
res = -errno;
@ -661,7 +662,7 @@ client_node_port_use_buffers(void *object,
uint32_t mem_id = SPA_PTR_TO_UINT32(d->data);
struct pw_memblock *bm;
bm = pw_mempool_find_id(data->remote->pool, mem_id);
bm = pw_mempool_find_id(data->pool, mem_id);
if (bm == NULL) {
pw_log_error("unknown buffer mem %u", mem_id);
res = -ENODEV;
@ -730,7 +731,7 @@ client_node_port_set_io(void *object,
goto error_exit;
}
if ((mm = pw_mempool_find_tag(data->remote->pool, tag, sizeof(tag))) != NULL)
if ((mm = pw_mempool_find_tag(data->pool, tag, sizeof(tag))) != NULL)
pw_memmap_free(mm);
if (memid == SPA_ID_INVALID) {
@ -738,7 +739,7 @@ client_node_port_set_io(void *object,
size = 0;
}
else {
mm = pw_mempool_map_id(data->remote->pool, memid,
mm = pw_mempool_map_id(data->pool, memid,
PW_MEMMAP_FLAG_READWRITE, offset, size, tag);
if (mm == NULL) {
res = -errno;
@ -819,7 +820,7 @@ client_node_set_activation(void *object,
size = 0;
}
else {
mm = pw_mempool_map_id(data->remote->pool, memid,
mm = pw_mempool_map_id(data->pool, memid,
PW_MEMMAP_FLAG_READWRITE, offset, size, NULL);
if (mm == NULL) {
res = -errno;
@ -1104,7 +1105,7 @@ static const struct spa_node_callbacks node_callbacks = {
.xrun = node_xrun
};
static struct pw_proxy *node_export(struct pw_remote *remote, void *object, bool do_free,
static struct pw_proxy *node_export(struct pw_core_proxy *core_proxy, void *object, bool do_free,
size_t user_data_size)
{
struct pw_node *node = object;
@ -1112,7 +1113,7 @@ static struct pw_proxy *node_export(struct pw_remote *remote, void *object, bool
struct node_data *data;
int i;
client_node = pw_core_proxy_create_object(remote->core_proxy,
client_node = pw_core_proxy_create_object(core_proxy,
"client-node",
PW_TYPE_INTERFACE_ClientNode,
PW_VERSION_CLIENT_NODE,
@ -1122,7 +1123,7 @@ static struct pw_proxy *node_export(struct pw_remote *remote, void *object, bool
return NULL;
data = pw_proxy_get_user_data(client_node);
data->remote = remote;
data->pool = pw_core_proxy_get_mempool(core_proxy);
data->node = node;
data->do_free = do_free;
data->core = pw_node_get_core(node);
@ -1166,13 +1167,12 @@ struct pw_proxy *pw_core_proxy_node_export(struct pw_core_proxy *core_proxy,
size_t user_data_size)
{
struct pw_node *node = object;
struct pw_remote *remote = pw_proxy_get_remote((struct pw_proxy*)core_proxy);
if (props) {
pw_node_update_properties(node, &props->dict);
pw_properties_free(props);
}
return node_export(remote, object, false, user_data_size);
return node_export(core_proxy, object, false, user_data_size);
}
struct pw_proxy *pw_core_proxy_spa_node_export(struct pw_core_proxy *core_proxy,
@ -1180,9 +1180,8 @@ struct pw_proxy *pw_core_proxy_spa_node_export(struct pw_core_proxy *core_proxy,
size_t user_data_size)
{
struct pw_node *node;
struct pw_remote *remote = pw_proxy_get_remote((struct pw_proxy*)core_proxy);
node = pw_node_new(pw_remote_get_core(remote), props, 0);
node = pw_node_new(pw_core_proxy_get_core(core_proxy), props, 0);
if (node == NULL)
return NULL;
@ -1190,5 +1189,5 @@ struct pw_proxy *pw_core_proxy_spa_node_export(struct pw_core_proxy *core_proxy,
pw_node_register(node, NULL);
pw_node_set_active(node, true);
return node_export(remote, node, true, user_data_size);
return node_export(core_proxy, node, true, user_data_size);
}

View file

@ -79,6 +79,7 @@ struct protocol_data {
struct client {
struct pw_protocol_client this;
struct pw_core *core;
struct spa_source *source;
@ -579,9 +580,11 @@ static void
on_remote_data(void *data, int fd, uint32_t mask)
{
struct client *impl = data;
struct pw_remote *this = impl->this.remote;
struct pw_core_proxy *this = impl->this.core_proxy;
struct pw_remote *remote = pw_proxy_get_remote((struct pw_proxy*)this);
struct pw_protocol_native_connection *conn = impl->connection;
struct pw_core *core = pw_remote_get_core(this);
struct pw_core *core = pw_core_proxy_get_core(this);
struct pw_loop *loop = pw_core_get_main_loop(core);
int res;
if (mask & (SPA_IO_ERR | SPA_IO_HUP)) {
@ -593,7 +596,7 @@ on_remote_data(void *data, int fd, uint32_t mask)
if (res >= 0) {
int mask = impl->source->mask;
SPA_FLAG_CLEAR(mask, SPA_IO_OUT);
pw_loop_update_io(core->main_loop,
pw_loop_update_io(loop,
impl->source, mask);
impl->flushing = false;
} else if (res != EAGAIN)
@ -620,7 +623,7 @@ on_remote_data(void *data, int fd, uint32_t mask)
pw_log_trace(NAME" %p: got message %d from %u seq:%d",
this, msg->opcode, msg->id, msg->seq);
this->recv_seq = msg->seq;
remote->recv_seq = msg->seq;
if (debug_messages) {
fprintf(stderr, "<<<<<<<<< in: id:%d op:%d size:%d seq:%d\n",
@ -628,7 +631,7 @@ on_remote_data(void *data, int fd, uint32_t mask)
spa_debug_pod(0, NULL, (struct spa_pod *)msg->data);
}
proxy = pw_remote_find_proxy(this, msg->id);
proxy = pw_core_proxy_find_proxy(this, msg->id);
if (proxy == NULL || proxy->zombie) {
if (proxy == NULL)
pw_log_error(NAME" %p: could not find proxy %u", this, msg->id);
@ -667,25 +670,24 @@ on_remote_data(void *data, int fd, uint32_t mask)
return;
error:
pw_log_error(NAME" %p: got connection error %d (%s)", impl, res, spa_strerror(res));
pw_proxy_notify((struct pw_proxy*)this->core_proxy,
pw_proxy_notify((struct pw_proxy*)this,
struct pw_core_proxy_events, error, 0, 0,
this->recv_seq, res, "connection error");
pw_loop_destroy_source(pw_core_get_main_loop(core), impl->source);
remote->recv_seq, res, "connection error");
pw_loop_destroy_source(loop, impl->source);
impl->source = NULL;
pw_remote_disconnect(this);
pw_core_proxy_disconnect(this);
}
static void on_need_flush(void *data)
{
struct client *impl = data;
struct pw_remote *remote = impl->this.remote;
if (!impl->flushing && impl->source) {
int mask = impl->source->mask;
impl->flushing = true;
SPA_FLAG_SET(mask, SPA_IO_OUT);
pw_loop_update_io(remote->core->main_loop,
pw_loop_update_io(impl->core->main_loop,
impl->source, mask);
}
}
@ -698,15 +700,15 @@ static const struct pw_protocol_native_connection_events client_conn_events = {
static int impl_connect_fd(struct pw_protocol_client *client, int fd, bool do_close)
{
struct client *impl = SPA_CONTAINER_OF(client, struct client, this);
struct pw_remote *remote = client->remote;
int res;
impl->disconnecting = false;
pw_protocol_native_connection_set_fd(impl->connection, fd);
impl->source = pw_loop_add_io(remote->core->main_loop,
impl->flushing = true;
impl->source = pw_loop_add_io(impl->core->main_loop,
fd,
SPA_IO_IN | SPA_IO_HUP | SPA_IO_ERR,
SPA_IO_IN | SPA_IO_OUT | SPA_IO_HUP | SPA_IO_ERR,
do_close, on_remote_data, impl);
if (impl->source == NULL) {
res = -errno;
@ -730,12 +732,11 @@ error_cleanup:
static void impl_disconnect(struct pw_protocol_client *client)
{
struct client *impl = SPA_CONTAINER_OF(client, struct client, this);
struct pw_remote *remote = client->remote;
impl->disconnecting = true;
if (impl->source)
pw_loop_destroy_source(remote->core->main_loop, impl->source);
pw_loop_destroy_source(impl->core->main_loop, impl->source);
impl->source = NULL;
if (impl->connection)
@ -755,7 +756,6 @@ static void impl_destroy(struct pw_protocol_client *client)
static struct pw_protocol_client *
impl_new_client(struct pw_protocol *protocol,
struct pw_remote *remote,
struct pw_properties *properties)
{
struct client *impl;
@ -768,9 +768,9 @@ impl_new_client(struct pw_protocol *protocol,
this = &impl->this;
this->protocol = protocol;
this->remote = remote;
impl->connection = pw_protocol_native_connection_new(remote->core, -1);
impl->core = protocol->core;
impl->connection = pw_protocol_native_connection_new(protocol->core, -1);
if (impl->connection == NULL) {
res = -errno;
goto error_free;
@ -872,10 +872,10 @@ get_name(const struct pw_properties *properties)
static struct pw_protocol_server *
impl_add_server(struct pw_protocol *protocol,
struct pw_core *core,
struct pw_properties *properties)
{
struct pw_protocol_server *this;
struct pw_core *core = protocol->core;
struct server *s;
const char *name;
int res;
@ -1034,7 +1034,7 @@ int pipewire__module_init(struct pw_module *module, const char *args)
if (val == NULL)
val = pw_properties_get(pw_core_get_properties(core), PW_KEY_CORE_DAEMON);
if (val && pw_properties_parse_bool(val)) {
if (impl_add_server(this, core, NULL) == NULL) {
if (impl_add_server(this, NULL) == NULL) {
res = -errno;
goto error_cleanup;
}

View file

@ -23,8 +23,10 @@
*/
int pw_protocol_native_connect_local_socket(struct pw_protocol_client *client,
const struct spa_dict *props,
void (*done_callback) (void *data, int res),
void *data);
int pw_protocol_native_connect_portal_screencast(struct pw_protocol_client *client,
const struct spa_dict *props,
void (*done_callback) (void *data, int res),
void *data);

View file

@ -37,12 +37,12 @@
#include <pipewire/pipewire.h>
static const char *
get_remote(const struct pw_properties *properties)
get_remote(const struct spa_dict *props)
{
const char *name = NULL;
if (properties)
name = pw_properties_get(properties, PW_KEY_REMOTE_NAME);
if (props)
name = spa_dict_lookup(props, PW_KEY_REMOTE_NAME);
if (name == NULL)
name = getenv("PIPEWIRE_REMOTE");
if (name == NULL)
@ -51,10 +51,10 @@ get_remote(const struct pw_properties *properties)
}
int pw_protocol_native_connect_local_socket(struct pw_protocol_client *client,
const struct spa_dict *props,
void (*done_callback) (void *data, int res),
void *data)
{
struct pw_remote *remote = client->remote;
struct sockaddr_un addr;
socklen_t size;
const char *runtime_dir, *name = NULL;
@ -66,7 +66,7 @@ int pw_protocol_native_connect_local_socket(struct pw_protocol_client *client,
goto error;
}
name = get_remote(pw_remote_get_properties(remote));
name = get_remote(props);
if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0) {
res = -errno;

View file

@ -33,6 +33,7 @@
#include <pipewire/pipewire.h>
int pw_protocol_native_connect_portal_screencast(struct pw_protocol_client *client,
const struct spa_dict *props,
void (*done_callback) (void *data, int res),
void *data)
{

View file

@ -70,7 +70,6 @@ struct queue {
struct data {
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook filter_listener;
};
@ -120,8 +119,6 @@ struct filter {
enum pw_filter_flags flags;
struct spa_hook remote_listener;
struct pw_node *node;
struct spa_node impl_node;
@ -139,7 +136,6 @@ struct filter {
uintptr_t seq;
struct pw_time time;
unsigned int async_connect:1;
unsigned int disconnecting:1;
unsigned int free_data:1;
unsigned int subscribe:1;
@ -882,83 +878,25 @@ static const struct pw_proxy_events proxy_events = {
.bound = proxy_bound,
};
static int handle_connect(struct pw_filter *filter)
{
struct filter *impl = SPA_CONTAINER_OF(filter, struct filter, this);
struct pw_properties *props;
int res;
pw_log_debug(NAME" %p: creating node", filter);
props = pw_properties_copy(filter->properties);
impl->node = pw_node_new(impl->core, props, 0);
if (impl->node == NULL) {
res = -errno;
goto error_node;
}
impl->node->port_user_data_size = sizeof(struct port);
pw_node_set_implementation(impl->node, &impl->impl_node);
pw_log_debug(NAME" %p: export node %p", filter, impl->node);
filter->proxy = pw_remote_export(filter->remote,
PW_TYPE_INTERFACE_Node, NULL, impl->node, 0);
if (filter->proxy == NULL) {
res = -errno;
goto error_proxy;
}
pw_proxy_add_listener(filter->proxy, &filter->proxy_listener, &proxy_events, filter);
if (!SPA_FLAG_IS_SET(impl->flags, PW_FILTER_FLAG_INACTIVE))
pw_node_set_active(impl->node, true);
return 0;
error_node:
pw_log_error(NAME" %p: can't make node: %s", filter, spa_strerror(res));
return res;
error_proxy:
pw_log_error(NAME" %p: can't make proxy: %s", filter, spa_strerror(res));
return res;
}
static void on_remote_state_changed(void *_data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
static void on_core_error(void *_data, uint32_t id, int seq, int res, const char *message)
{
struct pw_filter *filter = _data;
struct filter *impl = SPA_CONTAINER_OF(filter, struct filter, this);
pw_log_debug(NAME" %p: remote state %d", filter, state);
switch (state) {
case PW_REMOTE_STATE_ERROR:
filter_set_state(filter, PW_FILTER_STATE_ERROR, error);
break;
case PW_REMOTE_STATE_UNCONNECTED:
filter_set_state(filter, PW_FILTER_STATE_UNCONNECTED, "remote unconnected");
break;
case PW_REMOTE_STATE_CONNECTED:
if (impl->async_connect)
handle_connect(filter);
break;
default:
break;
pw_log_error(NAME" %p: error id:%u seq:%d res:%d (%s): %s", filter,
id, seq, res, spa_strerror(res), message);
if (id == 0) {
filter_set_state(filter, PW_FILTER_STATE_UNCONNECTED, message);
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_remote_state_changed,
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.error = on_core_error,
};
SPA_EXPORT
struct pw_filter * pw_filter_new(struct pw_remote *remote, const char *name,
struct pw_properties *props)
static struct filter *
filter_new(struct pw_core *core, const char *name,
struct pw_properties *props, struct pw_properties *extra)
{
struct filter *impl;
struct pw_filter *this;
@ -984,12 +922,10 @@ struct pw_filter * pw_filter_new(struct pw_remote *remote, const char *name,
goto error_properties;
}
if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL) {
const struct pw_properties *p = pw_remote_get_properties(remote);
if ((str = pw_properties_get(p, PW_KEY_APP_NAME)) != NULL)
if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL && extra) {
if ((str = pw_properties_get(extra, PW_KEY_APP_NAME)) != NULL)
pw_properties_set(props, PW_KEY_NODE_NAME, str);
else if ((str = pw_properties_get(p, PW_KEY_APP_PROCESS_BINARY)) != NULL)
else if ((str = pw_properties_get(extra, PW_KEY_APP_PROCESS_BINARY)) != NULL)
pw_properties_set(props, PW_KEY_NODE_NAME, str);
else
pw_properties_set(props, PW_KEY_NODE_NAME, name);
@ -998,7 +934,6 @@ struct pw_filter * pw_filter_new(struct pw_remote *remote, const char *name,
spa_hook_list_init(&impl->hooks);
this->properties = props;
this->remote = remote;
this->name = name ? strdup(name) : NULL;
this->node_id = SPA_ID_INVALID;
@ -1010,13 +945,11 @@ struct pw_filter * pw_filter_new(struct pw_remote *remote, const char *name,
this->state = PW_FILTER_STATE_UNCONNECTED;
impl->core = remote->core;
impl->core = core;
pw_remote_add_listener(remote, &impl->remote_listener, &remote_events, this);
// spa_list_append(&remote->filter_list, &this->link);
spa_list_append(&remote->filter_list, &this->link);
return this;
return impl;
error_properties:
free(impl);
@ -1027,6 +960,26 @@ error_cleanup:
return NULL;
}
SPA_EXPORT
struct pw_filter * pw_filter_new(struct pw_core_proxy *core_proxy, const char *name,
struct pw_properties *props)
{
struct filter *impl;
struct pw_filter *this;
struct pw_core *core = pw_core_proxy_get_core(core_proxy);
impl = filter_new(core, name, props, NULL);
if (impl == NULL)
return NULL;
this = &impl->this;
this->core_proxy = core_proxy;
pw_core_proxy_add_listener(core_proxy,
&this->core_listener, &core_events, this);
return this;
}
SPA_EXPORT
struct pw_filter *
pw_filter_new_simple(struct pw_loop *loop,
@ -1035,30 +988,26 @@ pw_filter_new_simple(struct pw_loop *loop,
const struct pw_filter_events *events,
void *data)
{
struct pw_filter *filter;
struct pw_filter *this;
struct filter *impl;
struct pw_core *core;
struct pw_remote *remote;
int res;
core = pw_core_new(loop, NULL, 0);
remote = pw_remote_new(core, NULL, 0);
filter = pw_filter_new(remote, name, props);
if (filter == NULL) {
impl = filter_new(core, name, props, NULL);
if (impl == NULL) {
res = -errno;
goto error_cleanup;
}
impl = SPA_CONTAINER_OF(filter, struct filter, this);
this = &impl->this;
impl->free_data = true;
impl->data.core = core;
impl->data.remote = remote;
pw_filter_add_listener(this, &impl->data.filter_listener, events, data);
pw_filter_add_listener(filter, &impl->data.filter_listener, events, data);
return filter;
return this;
error_cleanup:
pw_core_destroy(core);
@ -1095,8 +1044,11 @@ void pw_filter_destroy(struct pw_filter *filter)
pw_filter_disconnect(filter);
spa_hook_remove(&impl->remote_listener);
spa_list_remove(&filter->link);
if (filter->core_proxy) {
spa_hook_remove(&filter->core_listener);
filter->core_proxy = NULL;
}
// spa_list_remove(&filter->link);
clear_params(impl, NULL, SPA_ID_INVALID);
@ -1131,9 +1083,9 @@ enum pw_filter_state pw_filter_get_state(struct pw_filter *filter, const char **
}
SPA_EXPORT
struct pw_remote *pw_filter_get_remote(struct pw_filter *filter)
struct pw_core_proxy *pw_filter_get_core_proxy(struct pw_filter *filter)
{
return filter->remote;
return filter->core_proxy;
}
SPA_EXPORT
@ -1183,7 +1135,7 @@ pw_filter_connect(struct pw_filter *filter,
uint32_t n_params)
{
struct filter *impl = SPA_CONTAINER_OF(filter, struct filter, this);
enum pw_remote_state state;
struct pw_properties *props;
int res;
uint32_t i;
@ -1203,15 +1155,53 @@ pw_filter_connect(struct pw_filter *filter,
impl->disconnecting = false;
filter_set_state(filter, PW_FILTER_STATE_CONNECTING, NULL);
state = pw_remote_get_state(filter->remote, NULL);
impl->async_connect = (state == PW_REMOTE_STATE_UNCONNECTED ||
state == PW_REMOTE_STATE_ERROR);
if (filter->core_proxy == NULL) {
filter->core_proxy = pw_core_connect(impl->core,
pw_properties_copy(filter->properties), 0);
if (filter->core_proxy == NULL) {
res = -errno;
goto error_connect;
}
pw_core_proxy_add_listener(filter->core_proxy,
&filter->core_listener, &core_events, filter);
}
if (impl->async_connect)
res = pw_remote_connect(filter->remote);
else
res = handle_connect(filter);
pw_log_debug(NAME" %p: creating node", filter);
props = pw_properties_copy(filter->properties);
impl->node = pw_node_new(impl->core, props, 0);
if (impl->node == NULL) {
res = -errno;
goto error_node;
}
impl->node->port_user_data_size = sizeof(struct port);
pw_node_set_implementation(impl->node, &impl->impl_node);
pw_log_debug(NAME" %p: export node %p", filter, impl->node);
filter->proxy = pw_core_proxy_export(filter->core_proxy,
PW_TYPE_INTERFACE_Node, NULL, impl->node, 0);
if (filter->proxy == NULL) {
res = -errno;
goto error_proxy;
}
pw_proxy_add_listener(filter->proxy, &filter->proxy_listener, &proxy_events, filter);
if (!SPA_FLAG_IS_SET(impl->flags, PW_FILTER_FLAG_INACTIVE))
pw_node_set_active(impl->node, true);
return 0;
error_connect:
pw_log_error(NAME" %p: can't connect: %s", filter, spa_strerror(res));
return res;
error_node:
pw_log_error(NAME" %p: can't make node: %s", filter, spa_strerror(res));
return res;
error_proxy:
pw_log_error(NAME" %p: can't make proxy: %s", filter, spa_strerror(res));
return res;
}

View file

@ -124,7 +124,7 @@ enum pw_filter_port_flags {
/** Create a new unconneced \ref pw_filter \memberof pw_filter
* \return a newly allocated \ref pw_filter */
struct pw_filter *
pw_filter_new(struct pw_remote *remote, /**< a \ref pw_remote */
pw_filter_new(struct pw_core_proxy *proxy, /**< a \ref pw_core_proxy */
const char *name, /**< a filter media name */
struct pw_properties *props /**< filter properties, ownership is taken */);
@ -147,7 +147,7 @@ enum pw_filter_state pw_filter_get_state(struct pw_filter *filter, const char **
const char *pw_stream_get_name(struct pw_stream *stream);
struct pw_remote *pw_filter_get_remote(struct pw_filter *filter);
struct pw_core_proxy *pw_filter_get_core_proxy(struct pw_filter *filter);
/** Connect a filter for processing. \memberof pw_filter
* \return 0 on success < 0 on error.

View file

@ -774,8 +774,10 @@ struct pw_remote {
struct pw_stream {
struct pw_remote *remote; /**< the owner remote */
struct spa_list link; /**< link in the remote */
struct pw_core_proxy *core_proxy; /**< the owner core_proxy */
struct spa_hook core_listener;
struct spa_list link; /**< link in the core_proxy */
char *name; /**< the name of the stream */
struct pw_properties *properties; /**< properties of the stream */
@ -808,8 +810,10 @@ struct pw_stream {
struct pw_filter {
struct pw_remote *remote; /**< the owner remote */
struct spa_list link; /**< link in the remote */
struct pw_core_proxy *core_proxy; /**< the owner core proxy */
struct spa_hook core_listener;
struct spa_list link; /**< link in the core proxy */
char *name; /**< the name of the filter */
struct pw_properties *properties; /**< properties of the filter */

View file

@ -44,9 +44,10 @@ struct pw_protocol_client {
struct spa_list link; /**< link in protocol client_list */
struct pw_protocol *protocol; /**< the owner protocol */
struct pw_remote *remote; /**< the associated remote */
struct pw_core_proxy *core_proxy;
int (*connect) (struct pw_protocol_client *client,
const struct spa_dict *props,
void (*done_callback) (void *data, int result),
void *data);
int (*connect_fd) (struct pw_protocol_client *client, int fd, bool close);
@ -55,7 +56,7 @@ struct pw_protocol_client {
void (*destroy) (struct pw_protocol_client *client);
};
#define pw_protocol_client_connect(c,cb,d) ((c)->connect(c,cb,d))
#define pw_protocol_client_connect(c,p,cb,d) ((c)->connect(c,p,cb,d))
#define pw_protocol_client_connect_fd(c,fd,cl) ((c)->connect_fd(c,fd,cl))
#define pw_protocol_client_steal_fd(c) ((c)->steal_fd(c))
#define pw_protocol_client_disconnect(c) ((c)->disconnect(c))
@ -90,10 +91,8 @@ struct pw_protocol_implementaton {
uint32_t version;
struct pw_protocol_client * (*new_client) (struct pw_protocol *protocol,
struct pw_remote *remote,
struct pw_properties *properties);
struct pw_protocol_server * (*add_server) (struct pw_protocol *protocol,
struct pw_core *core,
struct pw_properties *properties);
};

View file

@ -247,7 +247,7 @@ struct pw_remote *pw_remote_new(struct pw_core *core,
goto error_protocol;
}
this->conn = pw_protocol_new_client(protocol, this, properties);
this->conn = pw_protocol_new_client(protocol, properties);
if (this->conn == NULL)
goto error_connection;
@ -411,6 +411,8 @@ static int init_connect(struct pw_remote *remote)
pw_core_proxy_hello(remote->core_proxy, PW_VERSION_CORE_PROXY);
pw_client_proxy_update_properties(remote->client_proxy, &remote->properties->dict);
remote->conn->core_proxy = remote->core_proxy;
return 0;
error_clean_core_proxy:
@ -469,7 +471,9 @@ int pw_remote_connect(struct pw_remote *remote)
if ((res = init_connect(remote)) < 0)
goto error;
if ((res = pw_protocol_client_connect(remote->conn, done_connect, remote)) < 0)
if ((res = pw_protocol_client_connect(remote->conn,
&remote->properties->dict,
done_connect, remote)) < 0)
goto error;
return remote->state == PW_REMOTE_STATE_ERROR ? -EIO : 0;
@ -587,3 +591,99 @@ exit:
errno = -res;
return NULL;
}
SPA_EXPORT
struct pw_core_proxy *
pw_core_connect(struct pw_core *core, struct pw_properties *properties,
size_t user_data_size)
{
struct pw_remote *remote;
int res;
remote = pw_remote_new(core, properties, user_data_size);
if (remote == NULL)
return NULL;
if ((res = pw_remote_connect(remote)) < 0)
goto error_free;
return remote->core_proxy;
error_free:
pw_remote_destroy(remote);
errno = -res;
return NULL;
}
SPA_EXPORT
struct pw_core_proxy *
pw_core_connect_fd(struct pw_core *core, int fd, struct pw_properties *properties,
size_t user_data_size)
{
struct pw_remote *remote;
int res;
remote = pw_remote_new(core, properties, user_data_size);
if (remote == NULL)
return NULL;
if ((res = pw_remote_connect_fd(remote, fd)) < 0)
goto error_free;
return remote->core_proxy;
error_free:
pw_remote_destroy(remote);
errno = -res;
return NULL;
}
SPA_EXPORT
struct pw_client_proxy * pw_core_proxy_get_client_proxy(struct pw_core_proxy *proxy)
{
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
return remote->client_proxy;
}
SPA_EXPORT
struct pw_core * pw_core_proxy_get_core(struct pw_core_proxy *proxy)
{
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
return remote->core;
}
SPA_EXPORT
struct pw_remote * pw_core_proxy_get_remote(struct pw_core_proxy *proxy)
{
return ((struct pw_proxy*)proxy)->remote;
}
SPA_EXPORT
struct pw_mempool * pw_core_proxy_get_mempool(struct pw_core_proxy *proxy)
{
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
return remote->pool;
}
SPA_EXPORT
struct pw_proxy *pw_core_proxy_find_proxy(struct pw_core_proxy *proxy, uint32_t id)
{
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
return pw_remote_find_proxy(remote, id);
}
SPA_EXPORT
int pw_core_proxy_disconnect(struct pw_core_proxy *proxy)
{
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
pw_remote_destroy(remote);
return 0;
}
SPA_EXPORT
struct pw_proxy *pw_core_proxy_export(struct pw_core_proxy *proxy,
uint32_t type, struct pw_properties *properties,
void *object, size_t user_data_size)
{
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
return pw_remote_export(remote, type, properties, object, user_data_size);
}

View file

@ -203,6 +203,41 @@ struct pw_proxy *pw_remote_export(struct pw_remote *remote, /**< the remote */
void *object, /**< object to export */
size_t user_data_size /**< extra user data */);
struct pw_core_proxy *
pw_core_connect(struct pw_core *core, /**< a \ref pw_core */
struct pw_properties *properties, /**< optional properties, ownership of
* the properties is taken.*/
size_t user_data_size /**< extra user data size */);
struct pw_core_proxy *
pw_core_connect_fd(struct pw_core *core, /**< a \ref pw_core */
int fd, /**< an fd */
struct pw_properties *properties, /**< optional properties, ownership of
* the properties is taken.*/
size_t user_data_size /**< extra user data size */);
int pw_core_proxy_disconnect(struct pw_core_proxy *proxy);
/** Get the client proxy */
struct pw_client_proxy * pw_core_proxy_get_client_proxy(struct pw_core_proxy *proxy);
struct pw_core * pw_core_proxy_get_core(struct pw_core_proxy *proxy);
struct pw_remote * pw_core_proxy_get_remote(struct pw_core_proxy *proxy);
struct pw_mempool * pw_core_proxy_get_mempool(struct pw_core_proxy *proxy);
/** Get the proxy with the given id */
struct pw_proxy *pw_core_proxy_find_proxy(struct pw_core_proxy *proxy, uint32_t id);
struct pw_proxy *pw_core_proxy_export(struct pw_core_proxy *proxy, /**< the proxy */
uint32_t type, /**< the type of object */
struct pw_properties *properties, /**< extra properties */
void *object, /**< object to export */
size_t user_data_size /**< extra user data */);
#ifdef __cplusplus
}
#endif

View file

@ -67,7 +67,6 @@ struct queue {
struct data {
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook stream_listener;
};
@ -125,7 +124,6 @@ struct stream {
uintptr_t seq;
struct pw_time time;
unsigned int async_connect:1;
unsigned int disconnecting:1;
unsigned int free_data:1;
unsigned int alloc_buffers:1;
@ -1000,114 +998,25 @@ static const struct pw_node_events node_events = {
.info_changed = node_event_info,
};
static int handle_connect(struct pw_stream *stream)
static void on_core_error(void *object, uint32_t id, int seq, int res, const char *message)
{
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
struct pw_factory *factory;
struct pw_properties *props;
struct pw_node *slave;
const char *str;
int res;
struct pw_stream *stream = object;
pw_log_debug(NAME" %p: creating node", stream);
props = pw_properties_copy(stream->properties);
if ((str = pw_properties_get(props, PW_KEY_STREAM_MONITOR)) &&
pw_properties_parse_bool(str)) {
pw_properties_set(props, "resample.peaks", "1");
}
slave = pw_node_new(impl->core, pw_properties_copy(props), 0);
if (slave == NULL) {
res = -errno;
goto error_node;
}
pw_node_set_implementation(slave, &impl->impl_node);
if (!SPA_FLAG_IS_SET(impl->flags, PW_STREAM_FLAG_INACTIVE))
pw_node_set_active(slave, true);
if (impl->media_type == SPA_MEDIA_TYPE_audio &&
impl->media_subtype == SPA_MEDIA_SUBTYPE_raw) {
factory = pw_core_find_factory(impl->core, "adapter");
if (factory == NULL) {
pw_log_error(NAME" %p: no adapter factory found", stream);
res = -ENOENT;
goto error_node;
}
pw_properties_setf(props, "adapt.slave.node", "pointer:%p", slave);
impl->node = pw_factory_create_object(factory,
NULL,
PW_TYPE_INTERFACE_Node,
PW_VERSION_NODE_PROXY,
props,
0);
if (impl->node == NULL) {
res = -errno;
goto error_node;
}
} else {
impl->node = slave;
}
pw_log_debug(NAME" %p: export node %p", stream, impl->node);
stream->proxy = pw_remote_export(stream->remote,
PW_TYPE_INTERFACE_Node, NULL, impl->node, 0);
if (stream->proxy == NULL) {
res = -errno;
goto error_proxy;
}
pw_proxy_add_listener(stream->proxy, &stream->proxy_listener, &proxy_events, stream);
pw_node_add_listener(impl->node, &stream->node_listener, &node_events, stream);
return 0;
error_node:
pw_log_error(NAME" %p: can't make node: %s", stream, spa_strerror(res));
return res;
error_proxy:
pw_log_error(NAME" %p: can't make proxy: %s", stream, spa_strerror(res));
return res;
}
static void on_remote_state_changed(void *_data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
{
struct pw_stream *stream = _data;
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
pw_log_debug(NAME" %p: remote state %d", stream, state);
switch (state) {
case PW_REMOTE_STATE_ERROR:
stream_set_state(stream, PW_STREAM_STATE_ERROR, error);
break;
case PW_REMOTE_STATE_UNCONNECTED:
stream_set_state(stream, PW_STREAM_STATE_UNCONNECTED, "remote unconnected");
break;
case PW_REMOTE_STATE_CONNECTED:
if (impl->async_connect)
handle_connect(stream);
break;
default:
break;
pw_log_error(NAME" %p: error id:%u seq:%d res:%d (%s): %s", stream,
id, seq, res, spa_strerror(res), message);
if (id == 0) {
stream_set_state(stream, PW_STREAM_STATE_UNCONNECTED, message);
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_remote_state_changed,
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.error = on_core_error,
};
SPA_EXPORT
struct pw_stream * pw_stream_new(struct pw_remote *remote, const char *name,
struct pw_properties *props)
static struct stream *
stream_new(struct pw_core *core, const char *name,
struct pw_properties *props, struct pw_properties *extra)
{
struct stream *impl;
struct pw_stream *this;
@ -1133,12 +1042,10 @@ struct pw_stream * pw_stream_new(struct pw_remote *remote, const char *name,
goto error_properties;
}
if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL) {
const struct pw_properties *p = pw_remote_get_properties(remote);
if ((str = pw_properties_get(p, PW_KEY_APP_NAME)) != NULL)
if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL && extra) {
if ((str = pw_properties_get(extra, PW_KEY_APP_NAME)) != NULL)
pw_properties_set(props, PW_KEY_NODE_NAME, str);
else if ((str = pw_properties_get(p, PW_KEY_APP_PROCESS_BINARY)) != NULL)
else if ((str = pw_properties_get(extra, PW_KEY_APP_PROCESS_BINARY)) != NULL)
pw_properties_set(props, PW_KEY_NODE_NAME, str);
else
pw_properties_set(props, PW_KEY_NODE_NAME, name);
@ -1147,7 +1054,6 @@ struct pw_stream * pw_stream_new(struct pw_remote *remote, const char *name,
spa_hook_list_init(&impl->hooks);
this->properties = props;
this->remote = remote;
this->name = name ? strdup(name) : NULL;
this->node_id = SPA_ID_INVALID;
@ -1160,13 +1066,11 @@ struct pw_stream * pw_stream_new(struct pw_remote *remote, const char *name,
this->state = PW_STREAM_STATE_UNCONNECTED;
impl->core = remote->core;
impl->core = core;
pw_remote_add_listener(remote, &impl->remote_listener, &remote_events, this);
// spa_list_append(&remote->stream_list, &this->link);
spa_list_append(&remote->stream_list, &this->link);
return this;
return impl;
error_properties:
free(impl);
@ -1177,6 +1081,26 @@ error_cleanup:
return NULL;
}
SPA_EXPORT
struct pw_stream * pw_stream_new(struct pw_core_proxy *core_proxy, const char *name,
struct pw_properties *props)
{
struct stream *impl;
struct pw_stream *this;
struct pw_core *core = pw_core_proxy_get_core(core_proxy);
impl = stream_new(core, name, props, NULL);
if (impl == NULL)
return NULL;
this = &impl->this;
this->core_proxy = core_proxy;
pw_core_proxy_add_listener(core_proxy,
&this->core_listener, &core_events, this);
return this;
}
SPA_EXPORT
struct pw_stream *
pw_stream_new_simple(struct pw_loop *loop,
@ -1185,30 +1109,25 @@ pw_stream_new_simple(struct pw_loop *loop,
const struct pw_stream_events *events,
void *data)
{
struct pw_stream *stream;
struct pw_stream *this;
struct stream *impl;
struct pw_core *core;
struct pw_remote *remote;
int res;
core = pw_core_new(loop, NULL, 0);
remote = pw_remote_new(core, NULL, 0);
stream = pw_stream_new(remote, name, props);
if (stream == NULL) {
impl = stream_new(core, name, props, NULL);
if (impl == NULL) {
res = -errno;
goto error_cleanup;
}
impl = SPA_CONTAINER_OF(stream, struct stream, this);
this = &impl->this;
impl->free_data = true;
impl->data.core = core;
impl->data.remote = remote;
pw_stream_add_listener(this, &impl->data.stream_listener, events, data);
pw_stream_add_listener(stream, &impl->data.stream_listener, events, data);
return stream;
return this;
error_cleanup:
pw_core_destroy(core);
@ -1246,8 +1165,11 @@ void pw_stream_destroy(struct pw_stream *stream)
pw_stream_disconnect(stream);
spa_hook_remove(&impl->remote_listener);
spa_list_remove(&stream->link);
if (stream->core_proxy) {
spa_hook_remove(&stream->core_listener);
stream->core_proxy = NULL;
}
// spa_list_remove(&stream->link);
clear_params(impl, SPA_ID_INVALID);
@ -1316,9 +1238,9 @@ int pw_stream_update_properties(struct pw_stream *stream, const struct spa_dict
}
SPA_EXPORT
struct pw_remote *pw_stream_get_remote(struct pw_stream *stream)
struct pw_core_proxy *pw_stream_get_core_proxy(struct pw_stream *stream)
{
return stream->remote;
return stream->core_proxy;
}
static void add_params(struct stream *impl)
@ -1390,9 +1312,12 @@ pw_stream_connect(struct pw_stream *stream,
uint32_t n_params)
{
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
enum pw_remote_state state;
int res;
struct pw_factory *factory;
struct pw_properties *props;
struct pw_node *slave;
const char *str;
uint32_t i;
int res;
pw_log_debug(NAME" %p: connect target:%d", stream, target_id);
impl->direction =
@ -1445,15 +1370,82 @@ pw_stream_connect(struct pw_stream *stream,
direction == PW_DIRECTION_INPUT ? "Input" : "Output",
get_media_class(impl));
state = pw_remote_get_state(stream->remote, NULL);
impl->async_connect = (state == PW_REMOTE_STATE_UNCONNECTED ||
state == PW_REMOTE_STATE_ERROR);
if (stream->core_proxy == NULL) {
stream->core_proxy = pw_core_connect(impl->core,
pw_properties_copy(stream->properties), 0);
if (stream->core_proxy == NULL) {
res = -errno;
goto error_connect;
}
pw_core_proxy_add_listener(stream->core_proxy,
&stream->core_listener, &core_events, stream);
}
if (impl->async_connect)
res = pw_remote_connect(stream->remote);
else
res = handle_connect(stream);
pw_log_debug(NAME" %p: creating node", stream);
props = pw_properties_copy(stream->properties);
if ((str = pw_properties_get(props, PW_KEY_STREAM_MONITOR)) &&
pw_properties_parse_bool(str)) {
pw_properties_set(props, "resample.peaks", "1");
}
slave = pw_node_new(impl->core, pw_properties_copy(props), 0);
if (slave == NULL) {
res = -errno;
goto error_node;
}
pw_node_set_implementation(slave, &impl->impl_node);
if (!SPA_FLAG_IS_SET(impl->flags, PW_STREAM_FLAG_INACTIVE))
pw_node_set_active(slave, true);
if (impl->media_type == SPA_MEDIA_TYPE_audio &&
impl->media_subtype == SPA_MEDIA_SUBTYPE_raw) {
factory = pw_core_find_factory(impl->core, "adapter");
if (factory == NULL) {
pw_log_error(NAME" %p: no adapter factory found", stream);
res = -ENOENT;
goto error_node;
}
pw_properties_setf(props, "adapt.slave.node", "pointer:%p", slave);
impl->node = pw_factory_create_object(factory,
NULL,
PW_TYPE_INTERFACE_Node,
PW_VERSION_NODE_PROXY,
props,
0);
if (impl->node == NULL) {
res = -errno;
goto error_node;
}
} else {
impl->node = slave;
}
pw_log_debug(NAME" %p: export node %p", stream, impl->node);
stream->proxy = pw_core_proxy_export(stream->core_proxy,
PW_TYPE_INTERFACE_Node, NULL, impl->node, 0);
if (stream->proxy == NULL) {
res = -errno;
goto error_proxy;
}
pw_proxy_add_listener(stream->proxy, &stream->proxy_listener, &proxy_events, stream);
pw_node_add_listener(impl->node, &stream->node_listener, &node_events, stream);
return 0;
error_connect:
pw_log_error(NAME" %p: can't connect: %s", stream, spa_strerror(res));
return res;
error_node:
pw_log_error(NAME" %p: can't make node: %s", stream, spa_strerror(res));
return res;
error_proxy:
pw_log_error(NAME" %p: can't make proxy: %s", stream, spa_strerror(res));
return res;
}

View file

@ -247,7 +247,7 @@ enum pw_stream_flags {
/** Create a new unconneced \ref pw_stream \memberof pw_stream
* \return a newly allocated \ref pw_stream */
struct pw_stream *
pw_stream_new(struct pw_remote *remote, /**< a \ref pw_remote */
pw_stream_new(struct pw_core_proxy *proxy, /**< a \ref pw_core_proxy */
const char *name, /**< a stream media name */
struct pw_properties *props /**< stream properties, ownership is taken */);
@ -270,7 +270,7 @@ enum pw_stream_state pw_stream_get_state(struct pw_stream *stream, const char **
const char *pw_stream_get_name(struct pw_stream *stream);
struct pw_remote *pw_stream_get_remote(struct pw_stream *stream);
struct pw_core_proxy *pw_stream_get_core_proxy(struct pw_stream *stream);
const struct pw_properties *pw_stream_get_properties(struct pw_stream *stream);

View file

@ -134,7 +134,6 @@ static void test_create(void)
{
struct pw_main_loop *loop;
struct pw_core *core;
struct pw_remote *remote;
struct pw_stream *stream;
struct pw_stream_events stream_events = stream_events_error;
struct spa_hook listener = { 0, };
@ -143,8 +142,7 @@ static void test_create(void)
loop = pw_main_loop_new(NULL);
core = pw_core_new(pw_main_loop_get_loop(loop), NULL, 12);
remote = pw_remote_new(core, NULL, 12);
stream = pw_stream_new(remote, "test", NULL);
stream = pw_stream_new(NULL, "test", NULL);
spa_assert(stream != NULL);
pw_stream_add_listener(stream, &listener, &stream_events, stream);
@ -153,8 +151,6 @@ static void test_create(void)
spa_assert(error == NULL);
/* check name */
spa_assert(!strcmp(pw_stream_get_name(stream), "test"));
/* check remote */
spa_assert(pw_stream_get_remote(stream) == remote);
/* check id, only when connected */
spa_assert(pw_stream_get_node_id(stream) == SPA_ID_INVALID);
@ -184,7 +180,6 @@ static void test_properties(void)
struct pw_main_loop *loop;
struct pw_core *core;
const struct pw_properties *props;
struct pw_remote *remote;
struct pw_stream *stream;
struct pw_stream_events stream_events = stream_events_error;
struct spa_hook listener = { NULL, };
@ -192,8 +187,7 @@ static void test_properties(void)
loop = pw_main_loop_new(NULL);
core = pw_core_new(pw_main_loop_get_loop(loop), NULL, 0);
remote = pw_remote_new(core, NULL, 0);
stream = pw_stream_new(remote, "test",
stream = pw_stream_new(NULL, "test",
pw_properties_new("foo", "bar",
"biz", "fuzz",
NULL));

View file

@ -28,6 +28,7 @@
#include <signal.h>
#include <string.h>
#include <spa/utils/result.h>
#include <spa/debug/pod.h>
#include <spa/debug/format.h>
@ -71,12 +72,11 @@ struct remote_data {
char *name;
uint32_t id;
struct pw_remote *remote;
struct spa_hook remote_listener;
int prompt_pending;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;
struct spa_hook core_proxy_listener;
struct pw_registry_proxy *registry_proxy;
struct spa_hook registry_listener;
@ -370,7 +370,27 @@ static const struct pw_registry_proxy_events registry_events = {
.global_remove = registry_event_global_remove,
};
static void on_remote_destroy(void *_data)
static void on_core_error(void *_data, uint32_t id, int seq, int res, const char *message)
{
struct remote_data *rd = _data;
struct data *data = rd->data;
pw_log_error("remote %p: error id:%u seq:%d res:%d (%s): %s", rd,
id, seq, res, spa_strerror(res), message);
if (id == 0) {
pw_main_loop_quit(data->loop);
}
}
static const struct pw_core_proxy_events remote_core_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.info = on_core_info,
.done = on_core_done,
.error = on_core_error,
};
static void on_core_destroy(void *_data)
{
struct remote_data *rd = _data;
struct data *data = rd->data;
@ -385,78 +405,49 @@ static void on_remote_destroy(void *_data)
free(rd->name);
}
static const struct pw_core_proxy_events remote_core_events = {
PW_VERSION_CORE_EVENTS,
.info = on_core_info,
.done = on_core_done,
static const struct pw_proxy_events core_proxy_events = {
PW_VERSION_PROXY_EVENTS,
.destroy = on_core_destroy,
};
static void on_state_changed(void *_data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
{
struct remote_data *rd = _data;
struct data *data = rd->data;
switch (state) {
case PW_REMOTE_STATE_ERROR:
fprintf(stderr, "remote %d error: %s\n", rd->id, error);
pw_main_loop_quit(data->loop);
break;
case PW_REMOTE_STATE_CONNECTED:
fprintf(stdout, "remote %d state: \"%s\"\n", rd->id, pw_remote_state_as_string(state));
rd->core_proxy = pw_remote_get_core_proxy(rd->remote);
pw_core_proxy_add_listener(rd->core_proxy,
&rd->core_listener,
&remote_core_events, rd);
rd->registry_proxy = pw_core_proxy_get_registry(rd->core_proxy,
PW_VERSION_REGISTRY_PROXY, 0);
pw_registry_proxy_add_listener(rd->registry_proxy,
&rd->registry_listener,
&registry_events, rd);
rd->prompt_pending = pw_core_proxy_sync(rd->core_proxy, 0, 0);
break;
default:
fprintf(stdout, "remote %d state: \"%s\"\n", rd->id, pw_remote_state_as_string(state));
break;
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.destroy = on_remote_destroy,
.state_changed = on_state_changed,
};
static bool do_connect(struct data *data, const char *cmd, char *args, char **error)
{
char *a[1];
int n;
struct pw_remote *remote;
struct pw_properties *props = NULL;
struct pw_core_proxy *core_proxy;
struct remote_data *rd;
n = pw_split_ip(args, WHITESPACE, 1, a);
if (n == 1) {
props = pw_properties_new(PW_KEY_REMOTE_NAME, a[0], NULL);
}
remote = pw_remote_new(data->core, props, sizeof(struct remote_data));
core_proxy = pw_core_connect(data->core, props, sizeof(struct remote_data));
if (core_proxy == NULL)
return false;
rd = pw_remote_get_user_data(remote);
rd->remote = remote;
rd = pw_proxy_get_user_data((struct pw_proxy*)core_proxy);
rd->core_proxy = core_proxy;
rd->data = data;
pw_map_init(&rd->globals, 64, 16);
rd->id = pw_map_insert_new(&data->vars, rd);
spa_list_append(&data->remotes, &rd->link);
fprintf(stdout, "%d = @remote:%p\n", rd->id, remote);
fprintf(stdout, "%d = @remote:%p\n", rd->id, rd->core_proxy);
data->current = rd;
pw_remote_add_listener(remote, &rd->remote_listener, &remote_events, rd);
if (pw_remote_connect(remote) < 0)
return false;
pw_core_proxy_add_listener(rd->core_proxy,
&rd->core_listener,
&remote_core_events, rd);
pw_proxy_add_listener((struct pw_proxy*)rd->core_proxy,
&rd->core_proxy_listener,
&core_proxy_events, rd);
rd->registry_proxy = pw_core_proxy_get_registry(rd->core_proxy,
PW_VERSION_REGISTRY_PROXY, 0);
pw_registry_proxy_add_listener(rd->registry_proxy,
&rd->registry_listener,
&registry_events, rd);
rd->prompt_pending = pw_core_proxy_sync(rd->core_proxy, 0, 0);
return true;
}
@ -476,8 +467,7 @@ static bool do_disconnect(struct data *data, const char *cmd, char *args, char *
goto no_remote;
}
pw_remote_disconnect(rd->remote);
pw_remote_destroy(rd->remote);
pw_core_proxy_disconnect(rd->core_proxy);
if (data->current == NULL) {
if (spa_list_is_empty(&data->remotes)) {
@ -498,7 +488,7 @@ static bool do_list_remotes(struct data *data, const char *cmd, char *args, char
struct remote_data *rd;
spa_list_for_each(rd, &data->remotes, link)
fprintf(stdout, "\t%d = @remote:%p '%s'\n", rd->id, rd->remote, rd->name);
fprintf(stdout, "\t%d = @remote:%p '%s'\n", rd->id, rd->core_proxy, rd->name);
return true;
}
@ -1428,7 +1418,7 @@ static bool do_export_node(struct data *data, const char *cmd, char *args, char
return false;
}
node = pw_global_get_object(global);
proxy = pw_remote_export(rd->remote, PW_TYPE_INTERFACE_Node, NULL, node, 0);
proxy = pw_core_proxy_export(rd->core_proxy, PW_TYPE_INTERFACE_Node, NULL, node, 0);
id = pw_map_insert_new(&data->vars, proxy);
fprintf(stdout, "%d = @proxy:%d\n", id, pw_proxy_get_id((struct pw_proxy*)proxy));

View file

@ -26,6 +26,7 @@
#include <signal.h>
#include <getopt.h>
#include <spa/utils/result.h>
#include <spa/debug/pod.h>
#include <spa/debug/format.h>
#include <spa/debug/types.h>
@ -48,9 +49,6 @@ struct data {
struct pw_main_loop *loop;
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;
@ -711,42 +709,22 @@ static void on_core_done(void *data, uint32_t id, int seq)
pw_main_loop_quit(d->loop);
}
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_EVENTS,
.done = on_core_done,
};
static void on_state_changed(void *_data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
static void on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
{
struct data *data = _data;
struct data *d = data;
switch (state) {
case PW_REMOTE_STATE_ERROR:
printf("remote error: %s\n", error);
pw_main_loop_quit(data->loop);
break;
pw_log_error("error id:%u seq:%d res:%d (%s): %s",
id, seq, res, spa_strerror(res), message);
case PW_REMOTE_STATE_CONNECTED:
data->core_proxy = pw_remote_get_core_proxy(data->remote);
pw_core_proxy_add_listener(data->core_proxy,
&data->core_listener,
&core_events, data);
data->registry_proxy = pw_core_proxy_get_registry(data->core_proxy,
PW_VERSION_REGISTRY_PROXY, 0);
pw_registry_proxy_add_listener(data->registry_proxy,
&data->registry_listener,
&registry_events, data);
break;
default:
break;
if (id == 0) {
pw_main_loop_quit(d->loop);
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.done = on_core_done,
.error = on_core_error,
};
static void do_quit(void *data, int signal_number)
@ -843,12 +821,8 @@ int main(int argc, char *argv[])
if (remote_name)
props = pw_properties_new(PW_KEY_REMOTE_NAME, remote_name, NULL);
data.remote = pw_remote_new(data.core, props, 0);
if (data.remote == NULL)
return -1;
pw_remote_add_listener(data.remote, &data.remote_listener, &remote_events, &data);
if (pw_remote_connect(data.remote) < 0)
data.core_proxy = pw_core_connect(data.core, props, 0);
if (data.core_proxy == NULL)
return -1;
data.dot_str = dot_str_new();
@ -857,12 +831,20 @@ int main(int argc, char *argv[])
spa_list_init(&data.globals);
pw_core_proxy_add_listener(data.core_proxy,
&data.core_listener,
&core_events, &data);
data.registry_proxy = pw_core_proxy_get_registry(data.core_proxy,
PW_VERSION_REGISTRY_PROXY, 0);
pw_registry_proxy_add_listener(data.registry_proxy,
&data.registry_listener,
&registry_events, &data);
pw_main_loop_run(data.loop);
draw_graph(&data, dot_path);
dot_str_clear(&data.dot_str);
pw_remote_destroy(data.remote);
pw_core_destroy(data.core);
pw_main_loop_destroy(data.loop);

View file

@ -25,13 +25,13 @@
#include <stdio.h>
#include <signal.h>
#include <spa/utils/result.h>
#include <spa/debug/pod.h>
#include <spa/debug/format.h>
#include <spa/debug/types.h>
#include <pipewire/interfaces.h>
#include <pipewire/type.h>
#include <pipewire/remote.h>
#include <pipewire/main-loop.h>
#include <pipewire/pipewire.h>
@ -50,9 +50,6 @@ struct data {
struct pw_main_loop *loop;
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_hook core_listener;
@ -670,46 +667,22 @@ static const struct pw_registry_proxy_events registry_events = {
.global_remove = registry_event_global_remove,
};
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_EVENTS,
.info = on_core_info,
.done = on_core_done,
};
static void on_state_changed(void *_data, enum pw_remote_state old,
enum pw_remote_state state, const char *error)
static void on_core_error(void *_data, uint32_t id, int seq, int res, const char *message)
{
struct data *data = _data;
switch (state) {
case PW_REMOTE_STATE_ERROR:
printf("remote error: %s\n", error);
pw_log_error("error id:%u seq:%d res:%d (%s): %s",
id, seq, res, spa_strerror(res), message);
if (id == 0) {
pw_main_loop_quit(data->loop);
break;
case PW_REMOTE_STATE_CONNECTED:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
data->core_proxy = pw_remote_get_core_proxy(data->remote);
pw_core_proxy_add_listener(data->core_proxy,
&data->core_listener,
&core_events, data);
data->registry_proxy = pw_core_proxy_get_registry(data->core_proxy,
PW_VERSION_REGISTRY_PROXY, 0);
pw_registry_proxy_add_listener(data->registry_proxy,
&data->registry_listener,
&registry_events, data);
break;
default:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
break;
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_PROXY_EVENTS,
.info = on_core_info,
.done = on_core_done,
.error = on_core_error,
};
static void do_quit(void *data, int signal_number)
@ -741,19 +714,23 @@ int main(int argc, char *argv[])
if (argc > 1)
props = pw_properties_new(PW_KEY_REMOTE_NAME, argv[1], NULL);
data.remote = pw_remote_new(data.core, props, 0);
if (data.remote == NULL)
return -1;
pw_remote_add_listener(data.remote, &data.remote_listener, &remote_events, &data);
if (pw_remote_connect(data.remote) < 0)
return -1;
spa_list_init(&data.pending_list);
data.core_proxy = pw_core_connect(data.core, props, 0);
if (data.core_proxy == NULL)
return -1;
pw_core_proxy_add_listener(data.core_proxy,
&data.core_listener,
&core_events, &data);
data.registry_proxy = pw_core_proxy_get_registry(data.core_proxy,
PW_VERSION_REGISTRY_PROXY, 0);
pw_registry_proxy_add_listener(data.registry_proxy,
&data.registry_listener,
&registry_events, &data);
pw_main_loop_run(data.loop);
pw_remote_destroy(data.remote);
pw_core_destroy(data.core);
pw_main_loop_destroy(data.loop);