OSDN Git Service

Initial version...
authorJaroslav Kysela <perex@perex.cz>
Sun, 27 Dec 1998 00:59:08 +0000 (00:59 +0000)
committerJaroslav Kysela <perex@perex.cz>
Sun, 27 Dec 1998 00:59:08 +0000 (00:59 +0000)
include/seq.h [new file with mode: 0644]
src/seq/Makefile.am [new file with mode: 0644]
src/seq/seq.c [new file with mode: 0644]

diff --git a/include/seq.h b/include/seq.h
new file mode 100644 (file)
index 0000000..ccd50bb
--- /dev/null
@@ -0,0 +1,55 @@
+/****************************************************************************
+ *                                                                          *
+ *                                seq.h                                     *
+ *                              Sequencer                                   *
+ *                                                                          *
+ ****************************************************************************/
+
+#define SND_SEQ_OPEN_OUT       (O_WRONLY)
+#define SND_SEQ_OPEN_IN                (O_RDONLY)
+#define SND_SEQ_OPEN           (O_RDWR)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int snd_seq_open(void **handle, int mode);
+int snd_seq_close(void *handle);
+int snd_seq_file_descriptor(void *handle);
+int snd_seq_block_mode(void *handle, int enable);
+int snd_seq_client_id(void *handle);
+int snd_seq_system_info(void *handle, snd_seq_system_info_t *info);
+int snd_seq_get_client_info(void *handle, snd_seq_client_info_t *info);
+int snd_seq_get_any_client_info(void *handle, int client, snd_seq_client_info_t *info);
+int snd_seq_set_client_info(void *handle, snd_seq_client_info_t *info);
+int snd_seq_create_port(void *handle, snd_seq_port_info_t *info);
+int snd_seq_delete_port(void *handle, snd_seq_port_info_t *info);
+int snd_seq_get_port_info(void *handle, int port, snd_seq_port_info_t *info);
+int snd_seq_get_any_port_info(void *handle, int client, int port, snd_seq_port_info_t *info);
+int snd_seq_set_port_info(void *handle, int port, snd_seq_port_info_t *info);
+int snd_seq_subscribe_port(void *handle, snd_seq_port_subscribe_t *sub);
+int snd_seq_unsubscribe_port(void *handle, snd_seq_port_subscribe_t *sub);
+int snd_seq_get_queue_info(void *handle, int q, snd_seq_queue_info_t *queue);
+int snd_seq_set_queue_info(void *handle, int q, snd_seq_queue_info_t *queue);
+int snd_seq_get_queue_client(void *handle, int q, snd_seq_queue_client_t *queue);
+int snd_seq_set_queue_client(void *handle, int q, snd_seq_queue_client_t *queue);
+int snd_seq_alloc_queue(void *handle, snd_seq_queue_info_t *queue);
+int snd_seq_free_queue(void *handle, int q);
+/* event routines */
+snd_seq_event_t *snd_seq_create_event(void);
+int snd_seq_free_event(snd_seq_event_t *ev);
+int snd_seq_event_length(snd_seq_event_t *ev);
+int snd_seq_event_output(void *handle, snd_seq_event_t *ev);
+int snd_seq_event_input(void *handle, snd_seq_event_t **ev);
+int snd_seq_flush_output(void *handle);
+int snd_seq_drain_output(void *handle);
+int snd_seq_drain_input(void *handle);
+/* misc */
+void snd_seq_set_bit(int nr, void *array);
+int snd_seq_change_bit(int nr, void *array);
+int snd_seq_get_bit(int nr, void *array);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/seq/Makefile.am b/src/seq/Makefile.am
new file mode 100644 (file)
index 0000000..778893d
--- /dev/null
@@ -0,0 +1,7 @@
+EXTRA_LTLIBRARIES=libseq.la
+
+libseq_la_SOURCES = seq.c
+all: libseq.la
+
+
+INCLUDES=-I$(top_srcdir)/include
diff --git a/src/seq/seq.c b/src/seq/seq.c
new file mode 100644 (file)
index 0000000..d3e3c1b
--- /dev/null
@@ -0,0 +1,670 @@
+/*
+ *  Sequencer Interface - main file
+ *  Copyright (c) 1998 by Jaroslav Kysela <perex@jcu.cz>
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Library General Public License as
+ *   published by the Free Software Foundation; either version 2 of
+ *   the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Library General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Library General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "asoundlib.h"
+
+#define SND_FILE_SEQ           "/dev/snd/seq"
+#define SND_SEQ_VERSION_MAX    SND_PROTOCOL_VERSION( 0, 0, 1 )
+#define SND_SEQ_OBUF_SIZE      (16*1024)       /* should be configurable */
+#define SND_SEQ_IBUF_SIZE      (4*1024)        /* should be configurable */
+
+typedef struct snd_stru_seq_cell {
+       snd_seq_event_t ev;
+       struct snd_stru_seq_cell *next;
+} snd_seq_cell_t;
+
+typedef struct {
+       int client;             /* client number */
+       int fd;
+       /* buffers */
+       char *obuf;             /* output buffer */
+       int obufsize;           /* output buffer size */
+       int obufused;           /* output buffer used size */
+       char *ibuf;             /* input buffer */
+       int ibufsize;           /* input buffer size */
+       /* input queue */
+       int cells;
+       snd_seq_cell_t *head;
+       snd_seq_cell_t *tail;
+} snd_seq_t;
+
+int snd_seq_open(void **handle, int mode)
+{
+       int fd, ver, client, flg;
+       char filename[32];
+       snd_seq_t *seq;
+
+       *handle = NULL;
+       sprintf(filename, SND_FILE_SEQ);
+       if ((fd = open(filename, mode)) < 0)
+               return -errno;
+       if (ioctl(fd, SND_SEQ_IOCTL_PVERSION, &ver) < 0) {
+               close(fd);
+               return -errno;
+       }
+       if (SND_PROTOCOL_UNCOMPATIBLE(ver, SND_SEQ_VERSION_MAX)) {
+               close(fd);
+               return -SND_ERROR_UNCOMPATIBLE_VERSION;
+       }
+       if (ioctl(fd, SND_SEQ_IOCTL_CLIENT_ID, &client) < 0) {
+               close(fd);
+               return -errno;
+       }
+       seq = (snd_seq_t *) calloc(1, sizeof(snd_seq_t));
+       if (seq == NULL) {
+               close(fd);
+               return -ENOMEM;
+       }
+       seq->client = client;
+       seq->fd = fd;
+       flg = 3;
+       if (mode == SND_SEQ_OPEN_OUT || mode == SND_SEQ_OPEN)
+               seq->obuf = (char *) malloc(seq->obufsize = SND_SEQ_OBUF_SIZE);
+       else
+               flg &= ~1;
+       if (mode == SND_SEQ_OPEN_IN || mode == SND_SEQ_OPEN)
+               seq->ibuf = (char *) malloc(seq->ibufsize = SND_SEQ_IBUF_SIZE);
+       else
+               flg &= ~2;
+       if ((!seq->obuf && (flg & 1)) || (!seq->ibuf && (flg & 2))) {
+               if (seq->obuf)
+                       free(seq->obuf);
+               if (seq->ibuf)
+                       free(seq->ibuf);
+               free(seq);
+               return -ENOMEM;
+       }
+       *handle = seq;
+       return 0;
+}
+
+int snd_seq_close(void *handle)
+{
+       snd_seq_t *seq;
+       int res;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq)
+               return -EINVAL;
+       res = close(seq->fd) < 0 ? -errno : 0;
+       free(seq);
+       return res;
+}
+
+int snd_seq_file_descriptor(void *handle)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq)
+               return -EINVAL;
+       return seq->fd;
+}
+
+int snd_seq_block_mode(void *handle, int enable)
+{
+       snd_seq_t *seq;
+       long flags;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq)
+               return -EINVAL;
+       if (fcntl(seq->fd, F_GETFL, &flags) < 0)
+               return -errno;
+       if (enable)
+               flags |= O_NONBLOCK;
+       else
+               flags &= ~O_NONBLOCK;
+       if (fcntl(seq->fd, F_SETFL, &flags) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_client_id(void *handle)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq)
+               return -EINVAL;
+       return seq->client;
+}
+
+int snd_seq_system_info(void *handle, snd_seq_system_info_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info)
+               return -EINVAL;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_SYSTEM_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_get_client_info(void *handle, snd_seq_client_info_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info)
+               return -EINVAL;
+       return snd_seq_get_any_client_info(handle, seq->client, info);
+}
+
+int snd_seq_get_any_client_info(void *handle, int client, snd_seq_client_info_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info || client < 0)
+               return -EINVAL;
+       bzero(info, sizeof(snd_seq_client_info_t));
+       info->client = client;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_GET_CLIENT_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_set_client_info(void *handle, snd_seq_client_info_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info)
+               return -EINVAL;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_SET_CLIENT_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_create_port(void *handle, snd_seq_port_info_t * port)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !port)
+               return -EINVAL;
+       port->client = seq->client;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_CREATE_PORT, port) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_delete_port(void *handle, snd_seq_port_info_t * port)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !port)
+               return -EINVAL;
+       port->client = seq->client;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_DELETE_PORT, port) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_get_port_info(void *handle, int port, snd_seq_port_info_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info || port < 0)
+               return -EINVAL;
+       return snd_seq_get_any_port_info(handle, seq->client, port, info);
+}
+
+int snd_seq_get_any_port_info(void *handle, int client, int port, snd_seq_port_info_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info || client < 0 || port < 0)
+               return -EINVAL;
+       bzero(info, sizeof(snd_seq_port_info_t));
+       info->client = client;
+       info->port = port;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_GET_PORT_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_set_port_info(void *handle, int port, snd_seq_port_info_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info || port < 0)
+               return -EINVAL;
+       info->port = port;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_SET_PORT_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_subscribe_port(void *handle, snd_seq_port_subscribe_t * sub)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !sub)
+               return -EINVAL;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_SUBSCRIBE_PORT, sub) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_unsubscribe_port(void *handle, snd_seq_port_subscribe_t * sub)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !sub)
+               return -EINVAL;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_UNSUBSCRIBE_PORT, sub) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_get_queue_info(void *handle, int q, snd_seq_queue_info_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info)
+               return -EINVAL;
+       bzero(info, sizeof(snd_seq_queue_info_t));
+       info->queue = q;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_GET_QUEUE_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_set_queue_info(void *handle, int q, snd_seq_queue_info_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info)
+               return -EINVAL;
+       info->queue = q;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_SET_QUEUE_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_get_queue_client(void *handle, int q, snd_seq_queue_client_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info)
+               return -EINVAL;
+       bzero(info, sizeof(snd_seq_queue_client_t));
+       info->queue = q;
+       info->client = seq->client;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_GET_QUEUE_CLIENT, info) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_set_queue_client(void *handle, int q, snd_seq_queue_client_t * info)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !info)
+               return -EINVAL;
+       info->queue = q;
+       info->client = seq->client;
+       if (ioctl(seq->fd, SND_SEQ_IOCTL_SET_QUEUE_CLIENT, info) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_seq_alloc_queue(void *handle, snd_seq_queue_info_t *info)
+{
+       int i, err;
+       snd_seq_system_info_t sysinfo;
+       snd_seq_queue_info_t inf;
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq)
+               return -EINVAL; 
+       if ((err = snd_seq_system_info(handle, &sysinfo))<0)
+               return err;
+       for (i = 0; i < sysinfo.queues; i++) {
+               if ((err = snd_seq_get_queue_info(handle, i, &inf))<0)
+                       continue;
+               if (inf.locked)
+                       continue;
+               inf.locked = 1;
+               inf.owner = seq->client;
+               if ((err = snd_seq_set_queue_info(handle, i, &inf))<0)
+                       continue;
+               if (info)
+                       memcpy(info, &inf, sizeof(snd_seq_queue_info_t));
+               return i;
+       }
+       return -EBUSY;
+}
+
+int snd_seq_free_queue(void *handle, int q)
+{
+       int err;
+       snd_seq_t *seq;
+       snd_seq_queue_info_t inf;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq)
+               return -EINVAL; 
+       if ((err = snd_seq_get_queue_info(handle, q, &inf))<0)
+               return err;
+       if (inf.locked && inf.owner == seq->client) {
+               inf.locked = 0;
+               inf.owner = -1;
+               if ((err = snd_seq_set_queue_info(handle, q, &inf))<0)
+                       return err;
+       }
+       return 0;
+}
+
+snd_seq_event_t *snd_seq_create_event(void)
+{
+       return (snd_seq_event_t *) calloc(1, sizeof(snd_seq_event_t));
+}
+
+static int snd_seq_free_event_static(snd_seq_event_t *ev)
+{
+       if (!ev)
+               return -EINVAL;
+       switch (ev->flags & SND_SEQ_EVENT_LENGTH_MASK) {
+       case SND_SEQ_EVENT_LENGTH_VARIABLE:
+               if (ev->data.ext.ptr)
+                       free(ev->data.ext.ptr);
+               break;
+       }
+       return 0;
+}
+
+int snd_seq_free_event(snd_seq_event_t *ev)
+{
+       int err;
+
+       if ((err = snd_seq_free_event_static(ev))<0)
+               return err;
+       free(ev);
+       return 0;
+}
+
+int snd_seq_event_length(snd_seq_event_t *ev)
+{
+       int len = sizeof(snd_seq_event_t);
+
+       if (!ev)
+               return -EINVAL;
+       switch (ev->flags & SND_SEQ_EVENT_LENGTH_MASK) {
+       case SND_SEQ_EVENT_LENGTH_VARIABLE:
+               len += ev->data.ext.len;
+               break;
+       }
+       return len;
+}
+
+int snd_seq_event_output(void *handle, snd_seq_event_t *ev)
+{
+       int len;
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq || !ev)
+               return -EINVAL;
+       len = snd_seq_event_length(ev);
+       if ((seq->obufsize - seq->obufused) < len) {
+               snd_seq_flush_output(handle);
+               if ((seq->obufsize - seq->obufused) < len)
+                       return -ENOMEM;
+       }
+       memcpy(seq->obuf + seq->obufused, ev, sizeof(snd_seq_event_t));
+       seq->obufused += sizeof(snd_seq_event_t);
+       switch (ev->flags & SND_SEQ_EVENT_LENGTH_MASK) {
+       case SND_SEQ_EVENT_LENGTH_VARIABLE:
+               memcpy(seq->obuf + seq->obufused, ev->data.ext.ptr, ev->data.ext.len);
+               seq->obufused += ev->data.ext.len;
+               break;
+       }
+       return seq->obufused;
+}
+
+static snd_seq_cell_t *snd_seq_create_cell(snd_seq_event_t *ev)
+{
+       snd_seq_cell_t *cell;
+
+       cell = (snd_seq_cell_t *) calloc(1, sizeof(snd_seq_cell_t));
+       if (!cell)
+               return NULL;
+       if (ev)
+               memcpy(&cell->ev, ev, sizeof(snd_seq_event_t));
+       return cell;
+}
+
+static int snd_seq_free_cell(snd_seq_cell_t *cell)
+{
+       if (!cell)
+               return -EINVAL;
+       snd_seq_free_event_static(&cell->ev);
+       free(cell);
+       return 0;
+}
+
+static snd_seq_cell_t *snd_seq_input_cell_out(snd_seq_t *seq)
+{
+       snd_seq_cell_t *cell;
+
+       if (!seq)
+               return NULL;
+       if (seq->head) {
+               cell = seq->head;
+               seq->head = cell->next;
+               seq->cells--;
+               if (!seq->head)
+                       seq->tail = NULL;
+               return cell;
+       }
+       return NULL;
+}
+
+static int snd_seq_input_cell_in(snd_seq_t *seq, snd_seq_cell_t *cell)
+{
+       if (!seq)
+               return -EINVAL;
+       cell->next = NULL;
+       if (!seq->tail) {
+               seq->head = seq->tail = cell;
+       } else {
+               seq->tail->next = cell;
+               seq->tail = cell;
+       }
+       seq->cells++;
+       return 0;
+}
+
+static int snd_seq_input_cell_available(snd_seq_t *seq)
+{
+       if (!seq)
+               return -EINVAL;
+       return seq->cells > 0;
+}
+
+static int snd_seq_decode_event(char **buf, int *len, snd_seq_event_t *ev)
+{
+       if (!ev || !buf || !*buf || !len )
+               return -EINVAL;
+       if (*len < sizeof(snd_seq_event_t)) {
+               *len = 0;
+               return -ENOENT;
+       }
+       memcpy(ev, *buf, sizeof(snd_seq_event_t));
+       *buf += sizeof(snd_seq_event_t);
+       *len -= sizeof(snd_seq_event_t);
+       switch (ev->flags & SND_SEQ_EVENT_LENGTH_MASK) {
+       case SND_SEQ_EVENT_LENGTH_VARIABLE:
+               if (*len < ev->data.ext.len) {
+                       *len = 0;
+                       return -ENOENT;
+               }
+               if (ev->data.ext.len > 0) {
+                       ev->data.ext.ptr = (char *) malloc(ev->data.ext.len);
+                       if (!(ev->data.ext.ptr)) {
+                               *buf += ev->data.ext.len;
+                               *len -= ev->data.ext.len;
+                               return -ENOENT;
+                       }
+                       memcpy(ev->data.ext.ptr, *buf, ev->data.ext.len);
+                       *buf += ev->data.ext.len;
+                       *len -= ev->data.ext.len;
+               }
+               break;
+       }
+       return 0;
+}
+
+/*
+ *  Current implementation uses FIFO cache.
+ */
+
+int snd_seq_event_input(void *handle, snd_seq_event_t **ev)
+{
+       snd_seq_t *seq;
+       snd_seq_cell_t *cell;
+       char *buf;
+       int count;
+
+       *ev = NULL;
+       seq = (snd_seq_t *) handle;
+       if (!seq)
+               return -EINVAL;
+       if (snd_seq_input_cell_available(seq)) {
+               *ev = snd_seq_create_event();
+               if (*ev == NULL)
+                       return -ENOMEM;
+               cell = snd_seq_input_cell_out(seq);
+               memcpy(*ev, &cell->ev, sizeof(snd_seq_event_t));
+               return seq->cells;
+       }
+       count = read(seq->fd, seq->ibuf, seq->ibufsize);
+       if (count < 0)
+               return -errno;
+       buf = seq->ibuf;
+       while (count > 0) {
+               if (*ev == NULL) {      /* first event */
+                       *ev = snd_seq_create_event();
+                       if (*ev == NULL)
+                               return -ENOMEM;
+                       if (snd_seq_decode_event(&buf, &count, *ev)<0) {
+                               snd_seq_free_event(*ev);
+                               *ev = NULL;
+                       }
+               } else {
+                       cell = snd_seq_create_cell(NULL);
+                       if (cell == NULL)
+                               return -ENOMEM;
+                       if (snd_seq_decode_event(&buf, &count, &cell->ev)<0) {
+                               snd_seq_free_cell(cell);
+                       } else {
+                               snd_seq_input_cell_in(seq, cell);
+                       }
+               }
+       }
+       return seq->cells;
+}
+
+int snd_seq_flush_output(void *handle)
+{
+       snd_seq_t *seq;
+       int result;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq)
+               return -EINVAL;
+       if (seq->obufused <= 0)
+               return 0;
+       result = write(seq->fd, seq->obuf, seq->obufused);
+       if (result < 0) {
+               snd_seq_drain_output(handle);
+               return -errno;
+       }
+       if (result < seq->obufused)
+               memmove(seq->obuf, seq->obuf + result, seq->obufused - result);
+       seq->obufused -= result;
+       return seq->obufused;
+}
+
+int snd_seq_drain_output(void *handle)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq)
+               return -EINVAL;
+       seq->obufused = 0;
+       return 0;
+}
+
+int snd_seq_drain_input(void *handle)
+{
+       snd_seq_t *seq;
+
+       seq = (snd_seq_t *) handle;
+       if (!seq)
+               return -EINVAL;
+       while (snd_seq_input_cell_available(seq))
+               snd_seq_free_cell(snd_seq_input_cell_out(seq));
+       return 0;
+}
+
+void snd_seq_set_bit(int nr, void *array)
+{
+       ((unsigned int *)array)[nr >> 5] |= 1UL << (nr & 31);
+}
+
+int snd_seq_change_bit(int nr, void *array)
+{
+       int result;
+
+       result = ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0;
+       ((unsigned int *)array)[nr >> 5] |= 1UL << (nr & 31);
+       return result;
+}
+
+int snd_seq_get_bit(int nr, void *array)
+{
+       return ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0;
+}
+