From 3a64ed723a5eb4503732ed8feab0f9ba50988bff Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Wed, 4 Oct 2017 22:31:23 +0200 Subject: [PATCH] alsamidisrc: Expand snd_seq_create_simple_port() and use a queue for timestamps Events are timestamped with a real-time value representing the time passed since the queue timer was started. The timestamp is not used just yet. https://bugzilla.gnome.org/show_bug.cgi?id=787683 --- ext/alsa/gstalsamidisrc.c | 70 ++++++++++++++++++++++++++++++++++++--- ext/alsa/gstalsamidisrc.h | 1 + 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/ext/alsa/gstalsamidisrc.c b/ext/alsa/gstalsamidisrc.c index 0461b94dc0..9378e0a10f 100644 --- a/ext/alsa/gstalsamidisrc.c +++ b/ext/alsa/gstalsamidisrc.c @@ -163,17 +163,77 @@ out_free_ports_list: } static int -create_port (GstAlsaMidiSrc * alsamidisrc) +start_queue_timer (GstAlsaMidiSrc * alsamidisrc) { int ret; - ret = snd_seq_create_simple_port (alsamidisrc->seq, DEFAULT_CLIENT_NAME, - SND_SEQ_PORT_CAP_WRITE | - SND_SEQ_PORT_CAP_SUBS_WRITE, - SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); + ret = snd_seq_start_queue (alsamidisrc->seq, alsamidisrc->queue, NULL); + if (ret < 0) { + GST_ERROR_OBJECT (alsamidisrc, "Timer event output error: %s\n", + snd_strerror (ret)); + return ret; + } + + ret = snd_seq_drain_output (alsamidisrc->seq); if (ret < 0) + GST_ERROR_OBJECT (alsamidisrc, "Drain output error: %s\n", + snd_strerror (ret)); + + return ret; +} + +static int +create_port (GstAlsaMidiSrc * alsamidisrc) +{ + snd_seq_port_info_t *pinfo; + int ret; + + snd_seq_port_info_alloca (&pinfo); + snd_seq_port_info_set_name (pinfo, DEFAULT_CLIENT_NAME); + snd_seq_port_info_set_type (pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); + snd_seq_port_info_set_capability (pinfo, + SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE); + + ret = snd_seq_alloc_named_queue (alsamidisrc->seq, DEFAULT_CLIENT_NAME); + if (ret < 0) { + GST_ERROR_OBJECT (alsamidisrc, "Cannot allocate queue: %s\n", + snd_strerror (ret)); + return ret; + } + + /* + * Sequencer queues are "per-system" entities, so it's important to remember + * the queue id to make sure alsamidisrc refers to this very one in future + * operations, and not to some other port created by another sequencer user. + */ + alsamidisrc->queue = ret; + + snd_seq_port_info_set_timestamping (pinfo, 1); + snd_seq_port_info_set_timestamp_real (pinfo, 1); + snd_seq_port_info_set_timestamp_queue (pinfo, alsamidisrc->queue); + + ret = snd_seq_create_port (alsamidisrc->seq, pinfo); + if (ret < 0) { GST_ERROR_OBJECT (alsamidisrc, "Cannot create port - %s", snd_strerror (ret)); + return ret; + } + + /* + * Conversely, it's not strictly necessary to remember the port id because + * ports are per-client and alsamidisrc is only creating one port (id = 0). + * + * If multiple ports were to be created, the ids could be retrieved with + * something like: + * + * alsamidisrc->port = snd_seq_port_info_get_port(pinfo); + */ + + ret = start_queue_timer (alsamidisrc); + if (ret < 0) + GST_ERROR_OBJECT (alsamidisrc, "Cannot start timer for queue: %d - %s", + alsamidisrc->queue, snd_strerror (ret)); return ret; } diff --git a/ext/alsa/gstalsamidisrc.h b/ext/alsa/gstalsamidisrc.h index d30a0c5781..eb026ea79a 100644 --- a/ext/alsa/gstalsamidisrc.h +++ b/ext/alsa/gstalsamidisrc.h @@ -55,6 +55,7 @@ struct _GstAlsaMidiSrc /*< private > */ snd_seq_t *seq; + int queue; int port_count; snd_seq_addr_t *seq_ports; snd_midi_event_t *parser;