// SPDX-License-Identifier: LGPL-3.0-or-later
#include "user-client.h"
#include "query.h"
+#include "event-fixed.h"
+#include "event-variable.h"
#include "privates.h"
#include <sys/types.h>
gpointer tag;
void *buf;
size_t buf_len;
+ ALSASeqEventFixed *ev_fixed;
+ ALSASeqEventVariable *ev_var;
} UserClientSource;
enum seq_user_client_prop_type {
ALSASeqUserClientPrivate *priv;
GIOCondition condition;
int len;
+ guint8 *buf;
+ struct snd_seq_event *event;
priv = alsaseq_user_client_get_instance_private(self);
if (priv->fd < 0)
return G_SOURCE_REMOVE;
}
- // TODO: dispatch event.
+ buf = src->buf;
+ while (len >= sizeof(*event)) {
+ struct snd_seq_event *data_ptr;
+ ALSASeqEvent *ev;
+
+ event = (struct snd_seq_event *)buf;
+
+ buf += sizeof(*event);
+ len -= sizeof(*event);
+
+ // For variable length of event.
+ switch (event->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) {
+ case SNDRV_SEQ_EVENT_LENGTH_FIXED:
+ ev = ALSASEQ_EVENT(src->ev_fixed);
+ break;
+ case SNDRV_SEQ_EVENT_LENGTH_VARIABLE:
+ {
+ unsigned int length = event->data.ext.len;
+ unsigned int offset = (length + sizeof(*event) - 1) / sizeof(*event);
+
+ // MEMO: Although ALSA Sequencer core never truncate the event,
+ // let's skip it for safe.
+ if (length == 0 || len < offset)
+ break;
+
+ event->data.ext.ptr = buf;
+ buf += offset;
+ len -= offset;
+
+ ev = ALSASEQ_EVENT(src->ev_var);
+ break;
+ }
+ case SNDRV_SEQ_EVENT_LENGTH_VARUSR:
+ // Unsupported since it handles raw pointer which is difficult to
+ // be exposed by interfaces capable for g-i.
+ default:
+ continue;
+ }
+
+ // Copy event cell (= 28 bytes).
+ seq_event_refer_private(ev, &data_ptr);
+ *data_ptr = *event;
+
+ g_signal_emit(self,
+ seq_user_client_sigs[SEQ_USER_CLIENT_SIG_TYPE_HANDLE_EVENT],
+ 0, ev);
+ }
// Just be sure to continue to process this source.
return G_SOURCE_CONTINUE;
{
UserClientSource *src = (UserClientSource *)gsrc;
+ g_object_unref(src->ev_fixed);
+ g_object_unref(src->ev_var);
+
g_free(src->buf);
g_object_unref(src->self);
}
*gsrc = g_source_new(&funcs, sizeof(*src));
src = (UserClientSource *)(*gsrc);
+ src->ev_fixed = g_object_new(ALSASEQ_TYPE_EVENT_FIXED, NULL);
+ src->ev_var = g_object_new(ALSASEQ_TYPE_EVENT_VARIABLE, NULL);
+
g_source_set_name(*gsrc, "ALSASeqUserClient");
g_source_set_priority(*gsrc, G_PRIORITY_HIGH_IDLE);
g_source_set_can_recurse(*gsrc, TRUE);