Improve version handling

Add version numbers to protocol interfaces and implementation.
Allow allocating user_data in proxy and resource
Use separate methods to set implementation.
Add protocol object to keep track of available protocols and
interfaces. Add possibility to dynamically register interfaces.
This commit is contained in:
Wim Taymans 2017-06-15 17:54:55 +02:00
parent c3b73ba47d
commit ae708c14e7
29 changed files with 572 additions and 225 deletions

View file

@ -27,6 +27,7 @@
#include "pipewire/client/context.h"
#include "pipewire/client/introspect.h"
#include "pipewire/client/interfaces.h"
#include "pipewire/client/protocol-native.h"
#include "pipewire/client/connection.h"
#include "pipewire/client/subscribe.h"
@ -49,6 +50,10 @@ struct context {
struct pw_listener need_flush;
struct spa_source *flush_event;
};
struct proxy_data {
void *info;
};
/** \endcond */
const char *pw_context_state_as_string(enum pw_context_state state)
@ -97,15 +102,16 @@ static void core_event_info(void *object, struct pw_core_info *info)
struct pw_proxy *proxy = object;
struct pw_context *this = proxy->context;
enum pw_subscription_event event;
struct proxy_data *data = proxy->user_data;
pw_log_debug("got core info");
if (proxy->user_data == NULL)
if (data->info == NULL)
event = PW_SUBSCRIPTION_EVENT_NEW;
else
event = PW_SUBSCRIPTION_EVENT_CHANGE;
proxy->user_data = pw_core_info_update(proxy->user_data, info);
data->info = pw_core_info_update(data->info, info);
pw_signal_emit(&this->subscription, this, event, proxy->type, proxy->id);
}
@ -169,15 +175,16 @@ static void module_event_info(void *object, struct pw_module_info *info)
struct pw_proxy *proxy = object;
struct pw_context *this = proxy->context;
enum pw_subscription_event event;
struct proxy_data *data = proxy->user_data;
pw_log_debug("got module info");
if (proxy->user_data == NULL)
if (data->info == NULL)
event = PW_SUBSCRIPTION_EVENT_NEW;
else
event = PW_SUBSCRIPTION_EVENT_CHANGE;
proxy->user_data = pw_module_info_update(proxy->user_data, info);
data->info = pw_module_info_update(data->info, info);
pw_signal_emit(&this->subscription, this, event, proxy->type, proxy->id);
}
@ -191,15 +198,16 @@ static void node_event_info(void *object, struct pw_node_info *info)
struct pw_proxy *proxy = object;
struct pw_context *this = proxy->context;
enum pw_subscription_event event;
struct proxy_data *data = proxy->user_data;
pw_log_debug("got node info");
if (proxy->user_data == NULL)
if (data->info == NULL)
event = PW_SUBSCRIPTION_EVENT_NEW;
else
event = PW_SUBSCRIPTION_EVENT_CHANGE;
proxy->user_data = pw_node_info_update(proxy->user_data, info);
data->info = pw_node_info_update(data->info, info);
pw_signal_emit(&this->subscription, this, event, proxy->type, proxy->id);
}
@ -213,15 +221,16 @@ static void client_event_info(void *object, struct pw_client_info *info)
struct pw_proxy *proxy = object;
struct pw_context *this = proxy->context;
enum pw_subscription_event event;
struct proxy_data *data = proxy->user_data;
pw_log_debug("got client info");
if (proxy->user_data == NULL)
if (data->info == NULL)
event = PW_SUBSCRIPTION_EVENT_NEW;
else
event = PW_SUBSCRIPTION_EVENT_CHANGE;
proxy->user_data = pw_client_info_update(proxy->user_data, info);
data->info = pw_client_info_update(data->info, info);
pw_signal_emit(&this->subscription, this, event, proxy->type, proxy->id);
}
@ -235,15 +244,16 @@ static void link_event_info(void *object, struct pw_link_info *info)
struct pw_proxy *proxy = object;
struct pw_context *this = proxy->context;
enum pw_subscription_event event;
struct proxy_data *data = proxy->user_data;
pw_log_debug("got link info");
if (proxy->user_data == NULL)
if (data->info == NULL)
event = PW_SUBSCRIPTION_EVENT_NEW;
else
event = PW_SUBSCRIPTION_EVENT_CHANGE;
proxy->user_data = pw_link_info_update(proxy->user_data, info);
data->info = pw_link_info_update(data->info, info);
pw_signal_emit(&this->subscription, this, event, proxy->type, proxy->id);
}
@ -253,23 +263,26 @@ static const struct pw_link_events link_events = {
};
static void
destroy_proxy (struct pw_proxy *proxy)
destroy_proxy (void *data)
{
if (proxy->user_data == NULL)
struct pw_proxy *proxy = data;
struct proxy_data *user_data = proxy->user_data;
if (user_data->info == NULL)
return;
if (proxy->type == proxy->context->type.core) {
pw_core_info_free (proxy->user_data);
pw_core_info_free (user_data->info);
} else if (proxy->type == proxy->context->type.node) {
pw_node_info_free (proxy->user_data);
pw_node_info_free (user_data->info);
} else if (proxy->type == proxy->context->type.module) {
pw_module_info_free (proxy->user_data);
pw_module_info_free (user_data->info);
} else if (proxy->type == proxy->context->type.client) {
pw_client_info_free (proxy->user_data);
pw_client_info_free (user_data->info);
} else if (proxy->type == proxy->context->type.link) {
pw_link_info_free (proxy->user_data);
pw_link_info_free (user_data->info);
}
proxy->user_data = NULL;
user_data->info = NULL;
}
static void registry_event_global(void *object, uint32_t id, const char *type, uint32_t version)
@ -278,6 +291,8 @@ static void registry_event_global(void *object, uint32_t id, const char *type, u
struct pw_context *this = registry_proxy->context;
struct context *impl = SPA_CONTAINER_OF(this, struct context, this);
struct pw_proxy *proxy = NULL;
uint32_t proxy_type, client_version;
const void *implementation;
if (impl->no_proxy)
return;
@ -285,34 +300,31 @@ static void registry_event_global(void *object, uint32_t id, const char *type, u
pw_log_debug("got global %u %s %u", id, type, version);
if (!strcmp(type, PIPEWIRE_TYPE__Node)) {
proxy = pw_proxy_new(this, SPA_ID_INVALID, this->type.node);
if (proxy == NULL)
goto no_mem;
proxy->implementation = &node_events;
proxy_type = this->type.node;
implementation = &node_events;
client_version = PW_VERSION_NODE;
} else if (!strcmp(type, PIPEWIRE_TYPE__Module)) {
proxy = pw_proxy_new(this, SPA_ID_INVALID, this->type.module);
if (proxy == NULL)
goto no_mem;
proxy->implementation = &module_events;
proxy_type = this->type.module;
implementation = &module_events;
client_version = PW_VERSION_MODULE;
} else if (!strcmp(type, PIPEWIRE_TYPE__Client)) {
proxy = pw_proxy_new(this, SPA_ID_INVALID, this->type.client);
if (proxy == NULL)
goto no_mem;
proxy->implementation = &client_events;
proxy_type = this->type.client;
implementation = &client_events;
client_version = PW_VERSION_CLIENT;
} else if (!strcmp(type, PIPEWIRE_TYPE__Link)) {
proxy = pw_proxy_new(this, SPA_ID_INVALID, this->type.link);
if (proxy == NULL)
goto no_mem;
proxy_type = this->type.link;
implementation = &link_events;
client_version = PW_VERSION_LINK;
} else
return;
proxy->implementation = &link_events;
}
if (proxy) {
proxy->destroy = (pw_destroy_t)destroy_proxy;
pw_registry_do_bind(registry_proxy, id, version, proxy->id);
}
proxy = pw_proxy_new(this, SPA_ID_INVALID, proxy_type, sizeof(struct proxy_data));
if (proxy == NULL)
goto no_mem;
pw_proxy_set_implementation(proxy, this, client_version, implementation, destroy_proxy);
pw_registry_do_bind(registry_proxy, id, version, proxy->id);
return;
@ -441,6 +453,9 @@ struct pw_context *pw_context_new(struct pw_loop *loop,
this->loop = loop;
this->protocol = pw_protocol_get(PW_TYPE_PROTOCOL__Native);
pw_protocol_native_client_init();
pw_type_init(&this->type);
spa_debug_set_type_map(this->type.map);
@ -593,25 +608,26 @@ bool pw_context_connect_fd(struct pw_context *context, enum pw_context_flags fla
SPA_IO_IN | SPA_IO_HUP | SPA_IO_ERR,
false, on_context_data, impl);
context->core_proxy = pw_proxy_new(context, 0, context->type.core);
context->core_proxy = pw_proxy_new(context, 0, context->type.core, sizeof(struct proxy_data));
if (context->core_proxy == NULL)
goto no_proxy;
context->core_proxy->implementation = &core_events;
context->core_proxy->destroy = (pw_destroy_t)destroy_proxy;
pw_proxy_set_implementation(context->core_proxy, context, PW_VERSION_CORE,
&core_events, destroy_proxy);
pw_core_do_client_update(context->core_proxy, &context->properties->dict);
if (!(flags & PW_CONTEXT_FLAG_NO_REGISTRY)) {
context->registry_proxy = pw_proxy_new(context,
SPA_ID_INVALID, context->type.registry);
SPA_ID_INVALID, context->type.registry, 0);
if (context->registry_proxy == NULL)
goto no_registry;
context->registry_proxy->implementation = &registry_events;
pw_proxy_set_implementation(context->registry_proxy, context, PW_VERSION_REGISTRY,
&registry_events, NULL);
pw_core_do_get_registry(context->core_proxy, context->registry_proxy->id);
}
impl->no_proxy = ! !(flags & PW_CONTEXT_FLAG_NO_PROXY);
@ -683,10 +699,13 @@ void pw_context_get_core_info(struct pw_context *context, pw_core_info_cb_t cb,
proxy = pw_map_lookup(&context->objects, 0);
if (proxy == NULL) {
cb(context, SPA_RESULT_INVALID_OBJECT_ID, NULL, user_data);
} else if (proxy->type == context->type.core && proxy->user_data) {
struct pw_core_info *info = proxy->user_data;
cb(context, SPA_RESULT_OK, info, user_data);
info->change_mask = 0;
} else if (proxy->type == context->type.core) {
struct proxy_data *data = proxy->user_data;
struct pw_core_info *info = data->info;
if (info) {
cb(context, SPA_RESULT_OK, info, user_data);
info->change_mask = 0;
}
}
cb(context, SPA_RESULT_ENUM_END, NULL, user_data);
}
@ -699,6 +718,7 @@ static void do_list(struct pw_context *context, uint32_t type, list_func_t cb, v
pw_array_for_each(item, &context->objects.items) {
struct pw_proxy *proxy;
struct proxy_data *data;
if (pw_map_item_is_free(item))
continue;
@ -707,8 +727,9 @@ static void do_list(struct pw_context *context, uint32_t type, list_func_t cb, v
if (proxy->type != type)
continue;
if (proxy->user_data)
cb(context, SPA_RESULT_OK, proxy->user_data, user_data);
data = proxy->user_data;
if (data->info)
cb(context, SPA_RESULT_OK, data->info, user_data);
}
cb(context, SPA_RESULT_ENUM_END, NULL, user_data);
}
@ -749,10 +770,13 @@ pw_context_get_module_info_by_id(struct pw_context *context,
proxy = pw_map_lookup(&context->objects, id);
if (proxy == NULL) {
cb(context, SPA_RESULT_INVALID_OBJECT_ID, NULL, user_data);
} else if (proxy->type == context->type.module && proxy->user_data) {
struct pw_module_info *info = proxy->user_data;
cb(context, SPA_RESULT_OK, info, user_data);
info->change_mask = 0;
} else if (proxy->type == context->type.module) {
struct proxy_data *data = proxy->user_data;
struct pw_module_info *info = data->info;
if (info) {
cb(context, SPA_RESULT_OK, info, user_data);
info->change_mask = 0;
}
}
cb(context, SPA_RESULT_ENUM_END, NULL, user_data);
}
@ -793,10 +817,13 @@ pw_context_get_client_info_by_id(struct pw_context *context,
proxy = pw_map_lookup(&context->objects, id);
if (proxy == NULL) {
cb(context, SPA_RESULT_INVALID_OBJECT_ID, NULL, user_data);
} else if (proxy->type == context->type.client && proxy->user_data) {
struct pw_client_info *info = proxy->user_data;
cb(context, SPA_RESULT_OK, info, user_data);
info->change_mask = 0;
} else if (proxy->type == context->type.client) {
struct proxy_data *data = proxy->user_data;
struct pw_client_info *info = data->info;
if (info) {
cb(context, SPA_RESULT_OK, info, user_data);
info->change_mask = 0;
}
}
cb(context, SPA_RESULT_ENUM_END, NULL, user_data);
}
@ -836,10 +863,13 @@ pw_context_get_node_info_by_id(struct pw_context *context,
proxy = pw_map_lookup(&context->objects, id);
if (proxy == NULL) {
cb(context, SPA_RESULT_INVALID_OBJECT_ID, NULL, user_data);
} else if (proxy->type == context->type.node && proxy->user_data) {
struct pw_node_info *info = proxy->user_data;
cb(context, SPA_RESULT_OK, info, user_data);
info->change_mask = 0;
} else if (proxy->type == context->type.node) {
struct proxy_data *data = proxy->user_data;
struct pw_node_info *info = data->info;
if (info) {
cb(context, SPA_RESULT_OK, info, user_data);
info->change_mask = 0;
}
}
cb(context, SPA_RESULT_ENUM_END, NULL, user_data);
}
@ -879,10 +909,13 @@ pw_context_get_link_info_by_id(struct pw_context *context,
proxy = pw_map_lookup(&context->objects, id);
if (proxy == NULL) {
cb(context, SPA_RESULT_INVALID_OBJECT_ID, NULL, user_data);
} else if (proxy->type == context->type.link && proxy->user_data) {
struct pw_link_info *info = proxy->user_data;
cb(context, SPA_RESULT_OK, info, user_data);
info->change_mask = 0;
} else if (proxy->type == context->type.link) {
struct proxy_data *data = proxy->user_data;
struct pw_link_info *info = data->info;
if (info) {
cb(context, SPA_RESULT_OK, info, user_data);
info->change_mask = 0;
}
}
cb(context, SPA_RESULT_ENUM_END, NULL, user_data);
}

View file

@ -103,6 +103,7 @@ extern "C" {
#include <pipewire/client/map.h>
#include <pipewire/client/loop.h>
#include <pipewire/client/properties.h>
#include <pipewire/client/protocol.h>
#include <pipewire/client/subscribe.h>
#include <pipewire/client/proxy.h>
#include <pipewire/client/type.h>
@ -159,6 +160,7 @@ struct pw_context {
struct spa_list stream_list; /**< list of \ref pw_stream objects */
struct spa_list proxy_list; /**< list of \ref pw_proxy objects */
struct pw_protocol *protocol; /**< the protocol in use */
void *protocol_private; /**< private data for the protocol */
enum pw_context_state state; /**< context state */

View file

@ -48,6 +48,8 @@ extern "C" {
* \section page_iface_pw_core API
*/
#define PW_VERSION_CORE 0
#define PW_CORE_METHOD_UPDATE_TYPES 0
#define PW_CORE_METHOD_SYNC 1
#define PW_CORE_METHOD_GET_REGISTRY 2
@ -215,6 +217,7 @@ struct pw_core_events {
#define pw_core_notify_remove_id(r,...) ((struct pw_core_events*)r->iface->events)->remove_id(r,__VA_ARGS__)
#define pw_core_notify_info(r,...) ((struct pw_core_events*)r->iface->events)->info(r,__VA_ARGS__)
#define PW_VERSION_REGISTRY 0
#define PW_REGISTRY_METHOD_BIND 0
#define PW_REGISTRY_METHOD_NUM 1
@ -269,8 +272,10 @@ struct pw_registry_events {
#define pw_registry_notify_global(r,...) ((struct pw_registry_events*)r->iface->events)->global(r,__VA_ARGS__)
#define pw_registry_notify_global_remove(r,...) ((struct pw_registry_events*)r->iface->events)->global_remove(r,__VA_ARGS__)
#define PW_MODULE_EVENT_INFO 0
#define PW_MODULE_EVENT_NUM 1
#define PW_VERSION_MODULE 0
#define PW_MODULE_EVENT_INFO 0
#define PW_MODULE_EVENT_NUM 1
/** Module events */
struct pw_module_events {
@ -284,8 +289,10 @@ struct pw_module_events {
#define pw_module_notify_info(r,...) ((struct pw_module_events*)r->iface->events)->info(r,__VA_ARGS__)
#define PW_NODE_EVENT_INFO 0
#define PW_NODE_EVENT_NUM 1
#define PW_VERSION_NODE 0
#define PW_NODE_EVENT_INFO 0
#define PW_NODE_EVENT_NUM 1
/** Node events */
struct pw_node_events {
@ -307,6 +314,8 @@ struct pw_client_node_buffer {
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_UPDATE 1
#define PW_CLIENT_NODE_METHOD_PORT_UPDATE 2
@ -554,8 +563,10 @@ struct pw_client_node_events {
#define pw_client_node_notify_port_command(r,...) ((struct pw_client_node_events*)r->iface->events)->port_command(r,__VA_ARGS__)
#define pw_client_node_notify_transport(r,...) ((struct pw_client_node_events*)r->iface->events)->transport(r,__VA_ARGS__)
#define PW_CLIENT_EVENT_INFO 0
#define PW_CLIENT_EVENT_NUM 1
#define PW_VERSION_CLIENT 0
#define PW_CLIENT_EVENT_INFO 0
#define PW_CLIENT_EVENT_NUM 1
/** Client events */
struct pw_client_events {
@ -569,8 +580,10 @@ struct pw_client_events {
#define pw_client_notify_info(r,...) ((struct pw_client_events*)r->iface->events)->info(r,__VA_ARGS__)
#define PW_LINK_EVENT_INFO 0
#define PW_LINK_EVENT_NUM 1
#define PW_VERSION_LINK 0
#define PW_LINK_EVENT_INFO 0
#define PW_LINK_EVENT_NUM 1
/** Link events */
struct pw_link_events {

View file

@ -10,6 +10,7 @@ pipewire_headers = [
'mem.h',
'pipewire.h',
'properties.h',
'protocol.h',
'protocol-native.h',
'proxy.h',
'rtkit.h',
@ -29,11 +30,12 @@ pipewire_sources = [
'log.c',
'loop.c',
'mem.c',
'pipewire.c',
'properties.c',
'protocol.c',
'protocol-native.c',
'proxy.c',
'stream.c',
'pipewire.c',
'rtkit.c',
'thread-loop.c',
'transport.c',

View file

@ -23,6 +23,7 @@
#include "pipewire/client/pipewire.h"
#include "pipewire/client/protocol-native.h"
#include "pipewire/client/protocol.h"
#include "pipewire/client/interfaces.h"
#include "pipewire/client/connection.h"
@ -929,6 +930,8 @@ static const demarshal_func_t pw_protocol_native_client_core_demarshal[PW_CORE_E
};
static const struct pw_interface pw_protocol_native_client_core_interface = {
PIPEWIRE_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
};
@ -943,6 +946,8 @@ static const demarshal_func_t pw_protocol_native_client_registry_demarshal[] = {
};
static const struct pw_interface pw_protocol_native_client_registry_interface = {
PIPEWIRE_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,
};
@ -970,6 +975,8 @@ static const demarshal_func_t pw_protocol_native_client_client_node_demarshal[]
};
static const struct pw_interface pw_protocol_native_client_client_node_interface = {
PIPEWIRE_TYPE_NODE_BASE "Client",
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,
};
@ -979,6 +986,8 @@ static const demarshal_func_t pw_protocol_native_client_module_demarshal[] = {
};
static const struct pw_interface pw_protocol_native_client_module_interface = {
PIPEWIRE_TYPE__Module,
PW_VERSION_MODULE,
0, NULL,
PW_MODULE_EVENT_NUM, pw_protocol_native_client_module_demarshal,
};
@ -988,6 +997,8 @@ static const demarshal_func_t pw_protocol_native_client_node_demarshal[] = {
};
static const struct pw_interface pw_protocol_native_client_node_interface = {
PIPEWIRE_TYPE__Node,
PW_VERSION_NODE,
0, NULL,
PW_NODE_EVENT_NUM, pw_protocol_native_client_node_demarshal,
};
@ -997,6 +1008,8 @@ static const demarshal_func_t pw_protocol_native_client_client_demarshal[] = {
};
static const struct pw_interface pw_protocol_native_client_client_interface = {
PIPEWIRE_TYPE__Client,
PW_VERSION_CLIENT,
0, NULL,
PW_CLIENT_EVENT_NUM, pw_protocol_native_client_client_demarshal,
};
@ -1006,30 +1019,43 @@ static const demarshal_func_t pw_protocol_native_client_link_demarshal[] = {
};
static const struct pw_interface pw_protocol_native_client_link_interface = {
PIPEWIRE_TYPE__Link,
PW_VERSION_LINK,
0, NULL,
PW_LINK_EVENT_NUM, pw_protocol_native_client_link_demarshal,
};
bool pw_protocol_native_client_setup(struct pw_proxy *proxy)
void pw_protocol_native_client_init(void)
{
const struct pw_interface *iface;
static bool init = false;
struct pw_protocol *protocol;
if (proxy->type == proxy->context->type.core) {
iface = &pw_protocol_native_client_core_interface;
} else if (proxy->type == proxy->context->type.registry) {
iface = &pw_protocol_native_client_registry_interface;
} else if (proxy->type == proxy->context->type.module) {
iface = &pw_protocol_native_client_module_interface;
} else if (proxy->type == proxy->context->type.node) {
iface = &pw_protocol_native_client_node_interface;
} else if (proxy->type == proxy->context->type.client_node) {
iface = &pw_protocol_native_client_client_node_interface;
} else if (proxy->type == proxy->context->type.client) {
iface = &pw_protocol_native_client_client_interface;
} else if (proxy->type == proxy->context->type.link) {
iface = &pw_protocol_native_client_link_interface;
} else
return false;
proxy->iface = iface;
return true;
if (init)
return;
protocol = pw_protocol_get(PW_TYPE_PROTOCOL__Native);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_core_interface,
NULL);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_registry_interface,
NULL);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_module_interface,
NULL);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_node_interface,
NULL);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_client_node_interface,
NULL);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_client_interface,
NULL);
pw_protocol_add_interfaces(protocol,
&pw_protocol_native_client_link_interface,
NULL);
init = true;
}

View file

@ -17,8 +17,4 @@
* Boston, MA 02110-1301, USA.
*/
#include "pipewire/client/pipewire.h"
#include "pipewire/client/interfaces.h"
bool
pw_protocol_native_client_setup(struct pw_proxy *proxy);
void pw_protocol_native_client_init(void);

View file

@ -0,0 +1,82 @@
/* PipeWire
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <pipewire/client/protocol.h>
static struct impl {
bool init;
struct spa_list protocol_list;
} protocols;
static struct impl *get_impl(void)
{
if (!protocols.init) {
spa_list_init(&protocols.protocol_list);
protocols.init = true;
}
return &protocols;
}
struct pw_protocol *pw_protocol_get(const char *name)
{
struct impl *impl = get_impl();
struct pw_protocol *protocol;
spa_list_for_each(protocol, &impl->protocol_list, link) {
if (strcmp(protocol->name, name) == 0)
return protocol;
}
protocol = calloc(1, sizeof(struct pw_protocol));
protocol->name = name;
spa_list_init(&protocol->iface_list);
spa_list_insert(impl->protocol_list.prev, &protocol->link);
return protocol;
}
void
pw_protocol_add_interfaces(struct pw_protocol *protocol,
const struct pw_interface *client_iface,
const struct pw_interface *server_iface)
{
struct pw_protocol_iface *iface;
iface = calloc(1, sizeof(struct pw_protocol_iface));
iface->client_iface = client_iface;
iface->server_iface = server_iface;
spa_list_insert(protocol->iface_list.prev, &iface->link);
}
const struct pw_interface *
pw_protocol_get_interface(struct pw_protocol *protocol,
const char *type,
bool server)
{
struct pw_protocol_iface *protocol_iface;
spa_list_for_each(protocol_iface, &protocol->iface_list, link) {
const struct pw_interface *iface = server ? protocol_iface->server_iface :
protocol_iface->client_iface;
if (strcmp(iface->type, type) == 0)
return iface;
}
return NULL;
}

View file

@ -0,0 +1,67 @@
/* PipeWire
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __PIPEWIRE_PROTOCOL_H__
#define __PIPEWIRE_PROTOCOL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <spa/defs.h>
#include <spa/list.h>
#include <pipewire/client/subscribe.h>
#include <pipewire/client/type.h>
#define PW_TYPE_PROTOCOL__Native PW_TYPE_PROTOCOL_BASE "Native"
struct pw_protocol_iface {
struct spa_list link;
const struct pw_interface *client_iface;
const struct pw_interface *server_iface;
};
struct pw_protocol {
struct spa_list link;
const char *name;
struct spa_list iface_list;
};
struct pw_protocol *pw_protocol_get(const char *name);
/** \class pw_protocol
*
* \brief Manages protocols and their implementation
*/
void
pw_protocol_add_interfaces(struct pw_protocol *protocol,
const struct pw_interface *client_iface,
const struct pw_interface *server_iface);
const struct pw_interface *
pw_protocol_get_interface(struct pw_protocol *protocol,
const char *type,
bool server);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __PIPEWIRE_PROTOCOL_H__ */

View file

@ -41,12 +41,14 @@ struct proxy {
*
* \memberof pw_proxy
*/
struct pw_proxy *pw_proxy_new(struct pw_context *context, uint32_t id, uint32_t type)
struct pw_proxy *pw_proxy_new(struct pw_context *context,
uint32_t id, uint32_t type,
size_t user_data_size)
{
struct proxy *impl;
struct pw_proxy *this;
impl = calloc(1, sizeof(struct proxy));
impl = calloc(1, sizeof(struct proxy) + user_data_size);
if (impl == NULL)
return NULL;
@ -63,7 +65,12 @@ struct pw_proxy *pw_proxy_new(struct pw_context *context, uint32_t id, uint32_t
this->id = id;
pw_protocol_native_client_setup(this);
if (user_data_size > 0)
this->user_data = SPA_MEMBER(impl, sizeof(struct proxy), void);
this->iface = pw_protocol_get_interface(context->protocol,
spa_type_map_get_type(context->type.map, type),
false);
spa_list_insert(&this->context->proxy_list, &this->link);
@ -77,6 +84,19 @@ struct pw_proxy *pw_proxy_new(struct pw_context *context, uint32_t id, uint32_t
return NULL;
}
int pw_proxy_set_implementation(struct pw_proxy *proxy,
void *object,
uint32_t version,
const void *implementation,
pw_destroy_t destroy)
{
proxy->object = object;
proxy->version = version;
proxy->implementation = implementation;
proxy->destroy = destroy;
return SPA_RESULT_OK;
}
/** Destroy a proxy object
*
* \param proxy Proxy object to destroy

View file

@ -88,26 +88,36 @@ extern "C" {
* See \ref page_proxy
*/
struct pw_proxy {
/** the owner context of this proxy */
struct pw_context *context;
/** link in the context */
struct spa_list link;
uint32_t id; /**< client side id */
uint32_t type; /**< object type id */
struct pw_context *context; /**< the owner context of this proxy */
struct spa_list link; /**< link in the context */
uint32_t id; /**< client side id */
uint32_t type; /**< object type id */
const struct pw_interface *iface; /**< methods/events marshal/demarshal functions */
const void *implementation; /**< event handler implementation */
void *user_data; /**< optional client user data */
pw_destroy_t destroy; /**< optional destroy function to clean up user_data */
void *object; /**< client side object */
uint32_t version;
const void *implementation; /**< event handler implementation */
pw_destroy_t destroy; /**< optional destroy function to clean up the object */
/** destroy_signal is emited when the proxy is destroyed */
PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_proxy *proxy));
void *user_data; /**< extra user data */
};
struct pw_proxy *
pw_proxy_new(struct pw_context *context, uint32_t id, uint32_t type);
pw_proxy_new(struct pw_context *context,
uint32_t id,
uint32_t type,
size_t user_data_size);
int
pw_proxy_set_implementation(struct pw_proxy *proxy,
void *object,
uint32_t version,
const void *implementation,
pw_destroy_t destroy);
void pw_proxy_destroy(struct pw_proxy *proxy);

View file

@ -652,7 +652,7 @@ client_node_set_format(void *object,
uint32_t port_id, uint32_t flags, const struct spa_format *format)
{
struct pw_proxy *proxy = object;
struct pw_stream *stream = proxy->user_data;
struct pw_stream *stream = proxy->object;
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
if (impl->format)
@ -686,7 +686,7 @@ client_node_add_mem(void *object,
uint32_t type, int memfd, uint32_t flags, uint32_t offset, uint32_t size)
{
struct pw_proxy *proxy = object;
struct pw_stream *stream = proxy->user_data;
struct pw_stream *stream = proxy->object;
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
struct mem_id *m;
@ -715,7 +715,7 @@ client_node_use_buffers(void *object,
uint32_t port_id, uint32_t n_buffers, struct pw_client_node_buffer *buffers)
{
struct pw_proxy *proxy = object;
struct pw_stream *stream = proxy->user_data;
struct pw_stream *stream = proxy->object;
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
struct buffer_id *bid;
uint32_t i, j, len;
@ -828,7 +828,7 @@ client_node_use_buffers(void *object,
static void client_node_node_command(void *object, uint32_t seq, const struct spa_command *command)
{
struct pw_proxy *proxy = object;
struct pw_stream *stream = proxy->user_data;
struct pw_stream *stream = proxy->object;
handle_node_command(stream, seq, command);
}
@ -844,7 +844,7 @@ client_node_port_command(void *object,
static void client_node_transport(void *object, int readfd, int writefd, int memfd, uint32_t offset, uint32_t size)
{
struct pw_proxy *proxy = object;
struct pw_stream *stream = proxy->user_data;
struct pw_stream *stream = proxy->object;
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
struct pw_transport_info info;
@ -933,16 +933,17 @@ pw_stream_connect(struct pw_stream *stream,
pw_properties_set(stream->properties, "pipewire.autoconnect", "1");
impl->node_proxy = pw_proxy_new(stream->context,
SPA_ID_INVALID, stream->context->type.client_node);
SPA_ID_INVALID, stream->context->type.client_node, 0);
if (impl->node_proxy == NULL)
return false;
pw_proxy_set_implementation(impl->node_proxy, stream, PW_VERSION_CLIENT_NODE,
&client_node_events, NULL);
pw_signal_add(&impl->node_proxy->destroy_signal,
&impl->node_proxy_destroy, on_node_proxy_destroy);
impl->node_proxy->user_data = stream;
impl->node_proxy->implementation = &client_node_events;
pw_core_do_create_node(stream->context->core_proxy,
"client-node",
"client-node",

View file

@ -44,6 +44,9 @@ extern "C" {
#define PIPEWIRE_TYPE__Module "PipeWire:Object:Module"
#define PIPEWIRE_TYPE_MODULE_BASE PIPEWIRE_TYPE__Module ":"
#define PW_TYPE__Protocol "PipeWire:Protocol"
#define PW_TYPE_PROTOCOL_BASE PW_TYPE__Protocol ":"
/** \enum pw_subscription_event
* subscription events
*/

View file

@ -19,17 +19,17 @@
#include <string.h>
#include "spa/defs.h"
#include "spa/clock.h"
#include "spa/type-map.h"
#include "spa/monitor.h"
#include "pipewire/client/pipewire.h"
#include "pipewire/client/type.h"
#include "pipewire/server/core.h"
#include "pipewire/server/node.h"
#include "pipewire/server/node-factory.h"
#include "pipewire/server/client.h"
#include "pipewire/server/client-node.h"
#include "pipewire/server/module.h"
#include "spa/monitor.h"
/** Initializes the type system
* \param type a type structure

View file

@ -44,6 +44,8 @@ extern "C" {
* \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 */

View file

@ -42,7 +42,7 @@ struct client_info {
struct impl *impl;
struct pw_client *client;
struct spa_list link;
struct pw_listener resource_added;
struct pw_listener resource_impl;
struct pw_listener resource_removed;
struct spa_list node_list;
};
@ -98,7 +98,7 @@ static void client_info_free(struct client_info *cinfo)
struct node_info *info, *tmp;
spa_list_remove(&cinfo->link);
pw_signal_remove(&cinfo->resource_added);
pw_signal_remove(&cinfo->resource_impl);
pw_signal_remove(&cinfo->resource_removed);
spa_list_for_each_safe(info, tmp, &cinfo->node_list, link)
@ -278,10 +278,10 @@ on_node_added(struct impl *impl,
}
static void
on_resource_added(struct pw_listener *listener,
struct pw_client *client, struct pw_resource *resource)
on_resource_impl(struct pw_listener *listener,
struct pw_client *client, struct pw_resource *resource)
{
struct client_info *cinfo = SPA_CONTAINER_OF(listener, struct client_info, resource_added);
struct client_info *cinfo = SPA_CONTAINER_OF(listener, struct client_info, resource_impl);
struct impl *impl = cinfo->impl;
if (resource->type == impl->core->type.client_node) {
@ -325,7 +325,7 @@ on_global_added(struct pw_listener *listener, struct pw_core *core, struct pw_gl
spa_list_insert(impl->client_list.prev, &cinfo->link);
pw_signal_add(&client->resource_added, &cinfo->resource_added, on_resource_added);
pw_signal_add(&client->resource_impl, &cinfo->resource_impl, on_resource_impl);
pw_signal_add(&client->resource_removed, &cinfo->resource_removed,
on_resource_removed);

View file

@ -57,7 +57,7 @@ struct client_info {
const struct pw_core_methods *old_methods;
struct pw_core_methods core_methods;
struct spa_list async_pending;
struct pw_listener resource_added;
struct pw_listener resource_impl;
struct pw_listener resource_removed;
};
@ -422,11 +422,11 @@ do_create_link(void *object,
new_id);
}
static void on_resource_added(struct pw_listener *listener,
struct pw_client *client,
struct pw_resource *resource)
static void on_resource_impl(struct pw_listener *listener,
struct pw_client *client,
struct pw_resource *resource)
{
struct client_info *cinfo = SPA_CONTAINER_OF(listener, struct client_info, resource_added);
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) {
@ -455,7 +455,7 @@ on_global_added(struct pw_listener *listener, struct pw_core *core, struct pw_gl
cinfo->is_sandboxed = true;
spa_list_init(&cinfo->async_pending);
pw_signal_add(&client->resource_added, &cinfo->resource_added, on_resource_added);
pw_signal_add(&client->resource_impl, &cinfo->resource_impl, on_resource_impl);
spa_list_insert(impl->client_list.prev, &cinfo->link);

View file

@ -89,15 +89,16 @@ struct native_client {
struct pw_listener busy_changed;
};
static void client_destroy(struct native_client *this)
static void client_destroy(void *data)
{
struct pw_client *client = data;
struct native_client *this = client->user_data;
pw_loop_destroy_source(this->impl->core->main_loop->loop, this->source);
pw_client_destroy(this->client);
spa_list_remove(&this->link);
pw_connection_destroy(this->connection);
close(this->fd);
free(this);
}
static void
@ -126,14 +127,14 @@ process_messages(struct native_client *client)
if (opcode >= resource->iface->n_methods) {
pw_log_error("protocol-native %p: invalid method %u %u", client->impl,
id, opcode);
client_destroy(client);
pw_client_destroy(c);
break;
}
demarshal = resource->iface->methods;
if (!demarshal[opcode] || !demarshal[opcode] (resource, message, size)) {
pw_log_error("protocol-native %p: invalid message received %u %u",
client->impl, id, opcode);
client_destroy(client);
pw_client_destroy(c);
break;
}
if (c->busy) {
@ -146,7 +147,9 @@ static void
on_resource_added(struct pw_listener *listener,
struct pw_client *client, struct pw_resource *resource)
{
pw_protocol_native_server_setup(resource);
resource->iface = pw_protocol_get_interface(client->protocol,
spa_type_map_get_type(client->core->type.map, resource->type),
true);
}
static void
@ -183,7 +186,7 @@ connection_data(struct spa_loop_utils *utils,
if (mask & (SPA_IO_ERR | SPA_IO_HUP)) {
pw_log_error("protocol-native %p: got connection error", client->impl);
client_destroy(client);
pw_client_destroy(client->client);
return;
}
@ -198,10 +201,21 @@ static struct native_client *client_new(struct impl *impl, int fd)
socklen_t len;
struct ucred ucred, *ucredp;
this = calloc(1, sizeof(struct native_client));
if (this == NULL)
goto no_native_client;
len = sizeof(ucred);
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) {
pw_log_error("no peercred: %m");
ucredp = NULL;
} else {
ucredp = &ucred;
}
client = pw_client_new(impl->core, ucredp, NULL, sizeof(struct native_client));
if (client == NULL)
goto no_client;
client->destroy = client_destroy;
this = client->user_data;
this->impl = impl;
this->fd = fd;
this->source = pw_loop_add_io(impl->core->main_loop->loop,
@ -214,18 +228,7 @@ static struct native_client *client_new(struct impl *impl, int fd)
if (this->connection == NULL)
goto no_connection;
len = sizeof(ucred);
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) {
pw_log_error("no peercred: %m");
ucredp = NULL;
} else {
ucredp = &ucred;
}
client = pw_client_new(impl->core, ucredp, NULL);
if (client == NULL)
goto no_client;
client->protocol = pw_protocol_get(PW_TYPE_PROTOCOL__Native);
client->protocol_private = this->connection;
this->client = client;
@ -236,15 +239,14 @@ static struct native_client *client_new(struct impl *impl, int fd)
pw_signal_add(&client->busy_changed, &this->busy_changed, on_busy_changed);
pw_global_bind(impl->core->global, client, 0, 0);
return this;
no_client:
pw_connection_destroy(this->connection);
no_connection:
pw_loop_destroy_source(impl->core->main_loop->loop, this->source);
no_source:
free(this);
no_native_client:
no_client:
return NULL;
}
@ -461,6 +463,8 @@ static void pw_protocol_native_destroy(struct impl *impl)
bool pipewire__module_init(struct pw_module *module, const char *args)
{
pw_protocol_native_server_init();
pw_protocol_native_new(module->core, NULL);
return true;
}

View file

@ -1169,13 +1169,17 @@ struct pw_client_node *pw_client_node_new(struct pw_client *client,
this->resource = pw_resource_new(client,
id,
client->core->type.client_node,
this,
&client_node_methods,
(pw_destroy_t) client_node_resource_destroy);
client->core->type.client_node, 0);
if (this->resource == NULL)
goto error_no_resource;
pw_resource_set_implementation(this->resource,
this,
PW_VERSION_CLIENT_NODE,
&client_node_methods,
(pw_destroy_t) client_node_resource_destroy);
impl->proxy.resource = this->resource;
pw_signal_add(&this->node->free_signal, &impl->node_free, on_node_free);

View file

@ -26,7 +26,7 @@
extern "C" {
#endif
#define PIPEWIRE_TYPE__ClientNode "PipeWire:Object:ClientNode"
#define PIPEWIRE_TYPE__ClientNode PIPEWIRE_TYPE_NODE_BASE "Client"
#define PIPEWIRE_TYPE_CLIENT_NODE_BASE PIPEWIRE_TYPE__ClientNode ":"
/** \class pw_client_node

View file

@ -43,10 +43,12 @@ client_bind_func(struct pw_global *global, struct pw_client *client, uint32_t ve
struct pw_client *this = global->object;
struct pw_resource *resource;
resource = pw_resource_new(client, id, global->type, global->object, NULL, client_unbind_func);
resource = pw_resource_new(client, id, global->type, 0);
if (resource == NULL)
goto no_mem;
pw_resource_set_implementation(resource, global->object, PW_VERSION_CLIENT, NULL, client_unbind_func);
pw_log_debug("client %p: bound to %d", global->object, resource->id);
spa_list_insert(this->resource_list.prev, &resource->link);
@ -73,12 +75,14 @@ client_bind_func(struct pw_global *global, struct pw_client *client, uint32_t ve
* \memberof pw_client
*/
struct pw_client *pw_client_new(struct pw_core *core,
struct ucred *ucred, struct pw_properties *properties)
struct ucred *ucred,
struct pw_properties *properties,
size_t user_data_size)
{
struct pw_client *this;
struct impl *impl;
impl = calloc(1, sizeof(struct impl));
impl = calloc(1, sizeof(struct impl) + user_data_size);
if (impl == NULL)
return NULL;
@ -90,9 +94,13 @@ struct pw_client *pw_client_new(struct pw_core *core,
this->ucred = *ucred;
this->properties = properties;
if (user_data_size > 0)
this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void);
spa_list_init(&this->resource_list);
pw_signal_init(&this->properties_changed);
pw_signal_init(&this->resource_added);
pw_signal_init(&this->resource_impl);
pw_signal_init(&this->resource_removed);
pw_signal_init(&this->busy_changed);
@ -143,6 +151,9 @@ void pw_client_destroy(struct pw_client *client)
if (client->properties)
pw_properties_free(client->properties);
if (client->destroy)
client->destroy(client);
free(impl);
}

View file

@ -86,8 +86,6 @@ struct pw_client {
bool ucred_valid; /**< if the ucred member is valid */
struct ucred ucred; /**< ucred information */
void *protocol_private; /**< private data for the protocol implementation */
struct pw_resource *core_resource; /**< core resource object */
struct pw_map objects; /**< list of resource objects */
@ -98,6 +96,9 @@ struct pw_client {
/** Emited when a resource is added */
PW_SIGNAL(resource_added, (struct pw_listener *listener,
struct pw_client *client, struct pw_resource *resource));
/** Emited when a resource implementation is set */
PW_SIGNAL(resource_impl, (struct pw_listener *listener,
struct pw_client *client, struct pw_resource *resource));
/** Emited when a resource is removed */
PW_SIGNAL(resource_removed, (struct pw_listener *listener,
struct pw_client *client, struct pw_resource *resource));
@ -109,11 +110,19 @@ struct pw_client {
/** Emited when the client is destroyed */
PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_client *client));
struct pw_protocol *protocol; /**< protocol in use */
void *protocol_private; /**< private data for the protocol */
void *user_data; /**< extra user data */
pw_destroy_t destroy; /**< function to clean up the object */
};
struct pw_client *
pw_client_new(struct pw_core *core,
struct ucred *ucred, struct pw_properties *properties);
struct ucred *ucred,
struct pw_properties *properties,
size_t user_data_size);
void
pw_client_destroy(struct pw_client *client);

View file

@ -116,12 +116,16 @@ static void core_get_registry(void *object, uint32_t new_id)
registry_resource = pw_resource_new(client,
new_id,
this->type.registry,
this,
&registry_methods,
destroy_registry_resource);
0);
if (registry_resource == NULL)
goto no_mem;
pw_resource_set_implementation(registry_resource,
this,
PW_VERSION_REGISTRY,
&registry_methods,
destroy_registry_resource);
spa_list_insert(this->registry_resource_list.prev, &registry_resource->link);
spa_list_for_each(global, &this->global_list, link) {
@ -238,10 +242,13 @@ core_bind_func(struct pw_global *global, struct pw_client *client, uint32_t vers
struct pw_core *this = global->object;
struct pw_resource *resource;
resource = pw_resource_new(client, id, global->type, global->object, &core_methods, core_unbind_func);
resource = pw_resource_new(client, id, global->type, 0);
if (resource == NULL)
goto no_mem;
pw_resource_set_implementation(resource, global->object,
PW_VERSION_CORE, &core_methods, core_unbind_func);
spa_list_insert(this->resource_list.prev, &resource->link);
client->core_resource = resource;

View file

@ -834,10 +834,12 @@ link_bind_func(struct pw_global *global, struct pw_client *client, uint32_t vers
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
struct pw_resource *resource;
resource = pw_resource_new(client, id, global->type, global->object, NULL, link_unbind_func);
resource = pw_resource_new(client, id, global->type, 0);
if (resource == NULL)
goto no_mem;
pw_resource_set_implementation(resource, global->object, PW_VERSION_LINK, NULL, link_unbind_func);
impl->refcount++;
pw_log_debug("link %p: bound to %d", global->object, resource->id);

View file

@ -92,10 +92,12 @@ module_bind_func(struct pw_global *global, struct pw_client *client, uint32_t ve
struct pw_module *this = global->object;
struct pw_resource *resource;
resource = pw_resource_new(client, id, global->type, global->object, NULL, NULL);
resource = pw_resource_new(client, id, global->type, 0);
if (resource == NULL)
goto no_mem;
pw_resource_set_implementation(resource, global->object, PW_VERSION_MODULE, NULL, NULL);
pw_log_debug("module %p: bound to %d", global->object, resource->id);
this->info.change_mask = ~0;

View file

@ -475,10 +475,12 @@ node_bind_func(struct pw_global *global, struct pw_client *client, uint32_t vers
struct pw_node *this = global->object;
struct pw_resource *resource;
resource = pw_resource_new(client, id, global->type, global->object, NULL, node_unbind_func);
resource = pw_resource_new(client, id, global->type, 0);
if (resource == NULL)
goto no_mem;
pw_resource_set_implementation(resource, global->object, PW_VERSION_NODE, NULL, node_unbind_func);
pw_log_debug("node %p: bound to %d", this, resource->id);
spa_list_insert(this->resource_list.prev, &resource->link);

View file

@ -883,6 +883,8 @@ static const struct pw_core_events pw_protocol_native_server_core_events = {
};
const struct pw_interface pw_protocol_native_server_core_interface = {
PIPEWIRE_TYPE__Core,
PW_VERSION_CORE,
PW_CORE_METHOD_NUM, pw_protocol_native_server_core_demarshal,
PW_CORE_EVENT_NUM, &pw_protocol_native_server_core_events,
};
@ -897,6 +899,8 @@ static const struct pw_registry_events pw_protocol_native_server_registry_events
};
const struct pw_interface pw_protocol_native_server_registry_interface = {
PIPEWIRE_TYPE__Registry,
PW_VERSION_REGISTRY,
PW_REGISTRY_METHOD_NUM, pw_protocol_native_server_registry_demarshal,
PW_REGISTRY_EVENT_NUM, &pw_protocol_native_server_registry_events,
};
@ -906,6 +910,8 @@ static const struct pw_module_events pw_protocol_native_server_module_events = {
};
const struct pw_interface pw_protocol_native_server_module_interface = {
PIPEWIRE_TYPE__Module,
PW_VERSION_MODULE,
0, NULL,
PW_MODULE_EVENT_NUM, &pw_protocol_native_server_module_events,
};
@ -915,6 +921,8 @@ static const struct pw_node_events pw_protocol_native_server_node_events = {
};
const struct pw_interface pw_protocol_native_server_node_interface = {
PIPEWIRE_TYPE__Node,
PW_VERSION_NODE,
0, NULL,
PW_NODE_EVENT_NUM, &pw_protocol_native_server_node_events,
};
@ -924,6 +932,8 @@ static const struct pw_client_events pw_protocol_native_server_client_events = {
};
const struct pw_interface pw_protocol_native_server_client_interface = {
PIPEWIRE_TYPE__Client,
PW_VERSION_CLIENT,
0, NULL,
PW_CLIENT_EVENT_NUM, &pw_protocol_native_server_client_events,
};
@ -951,6 +961,8 @@ static const struct pw_client_node_events pw_protocol_native_server_client_node_
};
const struct pw_interface pw_protocol_native_server_client_node_interface = {
PIPEWIRE_TYPE_NODE_BASE "Client",
PW_VERSION_CLIENT_NODE,
PW_CLIENT_NODE_METHOD_NUM, &pw_protocol_native_server_client_node_demarshal,
PW_CLIENT_NODE_EVENT_NUM, &pw_protocol_native_server_client_node_events,
};
@ -960,29 +972,43 @@ static const struct pw_link_events pw_protocol_native_server_link_events = {
};
const struct pw_interface pw_protocol_native_server_link_interface = {
PIPEWIRE_TYPE__Link,
PW_VERSION_LINK,
0, NULL,
PW_LINK_EVENT_NUM, &pw_protocol_native_server_link_events,
};
bool pw_protocol_native_server_setup(struct pw_resource *resource)
void pw_protocol_native_server_init(void)
{
const struct pw_interface *iface;
if (resource->type == resource->core->type.core) {
iface = &pw_protocol_native_server_core_interface;
} else if (resource->type == resource->core->type.registry) {
iface = &pw_protocol_native_server_registry_interface;
} else if (resource->type == resource->core->type.module) {
iface = &pw_protocol_native_server_module_interface;
} else if (resource->type == resource->core->type.node) {
iface = &pw_protocol_native_server_node_interface;
} else if (resource->type == resource->core->type.client) {
iface = &pw_protocol_native_server_client_interface;
} else if (resource->type == resource->core->type.client_node) {
iface = &pw_protocol_native_server_client_node_interface;
} else if (resource->type == resource->core->type.link) {
iface = &pw_protocol_native_server_link_interface;
} else
return false;
resource->iface = iface;
return true;
static bool init = false;
struct pw_protocol *protocol;
if (init)
return;
protocol = pw_protocol_get(PW_TYPE_PROTOCOL__Native);
pw_protocol_add_interfaces(protocol,
NULL,
&pw_protocol_native_server_core_interface);
pw_protocol_add_interfaces(protocol,
NULL,
&pw_protocol_native_server_registry_interface);
pw_protocol_add_interfaces(protocol,
NULL,
&pw_protocol_native_server_module_interface);
pw_protocol_add_interfaces(protocol,
NULL,
&pw_protocol_native_server_node_interface);
pw_protocol_add_interfaces(protocol,
NULL,
&pw_protocol_native_server_client_node_interface);
pw_protocol_add_interfaces(protocol,
NULL,
&pw_protocol_native_server_client_interface);
pw_protocol_add_interfaces(protocol,
NULL,
&pw_protocol_native_server_link_interface);
init = true;
}

View file

@ -19,4 +19,4 @@
#include "pipewire/client/pipewire.h"
bool pw_protocol_native_server_setup(struct pw_resource *resource);
void pw_protocol_native_server_init(void);

View file

@ -31,14 +31,12 @@ struct impl {
struct pw_resource *pw_resource_new(struct pw_client *client,
uint32_t id,
uint32_t type,
void *object,
const void *implementation,
pw_destroy_t destroy)
size_t user_data_size)
{
struct impl *impl;
struct pw_resource *this;
impl = calloc(1, sizeof(struct impl));
impl = calloc(1, sizeof(struct impl) + user_data_size);
if (impl == NULL)
return NULL;
@ -46,20 +44,20 @@ struct pw_resource *pw_resource_new(struct pw_client *client,
this->core = client->core;
this->client = client;
this->type = type;
this->object = object;
this->implementation = implementation;
this->destroy = destroy;
pw_signal_init(&this->destroy_signal);
if (id == SPA_ID_INVALID) {
this->id = pw_map_insert_new(&client->objects, this);
id = pw_map_insert_new(&client->objects, this);
} else if (!pw_map_insert_at(&client->objects, id, this))
goto in_use;
this->id = id;
pw_log_debug("resource %p: new for client %p id %u", this, client, this->id);
if (user_data_size > 0)
this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void);
pw_log_debug("resource %p: new for client %p id %u", this, client, id);
pw_signal_emit(&client->resource_added, client, this);
return this;
@ -70,6 +68,24 @@ struct pw_resource *pw_resource_new(struct pw_client *client,
return NULL;
}
int
pw_resource_set_implementation(struct pw_resource *resource,
void *object,
uint32_t version,
const void *implementation,
pw_destroy_t destroy)
{
struct pw_client *client = resource->client;
resource->object = object;
resource->version = version;
resource->implementation = implementation;
resource->destroy = destroy;
pw_signal_emit(&client->resource_impl, client, resource);
return SPA_RESULT_OK;
}
void pw_resource_destroy(struct pw_resource *resource)
{
struct pw_client *client = resource->client;

View file

@ -64,25 +64,32 @@ struct pw_resource {
uint32_t id; /**< per client unique id, index in client objects */
uint32_t type; /**< type id of the object */
void *object; /**< pointer to the object */
pw_destroy_t destroy; /**< function to clean up the object */
const struct pw_interface *iface; /**< protocol specific interface functions */
const void *implementation; /**< implementation */
void *access_private; /**< private data for access control */
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 */
/** Emited when the resource is destroyed */
PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_resource *resource));
void *access_private; /**< private data for access control */
void *user_data; /**< extra user data */
};
struct pw_resource *
pw_resource_new(struct pw_client *client,
uint32_t id,
uint32_t type,
void *object,
const void *implementation,
pw_destroy_t destroy);
size_t user_data_size);
int
pw_resource_set_implementation(struct pw_resource *resource,
void *object,
uint32_t version,
const void *implementation,
pw_destroy_t destroy);
void
pw_resource_destroy(struct pw_resource *resource);