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:
Wim Taymans 2019-09-20 13:04:14 +02:00
parent 818fb9e904
commit 6756a3c8fc
43 changed files with 474 additions and 1015 deletions

View file

@ -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,

View file

@ -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;

View file

@ -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',