]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Takashi Iwai <iwai@ww.uni-erlangen.de>
authorJaroslav Kysela <perex@perex.cz>
Fri, 17 Sep 1999 16:17:21 +0000 (16:17 +0000)
committerJaroslav Kysela <perex@perex.cz>
Fri, 17 Sep 1999 16:17:21 +0000 (16:17 +0000)
Fri, 17 Sep 1999 17:24:43 +0200

OK, the attached is the patch to alsa-driver and alsa-lib.
It will really violate the source/binary compatibility as
I wrote :-p

It includes:
 - change of event data for accessing Timer Port
 - new middle-level functions for sequencer in alsa-lib
 - some comments / fixes

The test programs in alsa-lib (playmidi1, aconnect, aseqnet)
were rewritten to use the new functions above.
I included also a patch to pmidi-1.2.2.

include/Makefile.am
include/seqmid.h [new file with mode: 0644]
src/seq/Makefile.am
src/seq/seq.c
src/seq/seq_priv.h [new file with mode: 0644]
src/seq/seqmid.c [new file with mode: 0644]
test/aconnect.c
test/aseqnet.c
test/playmidi1.c

index 33b57f4e5584f92ff08e2625a5f69cb853f439e6..fdb8036e07e55428a35f5a5b1393863b15a0d742 100644 (file)
@@ -4,7 +4,7 @@ sysinclude_HEADERS = asoundlib.h
 # This is the order they will be concatenated into asoundlib.h!
 #
 header_files=header.h version.h error.h control.h mixer.h pcm.h rawmidi.h \
-             timer.h seq.h conv.h instr.h footer.h
+             timer.h seq.h seqmid.h conv.h instr.h footer.h
 
 noinst_HEADERS=$(header_files)
 
diff --git a/include/seqmid.h b/include/seqmid.h
new file mode 100644 (file)
index 0000000..eb96dce
--- /dev/null
@@ -0,0 +1,192 @@
+/****************************************************************************
+ *                                                                          *
+ *                      Sequencer Middle Level                              *
+ *                                                                          *
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* initialize event record */
+void snd_seq_ev_clear(snd_seq_event_t *ev);
+
+/* set destination - following three macros are exclusive */
+  /* explicit destination */
+void snd_seq_ev_set_dest(snd_seq_event_t *ev, int client, int port);
+  /* to subscribers */
+void snd_seq_ev_set_subs(snd_seq_event_t *ev);
+  /* broadcast to all clients/ports */
+void snd_seq_ev_set_broadcast(snd_seq_event_t *ev);
+
+/* set source port */
+void snd_seq_ev_set_source(snd_seq_event_t *ev, int port);
+
+/* set scheduling - following three macros are exclusive */
+  /* direct event passing without enqueued */
+void snd_seq_ev_set_direct(snd_seq_event_t *ev);
+  /* scheduled on tick-queue */
+void snd_seq_ev_schedule_tick(snd_seq_event_t *ev, int q, int relative,
+                             unsigned long tick);
+  /* scheduled on real-time-queue */
+void snd_seq_ev_schedule_real(snd_seq_event_t *ev, int q, int relative,
+                             snd_seq_real_time_t *real);
+
+/* set event priority (optional) */
+void snd_seq_ev_set_priority(snd_seq_event_t *ev, int high_prior);
+
+/* set event data type - following two macros are exclusive */
+  /* fixed size event */
+void snd_seq_ev_set_fixed(snd_seq_event_t *ev);
+  /* variable size event */
+void snd_seq_ev_set_variable(snd_seq_event_t *ev, int len, void *ptr);
+
+/* queue controls -
+ * to send at scheduled time, set the schedule in ev.
+ * if ev is NULL, event is sent immediately (to output queue).
+ * Note: to send actually to driver, you need to call snd_seq_flush_event()
+ *       apropriately.
+ */
+int snd_seq_control_queue(snd_seq_t *seq, int q, int type, int value, snd_seq_event_t *ev);
+int snd_seq_start_queue(snd_seq_t *seq, int q, snd_seq_event_t *ev);
+int snd_seq_stop_queue(snd_seq_t *seq, int q, snd_seq_event_t *ev);
+int snd_seq_continue_queue(snd_seq_t *seq, int q, snd_seq_event_t *ev);
+int snd_seq_change_queue_tempo(snd_seq_t *seq, int q, int tempo, snd_seq_event_t *ev);
+
+/* create a port - simple version - return the port number */
+int snd_seq_create_simple_port(snd_seq_t *seq, char *name,
+                              unsigned int caps, unsigned int type);
+/* delete the port */
+int snd_seq_delete_simple_port(snd_seq_t *seq, int port);
+
+/* simple subscription between this port and another port
+   (w/o exclusive & time conversion)
+   */
+int snd_seq_connect_from(snd_seq_t *seq, int my_port, int src_client, int src_port);
+int snd_seq_connect_to(snd_seq_t *seq, int my_port, int dest_client, int dest_port);
+int snd_seq_disconnect_from(snd_seq_t *seq, int my_port, int src_client, int src_port);
+int snd_seq_disconnect_to(snd_seq_t *seq, int my_port, int dest_client, int dest_port);
+
+/*
+ * set client information
+ */
+int snd_seq_set_client_name(snd_seq_t *seq, char *name);
+int snd_seq_set_client_group(snd_seq_t *seq, char *name);
+int snd_seq_set_client_filter(snd_seq_t *seq, unsigned int filter);
+int snd_seq_set_client_event_filter(snd_seq_t *seq, int event_type);
+int snd_seq_set_client_pool_output(snd_seq_t *seq, int size);
+int snd_seq_set_client_pool_output_room(snd_seq_t *seq, int size);
+int snd_seq_set_client_pool_input(snd_seq_t *seq, int size);
+
+/*
+ * reset client input/output pool
+ */
+int snd_seq_reset_pool_output(snd_seq_t *seq);
+int snd_seq_reset_pool_input(snd_seq_t *seq);
+
+/*
+ * equivalent macros
+ */
+#define __snd_seq_ev_clear(ev) memset(ev, 0, sizeof(snd_seq_event_t))
+#define __snd_seq_ev_set_dest(ev,c,p) \
+       ((ev)->dest.client = (c), (ev)->dest.port = (p))
+#define __snd_seq_ev_set_subs(ev) \
+       ((ev)->dest.client = SND_SEQ_ADDRESS_SUBSCRIBERS,\
+        (ev)->dest.port = SND_SEQ_ADDRESS_UNKNOWN)
+#define __snd_seq_ev_set_broadcast(ev) \
+       ((ev)->dest.client = SND_SEQ_ADDRESS_BROADCAST,\
+        (ev)->dest.port = SND_SEQ_ADDRESS_BROADCAST)
+#define __snd_seq_ev_set_source(ev,p) ((ev)->source.port = (p))
+
+#define __snd_seq_start_queue(seq,q,ev) \
+       snd_seq_control_queue(seq, q, SND_SEQ_EVENT_START, 0, ev)
+#define __snd_seq_stop_queue(seq,q,ev) \
+       snd_seq_control_queue(seq, q, SND_SEQ_EVENT_STOP, 0, ev)
+#define __snd_seq_continue_queue(seq,q,ev) \
+       snd_seq_control_queue(seq, q, SND_SEQ_EVENT_CONTINUE, 0, ev)
+#define __snd_seq_change_queue_tempo(seq,q,tempo,ev) \
+       snd_seq_control_queue(seq, q, SND_SEQ_EVENT_TEMPO, tempo, ev)
+
+/*
+ * redefintion
+ */
+#define snd_seq_ev_clear(ev)           __snd_seq_ev_clear(ev)
+#define snd_seq_ev_set_dest(ev,c,p)    __snd_seq_ev_set_dest(ev,c,p)
+#define snd_seq_ev_set_subs(ev)                __snd_seq_ev_set_subs(ev)
+#define snd_seq_ev_set_broadcast(ev)   __snd_seq_ev_set_broadcast(ev)
+#define snd_seq_ev_set_source(ev,p)    __snd_seq_ev_set_source(ev,p)
+#define snd_seq_start_queue(seq,q,ev)  __snd_seq_start_queue(seq,q,ev)
+#define snd_seq_stop_queue(seq,q,ev)   __snd_seq_stop_queue(seq,q,ev)
+#define snd_seq_continue_queue(seq,q,ev)       __snd_seq_continue_queue(seq,q,ev)
+#define snd_seq_change_queue_tempo(seq,q,tempo,ev)     __snd_seq_change_queue_tempo(seq,q,tempo,ev)
+
+/*
+ * check event flags
+ */
+#define snd_seq_ev_is_direct(ev) ((ev)->flags & SND_SEQ_DEST_MASK)
+#define snd_seq_ev_is_prior(ev) ((ev)->flags & SND_SEQ_PRIORITY_MASK)
+#define snd_seq_ev_is_variable(ev) (((ev)->flags & SND_SEQ_EVENT_LENGTH_MASK) == SND_SEQ_EVENT_LENGTH_VARIABLE)
+#define snd_seq_ev_is_realtime(ev) ((ev)->flags & SND_SEQ_TIME_STAMP_MASK)
+#define snd_seq_ev_is_relative(ev) ((ev)->flags & SND_SEQ_TIME_MODE_MASK)
+/* ... etc. */
+
+/*
+ * macros to set standard event data
+ */
+#define snd_seq_ev_set_note(ev,ch,key,vel,dur) \
+       ((ev)->type = SND_SEQ_EVENT_NOTE,\
+        snd_seq_ev_set_fixed(ev),\
+        (ev)->dest.channel = (ch),\
+        (ev)->data.note.note = (key),\
+        (ev)->data.note.velocity = (vel),\
+        (ev)->data.note.dulation = (dur))
+#define snd_seq_ev_set_noteon(ev,ch,key,vel) \
+       ((ev)->type = SND_SEQ_EVENT_NOTEON,\
+        snd_seq_ev_set_fixed(ev),\
+        (ev)->dest.channel = (ch),\
+        (ev)->data.note.note = (key),\
+        (ev)->data.note.velocity = (vel))
+#define snd_seq_ev_set_noteoff(ev,ch,key,vel) \
+       ((ev)->type = SND_SEQ_EVENT_NOTEOFF,\
+        snd_seq_ev_set_fixed(ev),\
+        (ev)->dest.channel = (ch),\
+        (ev)->data.note.note = (key),\
+        (ev)->data.note.velocity = (vel))
+#define snd_seq_ev_set_keypress(ev,ch,key,vel) \
+       ((ev)->type = SND_SEQ_EVENT_KEYPRESS,\
+        snd_seq_ev_set_fixed(ev),\
+        (ev)->dest.channel = (ch),\
+        (ev)->data.note.note = (key),\
+        (ev)->data.note.velocity = (vel))
+#define snd_seq_ev_set_controller(ev,ch,cc,val) \
+       ((ev)->type = SND_SEQ_EVENT_CONTROLLER,\
+        snd_seq_ev_set_fixed(ev),\
+        (ev)->dest.channel = (ch),\
+        (ev)->data.control.param = (cc),\
+        (ev)->data.control.value = (val))
+#define snd_seq_ev_set_pgmchange(ev,ch,val) \
+       ((ev)->type = SND_SEQ_EVENT_PGMCHANGE,\
+        snd_seq_ev_set_fixed(ev),\
+        (ev)->dest.channel = (ch),\
+        (ev)->data.control.value = (val))
+#define snd_seq_ev_set_pitchbend(ev,ch,val) \
+       ((ev)->type = SND_SEQ_EVENT_PITCHBEND,\
+        snd_seq_ev_set_fixed(ev),\
+        (ev)->dest.channel = (ch),\
+        (ev)->data.control.value = (val))
+#define snd_seq_ev_set_chanpress(ev,ch,val) \
+       ((ev)->type = SND_SEQ_EVENT_CHANPRESS,\
+        snd_seq_ev_set_fixed(ev),\
+        (ev)->dest.channel = (ch),\
+        (ev)->data.control.value = (val))
+#define snd_seq_ev_set_sysex(ev,datalen,dataptr) \
+       ((ev)->type = SND_SEQ_EVENT_SYSEX,\
+        snd_seq_ev_set_variable(ev, datalen, dataptr))
+
+/* etc. etc... */
+
+
+#ifdef __cplusplus
+}
+#endif
+
index 778893d3049743ece32edcbcfa67150860c6490c..637dfec81f20d79629771f589de9c75b6d84d35c 100644 (file)
@@ -1,6 +1,8 @@
 EXTRA_LTLIBRARIES=libseq.la
 
-libseq_la_SOURCES = seq.c
+libseq_la_SOURCES = seq.c seqmid.c
+noinst_HEADERS = seq_priv.h
+
 all: libseq.la
 
 
index 33ba13d623c624a3fd952f0886a9ae65bf7a6146..38ff32064e947dea34429621aa7eb6b8c7923d26 100644 (file)
@@ -27,6 +27,7 @@
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include "asoundlib.h"
+#include "seq_priv.h"
 
 #define SND_FILE_SEQ           "/dev/snd/seq"
 #define SND_FILE_ALOADSEQ      "/dev/aloadSEQ"
 #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;
-
-struct snd_seq {
-       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;
-};
-
 int snd_seq_open(snd_seq_t **handle, int mode)
 {
        int fd, ver, client, flg;
@@ -863,4 +844,3 @@ int snd_seq_get_bit(int nr, void *array)
        return ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0;
 }
 
-
diff --git a/src/seq/seq_priv.h b/src/seq/seq_priv.h
new file mode 100644 (file)
index 0000000..1f35642
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  Sequencer Interface - definition of sequencer event handler
+ *  Copyright (c) 1998 by Jaroslav Kysela <perex@suse.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.
+ *
+ */
+
+#ifndef __SEQ_PRIV_H
+#define __SEQ_PRIV_H
+
+typedef struct snd_stru_seq_cell {
+       snd_seq_event_t ev;
+       struct snd_stru_seq_cell *next;
+} snd_seq_cell_t;
+
+struct snd_seq {
+       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;
+};
+
+#endif
diff --git a/src/seq/seqmid.c b/src/seq/seqmid.c
new file mode 100644 (file)
index 0000000..f2999e0
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ *  Sequencer Interface - middle-level routines
+ *
+ *  Copyright (c) 1999 by Takashi Iwai <iwai@ww.uni-erlangen.de>
+ *
+ *
+ *   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"
+#include "seq_priv.h"
+
+/* direct passing (without queued) */
+void snd_seq_ev_set_direct(snd_seq_event_t *ev)
+{
+       ev->flags &= ~SND_SEQ_DEST_MASK;
+       ev->flags |= SND_SEQ_DEST_DIRECT;
+       ev->dest.queue = SND_SEQ_ADDRESS_UNKNOWN; /* XXX */
+}
+
+/* queued on tick */
+void snd_seq_ev_schedule_tick(snd_seq_event_t *ev, int q, int relative,
+                             unsigned long tick)
+{
+       ev->flags &= ~(SND_SEQ_DEST_MASK | SND_SEQ_TIME_STAMP_MASK |
+                      SND_SEQ_TIME_MODE_MASK);
+       ev->flags |= SND_SEQ_DEST_QUEUE;
+       ev->flags |= SND_SEQ_TIME_STAMP_TICK;
+       ev->flags |= relative ? SND_SEQ_TIME_MODE_REL : SND_SEQ_TIME_MODE_ABS;
+       ev->time.tick = tick;
+}
+
+/* queued on real-time */
+void snd_seq_ev_schedule_real(snd_seq_event_t *ev, int q, int relative,
+                             snd_seq_real_time_t *real)
+{
+       ev->flags &= ~(SND_SEQ_DEST_MASK | SND_SEQ_TIME_STAMP_MASK |
+                      SND_SEQ_TIME_MODE_MASK);
+       ev->flags |= SND_SEQ_DEST_QUEUE;
+       ev->flags |= SND_SEQ_TIME_STAMP_REAL;
+       ev->flags |= relative ? SND_SEQ_TIME_MODE_REL : SND_SEQ_TIME_MODE_ABS;
+       ev->time.real = *real;
+}
+
+/* set event priority */
+void snd_seq_ev_set_priority(snd_seq_event_t *ev, int high_prior)
+{
+       ev->flags &= ~SND_SEQ_PRIORITY_MASK;
+       ev->flags |= high_prior ? SND_SEQ_PRIORITY_HIGH : SND_SEQ_PRIORITY_NORMAL;
+}
+
+/* set fixed data */
+void snd_seq_ev_set_fixed(snd_seq_event_t *ev)
+{
+       ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
+       ev->flags |= SND_SEQ_EVENT_LENGTH_FIXED;
+}
+
+/* set variable data */
+void snd_seq_ev_set_variable(snd_seq_event_t *ev, int len, void *ptr)
+{
+       ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
+       ev->flags |= SND_SEQ_EVENT_LENGTH_VARIABLE;
+       ev->data.ext.len = len;
+       ev->data.ext.ptr = ptr;
+}
+
+/* queue controls - start/stop/continue */
+/* if ev is NULL, send events immediately.
+   otherwise, duplicate the given event data.
+   destination is overwritten to Timer port (0:0)
+   */
+int snd_seq_control_queue(snd_seq_t *seq, int q, int type, int value, snd_seq_event_t *ev)
+{
+       snd_seq_event_t tmpev;
+       if (ev == NULL) {
+               snd_seq_ev_clear(&tmpev);
+               ev = &tmpev;
+               snd_seq_ev_set_direct(ev);
+       }
+
+       ev->type = type;
+       snd_seq_ev_set_dest(ev, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_TIMER);
+#if 1
+       /* new type */
+       ev->data.queue.addr.queue = q;
+       ev->data.queue.value = value;
+#else
+       /* old type */
+       ev->dest.queue = q;
+       ev->data.control.value = value;
+#endif
+
+       return snd_seq_event_output(seq, ev);
+}
+
+
+/* create a port - simple version
+ * return the port number
+ */
+int snd_seq_create_simple_port(snd_seq_t *seq, char *name,
+                              unsigned int caps, unsigned int type)
+{
+       snd_seq_port_info_t pinfo;
+       int result;
+
+       memset(&pinfo, 0, sizeof(pinfo));
+       if (name)
+               strncpy(pinfo.name, name, sizeof(pinfo.name) - 1);
+       pinfo.capability = caps;
+       pinfo.cap_group = caps;
+       pinfo.type = type;
+       pinfo.midi_channels = 16;
+       pinfo.midi_voices = 64; /* XXX */
+       pinfo.synth_voices = 0; /* XXX */
+       pinfo.kernel = NULL;
+
+       result = snd_seq_create_port(seq, &pinfo);
+       if (result < 0)
+               return result;
+       else
+               return pinfo.port;
+}
+
+/* delete the port */
+int snd_seq_delete_simple_port(snd_seq_t *seq, int port)
+{
+       snd_seq_port_info_t pinfo;
+
+       memset(&pinfo, 0, sizeof(pinfo));
+       pinfo.port = port;
+
+       return snd_seq_delete_port(seq, &pinfo);
+}
+
+/*
+ * sipmle subscription (w/o exclusive & time conversion)
+ */
+int snd_seq_connect_from(snd_seq_t *seq, int myport, int src_client, int src_port)
+{
+       snd_seq_port_subscribe_t subs;
+       
+       memset(&subs, 0, sizeof(subs));
+       subs.sender.client = src_client;
+       subs.sender.port = src_port;
+       /*subs.dest.client = seq->client;*/
+       subs.dest.client = snd_seq_client_id(seq);
+       subs.dest.port = myport;
+
+       return snd_seq_subscribe_port(seq, &subs);
+}
+
+int snd_seq_connect_to(snd_seq_t *seq, int myport, int dest_client, int dest_port)
+{
+       snd_seq_port_subscribe_t subs;
+       
+       memset(&subs, 0, sizeof(subs));
+       /*subs.sender.client = seq->client;*/
+       subs.sender.client = snd_seq_client_id(seq);
+       subs.sender.port = myport;
+       subs.dest.client = dest_client;
+       subs.dest.port = dest_port;
+
+       return snd_seq_subscribe_port(seq, &subs);
+}
+
+int snd_seq_disconnect_from(snd_seq_t *seq, int myport, int src_client, int src_port)
+{
+       snd_seq_port_subscribe_t subs;
+       
+       memset(&subs, 0, sizeof(subs));
+       subs.sender.client = src_client;
+       subs.sender.port = src_port;
+       /*subs.dest.client = seq->client;*/
+       subs.dest.client = snd_seq_client_id(seq);
+       subs.dest.port = myport;
+
+       return snd_seq_unsubscribe_port(seq, &subs);
+}
+
+int snd_seq_disconnect_to(snd_seq_t *seq, int myport, int dest_client, int dest_port)
+{
+       snd_seq_port_subscribe_t subs;
+       
+       memset(&subs, 0, sizeof(subs));
+       /*subs.sender.client = seq->client;*/
+       subs.sender.client = snd_seq_client_id(seq);
+       subs.sender.port = myport;
+       subs.dest.client = dest_client;
+       subs.dest.port = dest_port;
+
+       return snd_seq_unsubscribe_port(seq, &subs);
+}
+
+/*
+ * set client information
+ */
+int snd_seq_set_client_name(snd_seq_t *seq, char *name)
+{
+       snd_seq_client_info_t info;
+       int err;
+
+       if ((err = snd_seq_get_client_info(seq, &info)) < 0)
+               return err;
+       strncpy(info.name, name, sizeof(info.name) - 1);
+       return snd_seq_set_client_info(seq, &info);
+}
+
+int snd_seq_set_client_group(snd_seq_t *seq, char *name)
+{
+       snd_seq_client_info_t info;
+       int err;
+
+       if ((err = snd_seq_get_client_info(seq, &info)) < 0)
+               return err;
+       strncpy(info.group, name, sizeof(info.group) - 1);
+       return snd_seq_set_client_info(seq, &info);
+}
+
+int snd_seq_set_client_filter(snd_seq_t *seq, unsigned int filter)
+{
+       snd_seq_client_info_t info;
+       int err;
+
+       if ((err = snd_seq_get_client_info(seq, &info)) < 0)
+               return err;
+       info.filter = filter;
+       return snd_seq_set_client_info(seq, &info);
+}
+
+int snd_seq_set_client_event_filter(snd_seq_t *seq, int event_type)
+{
+       snd_seq_client_info_t info;
+       int err;
+
+       if ((err = snd_seq_get_client_info(seq, &info)) < 0)
+               return err;
+       info.filter |= SND_SEQ_FILTER_USE_EVENT;
+       snd_seq_set_bit(event_type, info.event_filter);
+       return snd_seq_set_client_info(seq, &info);
+}
+
+int snd_seq_set_client_pool_output(snd_seq_t *seq, int size)
+{
+       snd_seq_client_pool_t info;
+       int err;
+
+       if ((err = snd_seq_get_client_pool(seq, &info)) < 0)
+               return err;
+       info.output_pool = size;
+       return snd_seq_set_client_pool(seq, &info);
+}
+
+int snd_seq_set_client_pool_output_room(snd_seq_t *seq, int size)
+{
+       snd_seq_client_pool_t info;
+       int err;
+
+       if ((err = snd_seq_get_client_pool(seq, &info)) < 0)
+               return err;
+       info.output_room = size;
+       return snd_seq_set_client_pool(seq, &info);
+}
+
+int snd_seq_set_client_pool_input(snd_seq_t *seq, int size)
+{
+       snd_seq_client_pool_t info;
+       int err;
+
+       if ((err = snd_seq_get_client_pool(seq, &info)) < 0)
+               return err;
+       info.input_pool = size;
+       return snd_seq_set_client_pool(seq, &info);
+}
+
+/*
+ * reset client input/output pool
+ * use REMOVE_EVENTS ioctl instead of RESET_POOL
+ */
+int snd_seq_reset_pool_output(snd_seq_t *seq)
+{
+       snd_seq_remove_events_t rmp;
+
+       memset(&rmp, 0, sizeof(rmp));
+       rmp.output = 1;
+       rmp.remove_mode = 0; /* remove all */
+       return snd_seq_remove_events(seq, &rmp);
+}
+
+int snd_seq_reset_pool_input(snd_seq_t *seq)
+{
+       snd_seq_remove_events_t rmp;
+
+       memset(&rmp, 0, sizeof(rmp));
+       rmp.input = 1;
+       rmp.remove_mode = 0; /* remove all */
+       return snd_seq_remove_events(seq, &rmp);
+}
+
index 888f230114ae6b7d526a503d6f4294a37a6b6d91..0adf8d6ffc69339999359a2ca14bea7164c2adfd 100644 (file)
@@ -37,6 +37,7 @@ static void usage(void)
        fprintf(stderr, "            list input ports\n");
        fprintf(stderr, "       aconnect -o [-g group] [-l]\n");
        fprintf(stderr, "            list output ports\n");
+       fprintf(stderr, "            -l = list current connections\n");
 }
 
 /*
index 101981a51f45636d36bfb6c0cb71527ad501644b..d2f993ddf20ffad7f90fabb67edab5631ea5c47c 100644 (file)
 #include <netdb.h>
 #include <sys/asoundlib.h>
 #include <unistd.h>
+#include <signal.h>
 
 /*
  * prototypes
  */
 static void usage(void);
 static void init_buf(void);
+static void close_files(void);
 static void init_seq(char *source, char *dest);
 static int get_port(char *service);
+static void sigterm_exit(int sig);
 static void init_server(int port);
 static void init_client(char *server, int port);
 static void do_loop(void);
@@ -54,7 +57,7 @@ static int cur_wrlen, max_wrlen;
 #define MAX_CONNECTION 10
 
 static snd_seq_t *handle;
-static int seqfd, sockfd, netfd[MAX_CONNECTION] = {[1 ... MAX_CONNECTION] = -1};
+static int seqfd, sockfd, netfd[MAX_CONNECTION] = {[0 ... MAX_CONNECTION-1] = -1};
 static int max_connection;
 static int cur_connected;
 static int seq_port;
@@ -68,7 +71,7 @@ static int server_mode;
 
 int main(int argc, char **argv)
 {
-       int c, i;
+       int c;
        int port = DEFAULT_PORT;
        char *source = NULL, *dest = NULL;
 
@@ -92,6 +95,9 @@ int main(int argc, char **argv)
                }
        }
 
+       signal(SIGINT, sigterm_exit);
+       signal(SIGTERM, sigterm_exit);
+
        init_buf();
        init_seq(source, dest);
 
@@ -107,12 +113,7 @@ int main(int argc, char **argv)
 
        do_loop();
 
-       for (i = 0; i < max_connection; i++) {
-               if (netfd[i] >= 0)
-                       close(netfd[i]);
-       }
-       if (sockfd >= 0)
-               close(sockfd);
+       close_files();
 
        return 0;
 }
@@ -167,14 +168,29 @@ static void parse_addr(snd_seq_addr_t *addr, char *arg)
                addr->port = 0;
 }
 
+
+/*
+ * close all files
+ */
+static void close_files(void)
+{
+       int i;
+fprintf(stderr, "closing files..\n");
+       for (i = 0; i < max_connection; i++) {
+               if (netfd[i] >= 0)
+                       close(netfd[i]);
+       }
+       if (sockfd >= 0)
+               close(sockfd);
+}
+
+
 /*
  * initialize sequencer
  */
 static void init_seq(char *source, char *dest)
 {
-       snd_seq_client_info_t cinfo;
-       snd_seq_port_info_t pinfo;
-       snd_seq_port_subscribe_t subs;
+       snd_seq_addr_t addr;
 
        if (snd_seq_open(&handle, SND_SEQ_OPEN) < 0) {
                perror("snd_seq_open");
@@ -184,49 +200,38 @@ static void init_seq(char *source, char *dest)
        snd_seq_block_mode(handle, 0);
 
        /* set client info */
-       memset(&cinfo, 0, sizeof(cinfo));
        if (server_mode)
-               strcpy(cinfo.name, "Net Server");
+               snd_seq_set_client_name(handle, "Net Server");
        else
-               strcpy(cinfo.name, "Net Client");
-       if (snd_seq_set_client_info(handle, &cinfo) < 0) {
-               perror("set client info");
-               exit(1);
-       }
+               snd_seq_set_client_name(handle, "Net Client");
 
        /* create a port */
-       memset(&pinfo, 0, sizeof(pinfo));
-       pinfo.capability = SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_WRITE|
-                          SND_SEQ_PORT_CAP_SUBS_READ|SND_SEQ_PORT_CAP_SUBS_WRITE;
-       strcpy(pinfo.name, "Network");
-       pinfo.port = 0;
-       if (snd_seq_create_port(handle, &pinfo) < 0) {
+       seq_port = snd_seq_create_simple_port(handle, "Network",
+                                             SND_SEQ_PORT_CAP_READ |
+                                             SND_SEQ_PORT_CAP_WRITE |
+                                             SND_SEQ_PORT_CAP_SUBS_READ |
+                                             SND_SEQ_PORT_CAP_SUBS_WRITE,
+                                             SND_SEQ_PORT_TYPE_MIDI_GENERIC);
+       if (seq_port < 0) {
                perror("create seq port");
                exit(1);
        }
-       seq_port = pinfo.port;
-       fprintf(stderr, "sequencer opened: %d:%d\n", pinfo.client, pinfo.port);
+       fprintf(stderr, "sequencer opened: %d:%d\n",
+               snd_seq_client_id(handle), seq_port);
 
        /* explicit subscriptions */
-       memset(&subs, 0, sizeof(subs));
        if (source) {
                /* read subscription */
-               parse_addr(&subs.sender, source);
-               subs.dest.client = pinfo.client;
-               subs.dest.port = pinfo.port;
-               subs.sender.queue = subs.dest.queue = 0;
-               if (snd_seq_subscribe_port(handle, &subs)) {
+               parse_addr(&addr, source);
+               if (snd_seq_connect_from(handle, seq_port, addr.client, addr.port)) {
                        perror("read subscription");
                        exit(1);
                }
        }
        if (dest) {
                /* write subscription */
-               parse_addr(&subs.dest, dest);
-               subs.sender.client = pinfo.client;
-               subs.sender.port = pinfo.port;
-               subs.sender.queue = subs.dest.queue = 0;
-               if (snd_seq_subscribe_port(handle, &subs)) {
+               parse_addr(&addr, dest);
+               if (snd_seq_connect_to(handle, seq_port, addr.client, addr.port)) {
                        perror("write subscription");
                        exit(1);
                }
@@ -248,6 +253,16 @@ static int get_port(char *service)
        return sp->s_port;
 }
 
+/*
+ * signal handler
+ */
+static void sigterm_exit(int sig)
+{
+       close_files();
+       exit(1);
+}
+
+
 /*
  * initialize network server
  */
@@ -395,11 +410,6 @@ static void do_loop(void)
 }
 
 
-/*
- * is variable length event?
- */
-#define is_varlen(ev) (((ev)->flags & SND_SEQ_EVENT_LENGTH_MASK) == SND_SEQ_EVENT_LENGTH_VARIABLE)
-
 /*
  * flush write buffer - send data to the socket
  */
@@ -442,7 +452,7 @@ static int copy_local_to_remote(void)
                        snd_seq_free_event(ev);
                        continue;
                }
-               if (is_varlen(ev)) {
+               if (snd_seq_ev_is_variable(ev)) {
                        int len;
                        len = sizeof(snd_seq_event_t) + ev->data.ext.len;
                        buf = get_writebuf(len);
@@ -483,7 +493,7 @@ static int copy_remote_to_local(int fd)
                memcpy(ev, buf, sizeof(snd_seq_event_t));
                buf += sizeof(snd_seq_event_t);
                count -= sizeof(snd_seq_event_t);
-               if (is_varlen(ev) && ev->data.ext.len > 0) {
+               if (snd_seq_ev_is_variable(ev) && ev->data.ext.len > 0) {
                        ev->data.ext.ptr = malloc(ev->data.ext.len);
                        if (ev->data.ext.ptr == NULL) {
                                fprintf(stderr, "can't malloc\n");
@@ -493,8 +503,9 @@ static int copy_remote_to_local(int fd)
                        buf += ev->data.ext.len;
                        count -= ev->data.ext.len;
                }
-               ev->source.port = seq_port;
-               ev->dest.queue = SND_SEQ_ADDRESS_SUBSCRIBERS;
+               snd_seq_ev_set_direct(ev);
+               snd_seq_ev_set_source(ev, seq_port);
+               snd_seq_ev_set_subs(ev);
                snd_seq_event_output(handle, ev);
                snd_seq_free_event(ev);
        }
index 6c6151aae9c07699eefa711dd2ea4e3b94f6c49f..37446b0e812cf5293c28b068676fd703a7f180b2 100644 (file)
@@ -15,6 +15,9 @@
  *   19990827  Takashi Iwai <iwai@ww.uni-erlangen.de>
  *     - use snd_seq_alloc_queue()
  *
+ *   19990916  Takashi Iwai <iwai@ww.uni-erlangen.de>
+ *     - use middle-level sequencer routines and macros
+ *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
  *   the Free Software Foundation; either version 2 of the License, or
@@ -71,8 +74,7 @@ static int local_tempo = 500000;
 static int dest_queue = 0;
 static int dest_client = DEST_CLIENT_NUMBER;
 static int dest_port = DEST_PORT_NUMBER;
-static int source_channel = 0;
-static int source_port = 0;
+static int my_port = 0;
 
 static int verbose = 0;
 static int slave   = 0;                /* allow external sync */
@@ -102,7 +104,7 @@ static void tick2time(snd_seq_real_time_t * tm, int tick)
 
 #ifdef USE_BLOCKING_MODE
 /* write event - using blocking mode */
-static void write_ev_im(snd_seq_event_t *ev)
+static void write_ev(snd_seq_event_t *ev)
 {
        int written;
 
@@ -114,7 +116,7 @@ static void write_ev_im(snd_seq_event_t *ev)
 }
 #else
 /* write event - using select syscall */
-static void write_ev_im(snd_seq_event_t *ev)
+static void write_ev(snd_seq_event_t *ev)
 {
        int rc;
 
@@ -132,24 +134,6 @@ static void write_ev_im(snd_seq_event_t *ev)
 }
 #endif
 
-/* write event to ALSA sequencer */
-static void write_ev(snd_seq_event_t * ev)
-{
-       ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
-       ev->flags |= SND_SEQ_EVENT_LENGTH_FIXED;
-       write_ev_im(ev);
-}
-
-/* write variable length event to ALSA sequencer */
-static void write_ev_var(snd_seq_event_t * ev, int len, void *ptr)
-{
-       ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
-       ev->flags |= SND_SEQ_EVENT_LENGTH_VARIABLE;
-       ev->data.ext.len = len;
-       ev->data.ext.ptr = ptr;
-       write_ev_im(ev);
-}
-
 /* read byte */
 static int mygetc(void)
 {
@@ -210,75 +194,39 @@ static void do_header(int format, int ntracks, int division)
                alsa_start_timer();
 }
 
-/* fill normal event header */
-static void set_event_header(snd_seq_event_t *ev, int type, int chan)
+/* fill time */
+static void set_event_time(snd_seq_event_t *ev, unsigned int currtime)
 {
-       ev->source.port = source_port;
-       ev->source.channel = source_channel;
-
-       ev->dest.queue = dest_queue;
-       ev->dest.client = dest_client;
-       ev->dest.port = dest_port;
-       ev->dest.channel = chan;
-
 #ifdef USE_REALTIME
-       ev->flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_ABS;
-       tick2time(&ev->time.real, Mf_currtime);
+       snd_seq_real_time_t rtime;
+       tick2time(&rtime, currtime);
+       snd_seq_ev_schedule_real(ev, dest_queue, 0, &rtime);
 #else
-       ev->flags = SND_SEQ_TIME_STAMP_TICK | SND_SEQ_TIME_MODE_ABS;
-       ev->time.tick = Mf_currtime;
+       snd_seq_ev_schedule_tick(ev, dest_queue, 0, currtime);
 #endif
-
-       ev->type = type;
 }
 
-/* fill timer event header */
-static void set_timer_event_header(snd_seq_event_t *ev, int type)
+/* fill normal event header */
+static void set_event_header(snd_seq_event_t *ev)
 {
-       ev->source.port = source_port;
-       ev->source.channel = 0;
-
-       ev->dest.queue = dest_queue;
-       ev->dest.client = SND_SEQ_CLIENT_SYSTEM;        /* system */
-       ev->dest.port = SND_SEQ_PORT_SYSTEM_TIMER;      /* timer */
-       ev->dest.channel = 0;   /* don't care */
-
-#ifdef USE_REALTIME
-       ev->flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_ABS;
-       tick2time(&ev->time.real, Mf_currtime);
-#else
-       ev->flags = SND_SEQ_TIME_STAMP_TICK | SND_SEQ_TIME_MODE_ABS;
-       ev->time.tick = Mf_currtime;
-#endif
-
-       ev->type = type;
+       snd_seq_ev_clear(ev);
+       snd_seq_ev_set_dest(ev, dest_client, dest_port);
+       snd_seq_ev_set_source(ev, my_port);
+       set_event_time(ev, Mf_currtime);
 }
 
 /* start timer */
 static void alsa_start_timer(void)
 {
-       snd_seq_event_t ev;
-
-       set_timer_event_header(&ev, SND_SEQ_EVENT_START);
-#ifdef USE_REALTIME
-       ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_REL;
-       ev.time.real.tv_sec = 0;
-       ev.time.real.tv_nsec = 0;
-#else
-       ev.flags = SND_SEQ_TIME_STAMP_TICK | SND_SEQ_TIME_MODE_REL;
-       ev.time.tick = Mf_currtime;
-#endif
-
-       write_ev(&ev);
+       snd_seq_start_queue(seq_handle, dest_queue, NULL);
 }
 
 /* stop timer */
 static void alsa_stop_timer(void)
 {
        snd_seq_event_t ev;
-
-       set_timer_event_header(&ev, SND_SEQ_EVENT_STOP);
-       write_ev(&ev);
+       set_event_header(&ev);
+       snd_seq_stop_queue(seq_handle, dest_queue, &ev);
 }
 
 /* change tempo */
@@ -297,11 +245,9 @@ static void do_tempo(int us)
        local_ticks = Mf_currtime;
        local_tempo = us;
 
-       set_timer_event_header(&ev, SND_SEQ_EVENT_TEMPO);
-       ev.data.queue.addr.queue = dest_queue;
-       ev.data.queue.value = us;
+       set_event_header(&ev);
        if (!slave)
-               write_ev(&ev);
+               snd_seq_change_queue_tempo(seq_handle, dest_queue, us, &ev);
 }
 
 static void do_noteon(int chan, int pitch, int vol)
@@ -310,10 +256,8 @@ static void do_noteon(int chan, int pitch, int vol)
 
        if (verbose >= VERB_EVENT)
                printf("NoteOn (%d) %d %d\n", chan, pitch, vol);
-       set_event_header(&ev, SND_SEQ_EVENT_NOTEON, chan);
-       ev.data.note.note = pitch;
-       ev.data.note.velocity = vol;
-
+       set_event_header(&ev);
+       snd_seq_ev_set_noteon(&ev, chan, pitch, vol);
        write_ev(&ev);
 }
 
@@ -324,10 +268,8 @@ static void do_noteoff(int chan, int pitch, int vol)
 
        if (verbose >= VERB_EVENT)
                printf("NoteOff (%d) %d %d\n", chan, pitch, vol);
-       set_event_header(&ev, SND_SEQ_EVENT_NOTEOFF, chan);
-       ev.data.note.note = pitch;
-       ev.data.note.velocity = vol;
-
+       set_event_header(&ev);
+       snd_seq_ev_set_noteoff(&ev, chan, pitch, vol);
        write_ev(&ev);
 }
 
@@ -338,9 +280,8 @@ static void do_program(int chan, int program)
 
        if (verbose >= VERB_EVENT)
                printf("Program (%d) %d\n", chan, program);
-       set_event_header(&ev, SND_SEQ_EVENT_PGMCHANGE, chan);
-       ev.data.control.value = program;
-
+       set_event_header(&ev);
+       snd_seq_ev_set_pgmchange(&ev, chan, program);
        write_ev(&ev);
 }
 
@@ -351,10 +292,8 @@ static void do_parameter(int chan, int control, int value)
 
        if (verbose >= VERB_EVENT)
                printf("Control (%d) %d %d\n", chan, control, value);
-       set_event_header(&ev, SND_SEQ_EVENT_CONTROLLER, chan);
-       ev.data.control.param = control;
-       ev.data.control.value = value;
-
+       set_event_header(&ev);
+       snd_seq_ev_set_controller(&ev, chan, control, value);
        write_ev(&ev);
 }
 
@@ -365,9 +304,8 @@ static void do_pitchbend(int chan, int lsb, int msb)
 
        if (verbose >= VERB_EVENT)
                printf("Pitchbend (%d) %d %d\n", chan, lsb, msb);
-       set_event_header(&ev, SND_SEQ_EVENT_PITCHBEND, chan);
-       ev.data.control.value = (lsb + (msb << 7)) - 8192;
-
+       set_event_header(&ev);
+       snd_seq_ev_set_pitchbend(&ev, chan, (lsb + (msb << 7)) - 8192);
        write_ev(&ev);
 }
 
@@ -377,10 +315,8 @@ static void do_pressure(int chan, int pitch, int pressure)
 
        if (verbose >= VERB_EVENT)
                printf("KeyPress (%d) %d %d\n", chan, pitch, pressure);
-       set_event_header(&ev, SND_SEQ_EVENT_KEYPRESS, chan);
-       ev.data.control.param = pitch;
-       ev.data.control.value = pressure;
-
+       set_event_header(&ev);
+       snd_seq_ev_set_keypress(&ev, chan, pitch, pressure);
        write_ev(&ev);
 }
 
@@ -390,9 +326,8 @@ static void do_chanpressure(int chan, int pressure)
 
        if (verbose >= VERB_EVENT)
                printf("ChanPress (%d) %d\n", chan, pressure);
-       set_event_header(&ev, SND_SEQ_EVENT_CHANPRESS, chan);
-       ev.data.control.value = pressure;
-
+       set_event_header(&ev);
+       snd_seq_ev_set_chanpress(&ev, chan, pressure);
        write_ev(&ev);
 }
 
@@ -412,8 +347,9 @@ static void do_sysex(int len, char *msg)
                        putchar('\n');
        }
 
-       set_event_header(&ev, SND_SEQ_EVENT_SYSEX, 0);
-       write_ev_var(&ev, len, msg);
+       set_event_header(&ev);
+       snd_seq_ev_set_sysex(&ev, len, msg);
+       write_ev(&ev);
 }
 
 static snd_seq_event_t *wait_for_event(void)
@@ -458,19 +394,11 @@ static void alsa_sync(void)
        if (verbose >= VERB_MUCH)
                printf("alsa_sync syncing... send ECHO(%d) event to myself. time=%f\n",
                       SND_SEQ_EVENT_ECHO, (double) Mf_currtime+1);
-       ev.source.port = source_port;
-       ev.dest.queue = dest_queue;
-       ev.dest.client = snd_seq_client_id(seq_handle);
-       ev.dest.port = source_port;
-       ev.dest.channel = 0;    /* don't care */
-
-#ifdef USE_REALTIME
-       ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_ABS;
-       tick2time(&ev.time.real, Mf_currtime+1);
-#else
-       ev.flags = SND_SEQ_TIME_STAMP_TICK | SND_SEQ_TIME_MODE_ABS;
-       ev.time.tick = Mf_currtime+1;
-#endif
+       snd_seq_ev_clear(&ev);
+       /* redirect to itself */
+       snd_seq_ev_set_dest(&ev, snd_seq_client_id(seq_handle), my_port);
+       snd_seq_ev_set_source(&ev, my_port);
+       set_event_time(&ev, Mf_currtime+1);
        ev.type = SND_SEQ_EVENT_ECHO;
        write_ev(&ev);
   
@@ -484,8 +412,11 @@ static void alsa_sync(void)
                        if (verbose >= VERB_MUCH)
                                printf("alsa_sync got event. type=%d, flags=%d\n",
                                       input_event->type, input_event->flags);
-                       if (input_event->type == SND_SEQ_EVENT_ECHO)
+                       if (input_event->type == SND_SEQ_EVENT_ECHO &&
+                           input_event->source.client == snd_seq_client_id(seq_handle)) {
+                               snd_seq_free_event(input_event);
                                break;
+                       }
                        snd_seq_free_event(input_event);
                }
        }
@@ -507,8 +438,10 @@ static void wait_start(void)
                                printf("wait_start got event. type=%d, flags=%d\n",
                                       input_event->type, input_event->flags);
                        if (input_event->type == SND_SEQ_EVENT_START &&
-                           input_event->data.addr.queue == dest_queue)
+                           input_event->data.addr.queue == dest_queue) {
+                               snd_seq_free_event(input_event);
                                break;
+                       }
                        snd_seq_free_event(input_event);
                }
        }
@@ -540,10 +473,6 @@ void parse_address(char *arg, int *clientp, int *portp)
 
 int main(int argc, char *argv[])
 {
-       snd_seq_client_info_t inf;
-       snd_seq_port_info_t src_port_info;
-       snd_seq_port_subscribe_t subscribe;
-       snd_seq_client_pool_t pool;
        int tmp;
        int c;
 
@@ -594,31 +523,20 @@ int main(int argc, char *argv[])
        /* set name */
        /* set event filter to recieve only echo event */
        /* if running in slave mode also listen for START event */
-       memset(&inf, 0, sizeof(snd_seq_client_info_t));
-       inf.filter |= SND_SEQ_FILTER_USE_EVENT;
-       memset(&inf.event_filter, 0, sizeof(inf.event_filter));
-       snd_seq_set_bit(SND_SEQ_EVENT_ECHO, inf.event_filter);
+       snd_seq_set_client_event_filter(seq_handle, SND_SEQ_EVENT_ECHO);
        if (slave)
-               snd_seq_set_bit(SND_SEQ_EVENT_START, inf.event_filter);
-       strcpy(inf.name, "MIDI file player");
-       if (snd_seq_set_client_info(seq_handle, &inf) < 0) {
-               perror("ioctl");
-               exit(1);
-       }
+               snd_seq_set_client_event_filter(seq_handle, SND_SEQ_EVENT_ECHO);
+       snd_seq_set_client_name(seq_handle, "MIDI file player");
 
        /* create port */
-       memset(&src_port_info, 0, sizeof(snd_seq_port_info_t));
-       src_port_info.capability = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ;
-       src_port_info.type = SND_SEQ_PORT_TYPE_MIDI_GENERIC;
-       src_port_info.midi_channels = 16;
-       src_port_info.synth_voices = 0;
-       src_port_info.kernel = NULL;
-       tmp = snd_seq_create_port(seq_handle, &src_port_info);
-       if (tmp < 0) {
+       my_port = snd_seq_create_simple_port(seq_handle, "Port 0",
+                                            SND_SEQ_PORT_CAP_WRITE |
+                                            SND_SEQ_PORT_CAP_READ,
+                                            SND_SEQ_PORT_TYPE_MIDI_GENERIC);
+       if (my_port < 0) {
                perror("creat port");
                exit(1);
        }
-       source_port = src_port_info.port;
        
        /* setup queue */
        dest_queue = snd_seq_alloc_queue(seq_handle);
@@ -628,19 +546,7 @@ int main(int argc, char *argv[])
        }
 
        /* setup subscriber */
-       bzero(&subscribe,sizeof(subscribe));
-       if (verbose >= VERB_INFO)
-               printf("debug subscribe src_port_info.client=%d\n",
-                      src_port_info.client);
-       subscribe.sender.client = snd_seq_client_id(seq_handle);
-       subscribe.sender.queue = dest_queue;
-       subscribe.sender.port = src_port_info.port;
-       subscribe.dest.client = dest_client;
-       subscribe.dest.port = dest_port;
-       subscribe.dest.queue = dest_queue;
-       subscribe.realtime = 1;
-       subscribe.exclusive = 0;
-       tmp = snd_seq_subscribe_port(seq_handle, &subscribe);
+       tmp = snd_seq_connect_to(seq_handle, my_port, dest_client, dest_port);
        if (tmp < 0) {
                perror("subscribe");
                exit(1);
@@ -648,15 +554,9 @@ int main(int argc, char *argv[])
 
        /* subscribe for timer START event */   
        if (slave) {    
-               subscribe.sender.client = SND_SEQ_CLIENT_SYSTEM;
-               subscribe.sender.queue = dest_queue;
-               subscribe.sender.port = SND_SEQ_PORT_SYSTEM_TIMER;
-               subscribe.dest.client = snd_seq_client_id(seq_handle);
-               subscribe.dest.port = src_port_info.port;
-               subscribe.dest.queue = dest_queue;
-               subscribe.realtime = 0;
-               subscribe.exclusive = 0;
-               tmp = snd_seq_subscribe_port(seq_handle, &subscribe);
+               tmp = snd_seq_connect_from(seq_handle, my_port,
+                                          SND_SEQ_CLIENT_SYSTEM,
+                                          SND_SEQ_PORT_SYSTEM_TIMER);
                if (tmp < 0) {
                        perror("subscribe");
                        exit(1);
@@ -664,12 +564,9 @@ int main(int argc, char *argv[])
        }
        
        /* change pool size */
-       bzero(&pool,sizeof(pool));
-       pool.output_pool = WRITE_POOL_SIZE;
-       pool.input_pool = READ_POOL_SIZE;
-       pool.output_room = WRITE_POOL_SPACE;
-       tmp = snd_seq_set_client_pool(seq_handle, &pool);
-       if (tmp < 0) {
+       if (snd_seq_set_client_pool_output(seq_handle, WRITE_POOL_SIZE) < 0 ||
+           snd_seq_set_client_pool_input(seq_handle, READ_POOL_SIZE) < 0 ||
+           snd_seq_set_client_pool_output_room(seq_handle, WRITE_POOL_SPACE) < 0) {
                perror("pool");
                exit(1);
        }