From 6756a3c8fc47f46feaafe0373928110dc81124fc Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 20 Sep 2019 13:04:14 +0200 Subject: [PATCH] monitor: remove monitor API and use device Remove the monitor API, we can use the device API for it. Make sure we support creating devices (like alsa) from another device (udev). Use new object.id to store the object id in the object properties. Use the port.id/node.id etc to make relations to other objects. --- spa/include/spa/meson.build | 2 - spa/include/spa/monitor/device.h | 4 +- spa/include/spa/monitor/monitor.h | 133 ------- spa/include/spa/monitor/type-info.h | 51 --- spa/include/spa/utils/hook.h | 9 +- spa/include/spa/utils/keys.h | 4 + spa/include/spa/utils/names.h | 6 +- spa/include/spa/utils/type-info.h | 5 +- spa/include/spa/utils/type.h | 4 +- .../alsa/{alsa-monitor.c => alsa-udev.c} | 147 +++++--- spa/plugins/alsa/alsa.c | 4 +- spa/plugins/alsa/meson.build | 2 +- .../{bluez5-monitor.c => bluez5-dbus.c} | 77 ++-- spa/plugins/bluez5/meson.build | 2 +- spa/plugins/bluez5/plugin.c | 4 +- spa/plugins/v4l2/meson.build | 2 +- .../v4l2/{v4l2-monitor.c => v4l2-udev.c} | 135 ++++--- spa/plugins/v4l2/v4l2.c | 4 +- spa/tests/test-cpp.cpp | 1 - spa/tests/test-utils.c | 7 +- spa/tools/spa-monitor.c | 33 +- src/daemon/pipewire.conf.in | 3 +- src/examples/alsa-monitor.c | 27 +- src/examples/bluez-monitor.c | 28 +- src/examples/bluez-session.c | 49 ++- src/examples/media-session.c | 4 +- src/examples/v4l2-monitor.c | 26 +- src/modules/spa/meson.build | 9 - src/modules/spa/module-device.c | 1 - src/modules/spa/module-monitor.c | 123 ------- src/modules/spa/module-node.c | 1 - src/modules/spa/spa-monitor.c | 336 ------------------ src/modules/spa/spa-monitor.h | 60 ---- src/pipewire/client.c | 2 +- src/pipewire/core.c | 2 +- src/pipewire/device.c | 168 ++++++--- src/pipewire/factory.c | 2 +- src/pipewire/keys.h | 2 + src/pipewire/link.c | 2 +- src/pipewire/module.c | 2 +- src/pipewire/node.c | 2 +- src/pipewire/port.c | 2 +- src/pipewire/private.h | 2 +- 43 files changed, 474 insertions(+), 1015 deletions(-) delete mode 100644 spa/include/spa/monitor/monitor.h delete mode 100644 spa/include/spa/monitor/type-info.h rename spa/plugins/alsa/{alsa-monitor.c => alsa-udev.c} (83%) rename spa/plugins/bluez5/{bluez5-monitor.c => bluez5-dbus.c} (97%) rename spa/plugins/v4l2/{v4l2-monitor.c => v4l2-udev.c} (81%) delete mode 100644 src/modules/spa/module-monitor.c delete mode 100644 src/modules/spa/spa-monitor.c delete mode 100644 src/modules/spa/spa-monitor.h diff --git a/spa/include/spa/meson.build b/spa/include/spa/meson.build index 22cd244ca..7bdfc1ce7 100644 --- a/spa/include/spa/meson.build +++ b/spa/include/spa/meson.build @@ -37,8 +37,6 @@ install_headers(spa_graph_headers, spa_monitor_headers = [ 'monitor/device.h', - 'monitor/monitor.h', - 'monitor/type-info.h', 'monitor/utils.h', ] diff --git a/spa/include/spa/monitor/device.h b/spa/include/spa/monitor/device.h index 47ac74a6c..ef41c6e23 100644 --- a/spa/include/spa/monitor/device.h +++ b/spa/include/spa/monitor/device.h @@ -236,8 +236,10 @@ struct spa_device_methods { #define spa_device_enum_params(d,...) spa_device_method(d, enum_params, 0, __VA_ARGS__) #define spa_device_set_param(d,...) spa_device_method(d, set_param, 0, __VA_ARGS__) +#define SPA_KEY_DEVICE_ENUM_API "device.enum.api" /**< the api used to discover this + * device */ #define SPA_KEY_DEVICE_API "device.api" /**< the api used by the device - * Ex. "alsa", "v4l2". */ + * Ex. "udev", "alsa", "v4l2". */ #define SPA_KEY_DEVICE_NAME "device.name" /**< the name of the device */ #define SPA_KEY_DEVICE_ALIAS "device.alias" /**< altenative name of the device */ #define SPA_KEY_DEVICE_NICK "device.nick" /**< the device short name */ diff --git a/spa/include/spa/monitor/monitor.h b/spa/include/spa/monitor/monitor.h deleted file mode 100644 index ced24a61b..000000000 --- a/spa/include/spa/monitor/monitor.h +++ /dev/null @@ -1,133 +0,0 @@ -/* Simple Plugin API - * - * 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 SPA_MONITOR_H -#define SPA_MONITOR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#define SPA_VERSION_MONITOR 0 -struct spa_monitor { struct spa_interface iface; }; - -struct spa_monitor_info { -#define SPA_VERSION_MONITOR_INFO 0 - uint32_t version; - -#define SPA_MONITOR_CHANGE_MASK_FLAGS (1u<<0) -#define SPA_MONITOR_CHANGE_MASK_PROPS (1u<<1) - uint64_t change_mask; - uint64_t flags; - const struct spa_dict *props; -}; - -#define SPA_MONITOR_INFO_INIT() (struct spa_monitor_info){ SPA_VERSION_MONITOR_INFO, } - -struct spa_monitor_object_info { -#define SPA_VERSION_MONITOR_OBJECT_INFO 0 - uint32_t version; - - uint32_t type; - const char *factory_name; - -#define SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS (1u<<0) -#define SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS (1u<<1) - uint64_t change_mask; - uint64_t flags; - const struct spa_dict *props; -}; - -#define SPA_MONITOR_OBJECT_INFO_INIT() (struct spa_monitor_object_info){ SPA_VERSION_MONITOR_OBJECT_INFO, } -/** - * spa_monitor_callbacks: - */ -struct spa_monitor_callbacks { - /** version of the structure */ -#define SPA_VERSION_MONITOR_CALLBACKS 0 - uint32_t version; - - /** receive extra information about the monitor */ - int (*info) (void *data, const struct spa_monitor_info *info); - - /** an item is added/removed/changed on the monitor */ - int (*event) (void *data, const struct spa_event *event); - - /** info changed for an object managed by the monitor, info is NULL when - * the object is removed */ - int (*object_info) (void *data, uint32_t id, - const struct spa_monitor_object_info *info); -}; - -/** - * spa_monitor_methods: - * - * The device monitor methods. - */ -struct spa_monitor_methods { - /* the version of this monitor. This can be used to expand this - * structure in the future */ -#define SPA_VERSION_MONITOR_METHODS 0 - uint32_t version; - - /** - * Set callbacks to receive asynchronous notifications from - * the monitor. - * - * Setting the callbacks will emit the info - * - * \param monitor: a #spa_monitor - * \param callback: a #callbacks - * \return 0 on success - * < 0 errno on error - */ - int (*set_callbacks) (void *object, - const struct spa_monitor_callbacks *callbacks, - void *data); -}; - -static inline int spa_monitor_set_callbacks(struct spa_monitor *m, - const struct spa_monitor_callbacks *callbacks, void *data) -{ - int res = -ENOTSUP; - spa_interface_call_res(&m->iface, - struct spa_monitor_methods, res, set_callbacks, 0, - callbacks, data); - return res; - -} - -#define SPA_KEY_MONITOR_API "monitor.api" /**< the api used by the monitor. - * Ex. "udev", "dbus", ... */ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* SPA_MONITOR_H */ diff --git a/spa/include/spa/monitor/type-info.h b/spa/include/spa/monitor/type-info.h deleted file mode 100644 index 472727d3f..000000000 --- a/spa/include/spa/monitor/type-info.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Simple Plugin API - * - * 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 SPA_MONITOR_TYPES_H -#define SPA_MONITOR_TYPES_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#define SPA_TYPE_INFO_MonitorEvent SPA_TYPE_INFO_EVENT_BASE "Monitor" -#define SPA_TYPE_INFO_MONITOR_EVENT_BASE SPA_TYPE_INFO_MonitorEvent ":" - -static const struct spa_type_info spa_type_monitor_event_id[] = { - { 0, 0, NULL, NULL }, -}; - -static const struct spa_type_info spa_type_monitor_event[] = { - { 0, SPA_TYPE_Id, SPA_TYPE_INFO_MONITOR_EVENT_BASE, spa_type_monitor_event_id }, - { 0, 0, NULL, NULL }, -}; - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* SPA_MONITOR_TYPES_H */ diff --git a/spa/include/spa/utils/hook.h b/spa/include/spa/utils/hook.h index 1f285f022..b1f32890e 100644 --- a/spa/include/spa/utils/hook.h +++ b/spa/include/spa/utils/hook.h @@ -66,9 +66,9 @@ struct spa_interface { struct spa_hook { struct spa_list link; struct spa_callbacks cb; - void *priv; /**< private data for the hook list */ + /** callback and data for the hook list */ void (*removed) (struct spa_hook *hook); - + void *priv; }; /** Initialize a hook list */ @@ -77,6 +77,11 @@ static inline void spa_hook_list_init(struct spa_hook_list *list) spa_list_init(&list->list); } +static inline bool spa_hook_list_is_empty(struct spa_hook_list *list) +{ + return spa_list_is_empty(&list->list); +} + /** Append a hook \memberof spa_hook */ static inline void spa_hook_list_append(struct spa_hook_list *list, struct spa_hook *hook, diff --git a/spa/include/spa/utils/keys.h b/spa/include/spa/utils/keys.h index 92627616c..62f85d1f0 100644 --- a/spa/include/spa/utils/keys.h +++ b/spa/include/spa/utils/keys.h @@ -37,6 +37,10 @@ extern "C" { * Screen, Communication, Game, * Notification, DSP, Production, * Accessibility, Test */ +/** keys for udev api */ +#define SPA_KEY_API_UDEV "api.udev" /**< key for the udev api */ +#define SPA_KEY_API_UDEV_MATCH "api.udev.match" /**< udev subsystem match */ + /** keys for alsa api */ #define SPA_KEY_API_ALSA "api.alsa" /**< key for the alsa api */ #define SPA_KEY_API_ALSA_PATH "api.alsa.path" /**< alsa device path as can be diff --git a/spa/include/spa/utils/names.h b/spa/include/spa/utils/names.h index 43cbb808b..0f7da1374 100644 --- a/spa/include/spa/utils/names.h +++ b/spa/include/spa/utils/names.h @@ -77,7 +77,7 @@ extern "C" { #define SPA_NAME_VIDEO_ADAPT "video.adapt" /**< combination of a node and a * video.convert. */ /** keys for alsa factory names */ -#define SPA_NAME_API_ALSA_MONITOR "api.alsa.monitor" /**< an alsa Monitor interface */ +#define SPA_NAME_API_ALSA_ENUM_UDEV "api.alsa.enum.udev" /**< an alsa udev Device interface */ #define SPA_NAME_API_ALSA_DEVICE "api.alsa.device" /**< an alsa Device interface */ #define SPA_NAME_API_ALSA_PCM_SOURCE "api.alsa.pcm.source" /**< an alsa Node interface for * capturing PCM */ @@ -87,7 +87,7 @@ extern "C" { * capturing midi */ /** keys for bluez5 factory names */ -#define SPA_NAME_API_BLUEZ5_MONITOR "api.bluez5.monitor" /**< a Monitor interface */ +#define SPA_NAME_API_BLUEZ5_ENUM_DBUS "api.bluez5.enum.dbus" /**< a dbus Device interface */ #define SPA_NAME_API_BLUEZ5_DEVICE "api.bluez5.device" /**< a Device interface */ #define SPA_NAME_API_BLUEZ5_A2DP_SINK "api.bluez5.a2dp.sink" /**< a playback Node interface for A2DP profiles */ #define SPA_NAME_API_BLUEZ5_A2DP_SOURCE "api.bluez5.a2dp.source" /**< a capture Node interface for A2DP profiles */ @@ -95,7 +95,7 @@ extern "C" { #define SPA_NAME_API_BLUEZ5_SCO_SOURCE "api.bluez5.sco.source" /**< a capture Node interface for HSP/HFP profiles */ /** keys for v4l2 factory names */ -#define SPA_NAME_API_V4L2_MONITOR "api.v4l2.monitor" /**< a v4l2 Monitor interface */ +#define SPA_NAME_API_V4L2_ENUM_UDEV "api.v4l2.enum.udev" /**< a v4l2 udev Device interface */ #define SPA_NAME_API_V4L2_DEVICE "api.v4l2.device" /**< a v4l2 Device interface */ #define SPA_NAME_API_V4L2_SOURCE "api.v4l2.source" /**< a v4l2 Node interface for * capturing */ diff --git a/spa/include/spa/utils/type-info.h b/spa/include/spa/utils/type-info.h index 35826e733..738c35eac 100644 --- a/spa/include/spa/utils/type-info.h +++ b/spa/include/spa/utils/type-info.h @@ -52,7 +52,6 @@ static const struct spa_type_info spa_type_direction[] = { { 0, 0, NULL, NULL } }; -#include #include #include #include @@ -110,16 +109,16 @@ static const struct spa_type_info spa_types[] = { { SPA_TYPE_INTERFACE_DataSystem, SPA_TYPE_Pointer, SPA_TYPE_INFO_INTERFACE_BASE "DataSystem", NULL }, { SPA_TYPE_INTERFACE_DataLoop, SPA_TYPE_Pointer, SPA_TYPE_INFO_INTERFACE_BASE "DataLoop", NULL }, { SPA_TYPE_INTERFACE_DBus, SPA_TYPE_Pointer, SPA_TYPE_INFO_INTERFACE_BASE "DBus", NULL }, - { SPA_TYPE_INTERFACE_Monitor, SPA_TYPE_Pointer, SPA_TYPE_INFO_INTERFACE_BASE "Monitor", NULL }, { SPA_TYPE_INTERFACE_Node, SPA_TYPE_Pointer, SPA_TYPE_INFO_INTERFACE_BASE "Node", NULL }, { SPA_TYPE_INTERFACE_Device, SPA_TYPE_Pointer, SPA_TYPE_INFO_INTERFACE_BASE "Device", NULL }, { SPA_TYPE_INTERFACE_CPU, SPA_TYPE_Pointer, SPA_TYPE_INFO_INTERFACE_BASE "CPU", NULL }, { SPA_TYPE_EVENT_START, SPA_TYPE_Object, SPA_TYPE_INFO_Event, NULL }, - { SPA_TYPE_EVENT_Monitor, SPA_TYPE_Object, SPA_TYPE_INFO_EVENT_BASE "Monitor", spa_type_monitor_event }, + { SPA_TYPE_EVENT_Device, SPA_TYPE_Object, SPA_TYPE_INFO_EVENT_BASE "Device", NULL }, { SPA_TYPE_EVENT_Node, SPA_TYPE_Object, SPA_TYPE_INFO_EVENT_BASE "Node", spa_type_node_event }, { SPA_TYPE_COMMAND_START, SPA_TYPE_Object, SPA_TYPE_INFO_Command, NULL }, + { SPA_TYPE_COMMAND_Device, SPA_TYPE_Object, SPA_TYPE_INFO_COMMAND_BASE "Device", NULL }, { SPA_TYPE_COMMAND_Node, SPA_TYPE_Object, SPA_TYPE_INFO_COMMAND_BASE "Node", spa_type_node_command }, { SPA_TYPE_OBJECT_START, SPA_TYPE_Object, SPA_TYPE_INFO_Object, NULL }, diff --git a/spa/include/spa/utils/type.h b/spa/include/spa/utils/type.h index f9be29778..3e9b4aa72 100644 --- a/spa/include/spa/utils/type.h +++ b/spa/include/spa/utils/type.h @@ -75,7 +75,6 @@ enum { SPA_TYPE_INTERFACE_DataSystem, /**< System functions for data loop */ SPA_TYPE_INTERFACE_DataLoop, /**< a data loop */ SPA_TYPE_INTERFACE_DBus, /**< dbus connection */ - SPA_TYPE_INTERFACE_Monitor, /**< monitor of devices */ SPA_TYPE_INTERFACE_Node, /**< nodes for data processing */ SPA_TYPE_INTERFACE_Device, /**< device managing nodes */ SPA_TYPE_INTERFACE_CPU, /**< CPU functions */ @@ -83,12 +82,13 @@ enum { /* Events */ SPA_TYPE_EVENT_START = 0x30000, - SPA_TYPE_EVENT_Monitor, + SPA_TYPE_EVENT_Device, SPA_TYPE_EVENT_Node, SPA_TYPE_EVENT_LAST, /**< not part of ABI */ /* Commands */ SPA_TYPE_COMMAND_START = 0x40000, + SPA_TYPE_COMMAND_Device, SPA_TYPE_COMMAND_Node, SPA_TYPE_COMMAND_LAST, /**< not part of ABI */ diff --git a/spa/plugins/alsa/alsa-monitor.c b/spa/plugins/alsa/alsa-udev.c similarity index 83% rename from spa/plugins/alsa/alsa-monitor.c rename to spa/plugins/alsa/alsa-udev.c index 4831a50ea..c9f790fc0 100644 --- a/spa/plugins/alsa/alsa-monitor.c +++ b/spa/plugins/alsa/alsa-udev.c @@ -1,4 +1,4 @@ -/* Spa ALSA Monitor +/* Spa ALSA udev * * Copyright © 2018 Wim Taymans * @@ -30,7 +30,6 @@ #include #include -#include #include #include @@ -38,10 +37,10 @@ #include #include #include -#include +#include #include -#define NAME "alsa-monitor" +#define NAME "alsa-udev" #define MAX_CARDS 64 @@ -51,12 +50,15 @@ struct impl { struct spa_handle handle; - struct spa_monitor monitor; + struct spa_device device; struct spa_log *log; struct spa_loop *main_loop; - struct spa_callbacks callbacks; + struct spa_hook_list hooks; + + uint64_t info_all; + struct spa_device_info info; struct udev *udev; struct udev_monitor *umonitor; @@ -183,21 +185,21 @@ static void unescape(const char *src, char *dst) static int emit_object_info(struct impl *this, uint32_t id, struct udev_device *dev) { - struct spa_monitor_object_info info; + struct spa_device_object_info info; const char *str; char path[32]; struct spa_dict_item items[20]; uint32_t n_items = 0; - info = SPA_MONITOR_OBJECT_INFO_INIT(); + info = SPA_DEVICE_OBJECT_INFO_INIT(); info.type = SPA_TYPE_INTERFACE_Device; info.factory_name = SPA_NAME_API_ALSA_DEVICE; - info.change_mask = SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS | - SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS; + info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS | + SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS; info.flags = 0; - items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_MONITOR_API, "udev"); + items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_ENUM_API, "udev"); items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "alsa"); if ((str = path_get_card_id(udev_device_get_property_value(dev, "DEVPATH"))) == NULL) @@ -275,7 +277,8 @@ static int emit_object_info(struct impl *this, uint32_t id, struct udev_device * items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_FORM_FACTOR, str); } info.props = &SPA_DICT_INIT(items, n_items); - spa_monitor_call_object_info(&this->callbacks, id, &info); + + spa_device_emit_object_info(&this->hooks, id, &info); return 1; } @@ -348,7 +351,7 @@ static int emit_device(struct impl *this, uint32_t action, bool enumerated, stru emit_object_info(this, id, dev); break; default: - spa_monitor_call_object_info(&this->callbacks, id, NULL); + spa_device_emit_object_info(&this->hooks, id, NULL); break; } return 0; @@ -448,38 +451,67 @@ static int enum_devices(struct impl *this) return 0; } -static int -impl_monitor_set_callbacks(void *object, - const struct spa_monitor_callbacks *callbacks, - void *data) +static const struct spa_dict_item device_info_items[] = { + { SPA_KEY_DEVICE_API, "udev" }, + { SPA_KEY_DEVICE_NICK, "alsa-udev" }, + { SPA_KEY_API_UDEV_MATCH, "sound" }, +}; + +static void emit_device_info(struct impl *this, bool full) { - int res; - struct impl *this = object; + if (full) + this->info.change_mask = this->info_all; + if (this->info.change_mask) { + this->info.props = &SPA_DICT_INIT_ARRAY(device_info_items); + spa_device_emit_info(&this->hooks, &this->info); + this->info.change_mask = 0; + } +} - spa_return_val_if_fail(this != NULL, -EINVAL); - - this->callbacks = SPA_CALLBACKS_INIT(callbacks, data); - - if (callbacks) { - if ((res = impl_udev_open(this)) < 0) - return res; - - if ((res = enum_devices(this)) < 0) - return res; - - if ((res = start_monitor(this)) < 0) - return res; - } else { +static void impl_hook_removed(struct spa_hook *hook) +{ + struct impl *this = hook->priv; + if (spa_hook_list_is_empty(&this->hooks)) { stop_monitor(this); impl_udev_close(this); } +} + +static int +impl_device_add_listener(void *object, struct spa_hook *listener, + const struct spa_device_events *events, void *data) +{ + int res; + struct impl *this = object; + struct spa_hook_list save; + + spa_return_val_if_fail(this != NULL, -EINVAL); + spa_return_val_if_fail(events != NULL, -EINVAL); + + if ((res = impl_udev_open(this)) < 0) + return res; + + spa_hook_list_isolate(&this->hooks, &save, listener, events, data); + + emit_device_info(this, true); + + if ((res = enum_devices(this)) < 0) + return res; + + if ((res = start_monitor(this)) < 0) + return res; + + spa_hook_list_join(&this->hooks, &save); + + listener->removed = impl_hook_removed; + listener->priv = this; return 0; } -static const struct spa_monitor_methods impl_monitor = { - SPA_VERSION_MONITOR_METHODS, - .set_callbacks = impl_monitor_set_callbacks, +static const struct spa_device_methods impl_device = { + SPA_VERSION_DEVICE_METHODS, + .add_listener = impl_device_add_listener, }; static int impl_get_interface(struct spa_handle *handle, uint32_t type, void **interface) @@ -491,18 +523,21 @@ static int impl_get_interface(struct spa_handle *handle, uint32_t type, void **i this = (struct impl *) handle; - if (type == SPA_TYPE_INTERFACE_Monitor) - *interface = &this->monitor; - else + switch (type) { + case SPA_TYPE_INTERFACE_Device: + *interface = &this->device; + break; + default: return -ENOENT; - + } return 0; } static int impl_clear(struct spa_handle *handle) { struct impl *this = (struct impl *) handle; - impl_monitor_set_callbacks(this, NULL, NULL); + stop_monitor(this); + impl_udev_close(this); return 0; } @@ -532,26 +567,38 @@ impl_init(const struct spa_handle_factory *factory, this = (struct impl *) handle; for (i = 0; i < n_support; i++) { - if (support[i].type == SPA_TYPE_INTERFACE_Log) + switch (support[i].type) { + case SPA_TYPE_INTERFACE_Log: this->log = support[i].data; - else if (support[i].type == SPA_TYPE_INTERFACE_Loop) + break; + case SPA_TYPE_INTERFACE_Loop: this->main_loop = support[i].data; + break; + default: + break; + } } if (this->main_loop == NULL) { spa_log_error(this->log, "a main-loop is needed"); return -EINVAL; } + spa_hook_list_init(&this->hooks); - this->monitor.iface = SPA_INTERFACE_INIT( - SPA_TYPE_INTERFACE_Monitor, - SPA_VERSION_MONITOR, - &impl_monitor, this); + this->device.iface = SPA_INTERFACE_INIT( + SPA_TYPE_INTERFACE_Device, + SPA_VERSION_DEVICE, + &impl_device, this); + + this->info = SPA_DEVICE_INFO_INIT(); + this->info_all = SPA_DEVICE_CHANGE_MASK_FLAGS | + SPA_DEVICE_CHANGE_MASK_PROPS; + this->info.flags = 0; return 0; } static const struct spa_interface_info impl_interfaces[] = { - {SPA_TYPE_INTERFACE_Monitor,}, + {SPA_TYPE_INTERFACE_Device,}, }; static int @@ -570,9 +617,9 @@ impl_enum_interface_info(const struct spa_handle_factory *factory, return 1; } -const struct spa_handle_factory spa_alsa_monitor_factory = { +const struct spa_handle_factory spa_alsa_udev_factory = { SPA_VERSION_HANDLE_FACTORY, - SPA_NAME_API_ALSA_MONITOR, + SPA_NAME_API_ALSA_ENUM_UDEV, NULL, impl_get_size, impl_init, diff --git a/spa/plugins/alsa/alsa.c b/spa/plugins/alsa/alsa.c index 5b27cb9c6..d8e5ae7a9 100644 --- a/spa/plugins/alsa/alsa.c +++ b/spa/plugins/alsa/alsa.c @@ -28,7 +28,7 @@ extern const struct spa_handle_factory spa_alsa_source_factory; extern const struct spa_handle_factory spa_alsa_sink_factory; -extern const struct spa_handle_factory spa_alsa_monitor_factory; +extern const struct spa_handle_factory spa_alsa_udev_factory; extern const struct spa_handle_factory spa_alsa_device_factory; extern const struct spa_handle_factory spa_alsa_midi_source_factory; @@ -46,7 +46,7 @@ int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *factory = &spa_alsa_sink_factory; break; case 2: - *factory = &spa_alsa_monitor_factory; + *factory = &spa_alsa_udev_factory; break; case 3: *factory = &spa_alsa_device_factory; diff --git a/spa/plugins/alsa/meson.build b/spa/plugins/alsa/meson.build index 673840717..f370feb29 100644 --- a/spa/plugins/alsa/meson.build +++ b/spa/plugins/alsa/meson.build @@ -1,5 +1,5 @@ spa_alsa_sources = ['alsa.c', - 'alsa-monitor.c', + 'alsa-udev.c', 'alsa-device.c', 'alsa-seq-source.c', 'alsa-seq.c', diff --git a/spa/plugins/bluez5/bluez5-monitor.c b/spa/plugins/bluez5/bluez5-dbus.c similarity index 97% rename from spa/plugins/bluez5/bluez5-monitor.c rename to spa/plugins/bluez5/bluez5-dbus.c index b101592f5..407290635 100644 --- a/spa/plugins/bluez5/bluez5-monitor.c +++ b/spa/plugins/bluez5/bluez5-dbus.c @@ -1,4 +1,4 @@ -/* Spa V4l2 Monitor +/* Spa V4l2 dbus * * Copyright © 2018 Wim Taymans * @@ -41,8 +41,9 @@ #include #include #include -#include +#include #include +#include #include #include #include @@ -54,7 +55,7 @@ struct spa_bt_monitor { struct spa_handle handle; - struct spa_monitor monitor; + struct spa_device device; struct spa_log *log; struct spa_loop *main_loop; @@ -62,7 +63,7 @@ struct spa_bt_monitor { struct spa_dbus_connection *dbus_connection; DBusConnection *conn; - struct spa_callbacks callbacks; + struct spa_hook_list hooks; uint32_t count; uint32_t id; @@ -70,6 +71,8 @@ struct spa_bt_monitor { struct spa_list adapter_list; struct spa_list device_list; struct spa_list transport_list; + + unsigned int filters_added:1; }; struct transport_data { @@ -490,7 +493,7 @@ static int device_free(struct spa_bt_device *device) static int device_add(struct spa_bt_monitor *monitor, struct spa_bt_device *device) { - struct spa_monitor_object_info info; + struct spa_device_object_info info; char dev[32]; struct spa_dict_item items[20]; uint32_t n_items = 0; @@ -498,11 +501,11 @@ static int device_add(struct spa_bt_monitor *monitor, struct spa_bt_device *devi if (device->added) return 0; - info = SPA_MONITOR_OBJECT_INFO_INIT(); + info = SPA_DEVICE_OBJECT_INFO_INIT(); info.type = SPA_TYPE_INTERFACE_Device; info.factory_name = SPA_NAME_API_BLUEZ5_DEVICE; - info.change_mask = SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS | - SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS; + info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS | + SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS; info.flags = 0; items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "bluez5"); @@ -517,7 +520,7 @@ static int device_add(struct spa_bt_monitor *monitor, struct spa_bt_device *devi info.props = &SPA_DICT_INIT(items, n_items); device->added = true; - spa_monitor_call_object_info(&monitor->callbacks, device->id, &info); + spa_device_emit_object_info(&monitor->hooks, device->id, &info); return 0; } @@ -528,7 +531,7 @@ static int device_remove(struct spa_bt_monitor *monitor, struct spa_bt_device *d return 0; device->added = false; - spa_monitor_call_object_info(&monitor->callbacks, device->id, NULL); + spa_device_emit_object_info(&monitor->hooks, device->id, NULL); return 0; } @@ -2128,6 +2131,9 @@ static void add_filters(struct spa_bt_monitor *this) { DBusError err; + if (this->filters_added) + return; + dbus_error_init(&err); if (!dbus_connection_add_filter(this->conn, filter_cb, this, NULL)) { @@ -2158,6 +2164,8 @@ static void add_filters(struct spa_bt_monitor *this) "interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'," "arg0='" BLUEZ_MEDIA_TRANSPORT_INTERFACE "'", &err); + this->filters_added = true; + return; fail: @@ -2165,27 +2173,28 @@ fail: } static int -impl_monitor_set_callbacks(void *object, - const struct spa_monitor_callbacks *callbacks, - void *data) +impl_device_add_listener(void *object, struct spa_hook *listener, + const struct spa_device_events *events, void *data) { struct spa_bt_monitor *this = object; + struct spa_hook_list save; spa_return_val_if_fail(this != NULL, -EINVAL); + spa_return_val_if_fail(events != NULL, -EINVAL); - this->callbacks = SPA_CALLBACKS_INIT(callbacks, data); + spa_hook_list_isolate(&this->hooks, &save, listener, events, data); - if (callbacks) { - add_filters(this); - get_managed_objects(this); - } + add_filters(this); + get_managed_objects(this); + + spa_hook_list_join(&this->hooks, &save); return 0; } -static const struct spa_monitor_methods impl_monitor = { - SPA_VERSION_MONITOR_METHODS, - .set_callbacks = impl_monitor_set_callbacks, +static const struct spa_device_methods impl_device = { + SPA_VERSION_DEVICE_METHODS, + .add_listener = impl_device_add_listener, }; static int impl_get_interface(struct spa_handle *handle, uint32_t type, void **interface) @@ -2197,11 +2206,13 @@ static int impl_get_interface(struct spa_handle *handle, uint32_t type, void **i this = (struct spa_bt_monitor *) handle; - if (type == SPA_TYPE_INTERFACE_Monitor) - *interface = &this->monitor; - else + switch (type) { + case SPA_TYPE_INTERFACE_Device: + *interface = &this->device; + break; + default: return -ENOENT; - + } return 0; } @@ -2260,10 +2271,12 @@ impl_init(const struct spa_handle_factory *factory, } this->conn = spa_dbus_connection_get(this->dbus_connection); - this->monitor.iface = SPA_INTERFACE_INIT( - SPA_TYPE_INTERFACE_Monitor, - SPA_VERSION_MONITOR, - &impl_monitor, this); + spa_hook_list_init(&this->hooks); + + this->device.iface = SPA_INTERFACE_INIT( + SPA_TYPE_INTERFACE_Device, + SPA_VERSION_DEVICE, + &impl_device, this); spa_list_init(&this->adapter_list); spa_list_init(&this->device_list); @@ -2273,7 +2286,7 @@ impl_init(const struct spa_handle_factory *factory, } static const struct spa_interface_info impl_interfaces[] = { - {SPA_TYPE_INTERFACE_Monitor,}, + {SPA_TYPE_INTERFACE_Device,}, }; static int @@ -2293,9 +2306,9 @@ impl_enum_interface_info(const struct spa_handle_factory *factory, return 1; } -const struct spa_handle_factory spa_bluez5_monitor_factory = { +const struct spa_handle_factory spa_bluez5_dbus_factory = { SPA_VERSION_HANDLE_FACTORY, - SPA_NAME_API_BLUEZ5_MONITOR, + SPA_NAME_API_BLUEZ5_ENUM_DBUS, NULL, impl_get_size, impl_init, diff --git a/spa/plugins/bluez5/meson.build b/spa/plugins/bluez5/meson.build index ddcc74fa0..c055a3c17 100644 --- a/spa/plugins/bluez5/meson.build +++ b/spa/plugins/bluez5/meson.build @@ -6,7 +6,7 @@ bluez5_sources = ['plugin.c', 'sco-sink.c', 'sco-source.c', 'bluez5-device.c', - 'bluez5-monitor.c'] + 'bluez5-dbus.c'] bluez5lib = shared_library('spa-bluez5', bluez5_sources, diff --git a/spa/plugins/bluez5/plugin.c b/spa/plugins/bluez5/plugin.c index 2b70a5787..bb09a22a2 100644 --- a/spa/plugins/bluez5/plugin.c +++ b/spa/plugins/bluez5/plugin.c @@ -27,7 +27,7 @@ #include -extern const struct spa_handle_factory spa_bluez5_monitor_factory; +extern const struct spa_handle_factory spa_bluez5_dbus_factory; extern const struct spa_handle_factory spa_bluez5_device_factory; extern const struct spa_handle_factory spa_a2dp_sink_factory; extern const struct spa_handle_factory spa_a2dp_source_factory; @@ -42,7 +42,7 @@ int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t switch (*index) { case 0: - *factory = &spa_bluez5_monitor_factory; + *factory = &spa_bluez5_dbus_factory; break; case 1: *factory = &spa_bluez5_device_factory; diff --git a/spa/plugins/v4l2/meson.build b/spa/plugins/v4l2/meson.build index c80488d7f..802b61bb6 100644 --- a/spa/plugins/v4l2/meson.build +++ b/spa/plugins/v4l2/meson.build @@ -1,6 +1,6 @@ v4l2_sources = ['v4l2.c', 'v4l2-device.c', - 'v4l2-monitor.c', + 'v4l2-udev.c', 'v4l2-source.c'] v4l2lib = shared_library('spa-v4l2', diff --git a/spa/plugins/v4l2/v4l2-monitor.c b/spa/plugins/v4l2/v4l2-udev.c similarity index 81% rename from spa/plugins/v4l2/v4l2-monitor.c rename to spa/plugins/v4l2/v4l2-udev.c index 2069f9f10..faeed10ae 100644 --- a/spa/plugins/v4l2/v4l2-monitor.c +++ b/spa/plugins/v4l2/v4l2-udev.c @@ -1,4 +1,4 @@ -/* Spa V4l2 Monitor +/* Spa V4l2 udev monitor * * Copyright © 2018 Wim Taymans * @@ -37,19 +37,22 @@ #include #include #include -#include +#include #include -#define NAME "v4l2-monitor" +#define NAME "v4l2-udev" struct impl { struct spa_handle handle; - struct spa_monitor monitor; + struct spa_device device; struct spa_log *log; struct spa_loop *main_loop; - struct spa_callbacks callbacks; + struct spa_hook_list hooks; + + uint64_t info_all; + struct spa_device_info info; struct udev *udev; struct udev_monitor *umonitor; @@ -172,20 +175,20 @@ static void unescape(const char *src, char *dst) static int emit_object_info(struct impl *this, uint32_t id, struct udev_device *dev) { - struct spa_monitor_object_info info; + struct spa_device_object_info info; const char *str; struct spa_dict_item items[20]; uint32_t n_items = 0; - info = SPA_MONITOR_OBJECT_INFO_INIT(); + info = SPA_DEVICE_OBJECT_INFO_INIT(); info.type = SPA_TYPE_INTERFACE_Device; info.factory_name = SPA_NAME_API_V4L2_DEVICE; - info.change_mask = SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS | - SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS; + info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS | + SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS; info.flags = 0; - items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_MONITOR_API,"udev"); + items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_ENUM_API,"udev"); items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "v4l2"); items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_API_V4L2_PATH, udev_device_get_devnode(dev)); @@ -256,7 +259,7 @@ static int emit_object_info(struct impl *this, uint32_t id, struct udev_device * items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_CAPABILITIES, str); } info.props = &SPA_DICT_INIT(items, n_items); - spa_monitor_call_object_info(&this->callbacks, id, &info); + spa_device_emit_object_info(&this->hooks, id, &info); return 1; } @@ -282,7 +285,7 @@ static void impl_on_fd_events(struct spa_source *source) strcmp(action, "change") == 0) { emit_object_info(this, id, dev); } else { - spa_monitor_call_object_info(&this->callbacks, id, NULL); + spa_device_emit_object_info(&this->hooks, id, NULL); } udev_device_unref(dev); } @@ -358,38 +361,68 @@ static int enum_devices(struct impl *this) return 0; } +static const struct spa_dict_item device_info_items[] = { + { SPA_KEY_DEVICE_API, "udev" }, + { SPA_KEY_DEVICE_NICK, "v4l2-udev" }, + { SPA_KEY_API_UDEV_MATCH, "video4linux" }, +}; -static int -impl_monitor_set_callbacks(void *object, - const struct spa_monitor_callbacks *callbacks, - void *data) + +static void emit_device_info(struct impl *this, bool full) { - int res; - struct impl *this = object; + if (full) + this->info.change_mask = this->info_all; + if (this->info.change_mask) { + this->info.props = &SPA_DICT_INIT_ARRAY(device_info_items); + spa_device_emit_info(&this->hooks, &this->info); + this->info.change_mask = 0; + } +} - spa_return_val_if_fail(this != NULL, -EINVAL); - - this->callbacks = SPA_CALLBACKS_INIT(callbacks, data); - - if (callbacks) { - if ((res = impl_udev_open(this)) < 0) - return res; - - if ((res = enum_devices(this)) < 0) - return res; - - if ((res = start_monitor(this)) < 0) - return res; - } else { +static void impl_hook_removed(struct spa_hook *hook) +{ + struct impl *this = hook->priv; + if (spa_hook_list_is_empty(&this->hooks)) { stop_monitor(this); impl_udev_close(this); } +} + +static int +impl_device_add_listener(void *object, struct spa_hook *listener, + const struct spa_device_events *events, void *data) +{ + int res; + struct impl *this = object; + struct spa_hook_list save; + + spa_return_val_if_fail(this != NULL, -EINVAL); + spa_return_val_if_fail(events != NULL, -EINVAL); + + if ((res = impl_udev_open(this)) < 0) + return res; + + spa_hook_list_isolate(&this->hooks, &save, listener, events, data); + + emit_device_info(this, true); + + if ((res = enum_devices(this)) < 0) + return res; + + if ((res = start_monitor(this)) < 0) + return res; + + spa_hook_list_join(&this->hooks, &save); + + listener->removed = impl_hook_removed; + listener->priv = this; + return 0; } -static const struct spa_monitor_methods impl_monitor = { - SPA_VERSION_MONITOR_METHODS, - .set_callbacks = impl_monitor_set_callbacks, +static const struct spa_device_methods impl_device = { + SPA_VERSION_DEVICE_METHODS, + .add_listener = impl_device_add_listener, }; static int impl_get_interface(struct spa_handle *handle, uint32_t type, void **interface) @@ -401,10 +434,13 @@ static int impl_get_interface(struct spa_handle *handle, uint32_t type, void **i this = (struct impl *) handle; - if (type == SPA_TYPE_INTERFACE_Monitor) - *interface = &this->monitor; - else + switch (type) { + case SPA_TYPE_INTERFACE_Device: + *interface = &this->device; + break; + default: return -ENOENT; + } return 0; } @@ -412,7 +448,8 @@ static int impl_get_interface(struct spa_handle *handle, uint32_t type, void **i static int impl_clear(struct spa_handle *handle) { struct impl *this = (struct impl *) handle; - impl_monitor_set_callbacks(this, NULL, NULL); + stop_monitor(this); + impl_udev_close(this); return 0; } @@ -455,17 +492,23 @@ impl_init(const struct spa_handle_factory *factory, spa_log_error(this->log, "a main-loop is needed"); return -EINVAL; } + spa_hook_list_init(&this->hooks); - this->monitor.iface = SPA_INTERFACE_INIT( - SPA_TYPE_INTERFACE_Monitor, - SPA_VERSION_MONITOR, - &impl_monitor, this); + this->device.iface = SPA_INTERFACE_INIT( + SPA_TYPE_INTERFACE_Device, + SPA_VERSION_DEVICE, + &impl_device, this); + + this->info = SPA_DEVICE_INFO_INIT(); + this->info_all = SPA_DEVICE_CHANGE_MASK_FLAGS | + SPA_DEVICE_CHANGE_MASK_PROPS; + this->info.flags = 0; return 0; } static const struct spa_interface_info impl_interfaces[] = { - {SPA_TYPE_INTERFACE_Monitor,}, + {SPA_TYPE_INTERFACE_Device,}, }; static int @@ -485,9 +528,9 @@ impl_enum_interface_info(const struct spa_handle_factory *factory, return 1; } -const struct spa_handle_factory spa_v4l2_monitor_factory = { +const struct spa_handle_factory spa_v4l2_udev_factory = { SPA_VERSION_HANDLE_FACTORY, - SPA_NAME_API_V4L2_MONITOR, + SPA_NAME_API_V4L2_ENUM_UDEV, NULL, impl_get_size, impl_init, diff --git a/spa/plugins/v4l2/v4l2.c b/spa/plugins/v4l2/v4l2.c index 06d035696..ee10c2b18 100644 --- a/spa/plugins/v4l2/v4l2.c +++ b/spa/plugins/v4l2/v4l2.c @@ -27,7 +27,7 @@ #include extern const struct spa_handle_factory spa_v4l2_source_factory; -extern const struct spa_handle_factory spa_v4l2_monitor_factory; +extern const struct spa_handle_factory spa_v4l2_udev_factory; extern const struct spa_handle_factory spa_v4l2_device_factory; SPA_EXPORT @@ -42,7 +42,7 @@ int spa_handle_factory_enum(const struct spa_handle_factory **factory, *factory = &spa_v4l2_source_factory; break; case 1: - *factory = &spa_v4l2_monitor_factory; + *factory = &spa_v4l2_udev_factory; break; case 2: *factory = &spa_v4l2_device_factory; diff --git a/spa/tests/test-cpp.cpp b/spa/tests/test-cpp.cpp index 911466873..6e9c17778 100644 --- a/spa/tests/test-cpp.cpp +++ b/spa/tests/test-cpp.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/spa/tests/test-utils.c b/spa/tests/test-utils.c index 5d7c82206..b3fd9982c 100644 --- a/spa/tests/test-utils.c +++ b/spa/tests/test-utils.c @@ -102,13 +102,14 @@ static void test_abi(void) spa_assert(SPA_TYPE_LAST == 21); spa_assert(SPA_TYPE_EVENT_START == 0x30000); - spa_assert(SPA_TYPE_EVENT_Monitor == 0x30001); + spa_assert(SPA_TYPE_EVENT_Device == 0x30001); spa_assert(SPA_TYPE_EVENT_Node == 0x30002); spa_assert(SPA_TYPE_EVENT_LAST == 0x30003); spa_assert(SPA_TYPE_COMMAND_START == 0x40000); - spa_assert(SPA_TYPE_COMMAND_Node == 0x40001); - spa_assert(SPA_TYPE_COMMAND_LAST == 0x40002); + spa_assert(SPA_TYPE_COMMAND_Device == 0x40001); + spa_assert(SPA_TYPE_COMMAND_Node == 0x40002); + spa_assert(SPA_TYPE_COMMAND_LAST == 0x40003); spa_assert(SPA_TYPE_OBJECT_START == 0x50000); spa_assert(SPA_TYPE_OBJECT_PropInfo == 0x50001); diff --git a/spa/tools/spa-monitor.c b/spa/tools/spa-monitor.c index f6c5f49de..1e9e86650 100644 --- a/spa/tools/spa-monitor.c +++ b/spa/tools/spa-monitor.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -56,18 +56,17 @@ struct data { }; -static void inspect_info(struct data *data, const struct spa_monitor_object_info *info) +static void inspect_info(struct data *data, const struct spa_device_object_info *info) { spa_debug_dict(0, info->props); } -static int on_monitor_info(void *_data, const struct spa_monitor_info *info) +static void on_device_info(void *_data, const struct spa_device_info *info) { spa_debug_dict(0, info->props); - return 0; } -static int on_monitor_object_info(void *_data, uint32_t id, const struct spa_monitor_object_info *info) +static void on_device_object_info(void *_data, uint32_t id, const struct spa_device_object_info *info) { struct data *data = _data; @@ -78,7 +77,6 @@ static int on_monitor_object_info(void *_data, uint32_t id, const struct spa_mon fprintf(stderr, "added/changed: %u\n", id); inspect_info(data, info); } - return 0; } static int do_add_source(void *object, struct spa_source *source) @@ -97,15 +95,17 @@ static const struct spa_loop_methods impl_loop = { .add_source = do_add_source, }; -static const struct spa_monitor_callbacks impl_callbacks = { - SPA_VERSION_MONITOR_CALLBACKS, - .info = on_monitor_info, - .object_info = on_monitor_object_info, +static const struct spa_device_events impl_device_events = { + SPA_VERSION_DEVICE_EVENTS, + .info = on_device_info, + .object_info = on_device_object_info, }; -static void handle_monitor(struct data *data, struct spa_monitor *monitor) +static void handle_device(struct data *data, struct spa_device *device) { - spa_monitor_set_callbacks(monitor, &impl_callbacks, data); + struct spa_hook listener; + + spa_device_add_listener(device, &listener, &impl_device_events, data); while (true) { int r; @@ -129,7 +129,7 @@ static void handle_monitor(struct data *data, struct spa_monitor *monitor) break; } if (r == 0) { - fprintf(stderr, "monitor %p: select timeout", monitor); + fprintf(stderr, "device %p: select timeout", device); break; } @@ -139,6 +139,7 @@ static void handle_monitor(struct data *data, struct spa_monitor *monitor) p->func(p); } } + spa_hook_remove(&listener); } int main(int argc, char *argv[]) @@ -193,7 +194,7 @@ int main(int argc, char *argv[]) break; } - if (info->type == SPA_TYPE_INTERFACE_Monitor) { + if (info->type == SPA_TYPE_INTERFACE_Device) { struct spa_handle *handle; void *interface; @@ -206,12 +207,12 @@ int main(int argc, char *argv[]) } if ((res = - spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Monitor, + spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Device, &interface)) < 0) { printf("can't get interface: %s\n", strerror(res)); continue; } - handle_monitor(&data, interface); + handle_device(&data, interface); } } } diff --git a/src/daemon/pipewire.conf.in b/src/daemon/pipewire.conf.in index 0442717f6..d8d2c30c0 100644 --- a/src/daemon/pipewire.conf.in +++ b/src/daemon/pipewire.conf.in @@ -11,11 +11,12 @@ add-spa-lib api.vulkan.* vulkan/libspa-vulkan add-spa-lib api.jack.* jack/libspa-jack #load-module libpipewire-module-spa-device api.jack.device +#load-module libpipewire-module-spa-device api.alsa.enum.udev load-module libpipewire-module-spa-node api.alsa.midi.source node.name=MIDI-Bridge load-module libpipewire-module-rtkit load-module libpipewire-module-protocol-native load-module libpipewire-module-spa-node-factory -load-module libpipewire-module-spa-node api.vulkan.compute.source node.name=my-compute-source +#load-module libpipewire-module-spa-node api.vulkan.compute.source node.name=my-compute-source #load-module libpipewire-module-spa-node videotestsrc/libspa-videotestsrc videotestsrc videotestsrc Spa:POD:Object:Props:patternType=Spa:POD:Object:Props:patternType:snow load-module libpipewire-module-client-node load-module libpipewire-module-client-device diff --git a/src/examples/alsa-monitor.c b/src/examples/alsa-monitor.c index 14fb6c14d..d8e6e04dc 100644 --- a/src/examples/alsa-monitor.c +++ b/src/examples/alsa-monitor.c @@ -221,7 +221,7 @@ static struct alsa_object *alsa_find_object(struct monitor *monitor, uint32_t id } static void alsa_update_object(struct monitor *monitor, struct alsa_object *obj, - const struct spa_monitor_object_info *info) + const struct spa_device_object_info *info) { pw_log_debug("update object %u", obj->id); spa_debug_dict(0, info->props); @@ -306,7 +306,7 @@ static int update_device_props(struct alsa_object *obj) static struct alsa_object *alsa_create_object(struct monitor *monitor, uint32_t id, - const struct spa_monitor_object_info *info) + const struct spa_device_object_info *info) { struct impl *impl = monitor->impl; struct pw_core *core = impl->core; @@ -384,8 +384,8 @@ static void alsa_remove_object(struct monitor *monitor, struct alsa_object *obj) free(obj); } -static int alsa_monitor_object_info(void *data, uint32_t id, - const struct spa_monitor_object_info *info) +static void alsa_udev_object_info(void *data, uint32_t id, + const struct spa_device_object_info *info) { struct monitor *monitor = data; struct alsa_object *obj; @@ -394,21 +394,20 @@ static int alsa_monitor_object_info(void *data, uint32_t id, if (info == NULL) { if (obj == NULL) - return -ENODEV; + return; alsa_remove_object(monitor, obj); } else if (obj == NULL) { if ((obj = alsa_create_object(monitor, id, info)) == NULL) - return -ENOMEM; + return; } else { alsa_update_object(monitor, obj, info); } - return 0; } -static const struct spa_monitor_callbacks alsa_monitor_callbacks = +static const struct spa_device_events alsa_udev_events = { - SPA_VERSION_MONITOR_CALLBACKS, - .object_info = alsa_monitor_object_info, + SPA_VERSION_DEVICE_EVENTS, + .object_info = alsa_udev_object_info, }; static int alsa_start_monitor(struct impl *impl, struct monitor *monitor) @@ -418,14 +417,14 @@ static int alsa_start_monitor(struct impl *impl, struct monitor *monitor) int res; void *iface; - handle = pw_core_load_spa_handle(core, SPA_NAME_API_ALSA_MONITOR, NULL); + handle = pw_core_load_spa_handle(core, SPA_NAME_API_ALSA_ENUM_UDEV, NULL); if (handle == NULL) { res = -errno; goto out; } - if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Monitor, &iface)) < 0) { - pw_log_error("can't get MONITOR interface: %d", res); + if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Device, &iface)) < 0) { + pw_log_error("can't get udev Device interface: %d", res); goto out_unload; } @@ -434,7 +433,7 @@ static int alsa_start_monitor(struct impl *impl, struct monitor *monitor) monitor->monitor = iface; spa_list_init(&monitor->object_list); - spa_monitor_set_callbacks(monitor->monitor, &alsa_monitor_callbacks, monitor); + spa_device_add_listener(monitor->monitor, &monitor->listener, &alsa_udev_events, monitor); return 0; diff --git a/src/examples/bluez-monitor.c b/src/examples/bluez-monitor.c index 1ae5ffe0f..74771ae3f 100644 --- a/src/examples/bluez-monitor.c +++ b/src/examples/bluez-monitor.c @@ -212,14 +212,14 @@ static struct bluez5_object *bluez5_find_object(struct monitor *monitor, uint32_ } static void bluez5_update_object(struct monitor *monitor, struct bluez5_object *obj, - const struct spa_monitor_object_info *info) + const struct spa_device_object_info *info) { pw_log_debug("update object %u", obj->id); spa_debug_dict(0, info->props); } static struct bluez5_object *bluez5_create_object(struct monitor *monitor, uint32_t id, - const struct spa_monitor_object_info *info) + const struct spa_device_object_info *info) { struct impl *impl = monitor->impl; struct pw_core *core = impl->core; @@ -303,8 +303,8 @@ static void bluez5_remove_object(struct monitor *monitor, struct bluez5_object * free(obj); } -static int bluez5_monitor_object_info(void *data, uint32_t id, - const struct spa_monitor_object_info *info) +static void bluez5_enum_object_info(void *data, uint32_t id, + const struct spa_device_object_info *info) { struct monitor *monitor = data; struct bluez5_object *obj; @@ -313,21 +313,20 @@ static int bluez5_monitor_object_info(void *data, uint32_t id, if (info == NULL) { if (obj == NULL) - return -ENODEV; + return; bluez5_remove_object(monitor, obj); } else if (obj == NULL) { if ((obj = bluez5_create_object(monitor, id, info)) == NULL) - return -ENOMEM; + return; } else { bluez5_update_object(monitor, obj, info); } - return 0; } -static const struct spa_monitor_callbacks bluez5_monitor_callbacks = +static const struct spa_device_events bluez5_enum_callbacks = { - SPA_VERSION_MONITOR_CALLBACKS, - .object_info = bluez5_monitor_object_info, + SPA_VERSION_DEVICE_EVENTS, + .object_info = bluez5_enum_object_info, }; static int bluez5_start_monitor(struct impl *impl, struct monitor *monitor) @@ -337,14 +336,14 @@ static int bluez5_start_monitor(struct impl *impl, struct monitor *monitor) int res; void *iface; - handle = pw_core_load_spa_handle(core, SPA_NAME_API_BLUEZ5_MONITOR, NULL); + handle = pw_core_load_spa_handle(core, SPA_NAME_API_BLUEZ5_ENUM_DBUS, NULL); if (handle == NULL) { res = -errno; goto out; } - if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Monitor, &iface)) < 0) { - pw_log_error("can't get MONITOR interface: %d", res); + if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Device, &iface)) < 0) { + pw_log_error("can't get Device interface: %d", res); goto out_unload; } @@ -353,7 +352,8 @@ static int bluez5_start_monitor(struct impl *impl, struct monitor *monitor) monitor->monitor = iface; spa_list_init(&monitor->object_list); - spa_monitor_set_callbacks(monitor->monitor, &bluez5_monitor_callbacks, monitor); + spa_device_add_listener(monitor->monitor, &monitor->listener, + &bluez5_enum_callbacks, monitor); return 0; diff --git a/src/examples/bluez-session.c b/src/examples/bluez-session.c index 66898f6aa..aafef325f 100644 --- a/src/examples/bluez-session.c +++ b/src/examples/bluez-session.c @@ -64,7 +64,7 @@ struct object { struct spa_handle *handle; struct pw_proxy *proxy; struct spa_device *device; - struct spa_hook device_listener; + struct spa_hook listener; struct spa_list node_list; }; @@ -78,11 +78,11 @@ struct impl { struct pw_remote *remote; struct spa_hook remote_listener; - struct spa_handle *monitor_handle; - struct spa_monitor *monitor; - struct spa_hook monitor_listener; + struct spa_handle *handle; + struct spa_device *device; + struct spa_hook listener; - struct spa_list object_list; + struct spa_list device_list; }; static struct node *find_node(struct object *obj, uint32_t id) @@ -199,7 +199,7 @@ static struct object *find_object(struct impl *impl, uint32_t id) { struct object *obj; - spa_list_for_each(obj, &impl->object_list, link) { + spa_list_for_each(obj, &impl->device_list, link) { if (obj->id == id) return obj; } @@ -207,14 +207,14 @@ static struct object *find_object(struct impl *impl, uint32_t id) } static void update_object(struct impl *impl, struct object *obj, - const struct spa_monitor_object_info *info) + const struct spa_device_object_info *info) { pw_log_debug("update object %u", obj->id); spa_debug_dict(0, info->props); } static struct object *create_object(struct impl *impl, uint32_t id, - const struct spa_monitor_object_info *info) + const struct spa_device_object_info *info) { struct pw_core *core = impl->core; struct object *obj; @@ -256,9 +256,9 @@ static struct object *create_object(struct impl *impl, uint32_t id, spa_list_init(&obj->node_list); spa_device_add_listener(obj->device, - &obj->device_listener, &device_events, obj); + &obj->listener, &device_events, obj); - spa_list_append(&impl->object_list, &obj->link); + spa_list_append(&impl->device_list, &obj->link); update_object(impl, obj, info); @@ -276,14 +276,14 @@ static void remove_object(struct impl *impl, struct object *obj) { pw_log_debug("remove object %u", obj->id); spa_list_remove(&obj->link); - spa_hook_remove(&obj->device_listener); + spa_hook_remove(&obj->listener); pw_proxy_destroy(obj->proxy); free(obj->handle); free(obj); } -static int monitor_object_info(void *data, uint32_t id, - const struct spa_monitor_object_info *info) +static void dbus_device_object_info(void *data, uint32_t id, + const struct spa_device_object_info *info) { struct impl *impl = data; struct object *obj; @@ -292,21 +292,20 @@ static int monitor_object_info(void *data, uint32_t id, if (info == NULL) { if (obj == NULL) - return -ENODEV; + return; remove_object(impl, obj); } else if (obj == NULL) { if ((obj = create_object(impl, id, info)) == NULL) - return -ENOMEM; + return; } else { update_object(impl, obj, info); } - return 0; } -static const struct spa_monitor_callbacks monitor_callbacks = +static const struct spa_device_events dbus_device_events = { - SPA_VERSION_MONITOR_CALLBACKS, - .object_info = monitor_object_info, + SPA_VERSION_DEVICE_EVENTS, + .object_info = dbus_device_object_info, }; static int start_monitor(struct impl *impl) @@ -315,21 +314,21 @@ static int start_monitor(struct impl *impl) int res; void *iface; - handle = pw_core_load_spa_handle(impl->core, SPA_NAME_API_BLUEZ5_MONITOR, NULL); + handle = pw_core_load_spa_handle(impl->core, SPA_NAME_API_BLUEZ5_ENUM_DBUS, NULL); if (handle == NULL) { res = -errno; goto out; } - if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Monitor, &iface)) < 0) { + if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Device, &iface)) < 0) { pw_log_error("can't get MONITOR interface: %d", res); goto out_unload; } - impl->monitor_handle = handle; - impl->monitor = iface; + impl->handle = handle; + impl->device = iface; - spa_monitor_set_callbacks(impl->monitor, &monitor_callbacks, impl); + spa_device_add_listener(impl->device, &impl->listener, &dbus_device_events, impl); return 0; @@ -390,7 +389,7 @@ int main(int argc, char *argv[]) clock_gettime(CLOCK_MONOTONIC, &impl.now); - spa_list_init(&impl.object_list); + spa_list_init(&impl.device_list); pw_remote_add_listener(impl.remote, &impl.remote_listener, diff --git a/src/examples/media-session.c b/src/examples/media-session.c index 3db9b011c..a2bbf31b9 100644 --- a/src/examples/media-session.c +++ b/src/examples/media-session.c @@ -55,7 +55,9 @@ struct monitor { struct impl *impl; struct spa_handle *handle; - struct spa_monitor *monitor; + + struct spa_device *monitor; + struct spa_hook listener; struct spa_list object_list; }; diff --git a/src/examples/v4l2-monitor.c b/src/examples/v4l2-monitor.c index b273553d1..6f69debc7 100644 --- a/src/examples/v4l2-monitor.c +++ b/src/examples/v4l2-monitor.c @@ -206,7 +206,7 @@ static struct v4l2_object *v4l2_find_object(struct monitor *monitor, uint32_t id } static void v4l2_update_object(struct monitor *monitor, struct v4l2_object *obj, - const struct spa_monitor_object_info *info) + const struct spa_device_object_info *info) { pw_log_debug("update object %u", obj->id); spa_debug_dict(0, info->props); @@ -240,7 +240,7 @@ static int v4l2_update_device_props(struct v4l2_object *obj) } static struct v4l2_object *v4l2_create_object(struct monitor *monitor, uint32_t id, - const struct spa_monitor_object_info *info) + const struct spa_device_object_info *info) { struct impl *impl = monitor->impl; struct pw_core *core = impl->core; @@ -318,8 +318,8 @@ static void v4l2_remove_object(struct monitor *monitor, struct v4l2_object *obj) free(obj); } -static int v4l2_monitor_object_info(void *data, uint32_t id, - const struct spa_monitor_object_info *info) +static void v4l2_udev_object_info(void *data, uint32_t id, + const struct spa_device_object_info *info) { struct monitor *monitor = data; struct v4l2_object *obj; @@ -328,21 +328,20 @@ static int v4l2_monitor_object_info(void *data, uint32_t id, if (info == NULL) { if (obj == NULL) - return -ENODEV; + return; v4l2_remove_object(monitor, obj); } else if (obj == NULL) { if ((obj = v4l2_create_object(monitor, id, info)) == NULL) - return -ENOMEM; + return; } else { v4l2_update_object(monitor, obj, info); } - return 0; } -static const struct spa_monitor_callbacks v4l2_monitor_callbacks = +static const struct spa_device_events v4l2_udev_callbacks = { - SPA_VERSION_MONITOR_CALLBACKS, - .object_info = v4l2_monitor_object_info, + SPA_VERSION_DEVICE_EVENTS, + .object_info = v4l2_udev_object_info, }; static int v4l2_start_monitor(struct impl *impl, struct monitor *monitor) @@ -352,13 +351,13 @@ static int v4l2_start_monitor(struct impl *impl, struct monitor *monitor) int res; void *iface; - handle = pw_core_load_spa_handle(core, SPA_NAME_API_V4L2_MONITOR, NULL); + handle = pw_core_load_spa_handle(core, SPA_NAME_API_V4L2_ENUM_UDEV, NULL); if (handle == NULL) { res = -errno; goto out; } - if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Monitor, &iface)) < 0) { + if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Device, &iface)) < 0) { pw_log_error("can't get MONITOR interface: %d", res); goto out_unload; } @@ -368,7 +367,8 @@ static int v4l2_start_monitor(struct impl *impl, struct monitor *monitor) monitor->monitor = iface; spa_list_init(&monitor->object_list); - spa_monitor_set_callbacks(monitor->monitor, &v4l2_monitor_callbacks, monitor); + spa_device_add_listener(monitor->monitor, &monitor->listener, + &v4l2_udev_callbacks, monitor); return 0; diff --git a/src/modules/spa/meson.build b/src/modules/spa/meson.build index 255588d87..e8bbc9d53 100644 --- a/src/modules/spa/meson.build +++ b/src/modules/spa/meson.build @@ -3,15 +3,6 @@ pipewire_module_spa_c_args = [ '-D_GNU_SOURCE', ] -pipewire_module_spa_monitor = shared_library('pipewire-module-spa-monitor', - [ 'module-monitor.c', 'spa-monitor.c', 'spa-node.c', 'spa-device.c' ], - c_args : pipewire_module_spa_c_args, - include_directories : [configinc, spa_inc], - install : true, - install_dir : modules_install_dir, - dependencies : [mathlib, dl_lib, pipewire_dep], -) - pipewire_module_spa_node = shared_library('pipewire-module-spa-node', [ 'module-node.c', 'spa-node.c' ], c_args : pipewire_module_spa_c_args, diff --git a/src/modules/spa/module-device.c b/src/modules/spa/module-device.c index 684419a02..921bcd7f4 100644 --- a/src/modules/spa/module-device.c +++ b/src/modules/spa/module-device.c @@ -35,7 +35,6 @@ #include #include -#include "spa-monitor.h" #include "spa-device.h" #define MODULE_USAGE " [key=value ...]" diff --git a/src/modules/spa/module-monitor.c b/src/modules/spa/module-monitor.c deleted file mode 100644 index 8c7228bea..000000000 --- a/src/modules/spa/module-monitor.c +++ /dev/null @@ -1,123 +0,0 @@ -/* PipeWire - * Copyright © 2016 Axis Communications - * @author Linus Svensson - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "spa-monitor.h" - -#define MODULE_USAGE " [key=value ...]" - -static const struct spa_dict_item module_props[] = { - { PW_KEY_MODULE_AUTHOR, "Wim Taymans " }, - { PW_KEY_MODULE_DESCRIPTION, "Manage SPA monitors" }, - { PW_KEY_MODULE_USAGE, MODULE_USAGE }, - { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, -}; - -struct data { - struct pw_spa_monitor *monitor; - struct spa_hook module_listener; -}; - -static void module_destroy(void *data) -{ - struct data *d = data; - - spa_hook_remove(&d->module_listener); - - pw_spa_monitor_destroy(d->monitor); -} - -const struct pw_module_events module_events = { - PW_VERSION_MODULE_EVENTS, - .destroy = module_destroy, -}; - -SPA_EXPORT -int pipewire__module_init(struct pw_module *module, const char *args) -{ - struct pw_core *core = pw_module_get_core(module); - struct pw_properties *props = NULL; - char **argv = NULL; - int n_tokens, res; - struct pw_spa_monitor *monitor; - struct data *data; - - if (args == NULL) - goto error_arguments; - - argv = pw_split_strv(args, " \t", INT_MAX, &n_tokens); - if (n_tokens < 2) - goto error_arguments; - - if (n_tokens == 3) { - props = pw_properties_new_string(argv[2]); - if (props == NULL) { - res = -errno; - goto error_exit_cleanup; - } - } - - monitor = pw_spa_monitor_load(core, - argv[0], argv[1], - props, - sizeof(struct data)); - if (monitor == NULL) { - res = -errno; - goto error_exit_cleanup; - } - - pw_free_strv(argv); - - data = monitor->user_data; - data->monitor = monitor; - - pw_module_add_listener(module, &data->module_listener, &module_events, data); - - pw_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props)); - - return 0; - -error_arguments: - res = -EINVAL; - pw_log_error("usage: module-spa-monitor " MODULE_USAGE); - goto error_exit_cleanup; -error_exit_cleanup: - if (argv) - pw_free_strv(argv); - return res; -} diff --git a/src/modules/spa/module-node.c b/src/modules/spa/module-node.c index d4828c251..0b80fadc6 100644 --- a/src/modules/spa/module-node.c +++ b/src/modules/spa/module-node.c @@ -37,7 +37,6 @@ #include #include -#include "spa-monitor.h" #include "spa-node.h" #define MODULE_USAGE " [key=value ...]" diff --git a/src/modules/spa/spa-monitor.c b/src/modules/spa/spa-monitor.c deleted file mode 100644 index deff494b9..000000000 --- a/src/modules/spa/spa-monitor.c +++ /dev/null @@ -1,336 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "spa-monitor.h" -#include "spa-device.h" - -struct monitor_object { - uint32_t id; - char *name; - struct spa_list link; - struct spa_handle *handle; - uint32_t type; - void *object; - struct spa_hook object_listener; -}; - -struct impl { - struct pw_spa_monitor this; - - struct pw_core *core; - - struct spa_list item_list; -}; - -static void device_free(void *data) -{ - struct monitor_object *obj = data; - spa_hook_remove(&obj->object_listener); - spa_list_remove(&obj->link); - pw_unload_spa_handle(obj->handle); - free(obj); -} - -static const struct pw_device_events device_events = { - PW_VERSION_DEVICE_EVENTS, - .free = device_free -}; - -static struct monitor_object *add_object(struct pw_spa_monitor *this, uint32_t id, - const struct spa_monitor_object_info *info, uint64_t now) -{ - struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); - struct pw_core *core = impl->core; - int res; - struct spa_handle *handle; - struct monitor_object *obj; - const char *name, *str; - void *iface; - struct pw_properties *props = NULL; - - if (info->props) - props = pw_properties_new_dict(info->props); - else - props = pw_properties_new(NULL, NULL); - - if (props == NULL) - return NULL; - - if ((name = pw_properties_get(props, PW_KEY_DEVICE_NAME)) == NULL) - name = "unknown"; - - pw_log_debug("monitor %p: add: \"%s\" (%u)", this, name, id); - - if ((str = pw_properties_get(props, PW_KEY_DEVICE_FORM_FACTOR)) != NULL) - if (strcmp(str, "internal") == 0) - now = 0; - if (now != 0 && pw_properties_get(props, PW_KEY_DEVICE_PLUGGED) == NULL) - pw_properties_setf(props, PW_KEY_DEVICE_PLUGGED, "%"PRIu64, now); - - handle = pw_core_load_spa_handle(core, info->factory_name, - &props->dict); - if (handle == NULL) { - res = -errno; - pw_log_error("can't make factory instance: %m"); - goto error_exit_free_props; - } - - if ((res = spa_handle_get_interface(handle, info->type, &iface)) < 0) { - pw_log_error("can't get %d interface: %s", info->type, spa_strerror(res)); - goto error_exit_free_handle; - } - - obj = calloc(1, sizeof(struct monitor_object)); - if (obj == NULL) { - res = -errno; - goto error_exit_free_handle; - } - obj->id = id; - obj->name = strdup(name); - obj->handle = handle; - obj->type = info->type; - - switch (obj->type) { - case SPA_TYPE_INTERFACE_Device: - { - struct pw_device *device; - device = pw_spa_device_new(core, - 0, iface, handle, props, 0); - pw_device_add_listener(device, &obj->object_listener, - &device_events, obj); - obj->object = device; - break; - } - default: - res = -ENOTSUP; - pw_log_error("interface %d not implemented", obj->type); - goto error_exit_free_object; - } - - spa_list_append(&impl->item_list, &obj->link); - - return obj; - -error_exit_free_object: - free(obj->name); - free(obj); -error_exit_free_handle: - pw_unload_spa_handle(handle); -error_exit_free_props: - pw_properties_free(props); - errno = -res; - return NULL; -} - -static struct monitor_object *find_object(struct pw_spa_monitor *this, uint32_t id) -{ - struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); - struct monitor_object *obj; - - spa_list_for_each(obj, &impl->item_list, link) { - if (obj->id == id) { - return obj; - } - } - return NULL; -} - -void destroy_object(struct monitor_object *obj) -{ - switch (obj->type) { - case SPA_TYPE_INTERFACE_Node: - pw_node_destroy(obj->object); - break; - case SPA_TYPE_INTERFACE_Device: - pw_device_destroy(obj->object); - break; - default: - break; - } -} - -static void change_object(struct pw_spa_monitor *this, struct monitor_object *obj, - const struct spa_monitor_object_info *info, uint64_t now) -{ - pw_log_debug("monitor %p: change: \"%s\" (%u)", this, obj->name, obj->id); -} - -static int on_monitor_object_info(void *data, uint32_t id, - const struct spa_monitor_object_info *info) -{ - struct impl *impl = data; - struct pw_spa_monitor *this = &impl->this; - struct timespec now; - uint64_t now_nsec; - struct monitor_object *obj; - - clock_gettime(CLOCK_MONOTONIC, &now); - now_nsec = SPA_TIMESPEC_TO_NSEC(&now); - - obj = find_object(this, id); - - if (info == NULL) { - if (obj == NULL) - return -ENODEV; - - pw_log_debug("monitor %p: remove: (%s) %u", this, obj->name, id); - destroy_object(obj); - } else if (obj == NULL) { - obj = add_object(this, id, info, now_nsec); - if (obj == NULL) - return -errno; - } else { - change_object(this, obj, info, now_nsec); - } - return 0; -} - -static void update_monitor(struct pw_core *core, const char *name) -{ - const char *monitors; - struct spa_dict_item item; - const struct pw_properties *props; - struct spa_dict dict = SPA_DICT_INIT(&item, 1); - - props = pw_core_get_properties(core); - - if (props) - monitors = pw_properties_get(props, PW_KEY_CORE_MONITORS); - else - monitors = NULL; - - item.key = PW_KEY_CORE_MONITORS; - if (monitors == NULL) - item.value = name; - else - asprintf((char **) &item.value, "%s,%s", monitors, name); - - pw_core_update_properties(core, &dict); - - if (monitors != NULL) - free((void *) item.value); -} - -static const struct spa_monitor_callbacks callbacks = { - SPA_VERSION_MONITOR_CALLBACKS, - .object_info = on_monitor_object_info, -}; - -struct pw_spa_monitor *pw_spa_monitor_load(struct pw_core *core, - const char *factory_name, - const char *system_name, - struct pw_properties *properties, - size_t user_data_size) -{ - struct impl *impl; - struct pw_spa_monitor *this; - struct spa_handle *handle; - int res; - void *iface; - - handle = pw_core_load_spa_handle(core, - factory_name, - properties ? &properties->dict : NULL); - if (handle == NULL) { - res = -errno; - goto error_exit; - } - - if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Monitor, &iface)) < 0) { - pw_log_error("can't get MONITOR interface: %s", spa_strerror(res)); - goto error_exit_unload; - } - - impl = calloc(1, sizeof(struct impl) + user_data_size); - if (impl == NULL) { - res = -errno; - goto error_exit_unload; - } - - impl->core = core; - spa_list_init(&impl->item_list); - - this = &impl->this; - this->monitor = iface; - this->factory_name = strdup(factory_name); - this->system_name = strdup(system_name); - this->handle = handle; - this->properties = properties; - - if (user_data_size > 0) - this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void); - - update_monitor(core, this->system_name); - - spa_monitor_set_callbacks(this->monitor, &callbacks, impl); - - return this; - -error_exit_unload: - pw_unload_spa_handle(handle); -error_exit: - errno = -res; - return NULL; -} - -void pw_spa_monitor_destroy(struct pw_spa_monitor *monitor) -{ - struct impl *impl = SPA_CONTAINER_OF(monitor, struct impl, this); - struct monitor_object *obj, *tmp; - - pw_log_debug("spa-monitor %p: destroy", impl); - - spa_list_for_each_safe(obj, tmp, &impl->item_list, link) - destroy_object(obj); - - pw_unload_spa_handle(monitor->handle); - free(monitor->factory_name); - free(monitor->system_name); - if (monitor->properties) - pw_properties_free(monitor->properties); - free(impl); -} diff --git a/src/modules/spa/spa-monitor.h b/src/modules/spa/spa-monitor.h deleted file mode 100644 index 6bea028bb..000000000 --- a/src/modules/spa/spa-monitor.h +++ /dev/null @@ -1,60 +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_SPA_MONITOR_H -#define PIPEWIRE_SPA_MONITOR_H - -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct pw_spa_monitor { - struct spa_monitor *monitor; - - char *factory_name; - char *system_name; - struct spa_handle *handle; - struct pw_properties *properties; - - void *user_data; -}; - -struct pw_spa_monitor * -pw_spa_monitor_load(struct pw_core *core, - const char *factory_name, - const char *system_name, - struct pw_properties *properties, - size_t user_data_size); -void -pw_spa_monitor_destroy(struct pw_spa_monitor *monitor); - -#ifdef __cplusplus -} -#endif - -#endif /* PIPEWIRE_SPA_MONITOR_H */ diff --git a/src/pipewire/client.c b/src/pipewire/client.c index b37acbf30..149132f84 100644 --- a/src/pipewire/client.c +++ b/src/pipewire/client.c @@ -409,7 +409,7 @@ int pw_client_register(struct pw_client *client, client->registered = true; client->info.id = client->global->id; - pw_properties_setf(client->properties, PW_KEY_CLIENT_ID, "%d", client->info.id); + pw_properties_setf(client->properties, PW_KEY_OBJECT_ID, "%d", client->info.id); client->info.props = &client->properties->dict; pw_global_add_listener(client->global, &client->global_listener, &global_events, client); diff --git a/src/pipewire/core.c b/src/pipewire/core.c index 856fe6bfb..d84b6fc43 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -590,7 +590,7 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, goto error_free_loop; } this->info.id = this->global->id; - pw_properties_setf(this->properties, PW_KEY_CORE_ID, "%d", this->info.id); + pw_properties_setf(this->properties, PW_KEY_OBJECT_ID, "%d", this->info.id); this->info.props = &this->properties->dict; pw_global_add_listener(this->global, &this->global_listener, &global_events, this); diff --git a/src/pipewire/device.c b/src/pipewire/device.c index f1b5f5679..2a7d64ab3 100644 --- a/src/pipewire/device.c +++ b/src/pipewire/device.c @@ -65,14 +65,52 @@ struct resource_data { struct spa_hook listener; }; -struct node_data { +struct object_data { struct spa_list link; - struct pw_node *node; - struct spa_handle *handle; uint32_t id; - struct spa_hook node_listener; + uint32_t type; + struct spa_handle *handle; + void *object; + struct spa_hook listener; }; +static void object_destroy(struct object_data *od) +{ + switch (od->type) { + case SPA_TYPE_INTERFACE_Node: + pw_node_destroy(od->object); + break; + case SPA_TYPE_INTERFACE_Device: + pw_device_destroy(od->object); + break; + } +} + +static void object_update(struct object_data *od, const struct spa_dict *props) +{ + switch (od->type) { + case SPA_TYPE_INTERFACE_Node: + pw_node_update_properties(od->object, props); + break; + case SPA_TYPE_INTERFACE_Device: + pw_device_update_properties(od->object, props); + break; + } +} + +static void object_register(struct object_data *od) +{ + switch (od->type) { + case SPA_TYPE_INTERFACE_Node: + pw_node_register(od->object, NULL); + pw_node_set_active(od->object, true); + break; + case SPA_TYPE_INTERFACE_Device: + pw_device_register(od->object, NULL); + break; + } +} + static void check_properties(struct pw_device *device) { const char *str; @@ -116,7 +154,7 @@ struct pw_device *pw_device_new(struct pw_core *core, this->info.params = this->params; spa_hook_list_init(&this->listener_list); - spa_list_init(&this->node_list); + spa_list_init(&this->object_list); if (user_data_size > 0) this->user_data = SPA_MEMBER(this, sizeof(struct impl), void); @@ -137,13 +175,13 @@ error_cleanup: SPA_EXPORT void pw_device_destroy(struct pw_device *device) { - struct node_data *nd; + struct object_data *od; pw_log_debug(NAME" %p: destroy", device); pw_device_emit_destroy(device); - spa_list_consume(nd, &device->node_list, link) - pw_node_destroy(nd->node); + spa_list_consume(od, &device->object_list, link) + object_destroy(od); if (device->registered) spa_list_remove(&device->link); @@ -366,7 +404,7 @@ int pw_device_register(struct pw_device *device, struct pw_properties *properties) { struct pw_core *core = device->core; - struct node_data *nd; + struct object_data *od; const char *keys[] = { PW_KEY_MODULE_ID, PW_KEY_CLIENT_ID, @@ -400,16 +438,15 @@ int pw_device_register(struct pw_device *device, device->registered = true; device->info.id = device->global->id; - pw_properties_setf(device->properties, PW_KEY_DEVICE_ID, "%d", device->info.id); + pw_properties_setf(device->properties, PW_KEY_OBJECT_ID, "%d", device->info.id); device->info.props = &device->properties->dict; pw_global_add_listener(device->global, &device->global_listener, &global_events, device); pw_global_register(device->global); - spa_list_for_each(nd, &device->node_list, link) { - pw_node_register(nd->node, NULL); - pw_node_set_active(nd->node, true); - } + spa_list_for_each(od, &device->object_list, link) + object_register(od); + return 0; error_existed: @@ -418,22 +455,28 @@ error_existed: return -EEXIST; } -static void node_destroy(void *data) +static void on_object_destroy(void *data) { - struct node_data *nd = data; - spa_list_remove(&nd->link); + struct object_data *od = data; + spa_list_remove(&od->link); } -static void node_free(void *data) +static void on_object_free(void *data) { - struct node_data *nd = data; - pw_unload_spa_handle(nd->handle); + struct object_data *od = data; + pw_unload_spa_handle(od->handle); } -static const struct pw_node_events node_events = { +static const struct pw_node_events node_object_events = { PW_VERSION_NODE_EVENTS, - .destroy = node_destroy, - .free = node_free, + .destroy = on_object_destroy, + .free = on_object_free, +}; + +static const struct pw_device_events device_object_events = { + PW_VERSION_DEVICE_EVENTS, + .destroy = on_object_destroy, + .free = on_object_free, }; static void emit_info_changed(struct pw_device *device) @@ -481,21 +524,16 @@ static void device_info(void *data, const struct spa_device_info *info) emit_info_changed(device); } -static void device_add(struct pw_device *device, uint32_t id, +static void device_add_object(struct pw_device *device, uint32_t id, const struct spa_device_object_info *info) { struct pw_core *core = device->core; struct spa_handle *handle; - struct pw_node *node; - struct node_data *nd; struct pw_properties *props; int res; void *iface; + struct object_data *od = NULL; - if (info->type != SPA_TYPE_INTERFACE_Node) { - pw_log_warn(NAME" %p: unknown type %d", device, info->type); - return; - } if (info->factory_name == NULL) { pw_log_warn(NAME" %p: missing factory name", device); return; @@ -518,32 +556,52 @@ static void device_add(struct pw_device *device, uint32_t id, if (info->props && props) pw_properties_update(props, info->props); - node = pw_node_new(core, - props, - sizeof(struct node_data)); + switch (info->type) { + case SPA_TYPE_INTERFACE_Node: + { + struct pw_node *node; + node = pw_node_new(core, props, sizeof(struct object_data)); - nd = pw_node_get_user_data(node); - nd->id = id; - nd->node = node; - nd->handle = handle; - pw_node_add_listener(node, &nd->node_listener, &node_events, nd); - spa_list_append(&device->node_list, &nd->link); + od = pw_node_get_user_data(node); + od->object = node; + pw_node_add_listener(node, &od->listener, &node_object_events, od); + pw_node_set_implementation(node, iface); + break; + } + case SPA_TYPE_INTERFACE_Device: + { + struct pw_device *dev; + dev = pw_device_new(core, props, sizeof(struct object_data)); - pw_node_set_implementation(node, iface); + od = pw_device_get_user_data(dev); + od->object = dev; + pw_device_add_listener(dev, &od->listener, &device_object_events, od); + pw_device_set_implementation(dev, iface); + break; + } + default: + pw_log_warn(NAME" %p: unknown type %d", device, info->type); + pw_properties_free(props); + break; + } - if (device->global) { - pw_node_register(node, NULL); - pw_node_set_active(node, true); + if (od) { + od->id = id; + od->type = info->type; + od->handle = handle; + spa_list_append(&device->object_list, &od->link); + if (device->global) + object_register(od); } return; } -static struct node_data *find_node(struct pw_device *device, uint32_t id) +static struct object_data *find_object(struct pw_device *device, uint32_t id) { - struct node_data *nd; - spa_list_for_each(nd, &device->node_list, link) { - if (nd->id == id) - return nd; + struct object_data *od; + spa_list_for_each(od, &device->object_list, link) { + if (od->id == id) + return od; } return NULL; } @@ -552,25 +610,25 @@ static void device_object_info(void *data, uint32_t id, const struct spa_device_object_info *info) { struct pw_device *device = data; - struct node_data *nd; + struct object_data *od; - nd = find_node(device, id); + od = find_object(device, id); if (info == NULL) { - if (nd) { + if (od) { pw_log_debug(NAME" %p: remove node %d", device, id); - pw_node_destroy(nd->node); + object_destroy(od); } else { pw_log_warn(NAME" %p: unknown node %d", device, id); } } - else if (nd != NULL) { + else if (od != NULL) { if (info->change_mask & SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS) - pw_node_update_properties(nd->node, info->props); + object_update(od, info->props); } else { - device_add(device, id, info); + device_add_object(device, id, info); } } diff --git a/src/pipewire/factory.c b/src/pipewire/factory.c index 5fbff04c3..08d76c0da 100644 --- a/src/pipewire/factory.c +++ b/src/pipewire/factory.c @@ -229,7 +229,7 @@ int pw_factory_register(struct pw_factory *factory, factory->registered = true; factory->info.id = factory->global->id; - pw_properties_setf(factory->properties, PW_KEY_FACTORY_ID, "%d", factory->info.id); + pw_properties_setf(factory->properties, PW_KEY_OBJECT_ID, "%d", factory->info.id); factory->info.props = &factory->properties->dict; pw_global_add_listener(factory->global, &factory->global_listener, &global_events, factory); diff --git a/src/pipewire/keys.h b/src/pipewire/keys.h index 8600bd316..92f82f929 100644 --- a/src/pipewire/keys.h +++ b/src/pipewire/keys.h @@ -66,6 +66,8 @@ extern "C" { #define PW_KEY_LIBRARY_NAME_LOOP "library.name.loop" /**< name of the loop library to use */ #define PW_KEY_LIBRARY_NAME_DBUS "library.name.dbus" /**< name of the dbus library to use */ +#define PW_KEY_OBJECT_ID "object.id" /**< a global object id */ + #define PW_KEY_CORE_ID "core.id" /**< the core id */ #define PW_KEY_CORE_MONITORS "core.monitors" /**< the apis monitored by core. */ diff --git a/src/pipewire/link.c b/src/pipewire/link.c index c4aeb79ba..99f250c30 100644 --- a/src/pipewire/link.c +++ b/src/pipewire/link.c @@ -1451,7 +1451,7 @@ int pw_link_register(struct pw_link *link, link->registered = true; link->info.id = link->global->id; - pw_properties_setf(link->properties, PW_KEY_LINK_ID, "%d", link->info.id); + pw_properties_setf(link->properties, PW_KEY_OBJECT_ID, "%d", link->info.id); link->info.props = &link->properties->dict; pw_global_add_listener(link->global, &link->global_listener, &global_events, link); diff --git a/src/pipewire/module.c b/src/pipewire/module.c index a36107ac5..438acdbe8 100644 --- a/src/pipewire/module.c +++ b/src/pipewire/module.c @@ -261,7 +261,7 @@ pw_module_load(struct pw_core *core, spa_list_append(&core->module_list, &this->link); this->info.id = this->global->id; - pw_properties_setf(this->properties, PW_KEY_MODULE_ID, "%d", this->info.id); + pw_properties_setf(this->properties, PW_KEY_OBJECT_ID, "%d", this->info.id); this->info.props = &this->properties->dict; pw_global_add_listener(this->global, &this->global_listener, &global_events, this); diff --git a/src/pipewire/node.c b/src/pipewire/node.c index 8b01164ec..be95a9506 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -588,7 +588,7 @@ int pw_node_register(struct pw_node *this, this->info.id = this->global->id; this->rt.activation->position.clock.id = this->info.id; - pw_properties_setf(this->properties, PW_KEY_NODE_ID, "%d", this->info.id); + pw_properties_setf(this->properties, PW_KEY_OBJECT_ID, "%d", this->info.id); this->info.props = &this->properties->dict; pw_node_initialized(this); diff --git a/src/pipewire/port.c b/src/pipewire/port.c index 01037f91d..2ea9e179d 100644 --- a/src/pipewire/port.c +++ b/src/pipewire/port.c @@ -714,7 +714,7 @@ int pw_port_register(struct pw_port *port, port->info.id = port->global->id; pw_properties_setf(port->properties, PW_KEY_NODE_ID, "%d", node->global->id); - pw_properties_setf(port->properties, PW_KEY_PORT_ID, "%d", port->info.id); + pw_properties_setf(port->properties, PW_KEY_OBJECT_ID, "%d", port->info.id); port->info.props = &port->properties->dict; return pw_global_register(port->global); diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 8bc892790..6ff7c0cec 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -302,7 +302,7 @@ struct pw_device { struct spa_hook listener; struct spa_hook_list listener_list; - struct spa_list node_list; + struct spa_list object_list; void *user_data; /**< device user_data */