]> git.alsa-project.org Git - alsa-gobject.git/commitdiff
seq: event_cntr: add an API to calculate the number of events
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 d03af9bc623c08f2ad74145cf428d7455da2d435..745ecd05a6cf080981fb821b9092fe87dd5afe20 100644 (file)
@@ -172,6 +172,7 @@ ALSA_GOBJECT_0_0_0 {
 
     "alsaseq_event_cntr_get_type";
     "alsaseq_event_cntr_new";
+    "alsaseq_event_cntr_count_events";
   local:
     *;
 };
index cc935c237024463654c3e17214eb81cf0f81c7e8..598dbf7f81b0ee368f8758b4d3a25b8a2431e0f6 100644 (file)
@@ -74,3 +74,82 @@ ALSASeqEventCntr *alsaseq_event_cntr_new(guint count, GError **error)
 
     return self;
 }
+
+static gsize calculate_event_size(struct snd_seq_event *ev, gboolean aligned)
+{
+    gsize size = sizeof(*ev);
+
+    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 (aligned)
+            size += ext->len;
+        else
+            size += (ext->len + sizeof(*ev) - 1) / sizeof(*ev) * sizeof(*ev);
+        break;
+    }
+    default:
+        break;
+    }
+
+    return size;
+}
+
+struct event_iterator {
+    guint8 *buf;
+    gsize length;
+    gboolean aligned;
+
+    gsize offset;
+};
+
+static void event_iterator_init(struct event_iterator *iter, guint8 *buf,
+                                gsize length, gboolean aligned)
+{
+    iter->buf = buf;
+    iter->length = length;
+    iter->aligned = aligned;
+
+    iter->offset = 0;
+}
+
+static struct snd_seq_event *event_iterator_next(struct event_iterator *iter)
+{
+    struct snd_seq_event *ev;
+    gsize ev_size;
+
+    if (iter->offset + sizeof(*ev) > iter->length)
+        return NULL;
+    ev = (struct snd_seq_event *)(iter->buf + iter->offset);
+
+    ev_size = calculate_event_size(ev, iter->aligned);
+    if (iter->offset + ev_size > iter->length)
+        return NULL;
+    iter->offset += ev_size;
+
+    return ev;
+}
+
+/**
+ * alsaseq_event_cntr_count_events:
+ * @self: A #ALSASeqEventCntr.
+ * @count: (out): The count of stored events.
+ *
+ * count stored events.
+ */
+void alsaseq_event_cntr_count_events(ALSASeqEventCntr *self, gsize *count)
+{
+    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);
+
+    *count = 0;
+    while ((ev = event_iterator_next(&iter)))
+        ++(*count);
+}
index c737606423efe2c6c31c8e54cdc227667cdd7516..ac7caaa3b52d1e3be668e96971efda0595aeb9bc 100644 (file)
@@ -47,6 +47,8 @@ GType alsaseq_event_cntr_get_type() G_GNUC_CONST;
 
 ALSASeqEventCntr *alsaseq_event_cntr_new(guint count, GError **error);
 
+void alsaseq_event_cntr_count_events(ALSASeqEventCntr *self, gsize *count);
+
 G_END_DECLS
 
 #endif
index 96231900319008f5184869068a4ea5bdead81ae2..8727bf53365711986c9769490580ed123ab339a3 100644 (file)
@@ -13,6 +13,7 @@ target = ALSASeq.EventCntr()
 props = ()
 methods = (
     'new',
+    'count_events',
 )
 signals = ()