From 55f796b5ad339f13baf8dba953f9f195fb9618ed Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 18 Nov 2019 13:22:44 +0900 Subject: [PATCH] rawmidi: add global method to get list of directional subdevices for rawmidi device Signed-off-by: Takashi Sakamoto --- src/rawmidi/alsarawmidi.map | 1 + src/rawmidi/query.c | 100 ++++++++++++++++++++++++++++++++++++ src/rawmidi/query.h | 7 +++ 3 files changed, 108 insertions(+) diff --git a/src/rawmidi/alsarawmidi.map b/src/rawmidi/alsarawmidi.map index 5b375a2..31d8eee 100644 --- a/src/rawmidi/alsarawmidi.map +++ b/src/rawmidi/alsarawmidi.map @@ -6,6 +6,7 @@ ALSA_GOBJECT_0_0_0 { "alsarawmidi_get_device_id_list"; "alsarawmidi_get_rawmidi_sysname"; "alsarawmidi_get_rawmidi_devnode"; + "alsarawmidi_get_subdevice_id_list"; local: *; }; diff --git a/src/rawmidi/query.c b/src/rawmidi/query.c index 4d035f0..3abdfb2 100644 --- a/src/rawmidi/query.c +++ b/src/rawmidi/query.c @@ -5,15 +5,22 @@ #include #include #include +#include +#include +#include +#include #include +#include + // For error reporting. G_DEFINE_QUARK("alsarawmidi-error", alsarawmidi_error) // 'C' is required apart from emulation of Open Sound System. #define PREFIX_SYSNAME_TEMPLATE "midiC%u" #define RAWMIDI_SYSNAME_TEMPLATE "midiC%uD%u" +#define CTL_SYSNAME_TEMPLATE "controlC%u" static void prepare_udev_enum(struct udev_enumerate **enumerator, GError **error) { @@ -296,3 +303,96 @@ void alsarawmidi_get_rawmidi_devnode(guint card_id, guint device_id, udev_device_unref(dev); udev_unref(ctx); } + +static void rawmidi_perform_ctl_ioctl(guint card_id, long request, void *data, + GError **error) +{ + unsigned int length; + char *sysname; + struct udev *ctx; + struct udev_device *dev; + const char *devnode; + int fd; + + length = strlen(CTL_SYSNAME_TEMPLATE) + calculate_digits(card_id) + 1; + sysname = g_try_malloc0(length); + if (sysname == NULL) { + generate_error(error, ENOMEM); + return; + } + snprintf(sysname, length, CTL_SYSNAME_TEMPLATE, card_id); + + ctx = udev_new(); + if (ctx == NULL) { + generate_error(error, errno); + goto err_sysname; + } + + dev = udev_device_new_from_subsystem_sysname(ctx, "sound", sysname); + if (dev == NULL) { + generate_error(error, errno); + goto err_ctx; + } + + devnode = udev_device_get_devnode(dev); + if (devnode == NULL) { + generate_error(error, ENODEV); + goto err_device; + } + + fd = open(devnode, O_RDONLY); + if (fd < 0) { + generate_error(error, errno); + goto err_device; + } + + if (ioctl(fd, request, data) < 0) + generate_error(error, errno); +err_device: + udev_device_unref(dev); +err_ctx: + udev_unref(ctx); +err_sysname: + g_free(sysname); +} + +/** + * alsarawmidi_get_subdevice_id_list: + * @card: The numberical value for sound card to query. + * @device: The numerical value of rawmidi device to query. + * @direction: The direction of stream to query, one of + * ALSARawmidiStreamDirection. + * @entries: (array length=entry_count)(out): The list of card. + * @entry_count: The number of entries. + * @error: A #GError. + */ +void alsarawmidi_get_subdevice_id_list(guint card, guint device, + ALSARawmidiStreamDirection direction, + guint **entries, gsize *entry_count, + GError **error) +{ + struct snd_rawmidi_info info = { + .card = card, + .device = device, + .stream = direction, + .subdevice = 0, + }; + int i; + + g_return_if_fail(entries != NULL); + g_return_if_fail(entry_count != NULL); + + rawmidi_perform_ctl_ioctl(card, SNDRV_CTL_IOCTL_RAWMIDI_INFO, &info, error); + if (*error != NULL) + return; + + *entries = g_try_malloc0_n(info.subdevices_count, sizeof(guint)); + if (*entries == NULL) { + generate_error(error, ENOMEM); + return; + } + + for (i = 0; i < info.subdevices_count; ++i) + (*entries)[i] = i; + *entry_count = info.subdevices_count; +} diff --git a/src/rawmidi/query.h b/src/rawmidi/query.h index eb2b7c6..be5f2c9 100644 --- a/src/rawmidi/query.h +++ b/src/rawmidi/query.h @@ -5,6 +5,8 @@ #include #include +#include + G_BEGIN_DECLS void alsarawmidi_get_device_id_list(guint card_id, @@ -17,6 +19,11 @@ void alsarawmidi_get_rawmidi_sysname(guint card_id, guint device_id, void alsarawmidi_get_rawmidi_devnode(guint card_id, guint device_id, char **devnode, GError **error); +void alsarawmidi_get_subdevice_id_list(guint card, guint device, + ALSARawmidiStreamDirection direction, + guint **entries, gsize *entry_count, + GError **error); + G_END_DECLS #endif -- 2.47.3