]> git.alsa-project.org Git - alsa-gobject.git/commitdiff
seq: event_cntr: add accesor APIs for blob data of event pointed by index
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Mon, 8 Jun 2020 14:10:10 +0000 (23:10 +0900)
committer坂本 貴史 <o-takashi@sakamocchi.jp>
Tue, 9 Jun 2020 00:16:09 +0000 (09:16 +0900)
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
src/seq/alsaseq.map
src/seq/event-cntr.c
src/seq/event-cntr.h
tests/alsaseq-event-cntr

index ac54c9957ee4f4b3ceffe820f879c94d6d89a3c9..408a9f25d84da25e07bd7963550c47150fe92759 100644 (file)
@@ -202,6 +202,8 @@ ALSA_GOBJECT_0_0_0 {
     "alsaseq_event_cntr_set_byte_data";
     "alsaseq_event_cntr_get_quadlet_data";
     "alsaseq_event_cntr_set_quadlet_data";
+    "alsaseq_event_cntr_get_blob_data";
+    "alsaseq_event_cntr_set_blob_data";
   local:
     *;
 };
index 0884d516572c5b9d5bb3d1c2ab23d2a3832aed95..630dbb5872fa5ed98b82f0c85ae5c852dc622efd 100644 (file)
@@ -820,6 +820,57 @@ static void ensure_fixed_length_event(ALSASeqEventCntrPrivate *priv,
     ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
 }
 
+static void ensure_variable_length_event(ALSASeqEventCntrPrivate *priv,
+                                struct snd_seq_event *ev, const guint8 *data,
+                                gsize size, GError **error)
+{
+    guint8 *pos = (guint8 *)ev;
+    ptrdiff_t from_head = pos + sizeof(*ev) - priv->buf;
+    ptrdiff_t to_tail;
+    guint8 *next_ev;
+    guint8 *new;
+
+    if (!priv->allocated) {
+        generate_error(error, ENOBUFS);
+        return;
+    }
+
+    switch (ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) {
+    case SNDRV_SEQ_EVENT_LENGTH_VARIABLE:
+        // Expand or shrink total area for new blob.
+        next_ev = pos + sizeof(*ev) + ev->data.ext.len;
+        break;
+    default:
+        // Expand total area with blob size.
+        next_ev = pos + sizeof(*ev);
+        break;
+    }
+
+    to_tail = priv->length - (next_ev - priv->buf);
+
+    new = g_try_malloc(from_head + size + to_tail);
+    if (new == NULL) {
+        generate_error(error, ENOMEM);
+        return;
+    }
+
+    memcpy(new, priv->buf, from_head);
+    memcpy(new + from_head, data, size);
+    memcpy(new + from_head + size, next_ev, to_tail);
+
+    g_free(priv->buf);
+    priv->buf = new;
+    priv->length = from_head + size + to_tail;
+
+    from_head -= sizeof(*ev);
+    pos = priv->buf + from_head;
+    ev = (struct snd_seq_event *)pos;
+    ev->data.ext.len = size;
+
+    ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
+    ev->flags |= SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
+}
+
 /**
  * alsaseq_event_cntr_get_note_data:
  * @self: A #ALSASeqEventCntr.
@@ -1069,3 +1120,79 @@ void alsaseq_event_cntr_set_quadlet_data(ALSASeqEventCntr *self, gsize index,
 
     memcpy(ev->data.raw32.d, data, sizeof(ev->data.raw32.d));
 }
+
+/**
+ * alsaseq_event_cntr_get_blob_data:
+ * @self: A #ALSASeqEventCntr.
+ * @index: The index of event to set.
+ * @data: (array length=size)(out)(transfer none): The pointer to blob data.
+ * @size: The size of data.
+ * @error: A #GError.
+ *
+ * Refer to the blob data of event.
+ */
+void alsaseq_event_cntr_get_blob_data(ALSASeqEventCntr *self, gsize index,
+                                        const guint8 **data, gsize *size,
+                                        GError **error)
+{
+    ALSASeqEventCntrPrivate *priv;
+    struct event_iterator iter;
+    struct snd_seq_event *ev;
+
+    g_return_if_fail(ALSASEQ_IS_EVENT_CNTR(self));
+    priv = alsaseq_event_cntr_get_instance_private(self);
+
+    event_iterator_init(&iter, priv->buf, priv->length, priv->allocated);
+    ev = event_iterator_find(&iter, index);
+    if (ev == NULL) {
+        generate_error(error, EINVAL);
+        return;
+    }
+
+    switch (ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) {
+    case SNDRV_SEQ_EVENT_LENGTH_VARIABLE:
+    {
+        const struct snd_seq_ev_ext *ext = &ev->data.ext;
+        if (priv->allocated)
+            *data = ((guint8 *)ev) + sizeof(*ev);
+        else
+            *data = ext->ptr;
+        *size = ext->len;
+        break;
+    }
+    default:
+        generate_error(error, ENODATA);
+        break;
+    }
+}
+
+/**
+ * alsaseq_event_cntr_set_blob_data:
+ * @self: A #ALSASeqEventCntr.
+ * @index: The index of event to set.
+ * @data: (array length=size): The pointer to blob data for the event.
+ * @size: The size of data.
+ * @error: A #GError.
+ *
+ * Copy the quadlet data to the event pointed by the index.
+ */
+void alsaseq_event_cntr_set_blob_data(ALSASeqEventCntr *self, gsize index,
+                                        const guint8 *data, gsize size,
+                                        GError **error)
+{
+    ALSASeqEventCntrPrivate *priv;
+    struct event_iterator iter;
+    struct snd_seq_event *ev;
+
+    g_return_if_fail(ALSASEQ_IS_EVENT_CNTR(self));
+    priv = alsaseq_event_cntr_get_instance_private(self);
+
+    event_iterator_init(&iter, priv->buf, priv->length, priv->allocated);
+    ev = event_iterator_find(&iter, index);
+    if (ev == NULL) {
+        generate_error(error, EINVAL);
+        return;
+    }
+
+    ensure_variable_length_event(priv, ev, data, size, error);
+}
index 03b4f0ed77d4b0e974f9e9ad64c3ac41dbc2b6a0..902f1e0c781725ec7ab7f39fe5ee391baae2d5ef 100644 (file)
@@ -134,6 +134,13 @@ void alsaseq_event_cntr_get_quadlet_data(ALSASeqEventCntr *self, gsize index,
 void alsaseq_event_cntr_set_quadlet_data(ALSASeqEventCntr *self, gsize index,
                                         const guint32 data[3], GError **error);
 
+void alsaseq_event_cntr_get_blob_data(ALSASeqEventCntr *self, gsize index,
+                                        const guint8 **data, gsize *size,
+                                        GError **error);
+void alsaseq_event_cntr_set_blob_data(ALSASeqEventCntr *self, gsize index,
+                                        const guint8 *data, gsize size,
+                                        GError **error);
+
 G_END_DECLS
 
 #endif
index 4e9dbde01331cb203329fae7e72b1e4f11110f6a..91abad04bafa9cdca70d5bd40271fb3e8c4fcc8e 100644 (file)
@@ -42,6 +42,8 @@ methods = (
     'set_byte_data',
     'get_quadlet_data',
     'set_quadlet_data',
+    'get_blob_data',
+    'set_blob_data',
 )
 signals = ()