monitor: Remove monitor event

Remove the monitor event and emit events with structures like we do
for the devices.
This commit is contained in:
Wim Taymans 2019-05-30 12:45:06 +02:00
parent 3780bd1b30
commit 9785d99821
12 changed files with 268 additions and 422 deletions

View file

@ -43,6 +43,10 @@
#define MAX_CARDS 64
#define ACTION_ADD 0
#define ACTION_CHANGE 1
#define ACTION_REMOVE 2
extern const struct spa_handle_factory spa_alsa_device_factory;
struct impl {
@ -81,19 +85,6 @@ static int impl_udev_close(struct impl *this)
return 0;
}
static inline void add_dict(struct spa_pod_builder *builder, const char *key, ...)
{
va_list args;
va_start(args, key);
while (key) {
spa_pod_builder_string(builder, key);
spa_pod_builder_string(builder, va_arg(args, const char*));
key = va_arg(args, const char *);
}
va_end(args);
}
static const char *path_get_card_id(const char *path)
{
const char *e;
@ -110,11 +101,20 @@ static const char *path_get_card_id(const char *path)
return e + 5;
}
static int fill_item(struct impl *this, struct udev_device *dev,
struct spa_pod **result, struct spa_pod_builder *builder)
static int emit_object_info(struct impl *this, uint32_t id, struct udev_device *dev)
{
struct spa_monitor_object_info info;
const char *str, *name;
struct spa_pod_frame f[2];
struct spa_dict_item items[20];
uint32_t n_items = 0;
info = SPA_MONITOR_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Device;
info.factory = &spa_alsa_device_factory;
info.change_mask = SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS |
SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS;
info.flags = 0;
name = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE");
if (!(name && *name)) {
@ -126,54 +126,41 @@ static int fill_item(struct impl *this, struct udev_device *dev,
if (!(name && *name))
name = "Unknown";
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0);
spa_pod_builder_add(builder,
SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)),
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE),
SPA_MONITOR_ITEM_state, SPA_POD_Id(SPA_MONITOR_ITEM_STATE_Available),
SPA_MONITOR_ITEM_name, SPA_POD_String(name),
SPA_MONITOR_ITEM_class, SPA_POD_String("Audio/Device"),
SPA_MONITOR_ITEM_factory, SPA_POD_Pointer(SPA_TYPE_INTERFACE_HandleFactory, &spa_alsa_device_factory),
SPA_MONITOR_ITEM_type, SPA_POD_Id(SPA_TYPE_INTERFACE_Device),
0);
items[n_items++] = SPA_DICT_ITEM_INIT("udev-probed", "1");
items[n_items++] = SPA_DICT_ITEM_INIT("device.path", udev_device_get_devnode(dev));
if ((str = path_get_card_id(udev_device_get_property_value(dev, "DEVPATH"))) == NULL)
return 0;
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0);
spa_pod_builder_push_struct(builder, &f[1]),
add_dict(builder,
"udev-probed", "1",
"device.path", udev_device_get_devnode(dev),
"alsa.card", str,
NULL);
items[n_items++] = SPA_DICT_ITEM_INIT("alsa.card", str);
items[n_items++] = SPA_DICT_ITEM_INIT("device.name", name);
if ((str = udev_device_get_property_value(dev, "SOUND_CLASS")) && *str)
add_dict(builder, "device.class", str, NULL);
items[n_items++] = SPA_DICT_ITEM_INIT("device.class", str);
if ((str = udev_device_get_property_value(dev, "USEC_INITIALIZED")) && *str)
add_dict(builder, "device.plugged.usec", str, NULL);
items[n_items++] = SPA_DICT_ITEM_INIT("device.plugged.usec", str);
str = udev_device_get_property_value(dev, "ID_PATH");
if (!(str && *str))
str = udev_device_get_syspath(dev);
if (str && *str) {
add_dict(builder, "device.bus_path", str, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("device.bus_path", str);
}
if ((str = udev_device_get_syspath(dev)) && *str) {
add_dict(builder, "sysfs.path", str, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("sysfs.path", str);
}
if ((str = udev_device_get_property_value(dev, "ID_ID")) && *str) {
add_dict(builder, "udev.id", str, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("udev.id", str);
}
if ((str = udev_device_get_property_value(dev, "ID_BUS")) && *str) {
add_dict(builder, "device.bus", str, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("device.bus", str);
}
if ((str = udev_device_get_property_value(dev, "SUBSYSTEM")) && *str) {
add_dict(builder, "device.subsystem", str, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("device.subsystem", str);
}
if ((str = udev_device_get_property_value(dev, "ID_VENDOR_ID")) && *str) {
add_dict(builder, "device.vendor.id", str, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("device.vendor.id", str);
}
str = udev_device_get_property_value(dev, "ID_VENDOR_FROM_DATABASE");
if (!(str && *str)) {
@ -183,26 +170,27 @@ static int fill_item(struct impl *this, struct udev_device *dev,
}
}
if (str && *str) {
add_dict(builder, "device.vendor.name", str, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("device.vendor.name", str);
}
if ((str = udev_device_get_property_value(dev, "ID_MODEL_ID")) && *str) {
add_dict(builder, "device.product.id", str, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("device.product.id", str);
}
add_dict(builder, "device.product.name", name, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("device.product.name", name);
if ((str = udev_device_get_property_value(dev, "ID_SERIAL")) && *str) {
add_dict(builder, "device.serial", str, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("device.serial", str);
}
if ((str = udev_device_get_property_value(dev, "SOUND_FORM_FACTOR")) && *str) {
add_dict(builder, "device.form_factor", str, 0);
items[n_items++] = SPA_DICT_ITEM_INIT("device.form_factor", str);
}
spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder, &f[0]);
info.props = &SPA_DICT_INIT(items, n_items);
spa_monitor_call_object_info(&this->callbacks, id, &info);
return 1;
}
static int need_notify(struct impl *this, struct udev_device *dev, uint32_t id, bool enumerated)
static int need_notify(struct impl *this, struct udev_device *dev, uint32_t action, bool enumerated,
uint32_t *id)
{
const char *str;
uint32_t idx, i, found = SPA_ID_INVALID;
@ -225,8 +213,8 @@ static int need_notify(struct impl *this, struct udev_device *dev, uint32_t id,
}
}
switch (id) {
case SPA_MONITOR_EVENT_Added:
switch (action) {
case ACTION_ADD:
if (found != SPA_ID_INVALID)
return 0;
if (this->n_cards >= MAX_CARDS)
@ -237,14 +225,14 @@ static int need_notify(struct impl *this, struct udev_device *dev, uint32_t id,
return 0;
break;
case SPA_MONITOR_EVENT_Changed:
case ACTION_CHANGE:
if (found == SPA_ID_INVALID)
return 0;
if ((str = udev_device_get_property_value(dev, "SOUND_INITIALIZED")) == NULL)
return 0;
break;
case SPA_MONITOR_EVENT_Removed:
case ACTION_REMOVE:
if (found == SPA_ID_INVALID)
return 0;
this->cards[found] = this->cards[--this->n_cards];
@ -252,21 +240,26 @@ static int need_notify(struct impl *this, struct udev_device *dev, uint32_t id,
default:
return 0;
}
*id = idx;
return 1;
}
static int emit_device(struct impl *this, uint32_t id, struct udev_device *dev)
static int emit_device(struct impl *this, uint32_t action, bool enumerated, struct udev_device *dev)
{
uint8_t buffer[4096];
struct spa_pod_builder b = { NULL, };
struct spa_event *event;
struct spa_pod *item;
uint32_t id;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
event = spa_pod_builder_add_object(&b, SPA_TYPE_EVENT_Monitor, id);
fill_item(this, dev, &item, &b);
if (!need_notify(this, dev, action, enumerated, &id))
return 0;
spa_monitor_call_event(&this->callbacks, event);
switch (action) {
case ACTION_ADD:
case ACTION_CHANGE:
emit_object_info(this, id, dev);
break;
default:
spa_monitor_call_object_info(&this->callbacks, id, NULL);
break;
}
return 0;
}
@ -275,7 +268,7 @@ static void impl_on_fd_events(struct spa_source *source)
struct impl *this = source->data;
struct udev_device *dev;
const char *action;
uint32_t id;
uint32_t a;
dev = udev_monitor_receive_device(this->umonitor);
if (dev == NULL)
@ -287,16 +280,15 @@ static void impl_on_fd_events(struct spa_source *source)
spa_log_debug(this->log, "action %s", action);
if (strcmp(action, "add") == 0) {
id = SPA_MONITOR_EVENT_Added;
a = ACTION_ADD;
} else if (strcmp(action, "change") == 0) {
id = SPA_MONITOR_EVENT_Changed;
a = ACTION_CHANGE;
} else if (strcmp(action, "remove") == 0) {
id = SPA_MONITOR_EVENT_Removed;
a = ACTION_REMOVE;
} else
return;
if (need_notify(this, dev, id, false))
emit_device(this, id, dev);
emit_device(this, a, false, dev);
udev_device_unref(dev);
}
@ -354,8 +346,7 @@ static int enum_devices(struct impl *this)
dev = udev_device_new_from_syspath(this->udev, udev_list_entry_get_name(devices));
if (need_notify(this, dev, SPA_MONITOR_EVENT_Added, true))
emit_device(this, SPA_MONITOR_EVENT_Added, dev);
emit_device(this, ACTION_ADD, true, dev);
udev_device_unref(dev);

View file

@ -63,6 +63,7 @@ struct spa_bt_monitor {
struct spa_callbacks callbacks;
uint32_t count;
uint32_t id;
struct spa_list adapter_list;
struct spa_list device_list;
@ -82,39 +83,6 @@ static inline void add_dict(struct spa_pod_builder *builder, const char *key, co
spa_pod_builder_string(builder, val);
}
static void fill_item(struct spa_bt_monitor *this, struct spa_bt_device *device,
struct spa_pod **result, struct spa_pod_builder *builder)
{
char dev[16];
struct spa_pod_frame f[2];
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0);
spa_pod_builder_add(builder,
SPA_MONITOR_ITEM_id, SPA_POD_String(device->path),
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE),
SPA_MONITOR_ITEM_state, SPA_POD_Id(SPA_MONITOR_ITEM_STATE_Available),
SPA_MONITOR_ITEM_name, SPA_POD_String(device->name),
SPA_MONITOR_ITEM_class, SPA_POD_String("Adapter/Bluetooth"),
SPA_MONITOR_ITEM_factory, SPA_POD_Pointer(SPA_TYPE_INTERFACE_HandleFactory,
&spa_bluez5_device_factory),
SPA_MONITOR_ITEM_type, SPA_POD_Id(SPA_TYPE_INTERFACE_Device),
0);
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0);
spa_pod_builder_push_struct(builder, &f[1]);
snprintf(dev, sizeof(dev), "%p", device);
add_dict(builder, "device.api", "bluez5");
add_dict(builder, "device.name", device->name);
add_dict(builder, "device.alias", device->alias);
add_dict(builder, "device.icon", device->icon);
add_dict(builder, "device.bluez5.address", device->address);
add_dict(builder, "bluez5.device", dev);
spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder, &f[0]);
}
static uint8_t a2dp_default_bitpool(struct spa_bt_monitor *monitor, uint8_t freq, uint8_t mode) {
/* These bitpool values were chosen based on the A2DP spec recommendation */
switch (freq) {
@ -489,6 +457,7 @@ static struct spa_bt_device *device_create(struct spa_bt_monitor *monitor, const
if (d == NULL)
return NULL;
d->id = monitor->id++;
d->monitor = monitor;
d->path = strdup(path);
spa_list_init(&d->transport_list);
@ -521,40 +490,45 @@ 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_event *event;
struct spa_pod_builder b = { NULL, };
uint8_t buffer[4096];
struct spa_pod *item;
struct spa_monitor_object_info info;
char dev[16];
struct spa_dict_item items[20];
uint32_t n_items = 0;
if (device->added)
return 0;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
event = spa_pod_builder_add_object(&b, SPA_TYPE_EVENT_Monitor, SPA_MONITOR_EVENT_Added);
fill_item(monitor, device, &item, &b);
info = SPA_MONITOR_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Device;
info.factory = &spa_bluez5_device_factory;
info.change_mask = SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS |
SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS;
info.flags = 0;
items[n_items++] = SPA_DICT_ITEM_INIT("device.path", device->path);
items[n_items++] = SPA_DICT_ITEM_INIT("device.name", device->name);
items[n_items++] = SPA_DICT_ITEM_INIT("device.api", "bluez5");
items[n_items++] = SPA_DICT_ITEM_INIT("device.alias", device->alias);
items[n_items++] = SPA_DICT_ITEM_INIT("device.icon", device->icon);
items[n_items++] = SPA_DICT_ITEM_INIT("device.bluez5.address", device->address);
snprintf(dev, sizeof(dev), "%p", device);
items[n_items++] = SPA_DICT_ITEM_INIT("bluez5.device", dev);
info.props = &SPA_DICT_INIT(items, n_items);
device->added = true;
spa_monitor_call_event(&monitor->callbacks, event);
spa_monitor_call_object_info(&monitor->callbacks, device->id, &info);
return 0;
}
static int device_remove(struct spa_bt_monitor *monitor, struct spa_bt_device *device)
{
struct spa_event *event;
struct spa_pod_builder b = { NULL, };
uint8_t buffer[4096];
struct spa_pod *item;
if (!device->added)
return 0;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
event = spa_pod_builder_add_object(&b, SPA_TYPE_EVENT_Monitor, SPA_MONITOR_EVENT_Removed);
fill_item(monitor, device, &item, &b);
device->added = false;
spa_monitor_call_event(&monitor->callbacks, event);
spa_monitor_call_object_info(&monitor->callbacks, device->id, NULL);
return 0;
}

View file

@ -156,6 +156,7 @@ struct spa_bt_device {
struct spa_list link;
struct spa_bt_monitor *monitor;
struct spa_bt_adapter *adapter;
uint32_t id;
char *path;
char *alias;
char *address;

View file

@ -74,17 +74,36 @@ static int impl_udev_close(struct impl *this)
return 0;
}
static inline void add_dict(struct spa_pod_builder *builder, const char *key, const char *val)
static uint32_t get_device_id(struct impl *this, struct udev_device *dev)
{
spa_pod_builder_string(builder, key);
spa_pod_builder_string(builder, val);
const char *str;
if ((str = udev_device_get_devnode(dev)) == NULL)
return SPA_ID_INVALID;
if (!(str = strrchr(str, '/')))
return SPA_ID_INVALID;
if (strlen(str) <= 6 || strncmp(str, "/video", 6) != 0)
return SPA_ID_INVALID;
return atoi(str + 6);
}
static void fill_item(struct impl *this, struct udev_device *dev,
struct spa_pod **result, struct spa_pod_builder *builder)
static int emit_object_info(struct impl *this, uint32_t id, struct udev_device *dev)
{
struct spa_monitor_object_info info;
const char *str, *name;
struct spa_pod_frame f[2];
struct spa_dict_item items[20];
uint32_t n_items = 0;
info = SPA_MONITOR_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Device;
info.factory = &spa_v4l2_device_factory;
info.change_mask = SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS |
SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS;
info.flags = 0;
name = udev_device_get_property_value(dev, "ID_V4L_PRODUCT");
if (!(name && *name)) {
@ -99,45 +118,33 @@ static void fill_item(struct impl *this, struct udev_device *dev,
if (!(name && *name))
name = "Unknown";
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0);
spa_pod_builder_add(builder,
SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)),
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE),
SPA_MONITOR_ITEM_state, SPA_POD_Id(SPA_MONITOR_ITEM_STATE_Available),
SPA_MONITOR_ITEM_name, SPA_POD_String(name),
SPA_MONITOR_ITEM_class, SPA_POD_String("Video/Device"),
SPA_MONITOR_ITEM_factory, SPA_POD_Pointer(SPA_TYPE_INTERFACE_HandleFactory, &spa_v4l2_device_factory),
SPA_MONITOR_ITEM_type, SPA_POD_Id(SPA_TYPE_INTERFACE_Device),
0);
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0);
spa_pod_builder_push_struct(builder, &f[1]);
add_dict(builder, "udev-probed", "1");
add_dict(builder, "device.path", udev_device_get_devnode(dev));
items[n_items++] = SPA_DICT_ITEM_INIT("udev-probed", "1");
items[n_items++] = SPA_DICT_ITEM_INIT("device.path", udev_device_get_devnode(dev));
items[n_items++] = SPA_DICT_ITEM_INIT("device.name", name);
if ((str = udev_device_get_property_value(dev, "USEC_INITIALIZED")) && *str)
add_dict(builder, "device.plugged.usec", str);
items[n_items++] = SPA_DICT_ITEM_INIT("device.plugged.usec", str);
str = udev_device_get_property_value(dev, "ID_PATH");
if (!(str && *str))
str = udev_device_get_syspath(dev);
if (str && *str) {
add_dict(builder, "device.bus_path", str);
items[n_items++] = SPA_DICT_ITEM_INIT("device.bus_path", str);
}
if ((str = udev_device_get_syspath(dev)) && *str) {
add_dict(builder, "sysfs.path", str);
items[n_items++] = SPA_DICT_ITEM_INIT("sysfs.path", str);
}
if ((str = udev_device_get_property_value(dev, "ID_ID")) && *str) {
add_dict(builder, "udev.id", str);
items[n_items++] = SPA_DICT_ITEM_INIT("udev.id", str);
}
if ((str = udev_device_get_property_value(dev, "ID_BUS")) && *str) {
add_dict(builder, "device.bus", str);
items[n_items++] = SPA_DICT_ITEM_INIT("device.bus", str);
}
if ((str = udev_device_get_property_value(dev, "SUBSYSTEM")) && *str) {
add_dict(builder, "device.subsystem", str);
items[n_items++] = SPA_DICT_ITEM_INIT("device.subsystem", str);
}
if ((str = udev_device_get_property_value(dev, "ID_VENDOR_ID")) && *str) {
add_dict(builder, "device.vendor.id", str);
items[n_items++] = SPA_DICT_ITEM_INIT("device.vendor.id", str);
}
str = udev_device_get_property_value(dev, "ID_VENDOR_FROM_DATABASE");
if (!(str && *str)) {
@ -147,36 +154,22 @@ static void fill_item(struct impl *this, struct udev_device *dev,
}
}
if (str && *str) {
add_dict(builder, "device.vendor.name", str);
items[n_items++] = SPA_DICT_ITEM_INIT("device.vendor.name", str);
}
if ((str = udev_device_get_property_value(dev, "ID_MODEL_ID")) && *str) {
add_dict(builder, "device.product.id", str);
items[n_items++] = SPA_DICT_ITEM_INIT("device.product.id", str);
}
add_dict(builder, "device.product.name", name);
items[n_items++] = SPA_DICT_ITEM_INIT("device.product.name", name);
if ((str = udev_device_get_property_value(dev, "ID_SERIAL")) && *str) {
add_dict(builder, "device.serial", str);
items[n_items++] = SPA_DICT_ITEM_INIT("device.serial", str);
}
if ((str = udev_device_get_property_value(dev, "ID_V4L_CAPABILITIES")) && *str) {
add_dict(builder, "device.capabilities", str);
items[n_items++] = SPA_DICT_ITEM_INIT("device.capabilities", str);
}
info.props = &SPA_DICT_INIT(items, n_items);
spa_monitor_call_object_info(&this->callbacks, id, &info);
spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder, &f[0]);
}
static int emit_device(struct impl *this, uint32_t id, struct udev_device *dev)
{
uint8_t buffer[4096];
struct spa_pod_builder b = { NULL, };
struct spa_event *event;
struct spa_pod *item;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
event = spa_pod_builder_add_object(&b, SPA_TYPE_EVENT_Monitor, id);
fill_item(this, dev, &item, &b);
spa_monitor_call_event(&this->callbacks, event);
return 0;
return 1;
}
static void impl_on_fd_events(struct spa_source *source)
@ -190,20 +183,18 @@ static void impl_on_fd_events(struct spa_source *source)
if (dev == NULL)
return;
if ((id = get_device_id(this, dev)) == SPA_ID_INVALID)
return;
if ((action = udev_device_get_action(dev)) == NULL)
action = "change";
if (strcmp(action, "add") == 0) {
id = SPA_MONITOR_EVENT_Added;
} else if (strcmp(action, "change") == 0) {
id = SPA_MONITOR_EVENT_Changed;
} else if (strcmp(action, "remove") == 0) {
id = SPA_MONITOR_EVENT_Removed;
} else
return;
emit_device(this, id, dev);
if (strcmp(action, "add") == 0 ||
strcmp(action, "change") == 0) {
emit_object_info(this, id, dev);
} else {
spa_monitor_call_object_info(&this->callbacks, id, NULL);
}
udev_device_unref(dev);
}
@ -258,10 +249,16 @@ static int enum_devices(struct impl *this)
while (devices) {
struct udev_device *dev;
uint32_t id;
dev = udev_device_new_from_syspath(this->udev, udev_list_entry_get_name(devices));
if (dev == NULL)
continue;
emit_device(this, SPA_MONITOR_EVENT_Added, dev);
if ((id = get_device_id(this, dev)) == SPA_ID_INVALID)
continue;
emit_object_info(this, id, dev);
udev_device_unref(dev);