]> git.alsa-project.org Git - alsa-gobject.git/commitdiff
rawmidi: stream_pair: add APIs to open ALSA Rawmidi character device
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/privates.h
src/rawmidi/query.c
src/rawmidi/stream-pair.c
src/rawmidi/stream-pair.h
tests/alsarawmidi-stream-pair

index 1c68baaa23855ff8a87048ba038b4d5c39f1eee8..6aace36d2ede3729b23092f95c6082b28ad05298 100644 (file)
@@ -13,6 +13,7 @@ ALSA_GOBJECT_0_0_0 {
 
     "alsarawmidi_stream_pair_get_type";
     "alsarawmidi_stream_pair_new";
+    "alsarawmidi_stream_pair_open";
   local:
     *;
 };
index 9d901ca012707bab46145c081bd5824792060f64..b0f2674d45b22d13d2ee74dfb1d18c1ee2478b8b 100644 (file)
@@ -22,6 +22,8 @@ GQuark alsarawmidi_error_quark(void);
 void rawmidi_substream_info_refer_private(ALSARawmidiSubstreamInfo *self,
                                           struct snd_rawmidi_info **info);
 
+void rawmidi_select_subdevice(guint card_id, guint subdevice_id, GError **error);
+
 G_END_DECLS
 
 #endif
index 7ef4363a1488cf8d26f0842bef60d338fc7847da..b5670e9937455af4f51b7a5230947f790fce52c0 100644 (file)
@@ -429,3 +429,10 @@ void alsarawmidi_get_substream_info(guint card_id, guint device_id,
     if (*error != NULL)
         g_object_unref(*substream_info);
 }
+
+void rawmidi_select_subdevice(guint card_id, guint subdevice_id, GError **error)
+{
+    guint data = subdevice_id;
+    rawmidi_perform_ctl_ioctl(card_id, SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE,
+                              &data, error);
+}
index 4ce38ff283daf4fb06fc074ac984f584eb98dfec..bc00c2942ed18a8d10271ced5cb6034eb0ce07d2 100644 (file)
@@ -1,16 +1,45 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
 #include "stream-pair.h"
+#include "query.h"
+#include "privates.h"
 
-G_DEFINE_TYPE(ALSARawmidiStreamPair, alsarawmidi_stream_pair, G_TYPE_OBJECT)
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+struct _ALSARawmidiStreamPairPrivate {
+    int fd;
+};
+G_DEFINE_TYPE_WITH_PRIVATE(ALSARawmidiStreamPair, alsarawmidi_stream_pair, G_TYPE_OBJECT)
+
+static void rawmidi_stream_pair_finalize(GObject *obj)
+{
+    ALSARawmidiStreamPair *self = ALSARAWMIDI_STREAM_PAIR(obj);
+    ALSARawmidiStreamPairPrivate *priv =
+                            alsarawmidi_stream_pair_get_instance_private(self);
+
+    if (priv->fd >= 0)
+        close(priv->fd);
+
+    G_OBJECT_CLASS(alsarawmidi_stream_pair_parent_class)->finalize(obj);
+}
 
 static void alsarawmidi_stream_pair_class_init(ALSARawmidiStreamPairClass *klass)
 {
-    return;
+    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+    gobject_class->finalize = rawmidi_stream_pair_finalize;
 }
 
 static void alsarawmidi_stream_pair_init(ALSARawmidiStreamPair *self)
 {
-    return;
+    ALSARawmidiStreamPairPrivate *priv =
+                            alsarawmidi_stream_pair_get_instance_private(self);
+
+    priv->fd = -1;
 }
 
 /**
@@ -22,3 +51,64 @@ ALSARawmidiStreamPair *alsarawmidi_stream_pair_new()
 {
     return g_object_new(ALSARAWMIDI_TYPE_STREAM_PAIR, NULL);
 }
+
+/**
+ * alsarawmidi_stream_pair_open:
+ * @self: A #ALSARawmidiStreamPair.
+ * @card_id: The numerical ID of sound card.
+ * @device_id: The numerical ID of rawmidi device for the sound card.
+ * @subdevice_id: The numerical ID of subdevice for the rawmidi device.
+ * @access_modes: Access flags for stream direction.
+ * @open_flag: The flag of open(2) system call. O_RDWR, O_WRONLY and O_RDONLY
+ *             are forced to fulfil internally according to the access_modes.
+ * @error: A #GError.
+ *
+ * Open file descriptor for a pair of streams to attach input/output substreams
+ * corresponding to the given subdevice.
+ */
+void alsarawmidi_stream_pair_open(ALSARawmidiStreamPair *self, guint card_id,
+                                  guint device_id, guint subdevice_id,
+                                  ALSARawmidiStreamPairInfoFlag access_modes,
+                                  gint open_flag, GError **error)
+{
+    ALSARawmidiStreamPairPrivate *priv;
+    char *devnode;
+
+    g_return_if_fail(ALSARAWMIDI_IS_STREAM_PAIR(self));
+    priv = alsarawmidi_stream_pair_get_instance_private(self);
+
+    // The flag is used to attach substreams for each direction.
+    if (access_modes & ~(ALSARAWMIDI_STREAM_PAIR_INFO_FLAG_OUTPUT |
+                         ALSARAWMIDI_STREAM_PAIR_INFO_FLAG_INPUT)) {
+        generate_error(error, EINVAL);
+        return;
+    }
+
+    if ((access_modes & ALSARAWMIDI_STREAM_PAIR_INFO_FLAG_OUTPUT) &&
+        (access_modes & ALSARAWMIDI_STREAM_PAIR_INFO_FLAG_INPUT)) {
+        open_flag = O_RDWR;
+    } else if (access_modes & ALSARAWMIDI_STREAM_PAIR_INFO_FLAG_OUTPUT) {
+        open_flag = O_WRONLY;
+    } else if (access_modes & ALSARAWMIDI_STREAM_PAIR_INFO_FLAG_INPUT) {
+        open_flag = O_RDONLY;
+    } else {
+        generate_error(error, EINVAL);
+        return;
+    }
+
+    alsarawmidi_get_rawmidi_devnode(card_id, device_id, &devnode, error);
+    if (*error != NULL)
+        return;
+
+    rawmidi_select_subdevice(card_id, subdevice_id, error);
+    if (*error != NULL) {
+        g_free(devnode);
+        return;
+    }
+
+    priv->fd = open(devnode, open_flag);
+    if (priv->fd < 0)
+        generate_error(error, errno);
+
+    g_free(devnode);
+}
index 248d62cd2e1aec5da1b4b9ddedbbaafa772a0955..46c40809d0edb31bf21e9df3496ec003cd999789 100644 (file)
@@ -5,6 +5,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include <rawmidi/alsarawmidi-enums.h>
+
 G_BEGIN_DECLS
 
 #define ALSARAWMIDI_TYPE_STREAM_PAIR    (alsarawmidi_stream_pair_get_type())
@@ -31,9 +33,12 @@ G_BEGIN_DECLS
 
 typedef struct _ALSARawmidiStreamPair           ALSARawmidiStreamPair;
 typedef struct _ALSARawmidiStreamPairClass      ALSARawmidiStreamPairClass;
+typedef struct _ALSARawmidiStreamPairPrivate    ALSARawmidiStreamPairPrivate;
 
 struct _ALSARawmidiStreamPair {
     GObject parent_instance;
+
+    ALSARawmidiStreamPairPrivate *priv;
 };
 
 struct _ALSARawmidiStreamPairClass {
@@ -44,6 +49,11 @@ GType alsarawmidi_stream_pair_get_type(void) G_GNUC_CONST;
 
 ALSARawmidiStreamPair *alsarawmidi_stream_pair_new();
 
+void alsarawmidi_stream_pair_open(ALSARawmidiStreamPair *self, guint card_id,
+                                  guint device_id, guint subdevice_id,
+                                  ALSARawmidiStreamPairInfoFlag access_modes,
+                                 gint open_flag, GError **error);
+
 G_END_DECLS
 
 #endif
index cdf19836fc3d967ff94a526ceaf0703d128d1db0..f785617f9fc7a0f9165fe97cc999989d94ab5c36 100644 (file)
@@ -13,6 +13,7 @@ target = ALSARawmidi.StreamPair()
 props = ()
 methods = (
     'new',
+    'open',
 )
 signals = ()