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 */