From: Takashi Sakamoto Date: Mon, 18 Nov 2019 04:22:44 +0000 (+0900) Subject: rawmidi: stream_pair: add an API to create GSource X-Git-Tag: v0.1.0~171 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=4e0e683fdcbfc5468e240bc1aebbdc58ffa814a7;p=alsa-gobject.git rawmidi: stream_pair: add an API to create GSource Signed-off-by: Takashi Sakamoto --- diff --git a/src/rawmidi/alsarawmidi.map b/src/rawmidi/alsarawmidi.map index 9f81ab1..dc74eb6 100644 --- a/src/rawmidi/alsarawmidi.map +++ b/src/rawmidi/alsarawmidi.map @@ -21,6 +21,7 @@ ALSA_GOBJECT_0_0_0 { "alsarawmidi_stream_pair_write_to_substream"; "alsarawmidi_stream_pair_drain_substream"; "alsarawmidi_stream_pair_drop_substream"; + "alsarawmidi_stream_pair_create_source"; "alsarawmidi_substream_params_get_type"; "alsarawmidi_substream_params_new"; diff --git a/src/rawmidi/stream-pair.c b/src/rawmidi/stream-pair.c index 265e0c2..e085425 100644 --- a/src/rawmidi/stream-pair.c +++ b/src/rawmidi/stream-pair.c @@ -17,6 +17,12 @@ struct _ALSARawmidiStreamPairPrivate { }; G_DEFINE_TYPE_WITH_PRIVATE(ALSARawmidiStreamPair, alsarawmidi_stream_pair, G_TYPE_OBJECT) +typedef struct { + GSource src; + ALSARawmidiStreamPair *self; + gpointer tag; +} RawmidiStreamPairSource; + enum rawmidi_stream_pair_prop_type { RAWMIDI_STREAM_PAIR_PROP_DEVNODE = 1, RAWMIDI_STREAM_PAIR_PROP_COUNT, @@ -347,3 +353,92 @@ void alsarawmidi_stream_pair_drop_substream(ALSARawmidiStreamPair *self, if (ioctl(priv->fd, SNDRV_RAWMIDI_IOCTL_DROP, &direction) < 0) generate_error(error, errno); } + +static gboolean rawmidi_stream_pair_check_src(GSource *gsrc) +{ + RawmidiStreamPairSource *src = (RawmidiStreamPairSource *)gsrc; + GIOCondition condition; + + // Don't go to dispatch if nothing available. As an exception, return TRUE + // for POLLERR to call .dispatch for internal destruction. + condition = g_source_query_unix_fd(gsrc, src->tag); + return !!(condition & (G_IO_IN | G_IO_ERR)); +} + +static gboolean rawmidi_stream_pair_dispatch_src(GSource *gsrc, GSourceFunc cb, + gpointer user_data) +{ + RawmidiStreamPairSource *src = (RawmidiStreamPairSource *)gsrc; + ALSARawmidiStreamPair *self = src->self; + ALSARawmidiStreamPairPrivate *priv; + GIOCondition condition; + + priv = alsarawmidi_stream_pair_get_instance_private(self); + if (priv->fd < 0) + return G_SOURCE_REMOVE; + + condition = g_source_query_unix_fd(gsrc, src->tag); + if (condition & G_IO_ERR) + return G_SOURCE_REMOVE; + + // Just be sure to continue to process this source. + return G_SOURCE_CONTINUE; +} + +static void rawmidi_stream_pair_finalize_src(GSource *gsrc) +{ + RawmidiStreamPairSource *src = (RawmidiStreamPairSource *)gsrc; + + g_object_unref(src->self); +} + +/** + * alsarawmidi_stream_pair_create_source: + * @self: A #ALSARawmidiStreamPair. + * @gsrc: (out): A #GSource to handle events from ALSA rawmidi character device. + * @error: A #GError. + * + * Allocate GSource structure to handle events from ALSA rawmidi character + * device for input substream. + */ +void alsarawmidi_stream_pair_create_source(ALSARawmidiStreamPair *self, + GSource **gsrc, GError **error) +{ + static GSourceFuncs funcs = { + .check = rawmidi_stream_pair_check_src, + .dispatch = rawmidi_stream_pair_dispatch_src, + .finalize = rawmidi_stream_pair_finalize_src, + }; + ALSARawmidiStreamPairPrivate *priv; + RawmidiStreamPairSource *src; + int access_modes; + + g_return_if_fail(ALSARAWMIDI_IS_STREAM_PAIR(self)); + priv = alsarawmidi_stream_pair_get_instance_private(self); + + if (priv->fd < 0) { + generate_error(error, ENXIO); + return; + } + + access_modes = fcntl(priv->fd, F_GETFL); + if (access_modes < 0) { + generate_error(error, errno); + return; + } + + if (!(access_modes & O_RDWR) && !(access_modes & O_WRONLY)) { + generate_error(error, ENOTSUP); + return; + } + + *gsrc = g_source_new(&funcs, sizeof(RawmidiStreamPairSource)); + src = (RawmidiStreamPairSource *)(*gsrc); + + g_source_set_name(*gsrc, "ALSARawmidiStreamPair"); + g_source_set_priority(*gsrc, G_PRIORITY_HIGH_IDLE); + g_source_set_can_recurse(*gsrc, TRUE); + + src->self = g_object_ref(self); + src->tag = g_source_add_unix_fd(*gsrc, priv->fd, G_IO_IN); +} diff --git a/src/rawmidi/stream-pair.h b/src/rawmidi/stream-pair.h index 79a4d8e..f25c8f3 100644 --- a/src/rawmidi/stream-pair.h +++ b/src/rawmidi/stream-pair.h @@ -87,6 +87,9 @@ void alsarawmidi_stream_pair_drop_substream(ALSARawmidiStreamPair *self, ALSARawmidiStreamDirection direction, GError **error); +void alsarawmidi_stream_pair_create_source(ALSARawmidiStreamPair *self, + GSource **gsrc, GError **error); + G_END_DECLS #endif diff --git a/tests/alsarawmidi-stream-pair b/tests/alsarawmidi-stream-pair index 3002461..b31a095 100644 --- a/tests/alsarawmidi-stream-pair +++ b/tests/alsarawmidi-stream-pair @@ -23,6 +23,7 @@ methods = ( 'write_to_substream', 'drain_substream', 'drop_substream', + 'create_source', ) signals = ()