API cleanups

Fix docs
Add some more versions to interfaces
Make types for the various proxy object + inline methods that does type
checking and create proxys etc.
Set owner client of client-nodes in the properties
Pass type to bind to in create-node
Don't place global id in the info structs
Improve registration of marshal functions
Pass more types around as ids
This commit is contained in:
Wim Taymans 2017-07-13 15:21:52 +02:00
parent 465f12241e
commit 1acba78234
45 changed files with 963 additions and 764 deletions

View file

@ -780,7 +780,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = "@top_srcdir@/src/" INPUT = "@top_srcdir@/src/pipewire"
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses

View file

@ -43,8 +43,6 @@ enum spa_clock_state {
#include <spa/plugin.h> #include <spa/plugin.h>
#include <spa/props.h> #include <spa/props.h>
#define SPA_VERSION_CLOCK 0
/** /**
* spa_clock: * spa_clock:
* *
@ -53,6 +51,7 @@ enum spa_clock_state {
struct spa_clock { struct spa_clock {
/* the version of this clock. This can be used to expand this /* the version of this clock. This can be used to expand this
* structure in the future */ * structure in the future */
#define SPA_VERSION_CLOCK 0
uint32_t version; uint32_t version;
const struct spa_dict *info; const struct spa_dict *info;

View file

@ -70,6 +70,7 @@ enum spa_result {
SPA_RESULT_SKIPPED = -34, SPA_RESULT_SKIPPED = -34,
SPA_RESULT_OUT_OF_BUFFERS = -35, SPA_RESULT_OUT_OF_BUFFERS = -35,
SPA_RESULT_INCOMPATIBLE_PROPS = -36, SPA_RESULT_INCOMPATIBLE_PROPS = -36,
SPA_RESULT_INCOMPATIBLE_VERSION = -37,
}; };
#define SPA_ASYNC_BIT (1 << 30) #define SPA_ASYNC_BIT (1 << 30)

View file

@ -42,8 +42,6 @@ enum spa_log_level {
SPA_LOG_LEVEL_TRACE, SPA_LOG_LEVEL_TRACE,
}; };
#define SPA_VERSION_LOG 0
/** /**
* struct spa_log: * struct spa_log:
* *
@ -52,6 +50,7 @@ enum spa_log_level {
struct spa_log { struct spa_log {
/* the version of this log. This can be used to expand this /* the version of this log. This can be used to expand this
* structure in the future */ * structure in the future */
#define SPA_VERSION_LOG 0
uint32_t version; uint32_t version;
/** /**
* struct spa_log::info * struct spa_log::info

View file

@ -66,8 +66,6 @@ typedef int (*spa_invoke_func_t) (struct spa_loop *loop,
void *data, void *data,
void *user_data); void *user_data);
#define SPA_VERSION_LOOP 0
/** /**
* spa_loop: * spa_loop:
* *
@ -76,6 +74,7 @@ typedef int (*spa_invoke_func_t) (struct spa_loop *loop,
struct spa_loop { struct spa_loop {
/* the version of this structure. This can be used to expand this /* the version of this structure. This can be used to expand this
* structure in the future */ * structure in the future */
#define SPA_VERSION_LOOP 0
uint32_t version; uint32_t version;
int (*add_source) (struct spa_loop *loop, int (*add_source) (struct spa_loop *loop,
@ -160,8 +159,6 @@ typedef void (*spa_source_signal_func_t) (struct spa_loop_utils *utils,
struct spa_source *source, struct spa_source *source,
int signal_number, void *data); int signal_number, void *data);
#define SPA_VERSION_LOOP_UTILS 0
/** /**
* struct spa_loop_utils: * struct spa_loop_utils:
* *
@ -170,6 +167,7 @@ typedef void (*spa_source_signal_func_t) (struct spa_loop_utils *utils,
struct spa_loop_utils { struct spa_loop_utils {
/* the version of this structure. This can be used to expand this /* the version of this structure. This can be used to expand this
* structure in the future */ * structure in the future */
#define SPA_VERSION_LOOP_UTILS 0
uint32_t version; uint32_t version;
struct spa_source *(*add_io) (struct spa_loop_utils *utils, struct spa_source *(*add_io) (struct spa_loop_utils *utils,

View file

@ -104,19 +104,17 @@ enum spa_monitor_item_state {
SPA_MONITOR_ITEM_STATE_UNAVAILABLE, SPA_MONITOR_ITEM_STATE_UNAVAILABLE,
}; };
#define SPA_VERSION_MONITOR_CALLBACKS 0
/** /**
* spa_monitor_callbacks: * spa_monitor_callbacks:
*/ */
struct spa_monitor_callbacks { struct spa_monitor_callbacks {
uint32_t version; /**< version of the structure */ /** version of the structure */
#define SPA_VERSION_MONITOR_CALLBACKS 0
uint32_t version;
void (*event) (struct spa_monitor *monitor, struct spa_event *event, void *user_data); void (*event) (struct spa_monitor *monitor, struct spa_event *event, void *user_data);
}; };
#define SPA_VERSION_MONITOR 0
/** /**
* spa_monitor: * spa_monitor:
* *
@ -125,6 +123,7 @@ struct spa_monitor_callbacks {
struct spa_monitor { struct spa_monitor {
/* the version of this monitor. This can be used to expand this /* the version of this monitor. This can be used to expand this
* structure in the future */ * structure in the future */
#define SPA_VERSION_MONITOR 0
uint32_t version; uint32_t version;
/** /**

View file

@ -78,9 +78,9 @@ struct spa_port_info {
const struct spa_dict *props; /**< extra port properties */ const struct spa_dict *props; /**< extra port properties */
}; };
#define SPA_VERSION_NODE_CALLBACKS 0
struct spa_node_callbacks { struct spa_node_callbacks {
#define SPA_VERSION_NODE_CALLBACKS 0
uint32_t version; /**< version of this structure */ uint32_t version; /**< version of this structure */
/** Emited when an async operation completed */ /** Emited when an async operation completed */
@ -134,8 +134,6 @@ struct spa_node_callbacks {
}; };
#define SPA_VERSION_NODE 0
/** /**
* struct spa_node: * struct spa_node:
* *
@ -147,6 +145,7 @@ struct spa_node_callbacks {
struct spa_node { struct spa_node {
/* the version of this node. This can be used to expand this /* the version of this node. This can be used to expand this
* structure in the future */ * structure in the future */
#define SPA_VERSION_NODE 0
uint32_t version; uint32_t version;
/** /**
* spa_node::info * spa_node::info

View file

@ -30,10 +30,9 @@ extern "C" {
#define SPA_TYPE__Handle SPA_TYPE_INTERFACE_BASE "Handle" #define SPA_TYPE__Handle SPA_TYPE_INTERFACE_BASE "Handle"
#define SPA_TYPE__HandleFactory SPA_TYPE_INTERFACE_BASE "HandleFactory" #define SPA_TYPE__HandleFactory SPA_TYPE_INTERFACE_BASE "HandleFactory"
#define SPA_VERSION_HANDLE 0
struct spa_handle { struct spa_handle {
/** Version of this struct */ /** Version of this struct */
#define SPA_VERSION_HANDLE 0
uint32_t version; uint32_t version;
/* user_data that can be set by the application */ /* user_data that can be set by the application */
@ -103,10 +102,9 @@ static inline void *spa_support_find(const struct spa_support *support,
#define SPA_SUPPORT_INIT(type,data) (struct spa_support) { (type), (data) } #define SPA_SUPPORT_INIT(type,data) (struct spa_support) { (type), (data) }
#define SPA_VERSION_HANDLE_FACTORY 0
struct spa_handle_factory { struct spa_handle_factory {
/** The version of this structure */ /** The version of this structure */
#define SPA_VERSION_HANDLE_FACTORY 0
uint32_t version; uint32_t version;
/** /**
* spa_handle_factory::name * spa_handle_factory::name

View file

@ -30,8 +30,6 @@ extern "C" {
#define SPA_TYPE__TypeMap SPA_TYPE_INTERFACE_BASE "TypeMap" #define SPA_TYPE__TypeMap SPA_TYPE_INTERFACE_BASE "TypeMap"
#define SPA_VERSION_TYPE_MAP 0
/** /**
* spa_type_map: * spa_type_map:
* *
@ -40,6 +38,7 @@ extern "C" {
struct spa_type_map { struct spa_type_map {
/* the version of this structure. This can be used to expand this /* the version of this structure. This can be used to expand this
* structure in the future */ * structure in the future */
#define SPA_VERSION_TYPE_MAP 0
uint32_t version; uint32_t version;
/** /**
* spa_type_map::info * spa_type_map::info

View file

@ -30,8 +30,13 @@ extern "C" {
#include <spa/param-alloc.h> #include <spa/param-alloc.h>
#include <spa/node.h> #include <spa/node.h>
#define PW_TYPE__ClientNode PW_TYPE_NODE_BASE "Client" #include <pipewire/proxy.h>
#define PW_TYPE_CLIENT_NODE_BASE PW_TYPE__ClientNode ":"
struct pw_client_node_proxy { struct pw_proxy proxy; };
#define PW_TYPE_INTERFACE__ClientNode PW_TYPE_INTERFACE_BASE "ClientNode"
#define PW_VERSION_CLIENT_NODE 0
/** information about a buffer */ /** information about a buffer */
struct pw_client_node_buffer { struct pw_client_node_buffer {
@ -41,8 +46,6 @@ struct pw_client_node_buffer {
struct spa_buffer *buffer; /**< buffer describing metadata and buffer memory */ struct spa_buffer *buffer; /**< buffer describing metadata and buffer memory */
}; };
#define PW_VERSION_CLIENT_NODE 0
#define PW_CLIENT_NODE_METHOD_DONE 0 #define PW_CLIENT_NODE_METHOD_DONE 0
#define PW_CLIENT_NODE_METHOD_UPDATE 1 #define PW_CLIENT_NODE_METHOD_UPDATE 1
#define PW_CLIENT_NODE_METHOD_PORT_UPDATE 2 #define PW_CLIENT_NODE_METHOD_PORT_UPDATE 2
@ -52,6 +55,9 @@ struct pw_client_node_buffer {
/** \ref pw_client_node methods */ /** \ref pw_client_node methods */
struct pw_client_node_methods { struct pw_client_node_methods {
#define PW_VERSION_CLIENT_NODE_METHODS 0
uint32_t version;
/** Complete an async operation */ /** Complete an async operation */
void (*done) (void *object, int seq, int res); void (*done) (void *object, int seq, int res);
@ -113,11 +119,60 @@ struct pw_client_node_methods {
void (*destroy) (void *object); void (*destroy) (void *object);
}; };
#define pw_client_node_do_done(p,...) pw_proxy_do(p,struct pw_client_node_methods,done,__VA_ARGS__) static inline void
#define pw_client_node_do_update(p,...) pw_proxy_do(p,struct pw_client_node_methods,update,__VA_ARGS__) pw_client_node_proxy_done(struct pw_client_node_proxy *p, int seq, int res)
#define pw_client_node_do_port_update(p,...) pw_proxy_do(p,struct pw_client_node_methods,port_update,__VA_ARGS__) {
#define pw_client_node_do_event(p,...) pw_proxy_do(p,struct pw_client_node_methods,event,__VA_ARGS__) pw_proxy_do(&p->proxy, struct pw_client_node_methods, done, seq, res);
#define pw_client_node_do_destroy(p) pw_proxy_do_na(p,struct pw_client_node_methods,destroy) }
static inline void
pw_client_node_proxy_update(struct pw_client_node_proxy *p,
uint32_t change_mask,
uint32_t max_input_ports,
uint32_t max_output_ports,
const struct spa_props *props)
{
pw_proxy_do(&p->proxy, struct pw_client_node_methods, update, change_mask,
max_input_ports,
max_output_ports,
props);
}
static inline void
pw_client_node_proxy_port_update(struct pw_client_node_proxy *p,
enum spa_direction direction,
uint32_t port_id,
uint32_t change_mask,
uint32_t n_possible_formats,
const struct spa_format **possible_formats,
const struct spa_format *format,
uint32_t n_params,
const struct spa_param **params,
const struct spa_port_info *info)
{
pw_proxy_do(&p->proxy, struct pw_client_node_methods, port_update, direction,
port_id,
change_mask,
n_possible_formats,
possible_formats,
format,
n_params,
params,
info);
}
static inline void
pw_client_node_proxy_event(struct pw_client_node_proxy *p, struct spa_event *event)
{
pw_proxy_do(&p->proxy, struct pw_client_node_methods, event, event);
}
static inline void
pw_client_node_proxy_destroy(struct pw_client_node_proxy *p)
{
pw_proxy_do_na(&p->proxy, struct pw_client_node_methods, destroy);
}
#define PW_CLIENT_NODE_EVENT_TRANSPORT 0 #define PW_CLIENT_NODE_EVENT_TRANSPORT 0
#define PW_CLIENT_NODE_EVENT_SET_PROPS 1 #define PW_CLIENT_NODE_EVENT_SET_PROPS 1
@ -134,6 +189,8 @@ struct pw_client_node_methods {
/** \ref pw_client_node events */ /** \ref pw_client_node events */
struct pw_client_node_events { struct pw_client_node_events {
#define PW_VERSION_CLIENT_NODE_EVENTS 0
uint32_t version;
/** /**
* Notify of a new transport area * Notify of a new transport area
* *
@ -280,17 +337,24 @@ struct pw_client_node_events {
}; };
#define pw_client_node_notify_transport(r,...) pw_resource_notify(r,struct pw_client_node_events,transport,__VA_ARGS__) static inline void
#define pw_client_node_notify_set_props(r,...) pw_resource_notify(r,struct pw_client_node_events,props,__VA_ARGS__) pw_client_node_proxy_add_listener(struct pw_client_node_proxy *p,
#define pw_client_node_notify_event(r,...) pw_resource_notify(r,struct pw_client_node_events,event,__VA_ARGS__) void *object, const struct pw_client_node_events *events)
#define pw_client_node_notify_add_port(r,...) pw_resource_notify(r,struct pw_client_node_events,add_port,__VA_ARGS__) {
#define pw_client_node_notify_remove_port(r,...) pw_resource_notify(r,struct pw_client_node_events,remove_port,__VA_ARGS__) pw_proxy_add_listener(&p->proxy, object, events);
#define pw_client_node_notify_set_format(r,...) pw_resource_notify(r,struct pw_client_node_events,set_format,__VA_ARGS__) }
#define pw_client_node_notify_set_param(r,...) pw_resource_notify(r,struct pw_client_node_events,set_param,__VA_ARGS__)
#define pw_client_node_notify_add_mem(r,...) pw_resource_notify(r,struct pw_client_node_events,add_mem,__VA_ARGS__) #define pw_client_node_resource_transport(r,...) pw_resource_notify(r,struct pw_client_node_events,transport,__VA_ARGS__)
#define pw_client_node_notify_use_buffers(r,...) pw_resource_notify(r,struct pw_client_node_events,use_buffers,__VA_ARGS__) #define pw_client_node_resource_set_props(r,...) pw_resource_notify(r,struct pw_client_node_events,props,__VA_ARGS__)
#define pw_client_node_notify_node_command(r,...) pw_resource_notify(r,struct pw_client_node_events,node_command,__VA_ARGS__) #define pw_client_node_resource_event(r,...) pw_resource_notify(r,struct pw_client_node_events,event,__VA_ARGS__)
#define pw_client_node_notify_port_command(r,...) pw_resource_notify(r,struct pw_client_node_events,port_command,__VA_ARGS__) #define pw_client_node_resource_add_port(r,...) pw_resource_notify(r,struct pw_client_node_events,add_port,__VA_ARGS__)
#define pw_client_node_resource_remove_port(r,...) pw_resource_notify(r,struct pw_client_node_events,remove_port,__VA_ARGS__)
#define pw_client_node_resource_set_format(r,...) pw_resource_notify(r,struct pw_client_node_events,set_format,__VA_ARGS__)
#define pw_client_node_resource_set_param(r,...) pw_resource_notify(r,struct pw_client_node_events,set_param,__VA_ARGS__)
#define pw_client_node_resource_add_mem(r,...) pw_resource_notify(r,struct pw_client_node_events,add_mem,__VA_ARGS__)
#define pw_client_node_resource_use_buffers(r,...) pw_resource_notify(r,struct pw_client_node_events,use_buffers,__VA_ARGS__)
#define pw_client_node_resource_node_command(r,...) pw_resource_notify(r,struct pw_client_node_events,node_command,__VA_ARGS__)
#define pw_client_node_resource_port_command(r,...) pw_resource_notify(r,struct pw_client_node_events,port_command,__VA_ARGS__)
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View file

@ -193,7 +193,7 @@ enum
}; };
static GstDevice * static GstDevice *
new_node (GstPipeWireDeviceProvider *self, const struct pw_node_info *info) new_node (GstPipeWireDeviceProvider *self, const struct pw_node_info *info, uint32_t id)
{ {
GstCaps *caps = NULL; GstCaps *caps = NULL;
GstStructure *props; GstStructure *props;
@ -234,7 +234,7 @@ new_node (GstPipeWireDeviceProvider *self, const struct pw_node_info *info)
if (klass == NULL) if (klass == NULL)
klass = "unknown/unknown"; klass = "unknown/unknown";
return gst_pipewire_device_new (info->id, return gst_pipewire_device_new (id,
info->name, info->name,
caps, caps,
klass, klass,
@ -295,18 +295,24 @@ on_sync_reply (struct pw_listener *listener, struct pw_remote *remote, uint32_t
{ {
GstPipeWireDeviceProvider *self = SPA_CONTAINER_OF (listener, GstPipeWireDeviceProvider, on_sync_reply); GstPipeWireDeviceProvider *self = SPA_CONTAINER_OF (listener, GstPipeWireDeviceProvider, on_sync_reply);
if (seq == 1) if (seq == 1)
pw_core_do_sync(self->registry->remote->core_proxy, 2); pw_core_proxy_sync(self->remote->core_proxy, 2);
else if (seq == 2) else if (seq == 2)
self->end = true; self->end = true;
} }
struct node_data {
GstPipeWireDeviceProvider *self;
uint32_t id;
};
static void node_event_info(void *object, struct pw_node_info *info) static void node_event_info(void *object, struct pw_node_info *info)
{ {
struct pw_proxy *proxy = object; struct pw_proxy *proxy = object;
GstPipeWireDeviceProvider *self = proxy->object; struct node_data *node_data = proxy->user_data;
GstPipeWireDeviceProvider *self = node_data->self;
GstDevice *dev; GstDevice *dev;
dev = new_node (self, info); dev = new_node (self, info, node_data->id);
if (dev) { if (dev) {
if(self->list_only) if(self->list_only)
*self->devices = g_list_prepend (*self->devices, gst_object_ref_sink (dev)); *self->devices = g_list_prepend (*self->devices, gst_object_ref_sink (dev));
@ -316,26 +322,32 @@ static void node_event_info(void *object, struct pw_node_info *info)
} }
static const struct pw_node_events node_events = { static const struct pw_node_events node_events = {
PW_VERSION_NODE_EVENTS,
&node_event_info &node_event_info
}; };
static void registry_event_global(void *object, uint32_t id, uint32_t type, uint32_t version) static void registry_event_global(void *object, uint32_t id, uint32_t type, uint32_t version)
{ {
struct pw_proxy *registry = object; struct pw_registry_proxy *registry = object;
GstPipeWireDeviceProvider *self = registry->object; GstPipeWireDeviceProvider *self = registry->proxy.user_data;
struct pw_remote *remote = registry->remote; struct pw_remote *remote = self->remote;
struct pw_core *core = remote->core; struct pw_core *core = remote->core;
struct pw_proxy *proxy = NULL; struct pw_node_proxy *node;
struct node_data *data;
if (type != core->type.node) if (type != core->type.node)
return; return;
proxy = pw_proxy_new(remote, SPA_ID_INVALID, core->type.node, 0); node = pw_registry_proxy_bind(registry, id, core->type.node, PW_VERSION_NODE,
if (proxy == NULL) sizeof(struct node_data), NULL);
if (node == NULL)
goto no_mem; goto no_mem;
pw_proxy_set_implementation(proxy, self, PW_VERSION_NODE, &node_events, NULL); data = node->proxy.user_data;
pw_registry_do_bind(registry, id, version, proxy->id); data->id = id;
data->self = self;
pw_node_proxy_add_listener(node, node, &node_events);
return; return;
no_mem: no_mem:
@ -345,8 +357,8 @@ no_mem:
static void registry_event_global_remove(void *object, uint32_t id) static void registry_event_global_remove(void *object, uint32_t id)
{ {
struct pw_proxy *registry = object; struct pw_registry_proxy *registry = object;
GstPipeWireDeviceProvider *self = registry->object; GstPipeWireDeviceProvider *self = registry->proxy.user_data;
GstDeviceProvider *provider = GST_DEVICE_PROVIDER (self); GstDeviceProvider *provider = GST_DEVICE_PROVIDER (self);
GstPipeWireDevice *dev; GstPipeWireDevice *dev;
@ -358,6 +370,7 @@ static void registry_event_global_remove(void *object, uint32_t id)
} }
static const struct pw_registry_events registry_events = { static const struct pw_registry_events registry_events = {
PW_VERSION_REGISTRY_EVENTS,
registry_event_global, registry_event_global,
registry_event_global_remove, registry_event_global_remove,
}; };
@ -369,7 +382,7 @@ gst_pipewire_device_provider_probe (GstDeviceProvider * provider)
struct pw_loop *l = NULL; struct pw_loop *l = NULL;
struct pw_core *c = NULL; struct pw_core *c = NULL;
struct pw_remote *r = NULL; struct pw_remote *r = NULL;
struct pw_proxy *reg = NULL; struct pw_registry_proxy *reg = NULL;
GST_DEBUG_OBJECT (self, "starting probe"); GST_DEBUG_OBJECT (self, "starting probe");
@ -410,10 +423,10 @@ gst_pipewire_device_provider_probe (GstDeviceProvider * provider)
self->list_only = TRUE; self->list_only = TRUE;
self->devices = NULL; self->devices = NULL;
reg = pw_proxy_new(r, SPA_ID_INVALID, c->type.registry, 0); reg = pw_core_proxy_get_registry(r->core_proxy, PW_VERSION_REGISTRY, 0, NULL);
pw_proxy_set_implementation(reg, self, PW_VERSION_REGISTRY, &registry_events, NULL); reg->proxy.user_data = self;
pw_core_do_get_registry(r->core_proxy, PW_VERSION_REGISTRY, reg->id); pw_registry_proxy_add_listener(reg, reg, &registry_events);
pw_core_do_sync(r->core_proxy, 1); pw_core_proxy_sync(r->core_proxy, 1);
for (;;) { for (;;) {
if (r->state <= 0) if (r->state <= 0)
@ -515,10 +528,10 @@ gst_pipewire_device_provider_start (GstDeviceProvider * provider)
GST_DEBUG_OBJECT (self, "connected"); GST_DEBUG_OBJECT (self, "connected");
get_core_info (self->remote, self); get_core_info (self->remote, self);
self->registry = pw_proxy_new(self->remote, SPA_ID_INVALID, self->core->type.registry, 0); self->registry = pw_core_proxy_get_registry(self->remote->core_proxy, PW_VERSION_REGISTRY, 0, NULL);
pw_proxy_set_implementation(self->registry, self, PW_VERSION_REGISTRY, &registry_events, NULL); self->registry->proxy.user_data = self;
pw_core_do_get_registry(self->remote->core_proxy, PW_VERSION_REGISTRY, self->registry->id); pw_registry_proxy_add_listener(self->registry, self->registry, &registry_events);
pw_core_do_sync(self->remote->core_proxy, 1); pw_core_proxy_sync(self->remote->core_proxy, 1);
pw_thread_loop_unlock (self->main_loop); pw_thread_loop_unlock (self->main_loop);

View file

@ -86,7 +86,7 @@ struct _GstPipeWireDeviceProvider {
struct pw_core *core; struct pw_core *core;
struct pw_remote *remote; struct pw_remote *remote;
struct pw_proxy *registry; struct pw_registry_proxy *registry;
gboolean end; gboolean end;
gboolean list_only; gboolean list_only;
GList **devices; GList **devices;

View file

@ -554,9 +554,6 @@ gst_pipewire_src_stream_start (GstPipeWireSrc *pwsrc)
} }
parse_stream_properties (pwsrc, pwsrc->stream->properties); parse_stream_properties (pwsrc, pwsrc->stream->properties);
pw_thread_loop_unlock (pwsrc->main_loop);
pw_thread_loop_lock (pwsrc->main_loop);
GST_DEBUG_OBJECT (pwsrc, "signal started"); GST_DEBUG_OBJECT (pwsrc, "signal started");
pwsrc->started = TRUE; pwsrc->started = TRUE;
pw_thread_loop_signal (pwsrc->main_loop, FALSE); pw_thread_loop_signal (pwsrc->main_loop, FALSE);

View file

@ -101,11 +101,11 @@ on_link_state_changed(struct pw_listener *listener,
link->error); link->error);
spa_list_for_each(resource, &link->resource_list, link) { spa_list_for_each(resource, &link->resource_list, link) {
pw_core_notify_error(resource->client->core_resource, pw_core_resource_error(resource->client->core_resource,
resource->id, SPA_RESULT_ERROR, link->error); resource->id, SPA_RESULT_ERROR, link->error);
} }
if (info->node->owner) { if (info->node->owner) {
pw_core_notify_error(info->node->owner->client->core_resource, pw_core_resource_error(info->node->owner->client->core_resource,
info->node->owner->id, info->node->owner->id,
SPA_RESULT_ERROR, link->error); SPA_RESULT_ERROR, link->error);
} }
@ -194,7 +194,7 @@ static void try_link_port(struct pw_node *node, struct pw_port *port, struct nod
error: error:
pw_log_error("module %p: can't link node '%s'", impl, error); pw_log_error("module %p: can't link node '%s'", impl, error);
if (info->node->owner && info->node->owner->client->core_resource) { if (info->node->owner && info->node->owner->client->core_resource) {
pw_core_notify_error(info->node->owner->client->core_resource, pw_core_resource_error(info->node->owner->client->core_resource,
info->node->owner->id, SPA_RESULT_ERROR, error); info->node->owner->id, SPA_RESULT_ERROR, error);
} }
free(error); free(error);

View file

@ -44,6 +44,14 @@ static struct pw_node *create_node(struct pw_node_factory *factory,
{ {
struct pw_client_node *node; struct pw_client_node *node;
if (properties == NULL)
properties = pw_properties_new(NULL, NULL);
if (properties == NULL)
goto no_mem;
pw_properties_setf(properties,
"pipewire.owner.client", "%d", resource->client->global->id);
node = pw_client_node_new(resource, name, properties); node = pw_client_node_new(resource, name, properties);
if (node == NULL) if (node == NULL)
goto no_mem; goto no_mem;
@ -52,8 +60,10 @@ static struct pw_node *create_node(struct pw_node_factory *factory,
no_mem: no_mem:
pw_log_error("can't create node"); pw_log_error("can't create node");
pw_core_notify_error(resource->client->core_resource, pw_core_resource_error(resource->client->core_resource,
resource->client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory"); resource->client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory");
if (properties)
pw_properties_free(properties);
return NULL; return NULL;
} }
@ -68,7 +78,7 @@ static struct impl *module_new(struct pw_core *core, struct pw_properties *prope
impl->this.core = core; impl->this.core = core;
impl->this.name = "client-node"; impl->this.name = "client-node";
impl->this.type = spa_type_map_get_id(core->type.map, PW_TYPE__ClientNode);
pw_signal_init(&impl->this.destroy_signal); pw_signal_init(&impl->this.destroy_signal);
impl->this.create_node = create_node; impl->this.create_node = create_node;
@ -76,7 +86,8 @@ static struct impl *module_new(struct pw_core *core, struct pw_properties *prope
spa_list_insert(core->node_factory_list.prev, &impl->this.link); spa_list_insert(core->node_factory_list.prev, &impl->this.link);
pw_core_add_global(core, NULL, core->type.node_factory, 0, impl, NULL, &impl->this.global); pw_core_add_global(core, NULL, core->type.node_factory, 0,
NULL, impl, &impl->this.global);
return impl; return impl;
} }

View file

@ -114,8 +114,6 @@ struct proxy {
struct impl { struct impl {
struct pw_client_node this; struct pw_client_node this;
uint32_t type_client_node;
struct pw_core *core; struct pw_core *core;
struct proxy proxy; struct proxy proxy;
@ -194,10 +192,10 @@ static int spa_proxy_node_send_command(struct spa_node *node, struct spa_command
core = this->impl->core; core = this->impl->core;
if (SPA_COMMAND_TYPE(command) == core->type.command_node.ClockUpdate) { if (SPA_COMMAND_TYPE(command) == core->type.command_node.ClockUpdate) {
pw_client_node_notify_node_command(this->resource, this->seq++, command); pw_client_node_resource_node_command(this->resource, this->seq++, command);
} else { } else {
/* send start */ /* send start */
pw_client_node_notify_node_command(this->resource, this->seq, command); pw_client_node_resource_node_command(this->resource, this->seq, command);
if (SPA_COMMAND_TYPE(command) == core->type.command_node.Start) if (SPA_COMMAND_TYPE(command) == core->type.command_node.Start)
send_need_input(this); send_need_input(this);
@ -470,7 +468,7 @@ spa_proxy_node_port_set_format(struct spa_node *node,
if (this->resource == NULL) if (this->resource == NULL)
return SPA_RESULT_OK; return SPA_RESULT_OK;
pw_client_node_notify_set_format(this->resource, pw_client_node_resource_set_format(this->resource,
this->seq, direction, port_id, flags, format); this->seq, direction, port_id, flags, format);
return SPA_RESULT_RETURN_ASYNC(this->seq++); return SPA_RESULT_RETURN_ASYNC(this->seq++);
@ -644,7 +642,7 @@ spa_proxy_node_port_use_buffers(struct spa_node *node,
mb[i].offset = 0; mb[i].offset = 0;
mb[i].size = msh->size; mb[i].size = msh->size;
pw_client_node_notify_add_mem(this->resource, pw_client_node_resource_add_mem(this->resource,
direction, direction,
port_id, port_id,
mb[i].mem_id, mb[i].mem_id,
@ -662,7 +660,7 @@ spa_proxy_node_port_use_buffers(struct spa_node *node,
if (d->type == impl->core->type.data.DmaBuf || if (d->type == impl->core->type.data.DmaBuf ||
d->type == impl->core->type.data.MemFd) { d->type == impl->core->type.data.MemFd) {
pw_client_node_notify_add_mem(this->resource, pw_client_node_resource_add_mem(this->resource,
direction, direction,
port_id, port_id,
n_mem, n_mem,
@ -683,7 +681,7 @@ spa_proxy_node_port_use_buffers(struct spa_node *node,
} }
} }
pw_client_node_notify_use_buffers(this->resource, pw_client_node_resource_use_buffers(this->resource,
this->seq, direction, port_id, n_buffers, mb); this->seq, direction, port_id, n_buffers, mb);
return SPA_RESULT_RETURN_ASYNC(this->seq++); return SPA_RESULT_RETURN_ASYNC(this->seq++);
@ -948,6 +946,7 @@ static void client_node_destroy(void *object)
} }
static struct pw_client_node_methods client_node_methods = { static struct pw_client_node_methods client_node_methods = {
PW_VERSION_CLIENT_NODE_METHODS,
&client_node_done, &client_node_done,
&client_node_update, &client_node_update,
&client_node_port_update, &client_node_port_update,
@ -1053,7 +1052,7 @@ static void on_initialized(struct pw_listener *listener, struct pw_node *node)
pw_client_node_get_fds(this, &readfd, &writefd); pw_client_node_get_fds(this, &readfd, &writefd);
pw_transport_get_info(impl->transport, &info); pw_transport_get_info(impl->transport, &info);
pw_client_node_notify_transport(this->resource, node->global->id, pw_client_node_resource_transport(this->resource, node->global->id,
readfd, writefd, info.memfd, info.offset, info.size); readfd, writefd, info.memfd, info.offset, info.size);
} }
@ -1150,8 +1149,6 @@ struct pw_client_node *pw_client_node_new(struct pw_resource *resource,
impl->fds[0] = impl->fds[1] = -1; impl->fds[0] = impl->fds[1] = -1;
pw_log_debug("client-node %p: new", impl); pw_log_debug("client-node %p: new", impl);
impl->type_client_node = spa_type_map_get_id(core->type.map, PW_TYPE__ClientNode);
pw_signal_init(&this->destroy_signal); pw_signal_init(&this->destroy_signal);
proxy_init(&impl->proxy, NULL, core->support, core->n_support); proxy_init(&impl->proxy, NULL, core->support, core->n_support);
@ -1168,11 +1165,9 @@ struct pw_client_node *pw_client_node_new(struct pw_resource *resource,
if (this->node == NULL) if (this->node == NULL)
goto error_no_node; goto error_no_node;
this->resource->destroy = (pw_destroy_t) client_node_resource_destroy;
pw_resource_set_implementation(this->resource, pw_resource_set_implementation(this->resource,
this, this, &client_node_methods);
PW_VERSION_CLIENT_NODE,
&client_node_methods,
(pw_destroy_t) client_node_resource_destroy);
impl->proxy.resource = this->resource; impl->proxy.resource = this->resource;

View file

@ -158,7 +158,7 @@ static bool client_node_demarshal_set_props(void *object, void *data, size_t siz
-SPA_POD_TYPE_OBJECT, &props, 0)) -SPA_POD_TYPE_OBJECT, &props, 0))
return false; return false;
((struct pw_client_node_events *) proxy->implementation)->set_props(proxy, seq, props); pw_proxy_notify(proxy, struct pw_client_node_events, set_props, seq, props);
return true; return true;
} }
@ -173,7 +173,7 @@ static bool client_node_demarshal_event_event(void *object, void *data, size_t s
!spa_pod_iter_get(&it, SPA_POD_TYPE_OBJECT, &event, 0)) !spa_pod_iter_get(&it, SPA_POD_TYPE_OBJECT, &event, 0))
return false; return false;
((struct pw_client_node_events *) proxy->implementation)->event(proxy, event); pw_proxy_notify(proxy, struct pw_client_node_events, event, event);
return true; return true;
} }
@ -189,8 +189,7 @@ static bool client_node_demarshal_add_port(void *object, void *data, size_t size
SPA_POD_TYPE_INT, &direction, SPA_POD_TYPE_INT, &port_id, 0)) SPA_POD_TYPE_INT, &direction, SPA_POD_TYPE_INT, &port_id, 0))
return false; return false;
((struct pw_client_node_events *) proxy->implementation)->add_port(proxy, seq, direction, pw_proxy_notify(proxy, struct pw_client_node_events, add_port, seq, direction, port_id);
port_id);
return true; return true;
} }
@ -206,8 +205,7 @@ static bool client_node_demarshal_remove_port(void *object, void *data, size_t s
SPA_POD_TYPE_INT, &direction, SPA_POD_TYPE_INT, &port_id, 0)) SPA_POD_TYPE_INT, &direction, SPA_POD_TYPE_INT, &port_id, 0))
return false; return false;
((struct pw_client_node_events *) proxy->implementation)->remove_port(proxy, seq, direction, pw_proxy_notify(proxy, struct pw_client_node_events, remove_port, seq, direction, port_id);
port_id);
return true; return true;
} }
@ -228,9 +226,8 @@ static bool client_node_demarshal_set_format(void *object, void *data, size_t si
-SPA_POD_TYPE_OBJECT, &format, 0)) -SPA_POD_TYPE_OBJECT, &format, 0))
return false; return false;
((struct pw_client_node_events *) proxy->implementation)->set_format(proxy, seq, direction, pw_proxy_notify(proxy, struct pw_client_node_events, set_format, seq, direction, port_id,
port_id, flags, flags, format);
format);
return true; return true;
} }
@ -250,8 +247,7 @@ static bool client_node_demarshal_set_param(void *object, void *data, size_t siz
-SPA_POD_TYPE_OBJECT, &param, 0)) -SPA_POD_TYPE_OBJECT, &param, 0))
return false; return false;
((struct pw_client_node_events *) proxy->implementation)->set_param(proxy, seq, direction, pw_proxy_notify(proxy, struct pw_client_node_events, set_param, seq, direction, port_id, param);
port_id, param);
return true; return true;
} }
@ -276,8 +272,7 @@ static bool client_node_demarshal_add_mem(void *object, void *data, size_t size)
memfd = pw_protocol_native_get_proxy_fd(proxy, memfd_idx); memfd = pw_protocol_native_get_proxy_fd(proxy, memfd_idx);
((struct pw_client_node_events *) proxy->implementation)->add_mem(proxy, pw_proxy_notify(proxy, struct pw_client_node_events, add_mem, direction,
direction,
port_id, port_id,
mem_id, mem_id,
type, type,
@ -340,8 +335,7 @@ static bool client_node_demarshal_use_buffers(void *object, void *data, size_t s
d->data = SPA_UINT32_TO_PTR(data_id); d->data = SPA_UINT32_TO_PTR(data_id);
} }
} }
((struct pw_client_node_events *) proxy->implementation)->use_buffers(proxy, pw_proxy_notify(proxy, struct pw_client_node_events, use_buffers, seq,
seq,
direction, direction,
port_id, port_id,
n_buffers, buffers); n_buffers, buffers);
@ -360,7 +354,7 @@ static bool client_node_demarshal_node_command(void *object, void *data, size_t
!spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &seq, SPA_POD_TYPE_OBJECT, &command, 0)) !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &seq, SPA_POD_TYPE_OBJECT, &command, 0))
return false; return false;
((struct pw_client_node_events *) proxy->implementation)->node_command(proxy, seq, command); pw_proxy_notify(proxy, struct pw_client_node_events, node_command, seq, command);
return true; return true;
} }
@ -379,8 +373,7 @@ static bool client_node_demarshal_port_command(void *object, void *data, size_t
SPA_POD_TYPE_OBJECT, &command, 0)) SPA_POD_TYPE_OBJECT, &command, 0))
return false; return false;
((struct pw_client_node_events *) proxy->implementation)->port_command(proxy, pw_proxy_notify(proxy, struct pw_client_node_events, port_command, direction,
direction,
port_id, port_id,
command); command);
return true; return true;
@ -409,7 +402,7 @@ static bool client_node_demarshal_transport(void *object, void *data, size_t siz
if (readfd == -1 || writefd == -1 || memfd_idx == -1) if (readfd == -1 || writefd == -1 || memfd_idx == -1)
return false; return false;
((struct pw_client_node_events *) proxy->implementation)->transport(proxy, node_id, pw_proxy_notify(proxy, struct pw_client_node_events, transport, node_id,
readfd, writefd, readfd, writefd,
memfd, offset, sz); memfd, offset, sz);
return true; return true;
@ -666,7 +659,7 @@ static bool client_node_demarshal_done(void *object, void *data, size_t size)
SPA_POD_TYPE_INT, &res, 0)) SPA_POD_TYPE_INT, &res, 0))
return false; return false;
((struct pw_client_node_methods *) resource->implementation)->done(resource, seq, res); pw_resource_do(resource, struct pw_client_node_methods, done, seq, res);
return true; return true;
} }
@ -685,7 +678,7 @@ static bool client_node_demarshal_update(void *object, void *data, size_t size)
SPA_POD_TYPE_INT, &max_output_ports, -SPA_POD_TYPE_OBJECT, &props, 0)) SPA_POD_TYPE_INT, &max_output_ports, -SPA_POD_TYPE_OBJECT, &props, 0))
return false; return false;
((struct pw_client_node_methods *) resource->implementation)->update(resource, change_mask, pw_resource_do(resource, struct pw_client_node_methods, update, change_mask,
max_input_ports, max_input_ports,
max_output_ports, max_output_ports,
props); props);
@ -738,8 +731,7 @@ static bool client_node_demarshal_port_update(void *object, void *data, size_t s
return false; return false;
} }
((struct pw_client_node_methods *) resource->implementation)->port_update(resource, pw_resource_do(resource, struct pw_client_node_methods, port_update, direction,
direction,
port_id, port_id,
change_mask, change_mask,
n_possible_formats, n_possible_formats,
@ -761,7 +753,7 @@ static bool client_node_demarshal_event_method(void *object, void *data, size_t
!spa_pod_iter_get(&it, SPA_POD_TYPE_OBJECT, &event, 0)) !spa_pod_iter_get(&it, SPA_POD_TYPE_OBJECT, &event, 0))
return false; return false;
((struct pw_client_node_methods *) resource->implementation)->event(resource, event); pw_resource_do(resource, struct pw_client_node_methods, event, event);
return true; return true;
} }
@ -773,11 +765,12 @@ static bool client_node_demarshal_destroy(void *object, void *data, size_t size)
if (!spa_pod_iter_struct(&it, data, size)) if (!spa_pod_iter_struct(&it, data, size))
return false; return false;
((struct pw_client_node_methods *) resource->implementation)->destroy(resource); pw_resource_do_na(resource, struct pw_client_node_methods, destroy);
return true; return true;
} }
static const struct pw_client_node_methods pw_protocol_native_client_client_node_methods = { static const struct pw_client_node_methods pw_protocol_native_client_node_method_marshal = {
PW_VERSION_CLIENT_NODE_METHODS,
&client_node_marshal_done, &client_node_marshal_done,
&client_node_marshal_update, &client_node_marshal_update,
&client_node_marshal_port_update, &client_node_marshal_port_update,
@ -785,28 +778,7 @@ static const struct pw_client_node_methods pw_protocol_native_client_client_node
&client_node_marshal_destroy &client_node_marshal_destroy
}; };
static const demarshal_func_t pw_protocol_native_client_client_node_demarshal[] = { static const demarshal_func_t pw_protocol_native_client_node_method_demarshal[] = {
&client_node_demarshal_transport,
&client_node_demarshal_set_props,
&client_node_demarshal_event_event,
&client_node_demarshal_add_port,
&client_node_demarshal_remove_port,
&client_node_demarshal_set_format,
&client_node_demarshal_set_param,
&client_node_demarshal_add_mem,
&client_node_demarshal_use_buffers,
&client_node_demarshal_node_command,
&client_node_demarshal_port_command,
};
static const struct pw_interface pw_protocol_native_client_client_node_interface = {
PW_TYPE__ClientNode,
PW_VERSION_CLIENT_NODE,
PW_CLIENT_NODE_METHOD_NUM, &pw_protocol_native_client_client_node_methods,
PW_CLIENT_NODE_EVENT_NUM, pw_protocol_native_client_client_node_demarshal,
};
static const demarshal_func_t pw_protocol_native_server_client_node_demarshal[] = {
&client_node_demarshal_done, &client_node_demarshal_done,
&client_node_demarshal_update, &client_node_demarshal_update,
&client_node_demarshal_port_update, &client_node_demarshal_port_update,
@ -814,7 +786,8 @@ static const demarshal_func_t pw_protocol_native_server_client_node_demarshal[]
&client_node_demarshal_destroy, &client_node_demarshal_destroy,
}; };
static const struct pw_client_node_events pw_protocol_native_server_client_node_events = { static const struct pw_client_node_events pw_protocol_native_client_node_event_marshal = {
PW_VERSION_CLIENT_NODE_EVENTS,
&client_node_marshal_transport, &client_node_marshal_transport,
&client_node_marshal_set_props, &client_node_marshal_set_props,
&client_node_marshal_event_event, &client_node_marshal_event_event,
@ -828,11 +801,29 @@ static const struct pw_client_node_events pw_protocol_native_server_client_node_
&client_node_marshal_port_command, &client_node_marshal_port_command,
}; };
const struct pw_interface pw_protocol_native_server_client_node_interface = { static const demarshal_func_t pw_protocol_native_client_node_event_demarshal[] = {
PW_TYPE__ClientNode, &client_node_demarshal_transport,
&client_node_demarshal_set_props,
&client_node_demarshal_event_event,
&client_node_demarshal_add_port,
&client_node_demarshal_remove_port,
&client_node_demarshal_set_format,
&client_node_demarshal_set_param,
&client_node_demarshal_add_mem,
&client_node_demarshal_use_buffers,
&client_node_demarshal_node_command,
&client_node_demarshal_port_command,
};
const struct pw_protocol_marshal pw_protocol_native_client_node_marshal = {
PW_TYPE_INTERFACE__ClientNode,
PW_VERSION_CLIENT_NODE, PW_VERSION_CLIENT_NODE,
PW_CLIENT_NODE_METHOD_NUM, &pw_protocol_native_server_client_node_demarshal, PW_CLIENT_NODE_METHOD_NUM,
PW_CLIENT_NODE_EVENT_NUM, &pw_protocol_native_server_client_node_events, &pw_protocol_native_client_node_method_marshal,
&pw_protocol_native_client_node_method_demarshal,
PW_CLIENT_NODE_EVENT_NUM,
&pw_protocol_native_client_node_event_marshal,
pw_protocol_native_client_node_event_demarshal,
}; };
struct pw_protocol *pw_protocol_native_ext_client_node_init(struct pw_core *core) struct pw_protocol *pw_protocol_native_ext_client_node_init(struct pw_core *core)
@ -844,9 +835,7 @@ struct pw_protocol *pw_protocol_native_ext_client_node_init(struct pw_core *core
if (protocol == NULL) if (protocol == NULL)
return NULL; return NULL;
pw_protocol_add_interfaces(protocol, pw_protocol_add_marshal(protocol, &pw_protocol_native_client_node_marshal);
&pw_protocol_native_client_client_node_interface,
&pw_protocol_native_server_client_node_interface);
return protocol; return protocol;
} }

View file

@ -69,8 +69,9 @@ struct async_pending {
struct pw_resource *resource; struct pw_resource *resource;
char *factory_name; char *factory_name;
char *name; char *name;
struct pw_properties *properties; uint32_t type;
uint32_t version; uint32_t version;
struct pw_properties *properties;
uint32_t new_id; uint32_t new_id;
}; };
@ -230,7 +231,8 @@ do_global_filter(struct pw_global *global, struct pw_client *client, void *data)
if (link->input if (link->input
&& !check_global_owner(client->core, client, link->input->node->global)) && !check_global_owner(client->core, client, link->input->node->global))
return false; return false;
} else if (!check_global_owner(client->core, client, global)) }
else if (!check_global_owner(client->core, client, global))
return false; return false;
return true; return true;
@ -268,11 +270,12 @@ portal_response(DBusConnection *connection, DBusMessage *msg, void *user_data)
cinfo->old_methods->create_node (p->resource, cinfo->old_methods->create_node (p->resource,
p->factory_name, p->factory_name,
p->name, p->name,
&p->properties->dict, p->type,
p->version, p->version,
&p->properties->dict,
p->new_id); p->new_id);
} else { } else {
pw_core_notify_error(cinfo->client->core_resource, pw_core_resource_error(cinfo->client->core_resource,
p->resource->id, SPA_RESULT_NO_PERMISSION, "not allowed"); p->resource->id, SPA_RESULT_NO_PERMISSION, "not allowed");
} }
@ -288,8 +291,9 @@ portal_response(DBusConnection *connection, DBusMessage *msg, void *user_data)
static void do_create_node(void *object, static void do_create_node(void *object,
const char *factory_name, const char *factory_name,
const char *name, const char *name,
const struct spa_dict *props, uint32_t type,
uint32_t version, uint32_t version,
const struct spa_dict *props,
uint32_t new_id) uint32_t new_id)
{ {
struct pw_resource *resource = object; struct pw_resource *resource = object;
@ -306,7 +310,7 @@ static void do_create_node(void *object,
struct async_pending *p; struct async_pending *p;
if (!cinfo->is_sandboxed) { if (!cinfo->is_sandboxed) {
cinfo->old_methods->create_node (object, factory_name, name, props, version, new_id); cinfo->old_methods->create_node (object, factory_name, name, type, version, props, new_id);
return; return;
} }
if (strcmp(factory_name, "client-node") != 0) { if (strcmp(factory_name, "client-node") != 0) {
@ -362,8 +366,9 @@ static void do_create_node(void *object,
p->resource = resource; p->resource = resource;
p->factory_name = strdup(factory_name); p->factory_name = strdup(factory_name);
p->name = strdup(name); p->name = strdup(name);
p->properties = props ? pw_properties_new_dict(props) : NULL; p->type = type;
p->version = version; p->version = version;
p->properties = props ? pw_properties_new_dict(props) : NULL;
p->new_id = new_id; p->new_id = new_id;
pw_client_set_busy(client, true); pw_client_set_busy(client, true);
@ -393,7 +398,7 @@ static void do_create_node(void *object,
dbus_error_free(&error); dbus_error_free(&error);
goto not_allowed; goto not_allowed;
not_allowed: not_allowed:
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
resource->id, SPA_RESULT_NO_PERMISSION, "not allowed"); resource->id, SPA_RESULT_NO_PERMISSION, "not allowed");
return; return;
} }
@ -413,7 +418,7 @@ do_create_link(void *object,
struct pw_client *client = resource->client; struct pw_client *client = resource->client;
if (cinfo->is_sandboxed) { if (cinfo->is_sandboxed) {
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
resource->id, SPA_RESULT_NO_PERMISSION, "not allowed"); resource->id, SPA_RESULT_NO_PERMISSION, "not allowed");
return; return;
} }
@ -432,9 +437,8 @@ static void on_resource_impl(struct pw_listener *listener,
struct pw_resource *resource) struct pw_resource *resource)
{ {
struct client_info *cinfo = SPA_CONTAINER_OF(listener, struct client_info, resource_impl); struct client_info *cinfo = SPA_CONTAINER_OF(listener, struct client_info, resource_impl);
struct impl *impl = cinfo->impl;
if (resource->type == impl->core->type.core) { if (resource->type == client->core->type.core) {
cinfo->old_methods = resource->implementation; cinfo->old_methods = resource->implementation;
cinfo->core_methods = *cinfo->old_methods; cinfo->core_methods = *cinfo->old_methods;
resource->implementation = &cinfo->core_methods; resource->implementation = &cinfo->core_methods;

View file

@ -116,13 +116,13 @@ process_messages(struct pw_client *client)
client->protocol, id); client->protocol, id);
continue; continue;
} }
if (opcode >= resource->iface->n_methods) { if (opcode >= resource->marshal->n_methods) {
pw_log_error("protocol-native %p: invalid method %u %u", client->protocol, pw_log_error("protocol-native %p: invalid method %u %u", client->protocol,
id, opcode); id, opcode);
pw_client_destroy(client); pw_client_destroy(client);
break; break;
} }
demarshal = resource->iface->methods; demarshal = resource->marshal->method_demarshal;
if (!demarshal[opcode] || !demarshal[opcode] (resource, message, size)) { if (!demarshal[opcode] || !demarshal[opcode] (resource, message, size)) {
pw_log_error("protocol-native %p: invalid message received %u %u", pw_log_error("protocol-native %p: invalid message received %u %u",
client->protocol, id, opcode); client->protocol, id, opcode);
@ -449,13 +449,13 @@ on_remote_data(struct spa_loop_utils *utils,
pw_log_error("protocol-native %p: could not find proxy %u", this, id); pw_log_error("protocol-native %p: could not find proxy %u", this, id);
continue; continue;
} }
if (opcode >= proxy->iface->n_events) { if (opcode >= proxy->marshal->n_events) {
pw_log_error("protocol-native %p: invalid method %u for %u", this, opcode, pw_log_error("protocol-native %p: invalid method %u for %u", this, opcode,
id); id);
continue; continue;
} }
demarshal = proxy->iface->events; demarshal = proxy->marshal->event_demarshal;
if (demarshal[opcode]) { if (demarshal[opcode]) {
if (!demarshal[opcode] (proxy, message, size)) if (!demarshal[opcode] (proxy, message, size))
pw_log_error pw_log_error

View file

@ -375,7 +375,7 @@ pw_protocol_native_connection_begin_resource(struct pw_protocol_native_connectio
types[i] = spa_type_map_get_type(core->type.map, b); types[i] = spa_type_map_get_type(core->type.map, b);
client->n_types += diff; client->n_types += diff;
pw_core_notify_update_types(client->core_resource, base, diff, types); pw_core_resource_update_types(client->core_resource, base, diff, types);
} }
impl->dest_id = resource->id; impl->dest_id = resource->id;
@ -404,7 +404,7 @@ pw_protocol_native_connection_begin_proxy(struct pw_protocol_native_connection *
types[i] = spa_type_map_get_type(core->type.map, b); types[i] = spa_type_map_get_type(core->type.map, b);
remote->n_types += diff; remote->n_types += diff;
pw_core_do_update_types(remote->core_proxy, base, diff, types); pw_core_proxy_update_types(remote->core_proxy, base, diff, types);
} }
impl->dest_id = proxy->id; impl->dest_id = proxy->id;

View file

@ -89,9 +89,9 @@ static void core_marshal_get_registry(void *object, uint32_t version, uint32_t n
static void static void
core_marshal_create_node(void *object, core_marshal_create_node(void *object,
const char *factory_name, const char *factory_name, const char *name,
const char *name, const struct spa_dict *props, uint32_t type, uint32_t version,
uint32_t version, uint32_t new_id) const struct spa_dict *props, uint32_t new_id)
{ {
struct pw_proxy *proxy = object; struct pw_proxy *proxy = object;
struct spa_pod_builder *b; struct spa_pod_builder *b;
@ -105,7 +105,10 @@ core_marshal_create_node(void *object,
spa_pod_builder_add(b, spa_pod_builder_add(b,
SPA_POD_TYPE_STRUCT, &f, SPA_POD_TYPE_STRUCT, &f,
SPA_POD_TYPE_STRING, factory_name, SPA_POD_TYPE_STRING, factory_name,
SPA_POD_TYPE_STRING, name, SPA_POD_TYPE_INT, n_items, 0); SPA_POD_TYPE_STRING, name,
SPA_POD_TYPE_ID, type,
SPA_POD_TYPE_INT, version,
SPA_POD_TYPE_INT, n_items, 0);
for (i = 0; i < n_items; i++) { for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b, spa_pod_builder_add(b,
@ -113,7 +116,6 @@ core_marshal_create_node(void *object,
SPA_POD_TYPE_STRING, props->items[i].value, 0); SPA_POD_TYPE_STRING, props->items[i].value, 0);
} }
spa_pod_builder_add(b, spa_pod_builder_add(b,
SPA_POD_TYPE_INT, version,
SPA_POD_TYPE_INT, new_id, SPA_POD_TYPE_INT, new_id,
-SPA_POD_TYPE_STRUCT, &f, 0); -SPA_POD_TYPE_STRUCT, &f, 0);
@ -192,7 +194,6 @@ static bool core_demarshal_info(void *object, void *data, size_t size)
if (!spa_pod_iter_struct(&it, data, size) || if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it, !spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &info.id,
SPA_POD_TYPE_LONG, &info.change_mask, SPA_POD_TYPE_LONG, &info.change_mask,
SPA_POD_TYPE_STRING, &info.user_name, SPA_POD_TYPE_STRING, &info.user_name,
SPA_POD_TYPE_STRING, &info.host_name, SPA_POD_TYPE_STRING, &info.host_name,
@ -292,7 +293,6 @@ static void core_marshal_info(void *object, struct pw_core_info *info)
spa_pod_builder_add(b, spa_pod_builder_add(b,
SPA_POD_TYPE_STRUCT, &f, SPA_POD_TYPE_STRUCT, &f,
SPA_POD_TYPE_INT, info->id,
SPA_POD_TYPE_LONG, info->change_mask, SPA_POD_TYPE_LONG, info->change_mask,
SPA_POD_TYPE_STRING, info->user_name, SPA_POD_TYPE_STRING, info->user_name,
SPA_POD_TYPE_STRING, info->host_name, SPA_POD_TYPE_STRING, info->host_name,
@ -437,14 +437,18 @@ static bool core_demarshal_create_node(void *object, void *data, size_t size)
{ {
struct pw_resource *resource = object; struct pw_resource *resource = object;
struct spa_pod_iter it; struct spa_pod_iter it;
uint32_t version, new_id, i; uint32_t version, type, new_id, i;
const char *factory_name, *name; const char *factory_name, *name;
struct spa_dict props; struct spa_dict props;
if (!spa_pod_iter_struct(&it, data, size) || if (!spa_pod_iter_struct(&it, data, size) ||
!pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &resource->client->types) ||
!spa_pod_iter_get(&it, !spa_pod_iter_get(&it,
SPA_POD_TYPE_STRING, &factory_name, SPA_POD_TYPE_STRING, &factory_name,
SPA_POD_TYPE_STRING, &name, SPA_POD_TYPE_INT, &props.n_items, 0)) SPA_POD_TYPE_STRING, &name,
SPA_POD_TYPE_ID, &type,
SPA_POD_TYPE_INT, &version,
SPA_POD_TYPE_INT, &props.n_items, 0))
return false; return false;
props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
@ -455,12 +459,12 @@ static bool core_demarshal_create_node(void *object, void *data, size_t size)
return false; return false;
} }
if (!spa_pod_iter_get(&it, if (!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &version,
SPA_POD_TYPE_INT, &new_id, 0)) SPA_POD_TYPE_INT, &new_id, 0))
return false; return false;
pw_resource_do(resource, struct pw_core_methods, create_node, factory_name, pw_resource_do(resource, struct pw_core_methods, create_node, factory_name, name,
name, &props, version, new_id); type, version,
&props, new_id);
return true; return true;
} }
@ -558,16 +562,18 @@ static bool registry_demarshal_bind(void *object, void *data, size_t size)
{ {
struct pw_resource *resource = object; struct pw_resource *resource = object;
struct spa_pod_iter it; struct spa_pod_iter it;
uint32_t id, version, new_id; uint32_t id, version, type, new_id;
if (!spa_pod_iter_struct(&it, data, size) || if (!spa_pod_iter_struct(&it, data, size) ||
!pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &resource->client->types) ||
!spa_pod_iter_get(&it, !spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &id, SPA_POD_TYPE_INT, &id,
SPA_POD_TYPE_ID, &type,
SPA_POD_TYPE_INT, &version, SPA_POD_TYPE_INT, &version,
SPA_POD_TYPE_INT, &new_id, 0)) SPA_POD_TYPE_INT, &new_id, 0))
return false; return false;
pw_resource_do(resource, struct pw_registry_methods, bind, id, version, new_id); pw_resource_do(resource, struct pw_registry_methods, bind, id, type, version, new_id);
return true; return true;
} }
@ -584,7 +590,6 @@ static void module_marshal_info(void *object, struct pw_module_info *info)
spa_pod_builder_add(b, spa_pod_builder_add(b,
SPA_POD_TYPE_STRUCT, &f, SPA_POD_TYPE_STRUCT, &f,
SPA_POD_TYPE_INT, info->id,
SPA_POD_TYPE_LONG, info->change_mask, SPA_POD_TYPE_LONG, info->change_mask,
SPA_POD_TYPE_STRING, info->name, SPA_POD_TYPE_STRING, info->name,
SPA_POD_TYPE_STRING, info->filename, SPA_POD_TYPE_STRING, info->filename,
@ -610,7 +615,6 @@ static bool module_demarshal_info(void *object, void *data, size_t size)
if (!spa_pod_iter_struct(&it, data, size) || if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it, !spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &info.id,
SPA_POD_TYPE_LONG, &info.change_mask, SPA_POD_TYPE_LONG, &info.change_mask,
SPA_POD_TYPE_STRING, &info.name, SPA_POD_TYPE_STRING, &info.name,
SPA_POD_TYPE_STRING, &info.filename, SPA_POD_TYPE_STRING, &info.filename,
@ -640,7 +644,6 @@ static void node_marshal_info(void *object, struct pw_node_info *info)
spa_pod_builder_add(b, spa_pod_builder_add(b,
SPA_POD_TYPE_STRUCT, &f, SPA_POD_TYPE_STRUCT, &f,
SPA_POD_TYPE_INT, info->id,
SPA_POD_TYPE_LONG, info->change_mask, SPA_POD_TYPE_LONG, info->change_mask,
SPA_POD_TYPE_STRING, info->name, SPA_POD_TYPE_STRING, info->name,
SPA_POD_TYPE_INT, info->max_input_ports, SPA_POD_TYPE_INT, info->max_input_ports,
@ -685,7 +688,6 @@ static bool node_demarshal_info(void *object, void *data, size_t size)
if (!spa_pod_iter_struct(&it, data, size) || if (!spa_pod_iter_struct(&it, data, size) ||
!pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->remote->types) || !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->remote->types) ||
!spa_pod_iter_get(&it, !spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &info.id,
SPA_POD_TYPE_LONG, &info.change_mask, SPA_POD_TYPE_LONG, &info.change_mask,
SPA_POD_TYPE_STRING, &info.name, SPA_POD_TYPE_STRING, &info.name,
SPA_POD_TYPE_INT, &info.max_input_ports, SPA_POD_TYPE_INT, &info.max_input_ports,
@ -740,7 +742,6 @@ static void client_marshal_info(void *object, struct pw_client_info *info)
spa_pod_builder_add(b, spa_pod_builder_add(b,
SPA_POD_TYPE_STRUCT, &f, SPA_POD_TYPE_STRUCT, &f,
SPA_POD_TYPE_INT, info->id,
SPA_POD_TYPE_LONG, info->change_mask, SPA_POD_TYPE_INT, n_items, 0); SPA_POD_TYPE_LONG, info->change_mask, SPA_POD_TYPE_INT, n_items, 0);
for (i = 0; i < n_items; i++) { for (i = 0; i < n_items; i++) {
@ -763,7 +764,6 @@ static bool client_demarshal_info(void *object, void *data, size_t size)
if (!spa_pod_iter_struct(&it, data, size) || if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it, !spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &info.id,
SPA_POD_TYPE_LONG, &info.change_mask, SPA_POD_TYPE_LONG, &info.change_mask,
SPA_POD_TYPE_INT, &props.n_items, 0)) SPA_POD_TYPE_INT, &props.n_items, 0))
return false; return false;
@ -789,7 +789,6 @@ static void link_marshal_info(void *object, struct pw_link_info *info)
b = pw_protocol_native_begin_resource(resource, PW_LINK_EVENT_INFO); b = pw_protocol_native_begin_resource(resource, PW_LINK_EVENT_INFO);
spa_pod_builder_struct(b, &f, spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, info->id,
SPA_POD_TYPE_LONG, info->change_mask, SPA_POD_TYPE_LONG, info->change_mask,
SPA_POD_TYPE_INT, info->output_node_id, SPA_POD_TYPE_INT, info->output_node_id,
SPA_POD_TYPE_INT, info->output_port_id, SPA_POD_TYPE_INT, info->output_port_id,
@ -809,7 +808,6 @@ static bool link_demarshal_info(void *object, void *data, size_t size)
if (!spa_pod_iter_struct(&it, data, size) || if (!spa_pod_iter_struct(&it, data, size) ||
!pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->remote->types) || !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->remote->types) ||
!spa_pod_iter_get(&it, !spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &info.id,
SPA_POD_TYPE_LONG, &info.change_mask, SPA_POD_TYPE_LONG, &info.change_mask,
SPA_POD_TYPE_INT, &info.output_node_id, SPA_POD_TYPE_INT, &info.output_node_id,
SPA_POD_TYPE_INT, &info.output_port_id, SPA_POD_TYPE_INT, &info.output_port_id,
@ -854,7 +852,8 @@ static bool registry_demarshal_global_remove(void *object, void *data, size_t si
return true; return true;
} }
static void registry_marshal_bind(void *object, uint32_t id, uint32_t version, uint32_t new_id) static void registry_marshal_bind(void *object, uint32_t id,
uint32_t type, uint32_t version, uint32_t new_id)
{ {
struct pw_proxy *proxy = object; struct pw_proxy *proxy = object;
struct spa_pod_builder *b; struct spa_pod_builder *b;
@ -864,13 +863,15 @@ static void registry_marshal_bind(void *object, uint32_t id, uint32_t version, u
spa_pod_builder_struct(b, &f, spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, id, SPA_POD_TYPE_INT, id,
SPA_POD_TYPE_ID, type,
SPA_POD_TYPE_INT, version, SPA_POD_TYPE_INT, version,
SPA_POD_TYPE_INT, new_id); SPA_POD_TYPE_INT, new_id);
pw_protocol_native_end_proxy(proxy, b); pw_protocol_native_end_proxy(proxy, b);
} }
static const struct pw_core_methods pw_protocol_native_client_core_methods = { static const struct pw_core_methods pw_protocol_native_core_method_marshal = {
PW_VERSION_CORE_METHODS,
&core_marshal_update_types_client, &core_marshal_update_types_client,
&core_marshal_sync, &core_marshal_sync,
&core_marshal_get_registry, &core_marshal_get_registry,
@ -879,82 +880,7 @@ static const struct pw_core_methods pw_protocol_native_client_core_methods = {
&core_marshal_create_link &core_marshal_create_link
}; };
static const demarshal_func_t pw_protocol_native_client_core_demarshal[PW_CORE_EVENT_NUM] = { static const demarshal_func_t pw_protocol_native_core_method_demarshal[PW_CORE_METHOD_NUM] = {
&core_demarshal_update_types_client,
&core_demarshal_done,
&core_demarshal_error,
&core_demarshal_remove_id,
&core_demarshal_info
};
static const struct pw_interface pw_protocol_native_client_core_interface = {
PW_TYPE__Core,
PW_VERSION_CORE,
PW_CORE_METHOD_NUM, &pw_protocol_native_client_core_methods,
PW_CORE_EVENT_NUM, pw_protocol_native_client_core_demarshal
};
static const struct pw_registry_methods pw_protocol_native_client_registry_methods = {
&registry_marshal_bind
};
static const demarshal_func_t pw_protocol_native_client_registry_demarshal[] = {
&registry_demarshal_global,
&registry_demarshal_global_remove,
};
static const struct pw_interface pw_protocol_native_client_registry_interface = {
PW_TYPE__Registry,
PW_VERSION_REGISTRY,
PW_REGISTRY_METHOD_NUM, &pw_protocol_native_client_registry_methods,
PW_REGISTRY_EVENT_NUM, pw_protocol_native_client_registry_demarshal,
};
static const demarshal_func_t pw_protocol_native_client_module_demarshal[] = {
&module_demarshal_info,
};
static const struct pw_interface pw_protocol_native_client_module_interface = {
PW_TYPE__Module,
PW_VERSION_MODULE,
0, NULL,
PW_MODULE_EVENT_NUM, pw_protocol_native_client_module_demarshal,
};
static const demarshal_func_t pw_protocol_native_client_node_demarshal[] = {
&node_demarshal_info,
};
static const struct pw_interface pw_protocol_native_client_node_interface = {
PW_TYPE__Node,
PW_VERSION_NODE,
0, NULL,
PW_NODE_EVENT_NUM, pw_protocol_native_client_node_demarshal,
};
static const demarshal_func_t pw_protocol_native_client_client_demarshal[] = {
&client_demarshal_info,
};
static const struct pw_interface pw_protocol_native_client_client_interface = {
PW_TYPE__Client,
PW_VERSION_CLIENT,
0, NULL,
PW_CLIENT_EVENT_NUM, pw_protocol_native_client_client_demarshal,
};
static const demarshal_func_t pw_protocol_native_client_link_demarshal[] = {
&link_demarshal_info,
};
static const struct pw_interface pw_protocol_native_client_link_interface = {
PW_TYPE__Link,
PW_VERSION_LINK,
0, NULL,
PW_LINK_EVENT_NUM, pw_protocol_native_client_link_demarshal,
};
static const demarshal_func_t pw_protocol_native_server_core_demarshal[PW_CORE_METHOD_NUM] = {
&core_demarshal_update_types_server, &core_demarshal_update_types_server,
&core_demarshal_sync, &core_demarshal_sync,
&core_demarshal_get_registry, &core_demarshal_get_registry,
@ -963,7 +889,8 @@ static const demarshal_func_t pw_protocol_native_server_core_demarshal[PW_CORE_M
&core_demarshal_create_link &core_demarshal_create_link
}; };
static const struct pw_core_events pw_protocol_native_server_core_events = { static const struct pw_core_events pw_protocol_native_core_event_marshal = {
PW_VERSION_CORE_EVENTS,
&core_marshal_update_types_server, &core_marshal_update_types_server,
&core_marshal_done, &core_marshal_done,
&core_marshal_error, &core_marshal_error,
@ -971,92 +898,134 @@ static const struct pw_core_events pw_protocol_native_server_core_events = {
&core_marshal_info &core_marshal_info
}; };
const struct pw_interface pw_protocol_native_server_core_interface = { static const demarshal_func_t pw_protocol_native_core_event_demarshal[PW_CORE_EVENT_NUM] = {
PW_TYPE__Core, &core_demarshal_update_types_client,
PW_VERSION_CORE, &core_demarshal_done,
PW_CORE_METHOD_NUM, pw_protocol_native_server_core_demarshal, &core_demarshal_error,
PW_CORE_EVENT_NUM, &pw_protocol_native_server_core_events, &core_demarshal_remove_id,
&core_demarshal_info
}; };
static const demarshal_func_t pw_protocol_native_server_registry_demarshal[] = { static const struct pw_protocol_marshal pw_protocol_native_core_marshal = {
PW_TYPE_INTERFACE__Core,
PW_VERSION_CORE,
PW_CORE_METHOD_NUM,
&pw_protocol_native_core_method_marshal,
pw_protocol_native_core_method_demarshal,
PW_CORE_EVENT_NUM,
&pw_protocol_native_core_event_marshal,
pw_protocol_native_core_event_demarshal
};
static const struct pw_registry_methods pw_protocol_native_registry_method_marshal = {
PW_VERSION_REGISTRY_METHODS,
&registry_marshal_bind
};
static const demarshal_func_t pw_protocol_native_registry_method_demarshal[] = {
&registry_demarshal_bind, &registry_demarshal_bind,
}; };
static const struct pw_registry_events pw_protocol_native_server_registry_events = { static const struct pw_registry_events pw_protocol_native_registry_event_marshal = {
PW_VERSION_REGISTRY_EVENTS,
&registry_marshal_global, &registry_marshal_global,
&registry_marshal_global_remove, &registry_marshal_global_remove,
}; };
const struct pw_interface pw_protocol_native_server_registry_interface = { static const demarshal_func_t pw_protocol_native_registry_event_demarshal[] = {
PW_TYPE__Registry, &registry_demarshal_global,
PW_VERSION_REGISTRY, &registry_demarshal_global_remove,
PW_REGISTRY_METHOD_NUM, pw_protocol_native_server_registry_demarshal,
PW_REGISTRY_EVENT_NUM, &pw_protocol_native_server_registry_events,
}; };
static const struct pw_module_events pw_protocol_native_server_module_events = { const struct pw_protocol_marshal pw_protocol_native_registry_marshal = {
PW_TYPE_INTERFACE__Registry,
PW_VERSION_REGISTRY,
PW_REGISTRY_METHOD_NUM,
&pw_protocol_native_registry_method_marshal,
pw_protocol_native_registry_method_demarshal,
PW_REGISTRY_EVENT_NUM,
&pw_protocol_native_registry_event_marshal,
pw_protocol_native_registry_event_demarshal,
};
static const struct pw_module_events pw_protocol_native_module_event_marshal = {
PW_VERSION_MODULE_EVENTS,
&module_marshal_info, &module_marshal_info,
}; };
const struct pw_interface pw_protocol_native_server_module_interface = { static const demarshal_func_t pw_protocol_native_module_event_demarshal[] = {
PW_TYPE__Module, &module_demarshal_info,
PW_VERSION_MODULE,
0, NULL,
PW_MODULE_EVENT_NUM, &pw_protocol_native_server_module_events,
}; };
static const struct pw_node_events pw_protocol_native_server_node_events = { const struct pw_protocol_marshal pw_protocol_native_module_marshal = {
PW_TYPE_INTERFACE__Module,
PW_VERSION_MODULE,
0, NULL, NULL,
PW_MODULE_EVENT_NUM,
&pw_protocol_native_module_event_marshal,
pw_protocol_native_module_event_demarshal,
};
static const struct pw_node_events pw_protocol_native_node_event_marshal = {
PW_VERSION_NODE_EVENTS,
&node_marshal_info, &node_marshal_info,
}; };
const struct pw_interface pw_protocol_native_server_node_interface = { static const demarshal_func_t pw_protocol_native_node_event_demarshal[] = {
PW_TYPE__Node, &node_demarshal_info,
PW_VERSION_NODE,
0, NULL,
PW_NODE_EVENT_NUM, &pw_protocol_native_server_node_events,
}; };
static const struct pw_client_events pw_protocol_native_server_client_events = { static const struct pw_protocol_marshal pw_protocol_native_node_marshal = {
PW_TYPE_INTERFACE__Node,
PW_VERSION_NODE,
0, NULL, NULL,
PW_NODE_EVENT_NUM,
&pw_protocol_native_node_event_marshal,
pw_protocol_native_node_event_demarshal,
};
static const struct pw_client_events pw_protocol_native_client_event_marshal = {
PW_VERSION_CLIENT_EVENTS,
&client_marshal_info, &client_marshal_info,
}; };
const struct pw_interface pw_protocol_native_server_client_interface = { static const demarshal_func_t pw_protocol_native_client_event_demarshal[] = {
PW_TYPE__Client, &client_demarshal_info,
PW_VERSION_CLIENT,
0, NULL,
PW_CLIENT_EVENT_NUM, &pw_protocol_native_server_client_events,
}; };
static const struct pw_link_events pw_protocol_native_server_link_events = { static const struct pw_protocol_marshal pw_protocol_native_client_marshal = {
PW_TYPE_INTERFACE__Client,
PW_VERSION_CLIENT,
0, NULL, NULL,
PW_CLIENT_EVENT_NUM,
&pw_protocol_native_client_event_marshal,
pw_protocol_native_client_event_demarshal,
};
static const struct pw_link_events pw_protocol_native_link_event_marshal = {
PW_VERSION_LINK_EVENTS,
&link_marshal_info, &link_marshal_info,
}; };
const struct pw_interface pw_protocol_native_server_link_interface = { static const demarshal_func_t pw_protocol_native_link_event_demarshal[] = {
PW_TYPE__Link, &link_demarshal_info,
};
static const struct pw_protocol_marshal pw_protocol_native_link_marshal = {
PW_TYPE_INTERFACE__Link,
PW_VERSION_LINK, PW_VERSION_LINK,
0, NULL, 0, NULL, NULL,
PW_LINK_EVENT_NUM, &pw_protocol_native_server_link_events, PW_LINK_EVENT_NUM,
&pw_protocol_native_link_event_marshal,
pw_protocol_native_link_event_demarshal,
}; };
void pw_protocol_native_init(struct pw_protocol *protocol) void pw_protocol_native_init(struct pw_protocol *protocol)
{ {
pw_protocol_add_interfaces(protocol, pw_protocol_add_marshal(protocol, &pw_protocol_native_core_marshal);
&pw_protocol_native_client_core_interface, pw_protocol_add_marshal(protocol, &pw_protocol_native_registry_marshal);
&pw_protocol_native_server_core_interface); pw_protocol_add_marshal(protocol, &pw_protocol_native_module_marshal);
pw_protocol_add_interfaces(protocol, pw_protocol_add_marshal(protocol, &pw_protocol_native_node_marshal);
&pw_protocol_native_client_registry_interface, pw_protocol_add_marshal(protocol, &pw_protocol_native_client_marshal);
&pw_protocol_native_server_registry_interface); pw_protocol_add_marshal(protocol, &pw_protocol_native_link_marshal);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_module_interface,
&pw_protocol_native_server_module_interface);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_node_interface,
&pw_protocol_native_server_node_interface);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_client_interface,
&pw_protocol_native_server_client_interface);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_link_interface,
&pw_protocol_native_server_link_interface);
} }

View file

@ -66,7 +66,7 @@ static struct pw_node *create_node(struct pw_node_factory *factory,
no_properties: no_properties:
pw_log_error("missing properties"); pw_log_error("missing properties");
if (resource) { if (resource) {
pw_core_notify_error(resource->client->core_resource, pw_core_resource_error(resource->client->core_resource,
resource->client->core_resource->id, resource->client->core_resource->id,
SPA_RESULT_INVALID_ARGUMENTS, "missing properties"); SPA_RESULT_INVALID_ARGUMENTS, "missing properties");
} }
@ -74,7 +74,7 @@ static struct pw_node *create_node(struct pw_node_factory *factory,
no_mem: no_mem:
pw_log_error("can't create node"); pw_log_error("can't create node");
if (resource) { if (resource) {
pw_core_notify_error(resource->client->core_resource, pw_core_resource_error(resource->client->core_resource,
resource->client->core_resource->id, resource->client->core_resource->id,
SPA_RESULT_NO_MEMORY, "no memory"); SPA_RESULT_NO_MEMORY, "no memory");
} }
@ -97,7 +97,8 @@ static struct impl *module_new(struct pw_core *core, struct pw_properties *prope
spa_list_insert(core->node_factory_list.prev, &impl->this.link); spa_list_insert(core->node_factory_list.prev, &impl->this.link);
pw_core_add_global(core, NULL, core->type.node_factory, 0, impl, NULL, &impl->this.global); pw_core_add_global(core, NULL, core->type.node_factory, 0,
NULL, impl, &impl->this.global);
return impl; return impl;
} }

View file

@ -38,29 +38,32 @@ static void client_unbind_func(void *data)
} }
static int static int
client_bind_func(struct pw_global *global, struct pw_client *client, uint32_t version, uint32_t id) client_bind_func(struct pw_global *global,
struct pw_client *client,
uint32_t version, uint32_t id)
{ {
struct pw_client *this = global->object; struct pw_client *this = global->object;
struct pw_resource *resource; struct pw_resource *resource;
resource = pw_resource_new(client, id, global->type, version, 0); resource = pw_resource_new(client, id, global->type, version, 0, client_unbind_func);
if (resource == NULL) if (resource == NULL)
goto no_mem; goto no_mem;
pw_resource_set_implementation(resource, global->object, PW_VERSION_CLIENT, NULL, client_unbind_func); pw_resource_set_implementation(resource, this, NULL);
pw_log_debug("client %p: bound to %d", global->object, resource->id); pw_log_debug("client %p: bound to %d", this, resource->id);
spa_list_insert(this->resource_list.prev, &resource->link); spa_list_insert(this->resource_list.prev, &resource->link);
this->info.change_mask = ~0; this->info.change_mask = ~0;
pw_client_notify_info(resource, &this->info); pw_client_resource_info(resource, &this->info);
this->info.change_mask = 0;
return SPA_RESULT_OK; return SPA_RESULT_OK;
no_mem: no_mem:
pw_log_error("can't create client resource"); pw_log_error("can't create client resource");
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory"); client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory");
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
} }
@ -111,9 +114,8 @@ struct pw_client *pw_client_new(struct pw_core *core,
spa_list_insert(core->client_list.prev, &this->link); spa_list_insert(core->client_list.prev, &this->link);
pw_core_add_global(core, NULL, core->type.client, PW_VERSION_CLIENT, pw_core_add_global(core, NULL, core->type.client, PW_VERSION_CLIENT,
this, client_bind_func, &this->global); client_bind_func, this, &this->global);
this->info.id = this->global->id;
this->info.props = this->properties ? &this->properties->dict : NULL; this->info.props = this->properties ? &this->properties->dict : NULL;
return this; return this;
@ -192,7 +194,7 @@ void pw_client_update_properties(struct pw_client *client, const struct spa_dict
pw_signal_emit(&client->properties_changed, client); pw_signal_emit(&client->properties_changed, client);
spa_list_for_each(resource, &client->resource_list, link) { spa_list_for_each(resource, &client->resource_list, link) {
pw_client_notify_info(resource, &client->info); pw_client_resource_info(resource, &client->info);
} }
} }

View file

@ -32,7 +32,6 @@
/** \cond */ /** \cond */
struct global_impl { struct global_impl {
struct pw_global this; struct pw_global this;
pw_bind_func_t bind;
}; };
struct impl { struct impl {
@ -53,39 +52,59 @@ static bool pw_global_is_visible(struct pw_global *global,
core->global_filter(global, client, core->global_filter_data)); core->global_filter(global, client, core->global_filter_data));
} }
static void registry_bind(void *object, uint32_t id, uint32_t version, uint32_t new_id) static struct pw_global *find_global(struct pw_core *core, uint32_t id)
{
struct pw_global *global;
spa_list_for_each(global, &core->global_list, link) {
if (global->id == id)
return global;
}
return NULL;
}
static void registry_bind(void *object, uint32_t id,
uint32_t type, uint32_t version, uint32_t new_id)
{ {
struct pw_resource *resource = object; struct pw_resource *resource = object;
struct pw_client *client = resource->client; struct pw_client *client = resource->client;
struct pw_core *core = resource->core; struct pw_core *core = resource->core;
struct pw_global *global; struct pw_global *global;
const char *type_name;
spa_list_for_each(global, &core->global_list, link) { if ((global = find_global(core, id)) == 0)
if (global->id == id)
break;
}
if (&global->link == &core->global_list)
goto no_id; goto no_id;
if (!pw_global_is_visible(global, client)) if (!pw_global_is_visible(global, client))
goto no_id; goto no_id;
pw_log_debug("global %p: bind object id %d to %d", global, id, new_id); if (type != global->type)
goto wrong_interface;
type_name = spa_type_map_get_type(core->type.map, type);
pw_log_debug("global %p: bind global id %d, iface %s to %d", global, id, type_name, new_id);
pw_global_bind(global, client, version, new_id); pw_global_bind(global, client, version, new_id);
return; return;
no_id: no_id:
pw_log_debug("registry %p: no global with id %u to bind to %u", resource, id, new_id); pw_log_debug("registry %p: no global with id %u to bind to %u", resource, id, new_id);
goto exit;
wrong_interface:
pw_log_debug("registry %p: global with id %u has no interface %u", resource, id, type);
goto exit;
exit:
/* unmark the new_id the map, the client does not yet know about the failed /* unmark the new_id the map, the client does not yet know about the failed
* bind and will choose the next id, which we would refuse when we don't mark * bind and will choose the next id, which we would refuse when we don't mark
* new_id as 'used and freed' */ * new_id as 'used and freed' */
pw_map_insert_at(&client->objects, new_id, NULL); pw_map_insert_at(&client->objects, new_id, NULL);
pw_core_notify_remove_id(client->core_resource, new_id); pw_core_resource_remove_id(client->core_resource, new_id);
return; return;
} }
static struct pw_registry_methods registry_methods = { static struct pw_registry_methods registry_methods = {
PW_VERSION_REGISTRY_METHODS,
&registry_bind &registry_bind
}; };
@ -106,7 +125,7 @@ static void core_sync(void *object, uint32_t seq)
{ {
struct pw_resource *resource = object; struct pw_resource *resource = object;
pw_core_notify_done(resource, seq); pw_core_resource_done(resource, seq);
} }
static void core_get_registry(void *object, uint32_t version, uint32_t new_id) static void core_get_registry(void *object, uint32_t version, uint32_t new_id)
@ -121,31 +140,30 @@ static void core_get_registry(void *object, uint32_t version, uint32_t new_id)
new_id, new_id,
this->type.registry, this->type.registry,
version, version,
0); 0, destroy_registry_resource);
if (registry_resource == NULL) if (registry_resource == NULL)
goto no_mem; goto no_mem;
pw_resource_set_implementation(registry_resource, pw_resource_set_implementation(registry_resource,
this, registry_resource,
PW_VERSION_REGISTRY, &registry_methods);
&registry_methods,
destroy_registry_resource);
spa_list_insert(this->registry_resource_list.prev, &registry_resource->link); spa_list_insert(this->registry_resource_list.prev, &registry_resource->link);
spa_list_for_each(global, &this->global_list, link) { spa_list_for_each(global, &this->global_list, link) {
if (pw_global_is_visible(global, client)) if (pw_global_is_visible(global, client)) {
pw_registry_notify_global(registry_resource, pw_registry_resource_global(registry_resource,
global->id, global->id,
global->type, global->type,
global->version); global->version);
} }
}
return; return;
no_mem: no_mem:
pw_log_error("can't create registry resource"); pw_log_error("can't create registry resource");
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
resource->id, SPA_RESULT_NO_MEMORY, "no memory"); resource->id, SPA_RESULT_NO_MEMORY, "no memory");
} }
@ -153,8 +171,9 @@ static void
core_create_node(void *object, core_create_node(void *object,
const char *factory_name, const char *factory_name,
const char *name, const char *name,
const struct spa_dict *props, uint32_t type,
uint32_t version, uint32_t version,
const struct spa_dict *props,
uint32_t new_id) uint32_t new_id)
{ {
struct pw_resource *resource = object; struct pw_resource *resource = object;
@ -167,11 +186,7 @@ core_create_node(void *object,
if (factory == NULL) if (factory == NULL)
goto no_factory; goto no_factory;
node_resource = pw_resource_new(client, node_resource = pw_resource_new(client, new_id, type, version, 0, NULL);
new_id,
factory->type,
version,
0);
if (node_resource == NULL) if (node_resource == NULL)
goto no_resource; goto no_resource;
@ -191,7 +206,7 @@ core_create_node(void *object,
no_factory: no_factory:
pw_log_error("can't find node factory"); pw_log_error("can't find node factory");
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
resource->id, SPA_RESULT_INVALID_ARGUMENTS, "unknown factory name"); resource->id, SPA_RESULT_INVALID_ARGUMENTS, "unknown factory name");
goto done; goto done;
@ -203,7 +218,7 @@ core_create_node(void *object,
pw_resource_destroy(node_resource); pw_resource_destroy(node_resource);
goto no_mem; goto no_mem;
no_mem: no_mem:
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
resource->id, SPA_RESULT_NO_MEMORY, "no memory"); resource->id, SPA_RESULT_NO_MEMORY, "no memory");
goto done; goto done;
} }
@ -222,7 +237,7 @@ core_create_link(void *object,
struct pw_client *client = resource->client; struct pw_client *client = resource->client;
pw_log_error("can't create link"); pw_log_error("can't create link");
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
resource->id, SPA_RESULT_NOT_IMPLEMENTED, "not implemented"); resource->id, SPA_RESULT_NOT_IMPLEMENTED, "not implemented");
} }
@ -241,6 +256,7 @@ static void core_update_types(void *object, uint32_t first_id, uint32_t n_types,
} }
static const struct pw_core_methods core_methods = { static const struct pw_core_methods core_methods = {
PW_VERSION_CORE_METHODS,
&core_update_types, &core_update_types,
&core_sync, &core_sync,
&core_get_registry, &core_get_registry,
@ -257,26 +273,27 @@ static void core_unbind_func(void *data)
} }
static int static int
core_bind_func(struct pw_global *global, struct pw_client *client, uint32_t version, uint32_t id) core_bind_func(struct pw_global *global,
struct pw_client *client,
uint32_t version,
uint32_t id)
{ {
struct pw_core *this = global->object; struct pw_core *this = global->object;
struct pw_resource *resource; struct pw_resource *resource;
resource = pw_resource_new(client, id, global->type, version, 0); resource = pw_resource_new(client, id, global->type, version, 0, core_unbind_func);
if (resource == NULL) if (resource == NULL)
goto no_mem; goto no_mem;
pw_resource_set_implementation(resource, global->object, pw_resource_set_implementation(resource, resource, &core_methods);
PW_VERSION_CORE, &core_methods, core_unbind_func);
spa_list_insert(this->resource_list.prev, &resource->link); spa_list_insert(this->resource_list.prev, &resource->link);
client->core_resource = resource; client->core_resource = resource;
pw_log_debug("core %p: bound to %d", global->object, resource->id); pw_log_debug("core %p: bound to %d", this, resource->id);
this->info.change_mask = PW_CORE_CHANGE_MASK_ALL; this->info.change_mask = PW_CORE_CHANGE_MASK_ALL;
pw_core_notify_info(resource, &this->info); pw_core_resource_info(resource, &this->info);
this->info.change_mask = 0;
return SPA_RESULT_OK; return SPA_RESULT_OK;
@ -343,9 +360,8 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, struct pw_properties *pro
pw_signal_init(&this->global_removed); pw_signal_init(&this->global_removed);
pw_core_add_global(this, NULL, this->type.core, PW_VERSION_CORE, pw_core_add_global(this, NULL, this->type.core, PW_VERSION_CORE,
this, core_bind_func, &this->global); core_bind_func, this, &this->global);
this->info.id = this->global->id;
this->info.change_mask = 0; this->info.change_mask = 0;
this->info.user_name = pw_get_user_name(); this->info.user_name = pw_get_user_name();
this->info.host_name = pw_get_host_name(); this->info.host_name = pw_get_host_name();
@ -397,7 +413,8 @@ void pw_core_destroy(struct pw_core *core)
* \param core a core * \param core a core
* \param owner an optional owner of the global * \param owner an optional owner of the global
* \param type the type of the global * \param type the type of the global
* \param version the version * \param n_ifaces number of interfaces
* \param ifaces interface information
* \param object the associated object * \param object the associated object
* \param bind a function to bind to this global * \param bind a function to bind to this global
* \param[out] global a result global * \param[out] global a result global
@ -410,25 +427,26 @@ pw_core_add_global(struct pw_core *core,
struct pw_resource *owner, struct pw_resource *owner,
uint32_t type, uint32_t type,
uint32_t version, uint32_t version,
void *object,
pw_bind_func_t bind, pw_bind_func_t bind,
void *object,
struct pw_global **global) struct pw_global **global)
{ {
struct global_impl *impl; struct global_impl *impl;
struct pw_global *this; struct pw_global *this;
struct pw_resource *registry; struct pw_resource *registry;
const char *type_name;
impl = calloc(1, sizeof(struct global_impl)); impl = calloc(1, sizeof(struct global_impl));
if (impl == NULL) if (impl == NULL)
return false; return false;
this = &impl->this; this = &impl->this;
impl->bind = bind;
this->core = core; this->core = core;
this->owner = owner; this->owner = owner;
this->type = type; this->type = type;
this->version = version; this->version = version;
this->bind = bind;
this->object = object; this->object = object;
*global = this; *global = this;
@ -439,11 +457,13 @@ pw_core_add_global(struct pw_core *core,
spa_list_insert(core->global_list.prev, &this->link); spa_list_insert(core->global_list.prev, &this->link);
pw_signal_emit(&core->global_added, core, this); pw_signal_emit(&core->global_added, core, this);
pw_log_debug("global %p: new %u %d, owner %p", this, this->id, this->type, owner); type_name = spa_type_map_get_type(core->type.map, this->type);
pw_log_debug("global %p: new %u %s, owner %p", this, this->id, type_name, owner);
spa_list_for_each(registry, &core->registry_resource_list, link) spa_list_for_each(registry, &core->registry_resource_list, link)
if (pw_global_is_visible(this, registry->client)) if (pw_global_is_visible(this, registry->client))
pw_registry_notify_global(registry, this->id, this->type, this->version); pw_registry_resource_global(registry, this->id, this->type, this->version);
return true; return true;
} }
@ -462,18 +482,33 @@ pw_core_add_global(struct pw_core *core,
* \memberof pw_global * \memberof pw_global
*/ */
int int
pw_global_bind(struct pw_global *global, struct pw_client *client, uint32_t version, uint32_t id) pw_global_bind(struct pw_global *global, struct pw_client *client,
uint32_t version, uint32_t id)
{ {
int res; int res;
struct global_impl *impl = SPA_CONTAINER_OF(global, struct global_impl, this);
if (impl->bind) { if (global->bind == NULL)
res = impl->bind(global, client, version, id); goto no_bind;
} else {
if (global->version < version)
goto wrong_version;
res = global->bind(global, client, version, id);
return res;
wrong_version:
res = SPA_RESULT_INCOMPATIBLE_VERSION;
pw_core_resource_error(client->core_resource,
client->core_resource->id,
res, "id %d: interface version %d < %d",
id, global->version, version);
return res;
no_bind:
res = SPA_RESULT_NOT_IMPLEMENTED; res = SPA_RESULT_NOT_IMPLEMENTED;
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
client->core_resource->id, res, "can't bind object id %d", id); client->core_resource->id,
} res, "can't bind object id %d to interface", id);
return res; return res;
} }
@ -493,7 +528,7 @@ void pw_global_destroy(struct pw_global *global)
spa_list_for_each(registry, &core->registry_resource_list, link) spa_list_for_each(registry, &core->registry_resource_list, link)
if (pw_global_is_visible(global, registry->client)) if (pw_global_is_visible(global, registry->client))
pw_registry_notify_global_remove(registry, global->id); pw_registry_resource_global_remove(registry, global->id);
pw_map_remove(&core->objects, global->id); pw_map_remove(&core->objects, global->id);
@ -534,7 +569,7 @@ void pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict
pw_signal_emit(&core->info_changed, core); pw_signal_emit(&core->info_changed, core);
spa_list_for_each(resource, &core->resource_list, link) { spa_list_for_each(resource, &core->resource_list, link) {
pw_core_notify_info(resource, &core->info); pw_core_resource_info(resource, &core->info);
} }
core->info.change_mask = 0; core->info.change_mask = 0;
} }

View file

@ -37,12 +37,6 @@ struct pw_global;
#include <pipewire/node.h> #include <pipewire/node.h>
#include <pipewire/node-factory.h> #include <pipewire/node-factory.h>
#define PW_TYPE__Core PW_TYPE_OBJECT_BASE "Core"
#define PW_TYPE_CORE_BASE PW_TYPE__Core ":"
#define PW_TYPE__Registry PW_TYPE_OBJECT_BASE "Registry"
#define PW_TYPE_REGISTRY_BASE PW_TYPE__Registry ":"
/** \page page_server_api Server API /** \page page_server_api Server API
* *
* \section page_server_overview Overview * \section page_server_overview Overview
@ -96,8 +90,10 @@ struct pw_global;
* emit events to the client and lets the client invoke methods on * emit events to the client and lets the client invoke methods on
* the object. * the object.
*/ */
typedef int (*pw_bind_func_t) (struct pw_global *global, typedef int (*pw_bind_func_t) (struct pw_global *global, /**< the global to bind */
struct pw_client *client, uint32_t version, uint32_t id); struct pw_client *client, /**< client that binds */
uint32_t version, /**< client interface version */
uint32_t id); /**< client proxy id */
typedef bool (*pw_global_filter_func_t) (struct pw_global *global, typedef bool (*pw_global_filter_func_t) (struct pw_global *global,
struct pw_client *client, void *data); struct pw_client *client, void *data);
@ -131,9 +127,12 @@ struct pw_global {
struct spa_list link; /**< link in core list of globals */ struct spa_list link; /**< link in core list of globals */
uint32_t id; /**< server id of the object */ uint32_t id; /**< server id of the object */
uint32_t type; /**< type of the object */
uint32_t version; /**< version of the object */ uint32_t type; /**< type of interface */
void *object; /**< object associated with the global */ uint32_t version; /**< version of interface */
pw_bind_func_t bind; /**< function to bind to the interface */
void *object; /**< object associated with the interface */
/** Emited when the global is destroyed */ /** Emited when the global is destroyed */
PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_global *global)); PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_global *global));
@ -210,12 +209,15 @@ pw_core_add_global(struct pw_core *core,
struct pw_resource *owner, struct pw_resource *owner,
uint32_t type, uint32_t type,
uint32_t version, uint32_t version,
void *object, pw_bind_func_t bind, pw_bind_func_t bind,
void *object,
struct pw_global **global); struct pw_global **global);
int int
pw_global_bind(struct pw_global *global, pw_global_bind(struct pw_global *global,
struct pw_client *client, uint32_t version, uint32_t id); struct pw_client *client,
uint32_t version,
uint32_t id);
void void
pw_global_destroy(struct pw_global *global); pw_global_destroy(struct pw_global *global);

View file

@ -30,7 +30,18 @@ extern "C" {
#include <spa/param-alloc.h> #include <spa/param-alloc.h>
#include <spa/node.h> #include <spa/node.h>
#include <pipewire/type.h>
#include <pipewire/introspect.h> #include <pipewire/introspect.h>
#include <pipewire/proxy.h>
#include <pipewire/remote.h>
#include <pipewire/core.h>
struct pw_core_proxy { struct pw_proxy proxy; };
struct pw_registry_proxy { struct pw_proxy proxy; };
struct pw_module_proxy { struct pw_proxy proxy; };
struct pw_node_proxy { struct pw_proxy proxy; };
struct pw_client_proxy { struct pw_proxy proxy; };
struct pw_link_proxy { struct pw_proxy proxy; };
/** /**
* \page page_pipewire_protocol The PipeWire protocol * \page page_pipewire_protocol The PipeWire protocol
@ -48,6 +59,15 @@ extern "C" {
* \section page_iface_pw_core API * \section page_iface_pw_core API
*/ */
/** Core */
#define PW_TYPE_INTERFACE__Core PW_TYPE_INTERFACE_BASE "Core"
#define PW_TYPE_INTERFACE__Registry PW_TYPE_INTERFACE_BASE "Registry"
#define PW_TYPE_INTERFACE__Module PW_TYPE_INTERFACE_BASE "Module"
#define PW_TYPE_INTERFACE__Node PW_TYPE_INTERFACE_BASE "Node"
#define PW_TYPE_INTERFACE__Client PW_TYPE_INTERFACE_BASE "Client"
#define PW_TYPE_INTERFACE__Link PW_TYPE_INTERFACE_BASE "Link"
#define PW_VERSION_CORE 0 #define PW_VERSION_CORE 0
#define PW_CORE_METHOD_UPDATE_TYPES 0 #define PW_CORE_METHOD_UPDATE_TYPES 0
@ -67,6 +87,8 @@ extern "C" {
* for internal features. * for internal features.
*/ */
struct pw_core_methods { struct pw_core_methods {
#define PW_VERSION_CORE_METHODS 0
uint32_t version;
/** /**
* Update the type map * Update the type map
* *
@ -111,15 +133,17 @@ struct pw_core_methods {
* *
* \param factory_name the factory name to use * \param factory_name the factory name to use
* \param name the node name * \param name the node name
* \param props extra properties * \param type the interface to bind to
* \param version the version of the interface * \param version the version of the interface
* \param props extra properties
* \param new_id the client proxy id * \param new_id the client proxy id
*/ */
void (*create_node) (void *object, void (*create_node) (void *object,
const char *factory_name, const char *factory_name,
const char *name, const char *name,
const struct spa_dict *props, uint32_t type,
uint32_t version, uint32_t version,
const struct spa_dict *props,
uint32_t new_id); uint32_t new_id);
/** /**
* Create a new link between two node ports * Create a new link between two node ports
@ -142,12 +166,69 @@ struct pw_core_methods {
uint32_t new_id); uint32_t new_id);
}; };
#define pw_core_do_update_types(p,...) pw_proxy_do(p,struct pw_core_methods,update_types,__VA_ARGS__) static inline void
#define pw_core_do_sync(p,...) pw_proxy_do(p,struct pw_core_methods,sync,__VA_ARGS__) pw_core_proxy_update_types(struct pw_core_proxy *core, uint32_t first_id, uint32_t n_types, const char **types)
#define pw_core_do_get_registry(p,...) pw_proxy_do(p,struct pw_core_methods,get_registry,__VA_ARGS__) {
#define pw_core_do_client_update(p,...) pw_proxy_do(p,struct pw_core_methods,client_update,__VA_ARGS__) pw_proxy_do(&core->proxy, struct pw_core_methods, update_types, first_id, n_types, types);
#define pw_core_do_create_node(p,...) pw_proxy_do(p,struct pw_core_methods,create_node,__VA_ARGS__) }
#define pw_core_do_create_link(p,...) pw_proxy_do(p,struct pw_core_methods,create_link,__VA_ARGS__)
static inline void
pw_core_proxy_sync(struct pw_core_proxy *core, uint32_t seq)
{
pw_proxy_do(&core->proxy, struct pw_core_methods, sync, seq);
}
static inline struct pw_registry_proxy *
pw_core_proxy_get_registry(struct pw_core_proxy *core, uint32_t version, size_t user_data_size, pw_destroy_t destroy)
{
struct pw_core *c = core->proxy.remote->core;
struct pw_proxy *p = pw_proxy_new(core->proxy.remote, SPA_ID_INVALID, c->type.registry,
user_data_size, destroy);
pw_proxy_do(&core->proxy, struct pw_core_methods, get_registry, version, p->id);
return (struct pw_registry_proxy *) p;
}
static inline void
pw_core_proxy_client_update(struct pw_core_proxy *core, const struct spa_dict *props)
{
pw_proxy_do(&core->proxy, struct pw_core_methods, client_update, props);
}
static inline void *
pw_core_proxy_create_node(struct pw_core_proxy *core,
const char *factory_name,
const char *name,
uint32_t type,
uint32_t version,
const struct spa_dict *props,
size_t user_data_size,
pw_destroy_t destroy)
{
struct pw_proxy *p = pw_proxy_new(core->proxy.remote, SPA_ID_INVALID, type, user_data_size, destroy);
pw_proxy_do(&core->proxy, struct pw_core_methods, create_node, factory_name,
name, type, version, props, p->id);
return p;
}
static inline struct pw_link_proxy *
pw_core_proxy_create_link(struct pw_core_proxy *core,
uint32_t output_node_id,
uint32_t output_port_id,
uint32_t input_node_id,
uint32_t input_port_id,
const struct spa_format *filter,
const struct spa_dict *prop,
size_t user_data_size,
pw_destroy_t destroy)
{
struct pw_core *c = core->proxy.remote->core;
struct pw_proxy *p = pw_proxy_new(core->proxy.remote, SPA_ID_INVALID, c->type.link,
user_data_size, destroy);
pw_proxy_do(&core->proxy, struct pw_core_methods, create_link, output_node_id, output_port_id,
input_node_id, input_port_id, filter, prop, p->id);
return (struct pw_link_proxy*) p;
}
#define PW_CORE_EVENT_UPDATE_TYPES 0 #define PW_CORE_EVENT_UPDATE_TYPES 0
#define PW_CORE_EVENT_DONE 1 #define PW_CORE_EVENT_DONE 1
@ -161,6 +242,8 @@ struct pw_core_methods {
* \ingroup pw_core_interface The pw_core interface * \ingroup pw_core_interface The pw_core interface
*/ */
struct pw_core_events { struct pw_core_events {
#define PW_VERSION_CORE_EVENTS 0
uint32_t version;
/** /**
* Update the type map * Update the type map
* *
@ -214,11 +297,21 @@ struct pw_core_events {
void (*info) (void *object, struct pw_core_info *info); void (*info) (void *object, struct pw_core_info *info);
}; };
#define pw_core_notify_update_types(r,...) pw_resource_notify(r,struct pw_core_events,update_types,__VA_ARGS__) static inline void
#define pw_core_notify_done(r,...) pw_resource_notify(r,struct pw_core_events,done,__VA_ARGS__) pw_core_proxy_add_listener(struct pw_core_proxy *core,
#define pw_core_notify_error(r,...) pw_resource_notify(r,struct pw_core_events,error,__VA_ARGS__) void *object, const struct pw_core_events *events)
#define pw_core_notify_remove_id(r,...) pw_resource_notify(r,struct pw_core_events,remove_id,__VA_ARGS__) {
#define pw_core_notify_info(r,...) pw_resource_notify(r,struct pw_core_events,info,__VA_ARGS__) pw_proxy_add_listener(&core->proxy, object, events);
}
#define pw_core_resource_update_types(r,...) pw_resource_notify(r,struct pw_core_events,update_types,__VA_ARGS__)
#define pw_core_resource_done(r,...) pw_resource_notify(r,struct pw_core_events,done,__VA_ARGS__)
#define pw_core_resource_error(r,...) pw_resource_notify(r,struct pw_core_events,error,__VA_ARGS__)
#define pw_core_resource_remove_id(r,...) pw_resource_notify(r,struct pw_core_events,remove_id,__VA_ARGS__)
#define pw_core_resource_info(r,...) pw_resource_notify(r,struct pw_core_events,info,__VA_ARGS__)
#define PW_VERSION_REGISTRY 0 #define PW_VERSION_REGISTRY 0
@ -227,6 +320,8 @@ struct pw_core_events {
/** Registry methods */ /** Registry methods */
struct pw_registry_methods { struct pw_registry_methods {
#define PW_VERSION_REGISTRY_METHODS 0
uint32_t version;
/** /**
* Bind to a global object * Bind to a global object
* *
@ -235,13 +330,24 @@ struct pw_registry_methods {
* send to the remote global object and events can be received * send to the remote global object and events can be received
* *
* \param id the global id to bind to * \param id the global id to bind to
* \param version the version to use * \param type the interface type to bind to
* \param version the interface version to use
* \param new_id the client proxy to use * \param new_id the client proxy to use
*/ */
void (*bind) (void *object, uint32_t id, uint32_t version, uint32_t new_id); void (*bind) (void *object, uint32_t id, uint32_t type, uint32_t version, uint32_t new_id);
}; };
#define pw_registry_do_bind(p,...) pw_proxy_do(p,struct pw_registry_methods,bind,__VA_ARGS__) /** Registry */
static inline void *
pw_registry_proxy_bind(struct pw_registry_proxy *registry,
uint32_t id, uint32_t type, uint32_t version,
size_t user_data_size, pw_destroy_t destroy)
{
struct pw_proxy *p = pw_proxy_new(registry->proxy.remote, SPA_ID_INVALID,
type, user_data_size, destroy);
pw_proxy_do(&registry->proxy, struct pw_registry_methods, bind, id, type, version, p->id);
return p;
}
#define PW_REGISTRY_EVENT_GLOBAL 0 #define PW_REGISTRY_EVENT_GLOBAL 0
#define PW_REGISTRY_EVENT_GLOBAL_REMOVE 1 #define PW_REGISTRY_EVENT_GLOBAL_REMOVE 1
@ -249,6 +355,8 @@ struct pw_registry_methods {
/** Registry events */ /** Registry events */
struct pw_registry_events { struct pw_registry_events {
#define PW_VERSION_REGISTRY_EVENTS 0
uint32_t version;
/** /**
* Notify of a new global object * Notify of a new global object
* *
@ -256,8 +364,8 @@ struct pw_registry_events {
* available. * available.
* *
* \param id the global object id * \param id the global object id
* \param type the type of the object * \param type the type of the interface
* \param version the version of the object * \param version the version of the interface
*/ */
void (*global) (void *object, uint32_t id, uint32_t type, uint32_t version); void (*global) (void *object, uint32_t id, uint32_t type, uint32_t version);
/** /**
@ -272,8 +380,16 @@ struct pw_registry_events {
void (*global_remove) (void *object, uint32_t id); void (*global_remove) (void *object, uint32_t id);
}; };
#define pw_registry_notify_global(r,...) pw_resource_notify(r,struct pw_registry_events,global,__VA_ARGS__) static inline void
#define pw_registry_notify_global_remove(r,...) pw_resource_notify(r,struct pw_registry_events,global_remove,__VA_ARGS__) pw_registry_proxy_add_listener(struct pw_registry_proxy *registry,
void *object, const struct pw_registry_events *events)
{
pw_proxy_add_listener(&registry->proxy, object, events);
}
#define pw_registry_resource_global(r,...) pw_resource_notify(r,struct pw_registry_events,global,__VA_ARGS__)
#define pw_registry_resource_global_remove(r,...) pw_resource_notify(r,struct pw_registry_events,global_remove,__VA_ARGS__)
#define PW_VERSION_MODULE 0 #define PW_VERSION_MODULE 0
@ -282,6 +398,8 @@ struct pw_registry_events {
/** Module events */ /** Module events */
struct pw_module_events { struct pw_module_events {
#define PW_VERSION_MODULE_EVENTS 0
uint32_t version;
/** /**
* Notify module info * Notify module info
* *
@ -290,7 +408,14 @@ struct pw_module_events {
void (*info) (void *object, struct pw_module_info *info); void (*info) (void *object, struct pw_module_info *info);
}; };
#define pw_module_notify_info(r,...) pw_resource_notify(r,struct pw_module_events,info,__VA_ARGS__) static inline void
pw_module_proxy_add_listener(struct pw_module_proxy *module,
void *object, const struct pw_module_events *events)
{
pw_proxy_add_listener(&module->proxy, object, events);
}
#define pw_module_resource_info(r,...) pw_resource_notify(r,struct pw_module_events,info,__VA_ARGS__)
#define PW_VERSION_NODE 0 #define PW_VERSION_NODE 0
@ -299,6 +424,8 @@ struct pw_module_events {
/** Node events */ /** Node events */
struct pw_node_events { struct pw_node_events {
#define PW_VERSION_NODE_EVENTS 0
uint32_t version;
/** /**
* Notify node info * Notify node info
* *
@ -307,7 +434,14 @@ struct pw_node_events {
void (*info) (void *object, struct pw_node_info *info); void (*info) (void *object, struct pw_node_info *info);
}; };
#define pw_node_notify_info(r,...) pw_resource_notify(r,struct pw_node_events,info,__VA_ARGS__) static inline void
pw_node_proxy_add_listener(struct pw_node_proxy *node,
void *object, const struct pw_node_events *events)
{
pw_proxy_add_listener(&node->proxy, object, events);
}
#define pw_node_resource_info(r,...) pw_resource_notify(r,struct pw_node_events,info,__VA_ARGS__)
#define PW_VERSION_CLIENT 0 #define PW_VERSION_CLIENT 0
@ -316,6 +450,8 @@ struct pw_node_events {
/** Client events */ /** Client events */
struct pw_client_events { struct pw_client_events {
#define PW_VERSION_CLIENT_EVENTS 0
uint32_t version;
/** /**
* Notify client info * Notify client info
* *
@ -324,7 +460,16 @@ struct pw_client_events {
void (*info) (void *object, struct pw_client_info *info); void (*info) (void *object, struct pw_client_info *info);
}; };
#define pw_client_notify_info(r,...) pw_resource_notify(r,struct pw_client_events,info,__VA_ARGS__) /** Client */
static inline void
pw_client_proxy_add_listener(struct pw_client_proxy *client,
void *object, const struct pw_client_events *events)
{
pw_proxy_add_listener(&client->proxy, object, events);
}
#define pw_client_resource_info(r,...) pw_resource_notify(r,struct pw_client_events,info,__VA_ARGS__)
#define PW_VERSION_LINK 0 #define PW_VERSION_LINK 0
@ -333,6 +478,8 @@ struct pw_client_events {
/** Link events */ /** Link events */
struct pw_link_events { struct pw_link_events {
#define PW_VERSION_LINK_EVENTS 0
uint32_t version;
/** /**
* Notify link info * Notify link info
* *
@ -341,7 +488,15 @@ struct pw_link_events {
void (*info) (void *object, struct pw_link_info *info); void (*info) (void *object, struct pw_link_info *info);
}; };
#define pw_link_notify_info(r,...) pw_resource_notify(r,struct pw_link_events,info,__VA_ARGS__) /** Link */
static inline void
pw_link_proxy_add_listener(struct pw_link_proxy *link,
void *object, const struct pw_link_events *events)
{
pw_proxy_add_listener(&link->proxy, object, events);
}
#define pw_link_resource_info(r,...) pw_resource_notify(r,struct pw_link_events,info,__VA_ARGS__)
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View file

@ -125,7 +125,6 @@ struct pw_core_info *pw_core_info_update(struct pw_core_info *info,
if (info == NULL) if (info == NULL)
return NULL; return NULL;
} }
info->id = update->id;
info->change_mask = update->change_mask; info->change_mask = update->change_mask;
if (update->change_mask & (1 << 0)) { if (update->change_mask & (1 << 0)) {
@ -186,7 +185,6 @@ struct pw_node_info *pw_node_info_update(struct pw_node_info *info,
if (info == NULL) if (info == NULL)
return NULL; return NULL;
} }
info->id = update->id;
info->change_mask = update->change_mask; info->change_mask = update->change_mask;
if (update->change_mask & (1 << 0)) { if (update->change_mask & (1 << 0)) {
@ -283,7 +281,6 @@ struct pw_module_info *pw_module_info_update(struct pw_module_info *info,
if (info == NULL) if (info == NULL)
return NULL; return NULL;
} }
info->id = update->id;
info->change_mask = update->change_mask; info->change_mask = update->change_mask;
if (update->change_mask & (1 << 0)) { if (update->change_mask & (1 << 0)) {
@ -334,7 +331,6 @@ struct pw_client_info *pw_client_info_update(struct pw_client_info *info,
if (info == NULL) if (info == NULL)
return NULL; return NULL;
} }
info->id = update->id;
info->change_mask = update->change_mask; info->change_mask = update->change_mask;
if (update->change_mask & (1 << 0)) { if (update->change_mask & (1 << 0)) {
@ -363,7 +359,6 @@ struct pw_link_info *pw_link_info_update(struct pw_link_info *info,
if (info == NULL) if (info == NULL)
return NULL; return NULL;
} }
info->id = update->id;
info->change_mask = update->change_mask; info->change_mask = update->change_mask;
if (update->change_mask & (1 << 0)) if (update->change_mask & (1 << 0))

View file

@ -74,7 +74,6 @@ const char * pw_link_state_as_string(enum pw_link_state state);
/** The core information. Extra information can be added in later versions \memberof pw_introspect */ /** The core information. Extra information can be added in later versions \memberof pw_introspect */
struct pw_core_info { struct pw_core_info {
uint32_t id; /**< server side id of the core */
#define PW_CORE_CHANGE_MASK_USER_NAME (1 << 0) #define PW_CORE_CHANGE_MASK_USER_NAME (1 << 0)
#define PW_CORE_CHANGE_MASK_HOST_NAME (1 << 1) #define PW_CORE_CHANGE_MASK_HOST_NAME (1 << 1)
#define PW_CORE_CHANGE_MASK_VERSION (1 << 2) #define PW_CORE_CHANGE_MASK_VERSION (1 << 2)
@ -101,7 +100,6 @@ void pw_core_info_free(struct pw_core_info *info);
/** The module information. Extra information can be added in later versions \memberof pw_introspect */ /** The module information. Extra information can be added in later versions \memberof pw_introspect */
struct pw_module_info { struct pw_module_info {
uint32_t id; /**< server side id of the module */
uint64_t change_mask; /**< bitfield of changed fields since last call */ uint64_t change_mask; /**< bitfield of changed fields since last call */
const char *name; /**< name of the module */ const char *name; /**< name of the module */
const char *filename; /**< filename of the module */ const char *filename; /**< filename of the module */
@ -119,7 +117,6 @@ void pw_module_info_free(struct pw_module_info *info);
/** The client information. Extra information can be added in later versions \memberof pw_introspect */ /** The client information. Extra information can be added in later versions \memberof pw_introspect */
struct pw_client_info { struct pw_client_info {
uint32_t id; /**< server side id of the client */
uint64_t change_mask; /**< bitfield of changed fields since last call */ uint64_t change_mask; /**< bitfield of changed fields since last call */
struct spa_dict *props; /**< extra properties */ struct spa_dict *props; /**< extra properties */
}; };
@ -135,7 +132,6 @@ void pw_client_info_free(struct pw_client_info *info);
/** The node information. Extra information can be added in later versions \memberof pw_introspect */ /** The node information. Extra information can be added in later versions \memberof pw_introspect */
struct pw_node_info { struct pw_node_info {
uint32_t id; /**< server side id of the node */
uint64_t change_mask; /**< bitfield of changed fields since last call */ uint64_t change_mask; /**< bitfield of changed fields since last call */
const char *name; /**< name the node, suitable for display */ const char *name; /**< name the node, suitable for display */
uint32_t max_input_ports; /**< maximum number of inputs */ uint32_t max_input_ports; /**< maximum number of inputs */
@ -161,7 +157,6 @@ pw_node_info_free(struct pw_node_info *info);
/** The link information. Extra information can be added in later versions \memberof pw_introspect */ /** The link information. Extra information can be added in later versions \memberof pw_introspect */
struct pw_link_info { struct pw_link_info {
uint32_t id; /**< server side id of the link */
uint64_t change_mask; /**< bitfield of changed fields since last call */ uint64_t change_mask; /**< bitfield of changed fields since last call */
uint32_t output_node_id; /**< server side output node id */ uint32_t output_node_id; /**< server side output node id */
uint32_t output_port_id; /**< output port id */ uint32_t output_port_id; /**< output port id */

View file

@ -939,30 +939,33 @@ static void link_unbind_func(void *data)
} }
static int static int
link_bind_func(struct pw_global *global, struct pw_client *client, uint32_t version, uint32_t id) link_bind_func(struct pw_global *global,
struct pw_client *client,
uint32_t version, uint32_t id)
{ {
struct pw_link *this = global->object; struct pw_link *this = global->object;
struct pw_resource *resource; struct pw_resource *resource;
resource = pw_resource_new(client, id, global->type, version, 0); resource = pw_resource_new(client, id, global->type, version, 0, link_unbind_func);
if (resource == NULL) if (resource == NULL)
goto no_mem; goto no_mem;
pw_resource_set_implementation(resource, global->object, PW_VERSION_LINK, NULL, link_unbind_func); pw_resource_set_implementation(resource, this, NULL);
pw_log_debug("link %p: bound to %d", global->object, resource->id); pw_log_debug("link %p: bound to %d", this, resource->id);
spa_list_insert(this->resource_list.prev, &resource->link); spa_list_insert(this->resource_list.prev, &resource->link);
this->info.change_mask = ~0; this->info.change_mask = ~0;
pw_link_notify_info(resource, &this->info); pw_link_resource_info(resource, &this->info);
this->info.change_mask = 0;
return SPA_RESULT_OK; return SPA_RESULT_OK;
no_mem: no_mem:
pw_log_error("can't create link resource"); pw_log_error("can't create link resource");
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory"); client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory");
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
} }
@ -1054,9 +1057,8 @@ struct pw_link *pw_link_new(struct pw_core *core,
spa_list_insert(core->link_list.prev, &this->link); spa_list_insert(core->link_list.prev, &this->link);
pw_core_add_global(core, NULL, core->type.link, PW_VERSION_LINK, pw_core_add_global(core, NULL, core->type.link, PW_VERSION_LINK,
this, link_bind_func, &this->global); link_bind_func, this, &this->global);
this->info.id = this->global->id;
this->info.output_node_id = output ? output_node->global->id : -1; this->info.output_node_id = output ? output_node->global->id : -1;
this->info.output_port_id = output ? output->port_id : -1; this->info.output_port_id = output ? output->port_id : -1;
this->info.input_node_id = input ? input_node->global->id : -1; this->info.input_node_id = input ? input_node->global->id : -1;

View file

@ -88,27 +88,30 @@ static char *find_module(const char *path, const char *name)
} }
static int static int
module_bind_func(struct pw_global *global, struct pw_client *client, uint32_t version, uint32_t id) module_bind_func(struct pw_global *global,
struct pw_client *client,
uint32_t version, uint32_t id)
{ {
struct pw_module *this = global->object; struct pw_module *this = global->object;
struct pw_resource *resource; struct pw_resource *resource;
resource = pw_resource_new(client, id, global->type, version, 0); resource = pw_resource_new(client, id, global->type, version, 0, NULL);
if (resource == NULL) if (resource == NULL)
goto no_mem; goto no_mem;
pw_resource_set_implementation(resource, global->object, PW_VERSION_MODULE, NULL, NULL); pw_resource_set_implementation(resource, this, NULL);
pw_log_debug("module %p: bound to %d", global->object, resource->id); pw_log_debug("module %p: bound to %d", this, resource->id);
this->info.change_mask = ~0; this->info.change_mask = ~0;
pw_module_notify_info(resource, &this->info); pw_module_resource_info(resource, &this->info);
this->info.change_mask = 0;
return SPA_RESULT_OK; return SPA_RESULT_OK;
no_mem: no_mem:
pw_log_error("can't create module resource"); pw_log_error("can't create module resource");
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory"); client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory");
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
} }
@ -181,9 +184,8 @@ struct pw_module *pw_module_load(struct pw_core *core,
goto init_failed; goto init_failed;
pw_core_add_global(core, NULL, core->type.module, PW_VERSION_MODULE, pw_core_add_global(core, NULL, core->type.module, PW_VERSION_MODULE,
impl, module_bind_func, &this->global); module_bind_func, this, &this->global);
this->info.id = this->global->id;
this->info.name = name ? strdup(name) : NULL; this->info.name = name ? strdup(name) : NULL;
this->info.filename = filename; this->info.filename = filename;
this->info.args = args ? strdup(args) : NULL; this->info.args = args ? strdup(args) : NULL;

View file

@ -24,8 +24,8 @@
extern "C" { extern "C" {
#endif #endif
#define PW_TYPE__NodeFactory "PipeWire:Object:NodeFactory" #define PW_TYPE_INTERFACE__NodeFactory PW_TYPE_INTERFACE_BASE "NodeFactory"
#define PW_TYPE_NODE_FACTORY_BASE PW_TYPE__NodeFactory ":" #define PW_TYPE_NODE_FACTORY_BASE PW_TYPE_INTERFACE__NodeFactory ":"
#include <pipewire/core.h> #include <pipewire/core.h>
#include <pipewire/resource.h> #include <pipewire/resource.h>
@ -42,7 +42,6 @@ struct pw_node_factory {
struct pw_global *global; /**< global for this factory */ struct pw_global *global; /**< global for this factory */
const char *name; /**< the factory name */ const char *name; /**< the factory name */
uint32_t type; /**< type of the created nodes */
/** Emited when the factory is destroyed */ /** Emited when the factory is destroyed */
PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_node_factory *object)); PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_node_factory *object));

View file

@ -151,7 +151,6 @@ static void node_unbind_func(void *data)
static void static void
update_info(struct pw_node *this) update_info(struct pw_node *this)
{ {
this->info.id = this->global->id;
this->info.input_formats = NULL; this->info.input_formats = NULL;
if (!spa_list_is_empty(&this->input_ports)) { if (!spa_list_is_empty(&this->input_ports)) {
@ -211,30 +210,32 @@ clear_info(struct pw_node *this)
} }
static int static int
node_bind_func(struct pw_global *global, struct pw_client *client, uint32_t version, uint32_t id) node_bind_func(struct pw_global *global,
struct pw_client *client,
uint32_t version, uint32_t id)
{ {
struct pw_node *this = global->object; struct pw_node *this = global->object;
struct pw_resource *resource; struct pw_resource *resource;
resource = pw_resource_new(client, id, global->type, version, 0); resource = pw_resource_new(client, id, global->type, version, 0, node_unbind_func);
if (resource == NULL) if (resource == NULL)
goto no_mem; goto no_mem;
pw_resource_set_implementation(resource, global->object, PW_VERSION_NODE, NULL, node_unbind_func); pw_resource_set_implementation(resource, this, NULL);
pw_log_debug("node %p: bound to %d", this, resource->id); pw_log_debug("node %p: bound to %d", this, resource->id);
spa_list_insert(this->resource_list.prev, &resource->link); spa_list_insert(this->resource_list.prev, &resource->link);
this->info.change_mask = ~0; this->info.change_mask = ~0;
pw_node_notify_info(resource, &this->info); pw_node_resource_info(resource, &this->info);
this->info.change_mask = 0; this->info.change_mask = 0;
return SPA_RESULT_OK; return SPA_RESULT_OK;
no_mem: no_mem:
pw_log_error("can't create node resource"); pw_log_error("can't create node resource");
pw_core_notify_error(client->core_resource, pw_core_resource_error(client->core_resource,
client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory"); client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory");
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
} }
@ -250,6 +251,7 @@ do_node_add(struct spa_loop *loop,
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
void pw_node_export(struct pw_node *this) void pw_node_export(struct pw_node *this)
{ {
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
@ -259,7 +261,7 @@ void pw_node_export(struct pw_node *this)
spa_list_insert(this->core->node_list.prev, &this->link); spa_list_insert(this->core->node_list.prev, &this->link);
pw_core_add_global(this->core, this->owner, this->core->type.node, PW_VERSION_NODE, pw_core_add_global(this->core, this->owner, this->core->type.node, PW_VERSION_NODE,
this, node_bind_func, &this->global); node_bind_func, this, &this->global);
pw_loop_invoke(this->data_loop, do_node_add, 1, 0, NULL, false, this); pw_loop_invoke(this->data_loop, do_node_add, 1, 0, NULL, false, this);
@ -611,7 +613,7 @@ void pw_node_update_state(struct pw_node *node, enum pw_node_state state, char *
node->info.change_mask |= 1 << 5; node->info.change_mask |= 1 << 5;
spa_list_for_each(resource, &node->resource_list, link) spa_list_for_each(resource, &node->resource_list, link)
pw_node_notify_info(resource, &node->info); pw_node_resource_info(resource, &node->info);
node->info.change_mask = 0; node->info.change_mask = 0;
} }
} }

View file

@ -42,10 +42,8 @@ extern "C" {
struct pw_node; struct pw_node;
#define PW_VERSION_NODE_IMPLEMENTATION 0
struct pw_node_implementation { struct pw_node_implementation {
#define PW_VERSION_NODE_IMPLEMENTATION 0
uint32_t version; uint32_t version;
int (*get_props) (struct pw_node *node, struct spa_props **props); int (*get_props) (struct pw_node *node, struct spa_props **props);
@ -71,8 +69,6 @@ struct pw_node_implementation {
* The node object processes data. The node has a list of * The node object processes data. The node has a list of
* input and output ports (\ref page_port) on which it * input and output ports (\ref page_port) on which it
* will receive and send out buffers respectively. * will receive and send out buffers respectively.
*
* The node wraps an SPA node object.
*/ */
/** \class pw_node /** \class pw_node
* *

View file

@ -23,6 +23,12 @@ struct impl {
struct pw_protocol this; struct pw_protocol this;
}; };
struct marshal {
struct spa_list link;
const struct pw_protocol_marshal *marshal;
uint32_t type;
};
struct pw_protocol *pw_protocol_new(struct pw_core *core, struct pw_protocol *pw_protocol_new(struct pw_core *core,
const char *name, const char *name,
size_t user_data_size) size_t user_data_size)
@ -36,7 +42,7 @@ struct pw_protocol *pw_protocol_new(struct pw_core *core,
protocol->core = core; protocol->core = core;
protocol->name = strdup(name); protocol->name = strdup(name);
spa_list_init(&protocol->iface_list); spa_list_init(&protocol->marshal_list);
spa_list_init(&protocol->connection_list); spa_list_init(&protocol->connection_list);
spa_list_init(&protocol->listener_list); spa_list_init(&protocol->listener_list);
@ -55,7 +61,7 @@ struct pw_protocol *pw_protocol_new(struct pw_core *core,
void pw_protocol_destroy(struct pw_protocol *protocol) void pw_protocol_destroy(struct pw_protocol *protocol)
{ {
struct impl *impl = SPA_CONTAINER_OF(protocol, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(protocol, struct impl, this);
struct pw_protocol_iface *iface, *t1; struct marshal *marshal, *t1;
struct pw_protocol_listener *listener, *t2; struct pw_protocol_listener *listener, *t2;
struct pw_protocol_connection *connection, *t3; struct pw_protocol_connection *connection, *t3;
@ -64,8 +70,8 @@ void pw_protocol_destroy(struct pw_protocol *protocol)
spa_list_remove(&protocol->link); spa_list_remove(&protocol->link);
spa_list_for_each_safe(iface, t1, &protocol->iface_list, link) spa_list_for_each_safe(marshal, t1, &protocol->marshal_list, link)
free(iface); free(marshal);
spa_list_for_each_safe(listener, t2, &protocol->listener_list, link) spa_list_for_each_safe(listener, t2, &protocol->listener_list, link)
pw_protocol_listener_destroy(listener); pw_protocol_listener_destroy(listener);
@ -82,41 +88,31 @@ void pw_protocol_destroy(struct pw_protocol *protocol)
} }
void void
pw_protocol_add_interfaces(struct pw_protocol *protocol, pw_protocol_add_marshal(struct pw_protocol *protocol,
const struct pw_interface *client_iface, const struct pw_protocol_marshal *marshal)
const struct pw_interface *server_iface)
{ {
struct pw_protocol_iface *iface; struct marshal *impl;
const char *type;
uint32_t version;
iface = calloc(1, sizeof(struct pw_protocol_iface)); impl = calloc(1, sizeof(struct marshal));
iface->client_iface = client_iface; impl->marshal = marshal;
iface->server_iface = server_iface; impl->type = spa_type_map_get_id (protocol->core->type.map, marshal->type);
spa_list_insert(protocol->iface_list.prev, &iface->link); spa_list_insert(protocol->marshal_list.prev, &impl->link);
type = client_iface ? client_iface->type : server_iface->type; pw_log_info("Add marshal %s:%d to protocol %s", marshal->type, marshal->version, protocol->name);
version = client_iface ? client_iface->version : server_iface->version;
pw_log_info("Add iface %s:%d to protocol %s", type, version, protocol->name);
} }
const struct pw_interface * const struct pw_protocol_marshal *
pw_protocol_get_interface(struct pw_protocol *protocol, pw_protocol_get_marshal(struct pw_protocol *protocol, uint32_t type)
const char *type,
bool server)
{ {
struct pw_protocol_iface *protocol_iface; struct marshal *impl;
if (protocol == NULL) if (protocol == NULL)
return NULL; return NULL;
spa_list_for_each(protocol_iface, &protocol->iface_list, link) { spa_list_for_each(impl, &protocol->marshal_list, link) {
const struct pw_interface *iface = server ? protocol_iface->server_iface : if (impl->type == type)
protocol_iface->client_iface; return impl->marshal;
if (strcmp(iface->type, type) == 0)
return iface;
} }
return NULL; return NULL;
} }

View file

@ -63,10 +63,15 @@ struct pw_protocol_listener {
#define pw_protocol_listener_destroy(l) ((l)->destroy(l)) #define pw_protocol_listener_destroy(l) ((l)->destroy(l))
struct pw_protocol_iface { struct pw_protocol_marshal {
struct spa_list link; const char *type; /**< interface type */
const struct pw_interface *client_iface; uint32_t version; /**< version */
const struct pw_interface *server_iface; uint32_t n_methods; /**< number of methods in the interface */
const void *method_marshal;
const void *method_demarshal;
uint32_t n_events; /**< number of events in the interface */
const void *event_marshal;
const void *event_demarshal;
}; };
struct pw_protocol_implementaton { struct pw_protocol_implementaton {
@ -86,7 +91,7 @@ struct pw_protocol {
char *name; /**< type name of the protocol */ char *name; /**< type name of the protocol */
struct spa_list iface_list; /**< list of supported interfaces */ struct spa_list marshal_list; /**< list of marshallers for supported interfaces */
struct spa_list connection_list; /**< list of current connections */ struct spa_list connection_list; /**< list of current connections */
struct spa_list listener_list; /**< list of current listeners */ struct spa_list listener_list; /**< list of current listeners */
@ -104,9 +109,7 @@ struct pw_protocol {
#define pw_protocol_new_connection(p,...) ((p)->implementation->new_connection(p,__VA_ARGS__)) #define pw_protocol_new_connection(p,...) ((p)->implementation->new_connection(p,__VA_ARGS__))
#define pw_protocol_add_listener(p,...) ((p)->implementation->add_listener(p,__VA_ARGS__)) #define pw_protocol_add_listener(p,...) ((p)->implementation->add_listener(p,__VA_ARGS__))
#define pw_protocol_ext(p,type,method,...) ((type*)(p)->extension)->method( __VA_ARGS__) #define pw_protocol_ext(p,type,method,...) (((type*)(p)->extension)->method( __VA_ARGS__))
#define pw_protocol_connection_ext(c,type,method,...) ((type*)(c)->protocol->extension)->method( __VA_ARGS__)
#define pw_protocol_listener_ext(l,type,method,...) ((type*)(l)->protocol->extension)->method( __VA_ARGS__)
struct pw_protocol *pw_protocol_new(struct pw_core *core, const char *name, size_t user_data_size); struct pw_protocol *pw_protocol_new(struct pw_core *core, const char *name, size_t user_data_size);
@ -114,13 +117,11 @@ struct pw_protocol *pw_protocol_new(struct pw_core *core, const char *name, size
* *
* \brief Manages protocols and their implementation * \brief Manages protocols and their implementation
*/ */
void void pw_protocol_add_marshal(struct pw_protocol *protocol,
pw_protocol_add_interfaces(struct pw_protocol *protocol, const struct pw_protocol_marshal *marshal);
const struct pw_interface *client_iface,
const struct pw_interface *server_iface);
const struct pw_interface * const struct pw_protocol_marshal *
pw_protocol_get_interface(struct pw_protocol *protocol, const char *type, bool server); pw_protocol_get_marshal(struct pw_protocol *protocol, uint32_t type);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View file

@ -20,6 +20,7 @@
#include <pipewire/log.h> #include <pipewire/log.h>
#include <pipewire/proxy.h> #include <pipewire/proxy.h>
#include <pipewire/core.h> #include <pipewire/core.h>
#include <pipewire/remote.h>
/** \cond */ /** \cond */
struct proxy { struct proxy {
@ -42,8 +43,10 @@ struct proxy {
* \memberof pw_proxy * \memberof pw_proxy
*/ */
struct pw_proxy *pw_proxy_new(struct pw_remote *remote, struct pw_proxy *pw_proxy_new(struct pw_remote *remote,
uint32_t id, uint32_t type, uint32_t id,
size_t user_data_size) uint32_t type,
size_t user_data_size,
pw_destroy_t destroy)
{ {
struct proxy *impl; struct proxy *impl;
struct pw_proxy *this; struct pw_proxy *this;
@ -54,7 +57,6 @@ struct pw_proxy *pw_proxy_new(struct pw_remote *remote,
this = &impl->this; this = &impl->this;
this->remote = remote; this->remote = remote;
this->type = type;
pw_signal_init(&this->destroy_signal); pw_signal_init(&this->destroy_signal);
@ -64,13 +66,13 @@ struct pw_proxy *pw_proxy_new(struct pw_remote *remote,
goto in_use; goto in_use;
this->id = id; this->id = id;
this->type = type;
this->destroy = destroy;
if (user_data_size > 0) if (user_data_size > 0)
this->user_data = SPA_MEMBER(impl, sizeof(struct proxy), void); this->user_data = SPA_MEMBER(impl, sizeof(struct proxy), void);
this->iface = pw_protocol_get_interface(remote->conn->protocol, this->marshal = pw_protocol_get_marshal(remote->conn->protocol, type);
spa_type_map_get_type(remote->core->type.map, type),
false);
spa_list_insert(&this->remote->proxy_list, &this->link); spa_list_insert(&this->remote->proxy_list, &this->link);
@ -84,17 +86,11 @@ struct pw_proxy *pw_proxy_new(struct pw_remote *remote,
return NULL; return NULL;
} }
int pw_proxy_set_implementation(struct pw_proxy *proxy, void pw_proxy_add_listener(struct pw_proxy *proxy,
void *object, void *object, const void *listener)
uint32_t version,
const void *implementation,
pw_destroy_t destroy)
{ {
proxy->object = object; proxy->object = object;
proxy->version = version; proxy->listener = listener;
proxy->implementation = implementation;
proxy->destroy = destroy;
return SPA_RESULT_OK;
} }
/** Destroy a proxy object /** Destroy a proxy object

View file

@ -26,7 +26,8 @@ extern "C" {
#include <pipewire/type.h> #include <pipewire/type.h>
#include <pipewire/utils.h> #include <pipewire/utils.h>
#include <pipewire/remote.h>
struct pw_remote;
/** \page page_proxy Proxy /** \page page_proxy Proxy
* *
@ -82,7 +83,7 @@ extern "C" {
* A pw_proxy acts as a client side proxy to an object existing in the * A pw_proxy acts as a client side proxy to an object existing in the
* pipewire server. The proxy is responsible for converting interface functions * pipewire server. The proxy is responsible for converting interface functions
* invoked by the client to PipeWire messages. Events will call the handlers * invoked by the client to PipeWire messages. Events will call the handlers
* set in implementation. * set in listener.
* *
* See \ref page_proxy * See \ref page_proxy
*/ */
@ -91,39 +92,40 @@ struct pw_proxy {
struct spa_list link; /**< link in the remote */ struct spa_list link; /**< link in the remote */
uint32_t id; /**< client side id */ uint32_t id; /**< client side id */
uint32_t type; /**< object type id */ uint32_t type; /**< type id */
const struct pw_interface *iface; /**< methods/events marshal/demarshal functions */
void *object; /**< client side object */ const void *listener; /**< event listener */
uint32_t version; void *object; /**< object associated with proxy */
const void *implementation; /**< event handler implementation */
pw_destroy_t destroy; /**< optional destroy function to clean up the object */ const struct pw_protocol_marshal *marshal; /**< protocol specific marshal functions */
/** destroy is emited when the proxy is destroyed */ /** destroy is emited when the proxy is destroyed */
PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_proxy *proxy)); PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_proxy *proxy));
void *user_data; /**< extra user data */ void *user_data; /**< extra user data */
pw_destroy_t destroy; /**< optional destroy function to clean up the user_data */
}; };
/** Make a new proxy object. The id can be used to bind to a remote object. */
struct pw_proxy * struct pw_proxy *
pw_proxy_new(struct pw_remote *remote, pw_proxy_new(struct pw_remote *remote, /**< remote this proxy is from */
uint32_t id, uint32_t id, /**< local id, SPA_ID_INVALID to have one automatically
uint32_t type, * allocated for you */
size_t user_data_size); uint32_t type, /**< interface type id */
size_t user_data_size, /**< size of user data */
pw_destroy_t destroy /**< destroy function for user data */);
int void
pw_proxy_set_implementation(struct pw_proxy *proxy, pw_proxy_add_listener(struct pw_proxy *proxy, /**< the proxy */
void *object, void *object, /**< object associated with proxy */
uint32_t version, const void *events /**< events */);
const void *implementation,
pw_destroy_t destroy);
void pw_proxy_destroy(struct pw_proxy *proxy); void pw_proxy_destroy(struct pw_proxy *proxy);
#define pw_proxy_notify(p,type,event,...) ((type*) (p)->implementation)->event(p, __VA_ARGS__) #define pw_proxy_notify(p,type,event,...) ((type*) (p)->listener)->event(p, __VA_ARGS__)
#define pw_proxy_notify_na(p,type,event) ((type*) (p)->implementation)->event(p) #define pw_proxy_notify_na(p,type,event) ((type*) (p)->listener)->event(p)
#define pw_proxy_do(p,type,method,...) ((type*) (p)->iface->methods)->method(p, __VA_ARGS__) #define pw_proxy_do(p,type,method,...) ((type*) (p)->marshal->method_marshal)->method(p, __VA_ARGS__)
#define pw_proxy_do_na(p,type,method) ((type*) (p)->iface->methods)->method(p) #define pw_proxy_do_na(p,type,method) ((type*) (p)->marshal->method_marshal)->method(p)
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -87,7 +87,7 @@ remote_update_state(struct pw_remote *remote, enum pw_remote_state state, const
static void core_event_info(void *object, struct pw_core_info *info) static void core_event_info(void *object, struct pw_core_info *info)
{ {
struct pw_proxy *proxy = object; struct pw_proxy *proxy = object;
struct pw_remote *this = proxy->remote; struct pw_remote *this = proxy->object;
pw_log_debug("got core info"); pw_log_debug("got core info");
this->info = pw_core_info_update(this->info, info); this->info = pw_core_info_update(this->info, info);
@ -97,7 +97,7 @@ static void core_event_info(void *object, struct pw_core_info *info)
static void core_event_done(void *object, uint32_t seq) static void core_event_done(void *object, uint32_t seq)
{ {
struct pw_proxy *proxy = object; struct pw_proxy *proxy = object;
struct pw_remote *this = proxy->remote; struct pw_remote *this = proxy->object;
pw_log_debug("core event done %d", seq); pw_log_debug("core event done %d", seq);
if (seq == 0) if (seq == 0)
@ -109,15 +109,14 @@ static void core_event_done(void *object, uint32_t seq)
static void core_event_error(void *object, uint32_t id, int res, const char *error, ...) static void core_event_error(void *object, uint32_t id, int res, const char *error, ...)
{ {
struct pw_proxy *proxy = object; struct pw_proxy *proxy = object;
struct pw_remote *this = proxy->remote; struct pw_remote *this = proxy->object;
remote_update_state(this, PW_REMOTE_STATE_ERROR, error); remote_update_state(this, PW_REMOTE_STATE_ERROR, error);
} }
static void core_event_remove_id(void *object, uint32_t id) static void core_event_remove_id(void *object, uint32_t id)
{ {
struct pw_proxy *core_proxy = object; struct pw_proxy *proxy = object;
struct pw_remote *this = core_proxy->remote; struct pw_remote *this = proxy->object;
struct pw_proxy *proxy;
proxy = pw_map_lookup(&this->objects, id); proxy = pw_map_lookup(&this->objects, id);
if (proxy) { if (proxy) {
@ -130,7 +129,7 @@ static void
core_event_update_types(void *object, uint32_t first_id, uint32_t n_types, const char **types) core_event_update_types(void *object, uint32_t first_id, uint32_t n_types, const char **types)
{ {
struct pw_proxy *proxy = object; struct pw_proxy *proxy = object;
struct pw_remote *this = proxy->remote; struct pw_remote *this = proxy->object;
int i; int i;
for (i = 0; i < n_types; i++, first_id++) { for (i = 0; i < n_types; i++, first_id++) {
@ -141,6 +140,7 @@ core_event_update_types(void *object, uint32_t first_id, uint32_t n_types, const
} }
static const struct pw_core_events core_events = { static const struct pw_core_events core_events = {
PW_VERSION_CORE_EVENTS,
&core_event_update_types, &core_event_update_types,
&core_event_done, &core_event_done,
&core_event_error, &core_event_error,
@ -230,15 +230,14 @@ void pw_remote_destroy(struct pw_remote *remote)
static int do_connect(struct pw_remote *remote) static int do_connect(struct pw_remote *remote)
{ {
remote->core_proxy = pw_proxy_new(remote, 0, remote->core->type.core, 0); remote->core_proxy = (struct pw_core_proxy*)pw_proxy_new(remote, 0, remote->core->type.core, 0, NULL);
if (remote->core_proxy == NULL) if (remote->core_proxy == NULL)
goto no_proxy; goto no_proxy;
pw_proxy_set_implementation(remote->core_proxy, remote, PW_VERSION_CORE, pw_proxy_add_listener((struct pw_proxy*)remote->core_proxy, remote, &core_events);
&core_events, NULL);
pw_core_do_client_update(remote->core_proxy, &remote->properties->dict); pw_core_proxy_client_update(remote->core_proxy, &remote->properties->dict);
pw_core_do_sync(remote->core_proxy, 0); pw_core_proxy_sync(remote->core_proxy, 0);
return 0; return 0;

View file

@ -24,8 +24,6 @@
extern "C" { extern "C" {
#endif #endif
struct pw_remote;
#include <pipewire/map.h> #include <pipewire/map.h>
#include <pipewire/loop.h> #include <pipewire/loop.h>
#include <pipewire/properties.h> #include <pipewire/properties.h>
@ -123,7 +121,7 @@ struct pw_remote {
struct spa_list link; /**< link in core remote_list */ struct spa_list link; /**< link in core remote_list */
struct pw_properties *properties; /**< extra properties */ struct pw_properties *properties; /**< extra properties */
struct pw_proxy *core_proxy; /**< proxy for the core object */ struct pw_core_proxy *core_proxy; /**< proxy for the core object */
struct pw_map objects; /**< map of client side proxy objects struct pw_map objects; /**< map of client side proxy objects
* indexed with the client id */ * indexed with the client id */
struct pw_core_info *info; /**< info about the remote core */ struct pw_core_info *info; /**< info about the remote core */

View file

@ -32,8 +32,9 @@ struct impl {
struct pw_resource *pw_resource_new(struct pw_client *client, struct pw_resource *pw_resource_new(struct pw_client *client,
uint32_t id, uint32_t id,
uint32_t type, uint32_t type,
uint32_t client_version, uint32_t version,
size_t user_data_size) size_t user_data_size,
pw_destroy_t destroy)
{ {
struct impl *impl; struct impl *impl;
struct pw_resource *this; struct pw_resource *this;
@ -46,7 +47,7 @@ struct pw_resource *pw_resource_new(struct pw_client *client,
this->core = client->core; this->core = client->core;
this->client = client; this->client = client;
this->type = type; this->type = type;
this->client_version = client_version; this->version = version;
pw_signal_init(&this->destroy_signal); pw_signal_init(&this->destroy_signal);
@ -60,9 +61,9 @@ struct pw_resource *pw_resource_new(struct pw_client *client,
if (user_data_size > 0) if (user_data_size > 0)
this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void); this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void);
this->iface = pw_protocol_get_interface(client->protocol, this->destroy = destroy;
spa_type_map_get_type(client->core->type.map, type),
true); this->marshal = pw_protocol_get_marshal(client->protocol, type);
pw_log_debug("resource %p: new for client %p id %u", this, client, id); pw_log_debug("resource %p: new for client %p id %u", this, client, id);
pw_signal_emit(&client->resource_added, client, this); pw_signal_emit(&client->resource_added, client, this);
@ -77,17 +78,12 @@ struct pw_resource *pw_resource_new(struct pw_client *client,
int int
pw_resource_set_implementation(struct pw_resource *resource, pw_resource_set_implementation(struct pw_resource *resource,
void *object, void *object, const void *implementation)
uint32_t version,
const void *implementation,
pw_destroy_t destroy)
{ {
struct pw_client *client = resource->client; struct pw_client *client = resource->client;
resource->object = object; resource->object = object;
resource->version = version;
resource->implementation = implementation; resource->implementation = implementation;
resource->destroy = destroy;
pw_signal_emit(&client->resource_impl, client, resource); pw_signal_emit(&client->resource_impl, client, resource);
return SPA_RESULT_OK; return SPA_RESULT_OK;
@ -107,7 +103,7 @@ void pw_resource_destroy(struct pw_resource *resource)
resource->destroy(resource); resource->destroy(resource);
if (client->core_resource) if (client->core_resource)
pw_core_notify_remove_id(client->core_resource, resource->id); pw_core_resource_remove_id(client->core_resource, resource->id);
free(resource); free(resource);
} }

View file

@ -64,15 +64,16 @@ struct pw_resource {
struct pw_client *client; /**< owner client */ struct pw_client *client; /**< owner client */
uint32_t id; /**< per client unique id, index in client objects */ uint32_t id; /**< per client unique id, index in client objects */
uint32_t type; /**< type id of the object */ uint32_t type; /**< type of the client interface */
uint32_t client_version; /**< version of the client interface */ uint32_t version; /**< version of the client interface */
const struct pw_interface *iface; /**< protocol specific interface functions */
void *object;
const void *implementation;
void *object; /**< pointer to the object */
uint32_t version; /**< interface version */
const void *implementation; /**< method implementation */
pw_destroy_t destroy; /**< function to clean up the object */ pw_destroy_t destroy; /**< function to clean up the object */
const struct pw_protocol_marshal *marshal;
/** Emited when the resource is destroyed */ /** Emited when the resource is destroyed */
PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_resource *resource)); PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_resource *resource));
@ -80,27 +81,27 @@ struct pw_resource {
void *user_data; /**< extra user data */ void *user_data; /**< extra user data */
}; };
/** Make a new resource for client */
struct pw_resource * struct pw_resource *
pw_resource_new(struct pw_client *client, pw_resource_new(struct pw_client *client, /**< the client owning the resource */
uint32_t id, uint32_t id, /**< the remote per client id */
uint32_t type, uint32_t type, /**< interface of the resource */
uint32_t client_version, uint32_t version, /**< requested interface version */
size_t user_data_size); size_t user_data_size, /**< extra user data size */
pw_destroy_t destroy /**< destroy function for user data */);
int int
pw_resource_set_implementation(struct pw_resource *resource, pw_resource_set_implementation(struct pw_resource *resource,
void *object, void *object, const void *implementation);
uint32_t version,
const void *implementation,
pw_destroy_t destroy);
void void
pw_resource_destroy(struct pw_resource *resource); pw_resource_destroy(struct pw_resource *resource);
#define pw_resource_do(r,type,method,...) ((type*) r->implementation)->method(r, __VA_ARGS__) #define pw_resource_do(r,type,method,...) ((type*) r->implementation)->method(r, __VA_ARGS__)
#define pw_resource_do_na(r,type,method) ((type*) r->implementation)->method(r) #define pw_resource_do_na(r,type,method) ((type*) r->implementation)->method(r)
#define pw_resource_notify(r,type,event,...) ((type*) r->iface->events)->event(r, __VA_ARGS__) #define pw_resource_notify(r,type,event,...) ((type*) r->marshal->event_marshal)->event(r, __VA_ARGS__)
#define pw_resource_notify_na(r,type,event) ((type*) r->iface->events)->event(r) #define pw_resource_notify_na(r,type,event) ((type*) r->marshal->event_marshal)->event(r)
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -82,7 +82,7 @@ struct stream {
int rtwritefd; int rtwritefd;
struct spa_source *rtsocket_source; struct spa_source *rtsocket_source;
struct pw_proxy *node_proxy; struct pw_client_node_proxy *node_proxy;
bool disconnecting; bool disconnecting;
struct pw_listener node_proxy_destroy; struct pw_listener node_proxy_destroy;
struct pw_listener node_proxy_sync_done; struct pw_listener node_proxy_sync_done;
@ -204,7 +204,7 @@ struct pw_stream *pw_stream_new(struct pw_remote *remote,
this->remote = remote; this->remote = remote;
this->name = strdup(name); this->name = strdup(name);
impl->type_client_node = spa_type_map_get_id(remote->core->type.map, PW_TYPE__ClientNode); impl->type_client_node = spa_type_map_get_id(remote->core->type.map, PW_TYPE_INTERFACE__ClientNode);
pw_signal_init(&this->destroy_signal); pw_signal_init(&this->destroy_signal);
pw_signal_init(&this->state_changed); pw_signal_init(&this->state_changed);
@ -340,7 +340,7 @@ static void add_node_update(struct pw_stream *stream, uint32_t change_mask)
if (change_mask & PW_CLIENT_NODE_UPDATE_MAX_OUTPUTS) if (change_mask & PW_CLIENT_NODE_UPDATE_MAX_OUTPUTS)
max_output_ports = impl->direction == SPA_DIRECTION_OUTPUT ? 1 : 0; max_output_ports = impl->direction == SPA_DIRECTION_OUTPUT ? 1 : 0;
pw_client_node_do_update(impl->node_proxy, pw_client_node_proxy_update(impl->node_proxy,
change_mask, max_input_ports, max_output_ports, NULL); change_mask, max_input_ports, max_output_ports, NULL);
} }
@ -349,7 +349,7 @@ static void add_port_update(struct pw_stream *stream, uint32_t change_mask)
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this); struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
pw_client_node_do_port_update(impl->node_proxy, pw_client_node_proxy_port_update(impl->node_proxy,
impl->direction, impl->direction,
impl->port_id, impl->port_id,
change_mask, change_mask,
@ -386,7 +386,7 @@ static void add_request_clock_update(struct pw_stream *stream)
{ {
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this); struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
pw_client_node_do_event(impl->node_proxy, (struct spa_event *) pw_client_node_proxy_event(impl->node_proxy, (struct spa_event *)
&SPA_EVENT_NODE_REQUEST_CLOCK_UPDATE_INIT(stream->remote->core->type. &SPA_EVENT_NODE_REQUEST_CLOCK_UPDATE_INIT(stream->remote->core->type.
event_node. event_node.
RequestClockUpdate, RequestClockUpdate,
@ -398,7 +398,7 @@ static void add_async_complete(struct pw_stream *stream, uint32_t seq, int res)
{ {
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this); struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
pw_client_node_do_done(impl->node_proxy, seq, res); pw_client_node_proxy_done(impl->node_proxy, seq, res);
} }
static void do_node_init(struct pw_stream *stream) static void do_node_init(struct pw_stream *stream)
@ -862,6 +862,7 @@ static void client_node_transport(void *object, uint32_t node_id,
} }
static const struct pw_client_node_events client_node_events = { static const struct pw_client_node_events client_node_events = {
PW_VERSION_CLIENT_NODE_EVENTS,
&client_node_transport, &client_node_transport,
&client_node_set_props, &client_node_set_props,
&client_node_event, &client_node_event,
@ -913,27 +914,20 @@ pw_stream_connect(struct pw_stream *stream,
if (flags & PW_STREAM_FLAG_AUTOCONNECT) if (flags & PW_STREAM_FLAG_AUTOCONNECT)
pw_properties_set(stream->properties, "pipewire.autoconnect", "1"); pw_properties_set(stream->properties, "pipewire.autoconnect", "1");
impl->node_proxy = pw_proxy_new(stream->remote, impl->node_proxy = pw_core_proxy_create_node(stream->remote->core_proxy,
SPA_ID_INVALID, "client-node",
"client-node",
impl->type_client_node, impl->type_client_node,
0); PW_VERSION_CLIENT_NODE,
&stream->properties->dict, 0, NULL);
if (impl->node_proxy == NULL) if (impl->node_proxy == NULL)
return false; return false;
pw_proxy_set_implementation(impl->node_proxy, stream, PW_VERSION_CLIENT_NODE, pw_client_node_proxy_add_listener(impl->node_proxy, stream, &client_node_events);
&client_node_events, NULL);
pw_signal_add(&impl->node_proxy->destroy_signal, pw_signal_add(&impl->node_proxy->proxy.destroy_signal,
&impl->node_proxy_destroy, on_node_proxy_destroy); &impl->node_proxy_destroy, on_node_proxy_destroy);
pw_core_do_create_node(stream->remote->core_proxy,
"client-node",
"client-node",
&stream->properties->dict,
PW_VERSION_CLIENT_NODE,
impl->node_proxy->id);
do_node_init(stream); do_node_init(stream);
return true; return true;
@ -972,7 +966,7 @@ void pw_stream_disconnect(struct pw_stream *stream)
unhandle_socket(stream); unhandle_socket(stream);
if (impl->node_proxy) { if (impl->node_proxy) {
pw_client_node_do_destroy(impl->node_proxy); pw_client_node_proxy_destroy(impl->node_proxy);
impl->node_proxy = NULL; impl->node_proxy = NULL;
} }
} }

View file

@ -39,13 +39,13 @@ void pw_type_init(struct pw_type *type)
{ {
type->map = pw_get_support_interface(SPA_TYPE__TypeMap); type->map = pw_get_support_interface(SPA_TYPE__TypeMap);
type->core = spa_type_map_get_id(type->map, PW_TYPE__Core); type->core = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Core);
type->registry = spa_type_map_get_id(type->map, PW_TYPE__Registry); type->registry = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Registry);
type->node = spa_type_map_get_id(type->map, PW_TYPE__Node); type->node = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Node);
type->node_factory = spa_type_map_get_id(type->map, PW_TYPE__NodeFactory); type->node_factory = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__NodeFactory);
type->link = spa_type_map_get_id(type->map, PW_TYPE__Link); type->link = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Link);
type->client = spa_type_map_get_id(type->map, PW_TYPE__Client); type->client = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Client);
type->module = spa_type_map_get_id(type->map, PW_TYPE__Module); type->module = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Module);
type->spa_log = spa_type_map_get_id(type->map, SPA_TYPE__Log); type->spa_log = spa_type_map_get_id(type->map, SPA_TYPE__Log);
type->spa_node = spa_type_map_get_id(type->map, SPA_TYPE__Node); type->spa_node = spa_type_map_get_id(type->map, SPA_TYPE__Node);

View file

@ -33,27 +33,13 @@ extern "C" {
#include <pipewire/map.h> #include <pipewire/map.h>
#include <pipewire/transport.h> #include <pipewire/transport.h>
#define PW_TYPE__Object "PipeWire:Object" #define PW_TYPE_BASE "PipeWire:"
#define PW_TYPE__Object PW_TYPE_BASE "Object"
#define PW_TYPE_OBJECT_BASE PW_TYPE__Object ":" #define PW_TYPE_OBJECT_BASE PW_TYPE__Object ":"
/** \class pw_interface #define PW_TYPE__Interface PW_TYPE_BASE "Interface"
* \brief The interface definition #define PW_TYPE_INTERFACE_BASE PW_TYPE__Interface ":"
*
* The interface implements the methods and events for a \ref
* pw_proxy. It typically implements marshal functions for the
* methods and calls the user installed implementation after
* demarshalling the events.
*
* \sa pw_proxy, pw_resource
*/
struct pw_interface {
const char *type; /**< interface type */
uint32_t version; /**< version */
uint32_t n_methods; /**< number of methods in the interface */
const void *methods; /**< method implementations of the interface */
uint32_t n_events; /**< number of events in the interface */
const void *events; /**< event implementations of the interface */
};
/** \class pw_type /** \class pw_type
* \brief PipeWire type support struct * \brief PipeWire type support struct

View file

@ -31,13 +31,15 @@ struct data {
struct pw_loop *loop; struct pw_loop *loop;
struct pw_core *core; struct pw_core *core;
struct pw_remote *remote; struct pw_remote *remote;
struct pw_proxy *registry_proxy; struct pw_registry_proxy *registry_proxy;
struct pw_listener on_info_changed; struct pw_listener on_info_changed;
struct pw_listener on_state_changed; struct pw_listener on_state_changed;
}; };
struct proxy_data { struct proxy_data {
uint32_t id;
uint32_t version;
void *info; void *info;
}; };
@ -61,8 +63,7 @@ static void on_info_changed(struct pw_listener *listener, struct pw_remote *remo
struct pw_core_info *info = remote->info; struct pw_core_info *info = remote->info;
bool print_all = true, print_mark = false; bool print_all = true, print_mark = false;
printf("\tid: %u\n", info->id); printf("\ttype: %s\n", PW_TYPE_INTERFACE__Core);
printf("\ttype: %s\n", PW_TYPE__Core);
if (print_all) { if (print_all) {
printf("%c\tuser-name: \"%s\"\n", MARK_CHANGE(0), info->user_name); printf("%c\tuser-name: \"%s\"\n", MARK_CHANGE(0), info->user_name);
printf("%c\thost-name: \"%s\"\n", MARK_CHANGE(1), info->host_name); printf("%c\thost-name: \"%s\"\n", MARK_CHANGE(1), info->host_name);
@ -91,8 +92,8 @@ static void module_event_info(void *object, struct pw_module_info *info)
info = data->info = pw_module_info_update(data->info, info); info = data->info = pw_module_info_update(data->info, info);
printf("\tid: %u\n", info->id); printf("\tid: %d\n", data->id);
printf("\ttype: %s\n", PW_TYPE__Module); printf("\ttype: %s (version %d)\n", PW_TYPE_INTERFACE__Module, data->version);
if (print_all) { if (print_all) {
printf("%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name); printf("%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name);
printf("%c\tfilename: \"%s\"\n", MARK_CHANGE(1), info->filename); printf("%c\tfilename: \"%s\"\n", MARK_CHANGE(1), info->filename);
@ -102,6 +103,7 @@ static void module_event_info(void *object, struct pw_module_info *info)
} }
static const struct pw_module_events module_events = { static const struct pw_module_events module_events = {
PW_VERSION_MODULE_EVENTS,
&module_event_info, &module_event_info,
}; };
@ -123,8 +125,8 @@ static void node_event_info(void *object, struct pw_node_info *info)
info = data->info = pw_node_info_update(data->info, info); info = data->info = pw_node_info_update(data->info, info);
printf("\tid: %u\n", info->id); printf("\tid: %d\n", data->id);
printf("\ttype: %s\n", PW_TYPE__Node); printf("\ttype: %s (version %d)\n", PW_TYPE_INTERFACE__Node, data->version);
if (print_all) { if (print_all) {
int i; int i;
@ -149,6 +151,7 @@ static void node_event_info(void *object, struct pw_node_info *info)
} }
static const struct pw_node_events node_events = { static const struct pw_node_events node_events = {
PW_VERSION_NODE_EVENTS,
&node_event_info &node_event_info
}; };
@ -170,14 +173,15 @@ static void client_event_info(void *object, struct pw_client_info *info)
info = data->info = pw_client_info_update(data->info, info); info = data->info = pw_client_info_update(data->info, info);
printf("\tid: %u\n", info->id); printf("\tid: %d\n", data->id);
printf("\ttype: %s\n", PW_TYPE__Client); printf("\ttype: %s (version %d)\n", PW_TYPE_INTERFACE__Client, data->version);
if (print_all) { if (print_all) {
print_properties(info->props, MARK_CHANGE(0)); print_properties(info->props, MARK_CHANGE(0));
} }
} }
static const struct pw_client_events client_events = { static const struct pw_client_events client_events = {
PW_VERSION_CLIENT_EVENTS,
&client_event_info &client_event_info
}; };
@ -199,8 +203,8 @@ static void link_event_info(void *object, struct pw_link_info *info)
info = data->info = pw_link_info_update(data->info, info); info = data->info = pw_link_info_update(data->info, info);
printf("\tid: %u\n", info->id); printf("\tid: %d\n", data->id);
printf("\ttype: %s\n", PW_TYPE__Link); printf("\ttype: %s (version %d)\n", PW_TYPE_INTERFACE__Link, data->version);
if (print_all) { if (print_all) {
printf("%c\toutput-node-id: %u\n", MARK_CHANGE(0), info->output_node_id); printf("%c\toutput-node-id: %u\n", MARK_CHANGE(0), info->output_node_id);
printf("%c\toutput-port-id: %u\n", MARK_CHANGE(1), info->output_port_id); printf("%c\toutput-port-id: %u\n", MARK_CHANGE(1), info->output_port_id);
@ -215,6 +219,7 @@ static void link_event_info(void *object, struct pw_link_info *info)
} }
static const struct pw_link_events link_events = { static const struct pw_link_events link_events = {
PW_VERSION_LINK_EVENTS,
&link_event_info &link_event_info
}; };
@ -222,21 +227,25 @@ static void
destroy_proxy (void *data) destroy_proxy (void *data)
{ {
struct pw_proxy *proxy = data; struct pw_proxy *proxy = data;
struct proxy_data *user_data = proxy->user_data;
struct pw_core *core = proxy->remote->core; struct pw_core *core = proxy->remote->core;
struct proxy_data *user_data = proxy->user_data;
if (user_data->info == NULL) if (user_data->info == NULL)
return; return;
if (proxy->type == core->type.core) { if (proxy->type == core->type.core) {
pw_core_info_free (user_data->info); pw_core_info_free (user_data->info);
} else if (proxy->type == core->type.node) { }
else if (proxy->type == core->type.node) {
pw_node_info_free (user_data->info); pw_node_info_free (user_data->info);
} else if (proxy->type == core->type.module) { }
else if (proxy->type == core->type.module) {
pw_module_info_free (user_data->info); pw_module_info_free (user_data->info);
} else if (proxy->type == core->type.client) { }
else if (proxy->type == core->type.client) {
pw_client_info_free (user_data->info); pw_client_info_free (user_data->info);
} else if (proxy->type == core->type.link) { }
else if (proxy->type == core->type.link) {
pw_link_info_free (user_data->info); pw_link_info_free (user_data->info);
} }
user_data->info = NULL; user_data->info = NULL;
@ -245,39 +254,45 @@ destroy_proxy (void *data)
static void registry_event_global(void *object, uint32_t id, uint32_t type, uint32_t version) static void registry_event_global(void *object, uint32_t id, uint32_t type, uint32_t version)
{ {
struct pw_proxy *registry_proxy = object; struct pw_proxy *proxy = object;
struct data *data = registry_proxy->object; struct data *data = proxy->object;
struct pw_core *core = data->core;
struct pw_remote *remote = registry_proxy->remote;
struct pw_proxy *proxy = NULL;
uint32_t client_version; uint32_t client_version;
const void *implementation; const void *events;
struct pw_core *core = data->core;
struct proxy_data *pd;
if (type == core->type.node) { if (type == core->type.node) {
implementation = &node_events; events = &node_events;
client_version = PW_VERSION_NODE; client_version = PW_VERSION_NODE;
} }
else if (type == core->type.module) { else if (type == core->type.module) {
implementation = &module_events; events = &module_events;
client_version = PW_VERSION_MODULE; client_version = PW_VERSION_MODULE;
} }
else if (type == core->type.client) { else if (type == core->type.client) {
implementation = &client_events; events = &client_events;
client_version = PW_VERSION_CLIENT; client_version = PW_VERSION_CLIENT;
} }
else if (type == core->type.link) { else if (type == core->type.link) {
implementation = &link_events; events = &link_events;
client_version = PW_VERSION_LINK; client_version = PW_VERSION_LINK;
} else }
else {
printf("added:\n");
printf("\tid: %u\n", id);
printf("\ttype: %s (version %d)\n", spa_type_map_get_type(core->type.map, type), version);
return; return;
}
proxy = pw_proxy_new(remote, SPA_ID_INVALID, type, sizeof(struct proxy_data)); proxy = pw_registry_proxy_bind(data->registry_proxy, id, type,
client_version, sizeof(struct proxy_data), destroy_proxy);
if (proxy == NULL) if (proxy == NULL)
goto no_mem; goto no_mem;
pw_proxy_set_implementation(proxy, data, client_version, implementation, destroy_proxy); pd = proxy->user_data;
pd->id = id;
pw_registry_do_bind(registry_proxy, id, version, proxy->id); pd->version = version;
pw_proxy_add_listener(proxy, proxy, events);
return; return;
@ -293,6 +308,7 @@ static void registry_event_global_remove(void *object, uint32_t id)
} }
static const struct pw_registry_events registry_events = { static const struct pw_registry_events registry_events = {
PW_VERSION_REGISTRY_EVENTS,
registry_event_global, registry_event_global,
registry_event_global_remove, registry_event_global_remove,
}; };
@ -310,16 +326,10 @@ static void on_state_changed(struct pw_listener *listener, struct pw_remote *rem
case PW_REMOTE_STATE_CONNECTED: case PW_REMOTE_STATE_CONNECTED:
printf("remote state: \"%s\"\n", pw_remote_state_as_string(remote->state)); printf("remote state: \"%s\"\n", pw_remote_state_as_string(remote->state));
data->registry_proxy = pw_proxy_new(data->remote, data->registry_proxy = pw_core_proxy_get_registry(data->remote->core_proxy,
SPA_ID_INVALID, PW_VERSION_REGISTRY, 0, NULL);
data->core->type.registry, pw_registry_proxy_add_listener(data->registry_proxy,
0); data, &registry_events);
pw_proxy_set_implementation(data->registry_proxy, data, PW_VERSION_REGISTRY,
&registry_events, NULL);
pw_core_do_get_registry(data->remote->core_proxy, PW_VERSION_REGISTRY,
data->registry_proxy->id);
break; break;
default: default: