From: Jaroslav Kysela Date: Thu, 19 Aug 1999 16:35:48 +0000 (+0000) Subject: Sequencer queue remove events X-Git-Tag: v1.0.3~1446 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=3555271122c3da55a6307e23032a5ac8ca574574;p=alsa-lib.git Sequencer queue remove events --- diff --git a/include/seq.h b/include/seq.h index ad36428a..9a7ca2b5 100644 --- a/include/seq.h +++ b/include/seq.h @@ -55,6 +55,7 @@ int snd_seq_event_input(snd_seq_t *handle, snd_seq_event_t **ev); int snd_seq_flush_output(snd_seq_t *handle); int snd_seq_drain_output(snd_seq_t *handle); int snd_seq_drain_input(snd_seq_t *handle); +int snd_seq_remove_events(snd_seq_t *handle, snd_seq_remove_events_t *info); /* misc */ void snd_seq_set_bit(int nr, void *array); int snd_seq_change_bit(int nr, void *array); diff --git a/src/seq/seq.c b/src/seq/seq.c index 584b7298..f8f77592 100644 --- a/src/seq/seq.c +++ b/src/seq/seq.c @@ -630,10 +630,9 @@ int snd_seq_flush_output(snd_seq_t *seq) if (seq->obufused <= 0) return 0; result = write(seq->fd, seq->obuf, seq->obufused); - if (result < 0) { - snd_seq_drain_output(seq); + if (result < 0) return -errno; - } + if (result < seq->obufused) memmove(seq->obuf, seq->obuf + result, seq->obufused - result); seq->obufused -= result; @@ -642,12 +641,140 @@ int snd_seq_flush_output(snd_seq_t *seq) int snd_seq_drain_output(snd_seq_t *seq) { + snd_seq_remove_events_t rminfo; + if (!seq) return -EINVAL; - seq->obufused = 0; + + memset(&rminfo, 0, sizeof(rminfo)); + rminfo.output = 1; + + snd_seq_remove_events(seq, &rminfo); + return 0; +} + +/* compare timestamp between events */ +/* return 1 if a >= b; otherwise return 0 */ +static inline int snd_seq_compare_tick_time(snd_seq_tick_time_t *a, + snd_seq_tick_time_t *b) +{ + /* compare ticks */ + return (*a >= *b); +} + +static inline int snd_seq_compare_real_time(snd_seq_real_time_t *a, + snd_seq_real_time_t *b) +{ + /* compare real time */ + if (a->tv_sec > b->tv_sec) + return 1; + if ((a->tv_sec == b->tv_sec) && (a->tv_nsec >= b->tv_nsec)) + return 1; return 0; } +/* Routine to match events to be removed */ +static int remove_match(snd_seq_remove_events_t *info, + snd_seq_event_t *ev) +{ + int res; + + if (info->remove_mode & SND_SEQ_REMOVE_DEST) { + if (ev->dest.client != info->dest.client || + ev->dest.port != info->dest.port) + return 0; + } + if (info->remove_mode & SND_SEQ_REMOVE_DEST_CHANNEL) { + if (ev->dest.channel != info->dest.channel) + return 0; + } + if (info->remove_mode & SND_SEQ_REMOVE_TIME_AFTER) { + if (info->tick) + res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick); + else + res = snd_seq_compare_real_time(&ev->time.real, &info->time.real); + if (!res) + return 0; + } + if (info->remove_mode & SND_SEQ_REMOVE_TIME_BEFORE) { + if (info->tick) + res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick); + else + res = snd_seq_compare_real_time(&ev->time.real, &info->time.real); + if (res) + return 0; + } + if (info->remove_mode & SND_SEQ_REMOVE_EVENT_TYPE) { + if (ev->type != info->type) + return 0; + } + if (info->remove_mode & SND_SEQ_REMOVE_IGNORE_OFF) { + /* Do not remove off events */ + switch (ev->type) { + case SND_SEQ_EVENT_NOTEOFF: + /* case SND_SEQ_EVENT_SAMPLE_STOP: */ + return 0; + default: + break; + } + } + if (info->remove_mode & SND_SEQ_REMOVE_TAG_MATCH) { + if (info->tag != ev->tag) + return 0; + } + + return 1; +} + +/* + * Remove events from the sequencer queues. + */ +int snd_seq_remove_events(snd_seq_t *seq, snd_seq_remove_events_t *rmp) +{ + if (rmp->input) { + /* + * First deal with any events that are still buffered + * in the library. + */ + /* Input not implemented */ + } + + if (rmp->output) { + /* + * First deal with any events that are still buffered + * in the library. + */ + if (rmp->remove_mode == 0) { + /* The simple case - remove all */ + seq->obufused = 0; + } else { + char *ep; + int len; + snd_seq_event_t *ev; + + ep = seq->obuf; + while (ep - seq->obuf < seq->obufused) { + + ev = (snd_seq_event_t *) ep; + len = snd_seq_event_length(ev); + + if (remove_match(rmp, ev)) { + + /* Remove event */ + memcpy(ep, ep + len, len); + seq->obufused -= len; + } else { + ep += len; + } + } + } + } + + if (ioctl(seq->fd, SND_SEQ_IOCTL_REMOVE_EVENTS, rmp) < 0) + return -errno; + + return 0; +} int snd_seq_drain_input(snd_seq_t *seq) { if (!seq) @@ -696,3 +823,4 @@ int snd_seq_get_bit(int nr, void *array) return ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0; } +