mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
remote: remove the remote
Mostly rename pw_remote_* to pw_core_proxy_*
This commit is contained in:
parent
3d79970d88
commit
ca6f1bd2f1
20 changed files with 608 additions and 1063 deletions
|
|
@ -581,7 +581,6 @@ on_remote_data(void *data, int fd, uint32_t mask)
|
|||
{
|
||||
struct client *impl = data;
|
||||
struct pw_core_proxy *this = impl->this.core_proxy;
|
||||
struct pw_remote *remote = pw_proxy_get_remote((struct pw_proxy*)this);
|
||||
struct pw_protocol_native_connection *conn = impl->connection;
|
||||
struct pw_core *core = pw_core_proxy_get_core(this);
|
||||
struct pw_loop *loop = pw_core_get_main_loop(core);
|
||||
|
|
@ -623,7 +622,7 @@ on_remote_data(void *data, int fd, uint32_t mask)
|
|||
pw_log_trace(NAME" %p: got message %d from %u seq:%d",
|
||||
this, msg->opcode, msg->id, msg->seq);
|
||||
|
||||
remote->recv_seq = msg->seq;
|
||||
this->recv_seq = msg->seq;
|
||||
|
||||
if (debug_messages) {
|
||||
fprintf(stderr, "<<<<<<<<< in: id:%d op:%d size:%d seq:%d\n",
|
||||
|
|
@ -672,7 +671,7 @@ error:
|
|||
pw_log_error(NAME" %p: got connection error %d (%s)", impl, res, spa_strerror(res));
|
||||
pw_proxy_notify((struct pw_proxy*)this,
|
||||
struct pw_core_proxy_events, error, 0, 0,
|
||||
remote->recv_seq, res, "connection error");
|
||||
this->recv_seq, res, "connection error");
|
||||
pw_loop_destroy_source(loop, impl->source);
|
||||
impl->source = NULL;
|
||||
pw_core_proxy_disconnect(this);
|
||||
|
|
@ -924,28 +923,28 @@ const static struct pw_protocol_implementaton protocol_impl = {
|
|||
static struct spa_pod_builder *
|
||||
impl_ext_begin_proxy(struct pw_proxy *proxy, uint8_t opcode, struct pw_protocol_native_message **msg)
|
||||
{
|
||||
struct client *impl = SPA_CONTAINER_OF(proxy->remote->conn, struct client, this);
|
||||
struct client *impl = SPA_CONTAINER_OF(proxy->core_proxy->conn, struct client, this);
|
||||
return pw_protocol_native_connection_begin(impl->connection, proxy->id, opcode, msg);
|
||||
}
|
||||
|
||||
static uint32_t impl_ext_add_proxy_fd(struct pw_proxy *proxy, int fd)
|
||||
{
|
||||
struct client *impl = SPA_CONTAINER_OF(proxy->remote->conn, struct client, this);
|
||||
struct client *impl = SPA_CONTAINER_OF(proxy->core_proxy->conn, struct client, this);
|
||||
return pw_protocol_native_connection_add_fd(impl->connection, fd);
|
||||
}
|
||||
|
||||
static int impl_ext_get_proxy_fd(struct pw_proxy *proxy, uint32_t index)
|
||||
{
|
||||
struct client *impl = SPA_CONTAINER_OF(proxy->remote->conn, struct client, this);
|
||||
struct client *impl = SPA_CONTAINER_OF(proxy->core_proxy->conn, struct client, this);
|
||||
return pw_protocol_native_connection_get_fd(impl->connection, index);
|
||||
}
|
||||
|
||||
static int impl_ext_end_proxy(struct pw_proxy *proxy,
|
||||
struct spa_pod_builder *builder)
|
||||
{
|
||||
struct client *impl = SPA_CONTAINER_OF(proxy->remote->conn, struct client, this);
|
||||
struct pw_remote *remote = proxy->remote;
|
||||
return remote->send_seq = pw_protocol_native_connection_end(impl->connection, builder);
|
||||
struct pw_core_proxy *core_proxy = proxy->core_proxy;
|
||||
struct client *impl = SPA_CONTAINER_OF(core_proxy->conn, struct client, this);
|
||||
return core_proxy->send_seq = pw_protocol_native_connection_end(impl->connection, builder);
|
||||
}
|
||||
|
||||
static struct spa_pod_builder *
|
||||
|
|
|
|||
429
src/pipewire/core-proxy.c
Normal file
429
src/pipewire/core-proxy.c
Normal file
|
|
@ -0,0 +1,429 @@
|
|||
/* PipeWire
|
||||
*
|
||||
* Copyright © 2018 Wim Taymans
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/debug/types.h>
|
||||
|
||||
#include "pipewire/pipewire.h"
|
||||
#include "pipewire/private.h"
|
||||
|
||||
#include "extensions/protocol-native.h"
|
||||
|
||||
#define NAME "core-proxy"
|
||||
|
||||
/** \cond */
|
||||
|
||||
/** \endcond */
|
||||
static void core_event_ping(void *data, uint32_t id, int seq)
|
||||
{
|
||||
struct pw_core_proxy *this = data;
|
||||
pw_log_debug(NAME" %p: object %u ping %u", this, id, seq);
|
||||
pw_core_proxy_pong(this->core_proxy, id, seq);
|
||||
}
|
||||
|
||||
static void core_event_done(void *data, uint32_t id, int seq)
|
||||
{
|
||||
struct pw_core_proxy *this = data;
|
||||
struct pw_proxy *proxy;
|
||||
|
||||
pw_log_trace(NAME" %p: object %u done %d", this, id, seq);
|
||||
|
||||
proxy = pw_map_lookup(&this->objects, id);
|
||||
if (proxy)
|
||||
pw_proxy_emit_done(proxy, seq);
|
||||
}
|
||||
|
||||
static void core_event_error(void *data, uint32_t id, int seq, int res, const char *message)
|
||||
{
|
||||
struct pw_core_proxy *this = data;
|
||||
struct pw_proxy *proxy;
|
||||
|
||||
pw_log_error(NAME" %p: object error %u: seq:%d %d (%s): %s", this, id, seq,
|
||||
res, spa_strerror(res), message);
|
||||
|
||||
proxy = pw_map_lookup(&this->objects, id);
|
||||
if (proxy)
|
||||
pw_proxy_emit_error(proxy, seq, res, message);
|
||||
}
|
||||
|
||||
static void core_event_remove_id(void *data, uint32_t id)
|
||||
{
|
||||
struct pw_core_proxy *this = data;
|
||||
struct pw_proxy *proxy;
|
||||
|
||||
pw_log_debug(NAME" %p: object remove %u", this, id);
|
||||
if ((proxy = pw_map_lookup(&this->objects, id)) != NULL)
|
||||
pw_proxy_remove(proxy);
|
||||
}
|
||||
|
||||
static void core_event_bound_id(void *data, uint32_t id, uint32_t global_id)
|
||||
{
|
||||
struct pw_core_proxy *this = data;
|
||||
struct pw_proxy *proxy;
|
||||
|
||||
pw_log_debug(NAME" %p: proxy %u bound %u", this, id, global_id);
|
||||
if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) {
|
||||
pw_proxy_emit_bound(proxy, global_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void core_event_add_mem(void *data, uint32_t id, uint32_t type, int fd, uint32_t flags)
|
||||
{
|
||||
struct pw_core_proxy *this = data;
|
||||
struct pw_memblock *m;
|
||||
|
||||
pw_log_debug(NAME" %p: add mem %u type:%u fd:%d flags:%u", this, id, type, fd, flags);
|
||||
|
||||
m = pw_mempool_import(this->pool, flags, type, fd);
|
||||
if (m->id != id) {
|
||||
pw_log_error(NAME" %p: invalid mem id %u, expected %u",
|
||||
this, id, m->id);
|
||||
pw_memblock_unref(m);
|
||||
}
|
||||
}
|
||||
|
||||
static void core_event_remove_mem(void *data, uint32_t id)
|
||||
{
|
||||
struct pw_core_proxy *this = data;
|
||||
pw_log_debug(NAME" %p: remove mem %u", this, id);
|
||||
pw_mempool_unref_id(this->pool, id);
|
||||
}
|
||||
|
||||
static const struct pw_core_proxy_events core_events = {
|
||||
PW_VERSION_CORE_PROXY_EVENTS,
|
||||
.error = core_event_error,
|
||||
.ping = core_event_ping,
|
||||
.done = core_event_done,
|
||||
.remove_id = core_event_remove_id,
|
||||
.bound_id = core_event_bound_id,
|
||||
.add_mem = core_event_add_mem,
|
||||
.remove_mem = core_event_remove_mem,
|
||||
};
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_core *pw_core_proxy_get_core(struct pw_core_proxy *core_proxy)
|
||||
{
|
||||
return core_proxy->core;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
const struct pw_properties *pw_core_proxy_get_properties(struct pw_core_proxy *core_proxy)
|
||||
{
|
||||
return core_proxy->properties;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
int pw_core_proxy_update_properties(struct pw_core_proxy *core_proxy, const struct spa_dict *dict)
|
||||
{
|
||||
int changed;
|
||||
|
||||
changed = pw_properties_update(core_proxy->properties, dict);
|
||||
|
||||
pw_log_debug(NAME" %p: updated %d properties", core_proxy, changed);
|
||||
|
||||
if (!changed)
|
||||
return 0;
|
||||
|
||||
if (core_proxy->client_proxy)
|
||||
pw_client_proxy_update_properties(core_proxy->client_proxy, &core_proxy->properties->dict);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
void *pw_core_proxy_get_user_data(struct pw_core_proxy *core_proxy)
|
||||
{
|
||||
return core_proxy->user_data;
|
||||
}
|
||||
|
||||
static int destroy_proxy(void *object, void *data)
|
||||
{
|
||||
struct pw_core_proxy *core_proxy = data;
|
||||
|
||||
if (object && object != core_proxy)
|
||||
pw_proxy_destroy(object);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void core_proxy_destroy(void *data)
|
||||
{
|
||||
struct pw_core_proxy *core_proxy = data;
|
||||
struct pw_stream *stream, *s2;
|
||||
struct pw_filter *filter;
|
||||
|
||||
pw_log_debug(NAME" %p: core proxy destroy", core_proxy);
|
||||
|
||||
spa_list_for_each_safe(stream, s2, &core_proxy->stream_list, link)
|
||||
pw_stream_disconnect(stream);
|
||||
|
||||
pw_protocol_client_disconnect(core_proxy->conn);
|
||||
|
||||
core_proxy->client_proxy = NULL;
|
||||
|
||||
pw_map_for_each(&core_proxy->objects, destroy_proxy, core_proxy);
|
||||
pw_map_reset(&core_proxy->objects);
|
||||
|
||||
pw_mempool_destroy(core_proxy->pool);
|
||||
|
||||
spa_list_consume(stream, &core_proxy->stream_list, link)
|
||||
pw_stream_destroy(stream);
|
||||
spa_list_consume(filter, &core_proxy->filter_list, link)
|
||||
pw_filter_destroy(filter);
|
||||
|
||||
pw_protocol_client_destroy(core_proxy->conn);
|
||||
|
||||
spa_list_remove(&core_proxy->link);
|
||||
|
||||
pw_map_clear(&core_proxy->objects);
|
||||
|
||||
pw_log_debug(NAME" %p: free", core_proxy);
|
||||
pw_properties_free(core_proxy->properties);
|
||||
}
|
||||
|
||||
static const struct pw_proxy_events core_proxy_events = {
|
||||
PW_VERSION_PROXY_EVENTS,
|
||||
.destroy = core_proxy_destroy,
|
||||
};
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_client_proxy * pw_core_proxy_get_client_proxy(struct pw_core_proxy *core_proxy)
|
||||
{
|
||||
return core_proxy->client_proxy;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_proxy *pw_core_proxy_find_proxy(struct pw_core_proxy *core_proxy, uint32_t id)
|
||||
{
|
||||
return pw_map_lookup(&core_proxy->objects, id);
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_proxy *pw_core_proxy_export(struct pw_core_proxy *core_proxy,
|
||||
uint32_t type, struct pw_properties *props, void *object,
|
||||
size_t user_data_size)
|
||||
{
|
||||
struct pw_proxy *proxy;
|
||||
const struct pw_export_type *t;
|
||||
int res;
|
||||
|
||||
t = pw_core_find_export_type(core_proxy->core, type);
|
||||
if (t == NULL) {
|
||||
res = -EPROTO;
|
||||
goto error_export_type;
|
||||
}
|
||||
|
||||
proxy = t->func(core_proxy, type, props, object, user_data_size);
|
||||
if (proxy == NULL) {
|
||||
res = -errno;
|
||||
goto error_proxy_failed;
|
||||
}
|
||||
return proxy;
|
||||
|
||||
error_export_type:
|
||||
pw_log_error(NAME" %p: can't export type %d: %s", core_proxy, type, spa_strerror(res));
|
||||
goto exit_free;
|
||||
error_proxy_failed:
|
||||
pw_log_error(NAME" %p: failed to create proxy: %s", core_proxy, spa_strerror(res));
|
||||
goto exit;
|
||||
exit_free:
|
||||
if (props)
|
||||
pw_properties_free(props);
|
||||
exit:
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct pw_core_proxy *core_proxy_new(struct pw_core *core,
|
||||
struct pw_properties *properties, size_t user_data_size)
|
||||
{
|
||||
struct pw_core_proxy *p;
|
||||
struct pw_protocol *protocol = NULL;
|
||||
const char *protocol_name;
|
||||
int res;
|
||||
|
||||
p = calloc(1, sizeof(struct pw_core_proxy) + user_data_size);
|
||||
if (p == NULL) {
|
||||
res = -errno;
|
||||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
if (properties == NULL)
|
||||
properties = pw_properties_new(NULL, NULL);
|
||||
if (properties == NULL)
|
||||
goto error_properties;
|
||||
|
||||
p->proxy.core_proxy = p;
|
||||
p->core = core;
|
||||
p->properties = properties;
|
||||
p->pool = pw_mempool_new(NULL);
|
||||
p->core_proxy = p;
|
||||
if (user_data_size > 0)
|
||||
p->user_data = SPA_MEMBER(p, sizeof(struct pw_core_proxy), void);
|
||||
p->proxy.user_data = p->user_data;
|
||||
|
||||
pw_map_init(&p->objects, 64, 32);
|
||||
spa_list_init(&p->stream_list);
|
||||
spa_list_init(&p->filter_list);
|
||||
|
||||
if ((protocol_name = pw_properties_get(properties, PW_KEY_PROTOCOL)) == NULL) {
|
||||
if ((protocol_name = pw_properties_get(core->properties, PW_KEY_PROTOCOL)) == NULL) {
|
||||
protocol_name = PW_TYPE_INFO_PROTOCOL_Native;
|
||||
if ((protocol = pw_core_find_protocol(core, protocol_name)) == NULL) {
|
||||
res = -ENOTSUP;
|
||||
goto error_protocol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (protocol == NULL)
|
||||
protocol = pw_core_find_protocol(core, protocol_name);
|
||||
if (protocol == NULL) {
|
||||
res = -ENOTSUP;
|
||||
goto error_protocol;
|
||||
}
|
||||
|
||||
p->conn = pw_protocol_new_client(protocol, properties);
|
||||
if (p->conn == NULL)
|
||||
goto error_connection;
|
||||
|
||||
p->conn->core_proxy = p;
|
||||
|
||||
if ((res = pw_proxy_init(&p->proxy, PW_TYPE_INTERFACE_Core, PW_VERSION_CORE_PROXY)) < 0)
|
||||
goto error_proxy;
|
||||
|
||||
p->client_proxy = (struct pw_client_proxy*)pw_proxy_new(&p->proxy,
|
||||
PW_TYPE_INTERFACE_Client, PW_VERSION_CLIENT_PROXY, 0);
|
||||
if (p->client_proxy == NULL) {
|
||||
res = -errno;
|
||||
goto error_proxy;
|
||||
}
|
||||
|
||||
pw_core_proxy_add_listener(p, &p->core_listener, &core_events, p);
|
||||
pw_proxy_add_listener(&p->proxy, &p->core_proxy_listener, &core_proxy_events, p);
|
||||
|
||||
pw_core_proxy_hello(p, PW_VERSION_CORE_PROXY);
|
||||
pw_client_proxy_update_properties(p->client_proxy, &p->properties->dict);
|
||||
|
||||
spa_list_append(&core->core_proxy_list, &p->link);
|
||||
|
||||
return p;
|
||||
|
||||
error_properties:
|
||||
res = -errno;
|
||||
pw_log_error(NAME" %p: can't create properties: %m", p);
|
||||
goto exit_free;
|
||||
error_protocol:
|
||||
pw_log_error(NAME" %p: can't find native protocol: %s", p, spa_strerror(res));
|
||||
goto exit_free;
|
||||
error_connection:
|
||||
res = -errno;
|
||||
pw_log_error(NAME" %p: can't create new native protocol connection: %m", p);
|
||||
goto exit_free;
|
||||
error_proxy:
|
||||
pw_log_error(NAME" %p: can't initialize proxy: %s", p, spa_strerror(res));
|
||||
goto exit_free;
|
||||
|
||||
exit_free:
|
||||
free(p);
|
||||
exit_cleanup:
|
||||
if (properties)
|
||||
pw_properties_free(properties);
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_core_proxy *
|
||||
pw_core_connect(struct pw_core *core, struct pw_properties *properties,
|
||||
size_t user_data_size)
|
||||
{
|
||||
struct pw_core_proxy *core_proxy;
|
||||
int res;
|
||||
|
||||
core_proxy = core_proxy_new(core, properties, user_data_size);
|
||||
if (core_proxy == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((res = pw_protocol_client_connect(core_proxy->conn,
|
||||
&core_proxy->properties->dict,
|
||||
NULL, NULL)) < 0)
|
||||
goto error_free;
|
||||
|
||||
return core_proxy;
|
||||
|
||||
error_free:
|
||||
pw_core_proxy_disconnect(core_proxy);
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_core_proxy *
|
||||
pw_core_connect_fd(struct pw_core *core, int fd, struct pw_properties *properties,
|
||||
size_t user_data_size)
|
||||
{
|
||||
struct pw_core_proxy *core_proxy;
|
||||
int res;
|
||||
|
||||
core_proxy = core_proxy_new(core, properties, user_data_size);
|
||||
if (core_proxy == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((res = pw_protocol_client_connect_fd(core_proxy->conn, fd, true)) < 0)
|
||||
goto error_free;
|
||||
|
||||
return core_proxy;
|
||||
|
||||
error_free:
|
||||
pw_core_proxy_disconnect(core_proxy);
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
int pw_core_proxy_steal_fd(struct pw_core_proxy *proxy)
|
||||
{
|
||||
return pw_protocol_client_steal_fd(proxy->conn);
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_mempool * pw_core_proxy_get_mempool(struct pw_core_proxy *proxy)
|
||||
{
|
||||
return proxy->pool;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
int pw_core_proxy_disconnect(struct pw_core_proxy *proxy)
|
||||
{
|
||||
pw_proxy_destroy(&proxy->proxy);
|
||||
return 0;
|
||||
}
|
||||
86
src/pipewire/core-proxy.h
Normal file
86
src/pipewire/core-proxy.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* PipeWire
|
||||
*
|
||||
* Copyright © 2018 Wim Taymans
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PIPEWIRE_REMOTE_H
|
||||
#define PIPEWIRE_REMOTE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <spa/utils/hook.h>
|
||||
|
||||
#include <pipewire/core.h>
|
||||
#include <pipewire/properties.h>
|
||||
#include <pipewire/node.h>
|
||||
#include <pipewire/proxy.h>
|
||||
|
||||
/** Connect to a PipeWire instance \memberof pw_core_proxy
|
||||
* \return a pw_core_proxy on success or NULL with errno set on error */
|
||||
struct pw_core_proxy *
|
||||
pw_core_connect(struct pw_core *core, /**< a \ref pw_core */
|
||||
struct pw_properties *properties, /**< optional properties, ownership of
|
||||
* the properties is taken.*/
|
||||
size_t user_data_size /**< extra user data size */);
|
||||
|
||||
/** Connect to a PipeWire instance on the given socket \memberof pw_core_proxy
|
||||
* \param fd the connected socket to use, the socket will be closed
|
||||
* automatically on disconnect or error.
|
||||
* \return a pw_core_proxy on success or NULL with errno set on error */
|
||||
struct pw_core_proxy *
|
||||
pw_core_connect_fd(struct pw_core *core, /**< a \ref pw_core */
|
||||
int fd, /**< an fd */
|
||||
struct pw_properties *properties, /**< optional properties, ownership of
|
||||
* the properties is taken.*/
|
||||
size_t user_data_size /**< extra user data size */);
|
||||
|
||||
/** Steal the fd of the core_proxy connection or < 0 on error. The core_proxy
|
||||
* will be disconnected after this call. */
|
||||
int pw_core_proxy_steal_fd(struct pw_core_proxy *core_proxy);
|
||||
|
||||
/** Get the core proxy, can only be called when connected */
|
||||
int pw_core_proxy_disconnect(struct pw_core_proxy *proxy);
|
||||
|
||||
/** Get the client proxy */
|
||||
struct pw_client_proxy * pw_core_proxy_get_client_proxy(struct pw_core_proxy *proxy);
|
||||
|
||||
struct pw_core * pw_core_proxy_get_core(struct pw_core_proxy *proxy);
|
||||
|
||||
struct pw_mempool * pw_core_proxy_get_mempool(struct pw_core_proxy *proxy);
|
||||
|
||||
/** Get the proxy with the given id */
|
||||
struct pw_proxy *pw_core_proxy_find_proxy(struct pw_core_proxy *proxy, uint32_t id);
|
||||
|
||||
struct pw_proxy *pw_core_proxy_export(struct pw_core_proxy *proxy, /**< the proxy */
|
||||
uint32_t type, /**< the type of object */
|
||||
struct pw_properties *properties, /**< extra properties */
|
||||
void *object, /**< object to export */
|
||||
size_t user_data_size /**< extra user data */);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PIPEWIRE_REMOTE_H */
|
||||
|
|
@ -570,7 +570,7 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop,
|
|||
pw_map_init(&this->globals, 128, 32);
|
||||
|
||||
spa_list_init(&this->protocol_list);
|
||||
spa_list_init(&this->remote_list);
|
||||
spa_list_init(&this->core_proxy_list);
|
||||
spa_list_init(&this->registry_resource_list);
|
||||
spa_list_init(&this->global_list);
|
||||
spa_list_init(&this->module_list);
|
||||
|
|
@ -660,7 +660,7 @@ void pw_core_destroy(struct pw_core *core)
|
|||
struct pw_global *global;
|
||||
struct pw_module *module;
|
||||
struct pw_device *device;
|
||||
struct pw_remote *remote;
|
||||
struct pw_core_proxy *core_proxy;
|
||||
struct pw_resource *resource;
|
||||
struct pw_node *node;
|
||||
struct factory_entry *entry;
|
||||
|
|
@ -670,8 +670,8 @@ void pw_core_destroy(struct pw_core *core)
|
|||
|
||||
spa_hook_remove(&core->global_listener);
|
||||
|
||||
spa_list_consume(remote, &core->remote_list, link)
|
||||
pw_remote_destroy(remote);
|
||||
spa_list_consume(core_proxy, &core->core_proxy_list, link)
|
||||
pw_core_proxy_disconnect(core_proxy);
|
||||
|
||||
spa_list_consume(module, &core->module_list, link)
|
||||
pw_module_destroy(module);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ struct pw_core;
|
|||
#include <pipewire/client.h>
|
||||
#include <pipewire/introspect.h>
|
||||
#include <pipewire/interfaces.h>
|
||||
#include <pipewire/remote.h>
|
||||
#include <pipewire/core-proxy.h>
|
||||
#include <pipewire/global.h>
|
||||
#include <pipewire/loop.h>
|
||||
#include <pipewire/factory.h>
|
||||
|
|
|
|||
|
|
@ -947,8 +947,6 @@ filter_new(struct pw_core *core, const char *name,
|
|||
|
||||
impl->core = core;
|
||||
|
||||
// spa_list_append(&remote->filter_list, &this->link);
|
||||
|
||||
return impl;
|
||||
|
||||
error_properties:
|
||||
|
|
@ -1048,7 +1046,6 @@ void pw_filter_destroy(struct pw_filter *filter)
|
|||
spa_hook_remove(&filter->core_listener);
|
||||
filter->core_proxy = NULL;
|
||||
}
|
||||
// spa_list_remove(&filter->link);
|
||||
|
||||
clear_params(impl, NULL, SPA_ID_INVALID);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ struct pw_filter;
|
|||
#include <spa/node/io.h>
|
||||
#include <spa/param/param.h>
|
||||
|
||||
#include <pipewire/remote.h>
|
||||
#include <pipewire/core-proxy.h>
|
||||
|
||||
/** \enum pw_filter_state The state of a filter \memberof pw_filter */
|
||||
enum pw_filter_state {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
#include "pipewire/pipewire.h"
|
||||
|
||||
#include "pipewire/remote.h"
|
||||
#include "pipewire/core-proxy.h"
|
||||
|
||||
SPA_EXPORT
|
||||
const char *pw_node_state_as_string(enum pw_node_state state)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ pipewire_headers = [
|
|||
'properties.h',
|
||||
'protocol.h',
|
||||
'proxy.h',
|
||||
'remote.h',
|
||||
'core-proxy.h',
|
||||
'resource.h',
|
||||
'stream.h',
|
||||
'thread-loop.h',
|
||||
|
|
@ -58,7 +58,7 @@ pipewire_sources = [
|
|||
'properties.c',
|
||||
'protocol.c',
|
||||
'proxy.c',
|
||||
'remote.c',
|
||||
'core-proxy.c',
|
||||
'resource.c',
|
||||
'stream.c',
|
||||
'thread-loop.c',
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ extern "C" {
|
|||
#include <pipewire/port.h>
|
||||
#include <pipewire/properties.h>
|
||||
#include <pipewire/proxy.h>
|
||||
#include <pipewire/remote.h>
|
||||
#include <pipewire/core-proxy.h>
|
||||
#include <pipewire/resource.h>
|
||||
#include <pipewire/stream.h>
|
||||
#include <pipewire/thread-loop.h>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ extern "C" {
|
|||
|
||||
#include "pipewire/buffers.h"
|
||||
#include "pipewire/map.h"
|
||||
#include "pipewire/remote.h"
|
||||
#include "pipewire/mem.h"
|
||||
#include "pipewire/introspect.h"
|
||||
#include "pipewire/interfaces.h"
|
||||
|
|
@ -222,7 +221,7 @@ struct pw_core {
|
|||
struct pw_map globals; /**< map of globals */
|
||||
|
||||
struct spa_list protocol_list; /**< list of protocols */
|
||||
struct spa_list remote_list; /**< list of remote connections */
|
||||
struct spa_list core_proxy_list; /**< list of remote connections */
|
||||
struct spa_list registry_resource_list; /**< list of registry resources */
|
||||
struct spa_list module_list; /**< list of modules */
|
||||
struct spa_list device_list; /**< list of devices */
|
||||
|
|
@ -713,7 +712,7 @@ struct pw_resource {
|
|||
struct pw_proxy {
|
||||
struct spa_interface impl; /**< object implementation */
|
||||
|
||||
struct pw_remote *remote; /**< the owner remote of this proxy */
|
||||
struct pw_core_proxy *core_proxy; /**< the owner core_proxy of this proxy */
|
||||
|
||||
uint32_t id; /**< client side id */
|
||||
uint32_t type; /**< type of the interface */
|
||||
|
|
@ -731,17 +730,18 @@ struct pw_proxy {
|
|||
void *user_data; /**< extra user data */
|
||||
};
|
||||
|
||||
#define pw_remote_emit(r,m,v,...) spa_hook_list_call(&r->listener_list, struct pw_remote_events, m, v, ##__VA_ARGS__)
|
||||
#define pw_remote_emit_destroy(r) pw_remote_emit(r, destroy, 0)
|
||||
#define pw_remote_emit_state_changed(r,o,s,e) pw_remote_emit(r, state_changed, 0, o, s, e)
|
||||
struct pw_core_proxy {
|
||||
struct pw_proxy proxy;
|
||||
|
||||
struct pw_remote {
|
||||
struct pw_core *core; /**< core */
|
||||
struct spa_list link; /**< link in core remote_list */
|
||||
struct spa_list link; /**< link in core core_proxy_list */
|
||||
struct pw_properties *properties; /**< extra properties */
|
||||
|
||||
struct pw_mempool *pool; /**< memory pool */
|
||||
struct pw_core_proxy *core_proxy; /**< proxy for the core object */
|
||||
struct spa_hook core_listener;
|
||||
struct spa_hook core_proxy_listener;
|
||||
|
||||
struct pw_map objects; /**< map of client side proxy objects
|
||||
* indexed with the client id */
|
||||
struct pw_client_proxy *client_proxy; /**< proxy for the client object */
|
||||
|
|
@ -899,6 +899,8 @@ pw_core_find_port(struct pw_core *core,
|
|||
|
||||
const struct pw_export_type *pw_core_find_export_type(struct pw_core *core, uint32_t type);
|
||||
|
||||
int pw_proxy_init(struct pw_proxy *proxy, uint32_t type, uint32_t version);
|
||||
|
||||
int pw_proxy_install_marshal(struct pw_proxy *proxy, bool implementor);
|
||||
void pw_proxy_remove(struct pw_proxy *proxy);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <pipewire/log.h>
|
||||
#include <pipewire/proxy.h>
|
||||
#include <pipewire/core.h>
|
||||
#include <pipewire/remote.h>
|
||||
#include <pipewire/private.h>
|
||||
#include <pipewire/type.h>
|
||||
#include <pipewire/interfaces.h>
|
||||
|
|
@ -40,6 +39,38 @@ struct proxy {
|
|||
};
|
||||
/** \endcond */
|
||||
|
||||
int pw_proxy_init(struct pw_proxy *proxy, uint32_t type, uint32_t version)
|
||||
{
|
||||
int res;
|
||||
|
||||
proxy->refcount = 1;
|
||||
proxy->type = type;
|
||||
proxy->version = version;
|
||||
|
||||
proxy->id = pw_map_insert_new(&proxy->core_proxy->objects, proxy);
|
||||
if (proxy->id == SPA_ID_INVALID) {
|
||||
res = -errno;
|
||||
pw_log_error(NAME" %p: can't allocate new id: %m", proxy);
|
||||
goto error;
|
||||
}
|
||||
|
||||
spa_hook_list_init(&proxy->listener_list);
|
||||
spa_hook_list_init(&proxy->object_listener_list);
|
||||
|
||||
if ((res = pw_proxy_install_marshal(proxy, false)) < 0) {
|
||||
pw_log_error(NAME" %p: no marshal for type %s/%d", proxy,
|
||||
spa_debug_type_find_name(pw_type_info(), type),
|
||||
version);
|
||||
goto error_clean;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error_clean:
|
||||
pw_map_remove(&proxy->core_proxy->objects, proxy->id);
|
||||
error:
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Create a proxy object with a given id and type
|
||||
*
|
||||
* \param factory another proxy object that serves as a factory
|
||||
|
|
@ -50,7 +81,7 @@ struct proxy {
|
|||
* This function creates a new proxy object with the supplied id and type. The
|
||||
* proxy object will have an id assigned from the client id space.
|
||||
*
|
||||
* \sa pw_remote
|
||||
* \sa pw_core_proxy
|
||||
*
|
||||
* \memberof pw_proxy
|
||||
*/
|
||||
|
|
@ -61,7 +92,6 @@ struct pw_proxy *pw_proxy_new(struct pw_proxy *factory,
|
|||
{
|
||||
struct proxy *impl;
|
||||
struct pw_proxy *this;
|
||||
struct pw_remote *remote = factory->remote;
|
||||
int res;
|
||||
|
||||
impl = calloc(1, sizeof(struct proxy) + user_data_size);
|
||||
|
|
@ -69,38 +99,21 @@ struct pw_proxy *pw_proxy_new(struct pw_proxy *factory,
|
|||
return NULL;
|
||||
|
||||
this = &impl->this;
|
||||
this->remote = remote;
|
||||
this->refcount = 1;
|
||||
this->type = type;
|
||||
this->version = version;
|
||||
this->core_proxy = factory->core_proxy;
|
||||
|
||||
this->id = pw_map_insert_new(&remote->objects, this);
|
||||
if (this->id == SPA_ID_INVALID) {
|
||||
res = -errno;
|
||||
pw_log_error(NAME" %p: can't allocate new id: %m", this);
|
||||
goto error_clean;
|
||||
}
|
||||
|
||||
spa_hook_list_init(&this->listener_list);
|
||||
spa_hook_list_init(&this->object_listener_list);
|
||||
|
||||
if ((res = pw_proxy_install_marshal(this, false)) < 0) {
|
||||
pw_log_error(NAME" %p: no marshal for type %s/%d", this,
|
||||
spa_debug_type_find_name(pw_type_info(), type),
|
||||
version);
|
||||
goto error_clean;
|
||||
}
|
||||
if ((res = pw_proxy_init(this, type, version)) < 0)
|
||||
goto error_init;
|
||||
|
||||
if (user_data_size > 0)
|
||||
this->user_data = SPA_MEMBER(impl, sizeof(struct proxy), void);
|
||||
|
||||
pw_log_debug(NAME" %p: new %u type %s/%d remote:%p, marshal:%p",
|
||||
pw_log_debug(NAME" %p: new %u type %s/%d core-proxy:%p, marshal:%p",
|
||||
this, this->id,
|
||||
spa_debug_type_find_name(pw_type_info(), type), version,
|
||||
remote, this->marshal);
|
||||
this->core_proxy, this->marshal);
|
||||
return this;
|
||||
|
||||
error_clean:
|
||||
error_init:
|
||||
free(impl);
|
||||
errno = -res;
|
||||
return NULL;
|
||||
|
|
@ -109,10 +122,10 @@ error_clean:
|
|||
SPA_EXPORT
|
||||
int pw_proxy_install_marshal(struct pw_proxy *this, bool implementor)
|
||||
{
|
||||
struct pw_remote *remote = this->remote;
|
||||
struct pw_core_proxy *core_proxy = this->core_proxy;
|
||||
const struct pw_protocol_marshal *marshal;
|
||||
|
||||
marshal = pw_protocol_get_marshal(remote->conn->protocol,
|
||||
marshal = pw_protocol_get_marshal(core_proxy->conn->protocol,
|
||||
this->type, this->version,
|
||||
implementor ? PW_PROTOCOL_MARSHAL_FLAG_IMPL : 0);
|
||||
if (marshal == NULL)
|
||||
|
|
@ -147,15 +160,15 @@ uint32_t pw_proxy_get_type(struct pw_proxy *proxy, uint32_t *version)
|
|||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_remote *pw_proxy_get_remote(struct pw_proxy *proxy)
|
||||
struct pw_core_proxy *pw_proxy_get_core_proxy(struct pw_proxy *proxy)
|
||||
{
|
||||
return proxy->remote;
|
||||
return proxy->core_proxy;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy)
|
||||
{
|
||||
return proxy->remote->conn->protocol;
|
||||
return proxy->core_proxy->conn->protocol;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
|
|
@ -180,14 +193,14 @@ void pw_proxy_add_object_listener(struct pw_proxy *proxy,
|
|||
*
|
||||
* \param proxy Proxy object to destroy
|
||||
*
|
||||
* \note This is normally called by \ref pw_remote when the server
|
||||
* \note This is normally called by \ref pw_core_proxy when the server
|
||||
* decides to destroy the server side object
|
||||
* \memberof pw_proxy
|
||||
*/
|
||||
SPA_EXPORT
|
||||
void pw_proxy_destroy(struct pw_proxy *proxy)
|
||||
{
|
||||
struct pw_remote *remote = proxy->remote;
|
||||
struct pw_core_proxy *core_proxy = proxy->core_proxy;
|
||||
|
||||
if (!proxy->zombie) {
|
||||
pw_log_debug(NAME" %p: destroy %u", proxy, proxy->id);
|
||||
|
|
@ -196,15 +209,15 @@ void pw_proxy_destroy(struct pw_proxy *proxy)
|
|||
if (!proxy->removed) {
|
||||
/* if the server did not remove this proxy, remove ourselves
|
||||
* from the proxy objects and schedule a destroy. */
|
||||
if (remote->core_proxy) {
|
||||
if (core_proxy) {
|
||||
proxy->zombie = true;
|
||||
pw_core_proxy_destroy(remote->core_proxy, proxy);
|
||||
pw_core_proxy_destroy(core_proxy, proxy);
|
||||
} else {
|
||||
proxy->removed = true;
|
||||
}
|
||||
}
|
||||
if (proxy->removed) {
|
||||
pw_map_remove(&remote->objects, proxy->id);
|
||||
pw_map_remove(&core_proxy->objects, proxy->id);
|
||||
|
||||
pw_proxy_unref(proxy);
|
||||
}
|
||||
|
|
@ -230,10 +243,10 @@ SPA_EXPORT
|
|||
int pw_proxy_sync(struct pw_proxy *proxy, int seq)
|
||||
{
|
||||
int res = -EIO;
|
||||
struct pw_remote *remote = proxy->remote;
|
||||
struct pw_core_proxy *core_proxy = proxy->core_proxy;
|
||||
|
||||
if (remote->core_proxy != NULL) {
|
||||
res = pw_core_proxy_sync(remote->core_proxy, proxy->id, seq);
|
||||
if (core_proxy != NULL) {
|
||||
res = pw_core_proxy_sync(core_proxy, proxy->id, seq);
|
||||
pw_log_debug(NAME" %p: %u seq:%d sync %u", proxy, proxy->id, seq, res);
|
||||
}
|
||||
return res;
|
||||
|
|
@ -244,12 +257,12 @@ int pw_proxy_errorf(struct pw_proxy *proxy, int res, const char *error, ...)
|
|||
{
|
||||
va_list ap;
|
||||
int r = -EIO;
|
||||
struct pw_remote *remote = proxy->remote;
|
||||
struct pw_core_proxy *core_proxy = proxy->core_proxy;
|
||||
|
||||
va_start(ap, error);
|
||||
if (remote->core_proxy != NULL)
|
||||
r = pw_core_proxy_errorv(remote->core_proxy, proxy->id,
|
||||
remote->recv_seq, res, error, ap);
|
||||
if (core_proxy != NULL)
|
||||
r = pw_core_proxy_errorv(core_proxy, proxy->id,
|
||||
core_proxy->recv_seq, res, error, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
|
|
@ -258,10 +271,10 @@ SPA_EXPORT
|
|||
int pw_proxy_error(struct pw_proxy *proxy, int res, const char *error)
|
||||
{
|
||||
int r = -EIO;
|
||||
struct pw_remote *remote = proxy->remote;
|
||||
if (remote->core_proxy != NULL)
|
||||
r = pw_core_proxy_error(remote->core_proxy, proxy->id,
|
||||
remote->recv_seq, res, error);
|
||||
struct pw_core_proxy *core_proxy = proxy->core_proxy;
|
||||
if (core_proxy != NULL)
|
||||
r = pw_core_proxy_error(core_proxy, proxy->id,
|
||||
core_proxy->recv_seq, res, error);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,9 +43,8 @@ extern "C" {
|
|||
* \section sec_page_proxy_core Core proxy
|
||||
*
|
||||
* A proxy for a remote core object can be obtained by making
|
||||
* a remote connection. See \ref pw_page_remote_api
|
||||
*
|
||||
* A pw_core_proxy can then be retrieved with \ref pw_remote_get_core_proxy
|
||||
* a remote connection with \ref pw_core_connect.
|
||||
* See \ref pw_page_remote_api
|
||||
*
|
||||
* Some methods on proxy object allow creation of more proxy objects or
|
||||
* create a binding between a local proxy and global resource.
|
||||
|
|
@ -154,9 +153,6 @@ uint32_t pw_proxy_get_id(struct pw_proxy *proxy);
|
|||
/** Get the type and version of the proxy */
|
||||
uint32_t pw_proxy_get_type(struct pw_proxy *proxy, uint32_t *version);
|
||||
|
||||
/** Get the remote managing this proxy */
|
||||
struct pw_remote *pw_proxy_get_remote(struct pw_proxy *proxy);
|
||||
|
||||
/** Get the protocol used for the proxy */
|
||||
struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,572 +0,0 @@
|
|||
/* PipeWire
|
||||
*
|
||||
* Copyright © 2018 Wim Taymans
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/debug/types.h>
|
||||
|
||||
#include "pipewire/pipewire.h"
|
||||
#include "pipewire/private.h"
|
||||
|
||||
#include "extensions/protocol-native.h"
|
||||
|
||||
#define NAME "remote"
|
||||
|
||||
/** \cond */
|
||||
|
||||
struct remote {
|
||||
struct pw_remote this;
|
||||
struct spa_hook core_listener;
|
||||
struct spa_hook core_proxy_listener;
|
||||
size_t user_data_size;
|
||||
};
|
||||
|
||||
/** \endcond */
|
||||
static void core_event_ping(void *data, uint32_t id, int seq)
|
||||
{
|
||||
struct pw_remote *this = data;
|
||||
pw_log_debug(NAME" %p: object %u ping %u", this, id, seq);
|
||||
pw_core_proxy_pong(this->core_proxy, id, seq);
|
||||
}
|
||||
|
||||
static void core_event_done(void *data, uint32_t id, int seq)
|
||||
{
|
||||
struct pw_remote *this = data;
|
||||
struct pw_proxy *proxy;
|
||||
|
||||
pw_log_trace(NAME" %p: object %u done %d", this, id, seq);
|
||||
|
||||
proxy = pw_map_lookup(&this->objects, id);
|
||||
if (proxy)
|
||||
pw_proxy_emit_done(proxy, seq);
|
||||
}
|
||||
|
||||
static void core_event_error(void *data, uint32_t id, int seq, int res, const char *message)
|
||||
{
|
||||
struct pw_remote *this = data;
|
||||
struct pw_proxy *proxy;
|
||||
|
||||
pw_log_error(NAME" %p: object error %u: seq:%d %d (%s): %s", this, id, seq,
|
||||
res, spa_strerror(res), message);
|
||||
|
||||
proxy = pw_map_lookup(&this->objects, id);
|
||||
if (proxy)
|
||||
pw_proxy_emit_error(proxy, seq, res, message);
|
||||
}
|
||||
|
||||
static void core_event_remove_id(void *data, uint32_t id)
|
||||
{
|
||||
struct pw_remote *this = data;
|
||||
struct pw_proxy *proxy;
|
||||
|
||||
pw_log_debug(NAME" %p: object remove %u", this, id);
|
||||
if ((proxy = pw_map_lookup(&this->objects, id)) != NULL)
|
||||
pw_proxy_remove(proxy);
|
||||
}
|
||||
|
||||
static void core_event_bound_id(void *data, uint32_t id, uint32_t global_id)
|
||||
{
|
||||
struct pw_remote *this = data;
|
||||
struct pw_proxy *proxy;
|
||||
|
||||
pw_log_debug(NAME" %p: proxy %u bound %u", this, id, global_id);
|
||||
if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) {
|
||||
pw_proxy_emit_bound(proxy, global_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void core_event_add_mem(void *data, uint32_t id, uint32_t type, int fd, uint32_t flags)
|
||||
{
|
||||
struct pw_remote *this = data;
|
||||
struct pw_memblock *m;
|
||||
|
||||
pw_log_debug(NAME" %p: add mem %u type:%u fd:%d flags:%u", this, id, type, fd, flags);
|
||||
|
||||
m = pw_mempool_import(this->pool, flags, type, fd);
|
||||
if (m->id != id) {
|
||||
pw_log_error(NAME" %p: invalid mem id %u, expected %u",
|
||||
this, id, m->id);
|
||||
pw_memblock_unref(m);
|
||||
}
|
||||
}
|
||||
|
||||
static void core_event_remove_mem(void *data, uint32_t id)
|
||||
{
|
||||
struct pw_remote *this = data;
|
||||
pw_log_debug(NAME" %p: remove mem %u", this, id);
|
||||
pw_mempool_unref_id(this->pool, id);
|
||||
}
|
||||
|
||||
static const struct pw_core_proxy_events core_events = {
|
||||
PW_VERSION_CORE_PROXY_EVENTS,
|
||||
.error = core_event_error,
|
||||
.ping = core_event_ping,
|
||||
.done = core_event_done,
|
||||
.remove_id = core_event_remove_id,
|
||||
.bound_id = core_event_bound_id,
|
||||
.add_mem = core_event_add_mem,
|
||||
.remove_mem = core_event_remove_mem,
|
||||
};
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_remote *pw_remote_new(struct pw_core *core,
|
||||
struct pw_properties *properties,
|
||||
size_t user_data_size)
|
||||
{
|
||||
struct remote *impl;
|
||||
struct pw_remote *this;
|
||||
struct pw_protocol *protocol = NULL;
|
||||
const char *protocol_name;
|
||||
int res;
|
||||
|
||||
impl = calloc(1, sizeof(struct remote) + user_data_size);
|
||||
if (impl == NULL) {
|
||||
res = -errno;
|
||||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
this = &impl->this;
|
||||
pw_log_debug(NAME" %p: new", impl);
|
||||
|
||||
this->core = core;
|
||||
impl->user_data_size = user_data_size;
|
||||
|
||||
if (user_data_size > 0)
|
||||
this->user_data = SPA_MEMBER(impl, sizeof(struct remote), void);
|
||||
|
||||
if (properties == NULL)
|
||||
properties = pw_properties_new(NULL, NULL);
|
||||
if (properties == NULL)
|
||||
goto error_properties;
|
||||
|
||||
pw_fill_remote_properties(core, properties);
|
||||
this->properties = properties;
|
||||
|
||||
pw_map_init(&this->objects, 64, 32);
|
||||
|
||||
spa_list_init(&this->stream_list);
|
||||
spa_list_init(&this->filter_list);
|
||||
|
||||
if ((protocol_name = pw_properties_get(properties, PW_KEY_PROTOCOL)) == NULL) {
|
||||
if ((protocol_name = pw_properties_get(core->properties, PW_KEY_PROTOCOL)) == NULL) {
|
||||
protocol_name = PW_TYPE_INFO_PROTOCOL_Native;
|
||||
if ((protocol = pw_core_find_protocol(core, protocol_name)) == NULL) {
|
||||
goto error_protocol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (protocol == NULL)
|
||||
protocol = pw_core_find_protocol(core, protocol_name);
|
||||
if (protocol == NULL) {
|
||||
res = -ENOTSUP;
|
||||
goto error_protocol;
|
||||
}
|
||||
|
||||
this->conn = pw_protocol_new_client(protocol, properties);
|
||||
if (this->conn == NULL)
|
||||
goto error_connection;
|
||||
|
||||
spa_list_append(&core->remote_list, &this->link);
|
||||
|
||||
return this;
|
||||
|
||||
error_properties:
|
||||
res = -errno;
|
||||
pw_log_error(NAME" %p: can't create properties: %m", this);
|
||||
goto exit_free;
|
||||
error_protocol:
|
||||
pw_log_error(NAME" %p: can't load native protocol: %s", this, spa_strerror(res));
|
||||
goto exit_free;
|
||||
error_connection:
|
||||
res = -errno;
|
||||
pw_log_error(NAME" %p: can't create new native protocol connection: %m", this);
|
||||
goto exit_free;
|
||||
|
||||
exit_free:
|
||||
free(impl);
|
||||
exit_cleanup:
|
||||
if (properties)
|
||||
pw_properties_free(properties);
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
void pw_remote_destroy(struct pw_remote *remote)
|
||||
{
|
||||
struct remote *impl = SPA_CONTAINER_OF(remote, struct remote, this);
|
||||
struct pw_stream *stream;
|
||||
struct pw_filter *filter;
|
||||
|
||||
pw_log_debug(NAME" %p: destroy", remote);
|
||||
|
||||
pw_remote_disconnect(remote);
|
||||
|
||||
spa_list_consume(stream, &remote->stream_list, link)
|
||||
pw_stream_destroy(stream);
|
||||
spa_list_consume(filter, &remote->filter_list, link)
|
||||
pw_filter_destroy(filter);
|
||||
|
||||
pw_protocol_client_destroy(remote->conn);
|
||||
|
||||
spa_list_remove(&remote->link);
|
||||
|
||||
pw_map_clear(&remote->objects);
|
||||
|
||||
pw_log_debug(NAME" %p: free", remote);
|
||||
pw_properties_free(remote->properties);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_core *pw_remote_get_core(struct pw_remote *remote)
|
||||
{
|
||||
return remote->core;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
const struct pw_properties *pw_remote_get_properties(struct pw_remote *remote)
|
||||
{
|
||||
return remote->properties;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
int pw_remote_update_properties(struct pw_remote *remote, const struct spa_dict *dict)
|
||||
{
|
||||
int changed;
|
||||
|
||||
changed = pw_properties_update(remote->properties, dict);
|
||||
|
||||
pw_log_debug(NAME" %p: updated %d properties", remote, changed);
|
||||
|
||||
if (!changed)
|
||||
return 0;
|
||||
|
||||
if (remote->client_proxy)
|
||||
pw_client_proxy_update_properties(remote->client_proxy, &remote->properties->dict);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
void *pw_remote_get_user_data(struct pw_remote *remote)
|
||||
{
|
||||
return remote->user_data;
|
||||
}
|
||||
|
||||
static void core_proxy_destroy(void *data)
|
||||
{
|
||||
struct pw_remote *remote = data;
|
||||
struct remote *impl = SPA_CONTAINER_OF(remote, struct remote, this);
|
||||
|
||||
pw_log_debug(NAME" %p: core proxy destroy", remote);
|
||||
if (remote->core_proxy) {
|
||||
spa_hook_remove(&impl->core_proxy_listener);
|
||||
spa_hook_remove(&impl->core_listener);
|
||||
remote->core_proxy = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const struct pw_proxy_events core_proxy_events = {
|
||||
PW_VERSION_PROXY_EVENTS,
|
||||
.destroy = core_proxy_destroy,
|
||||
};
|
||||
|
||||
static int init_connect(struct pw_remote *remote)
|
||||
{
|
||||
struct remote *impl = SPA_CONTAINER_OF(remote, struct remote, this);
|
||||
struct pw_proxy dummy, *core_proxy;
|
||||
int res;
|
||||
|
||||
spa_zero(dummy);
|
||||
dummy.remote = remote;
|
||||
|
||||
core_proxy = pw_proxy_new(&dummy,
|
||||
PW_TYPE_INTERFACE_Core,
|
||||
PW_VERSION_CORE_PROXY,
|
||||
impl->user_data_size);
|
||||
if (core_proxy == NULL) {
|
||||
res = -errno;
|
||||
goto error;
|
||||
}
|
||||
remote->core_proxy = (struct pw_core_proxy*)core_proxy;
|
||||
|
||||
remote->client_proxy = (struct pw_client_proxy*)pw_proxy_new(&dummy,
|
||||
PW_TYPE_INTERFACE_Client, PW_VERSION_CLIENT_PROXY, 0);
|
||||
if (remote->client_proxy == NULL) {
|
||||
res = -errno;
|
||||
goto error_clean_core_proxy;
|
||||
}
|
||||
remote->pool = pw_mempool_new(NULL);
|
||||
|
||||
pw_core_proxy_add_listener(remote->core_proxy, &impl->core_listener, &core_events, remote);
|
||||
pw_proxy_add_listener(core_proxy, &impl->core_proxy_listener, &core_proxy_events, remote);
|
||||
|
||||
pw_core_proxy_hello(remote->core_proxy, PW_VERSION_CORE_PROXY);
|
||||
pw_client_proxy_update_properties(remote->client_proxy, &remote->properties->dict);
|
||||
|
||||
remote->conn->core_proxy = remote->core_proxy;
|
||||
|
||||
return 0;
|
||||
|
||||
error_clean_core_proxy:
|
||||
pw_proxy_remove((struct pw_proxy*)remote->core_proxy);
|
||||
error:
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_core_proxy * pw_remote_get_core_proxy(struct pw_remote *remote)
|
||||
{
|
||||
return remote->core_proxy;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_client_proxy * pw_remote_get_client_proxy(struct pw_remote *remote)
|
||||
{
|
||||
return remote->client_proxy;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_proxy *pw_remote_find_proxy(struct pw_remote *remote, uint32_t id)
|
||||
{
|
||||
return pw_map_lookup(&remote->objects, id);
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
int pw_remote_connect(struct pw_remote *remote)
|
||||
{
|
||||
int res;
|
||||
|
||||
if ((res = init_connect(remote)) < 0)
|
||||
goto error;
|
||||
|
||||
if ((res = pw_protocol_client_connect(remote->conn,
|
||||
&remote->properties->dict,
|
||||
NULL, NULL)) < 0)
|
||||
goto error;
|
||||
|
||||
error:
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
int pw_remote_connect_fd(struct pw_remote *remote, int fd)
|
||||
{
|
||||
int res;
|
||||
|
||||
if ((res = init_connect(remote)) < 0)
|
||||
goto error;
|
||||
|
||||
if ((res = pw_protocol_client_connect_fd(remote->conn, fd, true)) < 0)
|
||||
goto error;
|
||||
|
||||
error:
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
int pw_remote_steal_fd(struct pw_remote *remote)
|
||||
{
|
||||
int fd;
|
||||
fd = pw_protocol_client_steal_fd(remote->conn);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int destroy_proxy(void *object, void *data)
|
||||
{
|
||||
if (object)
|
||||
pw_proxy_destroy(object);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
int pw_remote_disconnect(struct pw_remote *remote)
|
||||
{
|
||||
struct pw_stream *stream, *s2;
|
||||
|
||||
pw_log_debug(NAME" %p: disconnect", remote);
|
||||
|
||||
spa_list_for_each_safe(stream, s2, &remote->stream_list, link)
|
||||
pw_stream_disconnect(stream);
|
||||
|
||||
pw_protocol_client_disconnect(remote->conn);
|
||||
|
||||
remote->client_proxy = NULL;
|
||||
|
||||
pw_map_for_each(&remote->objects, destroy_proxy, remote);
|
||||
pw_map_reset(&remote->objects);
|
||||
|
||||
pw_mempool_destroy(remote->pool);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_proxy *pw_remote_export(struct pw_remote *remote,
|
||||
uint32_t type, struct pw_properties *props, void *object,
|
||||
size_t user_data_size)
|
||||
{
|
||||
struct pw_proxy *proxy;
|
||||
const struct pw_export_type *t;
|
||||
int res;
|
||||
|
||||
if (remote->core_proxy == NULL) {
|
||||
res = -ENETDOWN;
|
||||
goto error_core_proxy;
|
||||
}
|
||||
|
||||
t = pw_core_find_export_type(remote->core, type);
|
||||
if (t == NULL) {
|
||||
res = -EPROTO;
|
||||
goto error_export_type;
|
||||
}
|
||||
|
||||
proxy = t->func(remote->core_proxy, type, props, object, user_data_size);
|
||||
if (proxy == NULL) {
|
||||
res = -errno;
|
||||
goto error_proxy_failed;
|
||||
}
|
||||
return proxy;
|
||||
|
||||
error_core_proxy:
|
||||
pw_log_error(NAME" %p: no core proxy: %s", remote, spa_strerror(res));
|
||||
goto exit_free;
|
||||
error_export_type:
|
||||
pw_log_error(NAME" %p: can't export type %d: %s", remote, type, spa_strerror(res));
|
||||
goto exit_free;
|
||||
error_proxy_failed:
|
||||
pw_log_error(NAME" %p: failed to create proxy: %s", remote, spa_strerror(res));
|
||||
goto exit;
|
||||
exit_free:
|
||||
if (props)
|
||||
pw_properties_free(props);
|
||||
exit:
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_core_proxy *
|
||||
pw_core_connect(struct pw_core *core, struct pw_properties *properties,
|
||||
size_t user_data_size)
|
||||
{
|
||||
struct pw_remote *remote;
|
||||
int res;
|
||||
|
||||
remote = pw_remote_new(core, properties, user_data_size);
|
||||
if (remote == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((res = pw_remote_connect(remote)) < 0)
|
||||
goto error_free;
|
||||
|
||||
return remote->core_proxy;
|
||||
|
||||
error_free:
|
||||
pw_remote_destroy(remote);
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_core_proxy *
|
||||
pw_core_connect_fd(struct pw_core *core, int fd, struct pw_properties *properties,
|
||||
size_t user_data_size)
|
||||
{
|
||||
struct pw_remote *remote;
|
||||
int res;
|
||||
|
||||
remote = pw_remote_new(core, properties, user_data_size);
|
||||
if (remote == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((res = pw_remote_connect_fd(remote, fd)) < 0)
|
||||
goto error_free;
|
||||
|
||||
return remote->core_proxy;
|
||||
|
||||
error_free:
|
||||
pw_remote_destroy(remote);
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_client_proxy * pw_core_proxy_get_client_proxy(struct pw_core_proxy *proxy)
|
||||
{
|
||||
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
|
||||
return remote->client_proxy;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_core * pw_core_proxy_get_core(struct pw_core_proxy *proxy)
|
||||
{
|
||||
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
|
||||
return remote->core;
|
||||
}
|
||||
SPA_EXPORT
|
||||
struct pw_remote * pw_core_proxy_get_remote(struct pw_core_proxy *proxy)
|
||||
{
|
||||
return ((struct pw_proxy*)proxy)->remote;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_mempool * pw_core_proxy_get_mempool(struct pw_core_proxy *proxy)
|
||||
{
|
||||
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
|
||||
return remote->pool;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_proxy *pw_core_proxy_find_proxy(struct pw_core_proxy *proxy, uint32_t id)
|
||||
{
|
||||
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
|
||||
return pw_remote_find_proxy(remote, id);
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
int pw_core_proxy_disconnect(struct pw_core_proxy *proxy)
|
||||
{
|
||||
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
|
||||
pw_remote_destroy(remote);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct pw_proxy *pw_core_proxy_export(struct pw_core_proxy *proxy,
|
||||
uint32_t type, struct pw_properties *properties,
|
||||
void *object, size_t user_data_size)
|
||||
{
|
||||
struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote;
|
||||
return pw_remote_export(remote, type, properties, object, user_data_size);
|
||||
}
|
||||
|
|
@ -1,213 +0,0 @@
|
|||
/* PipeWire
|
||||
*
|
||||
* Copyright © 2018 Wim Taymans
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PIPEWIRE_REMOTE_H
|
||||
#define PIPEWIRE_REMOTE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <spa/utils/hook.h>
|
||||
|
||||
/** \page page_remote_api Remote API
|
||||
*
|
||||
* \section sec_remote_api_overview Overview
|
||||
*
|
||||
* The remote API allows you to connect to a remote PipeWire instance
|
||||
* and perform actions on the PipeWire graph. This includes
|
||||
*
|
||||
* \li introspecting the objects on the instance
|
||||
* \li Creating nodes
|
||||
* \li Linking nodes on their ports
|
||||
* \li providing media to the server for playback or consumption
|
||||
* \li retrieving media from the remote instance
|
||||
*
|
||||
* \section sec_remote_api_loop Event Loop Abstraction
|
||||
*
|
||||
* Most API is asynchronous and based around an event loop. Methods will
|
||||
* start an operation which will cause a state change of the \ref pw_remote
|
||||
* object. Connect to the state_changed event to be notified of these
|
||||
* state changes.
|
||||
*
|
||||
* The most convenient way to deal with the asynchronous calls is probably
|
||||
* with the thread loop (See \subpage page_thread_loop for more details).
|
||||
*
|
||||
* \subsection ssec_remote_api_proxy Proxy
|
||||
*
|
||||
* Proxies are local representations of remote resources. They
|
||||
* allow communication between local and remote objects.
|
||||
*
|
||||
* The \ref pw_remote maintains a list of all proxies, including a core
|
||||
* proxy that is used to get access to other proxy objects.
|
||||
*
|
||||
* See also \subpage page_proxy
|
||||
*
|
||||
* \section sec_remote_api_remote Remote
|
||||
*
|
||||
* \subsection ssec_remote_create Create
|
||||
*
|
||||
* To create a new remote use pw_remote_new(). You will
|
||||
* need to pass a local \ref pw_core implementation for event and
|
||||
* data loop.
|
||||
*
|
||||
* A typical loop would be created with pw_thread_loop_new() but
|
||||
* other implementation are possible.
|
||||
*
|
||||
* You will also need to pass properties for the remote. Use
|
||||
* pw_fill_remote_properties() to get a default set of properties.
|
||||
*
|
||||
* After creating the remote, you can track the state of the remote
|
||||
* by listening for the state_changed event.
|
||||
*
|
||||
* \subsection ssec_remote_api_remote_connect Connecting
|
||||
*
|
||||
* A remote must be connected before any operation can be issued.
|
||||
* Calling pw_remote_connect() will initiate the connection procedure.
|
||||
*
|
||||
* When connecting, the remote will automatically create a core
|
||||
* proxy to get access to the registry proxy and types.
|
||||
*
|
||||
* \subsection ssec_remote_api_remote_registry Registry
|
||||
*
|
||||
* \subpage page_registry
|
||||
*
|
||||
*
|
||||
* \subsection ssec_remote_api_remote_disconnect Disconnect
|
||||
*
|
||||
* Use pw_remote_disconnect() to disconnect from the remote.
|
||||
*/
|
||||
/** \class pw_remote
|
||||
*
|
||||
* \brief Represents a connection with a remote PipeWire instance
|
||||
*
|
||||
* a \ref pw_remote is created and used to connect to a remote PipeWire
|
||||
* instance.
|
||||
* A \ref pw_proxy for the core object will automatically be created
|
||||
* when connecting.
|
||||
*
|
||||
* See also \ref page_core_api
|
||||
*/
|
||||
struct pw_remote;
|
||||
|
||||
#include <pipewire/core.h>
|
||||
#include <pipewire/properties.h>
|
||||
#include <pipewire/node.h>
|
||||
#include <pipewire/proxy.h>
|
||||
|
||||
/** Create a new unconnected remote \memberof pw_remote
|
||||
* \return a new unconnected remote */
|
||||
struct pw_remote *
|
||||
pw_remote_new(struct pw_core *core, /**< a \ref pw_core */
|
||||
struct pw_properties *properties, /**< optional properties, ownership of
|
||||
* the properties is taken.*/
|
||||
size_t user_data_size /**< extra user data size */);
|
||||
|
||||
/** Destroy a remote \memberof pw_remote */
|
||||
void pw_remote_destroy(struct pw_remote *remote);
|
||||
|
||||
/** Get the core used to construct this remote */
|
||||
struct pw_core *pw_remote_get_core(struct pw_remote *remote);
|
||||
|
||||
/** Get the remote properties */
|
||||
const struct pw_properties *pw_remote_get_properties(struct pw_remote *remote);
|
||||
|
||||
/** Update properties */
|
||||
int pw_remote_update_properties(struct pw_remote *remote, const struct spa_dict *dict);
|
||||
|
||||
/** Get the user_data. The size was given in \ref pw_remote_new */
|
||||
void *pw_remote_get_user_data(struct pw_remote *remote);
|
||||
|
||||
/** Connect to a remote PipeWire \memberof pw_remote
|
||||
* \return 0 on success, < 0 on error */
|
||||
int pw_remote_connect(struct pw_remote *remote);
|
||||
|
||||
/** Connect to a remote PipeWire on the given socket \memberof pw_remote
|
||||
* \param fd the connected socket to use, the socket will be closed
|
||||
* automatically on disconnect or error.
|
||||
* \return 0 on success, < 0 on error */
|
||||
int pw_remote_connect_fd(struct pw_remote *remote, int fd);
|
||||
|
||||
/** Steal the fd of the remote connection or < 0 on error. The remote
|
||||
* will be in the unconnected state after this call. */
|
||||
int pw_remote_steal_fd(struct pw_remote *remote);
|
||||
|
||||
/** Get the core proxy, can only be called when connected */
|
||||
struct pw_core_proxy * pw_remote_get_core_proxy(struct pw_remote *remote);
|
||||
/** Get the client proxy, can only be called when connected */
|
||||
struct pw_client_proxy * pw_remote_get_client_proxy(struct pw_remote *remote);
|
||||
|
||||
/** Get the proxy with the given id */
|
||||
struct pw_proxy *pw_remote_find_proxy(struct pw_remote *remote, uint32_t id);
|
||||
|
||||
/** Disconnect from the remote PipeWire. \memberof pw_remote */
|
||||
int pw_remote_disconnect(struct pw_remote *remote);
|
||||
|
||||
/** run a local node in a remote graph */
|
||||
struct pw_proxy *pw_remote_export(struct pw_remote *remote, /**< the remote */
|
||||
uint32_t type, /**< the type of object */
|
||||
struct pw_properties *properties, /**< extra properties */
|
||||
void *object, /**< object to export */
|
||||
size_t user_data_size /**< extra user data */);
|
||||
|
||||
|
||||
struct pw_core_proxy *
|
||||
pw_core_connect(struct pw_core *core, /**< a \ref pw_core */
|
||||
struct pw_properties *properties, /**< optional properties, ownership of
|
||||
* the properties is taken.*/
|
||||
size_t user_data_size /**< extra user data size */);
|
||||
|
||||
struct pw_core_proxy *
|
||||
pw_core_connect_fd(struct pw_core *core, /**< a \ref pw_core */
|
||||
int fd, /**< an fd */
|
||||
struct pw_properties *properties, /**< optional properties, ownership of
|
||||
* the properties is taken.*/
|
||||
size_t user_data_size /**< extra user data size */);
|
||||
|
||||
int pw_core_proxy_disconnect(struct pw_core_proxy *proxy);
|
||||
|
||||
/** Get the client proxy */
|
||||
struct pw_client_proxy * pw_core_proxy_get_client_proxy(struct pw_core_proxy *proxy);
|
||||
|
||||
struct pw_core * pw_core_proxy_get_core(struct pw_core_proxy *proxy);
|
||||
|
||||
struct pw_remote * pw_core_proxy_get_remote(struct pw_core_proxy *proxy);
|
||||
|
||||
struct pw_mempool * pw_core_proxy_get_mempool(struct pw_core_proxy *proxy);
|
||||
|
||||
/** Get the proxy with the given id */
|
||||
struct pw_proxy *pw_core_proxy_find_proxy(struct pw_core_proxy *proxy, uint32_t id);
|
||||
|
||||
struct pw_proxy *pw_core_proxy_export(struct pw_core_proxy *proxy, /**< the proxy */
|
||||
uint32_t type, /**< the type of object */
|
||||
struct pw_properties *properties, /**< extra properties */
|
||||
void *object, /**< object to export */
|
||||
size_t user_data_size /**< extra user data */);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PIPEWIRE_REMOTE_H */
|
||||
|
|
@ -96,8 +96,6 @@ struct stream {
|
|||
enum spa_direction direction;
|
||||
enum pw_stream_flags flags;
|
||||
|
||||
struct spa_hook remote_listener;
|
||||
|
||||
struct pw_node *node;
|
||||
struct spa_port_info port_info;
|
||||
|
||||
|
|
@ -1068,8 +1066,6 @@ stream_new(struct pw_core *core, const char *name,
|
|||
|
||||
impl->core = core;
|
||||
|
||||
// spa_list_append(&remote->stream_list, &this->link);
|
||||
|
||||
return impl;
|
||||
|
||||
error_properties:
|
||||
|
|
@ -1169,7 +1165,6 @@ void pw_stream_destroy(struct pw_stream *stream)
|
|||
spa_hook_remove(&stream->core_listener);
|
||||
stream->core_proxy = NULL;
|
||||
}
|
||||
// spa_list_remove(&stream->link);
|
||||
|
||||
clear_params(impl, SPA_ID_INVALID);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ extern "C" {
|
|||
*
|
||||
* For more complicated nodes such as filters or ports with multiple
|
||||
* inputs and/or outputs you will need to use the pw_filter or make
|
||||
* a pw_node yourself and export it with \ref pw_remote_export.
|
||||
* a pw_node yourself and export it with \ref pw_core_proxy_export.
|
||||
*
|
||||
* \section sec_create Create
|
||||
*
|
||||
|
|
@ -152,7 +152,7 @@ struct pw_stream;
|
|||
#include <spa/buffer/buffer.h>
|
||||
#include <spa/param/param.h>
|
||||
|
||||
#include <pipewire/remote.h>
|
||||
#include <pipewire/core-proxy.h>
|
||||
|
||||
/** \enum pw_stream_state The state of a stream \memberof pw_stream */
|
||||
enum pw_stream_state {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
#include <pipewire/properties.h>
|
||||
#include <pipewire/protocol.h>
|
||||
#include <pipewire/proxy.h>
|
||||
#include <pipewire/remote.h>
|
||||
#include <pipewire/core-proxy.h>
|
||||
#include <pipewire/resource.h>
|
||||
#include <pipewire/stream.h>
|
||||
#include <pipewire/thread-loop.h>
|
||||
|
|
|
|||
|
|
@ -1,186 +0,0 @@
|
|||
/* PipeWire
|
||||
*
|
||||
* Copyright © 2019 Wim Taymans
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <pipewire/main-loop.h>
|
||||
#include <pipewire/remote.h>
|
||||
|
||||
#define TEST_FUNC(a,b,func) \
|
||||
do { \
|
||||
a.func = b.func; \
|
||||
spa_assert(SPA_PTRDIFF(&a.func, &a) == SPA_PTRDIFF(&b.func, &b)); \
|
||||
} while(0)
|
||||
|
||||
static void test_abi(void)
|
||||
{
|
||||
struct pw_remote_events ev;
|
||||
struct {
|
||||
uint32_t version;
|
||||
void (*destroy) (void *data);
|
||||
void (*state_changed) (void *data, enum pw_remote_state old,
|
||||
enum pw_remote_state state, const char *error);
|
||||
} test = { PW_VERSION_REMOTE_EVENTS, NULL };
|
||||
|
||||
TEST_FUNC(ev, test, destroy);
|
||||
TEST_FUNC(ev, test, state_changed);
|
||||
|
||||
spa_assert(PW_VERSION_REMOTE_EVENTS == 0);
|
||||
spa_assert(sizeof(ev) == sizeof(test));
|
||||
|
||||
spa_assert(PW_REMOTE_STATE_ERROR == -1);
|
||||
spa_assert(PW_REMOTE_STATE_UNCONNECTED == 0);
|
||||
spa_assert(PW_REMOTE_STATE_CONNECTING == 1);
|
||||
spa_assert(PW_REMOTE_STATE_CONNECTED == 2);
|
||||
|
||||
spa_assert(pw_remote_state_as_string(PW_REMOTE_STATE_ERROR) != NULL);
|
||||
spa_assert(pw_remote_state_as_string(PW_REMOTE_STATE_UNCONNECTED) != NULL);
|
||||
spa_assert(pw_remote_state_as_string(PW_REMOTE_STATE_CONNECTING) != NULL);
|
||||
spa_assert(pw_remote_state_as_string(PW_REMOTE_STATE_CONNECTED) != NULL);
|
||||
}
|
||||
|
||||
static void remote_destroy_error(void *data)
|
||||
{
|
||||
spa_assert_not_reached();
|
||||
}
|
||||
static void remote_state_changed_error(void *data, enum pw_remote_state old,
|
||||
enum pw_remote_state state, const char *error)
|
||||
{
|
||||
spa_assert_not_reached();
|
||||
}
|
||||
|
||||
static const struct pw_remote_events remote_events_error =
|
||||
{
|
||||
PW_VERSION_REMOTE_EVENTS,
|
||||
.destroy = remote_destroy_error,
|
||||
.state_changed = remote_state_changed_error,
|
||||
};
|
||||
|
||||
static int destroy_count = 0;
|
||||
static void remote_destroy_count(void *data)
|
||||
{
|
||||
destroy_count++;
|
||||
}
|
||||
static void test_create(void)
|
||||
{
|
||||
struct pw_main_loop *loop;
|
||||
struct pw_core *core;
|
||||
struct pw_remote *remote;
|
||||
struct pw_remote_events remote_events = remote_events_error;
|
||||
struct spa_hook listener = { 0, };
|
||||
const char *error = NULL;
|
||||
|
||||
loop = pw_main_loop_new(NULL);
|
||||
core = pw_core_new(pw_main_loop_get_loop(loop), NULL, 12);
|
||||
|
||||
remote = pw_remote_new(core, NULL, 12);
|
||||
spa_assert(remote != NULL);
|
||||
pw_remote_add_listener(remote, &listener, &remote_events, remote);
|
||||
|
||||
/* check core */
|
||||
spa_assert(pw_remote_get_core(remote) == core);
|
||||
/* check user data */
|
||||
spa_assert(pw_remote_get_user_data(remote) != NULL);
|
||||
/* check state */
|
||||
spa_assert(pw_remote_get_state(remote, &error) == PW_REMOTE_STATE_UNCONNECTED);
|
||||
spa_assert(error == NULL);
|
||||
|
||||
/* check core proxy, only available when connected */
|
||||
spa_assert(pw_remote_get_core_proxy(remote) == NULL);
|
||||
|
||||
/* check some non-existing proxies */
|
||||
spa_assert(pw_remote_find_proxy(remote, 0) == NULL);
|
||||
spa_assert(pw_remote_find_proxy(remote, 5) == NULL);
|
||||
|
||||
/* check destroy */
|
||||
destroy_count = 0;
|
||||
remote_events.destroy = remote_destroy_count;
|
||||
pw_remote_destroy(remote);
|
||||
spa_assert(destroy_count == 1);
|
||||
|
||||
pw_core_destroy(core);
|
||||
pw_main_loop_destroy(loop);
|
||||
}
|
||||
|
||||
static void test_properties(void)
|
||||
{
|
||||
struct pw_main_loop *loop;
|
||||
struct pw_core *core;
|
||||
const struct pw_properties *props;
|
||||
struct pw_remote *remote;
|
||||
struct pw_remote_events remote_events = remote_events_error;
|
||||
struct spa_hook listener = { NULL, };
|
||||
struct spa_dict_item items[3];
|
||||
|
||||
loop = pw_main_loop_new(NULL);
|
||||
core = pw_core_new(pw_main_loop_get_loop(loop), NULL, 0);
|
||||
remote = pw_remote_new(core,
|
||||
pw_properties_new("foo", "bar",
|
||||
"biz", "fuzz",
|
||||
NULL),
|
||||
0);
|
||||
spa_assert(remote != NULL);
|
||||
spa_assert(pw_remote_get_user_data(remote) == NULL);
|
||||
pw_remote_add_listener(remote, &listener, &remote_events, remote);
|
||||
|
||||
props = pw_remote_get_properties(remote);
|
||||
spa_assert(props != NULL);
|
||||
spa_assert(!strcmp(pw_properties_get(props, "foo"), "bar"));
|
||||
spa_assert(!strcmp(pw_properties_get(props, "biz"), "fuzz"));
|
||||
spa_assert(pw_properties_get(props, "buzz") == NULL);
|
||||
|
||||
/* remove foo */
|
||||
items[0] = SPA_DICT_ITEM_INIT("foo", NULL);
|
||||
/* change biz */
|
||||
items[1] = SPA_DICT_ITEM_INIT("biz", "buzz");
|
||||
/* add buzz */
|
||||
items[2] = SPA_DICT_ITEM_INIT("buzz", "frizz");
|
||||
/* update properties does not emit the info_changed signal
|
||||
* because that is only emited when the remote core properties
|
||||
* changed */
|
||||
pw_remote_update_properties(remote, &SPA_DICT_INIT(items, 3));
|
||||
|
||||
spa_assert(props == pw_remote_get_properties(remote));
|
||||
spa_assert(pw_properties_get(props, "foo") == NULL);
|
||||
spa_assert(!strcmp(pw_properties_get(props, "biz"), "buzz"));
|
||||
spa_assert(!strcmp(pw_properties_get(props, "buzz"), "frizz"));
|
||||
|
||||
/* check destroy */
|
||||
destroy_count = 0;
|
||||
remote_events.destroy = remote_destroy_count;
|
||||
pw_core_destroy(core);
|
||||
spa_assert(destroy_count == 1);
|
||||
|
||||
pw_main_loop_destroy(loop);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
pw_init(&argc, &argv);
|
||||
|
||||
test_abi();
|
||||
test_create();
|
||||
test_properties();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include <pipewire/interfaces.h>
|
||||
#include <pipewire/type.h>
|
||||
#include <pipewire/remote.h>
|
||||
#include <pipewire/main-loop.h>
|
||||
#include <pipewire/pipewire.h>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue