]> git.alsa-project.org Git - alsa-gobject.git/commitdiff
rawmidi: stream_pair: add an API to create GSource
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Mon, 18 Nov 2019 04:22:44 +0000 (13:22 +0900)
committer坂本 貴史 <o-takashi@sakamocchi.jp>
Sun, 12 Apr 2020 05:30:33 +0000 (14:30 +0900)
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
src/rawmidi/alsarawmidi.map
src/rawmidi/stream-pair.c
src/rawmidi/stream-pair.h
tests/alsarawmidi-stream-pair

index 9f81ab183cfb3c4ca8a3585cf971341556c2f307..dc74eb6ec50b7f4298ffd9640e1de83f466e6088 100644 (file)
@@ -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";
index 265e0c2eaf6028239644bdd71723fa5f69d601c4..e085425d4b9d602bb3477e73985c2bcda5cd9685 100644 (file)
@@ -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);
+}
index 79a4d8e8202d562e3443af70f6fe026966ef5804..f25c8f3a5cc9c38139c7c1e7d0fb92adafb0f700 100644 (file)
@@ -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
index 300246117ed1a48256149ef8d4d8cf812400b7ef..b31a0956f9368f3a98354899bb97b4bb5fc8c293 100644 (file)
@@ -23,6 +23,7 @@ methods = (
     'write_to_substream',
     'drain_substream',
     'drop_substream',
+    'create_source',
 )
 signals = ()