* sending a sequencer event to a delayed queue @ 2012-03-10 18:20 Henning Thielemann 2012-03-10 20:51 ` Clemens Ladisch 0 siblings, 1 reply; 13+ messages in thread From: Henning Thielemann @ 2012-03-10 18:20 UTC (permalink / raw) To: alsa-devel Unfortunately the ALSA doc does not say, what happens if I send an event to a queue that is not running. I expected that the event is being delivered once the queue is started. But it seems that instead the event is dropped. What is the reason for that behaviour? What I want to do is the following: I have a program that computes a sequence of events in real-time. Since computation of an event requires varying amount of time, I want to add a latency in order to get a correctly timed output. To this end I set up two queues: One queue triggers computation of events via Echo messages and the other queue delivers the computed events. I want to use the same time stamps for both queues and just start the queues with a delay between them. Why is it not possible to use one queue and add latency manually to the timestamps? Because the user of the program shall be able to halt the computation. Thus the computation must be halted first and the delivery of events must be halted later. I cannot achieve this with one queue and a queue_stop command. Now the problem is: When my program starts it computes the first event and sends it to the second (delayed) queue. But since this queue is started only after a delay, it is not yet running and thus my event is not delayed, but lost. :-( How to solve that problem? Is there a proposed way to manage latency in ALSA sequencing? Regards, Henning ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-10 18:20 sending a sequencer event to a delayed queue Henning Thielemann @ 2012-03-10 20:51 ` Clemens Ladisch 2012-03-11 15:41 ` Henning Thielemann 0 siblings, 1 reply; 13+ messages in thread From: Clemens Ladisch @ 2012-03-10 20:51 UTC (permalink / raw) To: Henning Thielemann; +Cc: alsa-devel Henning Thielemann wrote: > Unfortunately the ALSA doc does not say, what happens if I send an event > to a queue that is not running. Exactly the same as with a running queue: the event stays in the client's output buffer if its scheduled time has not yet been reached. > I expected that the event is being delivered once the queue is started. > But it seems that instead the event is dropped. Perhaps it was delivered too early? Regards, Clemens ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-10 20:51 ` Clemens Ladisch @ 2012-03-11 15:41 ` Henning Thielemann 2012-03-11 20:40 ` Clemens Ladisch 0 siblings, 1 reply; 13+ messages in thread From: Henning Thielemann @ 2012-03-11 15:41 UTC (permalink / raw) To: alsa-devel; +Cc: Clemens Ladisch [-- Attachment #1: Type: text/plain, Size: 1008 bytes --] Clemens Ladisch schrieb: > Henning Thielemann wrote: >> Unfortunately the ALSA doc does not say, what happens if I send an event >> to a queue that is not running. > > Exactly the same as with a running queue: the event stays in the client's > output buffer if its scheduled time has not yet been reached. > >> I expected that the event is being delivered once the queue is started. >> But it seems that instead the event is dropped. > > Perhaps it was delivered too early? I have attached a C program that demonstrates the effect: I start the "player" queue with one second delay and immediately send a message with a timestamp 0 that is meant to be the local time of the "player" queue. I expected that this event is delivered when the player queue starts, that is, one second after program start. But actually it is played immediately. If I choose a time larger than 0, say 1ns or 1s, then the event is not delivered at all. I use output_direct, but the effect is the same if I use output and drain. [-- Attachment #2: send-note-delayed.c --] [-- Type: text/x-c++src, Size: 2168 bytes --] #include <alsa/asoundlib.h> #include <time.h> void connect (snd_seq_t *seq, int port, const char* dest_name) { snd_seq_addr_t addr; snd_seq_parse_address(seq, &addr, dest_name); snd_seq_connect_to(seq, port, addr.client, addr.port); printf("connect to %s: %d:%d\n", dest_name, addr.client, addr.port); } int main () { snd_seq_t *seq; snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, 0); int port = snd_seq_create_simple_port(seq, "out", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC); connect (seq, port, "aseqdump"); connect (seq, port, "TiMidity"); int control = snd_seq_alloc_queue(seq); int player = snd_seq_alloc_queue(seq); /* start controller queue */ snd_seq_control_queue(seq, control, SND_SEQ_EVENT_START, 0, NULL); snd_seq_drain_output(seq); /* start player queue after one second using controller queue for timing */ const int absolute = 0; snd_seq_real_time_t rtime; rtime.tv_sec = 1; rtime.tv_nsec = 0; snd_seq_ev_schedule_real(&ev, control, absolute, &rtime); snd_seq_control_queue(seq, player, SND_SEQ_EVENT_START, 0, &ev); snd_seq_drain_output(seq); snd_seq_ev_set_source(&ev, port); snd_seq_ev_set_subs(&ev); /* send note-on to player queue with local time 0 */ /* this is played too early, if you increase the time, then the note is not played at all. */ rtime.tv_sec = 0; rtime.tv_nsec = 0; snd_seq_ev_schedule_real(&ev, player, absolute, &rtime); snd_seq_ev_set_noteon(&ev, 0, 60, 64); snd_seq_event_output_direct(seq, &ev); /* send note-off to player queue with local time 1 */ /* this event is dropped */ rtime.tv_sec = 1; rtime.tv_nsec = 0; snd_seq_ev_schedule_real(&ev, player, absolute, &rtime); snd_seq_ev_set_noteoff(&ev, 0, 60, 64); snd_seq_event_output_direct(seq, &ev); snd_seq_sync_output_queue(seq); /* make sure that we do not destroy pending messages */ sleep(3); snd_seq_free_queue(seq, control); snd_seq_free_queue(seq, player); snd_seq_delete_simple_port(seq, port); snd_seq_close(seq); return 0; } [-- Attachment #3: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-11 15:41 ` Henning Thielemann @ 2012-03-11 20:40 ` Clemens Ladisch 2012-03-11 21:08 ` Henning Thielemann ` (2 more replies) 0 siblings, 3 replies; 13+ messages in thread From: Clemens Ladisch @ 2012-03-11 20:40 UTC (permalink / raw) To: Henning Thielemann; +Cc: alsa-devel Henning Thielemann wrote: > Clemens Ladisch schrieb: >> Henning Thielemann wrote: >>> Unfortunately the ALSA doc does not say, what happens if I send an event >>> to a queue that is not running. >> >> Exactly the same as with a running queue: the event stays in the client's >> output buffer if its scheduled time has not yet been reached. > > I have attached a C program that demonstrates the effect: I start the > "player" queue with one second delay and immediately send a message with > a timestamp 0 that is meant to be the local time of the "player" queue. > I expected that this event is delivered when the player queue starts, > that is, one second after program start. But actually it is played > immediately. Yes; whether an event is delivered depends only on its scheduled time, not whether the queue is running. > If I choose a time larger than 0, say 1ns or 1s, then the > event is not delivered at all. Starting a queue also clears it. (This is done explicitly in the code, so I guess this is a feature.) I'd suggest to use one queue for both kinds of events, and to add the delay to the scheduled time. To remove certain events, use snd_seq_remove_events(). Regards, Clemens ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-11 20:40 ` Clemens Ladisch @ 2012-03-11 21:08 ` Henning Thielemann 2012-03-11 22:14 ` Henning Thielemann 2012-03-12 8:21 ` Clemens Ladisch 2012-03-13 22:33 ` Henning Thielemann 2012-03-14 17:37 ` Henning Thielemann 2 siblings, 2 replies; 13+ messages in thread From: Henning Thielemann @ 2012-03-11 21:08 UTC (permalink / raw) To: Clemens Ladisch; +Cc: alsa-devel On Sun, 11 Mar 2012, Clemens Ladisch wrote: > Yes; whether an event is delivered depends only on its scheduled time, > not whether the queue is running. That is, if the queue time is zero and the event time is zero, then the event is sent, independent of whether the queue is running or not. Right? This is good to know and good to be documented. Is this documented somewhere and if not how could I document it myself? I remember there is an ALSA wiki ... >> If I choose a time larger than 0, say 1ns or 1s, then the >> event is not delivered at all. > > Starting a queue also clears it. (This is done explicitly in the code, > so I guess this is a feature.) Should be certainly documented somehow. So maybe, 'CONTINUE' is the solution. > I'd suggest to use one queue for both kinds of events, and to add the > delay to the scheduled time. To remove certain events, use > snd_seq_remove_events(). I'll think about that. Since we are at documentation. seq.h states: #define SND_SEQ_PORT_CAP_SYNC_READ (1<<2) /**< allow read subscriptions */ #define SND_SEQ_PORT_CAP_SYNC_WRITE (1<<3) /**< allow write subscriptions */ ... #define SND_SEQ_PORT_CAP_SUBS_READ (1<<5) /**< allow read subscription */ #define SND_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /**< allow write subscription */ So are the comments for SYNC_READ and SYNC_WRITE correct? ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-11 21:08 ` Henning Thielemann @ 2012-03-11 22:14 ` Henning Thielemann 2012-03-12 8:21 ` Clemens Ladisch 1 sibling, 0 replies; 13+ messages in thread From: Henning Thielemann @ 2012-03-11 22:14 UTC (permalink / raw) To: alsa-devel; +Cc: Clemens Ladisch On Sun, 11 Mar 2012, Henning Thielemann wrote: > Should be certainly documented somehow. So maybe, 'CONTINUE' is the solution. Yes, CONTINUE works as I want, great! ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-11 21:08 ` Henning Thielemann 2012-03-11 22:14 ` Henning Thielemann @ 2012-03-12 8:21 ` Clemens Ladisch 2012-03-14 20:01 ` Henning Thielemann 1 sibling, 1 reply; 13+ messages in thread From: Clemens Ladisch @ 2012-03-12 8:21 UTC (permalink / raw) To: Henning Thielemann; +Cc: alsa-devel Henning Thielemann wrote: > On Sun, 11 Mar 2012, Clemens Ladisch wrote: >> Yes; whether an event is delivered depends only on its scheduled time, >> not whether the queue is running. > > That is, if the queue time is zero and the event time is zero, then > the event is sent, independent of whether the queue is running or not. Yes. > Since we are at documentation. seq.h states: > > #define SND_SEQ_PORT_CAP_SYNC_READ (1<<2) /**< allow read subscriptions */ > #define SND_SEQ_PORT_CAP_SYNC_WRITE (1<<3) /**< allow write subscriptions */ > ... > #define SND_SEQ_PORT_CAP_SUBS_READ (1<<5) /**< allow read subscription */ > #define SND_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /**< allow write subscription */ > > So are the comments for SYNC_READ and SYNC_WRITE correct? No, they should say "obsolete; no effect". Regards, Clemens ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-12 8:21 ` Clemens Ladisch @ 2012-03-14 20:01 ` Henning Thielemann 2012-03-14 20:22 ` Henning Thielemann 0 siblings, 1 reply; 13+ messages in thread From: Henning Thielemann @ 2012-03-14 20:01 UTC (permalink / raw) To: Clemens Ladisch; +Cc: alsa-devel On Mon, 12 Mar 2012, Clemens Ladisch wrote: > Henning Thielemann wrote: >> On Sun, 11 Mar 2012, Clemens Ladisch wrote: >>> Yes; whether an event is delivered depends only on its scheduled time, >>> not whether the queue is running. >> >> That is, if the queue time is zero and the event time is zero, then >> the event is sent, independent of whether the queue is running or not. > > Yes. Ok, I had an idea of how to solve my problem. I want to halt the queue and send all messages immediately that are still in the queue. To this end I think I could just increase the queue time. Thus I did a test whether this will work. I did the following: output note-on event with timestamp 1s output note-off event with timestamp 2s control_queue SND_SEQ_EVENT_SETPOS_TIME 3s drain Nothing happens. I continue the queue after increasing the time: output note-on event with timestamp 1s output note-off event with timestamp 2s control_queue SND_SEQ_EVENT_SETPOS_TIME 3s control_queue SND_SEQ_EVENT_CONTINUE drain Now the note events are scheduled at 1s and 2s as if the SETPOS_TIME control was ignored. Then I continued the queue before increasing the time: output note-on event with timestamp 1s output note-off event with timestamp 2s control_queue SND_SEQ_EVENT_CONTINUE control_queue SND_SEQ_EVENT_SETPOS_TIME 3s drain Now the events arrive instantly. This is the behavior I want to have. It looks like SETPOS_TIME is ignored if the queue is halted. Is this correct? ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-14 20:01 ` Henning Thielemann @ 2012-03-14 20:22 ` Henning Thielemann 2012-03-14 21:36 ` Clemens Ladisch 0 siblings, 1 reply; 13+ messages in thread From: Henning Thielemann @ 2012-03-14 20:22 UTC (permalink / raw) To: alsa-devel; +Cc: Clemens Ladisch I get interesting result if I print the queue time using snd_seq_queue_status_get_real_time. On Wed, 14 Mar 2012, Henning Thielemann wrote: > Ok, I had an idea of how to solve my problem. I want to halt the queue and > send all messages immediately that are still in the queue. To this end I > think I could just increase the queue time. > > Thus I did a test whether this will work. I did the following: > > output note-on event with timestamp 1s > output note-off event with timestamp 2s > control_queue SND_SEQ_EVENT_SETPOS_TIME 3s > drain > > Nothing happens. Queue time is exactly 3s after drain. > I continue the queue after increasing the time: > > output note-on event with timestamp 1s > output note-off event with timestamp 2s > control_queue SND_SEQ_EVENT_SETPOS_TIME 3s > control_queue SND_SEQ_EVENT_CONTINUE > drain > > Now the note events are scheduled at 1s and 2s as if the SETPOS_TIME control > was ignored. Queue time is some microseconds larger than 0. That is, SETPOS_TIME seems to successfully alter the time, but then CONTINUE seems to reset the time. Is this a bug or a feature? SETPOS_TIME does not emit events that become older than queue time. Is it a bug or a feature? ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-14 20:22 ` Henning Thielemann @ 2012-03-14 21:36 ` Clemens Ladisch 0 siblings, 0 replies; 13+ messages in thread From: Clemens Ladisch @ 2012-03-14 21:36 UTC (permalink / raw) To: Henning Thielemann; +Cc: alsa-devel Henning Thielemann wrote: > On Wed, 14 Mar 2012, Henning Thielemann wrote: >> output note-on event with timestamp 1s >> output note-off event with timestamp 2s >> control_queue SND_SEQ_EVENT_SETPOS_TIME 3s >> drain >> >> Nothing happens. To get events to be dispatched, you need a timer tick, i.e., you have to make the timer run again. >> I continue the queue after increasing the time: >> >> output note-on event with timestamp 1s >> output note-off event with timestamp 2s >> control_queue SND_SEQ_EVENT_SETPOS_TIME 3s >> control_queue SND_SEQ_EVENT_CONTINUE >> drain >> >> Now the note events are scheduled at 1s and 2s as if the SETPOS_TIME control was ignored. > > Queue time is some microseconds larger than 0. > > > That is, SETPOS_TIME seems to successfully alter the time, but then CONTINUE seems to reset the time. Is this a bug or a feature? CONTINUE behaves like START if the timer hasn't run yet. Regards, Clemens ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-11 20:40 ` Clemens Ladisch 2012-03-11 21:08 ` Henning Thielemann @ 2012-03-13 22:33 ` Henning Thielemann 2012-03-14 8:22 ` Clemens Ladisch 2012-03-14 17:37 ` Henning Thielemann 2 siblings, 1 reply; 13+ messages in thread From: Henning Thielemann @ 2012-03-13 22:33 UTC (permalink / raw) To: Clemens Ladisch; +Cc: alsa-devel On Sun, 11 Mar 2012, Clemens Ladisch wrote: > I'd suggest to use one queue for both kinds of events, and to add the > delay to the scheduled time. To remove certain events, use > snd_seq_remove_events(). In order to understand how snd_seq_remove_events works, I looked into its source code ... I wondered why I can set the queue as condition with snd_seq_remove_events_set_queue but there is no flag that enables queue matching and actually the queue is not checked in remove_match, as far as I can see. I have another question: Is snd_seq_remove_events atomic, that is, if some events have the same time stamp, is it guaranteed that they are removed all or none at all? Are events still delivered while removing? Or is there a possibility to check what I actually removed? I also thought about using snd_seq_extract_output, but I am concerned about removing events while events are delivered. Regards, Henning ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-13 22:33 ` Henning Thielemann @ 2012-03-14 8:22 ` Clemens Ladisch 0 siblings, 0 replies; 13+ messages in thread From: Clemens Ladisch @ 2012-03-14 8:22 UTC (permalink / raw) To: Henning Thielemann; +Cc: alsa-devel Henning Thielemann wrote: > In order to understand how snd_seq_remove_events works, I looked into > its source code ... I wondered why I can set the queue as condition > with snd_seq_remove_events_set_queue but there is no flag that enables > queue matching SND_SEQ_REMOVE_DEST enables queue/client/port matching. > and actually the queue is not checked in remove_match, as far as I can > see. Well, it's checked in the kernel. :) I guess this is a bug in alsa-lib. > I have another question: Is snd_seq_remove_events atomic, that is, if > some events have the same time stamp, is it guaranteed that they are > removed all or none at all? Are events still delivered while removing? Queues are locked one at a time; events in the same queue with the same timestamping mode should be removed atomically. Regards, Clemens ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: sending a sequencer event to a delayed queue 2012-03-11 20:40 ` Clemens Ladisch 2012-03-11 21:08 ` Henning Thielemann 2012-03-13 22:33 ` Henning Thielemann @ 2012-03-14 17:37 ` Henning Thielemann 2 siblings, 0 replies; 13+ messages in thread From: Henning Thielemann @ 2012-03-14 17:37 UTC (permalink / raw) To: Clemens Ladisch; +Cc: alsa-devel On Sun, 11 Mar 2012, Clemens Ladisch wrote: > I'd suggest to use one queue for both kinds of events, and to add the > delay to the scheduled time. To remove certain events, use > snd_seq_remove_events(). Hm, I am thinking about how to make use of snd_seq_remove_events in my application. It's sad that I cannot find out what events I have actually removed. It would be bad if e.g. a NoteOff gets lost and thus a tone is played forever. It would be great if I could find out pending events in the queue (in the kernel space). Then I could fetch them and re-send them immediately, when the user stops my sequencer. Unfortunately snd_seq_extract_output only fetches events from the user buffer. Is there a snd_seq_extract_output for drained messages? Regards, Henning ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2012-03-14 21:37 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-03-10 18:20 sending a sequencer event to a delayed queue Henning Thielemann 2012-03-10 20:51 ` Clemens Ladisch 2012-03-11 15:41 ` Henning Thielemann 2012-03-11 20:40 ` Clemens Ladisch 2012-03-11 21:08 ` Henning Thielemann 2012-03-11 22:14 ` Henning Thielemann 2012-03-12 8:21 ` Clemens Ladisch 2012-03-14 20:01 ` Henning Thielemann 2012-03-14 20:22 ` Henning Thielemann 2012-03-14 21:36 ` Clemens Ladisch 2012-03-13 22:33 ` Henning Thielemann 2012-03-14 8:22 ` Clemens Ladisch 2012-03-14 17:37 ` Henning Thielemann
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.