mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-14 06:59:57 -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
|
|
@ -1,4 +1,4 @@
|
|||
/* Spa ALSA Monitor
|
||||
/* Spa ALSA udev
|
||||
*
|
||||
* Copyright © 2018 Wim Taymans
|
||||
*
|
||||
|
|
@ -30,7 +30,6 @@
|
|||
#include <poll.h>
|
||||
|
||||
#include <libudev.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include <spa/support/log.h>
|
||||
#include <spa/utils/type.h>
|
||||
|
|
@ -38,10 +37,10 @@
|
|||
#include <spa/utils/names.h>
|
||||
#include <spa/support/loop.h>
|
||||
#include <spa/support/plugin.h>
|
||||
#include <spa/monitor/monitor.h>
|
||||
#include <spa/monitor/device.h>
|
||||
#include <spa/monitor/utils.h>
|
||||
|
||||
#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,
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Spa V4l2 Monitor
|
||||
/* Spa V4l2 dbus
|
||||
*
|
||||
* Copyright © 2018 Wim Taymans
|
||||
*
|
||||
|
|
@ -41,8 +41,9 @@
|
|||
#include <spa/support/loop.h>
|
||||
#include <spa/support/dbus.h>
|
||||
#include <spa/support/plugin.h>
|
||||
#include <spa/monitor/monitor.h>
|
||||
#include <spa/monitor/device.h>
|
||||
#include <spa/monitor/utils.h>
|
||||
#include <spa/utils/hook.h>
|
||||
#include <spa/utils/type.h>
|
||||
#include <spa/utils/keys.h>
|
||||
#include <spa/utils/names.h>
|
||||
|
|
@ -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,
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include <spa/support/plugin.h>
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Spa V4l2 Monitor
|
||||
/* Spa V4l2 udev monitor
|
||||
*
|
||||
* Copyright © 2018 Wim Taymans
|
||||
*
|
||||
|
|
@ -37,19 +37,22 @@
|
|||
#include <spa/utils/type.h>
|
||||
#include <spa/utils/keys.h>
|
||||
#include <spa/utils/names.h>
|
||||
#include <spa/monitor/monitor.h>
|
||||
#include <spa/monitor/device.h>
|
||||
#include <spa/monitor/utils.h>
|
||||
|
||||
#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,
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
#include <spa/support/plugin.h>
|
||||
|
||||
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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue