OSDN Git Service

Sequencer queue remove events
authorJaroslav Kysela <perex@perex.cz>
Thu, 19 Aug 1999 16:35:48 +0000 (16:35 +0000)
committerJaroslav Kysela <perex@perex.cz>
Thu, 19 Aug 1999 16:35:48 +0000 (16:35 +0000)
include/seq.h
src/seq/seq.c

index ad36428..9a7ca2b 100644 (file)
@@ -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);
index 584b729..f8f7759 100644 (file)
@@ -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;
 }
 
+