summaryrefslogtreecommitdiff
path: root/lib/libsalsa/seq.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
committerIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
commit1058def8e7827e56ce4a70afb4aeacb5dc44148f (patch)
tree4495d23e7b54ab5700e3839081e797c1eafe0db9 /lib/libsalsa/seq.c
downloadoss4-1058def8e7827e56ce4a70afb4aeacb5dc44148f.tar.gz
Imported Upstream version 4.2-build2006upstream/4.2-build2006upstream
Diffstat (limited to 'lib/libsalsa/seq.c')
-rw-r--r--lib/libsalsa/seq.c2230
1 files changed, 2230 insertions, 0 deletions
diff --git a/lib/libsalsa/seq.c b/lib/libsalsa/seq.c
new file mode 100644
index 0000000..67f134b
--- /dev/null
+++ b/lib/libsalsa/seq.c
@@ -0,0 +1,2230 @@
+/*
+ * Copyright (c) 2004 by Hannu Savolainen < hannu@opensound.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <stdio.h>
+#include "local.h"
+
+static int nports = 0;
+
+typedef struct _snd_seq_port_subscribe
+{
+ int dummy;
+} snd_seq_port_subscribe_t;
+
+typedef struct _snd_seq_queue_tempo
+{
+ int dummy;
+} snd_seq_queue_tempo_t;
+
+typedef struct _snd_seq_system_info
+{
+ int dummy;
+} snd_seq_system_info_t;
+
+struct _snd_seq_remove_events
+{
+ int dummy;
+};
+
+struct _snd_seq_query_subscribe
+{
+ int dummy;
+};
+
+/**
+ * \brief Open the ALSA sequencer
+ *
+ * \param seqp Pointer to a snd_seq_t pointer. This pointer must be
+ * kept and passed to most of the other sequencer functions.
+ * \param name The sequencer's "name". This is \em not a name you make
+ * up for your own purposes; it has special significance to the ALSA
+ * library. Usually you need to pass \c "default" here.
+ * \param streams The read/write mode of the sequencer. Can be one of
+ * three values:
+ * - #SND_SEQ_OPEN_OUTPUT - open the sequencer for output only
+ * - #SND_SEQ_OPEN_INPUT - open the sequencer for input only
+ * - #SND_SEQ_OPEN_DUPLEX - open the sequencer for output and input
+ * \note Internally, these are translated to \c O_WRONLY, \c O_RDONLY and
+ * \c O_RDWR respectively and used as the second argument to the C library
+ * open() call.
+ * \param mode Optional modifier. Can be either 0, or
+ * #SND_SEQ_NONBLOCK, which will make read/write operations
+ * non-blocking. This can also be set later using #snd_seq_nonblock().
+ * \return 0 on success otherwise a negative error code
+ *
+* Creates a new handle and opens a connection to the kernel
+ * sequencer interface.
+ * After a client is created successfully, an event
+ * with #SND_SEQ_EVENT_CLIENT_START is broadcast to announce port.
+ *
+ * \sa snd_seq_open_lconf(), snd_seq_close(), snd_seq_type(), snd_seq_name(),
+ * snd_seq_nonblock(), snd_seq_client_id()
+ */
+int
+snd_seq_open (snd_seq_t ** seqp, const char *name, int streams, int mode)
+{
+ snd_seq_t *seq;
+ int err, oss_mode;
+ static int instance = 0;
+
+ char *fname = "/dev/midi", *envname = NULL, tmp[128];
+
+ ALIB_INIT ();
+
+ dbg_printf ("snd_seq_open(name='%s', streams=%d, mode=%x)\n", name, streams,
+ mode);
+
+ if (!alib_appcheck ())
+ return -ENODEV;
+
+ instance++;
+
+ sprintf (tmp, "%s_mididev%d", alib_appname, instance);
+
+ if ((envname = getenv (tmp)) != NULL)
+ {
+ fname = envname;
+ }
+#if 0
+ if (streams != 1)
+ {
+ fprintf (stderr, "salsa: snd_seq_open doesn't support streams=%d\n",
+ streams);
+ return -EIO;
+ }
+#endif
+
+ if ((seq = malloc (sizeof (*seq))) == NULL)
+ return -ENOMEM;
+
+ dbg_printf ("Created sequencer seq=%x\n", seq);
+
+ memset (seq, 0, sizeof (*seq));
+
+ switch (streams)
+ {
+ case SND_SEQ_OPEN_INPUT:
+ oss_mode = O_RDONLY;
+ dbg_printf ("Open SND_SEQ_OPEN_INPUT\n");
+ break;
+ case SND_SEQ_OPEN_OUTPUT:
+ oss_mode = O_WRONLY;
+ dbg_printf ("Open SND_SEQ_OPEN_OUTPUT\n");
+ break;
+ case SND_SEQ_OPEN_DUPLEX:
+ dbg_printf ("SND_SEQ_OPEN_DUPLEX\n");
+ oss_mode = O_RDWR;
+ break;
+
+ default:
+ fprintf (stderr, "snd_seq_open: Unknown stream %x\n", streams);
+ return -ENODEV;
+ }
+
+ if ((seq->fd = open (fname, oss_mode, 0)) == -1)
+ {
+ err = errno;
+ perror (fname);
+
+ if (envname == NULL)
+ {
+ fprintf (stderr,
+ "You can select another filename using environment variable %s_mididev%d\n",
+ alib_appname, instance);
+ }
+ return -err;
+ }
+
+ seq->streams = streams;
+ seq->oss_mode = oss_mode;
+
+ if (streams == SND_SEQ_OPEN_INPUT || streams == SND_SEQ_OPEN_DUPLEX)
+ {
+ seq->parser = midiparser_create (midiparser_callback, seq);
+ if (seq->parser == NULL)
+ {
+ fprintf (stderr, "libsalsa: Can't create MIDI parser\n");
+ return -ENODEV;
+ }
+ }
+
+ *seqp = seq;
+ return 0;
+}
+
+/**
+ * \brief Close the sequencer
+ * \param handle Handle returned from #snd_seq_open()
+ * \return 0 on success otherwise a negative error code
+ *
+ * Closes the sequencer client and releases its resources.
+ * After a client is closed, an event with
+ * #SND_SEQ_EVENT_CLIENT_EXIT is broadcast to announce port.
+ * The connection between other clients are disconnected.
+ * Call this just before exiting your program.
+ *
+ * \sa snd_seq_close()
+ */
+int
+snd_seq_close (snd_seq_t * seq)
+{
+ dbg_printf ("snd_seq_close(seq=%x)\n", seq);
+
+ close (seq->fd);
+ free (seq);
+}
+
+/**
+ * \brief Set nonblock mode
+ * \param seq sequencer handle
+ * \param nonblock 0 = block, 1 = nonblock mode
+ * \return 0 on success otherwise a negative error code
+ *
+ * Change the blocking mode of the given client.
+ * In block mode, the client falls into sleep when it fills the
+ * output memory pool with full events. The client will be woken up
+ * after a certain amount of free space becomes available.
+ *
+ * \sa snd_seq_open()
+ */
+int
+snd_seq_nonblock (snd_seq_t * seq, int nonblock)
+{
+ dbg_printf ("snd_seq_nonblock(seq=%x, nonblock=%d)\n", seq, nonblock);
+
+ seq->nonblock = nonblock;
+ return 0;
+}
+
+/**
+ * \brief create a sequencer port on the current client
+ * \param seq sequencer handle
+ * \param port port information for the new port
+ * \return 0 on success otherwise a negative error code
+ *
+ * Creates a sequencer port on the current client.
+ * The attributes of created port is specified in \a info argument.
+ *
+ * The client field in \a info argument is overwritten with the current client id.
+ * The port id to be created can be specified via #snd_seq_port_info_set_port_specified.
+ * You can get the created port id by reading the port pointer via #snd_seq_port_info_get_port.
+ *
+ * Each port has the capability bit-masks to specify the access capability
+ * of the port from other clients.
+ * The capability bit flags are defined as follows:
+ * - #SND_SEQ_PORT_CAP_READ Readable from this port
+ * - #SND_SEQ_PORT_CAP_WRITE Writable to this port.
+ * - #SND_SEQ_PORT_CAP_SYNC_READ For synchronization (not implemented)
+ * - #SND_SEQ_PORT_CAP_SYNC_WRITE For synchronization (not implemented)
+ * - #SND_SEQ_PORT_CAP_DUPLEX Read/write duplex access is supported
+ * - #SND_SEQ_PORT_CAP_SUBS_READ Read subscription is allowed
+ * - #SND_SEQ_PORT_CAP_SUBS_WRITE Write subscription is allowed
+ * - #SND_SEQ_PORT_CAP_SUBS_NO_EXPORT Subscription management from 3rd client is disallowed
+ *
+ * Each port has also the type bitmasks defined as follows:
+ * - #SND_SEQ_PORT_TYPE_SPECIFIC Hardware specific port
+ * - #SND_SEQ_PORT_TYPE_MIDI_GENERIC Generic MIDI device
+ * - #SND_SEQ_PORT_TYPE_MIDI_GM General MIDI compatible device
+ * - #SND_SEQ_PORT_TYPE_MIDI_GS GS compatible device
+ * - #SND_SEQ_PORT_TYPE_MIDI_XG XG compatible device
+ * - #SND_SEQ_PORT_TYPE_MIDI_MT32 MT-32 compatible device
+ * - #SND_SEQ_PORT_TYPE_SYNTH Synth device
+ * - #SND_SEQ_PORT_TYPE_DIRECT_SAMPLE Sampling device (supporting download)
+ * - #SND_SEQ_PORT_TYPE_SAMPLE Sampling device (sample can be downloaded at any time)
+ * - #SND_SEQ_PORT_TYPE_APPLICATION Application (sequencer/editor)
+ *
+ * A port may contain specific midi channels, midi voices and synth voices.
+ * These values could be zero as default.
+ *
+ * \sa snd_seq_delete_port(), snd_seq_get_port_info(),
+ * snd_seq_create_simple_port()
+ */
+int
+snd_seq_create_port (snd_seq_t * seq, snd_seq_port_info_t * port)
+{
+ dbg_printf ("snd_seq_create_port(seq=%x, port=%x)\n", seq, port);
+
+ port->port = nports++;
+ return 0;
+}
+
+/**
+ * \brief Get the client id
+ * \param seq sequencer handle
+ * \return the client id
+ *
+ * Returns the id of the specified client.
+ * If an error occurs, function returns the negative error code.
+ * A client id is necessary to inquiry or to set the client information.
+ * A user client is assigned from 128 to 191.
+ *
+ * \sa snd_seq_open()
+ */
+int
+snd_seq_client_id (snd_seq_t * seq)
+{
+ static int client_id = 128;
+
+ dbg_printf ("snd_seq_client_id(seq=%x)=%d\n", seq, client_id);
+
+ return client_id++;
+}
+
+/**
+ * \brief Get client id of a client_info container
+ * \param info client_info container
+ * \return client id
+ *
+ * \sa snd_seq_get_client_info(), snd_seq_client_info_set_client(), snd_seq_client_id()
+ */
+int
+snd_seq_client_info_get_client (const snd_seq_client_info_t * info)
+{
+ dbg_printf ("snd_seq_client_info_get_client()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Get client type of a client_info container
+ * \param info client_info container
+ * \return client type
+ *
+ * The client type is either #SEQ_CLIENT_TYPE_KERNEL or #SEQ_CLIENT_TYPE_USER
+ * for kernel or user client respectively.
+ *
+ * \sa snd_seq_get_client_info()
+ */
+snd_seq_client_type_t
+snd_seq_client_info_get_type (const snd_seq_client_info_t * info)
+{
+ dbg_printf ("snd_seq_client_info_get_type(infp=%x)\n", info);
+
+ return SND_SEQ_KERNEL_CLIENT; // TODO
+}
+
+/**
+ * \brief Set the client id of a client_info container
+ * \param info client_info container
+ * \param client client id
+ *
+ * \sa snd_seq_get_client_info(), snd_seq_client_info_get_client()
+ */
+void
+snd_seq_client_info_set_client (snd_seq_client_info_t * info, int client)
+{
+ dbg_printf ("snd_seq_client_info_set_client(%x, %d)\n", info, client);
+
+ info->client = client;
+}
+
+/**
+ * \brief get size of #snd_seq_client_info_t
+ * \return size in bytes
+ */
+size_t
+snd_seq_client_info_sizeof ()
+{
+ dbg_printf ("snd_seq_client_info_sizeof()\n");
+
+ return sizeof (snd_seq_client_info_t);
+}
+
+/**
+ * \brief retrieve an event from sequencer
+ * \param seq sequencer handle
+ * \param ev event pointer to be stored
+ * \return
+ *
+ * Obtains an input event from sequencer.
+ * The event is created via snd_seq_create_event(), and its pointer is stored on * ev argument.
+ *
+ * This function firstly receives the event byte-stream data from sequencer
+ * as much as possible at once. Then it retrieves the first event record
+ * and store the pointer on ev.
+ * By calling this function sequentially, events are extracted from the input buffer.
+ *
+ * If there is no input from sequencer, function falls into sleep
+ * in blocking mode until an event is received,
+ * or returns \c -EAGAIN error in non-blocking mode.
+ * Occasionally, this function may return \c -ENOSPC error.
+ * This means that the input FIFO of sequencer overran, and some events are
+ * lost.
+ * Once this error is returned, the input FIFO is cleared automatically.
+ *
+ * Function returns the byte size of remaining events on the input buffer
+ * if an event is successfully received.
+ * Application can determine from the returned value whether to call
+ * input once more or not.
+ *
+ * \sa snd_seq_event_input_pending(), snd_seq_drop_input()
+ */
+int
+snd_seq_event_input (snd_seq_t * seq, snd_seq_event_t ** evp)
+{
+ static snd_seq_event_t *ev;
+ unsigned char buf[256];
+ int i, l;
+
+ dbg_printf2 ("snd_seq_event_input(seq=%x)\n", seq);
+
+ while (1)
+ {
+
+ if (seq->nextevent < seq->nevents)
+ {
+ *evp = &seq->events[seq->nextevent++];
+
+ return (seq->nevents - seq->nextevent) * sizeof (snd_seq_event_t);
+ }
+
+ seq->nextevent = seq->nevents = 0;
+ memset (seq->events, 0, sizeof (seq->events));
+
+ // TODO Handling of nonblocking mode
+ if ((l = read (seq->fd, buf, sizeof (buf))) == -1)
+ return -errno;
+
+ midiparser_input_buf (seq->parser, buf, l);
+
+ }
+
+}
+
+/**
+ * \brief output an event directly to the sequencer NOT through output buffer
+ * \param seq sequencer handle
+ * \param ev event to be output
+ * \return the byte size sent to sequencer or a negative error code
+ *
+ * This function sends an event to the sequencer directly not through the
+ * output buffer. When the event is a variable length event, a temporary
+ * buffer is allocated inside alsa-lib and the data is copied there before
+ * actually sent.
+ *
+ * \sa snd_seq_event_output()
+ */
+int
+snd_seq_event_output_direct (snd_seq_t * seq, snd_seq_event_t * ev)
+{
+ int err;
+
+ dbg_printf3 ("snd_seq_event_output_direct()\n");
+
+ if ((err = convert_event (seq, ev)) < 0)
+ return err;
+ if ((err = snd_seq_drain_output (seq)) < 0)
+ return err;
+
+ return 0;
+}
+
+/**
+ * \brief (DEPRECATED) free an event
+ *
+ * In the former version, this function was used to
+ * release the event pointer which was allocated by snd_seq_event_input().
+ * In the current version, the event record is not allocated, so
+ * you don't have to call this function any more.
+ */
+int
+snd_seq_free_event (snd_seq_event_t * ev)
+{
+ return 0;
+}
+
+/**
+ * \brief obtain the current client information
+ * \param seq sequencer handle
+ * \param info the pointer to be stored
+ * \return 0 on success otherwise a negative error code
+ *
+ * Obtains the information of the current client stored on info.
+ * client and type fields are ignored.
+ *
+ * \sa snd_seq_get_any_client_info(), snd_seq_set_client_info(),
+ * snd_seq_query_next_client()
+ */
+int
+snd_seq_get_client_info (snd_seq_t * seq, snd_seq_client_info_t * info)
+{
+ dbg_printf ("snd_seq_get_client_info(seq=%x, info=%x)\n", seq, info);
+
+ return 0;
+}
+
+/**
+ * \brief query the next matching port
+ * \param seq sequencer handle
+ * \param info query pattern and result
+
+ * Queries the next matching port on the client specified in
+ * \a info argument.
+ * The search begins at the next port specified in
+ * port field of \a info argument.
+ * For finding the first port at a certain client, give -1.
+ *
+ * If a matching port is found, its attributes are stored on
+ * \a info and function returns zero.
+ * Otherwise, a negative error code is returned.
+ *
+ * \sa snd_seq_get_port_info()
+ */
+int
+snd_seq_query_next_port (snd_seq_t * seq, snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_query_next_port()\n");
+
+ return -EINVAL;
+}
+
+/**
+ * \brief Set the name of a client_info container
+ * \param info client_info container
+ * \param name name string
+ *
+ * \sa snd_seq_get_client_info(), snd_seq_client_info_get_name(),
+ * snd_seq_set_client_name()
+ */
+void
+snd_seq_client_info_set_name (snd_seq_client_info_t * info, const char *name)
+{
+ dbg_printf ("snd_seq_client_info_set_name(%s)\n", name);
+
+ strncpy (info->name, name, sizeof (info->name) - 1);
+ info->name[sizeof (info->name) - 1] = 0;
+}
+
+/**
+ * \brief subscribe a port connection
+ * \param seq sequencer handle
+ * \param sub subscription information
+ * \return 0 on success otherwise a negative error code
+ *
+ * Subscribes a connection between two ports.
+ * The subscription information is stored in sub argument.
+ *
+ * \sa snd_seq_get_port_subscription(), snd_seq_unsubscribe_port(),
+ * snd_seq_connect_from(), snd_seq_connect_to()
+ */
+int
+snd_seq_subscribe_port (snd_seq_t * seq, snd_seq_port_subscribe_t * sub)
+{
+ dbg_printf ("snd_seq_subscribe_port()\n");
+
+ return -EINVAL;
+}
+
+/**
+ * \brief get size of #snd_seq_port_subscribe_t
+ * \return size in bytes
+ */
+size_t
+snd_seq_port_subscribe_sizeof ()
+{
+ return sizeof (snd_seq_port_subscribe_t);
+}
+
+/**
+ * \brief Set sender address of a port_subscribe container
+ * \param info port_subscribe container
+ * \param addr sender address
+ *
+ * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_sender()
+ */
+void
+snd_seq_port_subscribe_set_sender (snd_seq_port_subscribe_t * info,
+ const snd_seq_addr_t * addr)
+{
+ dbg_printf ("snd_seq_port_subscribe_set_sender()\n");
+}
+
+/**
+ * \brief Set destination address of a port_subscribe container
+ * \param info port_subscribe container
+ * \param addr destination address
+ *
+ * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_dest()
+ */
+void
+snd_seq_port_subscribe_set_dest (snd_seq_port_subscribe_t * info,
+ const snd_seq_addr_t * addr)
+{
+ dbg_printf ("snd_seq_port_subscribe_set_dest()\n");
+}
+
+/**
+ * \brief Set the queue id of a port_subscribe container
+ * \param info port_subscribe container
+ * \param q queue id
+ *
+ * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_queue()
+ */
+void
+snd_seq_port_subscribe_set_queue (snd_seq_port_subscribe_t * info, int q)
+{
+ dbg_printf ("snd_seq_port_subscribe_set_queue()\n");
+}
+
+/**
+ * \brief Set the real-time mode of a port_subscribe container
+ * \param info port_subscribe container
+ * \param val non-zero to enable
+ *
+ * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_time_real()
+ */
+void
+snd_seq_port_subscribe_set_time_real (snd_seq_port_subscribe_t * info,
+ int val)
+{
+ dbg_printf ("snd_seq_port_subscribe_set_time_real()\n");
+}
+
+/**
+ * \brief Set the time-update mode of a port_subscribe container
+ * \param info port_subscribe container
+ * \param val non-zero to enable
+ *
+ * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_time_update()
+ */
+void
+snd_seq_port_subscribe_set_time_update (snd_seq_port_subscribe_t * info, int
+ val)
+{
+ dbg_printf ("snd_seq_port_subscribe_set_time_update()\n");
+}
+
+/*
+ * Port
+ */
+
+/**
+ * \brief get size of #snd_seq_port_info_t
+ * \return size in bytes
+ */
+size_t
+snd_seq_port_info_sizeof ()
+{
+ return sizeof (snd_seq_port_info_t);
+}
+
+/**
+ * \brief Get the capability bits of a port_info container
+ * \param info port_info container
+ * \return capability bits
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_capability()
+ */
+unsigned int
+snd_seq_port_info_get_capability (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_capability()\n");
+
+ return info->capability;
+}
+
+/**
+ * \brief Get client/port address of a port_info container
+ * \param info port_info container
+ * \return client/port address pointer
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_addr()
+ */
+const snd_seq_addr_t *
+snd_seq_port_info_get_addr (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_addr(info=%x)\n", info);
+
+ return NULL; // TODO
+}
+
+/**
+ * \brief set the capability bits of a port_info container
+ * \param info port_info container
+ * \param capability capability bits
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_get_capability()
+ */
+void
+snd_seq_port_info_set_capability (snd_seq_port_info_t * info,
+ unsigned int capability)
+{
+ dbg_printf ("snd_seq_port_info_set_capability()\n");
+}
+
+/**
+ * \brief Set the port-specified mode of a port_info container
+ * \param info port_info container
+ * \param val non-zero if specifying the port id at creation
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_get_port_specified()
+ */
+void
+snd_seq_port_info_set_port_specified (snd_seq_port_info_t * info, int val)
+{
+ dbg_printf ("snd_seq_port_info_set_port_specified()\n");
+}
+
+/**
+ * \brief Get the midi channels of a port_info container
+ * \param info port_info container
+ * \return number of midi channels (default 0)
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_midi_channels()
+ */
+int
+snd_seq_port_info_get_midi_channels (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_midi_channels(info=%x)=%d\n",
+ info, info->midi_channels);
+
+ return info->midi_channels;
+}
+
+/**
+ * \brief set the midi channels of a port_info container
+ * \param info port_info container
+ * \param channels midi channels (default 0)
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_get_midi_channels()
+ */
+void
+snd_seq_port_info_set_midi_channels (snd_seq_port_info_t * info, int channels)
+{
+ dbg_printf ("snd_seq_port_info_set_midi_channels(info=%x, channels=%d)\n",
+ info, channels);
+ info->midi_channels = channels;
+}
+
+/**
+ * \brief Get the queue id to update timestamps
+ * \param info port_info container
+ * \return the queue id to get the timestamps
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_timestamp_queue()
+ */
+int
+snd_seq_port_info_get_timestamp_queue (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_timestamp_queue(info=%x)\n", info);
+
+ return 0; // TODO
+}
+
+/**
+ * \brief Set the queue id for timestamping
+ * \param info port_info container
+ * \param queue the queue id to get timestamps
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_get_timestamp_queue()
+ */
+void
+snd_seq_port_info_set_timestamp_queue (snd_seq_port_info_t * info, int queue)
+{
+ dbg_printf ("snd_seq_port_info_set_timestamp_queue(info=%x, queue=%d)\n",
+ info, queue);
+
+ // TODO
+}
+
+/**
+ * \brief Get whether the time-stamping of the given port is real-time mode
+ * \param info port_info container
+ * \return 1 if the time-stamping is in the real-time mode
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_timestamp_real()
+ */
+int
+snd_seq_port_info_get_timestamp_real (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_timestamp_real(info=%x)\n", info);
+
+ return 0; // TODO
+}
+
+/**
+ * \brief Set whether the timestime is updated in the real-time mode
+ * \param info port_info container
+ * \param enable non-zero if updating the timestamps in real-time mode
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_get_timestamp_real()
+ */
+void
+snd_seq_port_info_set_timestamp_real (snd_seq_port_info_t * info, int enable)
+{
+ dbg_printf ("snd_seq_port_info_set_timestamp_real(infp=%x, enable=%d)\n",
+ info, enable);
+}
+
+/**
+ * \brief Get the time-stamping mode of the given port in a port_info container * \param info port_info container
+ * \return 1 if the port updates timestamps of incoming events
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_timestamping()
+ */
+int
+snd_seq_port_info_get_timestamping (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_timestamping(info=%x)\n", info);
+
+ return 0; // TODO
+}
+
+/**
+ * \brief Set the time-stamping mode of the given port
+ * \param info port_info container
+ * \param enable non-zero if updating the timestamps of incoming events
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_get_timestamping()
+ */
+void
+snd_seq_port_info_set_timestamping (snd_seq_port_info_t * info, int enable)
+{
+ dbg_printf ("snd_seq_port_info_set_timestamping(info=%x, enable=%d)\n",
+ info, enable);
+
+ // TODO
+}
+
+/**
+ * \brief Set the name of a port_info container
+ * \param info port_info container
+ * \param name name string
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_get_name()
+ */
+void
+snd_seq_port_info_set_name (snd_seq_port_info_t * info, const char *name)
+{
+ dbg_printf ("snd_seq_port_info_set_name()\n");
+
+ strncpy (info->name, name, sizeof (info->name));
+}
+
+/**
+ * \brief Get the name of a port_info container
+ * \param info port_info container
+ * \return name string
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_name()
+ */
+const char *
+snd_seq_port_info_get_name (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_name()\n");
+
+ return "Port Name";
+}
+
+/**
+ * \brief Get port id of a port_info container
+ * \param info port_info container
+ * \return port id
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_port()
+ */
+int
+snd_seq_port_info_get_port (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_port()\n");
+
+ return -EIO;
+}
+
+/**
+ * \brief Get the type bits of a port_info container
+ * \param info port_info container
+ * \return port type bits
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_type()
+ */
+unsigned int
+snd_seq_port_info_get_type (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_type()\n");
+
+ return info->type;
+}
+
+/**
+ * \brief Set the client id of a port_info container
+ * \param info port_info container
+ * \param client client id
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_get_client()
+ */
+void
+snd_seq_port_info_set_client (snd_seq_port_info_t * info, int client)
+{
+ dbg_printf ("snd_seq_port_info_set_client()\n");
+}
+
+/**
+ * \brief Set the port id of a port_info container
+ * \param info port_info container
+ * \param port port id
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_get_port()
+ */
+void
+snd_seq_port_info_set_port (snd_seq_port_info_t * info, int port)
+{
+ dbg_printf ("snd_seq_port_info_set_port()\n");
+}
+
+/**
+ * \brief query the next matching client
+ * \param seq sequencer handle
+ * \param info query pattern and result
+ *
+ * Queries the next matching client with the given condition in
+ * info argument.
+ * The search begins at the client with an id one greater than
+ * client field in info.
+ * If name field in info is not empty, the client name is compared.
+ * If a matching client is found, its attributes are stored o
+ * info and returns zero.
+ * Otherwise returns a negative error code.
+ *
+ * \sa snd_seq_get_any_client_info()
+ */
+int
+snd_seq_query_next_client (snd_seq_t * seq, snd_seq_client_info_t * info)
+{
+ dbg_printf ("snd_seq_query_next_client()\n");
+
+ return -EIO;
+}
+
+/**
+ * \brief set the current client information
+ * \param seq sequencer handle
+ * \param info the client info data to set
+ * \return 0 on success otherwise a negative error code
+ *
+ * Obtains the information of the current client stored on info.
+ * client and type fields are ignored.
+ *
+ * \sa snd_seq_get_client_info()
+ */
+int
+snd_seq_set_client_info (snd_seq_t * seq, snd_seq_client_info_t * info)
+{
+ dbg_printf ("snd_seq_set_client_info(seq=%x, info=%x)\n", seq, info);
+
+ if (*info->name)
+ {
+ strcpy (seq->name, info->name);
+ ioctl (seq->fd, SNDCTL_SETNAME, seq->name);
+ ioctl (seq->fd, SNDCTL_SETSONG, seq->name);
+ }
+
+ return 0;
+}
+
+/**
+ * \brief check events in input buffer
+ * \return the byte size of remaining input events on input buffer.
+ *
+ * If events remain on the input buffer of user-space, function returns
+ * the total byte size of events on it.
+ * If fetch_sequencer argument is non-zero,
+ * this function checks the presence of events on sequencer FIFO
+ * When events exist, they are transferred to the input buffer,
+ * and the number of received events are returned.
+ * If fetch_sequencer argument is zero and
+ * no events remain on the input buffer, function simply returns zero.
+ *
+ * \sa snd_seq_event_input()
+ */
+int
+snd_seq_event_input_pending (snd_seq_t * seq, int fetch_sequencer)
+{
+ dbg_printf ("snd_seq_event_input_pending()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Get poll descriptors
+ * \param seq sequencer handle
+ * \param pfds array of poll descriptors
+ * \param space space in the poll descriptor array
+ * \param events polling events to be checked (\c POLLIN and \c POLLOUT)
+ * \return count of filled descriptors
+ *
+ * Get poll descriptors assigned to the sequencer handle.
+ * Since a sequencer handle can duplex streams, you need to set which direction(s)
+ * is/are polled in \a events argument. When \c POLLIN bit is specified,
+ * the incoming events to the ports are checked.
+ *
+ * To check the returned poll-events, call #snd_seq_poll_descriptors_revents()
+ * instead of reading the pollfd structs directly.
+ *
+ * \sa snd_seq_poll_descriptors_count(), snd_seq_poll_descriptors_revents()
+ */
+int
+snd_seq_poll_descriptors (snd_seq_t * seq, struct pollfd *pfds,
+ unsigned int space, short events)
+{
+ dbg_printf ("snd_seq_poll_descriptors(seq=%x)\n", seq);
+
+ pfds->fd = seq->fd;
+ pfds->events = 0;
+ pfds->revents = 0;
+
+ if (seq->oss_mode == O_WRONLY || seq->oss_mode == O_RDWR)
+ pfds->events = POLLOUT;
+ if (seq->oss_mode == O_RDONLY || seq->oss_mode == O_RDWR)
+ pfds->events = POLLIN;
+
+ return 1;
+}
+
+
+/**
+ * \brief Returns the number of poll descriptors
+ * \param seq sequencer handle
+ * \param events the poll events to be checked (\c POLLIN and \c POLLOUT)
+ * \return the number of poll descriptors.
+ *
+ * Get the number of poll descriptors. The polling events to be checked
+ * can be specified by the second argument. When both input and output
+ * are checked, pass \c POLLIN|POLLOUT
+ *
+ * \sa snd_seq_poll_descriptors()
+ */
+int
+snd_seq_poll_descriptors_count (snd_seq_t * seq, short events)
+{
+ dbg_printf ("snd_seq_poll_descriptors_count(seq=%x, events=%x)\n",
+ seq, events);
+ return 1;
+}
+
+/**
+ * \brief create a queue
+ * \param seq sequencer handle
+ * \param info queue information to initialize
+ * \return the queue id (zero or positive) on success otherwise a negative error code
+ *
+ * \sa snd_seq_alloc_queue()
+ */
+int
+snd_seq_create_queue (snd_seq_t * seq, snd_seq_queue_info_t * info)
+{
+ dbg_printf ("snd_seq_create_queue()\n");
+
+ return 0;
+}
+
+/**
+ * \brief simple subscription (w/o exclusive & time conversion)
+ * \param myport the port id as sender
+ * \param dest_client destination client id
+ * \param dest_port destination port id
+ * \return 0 on success or negative error code
+ *
+ * Connect from the given receiver port in the current client
+ * to the given destination client:port.
+ *
+ * \sa snd_seq_subscribe_port(), snd_seq_disconnect_to()
+ */
+int
+snd_seq_connect_to (snd_seq_t * seq, int myport, int dest_client,
+ int dest_port)
+{
+ dbg_printf ("snd_seq_connect_to(%d->%d/%d)\n", myport, dest_client,
+ dest_port);
+
+ return 0;
+}
+
+/**
+ * \brief simple subscription (w/o exclusive & time conversion)
+ * \param myport the port id as receiver
+ * \param src_client sender client id
+ * \param src_port sender port id
+ * \return 0 on success or negative error code
+ *
+ * Connect from the given sender client:port to the given destination port in the
+ * current client.
+ *
+ * \sa snd_seq_subscribe_port(), snd_seq_disconnect_from()
+ */
+int
+snd_seq_connect_from (snd_seq_t * seq, int myport, int src_client,
+ int src_port)
+{
+ dbg_printf
+ ("snd_seq_connect_from(seq=%x, myport=%d, src_client=%d, src_port=%d)\n",
+ seq, myport, src_client, src_port);
+
+ return 0;
+}
+
+/**
+ * \brief queue controls - start/stop/continue
+ * \param seq sequencer handle
+ * \param q queue id to control
+ * \param type event type
+ * \param value event value
+ * \param ev event instance
+ *
+ * This function sets up general queue control event and sends it.
+ * To send at scheduled time, set the schedule in \a ev.
+ * If \a ev is NULL, the event is composed locally and sent immediately
+ * to the specified queue. In any cases, you need to call #snd_seq_drain_output()
+ * appropriately to feed the event.
+ *
+ * \sa snd_seq_alloc_queue()
+ */
+int
+snd_seq_control_queue (snd_seq_t * seq, int q, int type, int value,
+ snd_seq_event_t * ev)
+{
+ dbg_printf ("snd_seq_control_queue()\n");
+
+ return 0;
+}
+
+/**
+ * \brief drain output buffer to sequencer
+ * \param seq sequencer handle
+ * \return 0 when all events are drained and sent to sequencer.
+ * When events still remain on the buffer, the byte size of remaining
+ * events are returned. On error a negative error code is returned.
+ *
+ * This function drains all pending events on the output buffer.
+ * The function returns immediately after the events are sent to the queues
+ * regardless whether the events are processed or not.
+ * To get synchronization with the all event processes, use
+ * #snd_seq_sync_output_queue() after calling this function.
+ *
+ * \sa snd_seq_event_output(), snd_seq_sync_output_queue()
+ */
+int
+snd_seq_drain_output (snd_seq_t * seq)
+{
+ dbg_printf3 ("snd_seq_drain_output(seq=%x)\n", seq);
+
+ return 0;
+}
+
+
+/**
+ * \brief remove all events on output buffer
+ * \param seq sequencer handle
+ *
+ * Removes all events on both user-space output buffer and
+ * output memory pool on kernel.
+ *
+ * \sa snd_seq_drain_output(), snd_seq_drop_output_buffer(), snd_seq_remove_events()
+ */
+int
+snd_seq_drop_output (snd_seq_t * seq)
+{
+ dbg_printf ("snd_seq_drop_output()\n");
+
+ return 0;
+}
+
+/**
+ * \brief output an event
+ * \param seq sequencer handle
+ * \param ev event to be output
+ * \return the number of remaining events or a negative error code
+ *
+ * An event is once expanded on the output buffer.
+ * The output buffer will be drained automatically if it becomes full.
+ *
+ * If events remain unprocessed on output buffer before drained,
+ * the size of total byte data on output buffer is returned.
+ * If the output buffer is empty, this returns zero.
+ *
+ * \sa snd_seq_event_output_direct(), snd_seq_event_output_buffer(),
+ * snd_seq_event_output_pending(), snd_seq_drain_output(),
+ * snd_seq_drop_output(), snd_seq_extract_output(),
+ * snd_seq_remove_events()
+ */
+int
+snd_seq_event_output (snd_seq_t * seq, snd_seq_event_t * ev)
+{
+ dbg_printf3 ("snd_seq_event_output(seq=%x, ev=%x)\n", seq, ev);
+
+ return convert_event (seq, ev);
+}
+
+/**
+ * \brief delete the specified queue
+ * \param seq sequencer handle
+ * \param q queue id to delete
+ * \return 0 on success otherwise a negative error code
+ *
+ * \sa snd_seq_alloc_queue()
+ */
+int
+snd_seq_free_queue (snd_seq_t * seq, int q)
+{
+ dbg_printf ("snd_seq_free_queue()\n");
+
+ return 0;
+}
+
+/**
+ * \brief obtain the information of the given client
+ * \param seq sequencer handle
+ * \param client client id
+ * \param info the pointer to be stored
+ * \return 0 on success otherwise a negative error code
+ *
+ * Obtains the information of the client with a client id specified by
+ * info argument.
+ * The obtained information is written on info parameter.
+ *
+ * \sa snd_seq_get_client_info()
+ */
+int
+snd_seq_get_any_client_info (snd_seq_t * seq, int client,
+ snd_seq_client_info_t * info)
+{
+ dbg_printf ("snd_seq_get_any_client_info()\n");
+
+ strcpy (info->name, seq->name);
+
+ return 0;
+}
+
+/**
+ * \brief obtain the information of a port on an arbitrary client
+ * \param seq sequencer handle
+ * \param client client id to get
+ * \param port port id to get
+ * \param info pointer information returns
+ * \return 0 on success otherwise a negative error code
+ *
+ * \sa snd_seq_get_port_info()
+ */
+int
+snd_seq_get_any_port_info (snd_seq_t * seq, int client, int port,
+ snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_get_any_port_info()\n");
+
+ return 0;
+}
+
+/**
+ * \brief allocate an empty #snd_seq_port_info_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_seq_port_info_malloc (snd_seq_port_info_t ** ptr)
+{
+ snd_seq_port_info_t *p;
+
+ dbg_printf ("snd_seq_port_info_malloc()\n");
+
+ if ((p = malloc (sizeof (*p))) == NULL)
+ return -ENOMEM;
+
+ *ptr = p;
+
+ return 0;
+}
+
+/**
+ * \brief frees a previously allocated #snd_seq_port_info_t
+ * \param pointer to object to free
+ */
+void
+snd_seq_port_info_free (snd_seq_port_info_t * obj)
+{
+ free (obj);
+}
+
+/**
+ * \brief allocate an empty #snd_seq_queue_tempo_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_seq_queue_tempo_malloc (snd_seq_queue_tempo_t ** ptr)
+{
+ assert (ptr);
+ *ptr = calloc (1, sizeof (snd_seq_queue_tempo_t));
+ dbg_printf ("snd_seq_queue_tempo_malloc()=%x\n", *ptr);
+ if (!*ptr)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * \brief frees a previously allocated #snd_seq_queue_tempo_t
+ * \param pointer to object to free
+ */
+void
+snd_seq_queue_tempo_free (snd_seq_queue_tempo_t * obj)
+{
+ dbg_printf ("snd_seq_queue_tempo_free(%x)\n", obj);
+ free (obj);
+}
+
+/**
+ * \brief Set the ppq of a queue_status container
+ * \param info queue_status container
+ * \param ppq ppq value
+ *
+ * \sa snd_seq_get_queue_tempo()
+ */
+void
+snd_seq_queue_tempo_set_ppq (snd_seq_queue_tempo_t * info, int ppq)
+{
+ dbg_printf ("snd_seq_queue_tempo_set_ppq(info=%x, %d)\n", info, ppq);
+}
+
+/**
+ * \brief Set the tempo of a queue_status container
+ * \param info queue_status container
+ * \param tempo tempo value
+ *
+ * \sa snd_seq_get_queue_tempo()
+ */
+void
+snd_seq_queue_tempo_set_tempo (snd_seq_queue_tempo_t * info,
+ unsigned int tempo)
+{
+ dbg_printf ("snd_seq_queue_tempo_set_tempo(info=%x, %d)\n", info, tempo);
+}
+
+/**
+ * \brief get size of #snd_seq_queue_tempo_t
+ * \return size in bytes
+ */
+size_t
+snd_seq_queue_tempo_sizeof ()
+{
+ return sizeof (snd_seq_queue_tempo_t);
+}
+
+/**
+ * \brief set the queue timer information
+ * \param seq sequencer handle
+ * \param q queue id to change the timer
+ * \param timer timer information
+ * \return 0 on success otherwise a negative error code
+ *
+ * \sa snd_seq_get_queue_timer()
+ */
+int
+snd_seq_set_queue_timer (snd_seq_t * seq, int q,
+ snd_seq_queue_timer_t * timer)
+{
+ dbg_printf ("snd_seq_get_queue_timer(seq=%x, q=%d, timer=%X)\n", seq, q,
+ timer);
+ return -ENXIO; // TODO
+}
+
+
+/**
+ * \brief Opens a new connection to the timer query interface.
+ * \param timer Returned handle (NULL if not wanted)
+ * \param name ASCII identifier of the RawMidi handle
+ * \param mode Open mode
+ * \return 0 on success otherwise a negative error code
+ *
+ * Opens a new connection to the RawMidi interface specified with
+ * an ASCII identifier and mode.
+ */
+int
+snd_timer_query_open (snd_timer_query_t ** timer, const char *name, int mode)
+{
+ dbg_printf ("snd_timer_query_open(name=%s, mode=%x)\n", name, mode);
+ return -ENXIO; // TODO
+}
+
+/**
+ * \brief obtain the current tempo of the queue
+ * \param seq sequencer handle
+ * \param q queue id to be queried
+ * \param tempo pointer to store the current tempo
+ * \return 0 on success otherwise a negative error code
+ *
+ * \sa snd_seq_set_queue_tempo()
+ */
+int
+snd_seq_get_queue_tempo (snd_seq_t * seq, int q,
+ snd_seq_queue_tempo_t * tempo)
+{
+ dbg_printf ("snd_seq_get_queue_tempo(seq=%x, q=%d, tempo=%x)\n", seq, q,
+ tempo);
+
+ return 0;
+}
+
+/**
+ * \brief allocate an empty #snd_seq_client_info_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_seq_client_info_malloc (snd_seq_client_info_t ** ptr)
+{
+ dbg_printf ("snd_seq_client_info_malloc()\n");
+
+ *ptr = malloc (sizeof (snd_seq_client_info_t));
+ if (!*ptr)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * \brief frees a previously allocated #snd_seq_client_info_t
+ * \param pointer to object to free
+ */
+void
+snd_seq_client_info_free (snd_seq_client_info_t * obj)
+{
+ dbg_printf ("snd_seq_client_info_free()\n");
+
+ free (obj);
+}
+
+/**
+ * \brief Get the name of a client_info container
+ * \param info client_info container
+ * \return name string
+ *
+ * \sa snd_seq_get_client_info(), snd_seq_client_info_set_name()
+ */
+const char *
+snd_seq_client_info_get_name (snd_seq_client_info_t * info)
+{
+ dbg_printf ("snd_seq_client_info_get_name()\n");
+ return "OSS seq client";
+}
+
+/**
+ * \brief Get the number of opened ports of a client_info container
+ * \param info client_info container
+ * \return number of opened ports
+ *
+ * \sa snd_seq_get_client_info()
+ */
+int
+snd_seq_client_info_get_num_ports (const snd_seq_client_info_t * info)
+{
+ dbg_printf ("snd_seq_client_info_get_num_ports()\n");
+
+ return 1;
+}
+
+/**
+ * \brief Get size of #snd_seq_system_info_t
+ * \return size in bytes
+ */
+size_t
+snd_seq_system_info_sizeof ()
+{
+ return sizeof (snd_seq_system_info_t);
+}
+
+
+/**
+ * \brief Allocate an empty #snd_seq_system_info_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_seq_system_info_malloc (snd_seq_system_info_t ** ptr)
+{
+ dbg_printf ("snd_seq_system_info_malloc()\n");
+
+ *ptr = malloc (sizeof (snd_seq_system_info_t));
+ if (*ptr == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * \brief Frees a previously allocated #snd_seq_system_info_t
+ * \param pointer to object to free
+ */
+void
+snd_seq_system_info_free (snd_seq_system_info_t * obj)
+{
+ free (obj);
+}
+
+/**
+ * \brief obtain the sequencer system information
+ * \param seq sequencer handle
+ * \param info the pointer to be stored
+ * \return 0 on success otherwise a negative error code
+ *
+ * Stores the global system information of ALSA sequencer system.
+ * The returned data contains
+ * the maximum available numbers of queues, clients, ports and channels.
+ */
+int
+snd_seq_system_info (snd_seq_t * seq, snd_seq_system_info_t * info)
+{
+ dbg_printf ("snd_seq_system_info()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Get maximum number of clients
+ * \param info #snd_seq_system_info_t container
+ * \return maximum number of clients
+ *
+ * \sa snd_seq_system_info()
+ */
+int
+snd_seq_system_info_get_clients (const snd_seq_system_info_t * info)
+{
+ dbg_printf ("snd_seq_system_info_get_clients()\n");
+
+ return 4;
+}
+
+/**
+ * \brief Get maximum number of queues
+ * \param info #snd_seq_system_info_t container
+ * \return maximum number of queues
+ *
+ * \sa snd_seq_system_info()
+ */
+int
+snd_seq_system_info_get_queues (const snd_seq_system_info_t * info)
+{
+ dbg_printf ("snd_seq_system_info_get_queues(info=%x)\n", info);
+
+ return 1; // TODO
+}
+
+/**
+ * \brief Get maximum number of ports
+ * \param info #snd_seq_system_info_t container
+ * \return maximum number of ports
+ *
+ * \sa snd_seq_system_info()
+ */
+int
+snd_seq_system_info_get_ports (const snd_seq_system_info_t * info)
+{
+ dbg_printf ("snd_seq_system_info_get_ports()\n");
+
+ return 4;
+}
+
+/**
+ * \brief allocate a queue with the specified name
+ * \param seq sequencer handle
+ * \param name the name of the new queue
+ * \return the queue id (zero or positive) on success otherwise a negative error code
+ *
+ * \sa snd_seq_alloc_queue()
+ */
+int
+snd_seq_alloc_named_queue (snd_seq_t * seq, const char *name)
+{
+ dbg_printf ("snd_seq_alloc_named_queue(seq=%x, name=%s)\n", seq, name);
+
+ return 0;
+}
+
+
+/**
+ * \brief Get client id of a port_info container
+ * \param info port_info container
+ * \return client id
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_client()
+ */
+int
+snd_seq_port_info_get_client (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_client()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Get the port-specified mode of a port_info container
+ * \param info port_info container
+ * \return 1 if port id is specified at creation
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_set_port_specified()
+ */
+int
+snd_seq_port_info_get_port_specified (const snd_seq_port_info_t * info)
+{
+ dbg_printf ("snd_seq_port_info_get_port_specified()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Get the type bits of a port_info container
+ * \param info port_info container
+ * \return port type bits
+ *
+ * \sa snd_seq_get_port_info(), snd_seq_port_info_get_type()
+ */
+void
+snd_seq_port_info_set_type (snd_seq_port_info_t * info, unsigned int type)
+{
+ dbg_printf ("snd_seq_port_info_set_type(%u)\n", type);
+}
+
+
+/**
+ * \brief Get the ppq of a queue_status container
+ * \param info queue_status container
+ * \return ppq value
+ *
+ * \sa snd_seq_get_queue_tempo()
+ */
+int
+snd_seq_queue_tempo_get_ppq (const snd_seq_queue_tempo_t * info)
+{
+ dbg_printf ("snd_seq_queue_tempo_get_ppq()\n");
+
+ return 0;
+}
+
+
+/**
+ * \brief Get the tempo of a queue_status container
+ * \param info queue_status container
+ * \return tempo value
+ *
+ * \sa snd_seq_get_queue_tempo()
+ */
+unsigned int
+snd_seq_queue_tempo_get_tempo (const snd_seq_queue_tempo_t * info)
+{
+ dbg_printf ("snd_seq_queue_tempo_get_tempo()\n");
+
+ return 0;
+}
+
+/**
+ * \brief set the tempo of the queue
+ * \param seq sequencer handle
+ * \param q queue id to change the tempo
+ * \param tempo tempo information
+ * \return 0 on success otherwise a negative error code
+ *
+ * \sa snd_seq_get_queue_tempo()
+ */
+int
+snd_seq_set_queue_tempo (snd_seq_t * seq, int q,
+ snd_seq_queue_tempo_t * tempo)
+{
+ dbg_printf ("snd_seq_set_queue_tempo(seq=%x, q=%d, tempo=%x)\n", seq, q,
+ tempo);
+
+ return 0;
+}
+
+/**
+ * \brief allocate a queue
+ * \param seq sequencer handle
+ * \return the queue id (zero or positive) on success otherwise a negative error code
+ *
+ * \sa snd_seq_alloc_named_queue(), snd_seq_create_queue(), snd_seq_free_queue(),
+ * snd_seq_get_queue_info()
+ */
+int
+snd_seq_alloc_queue (snd_seq_t * seq)
+{
+ static int queue_num = 0;
+ dbg_printf ("snd_seq_alloc_queue(seq=%x)=%d\n", seq, queue_num);
+
+ return queue_num++;
+}
+
+#define FIXED_EV(x) (_SND_SEQ_TYPE(SND_SEQ_EVFLG_FIXED) | _SND_SEQ_TYPE(x))
+
+/** Event types conversion array */
+const unsigned int snd_seq_event_types[256] = {
+ [SND_SEQ_EVENT_SYSTEM...SND_SEQ_EVENT_RESULT]
+ = FIXED_EV (SND_SEQ_EVFLG_RESULT),
+ [SND_SEQ_EVENT_NOTE]
+ =
+ FIXED_EV (SND_SEQ_EVFLG_NOTE) |
+ _SND_SEQ_TYPE_OPT (SND_SEQ_EVFLG_NOTE_TWOARG),
+ [SND_SEQ_EVENT_NOTEON...SND_SEQ_EVENT_KEYPRESS] =
+ FIXED_EV (SND_SEQ_EVFLG_NOTE),
+ [SND_SEQ_EVENT_CONTROLLER...SND_SEQ_EVENT_REGPARAM] =
+ FIXED_EV (SND_SEQ_EVFLG_CONTROL),
+ [SND_SEQ_EVENT_START...SND_SEQ_EVENT_STOP] = FIXED_EV (SND_SEQ_EVFLG_QUEUE),
+ [SND_SEQ_EVENT_SETPOS_TICK]
+ =
+ FIXED_EV (SND_SEQ_EVFLG_QUEUE) |
+ _SND_SEQ_TYPE_OPT (SND_SEQ_EVFLG_QUEUE_TICK),
+ [SND_SEQ_EVENT_SETPOS_TIME] =
+ FIXED_EV (SND_SEQ_EVFLG_QUEUE) |
+ _SND_SEQ_TYPE_OPT (SND_SEQ_EVFLG_QUEUE_TIME),
+ [SND_SEQ_EVENT_TEMPO...SND_SEQ_EVENT_SYNC_POS] =
+ FIXED_EV (SND_SEQ_EVFLG_QUEUE) |
+ _SND_SEQ_TYPE_OPT (SND_SEQ_EVFLG_QUEUE_VALUE),
+ [SND_SEQ_EVENT_TUNE_REQUEST...SND_SEQ_EVENT_SENSING] =
+ FIXED_EV (SND_SEQ_EVFLG_NONE),
+ [SND_SEQ_EVENT_ECHO...SND_SEQ_EVENT_OSS] =
+ FIXED_EV (SND_SEQ_EVFLG_RAW) | FIXED_EV (SND_SEQ_EVFLG_SYSTEM),
+ [SND_SEQ_EVENT_CLIENT_START...SND_SEQ_EVENT_PORT_CHANGE] =
+ FIXED_EV (SND_SEQ_EVFLG_MESSAGE),
+ [SND_SEQ_EVENT_PORT_SUBSCRIBED...SND_SEQ_EVENT_PORT_UNSUBSCRIBED] =
+ FIXED_EV (SND_SEQ_EVFLG_CONNECTION),
+ [SND_SEQ_EVENT_USR0...SND_SEQ_EVENT_USR9] =
+ FIXED_EV (SND_SEQ_EVFLG_RAW) | FIXED_EV (SND_SEQ_EVFLG_USERS),
+ [SND_SEQ_EVENT_SYSEX...SND_SEQ_EVENT_BOUNCE] =
+ _SND_SEQ_TYPE (SND_SEQ_EVFLG_VARIABLE),
+ [SND_SEQ_EVENT_USR_VAR0...SND_SEQ_EVENT_USR_VAR4] =
+ _SND_SEQ_TYPE (SND_SEQ_EVFLG_VARIABLE) |
+ _SND_SEQ_TYPE (SND_SEQ_EVFLG_USERS),
+ [SND_SEQ_EVENT_NONE] = FIXED_EV (SND_SEQ_EVFLG_NONE),
+};
+
+/**
+ * \brief obtain the running state of the queue
+ * \param seq sequencer handle
+ * \param q queue id to query
+ * \param status pointer to store the current status
+ * \return 0 on success otherwise a negative error code
+ *
+ * Obtains the running state of the specified queue q.
+ */
+int
+snd_seq_get_queue_status (snd_seq_t * seq, int q,
+ snd_seq_queue_status_t * status)
+{
+ dbg_printf ("snd_seq_get_queue_status(seq=%x. q=%d)\n", seq, q);
+
+ return 0;
+}
+
+/**
+ * \brief allocate an empty #snd_seq_queue_status_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_seq_queue_status_malloc (snd_seq_queue_status_t ** ptr)
+{
+ dbg_printf ("snd_seq_queue_status_malloc()\n");
+ *ptr = calloc (1, sizeof (snd_seq_queue_status_t));
+ dbg_printf ("snd_seq_queue_status_malloc()=%x\n", *ptr);
+ if (!*ptr)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * \brief frees a previously allocated #snd_seq_queue_status_t
+ * \param pointer to object to free
+ */
+void
+snd_seq_queue_status_free (snd_seq_queue_status_t * obj)
+{
+ dbg_printf ("snd_seq_queue_status_free(%x)\n", obj);
+
+ free (obj);
+}
+
+/**
+ * \brief Get the tick time of a queue_status container
+ * \param info queue_status container
+ * \return tick time
+ *
+ * \sa snd_seq_get_queue_status()
+ */
+snd_seq_tick_time_t
+snd_seq_queue_status_get_tick_time (const snd_seq_queue_status_t * info)
+{
+ dbg_printf ("snd_seq_queue_status_get_tick_time(info=%x)\n", info);
+
+ return 0;
+}
+
+/**
+ * \brief get size of #snd_seq_remove_events_t
+ * \return size in bytes
+ */
+size_t
+snd_seq_remove_events_sizeof ()
+{
+ return sizeof (snd_seq_remove_events_t);
+}
+
+/**
+ * \brief allocate an empty #snd_seq_remove_events_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_seq_remove_events_malloc (snd_seq_remove_events_t ** ptr)
+{
+ assert (ptr);
+ *ptr = calloc (1, sizeof (snd_seq_remove_events_t));
+ dbg_printf ("snd_seq_remove_events_malloc()=%x\n", *ptr);
+ if (!*ptr)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * \brief frees a previously allocated #snd_seq_remove_events_t
+ * \param pointer to object to free
+ */
+void
+snd_seq_remove_events_free (snd_seq_remove_events_t * obj)
+{
+ free (obj);
+}
+
+/**
+ * \brief Set the removal condition bits
+ * \param info remove_events container
+ * \param flags removal condition bits
+ *
+ * \sa snd_seq_remove_events()
+ */
+void
+snd_seq_remove_events_set_condition (snd_seq_remove_events_t * info,
+ unsigned int flags)
+{
+ dbg_printf ("snd_seq_remove_events_set_condition(rmp=%x, flags=%lu)\n",
+ info, flags);
+}
+
+/**
+ * \brief Set the queue as removal condition
+ * \param info remove_events container
+ * \param queue queue id
+ *
+ * \sa snd_seq_remove_events()
+ */
+void
+snd_seq_remove_events_set_queue (snd_seq_remove_events_t * info, int queue)
+{
+ dbg_printf ("snd_seq_remove_events_set_queue(rmp=%x, q=%d)\n", info, queue);
+}
+
+/**
+ * \brief remove events on input/output buffers and pools
+ * \param seq sequencer handle
+ * \param rmp remove event container
+ *
+ * Removes matching events with the given condition from input/output buffers
+ * and pools.
+ * The removal condition is specified in \a rmp argument.
+ *
+ * \sa snd_seq_event_output(), snd_seq_drop_output(), snd_seq_reset_pool_output()
+ */
+int
+snd_seq_remove_events (snd_seq_t * seq, snd_seq_remove_events_t * rmp)
+{
+ dbg_printf ("snd_seq_remove_events(seq=%x, rmp=%x)\n", seq, rmp);
+
+ return 1;
+}
+
+
+/**
+ * \brief clear input buffer and and remove events in sequencer queue
+ * \param seq sequencer handle
+ *
+ * \sa snd_seq_drop_input_buffer(), snd_seq_remove_events()
+ */
+int
+snd_seq_drop_input (snd_seq_t * seq)
+{
+ dbg_printf ("snd_seq_drop_input(seq=%x)\n", seq);
+
+ return 0;
+}
+
+/**
+ * \brief remove all events on user-space output buffer
+ * \param seq sequencer handle
+ *
+ * Removes all events on user-space output buffer.
+ * Unlike snd_seq_drain_output(), this function doesn't remove
+ * events on output memory pool of sequencer.
+ *
+ * \sa snd_seq_drop_output()
+ */
+int
+snd_seq_drop_output_buffer (snd_seq_t * seq)
+{
+ dbg_printf ("snd_seq_drop_output_buffer(seq=%x)\n", seq);
+
+ return 0;
+}
+
+/**
+ * \brief extract the first event in output buffer
+ * \param seq sequencer handle
+ * \param ev_res event pointer to be extracted
+ * \return 0 on success otherwise a negative error code
+ *
+ * Extracts the first event in output buffer.
+ * If ev_res is NULL, just remove the event.
+ *
+ * \sa snd_seq_event_output()
+ */
+int
+snd_seq_extract_output (snd_seq_t * seq, snd_seq_event_t ** ev_res)
+{
+ dbg_printf ("snd_seq_extract_output(seq=%x)\n", seq);
+
+ return -EIO;
+}
+
+/**
+ * \brief get size of #snd_seq_queue_status_t
+ * \return size in bytes
+ */
+size_t
+snd_seq_queue_status_sizeof ()
+{
+ return sizeof (snd_seq_queue_status_t);
+}
+
+/**
+ * \brief Return the size of output buffer
+ * \param seq sequencer handle
+ * \return the size of output buffer in bytes
+ *
+ * Obtains the size of output buffer.
+ * This buffer is used to store decoded byte-stream of output events
+ * before transferring to sequencer.
+ *
+ * \sa snd_seq_set_output_buffer_size()
+ */
+size_t
+snd_seq_get_output_buffer_size (snd_seq_t * seq)
+{
+ dbg_printf ("snd_seq_get_output_buffer_size(seq=%x)\n", seq);
+
+ return 1024;
+}
+
+/**
+ * \brief Change the size of output buffer
+ * \param seq sequencer handle
+ * \param size the size of output buffer to be changed in bytes
+ * \return 0 on success otherwise a negative error code
+ *
+ * Changes the size of output buffer.
+ *
+ * \sa snd_seq_get_output_buffer_size()
+ */
+int
+snd_seq_set_output_buffer_size (snd_seq_t * seq, size_t size)
+{
+ dbg_printf ("snd_seq_set_output_buffer_size(seq=%x, size=%d)\n", seq, size);
+ return 0;
+}
+
+/**
+ * \brief unsubscribe a connection between ports
+ * \param seq sequencer handle
+ * \param sub subscription information to disconnect
+ * \return 0 on success otherwise a negative error code
+ *
+ * Unsubscribes a connection between two ports,
+ * described in sender and dest fields in sub argument.
+ *
+ * \sa snd_seq_subscribe_port(), snd_seq_disconnect_from(), snd_seq_disconnect_to()
+ */
+int
+snd_seq_unsubscribe_port (snd_seq_t * seq, snd_seq_port_subscribe_t * sub)
+{
+ dbg_printf ("snd_seq_unsubscribe_port(seq=%x, sub=%x)\n", seq, sub);
+
+ return 0;
+}
+
+/**
+ * \brief Get the queue id of a queue_timer container
+ * \param info queue_timer container
+ * \return queue id
+ *
+ * \sa snd_seq_get_queue_timer()
+ */
+int
+snd_seq_queue_timer_get_queue (const snd_seq_queue_timer_t * info)
+{
+ dbg_printf ("snd_seq_queue_timer_get_queue(timer=%x)\n", info);
+
+ return 0;
+}
+
+/**
+ * \brief obtain the queue timer information
+ * \param seq sequencer handle
+ * \param q queue id to query
+ * \param timer pointer to store the timer information
+ * \return 0 on success otherwise a negative error code
+ *
+ * \sa snd_seq_set_queue_timer()
+ */
+int
+snd_seq_get_queue_timer (snd_seq_t * seq, int q,
+ snd_seq_queue_timer_t * timer)
+{
+ dbg_printf ("snd_seq_get_queue_timer(seq=%x, q=%d, timer=%x)\n",
+ seq, 1, timer);
+
+ return 0;
+}
+
+/**
+ * \brief Set the timer id of a queue_timer container
+ * \param info queue_timer container
+ * \param id timer id pointer
+ *
+ * \sa snd_seq_get_queue_timer()
+ */
+void
+snd_seq_queue_timer_set_id (snd_seq_queue_timer_t * info,
+ const snd_timer_id_t * id)
+{
+ dbg_printf ("snd_seq_queue_timer_set_id(timer=%x, id=%x)\n", info, id);
+}
+
+/**
+ * \brief get size of #snd_seq_queue_timer_t
+ * \return size in bytes
+ */
+size_t
+snd_seq_queue_timer_sizeof ()
+{
+ return sizeof (snd_seq_queue_timer_t);
+}
+
+/**
+ * \brief get size of #snd_seq_query_subscribe_t
+ * \return size in bytes
+ */
+size_t
+snd_seq_query_subscribe_sizeof ()
+{
+ return sizeof (snd_seq_query_subscribe_t);
+}
+
+/**
+ * \brief allocate an empty #snd_seq_query_subscribe_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_seq_query_subscribe_malloc (snd_seq_query_subscribe_t ** ptr)
+{
+ *ptr = calloc (1, sizeof (snd_seq_query_subscribe_t));
+
+ dbg_printf ("snd_seq_query_subscribe_malloc()=%x\n", *ptr);
+ if (!*ptr)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * \brief frees a previously allocated #snd_seq_query_subscribe_t
+ * \param pointer to object to free
+ */
+void
+snd_seq_query_subscribe_free (snd_seq_query_subscribe_t * obj)
+{
+ dbg_printf ("snd_seq_query_subscribe_free(obj=%x)\n", obj);
+ free (obj);
+}
+
+/**
+ * \brief Get the address of subscriber of a query_subscribe container
+ * \param info query_subscribe container
+ * \return subscriber's address pointer
+ *
+ * \sa snd_seq_query_port_subscribers()
+ */
+const snd_seq_addr_t *
+snd_seq_query_subscribe_get_addr (const snd_seq_query_subscribe_t * info)
+{
+ dbg_printf ("snd_seq_query_subscribe_get_addr(info=%x)\n", info);
+
+ return NULL; // TODO
+}
+
+/**
+ * \brief Get the index of subscriber of a query_subscribe container
+ * \param info query_subscribe container
+ * \return subscriber's index
+ *
+ * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_index()
+ */
+int
+snd_seq_query_subscribe_get_index (const snd_seq_query_subscribe_t * info)
+{
+ dbg_printf ("snd_seq_query_subscribe_get_index(info=%x)\n", info);
+
+ return 0; // TODO
+}
+
+/**
+ * \brief Set the subscriber's index to be queried
+ * \param info query_subscribe container
+ * \param index index to be queried
+ *
+ * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_index()
+ */
+void
+snd_seq_query_subscribe_set_index (snd_seq_query_subscribe_t * info,
+ int index)
+{
+ dbg_printf ("snd_seq_query_subscribe_t(info=%x, index=%d)\n", info, index);
+
+ // TODO
+}
+
+/**
+ * \brief Get the client/port address of a query_subscribe container
+ * \param info query_subscribe container
+ * \return client/port address pointer
+ *
+ * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_root()
+ */
+const snd_seq_addr_t *
+snd_seq_query_subscribe_get_root (const snd_seq_query_subscribe_t * info)
+{
+ dbg_printf ("snd_seq_query_subscribe_get_root(info=%x)\n", info);
+
+ return NULL; // TODO
+}
+
+/**
+ * \brief Set the client/port address of a query_subscribe container
+ * \param info query_subscribe container
+ * \param addr client/port address pointer
+ *
+ * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_root()
+ */
+void
+snd_seq_query_subscribe_set_root (snd_seq_query_subscribe_t * info,
+ const snd_seq_addr_t * addr)
+{
+ dbg_printf ("snd_seq_query_subscribe_set_root(info=%d, addr=%x)\n",
+ info, addr);
+}
+
+/**
+ * \brief Get the query type of a query_subscribe container
+ * \param info query_subscribe container
+ * \return query type
+ *
+ * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_type()
+ */
+snd_seq_query_subs_type_t
+snd_seq_query_subscribe_get_type (const snd_seq_query_subscribe_t * info)
+{
+ dbg_printf ("snd_seq_query_subscribe_get_type(info=%x)\n", info);
+
+ return 0; // TODO
+}
+
+/**
+ * \brief Set the query type of a query_subscribe container
+ * \param info query_subscribe container
+ * \param type query type
+ *
+ * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_type()
+ */
+void
+snd_seq_query_subscribe_set_type (snd_seq_query_subscribe_t * info,
+ snd_seq_query_subs_type_t type)
+{
+ dbg_printf ("snd_seq_query_subscribe_set_type(info=%x, type=%x)\n",
+ info, type);
+
+ // TODO
+}
+
+/**
+ * \brief obtain subscription information
+ * \param seq sequencer handle
+ * \param sub pointer to return the subscription information
+ * \return 0 on success otherwise a negative error code
+ *
+ * \sa snd_seq_subscribe_port(), snd_seq_query_port_subscribers()
+ */
+int
+snd_seq_get_port_subscription (snd_seq_t * seq,
+ snd_seq_port_subscribe_t * sub)
+{
+ dbg_printf ("snd_seq_get_port_subscription(seq=%x, sub=%x)\n", seq, sub);
+
+ return 0; // TODO
+}
+
+/**
+ * \brief query port subscriber list
+ * \param seq sequencer handle
+ * \param subs subscription to query
+ * \return 0 on success otherwise a negative error code
+ *
+ * Queries the subscribers accessing to a port.
+ * The query information is specified in subs argument.
+ *
+ * At least, the client id, the port id, the index number and
+ * the query type must be set to perform a proper query.
+ * As the query type, #SND_SEQ_QUERY_SUBS_READ or #SND_SEQ_QUERY_SUBS_WRITE
+ * can be specified to check whether the readers or the writers to the port.
+ * To query the first subscription, set 0 to the index number. To list up
+ * all the subscriptions, call this function with the index numbers from 0
+ * until this returns a negative value.
+ *
+ * \sa snd_seq_get_port_subscription()
+ */
+int
+snd_seq_query_port_subscribers (snd_seq_t * seq, snd_seq_query_subscribe_t *
+ subs)
+{
+ dbg_printf ("snd_seq_query_port_subscribers(seq=%x, subs=%x)\n", seq, subs);
+
+ return 0; // TODO
+}
+
+/**
+ * \brief Get the real time of a queue_status container
+ * \param info queue_status container
+ * \param time real time
+ *
+ * \sa snd_seq_get_queue_status()
+ */
+const snd_seq_real_time_t *
+snd_seq_queue_status_get_real_time (const snd_seq_queue_status_t * info)
+{
+ dbg_printf ("snd_seq_queue_status_get_real_time(info=%x)\n", info);
+
+ return NULL; // TODO
+}