From 18d35c9ab23c55119100c60a2ce71b607d862ec7 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 1 Apr 2020 18:13:28 +0900 Subject: [PATCH] seq: user_client: add an API to create GSource Signed-off-by: Takashi Sakamoto --- src/seq/alsaseq.map | 1 + src/seq/user-client.c | 106 ++++++++++++++++++++++++++++++++++++++ src/seq/user-client.h | 3 ++ tests/alsaseq-user-client | 1 + 4 files changed, 111 insertions(+) diff --git a/src/seq/alsaseq.map b/src/seq/alsaseq.map index 9b0f883..85998bb 100644 --- a/src/seq/alsaseq.map +++ b/src/seq/alsaseq.map @@ -43,6 +43,7 @@ ALSA_GOBJECT_0_0_0 { "alsaseq_user_client_set_pool"; "alsaseq_user_client_get_pool"; "alsaseq_user_client_schedule_event"; + "alsaseq_user_client_create_source"; "alsaseq_addr_get_type"; "alsaseq_addr_new"; diff --git a/src/seq/user-client.c b/src/seq/user-client.c index 3836438..e8c5367 100644 --- a/src/seq/user-client.c +++ b/src/seq/user-client.c @@ -16,6 +16,14 @@ struct _ALSASeqUserClientPrivate { }; G_DEFINE_TYPE_WITH_PRIVATE(ALSASeqUserClient, alsaseq_user_client, G_TYPE_OBJECT) +typedef struct { + GSource src; + ALSASeqUserClient *self; + gpointer tag; + void *buf; + size_t buf_len; +} UserClientSource; + enum seq_user_client_prop_type { SEQ_USER_CLIENT_PROP_CLIENT_ID = 1, SEQ_USER_CLIENT_PROP_COUNT, @@ -371,3 +379,101 @@ void alsaseq_user_client_schedule_event(ALSASeqUserClient *self, if (ptr != NULL) g_free(ptr); } + +static gboolean seq_user_client_check_src(GSource *gsrc) +{ + UserClientSource *src = (UserClientSource *)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 seq_user_client_dispatch_src(GSource *gsrc, GSourceFunc cb, + gpointer user_data) +{ + UserClientSource *src = (UserClientSource *)gsrc; + ALSASeqUserClient *self = src->self; + ALSASeqUserClientPrivate *priv; + GIOCondition condition; + int len; + + priv = alsaseq_user_client_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; + + len = read(priv->fd, src->buf, src->buf_len); + if (len < 0) { + if (errno == EAGAIN) + return G_SOURCE_CONTINUE; + + return G_SOURCE_REMOVE; + } + + // TODO: dispatch event. + + // Just be sure to continue to process this source. + return G_SOURCE_CONTINUE; +} + +static void seq_user_client_finalize_src(GSource *gsrc) +{ + UserClientSource *src = (UserClientSource *)gsrc; + + g_free(src->buf); + g_object_unref(src->self); +} + +/** + * alsaseq_user_client_create_source: + * @self: A #ALSASeqUserClient. + * @gsrc: (out): A #GSource to handle events from ALSA seq character device. + * @error: A #GError. + * + * Allocate GSource structure to handle events from ALSA seq character device. + */ +void alsaseq_user_client_create_source(ALSASeqUserClient *self, + GSource **gsrc, GError **error) +{ + static GSourceFuncs funcs = { + .check = seq_user_client_check_src, + .dispatch = seq_user_client_dispatch_src, + .finalize = seq_user_client_finalize_src, + }; + ALSASeqUserClientPrivate *priv; + UserClientSource *src; + void *buf; + long page_size = sysconf(_SC_PAGESIZE); + + g_return_if_fail(ALSASEQ_IS_USER_CLIENT(self)); + priv = alsaseq_user_client_get_instance_private(self); + + if (priv->fd < 0) { + generate_error(error, ENXIO); + return; + } + + buf = g_try_malloc0(page_size); + if (buf == NULL) { + generate_error(error, ENOMEM); + return; + } + + *gsrc = g_source_new(&funcs, sizeof(*src)); + src = (UserClientSource *)(*gsrc); + + g_source_set_name(*gsrc, "ALSASeqUserClient"); + 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); + src->buf = buf; + src->buf_len = page_size; +} diff --git a/src/seq/user-client.h b/src/seq/user-client.h index 8db8f8d..c3ba524 100644 --- a/src/seq/user-client.h +++ b/src/seq/user-client.h @@ -85,6 +85,9 @@ void alsaseq_user_client_get_pool(ALSASeqUserClient *self, void alsaseq_user_client_schedule_event(ALSASeqUserClient *self, ALSASeqEvent *event, GError **error); +void alsaseq_user_client_create_source(ALSASeqUserClient *self, + GSource **gsrc, GError **error); + G_END_DECLS #endif diff --git a/tests/alsaseq-user-client b/tests/alsaseq-user-client index f2c3b67..fd84fc2 100644 --- a/tests/alsaseq-user-client +++ b/tests/alsaseq-user-client @@ -24,6 +24,7 @@ methods = ( 'set_pool', 'get_pool', 'schedule_event', + 'create_source', ) signals = () -- 2.47.3