mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-20 06:59:58 -05:00
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.
This commit is contained in:
parent
818fb9e904
commit
6756a3c8fc
43 changed files with 474 additions and 1015 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
#include <pipewire/utils.h>
|
||||
#include <pipewire/keys.h>
|
||||
|
||||
#include "spa-monitor.h"
|
||||
#include "spa-device.h"
|
||||
|
||||
#define MODULE_USAGE "<factory> [key=value ...]"
|
||||
|
|
|
|||
|
|
@ -1,123 +0,0 @@
|
|||
/* PipeWire
|
||||
* Copyright © 2016 Axis Communications <dev-gstreamer@axis.com>
|
||||
* @author Linus Svensson <linus.svensson@axis.com>
|
||||
* 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 <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <pipewire/utils.h>
|
||||
#include <pipewire/log.h>
|
||||
#include <pipewire/core.h>
|
||||
#include <pipewire/module.h>
|
||||
#include <pipewire/keys.h>
|
||||
|
||||
#include "spa-monitor.h"
|
||||
|
||||
#define MODULE_USAGE "<factory> <name> [key=value ...]"
|
||||
|
||||
static const struct spa_dict_item module_props[] = {
|
||||
{ PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
|
||||
{ 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;
|
||||
}
|
||||
|
|
@ -37,7 +37,6 @@
|
|||
#include <pipewire/module.h>
|
||||
#include <pipewire/utils.h>
|
||||
|
||||
#include "spa-monitor.h"
|
||||
#include "spa-node.h"
|
||||
|
||||
#define MODULE_USAGE "<factory> [key=value ...]"
|
||||
|
|
|
|||
|
|
@ -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 <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <spa/node/node.h>
|
||||
#include <spa/monitor/monitor.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/debug/pod.h>
|
||||
|
||||
#include <pipewire/log.h>
|
||||
#include <pipewire/type.h>
|
||||
#include <pipewire/node.h>
|
||||
#include <pipewire/device.h>
|
||||
#include <pipewire/keys.h>
|
||||
#include <pipewire/pipewire.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -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 <spa/monitor/monitor.h>
|
||||
|
||||
#include <pipewire/core.h>
|
||||
|
||||
#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 */
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue