2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \file seq/seq.c
|
2001-07-18 12:17:11 +00:00
|
|
|
* \brief Sequencer Interface
|
2001-06-06 17:50:16 +00:00
|
|
|
* \author Jaroslav Kysela <perex@suse.cz>
|
|
|
|
|
* \author Abramo Bagnara <abramo@alsa-project.org>
|
|
|
|
|
* \author Takashi Iwai <tiwai@suse.de>
|
|
|
|
|
* \date 2000-2001
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Sequencer Interface - main file
|
1998-12-27 00:59:08 +00:00
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or modify
|
2001-12-30 09:22:54 +00:00
|
|
|
* it under the terms of the GNU Lesser General Public License as
|
|
|
|
|
* published by the Free Software Foundation; either version 2.1 of
|
1998-12-27 00:59:08 +00:00
|
|
|
* 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
|
2001-12-30 09:22:54 +00:00
|
|
|
* GNU Lesser General Public License for more details.
|
1998-12-27 00:59:08 +00:00
|
|
|
*
|
2001-12-30 09:22:54 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
1998-12-27 00:59:08 +00:00
|
|
|
* License along with this library; if not, write to the Free Software
|
2001-12-30 09:22:54 +00:00
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
1998-12-27 00:59:08 +00:00
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2000-11-20 20:10:46 +00:00
|
|
|
#include <dlfcn.h>
|
2001-10-24 14:14:11 +00:00
|
|
|
#include <sys/poll.h>
|
2000-11-20 20:10:46 +00:00
|
|
|
#include "seq_local.h"
|
1998-12-27 00:59:08 +00:00
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/****************************************************************************
|
|
|
|
|
* *
|
|
|
|
|
* seq.h *
|
|
|
|
|
* Sequencer *
|
|
|
|
|
* *
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief get identifier of sequencer handle
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \return ascii identifier of sequencer handle
|
|
|
|
|
*
|
|
|
|
|
* Returns the ASCII identifier of the given sequencer handle. It's the same
|
|
|
|
|
* identifier specified in snd_seq_open().
|
|
|
|
|
*/
|
2001-02-11 15:45:35 +00:00
|
|
|
const char *snd_seq_name(snd_seq_t *seq)
|
|
|
|
|
{
|
|
|
|
|
assert(seq);
|
|
|
|
|
return seq->name;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief get type of sequencer handle
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \return type of sequencer handle
|
|
|
|
|
*
|
|
|
|
|
* Returns the type #snd_seq_type_t of the given sequencer handle.
|
|
|
|
|
*/
|
2001-02-11 15:45:35 +00:00
|
|
|
snd_seq_type_t snd_seq_type(snd_seq_t *seq)
|
|
|
|
|
{
|
|
|
|
|
assert(seq);
|
|
|
|
|
return seq->type;
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-22 09:19:43 +00:00
|
|
|
static int snd_seq_open_conf(snd_seq_t **seqp, const char *name,
|
2001-06-16 22:03:23 +00:00
|
|
|
snd_config_t *seq_root, snd_config_t *seq_conf,
|
2001-05-22 09:19:43 +00:00
|
|
|
int streams, int mode)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-02-06 23:48:10 +00:00
|
|
|
const char *str;
|
2001-03-07 12:36:05 +00:00
|
|
|
char buf[256];
|
2000-11-20 20:10:46 +00:00
|
|
|
int err;
|
2001-05-22 09:19:43 +00:00
|
|
|
snd_config_t *conf, *type_conf = NULL;
|
2001-02-11 15:45:35 +00:00
|
|
|
snd_config_iterator_t i, next;
|
2001-11-19 08:14:21 +00:00
|
|
|
const char *id;
|
2001-03-29 17:50:28 +00:00
|
|
|
const char *lib = NULL, *open_name = NULL;
|
2001-06-16 22:03:23 +00:00
|
|
|
int (*open_func)(snd_seq_t **, const char *,
|
|
|
|
|
snd_config_t *, snd_config_t *,
|
|
|
|
|
int, int) = NULL;
|
2001-10-24 14:14:11 +00:00
|
|
|
#ifndef PIC
|
|
|
|
|
extern void *snd_seq_open_symbols(void);
|
|
|
|
|
#endif
|
2000-11-20 20:10:46 +00:00
|
|
|
void *h;
|
2001-02-07 11:34:33 +00:00
|
|
|
if (snd_config_get_type(seq_conf) != SND_CONFIG_TYPE_COMPOUND) {
|
2001-05-22 09:19:43 +00:00
|
|
|
if (name)
|
|
|
|
|
SNDERR("Invalid type for SEQ %s definition", name);
|
|
|
|
|
else
|
|
|
|
|
SNDERR("Invalid type for SEQ definition");
|
2000-11-20 20:10:46 +00:00
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
err = snd_config_search(seq_conf, "type", &conf);
|
|
|
|
|
if (err < 0) {
|
2001-03-04 20:39:02 +00:00
|
|
|
SNDERR("type is not defined");
|
2000-11-20 20:10:46 +00:00
|
|
|
return err;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
2001-11-19 08:14:21 +00:00
|
|
|
err = snd_config_get_id(conf, &id);
|
|
|
|
|
if (err < 0) {
|
|
|
|
|
SNDERR("unable to get id");
|
|
|
|
|
return err;
|
|
|
|
|
}
|
2001-02-07 11:34:33 +00:00
|
|
|
err = snd_config_get_string(conf, &str);
|
2000-11-20 20:10:46 +00:00
|
|
|
if (err < 0) {
|
2001-11-19 08:14:21 +00:00
|
|
|
SNDERR("Invalid type for %s", id);
|
2000-11-20 20:10:46 +00:00
|
|
|
return err;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
2001-06-16 22:03:23 +00:00
|
|
|
err = snd_config_search_definition(seq_root, "seq_type", str, &type_conf);
|
2001-03-07 12:36:05 +00:00
|
|
|
if (err >= 0) {
|
2001-05-22 09:19:43 +00:00
|
|
|
if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
|
|
|
|
|
SNDERR("Invalid type for SEQ type %s definition", str);
|
2001-06-15 14:00:19 +00:00
|
|
|
goto _err;
|
2001-05-22 09:19:43 +00:00
|
|
|
}
|
2001-03-07 12:36:05 +00:00
|
|
|
snd_config_for_each(i, next, type_conf) {
|
|
|
|
|
snd_config_t *n = snd_config_iterator_entry(i);
|
2001-11-19 08:14:21 +00:00
|
|
|
const char *id;
|
|
|
|
|
if (snd_config_get_id(n, &id) < 0)
|
|
|
|
|
continue;
|
2001-03-07 12:36:05 +00:00
|
|
|
if (strcmp(id, "comment") == 0)
|
|
|
|
|
continue;
|
|
|
|
|
if (strcmp(id, "lib") == 0) {
|
|
|
|
|
err = snd_config_get_string(n, &lib);
|
|
|
|
|
if (err < 0) {
|
|
|
|
|
SNDERR("Invalid type for %s", id);
|
2001-06-15 14:00:19 +00:00
|
|
|
goto _err;
|
2001-03-07 12:36:05 +00:00
|
|
|
}
|
|
|
|
|
continue;
|
2000-11-20 20:10:46 +00:00
|
|
|
}
|
2001-03-07 12:36:05 +00:00
|
|
|
if (strcmp(id, "open") == 0) {
|
2001-03-29 17:50:28 +00:00
|
|
|
err = snd_config_get_string(n, &open_name);
|
2001-03-07 12:36:05 +00:00
|
|
|
if (err < 0) {
|
|
|
|
|
SNDERR("Invalid type for %s", id);
|
2001-06-15 14:00:19 +00:00
|
|
|
goto _err;
|
2001-03-07 12:36:05 +00:00
|
|
|
}
|
|
|
|
|
continue;
|
2000-11-20 20:10:46 +00:00
|
|
|
}
|
2001-03-04 20:39:02 +00:00
|
|
|
SNDERR("Unknown field %s", id);
|
2001-12-27 20:55:53 +00:00
|
|
|
err = -EINVAL;
|
|
|
|
|
goto _err;
|
2000-11-20 20:10:46 +00:00
|
|
|
}
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
2001-03-29 17:50:28 +00:00
|
|
|
if (!open_name) {
|
|
|
|
|
open_name = buf;
|
2001-03-07 12:36:05 +00:00
|
|
|
snprintf(buf, sizeof(buf), "_snd_seq_%s_open", str);
|
2000-11-20 20:10:46 +00:00
|
|
|
}
|
2001-10-24 14:14:11 +00:00
|
|
|
#ifndef PIC
|
|
|
|
|
snd_seq_open_symbols();
|
|
|
|
|
#endif
|
|
|
|
|
h = snd_dlopen(lib, RTLD_NOW);
|
|
|
|
|
if (h)
|
|
|
|
|
open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_SEQ_DLSYM_VERSION));
|
2001-06-16 22:03:23 +00:00
|
|
|
err = 0;
|
2000-11-20 20:10:46 +00:00
|
|
|
if (!h) {
|
2001-03-04 20:39:02 +00:00
|
|
|
SNDERR("Cannot open shared library %s", lib);
|
2001-06-16 22:03:23 +00:00
|
|
|
err = -ENOENT;
|
|
|
|
|
} else if (!open_func) {
|
2001-03-29 17:50:28 +00:00
|
|
|
SNDERR("symbol %s is not defined inside %s", open_name, lib);
|
2001-10-24 14:14:11 +00:00
|
|
|
snd_dlclose(h);
|
2001-06-16 22:03:23 +00:00
|
|
|
err = -ENXIO;
|
2000-11-20 20:10:46 +00:00
|
|
|
}
|
2001-06-16 22:03:23 +00:00
|
|
|
_err:
|
|
|
|
|
if (type_conf)
|
|
|
|
|
snd_config_delete(type_conf);
|
|
|
|
|
return err >= 0 ? open_func(seqp, name, seq_root, seq_conf, streams, mode) : err;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-15 08:47:59 +00:00
|
|
|
static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root,
|
|
|
|
|
const char *name, int streams, int mode)
|
2001-05-22 09:19:43 +00:00
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
snd_config_t *seq_conf;
|
2001-06-15 14:00:19 +00:00
|
|
|
err = snd_config_search_definition(root, "seq", name, &seq_conf);
|
2001-06-15 08:47:59 +00:00
|
|
|
if (err < 0) {
|
2001-06-15 14:00:19 +00:00
|
|
|
SNDERR("Unknown SEQ %s", name);
|
2001-06-15 08:47:59 +00:00
|
|
|
return err;
|
2001-05-22 09:19:43 +00:00
|
|
|
}
|
2001-06-16 22:03:23 +00:00
|
|
|
err = snd_seq_open_conf(seqp, name, root, seq_conf, streams, mode);
|
2001-06-15 08:47:59 +00:00
|
|
|
snd_config_delete(seq_conf);
|
2001-05-22 09:19:43 +00:00
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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
|
2001-07-04 13:54:13 +00:00
|
|
|
* library. Usually you need to pass \c "default" here.
|
2001-06-06 17:50:16 +00:00
|
|
|
* \param streams The read/write mode of the sequencer. Can be one of
|
|
|
|
|
* three values:
|
2001-07-04 13:54:13 +00:00
|
|
|
* - #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
|
2001-06-06 17:50:16 +00:00
|
|
|
* \note Internally, these are translated to \c O_WRONLY, \c O_RDONLY and
|
|
|
|
|
* \O_RDWR respectively and used as the second argument to the C library
|
|
|
|
|
* open() call.
|
2001-07-04 13:54:13 +00:00
|
|
|
* \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().
|
2001-06-06 17:50:16 +00:00
|
|
|
* \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
|
2001-07-04 13:54:13 +00:00
|
|
|
* with #SND_SEQ_EVENT_CLIENT_START is broadcasted to announce port.
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-05-22 09:19:43 +00:00
|
|
|
int snd_seq_open(snd_seq_t **seqp, const char *name,
|
|
|
|
|
int streams, int mode)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
assert(seqp && name);
|
|
|
|
|
err = snd_config_update();
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
2001-06-15 08:47:59 +00:00
|
|
|
return snd_seq_open_noupdate(seqp, snd_config, name, streams, mode);
|
2001-05-22 09:19:43 +00:00
|
|
|
}
|
|
|
|
|
|
2001-11-24 17:47:01 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Open the ALSA sequencer using local configuration
|
|
|
|
|
*
|
|
|
|
|
* \param seqp Pointer to a snd_seq_t pointer.
|
|
|
|
|
* \param streams The read/write mode of the sequencer.
|
|
|
|
|
* \param mode Optional modifier
|
|
|
|
|
* \param lconf Local configuration
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*
|
|
|
|
|
* See the snd_seq_open() function for further details. The extension
|
|
|
|
|
* is that the given configuration is used to resolve abstract name.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_open_lconf(snd_seq_t **seqp, const char *name,
|
|
|
|
|
int streams, int mode, snd_config_t *lconf)
|
|
|
|
|
{
|
|
|
|
|
assert(seqp && name && lconf);
|
|
|
|
|
return snd_seq_open_noupdate(seqp, lconf, name, streams, mode);
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Close the sequencer
|
2001-07-04 13:54:13 +00:00
|
|
|
* \param handle Handle returned from #snd_seq_open()
|
2001-06-06 17:50:16 +00:00
|
|
|
* \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
|
2001-07-04 13:54:13 +00:00
|
|
|
* #SND_SEQ_EVENT_CLIENT_EXIT is broadcasted to announce port.
|
2001-06-06 17:50:16 +00:00
|
|
|
* The connection between other clients are disconnected.
|
|
|
|
|
* Call this just before exiting your program.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
1999-06-15 22:26:21 +00:00
|
|
|
int snd_seq_close(snd_seq_t *seq)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
int err;
|
|
|
|
|
assert(seq);
|
|
|
|
|
err = seq->ops->close(seq);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
1999-09-16 09:26:28 +00:00
|
|
|
if (seq->obuf)
|
|
|
|
|
free(seq->obuf);
|
|
|
|
|
if (seq->ibuf)
|
|
|
|
|
free(seq->ibuf);
|
2000-08-29 11:39:08 +00:00
|
|
|
if (seq->tmpbuf)
|
|
|
|
|
free(seq->tmpbuf);
|
2000-11-20 20:10:46 +00:00
|
|
|
if (seq->name)
|
|
|
|
|
free(seq->name);
|
1998-12-27 00:59:08 +00:00
|
|
|
free(seq);
|
2000-11-20 20:10:46 +00:00
|
|
|
return 0;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \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 specifed by the second argument. When both input and output
|
|
|
|
|
* are checked, pass \c POLLIN|POLLOUT
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-02-21 16:29:40 +00:00
|
|
|
int snd_seq_poll_descriptors_count(snd_seq_t *seq, short events)
|
2001-02-14 12:15:03 +00:00
|
|
|
{
|
2001-02-21 16:29:40 +00:00
|
|
|
int result = 0;
|
2001-02-14 12:15:03 +00:00
|
|
|
assert(seq);
|
2001-02-21 16:29:40 +00:00
|
|
|
if (events & POLLIN) {
|
|
|
|
|
assert(seq->streams & SND_SEQ_OPEN_INPUT);
|
|
|
|
|
result++;
|
|
|
|
|
}
|
|
|
|
|
if (events & POLLOUT) {
|
|
|
|
|
assert(seq->streams & SND_SEQ_OPEN_OUTPUT);
|
|
|
|
|
result++;
|
|
|
|
|
}
|
|
|
|
|
return result ? 1 : 0;
|
2001-02-14 12:15:03 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get poll descriptors
|
2001-06-06 17:50:16 +00:00
|
|
|
* \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.
|
|
|
|
|
*/
|
2001-02-21 16:29:40 +00:00
|
|
|
int snd_seq_poll_descriptors(snd_seq_t *seq, struct pollfd *pfds, unsigned int space, short events)
|
2001-02-12 23:51:49 +00:00
|
|
|
{
|
2001-02-21 16:29:40 +00:00
|
|
|
short revents = 0;
|
|
|
|
|
|
2001-02-12 23:51:49 +00:00
|
|
|
assert(seq);
|
2001-02-21 16:29:40 +00:00
|
|
|
if ((events & POLLIN) && space >= 1) {
|
|
|
|
|
assert(seq->streams & SND_SEQ_OPEN_INPUT);
|
2001-11-30 17:36:45 +00:00
|
|
|
revents |= POLLIN|POLLERR;
|
2001-02-12 23:51:49 +00:00
|
|
|
}
|
2001-02-21 16:29:40 +00:00
|
|
|
if ((events & POLLOUT) && space >= 1) {
|
|
|
|
|
assert(seq->streams & SND_SEQ_OPEN_INPUT);
|
2001-11-30 17:36:45 +00:00
|
|
|
revents |= POLLOUT|POLLERR;
|
2001-02-21 16:29:40 +00:00
|
|
|
}
|
|
|
|
|
if (!revents)
|
|
|
|
|
return 0;
|
|
|
|
|
pfds->fd = seq->poll_fd;
|
|
|
|
|
pfds->events = revents;
|
|
|
|
|
return 1;
|
2001-02-12 23:51:49 +00:00
|
|
|
}
|
|
|
|
|
|
2001-11-30 17:36:45 +00:00
|
|
|
/**
|
|
|
|
|
* \brief get returned events from poll descriptors
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param pfds array of poll descriptors
|
|
|
|
|
* \param nfds count of poll descriptors
|
|
|
|
|
* \param revents returned events
|
|
|
|
|
* \return zero if success, otherwise a negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_poll_descriptors_revents(snd_seq_t *seq, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && pfds && revents);
|
|
|
|
|
if (nfds == 1) {
|
|
|
|
|
*revents = pfds->revents;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Set nonblock mode
|
2001-06-06 17:50:16 +00:00
|
|
|
* \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
|
2001-07-04 13:54:13 +00:00
|
|
|
* after a certain amount of free space becomes available.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2000-11-20 20:10:46 +00:00
|
|
|
int snd_seq_nonblock(snd_seq_t *seq, int nonblock)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
int err;
|
|
|
|
|
assert(seq);
|
|
|
|
|
err = seq->ops->nonblock(seq, nonblock);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
if (nonblock)
|
|
|
|
|
seq->mode |= SND_SEQ_NONBLOCK;
|
1999-01-13 14:51:21 +00:00
|
|
|
else
|
2000-11-20 20:10:46 +00:00
|
|
|
seq->mode &= ~SND_SEQ_NONBLOCK;
|
1998-12-27 00:59:08 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the client id
|
2001-06-06 17:50:16 +00:00
|
|
|
* \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.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
1999-06-15 22:26:21 +00:00
|
|
|
int snd_seq_client_id(snd_seq_t *seq)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq);
|
1998-12-27 00:59:08 +00:00
|
|
|
return seq->client;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Return the size of output buffer
|
2001-06-06 17:50:16 +00:00
|
|
|
* \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.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
size_t snd_seq_get_output_buffer_size(snd_seq_t *seq)
|
2000-03-18 18:03:50 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq);
|
2000-03-18 18:03:50 +00:00
|
|
|
if (!seq->obuf)
|
|
|
|
|
return 0;
|
|
|
|
|
return seq->obufsize;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Return the size of input buffer
|
2001-06-06 17:50:16 +00:00
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \return the size of input buffer in bytes
|
|
|
|
|
*
|
|
|
|
|
* Obtains the size of input buffer.
|
|
|
|
|
* This buffer is used to read byte-stream of input events from sequencer.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
size_t snd_seq_get_input_buffer_size(snd_seq_t *seq)
|
2000-03-18 18:03:50 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq);
|
2000-03-18 18:03:50 +00:00
|
|
|
if (!seq->ibuf)
|
|
|
|
|
return 0;
|
2000-08-29 11:39:08 +00:00
|
|
|
return seq->ibufsize * sizeof(snd_seq_event_t);
|
2000-03-18 18:03:50 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Change the size of output buffer
|
2001-06-06 17:50:16 +00:00
|
|
|
* \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.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_set_output_buffer_size(snd_seq_t *seq, size_t size)
|
2000-03-18 18:03:50 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq && seq->obuf);
|
|
|
|
|
assert(size >= sizeof(snd_seq_event_t));
|
2000-09-29 20:49:18 +00:00
|
|
|
snd_seq_drop_output(seq);
|
2000-03-18 18:03:50 +00:00
|
|
|
if (size != seq->obufsize) {
|
|
|
|
|
char *newbuf;
|
|
|
|
|
newbuf = calloc(1, size);
|
|
|
|
|
if (newbuf == NULL)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
free(seq->obuf);
|
|
|
|
|
seq->obuf = newbuf;
|
|
|
|
|
seq->obufsize = size;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Resize the input buffer
|
2001-06-06 17:50:16 +00:00
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param size the size of input buffer to be changed in bytes
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*
|
|
|
|
|
* Changes the size of input buffer.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_set_input_buffer_size(snd_seq_t *seq, size_t size)
|
2000-03-18 18:03:50 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq && seq->ibuf);
|
|
|
|
|
assert(size >= sizeof(snd_seq_event_t));
|
2000-09-29 20:49:18 +00:00
|
|
|
snd_seq_drop_input(seq);
|
2000-08-29 11:39:08 +00:00
|
|
|
size = (size + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t);
|
2000-03-18 18:03:50 +00:00
|
|
|
if (size != seq->ibufsize) {
|
2000-08-29 11:39:08 +00:00
|
|
|
snd_seq_event_t *newbuf;
|
|
|
|
|
newbuf = calloc(sizeof(snd_seq_event_t), size);
|
2000-03-18 18:03:50 +00:00
|
|
|
if (newbuf == NULL)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
free(seq->ibuf);
|
|
|
|
|
seq->ibuf = newbuf;
|
|
|
|
|
seq->ibufsize = size;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get size of #snd_seq_system_info_t
|
|
|
|
|
* \return size in bytes
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
size_t snd_seq_system_info_sizeof()
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
return sizeof(snd_seq_system_info_t);
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Allocate an empty #snd_seq_system_info_t using standard malloc
|
|
|
|
|
* \param ptr returned pointer
|
|
|
|
|
* \return 0 on success otherwise negative error code
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_system_info_malloc(snd_seq_system_info_t **ptr)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(ptr);
|
|
|
|
|
*ptr = calloc(1, sizeof(snd_seq_system_info_t));
|
|
|
|
|
if (!*ptr)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
return 0;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Frees a previously allocated #snd_seq_system_info_t
|
|
|
|
|
* \param pointer to object to free
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_system_info_free(snd_seq_system_info_t *obj)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
free(obj);
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Copy one #snd_seq_system_info_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_system_info_copy(snd_seq_system_info_t *dst, const snd_seq_system_info_t *src)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2000-03-18 18:03:50 +00:00
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get maximum number of queues
|
|
|
|
|
* \param info #snd_seq_system_info_t container
|
|
|
|
|
* \return maximum number of queues
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_system_info_get_queues(const snd_seq_system_info_t *info)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return info->queues;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get maximum number of clients
|
|
|
|
|
* \param info #snd_seq_system_info_t container
|
|
|
|
|
* \return maximum number of clients
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_system_info_get_clients(const snd_seq_system_info_t *info)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return info->clients;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get maximum number of ports
|
|
|
|
|
* \param info #snd_seq_system_info_t container
|
|
|
|
|
* \return maximum number of ports
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_system_info_get_ports(const snd_seq_system_info_t *info)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return info->ports;
|
2000-11-20 20:10:46 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get maximum number of channels
|
|
|
|
|
* \param info #snd_seq_system_info_t container
|
|
|
|
|
* \return maximum number of channels
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_system_info_get_channels(const snd_seq_system_info_t *info)
|
2000-11-20 20:10:46 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return info->channels;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-07-25 17:33:34 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Get the current number of clients
|
|
|
|
|
* \param info #snd_seq_system_info_t container
|
|
|
|
|
* \return current number of clients
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_system_info_get_cur_clients(const snd_seq_system_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->cur_clients;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the current number of queues
|
|
|
|
|
* \param info #snd_seq_system_info_t container
|
|
|
|
|
* \return current number of queues
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_system_info_get_cur_queues(const snd_seq_system_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->cur_queues;
|
|
|
|
|
}
|
2001-07-04 13:54:13 +00:00
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief obtain the sequencer system information
|
2001-06-06 17:50:16 +00:00
|
|
|
* \param seq sequencer handle
|
2001-07-04 13:54:13 +00:00
|
|
|
* \param info the pointer to be stored
|
2001-06-06 17:50:16 +00:00
|
|
|
* \return 0 on success otherwise a negative error code
|
2001-07-04 13:54:13 +00:00
|
|
|
*
|
|
|
|
|
* Stores the global system information of ALSA sequencer system.
|
|
|
|
|
* The returned data contains
|
|
|
|
|
* the maximum available numbers of queues, clients, ports and channels.
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_system_info(snd_seq_t *seq, snd_seq_system_info_t * info)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(seq && info);
|
|
|
|
|
return seq->ops->system_info(seq, info);
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2000-03-18 18:03:50 +00:00
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/*----------------------------------------------------------------*/
|
2000-03-18 18:03:50 +00:00
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief get size of #snd_seq_client_info_t
|
|
|
|
|
* \return size in bytes
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
size_t snd_seq_client_info_sizeof()
|
1999-08-26 10:23:28 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
return sizeof(snd_seq_client_info_t);
|
1999-08-26 10:23:28 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief allocate an empty #snd_seq_client_info_t using standard malloc
|
|
|
|
|
* \param ptr returned pointer
|
|
|
|
|
* \return 0 on success otherwise negative error code
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_client_info_malloc(snd_seq_client_info_t **ptr)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(ptr);
|
|
|
|
|
*ptr = calloc(1, sizeof(snd_seq_client_info_t));
|
|
|
|
|
if (!*ptr)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
return 0;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief frees a previously allocated #snd_seq_client_info_t
|
|
|
|
|
* \param pointer to object to free
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_client_info_free(snd_seq_client_info_t *obj)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
free(obj);
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief copy one #snd_seq_client_info_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_client_info_copy(snd_seq_client_info_t *dst, const snd_seq_client_info_t *src)
|
1999-08-26 10:23:28 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
1999-08-26 10:23:28 +00:00
|
|
|
}
|
|
|
|
|
|
2000-03-18 18:03:50 +00:00
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Get client id of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \return client id
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_client_info_get_client(const snd_seq_client_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->client;
|
|
|
|
|
}
|
2000-03-18 18:03:50 +00:00
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get client type of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \return client type
|
2001-06-06 17:50:16 +00:00
|
|
|
*
|
2001-07-04 13:54:13 +00:00
|
|
|
* The client type is either #SEQ_CLIENT_TYPE_KERNEL or #SEQ_CLIENT_TYPE_USER
|
|
|
|
|
* for kernel or user client respectively.
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
snd_seq_client_type_t snd_seq_client_info_get_type(const snd_seq_client_info_t *info)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return info->type;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the name of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \return name string
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
const char *snd_seq_client_info_get_name(snd_seq_client_info_t *info)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return info->name;
|
1999-05-09 23:15:42 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the broadcast filter usage of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \return 1 if broadcast is accepted
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_client_info_get_broadcast_filter(const snd_seq_client_info_t *info)
|
1999-05-09 23:15:42 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return (info->filter & SNDRV_SEQ_FILTER_BROADCAST) ? 1 : 0;
|
1999-05-09 23:15:42 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the error-bounce usage of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \return 1 if error-bounce is enabled
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_client_info_get_error_bounce(const snd_seq_client_info_t *info)
|
1999-05-09 23:15:42 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return (info->filter & SNDRV_SEQ_FILTER_BOUNCE) ? 1 : 0;
|
1999-05-09 23:15:42 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the event filter bitmap of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \return NULL if no event filter, or pointer to event filter bitmap
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
const unsigned char *snd_seq_client_info_get_event_filter(const snd_seq_client_info_t *info)
|
1999-05-09 23:15:42 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
if (info->filter & SNDRV_SEQ_FILTER_USE_EVENT)
|
|
|
|
|
return info->event_filter;
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
1999-05-09 23:15:42 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the number of opened ports of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \return number of opened ports
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_client_info_get_num_ports(const snd_seq_client_info_t *info)
|
1999-05-09 23:15:42 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return info->num_ports;
|
1999-05-09 23:15:42 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the number of lost events of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \return number of lost events
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_client_info_get_event_lost(const snd_seq_client_info_t *info)
|
1999-05-09 23:15:42 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return info->event_lost;
|
1999-05-09 23:15:42 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Set the client id of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \param client client id
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_client_info_set_client(snd_seq_client_info_t *info, int client)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
info->client = client;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Set the name of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \param name name string
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_client_info_set_name(snd_seq_client_info_t *info, const char *name)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info && name);
|
|
|
|
|
strncpy(info->name, name, sizeof(info->name));
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Set the broadcast filter usage of a client_info container
|
|
|
|
|
* \param info client_info container
|
2001-07-04 15:05:05 +00:00
|
|
|
* \param val non-zero if broadcast is accepted
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 15:05:05 +00:00
|
|
|
void snd_seq_client_info_set_broadcast_filter(snd_seq_client_info_t *info, int val)
|
2000-08-29 11:39:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
2001-07-04 15:05:05 +00:00
|
|
|
if (val)
|
2001-07-04 13:54:13 +00:00
|
|
|
info->filter |= SNDRV_SEQ_FILTER_BROADCAST;
|
|
|
|
|
else
|
|
|
|
|
info->filter &= ~SNDRV_SEQ_FILTER_BROADCAST;
|
2000-08-29 11:39:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Set the error-bounce usage of a client_info container
|
|
|
|
|
* \param info client_info container
|
2001-07-04 15:05:05 +00:00
|
|
|
* \param val non-zero if error is bounced
|
2001-07-04 13:54:13 +00:00
|
|
|
*/
|
2001-07-04 15:05:05 +00:00
|
|
|
void snd_seq_client_info_set_error_bounce(snd_seq_client_info_t *info, int val)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
2001-07-04 15:05:05 +00:00
|
|
|
if (val)
|
2001-07-04 13:54:13 +00:00
|
|
|
info->filter |= SNDRV_SEQ_FILTER_BOUNCE;
|
|
|
|
|
else
|
|
|
|
|
info->filter &= ~SNDRV_SEQ_FILTER_BOUNCE;
|
1999-11-16 15:07:05 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Set the event filter bitmap of a client_info container
|
|
|
|
|
* \param info client_info container
|
|
|
|
|
* \param filter event filter bitmap
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_client_info_set_event_filter(snd_seq_client_info_t *info, unsigned char *filter)
|
1999-11-16 15:07:05 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
if (! filter)
|
|
|
|
|
info->filter &= ~SNDRV_SEQ_FILTER_USE_EVENT;
|
|
|
|
|
else {
|
|
|
|
|
info->filter |= SNDRV_SEQ_FILTER_USE_EVENT;
|
|
|
|
|
memcpy(info->event_filter, filter, sizeof(info->event_filter));
|
|
|
|
|
}
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \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.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_get_any_client_info(snd_seq_t *seq, int client, snd_seq_client_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && info && client >= 0);
|
|
|
|
|
memset(info, 0, sizeof(snd_seq_client_info_t));
|
|
|
|
|
info->client = client;
|
|
|
|
|
return seq->ops->get_client_info(seq, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_get_client_info(snd_seq_t *seq, snd_seq_client_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
return snd_seq_get_any_client_info(seq, seq->client, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_set_client_info(snd_seq_t *seq, snd_seq_client_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && info);
|
|
|
|
|
info->client = seq->client;
|
|
|
|
|
info->type = USER_CLIENT;
|
|
|
|
|
return seq->ops->set_client_info(seq, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_next_client(snd_seq_t *seq, snd_seq_client_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && info);
|
|
|
|
|
return seq->ops->query_next_client(seq, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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 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)
|
|
|
|
|
{
|
|
|
|
|
assert(ptr);
|
|
|
|
|
*ptr = calloc(1, sizeof(snd_seq_port_info_t));
|
|
|
|
|
if (!*ptr)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
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 copy one #snd_seq_port_info_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_info_copy(snd_seq_port_info_t *dst, const snd_seq_port_info_t *src)
|
|
|
|
|
{
|
|
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get client id of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return client id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_info_get_client(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->addr.client;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get port id of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return port id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_info_get_port(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->addr.port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get client/port address of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return client/port address pointer
|
|
|
|
|
*/
|
|
|
|
|
const snd_seq_addr_t *snd_seq_port_info_get_addr(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
return (snd_seq_addr_t *)&info->addr;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the name of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return name string
|
|
|
|
|
*/
|
|
|
|
|
const char *snd_seq_port_info_get_name(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the capability bits of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return capability bits
|
|
|
|
|
*/
|
|
|
|
|
unsigned int snd_seq_port_info_get_capability(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->capability;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the type bits of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return port type bits
|
|
|
|
|
*/
|
|
|
|
|
unsigned int snd_seq_port_info_get_type(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the number of read subscriptions of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return number of read subscriptions
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_info_get_read_use(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->read_use;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the number of write subscriptions of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return number of write subscriptions
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_info_get_write_use(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->write_use;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the midi channels of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return number of midi channels (default 0)
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_info_get_midi_channels(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->midi_channels;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the midi voices of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return number of midi voices (default 0)
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_info_get_midi_voices(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->midi_voices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the synth voices of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return number of synth voices (default 0)
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_info_get_synth_voices(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->synth_voices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_info_get_port_specified(const snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the client id of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \param client client id
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_info_set_client(snd_seq_port_info_t *info, int client)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->addr.client = client;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the port id of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \param port port id
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_info_set_port(snd_seq_port_info_t *info, int port)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->addr.port = port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the client/port address of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \param addr client/port address
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_info_set_addr(snd_seq_port_info_t *info, const snd_seq_addr_t *addr)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
info->addr = *(struct sndrv_seq_addr *)addr;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the name of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \param name name string
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_info_set_name(snd_seq_port_info_t *info, const char *name)
|
|
|
|
|
{
|
|
|
|
|
assert(info && name);
|
|
|
|
|
strncpy(info->name, name, sizeof(info->name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief set the capability bits of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \param capability capability bits
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_info_set_capability(snd_seq_port_info_t *info, unsigned int capability)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->capability = capability;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the type bits of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \return port type bits
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_info_set_type(snd_seq_port_info_t *info, unsigned int type)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->type = type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief set the midi channels of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \param channels midi channels (default 0)
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_info_set_midi_channels(snd_seq_port_info_t *info, int channels)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->midi_channels = channels;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief set the midi voices of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \param voices midi voices (default 0)
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_info_set_midi_voices(snd_seq_port_info_t *info, int voices)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->midi_voices = voices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief set the synth voices of a port_info container
|
|
|
|
|
* \param info port_info container
|
|
|
|
|
* \param voices synth voices (default 0)
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_info_set_synth_voices(snd_seq_port_info_t *info, int voices)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->synth_voices = voices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the port-specifiied mode of a port_info container
|
|
|
|
|
* \param info port_info container
|
2001-07-04 15:05:05 +00:00
|
|
|
* \param val non-zero if specifying the port id at creation
|
2001-07-04 13:54:13 +00:00
|
|
|
*/
|
2001-07-04 15:05:05 +00:00
|
|
|
void snd_seq_port_info_set_port_specified(snd_seq_port_info_t *info, int val)
|
2001-07-04 13:54:13 +00:00
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-07-04 15:05:05 +00:00
|
|
|
if (val)
|
2001-07-04 13:54:13 +00:00
|
|
|
info->flags |= SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
|
|
|
|
|
else
|
|
|
|
|
info->flags &= ~SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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 (suquencer/editor)
|
|
|
|
|
*
|
|
|
|
|
* A port may contain speicific midi channels, midi voices and synth voices.
|
|
|
|
|
* These values could be zero as default.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_create_port(snd_seq_t *seq, snd_seq_port_info_t * port)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && port);
|
|
|
|
|
port->addr.client = seq->client;
|
|
|
|
|
return seq->ops->create_port(seq, port);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief delete a sequencer port on the current client
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param port port to be deleted
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*
|
|
|
|
|
* Deletes the existing sequencer port on the current client.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_delete_port(snd_seq_t *seq, int port)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_port_info_t pinfo;
|
|
|
|
|
assert(seq);
|
|
|
|
|
memset(&pinfo, 0, sizeof(pinfo));
|
|
|
|
|
pinfo.addr.client = seq->client;
|
|
|
|
|
pinfo.addr.port = port;
|
|
|
|
|
return seq->ops->delete_port(seq, &pinfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief obatin 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
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_get_any_port_info(snd_seq_t *seq, int client, int port, snd_seq_port_info_t * info)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && info && client >= 0 && port >= 0);
|
|
|
|
|
memset(info, 0, sizeof(snd_seq_port_info_t));
|
|
|
|
|
info->addr.client = client;
|
|
|
|
|
info->addr.port = port;
|
|
|
|
|
return seq->ops->get_port_info(seq, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief obatin the information of a port on the current client
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param port port id to get
|
|
|
|
|
* \param info pointer information returns
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_get_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info)
|
|
|
|
|
{
|
|
|
|
|
return snd_seq_get_any_port_info(seq, seq->client, port, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief set the information of a port on the current client
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param port port to be set
|
|
|
|
|
* \param info port information to be set
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_set_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && info && port >= 0);
|
|
|
|
|
info->addr.client = seq->client;
|
|
|
|
|
info->addr.port = port;
|
|
|
|
|
return seq->ops->set_port_info(seq, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_next_port(snd_seq_t *seq, snd_seq_port_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && info);
|
|
|
|
|
return seq->ops->query_next_port(seq, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* subscription
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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 allocate an empty #snd_seq_port_subscribe_t using standard malloc
|
|
|
|
|
* \param ptr returned pointer
|
|
|
|
|
* \return 0 on success otherwise negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_subscribe_malloc(snd_seq_port_subscribe_t **ptr)
|
|
|
|
|
{
|
|
|
|
|
assert(ptr);
|
|
|
|
|
*ptr = calloc(1, sizeof(snd_seq_port_subscribe_t));
|
|
|
|
|
if (!*ptr)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief frees a previously allocated #snd_seq_port_subscribe_t
|
|
|
|
|
* \param pointer to object to free
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_subscribe_free(snd_seq_port_subscribe_t *obj)
|
|
|
|
|
{
|
|
|
|
|
free(obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief copy one #snd_seq_port_subscribe_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_subscribe_copy(snd_seq_port_subscribe_t *dst, const snd_seq_port_subscribe_t *src)
|
|
|
|
|
{
|
|
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get sender address of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
|
|
|
|
* \param addr sender address
|
|
|
|
|
*/
|
|
|
|
|
const snd_seq_addr_t *snd_seq_port_subscribe_get_sender(const snd_seq_port_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
return (snd_seq_addr_t *)&info->sender;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get destination address of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
|
|
|
|
* \param addr destination address
|
|
|
|
|
*/
|
|
|
|
|
const snd_seq_addr_t *snd_seq_port_subscribe_get_dest(const snd_seq_port_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
return (snd_seq_addr_t *)&info->dest;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the queue id of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
|
|
|
|
* \return queue id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_subscribe_get_queue(const snd_seq_port_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->queue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the exclusive mode of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
|
|
|
|
* \return 1 if exclusive mode
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_subscribe_get_exclusive(const snd_seq_port_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return (info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the time-update mode of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
|
|
|
|
* \return 1 if update timestamp
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_subscribe_get_time_update(const snd_seq_port_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the real-time update mode of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
|
|
|
|
* \return 1 if real-time update mode
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_port_subscribe_get_time_real(const snd_seq_port_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return (info->flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set sender address of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
|
|
|
|
* \param addr sender address
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_subscribe_set_sender(snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
memcpy(&info->sender, addr, sizeof(*addr));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set destination address of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
|
|
|
|
* \param addr destination address
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_subscribe_set_dest(snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
memcpy(&info->dest, addr, sizeof(*addr));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the queue id of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
|
|
|
|
* \param q queue id
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_port_subscribe_set_queue(snd_seq_port_subscribe_t *info, int q)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->queue = q;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the exclusive mode of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
2001-07-04 15:05:05 +00:00
|
|
|
* \param val non-zero to enable
|
2001-07-04 13:54:13 +00:00
|
|
|
*/
|
2001-07-04 15:05:05 +00:00
|
|
|
void snd_seq_port_subscribe_set_exclusive(snd_seq_port_subscribe_t *info, int val)
|
2001-07-04 13:54:13 +00:00
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-07-04 15:05:05 +00:00
|
|
|
if (val)
|
2001-07-04 13:54:13 +00:00
|
|
|
info->flags |= SNDRV_SEQ_PORT_SUBS_EXCLUSIVE;
|
|
|
|
|
else
|
|
|
|
|
info->flags &= ~SNDRV_SEQ_PORT_SUBS_EXCLUSIVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the time-update mode of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
2001-07-04 15:05:05 +00:00
|
|
|
* \param val non-zero to enable
|
2001-07-04 13:54:13 +00:00
|
|
|
*/
|
2001-07-04 15:05:05 +00:00
|
|
|
void snd_seq_port_subscribe_set_time_update(snd_seq_port_subscribe_t *info, int val)
|
2001-07-04 13:54:13 +00:00
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-07-04 15:05:05 +00:00
|
|
|
if (val)
|
2001-07-04 13:54:13 +00:00
|
|
|
info->flags |= SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
|
|
|
|
|
else
|
|
|
|
|
info->flags &= ~SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the real-time mode of a port_subscribe container
|
|
|
|
|
* \param info port_subscribe container
|
2001-07-04 15:05:05 +00:00
|
|
|
* \param val non-zero to enable
|
2001-07-04 13:54:13 +00:00
|
|
|
*/
|
2001-07-04 15:05:05 +00:00
|
|
|
void snd_seq_port_subscribe_set_time_real(snd_seq_port_subscribe_t *info, int val)
|
2001-07-04 13:54:13 +00:00
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-07-04 15:05:05 +00:00
|
|
|
if (val)
|
2001-07-04 13:54:13 +00:00
|
|
|
info->flags |= SNDRV_SEQ_PORT_SUBS_TIME_REAL;
|
|
|
|
|
else
|
|
|
|
|
info->flags &= ~SNDRV_SEQ_PORT_SUBS_TIME_REAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_get_port_subscription(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && sub);
|
|
|
|
|
return seq->ops->get_port_subscription(seq, sub);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_subscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && sub);
|
|
|
|
|
return seq->ops->subscribe_port(seq, sub);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_unsubscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && sub);
|
|
|
|
|
return seq->ops->unsubscribe_port(seq, sub);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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)
|
|
|
|
|
{
|
|
|
|
|
assert(ptr);
|
|
|
|
|
*ptr = calloc(1, sizeof(snd_seq_query_subscribe_t));
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
free(obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief copy one #snd_seq_query_subscribe_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_query_subscribe_copy(snd_seq_query_subscribe_t *dst, const snd_seq_query_subscribe_t *src)
|
|
|
|
|
{
|
|
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the client id of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return client id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_subscribe_get_client(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->root.client;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the port id of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return port id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_subscribe_get_port(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->root.port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the client/port address of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return client/port address pointer
|
|
|
|
|
*/
|
|
|
|
|
const snd_seq_addr_t *snd_seq_query_subscribe_get_root(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
return (snd_seq_addr_t *)&info->root;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the query type of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return query type
|
|
|
|
|
*/
|
|
|
|
|
snd_seq_query_subs_type_t snd_seq_query_subscribe_get_type(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the index of subscriber of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return subscriber's index
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_subscribe_get_index(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the number of subscriptiosn of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return number of subscriptions
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_subscribe_get_num_subs(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->num_subs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the address of subscriber of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return subscriber's address pointer
|
|
|
|
|
*/
|
|
|
|
|
const snd_seq_addr_t *snd_seq_query_subscribe_get_addr(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
return (snd_seq_addr_t *)&info->addr;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the queue id of subscriber of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return subscriber's queue id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_subscribe_get_queue(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->queue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the exclusive mode of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return 1 if exclusive mode
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_subscribe_get_exclusive(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return (info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the time-update mode of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return 1 if update timestamp
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_subscribe_get_time_update(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the real-time update mode of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \return 1 if real-time update mode
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_subscribe_get_time_real(const snd_seq_query_subscribe_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the client id of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \param client client id
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_query_subscribe_set_client(snd_seq_query_subscribe_t *info, int client)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->root.client = client;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the port id of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \param port port id
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_query_subscribe_set_port(snd_seq_query_subscribe_t *info, int port)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->root.port = port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the client/port address of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \param addr client/port address pointer
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_query_subscribe_set_root(snd_seq_query_subscribe_t *info, const snd_seq_addr_t *addr)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
info->root = *(struct sndrv_seq_addr *)addr;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the query type of a query_subscribe container
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \param type query type
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_query_subscribe_set_type(snd_seq_query_subscribe_t *info, snd_seq_query_subs_type_t type)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->type = type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the subscriber's index to be queried
|
|
|
|
|
* \param info query_subscribe container
|
|
|
|
|
* \param index index to be queried
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_query_subscribe_set_index(snd_seq_query_subscribe_t *info, int index)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->index = index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subscribe_t * subs)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && subs);
|
|
|
|
|
return seq->ops->query_port_subscribers(seq, subs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* queue handlers
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief get size of #snd_seq_queue_info_t
|
|
|
|
|
* \return size in bytes
|
|
|
|
|
*/
|
|
|
|
|
size_t snd_seq_queue_info_sizeof()
|
|
|
|
|
{
|
|
|
|
|
return sizeof(snd_seq_queue_info_t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief allocate an empty #snd_seq_queue_info_t using standard malloc
|
|
|
|
|
* \param ptr returned pointer
|
|
|
|
|
* \return 0 on success otherwise negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_queue_info_malloc(snd_seq_queue_info_t **ptr)
|
|
|
|
|
{
|
|
|
|
|
assert(ptr);
|
|
|
|
|
*ptr = calloc(1, sizeof(snd_seq_queue_info_t));
|
|
|
|
|
if (!*ptr)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief frees a previously allocated #snd_seq_queue_info_t
|
|
|
|
|
* \param pointer to object to free
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_info_free(snd_seq_queue_info_t *obj)
|
|
|
|
|
{
|
|
|
|
|
free(obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief copy one #snd_seq_queue_info_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_info_copy(snd_seq_queue_info_t *dst, const snd_seq_queue_info_t *src)
|
|
|
|
|
{
|
|
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the queue id of a queue_info container
|
|
|
|
|
* \param info queue_info container
|
|
|
|
|
* \return queue id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_queue_info_get_queue(const snd_seq_queue_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->queue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the name of a queue_info container
|
|
|
|
|
* \param info queue_info container
|
|
|
|
|
* \return name string
|
|
|
|
|
*/
|
|
|
|
|
const char *snd_seq_queue_info_get_name(const snd_seq_queue_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the owner client id of a queue_info container
|
|
|
|
|
* \param info queue_info container
|
|
|
|
|
* \return owner client id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_queue_info_get_owner(const snd_seq_queue_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->owner;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the lock status of a queue_info container
|
|
|
|
|
* \param info queue_info container
|
|
|
|
|
* \return lock status --- non-zero = locked
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_queue_info_get_locked(const snd_seq_queue_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->locked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the conditional bit flags of a queue_info container
|
|
|
|
|
* \param info queue_info container
|
|
|
|
|
* \return conditional bit flags
|
|
|
|
|
*/
|
|
|
|
|
unsigned int snd_seq_queue_info_get_flags(const snd_seq_queue_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the name of a queue_info container
|
|
|
|
|
* \param info queue_info container
|
|
|
|
|
* \param name name string
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_info_set_name(snd_seq_queue_info_t *info, const char *name)
|
|
|
|
|
{
|
|
|
|
|
assert(info && name);
|
|
|
|
|
strncpy(info->name, name, sizeof(info->name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the owner client id of a queue_info container
|
|
|
|
|
* \param info queue_info container
|
|
|
|
|
* \param owner client id
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_info_set_owner(snd_seq_queue_info_t *info, int owner)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->owner = owner;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the lock status of a queue_info container
|
|
|
|
|
* \param info queue_info container
|
|
|
|
|
* \param locked lock status
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_info_set_locked(snd_seq_queue_info_t *info, int locked)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->locked = locked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the conditional bit flags of a queue_info container
|
|
|
|
|
* \param info queue_info container
|
|
|
|
|
* \param flags contidional bit flags
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_info_set_flags(snd_seq_queue_info_t *info, unsigned int flags)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->flags = flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_create_queue(snd_seq_t *seq, snd_seq_queue_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
assert(seq && info);
|
|
|
|
|
info->owner = seq->client;
|
|
|
|
|
err = seq->ops->create_queue(seq, info);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
return info->queue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief allocate a queue with the speicified name
|
2001-06-06 17:50:16 +00:00
|
|
|
* \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
|
2001-07-04 13:54:13 +00:00
|
|
|
*/
|
|
|
|
|
int snd_seq_alloc_named_queue(snd_seq_t *seq, const char *name)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_queue_info_t info;
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
|
info.locked = 1;
|
|
|
|
|
if (name)
|
|
|
|
|
strncpy(info.name, name, sizeof(info.name) - 1);
|
|
|
|
|
return snd_seq_create_queue(seq, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief allocate a queue
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \return the queue id (zero or positive) on success otherwise a negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_alloc_queue(snd_seq_t *seq)
|
|
|
|
|
{
|
|
|
|
|
return snd_seq_alloc_named_queue(seq, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \breif delete the specified queue
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param q queue id to delete
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_free_queue(snd_seq_t *seq, int q)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_queue_info_t info;
|
|
|
|
|
assert(seq);
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
|
info.queue = q;
|
|
|
|
|
return seq->ops->delete_queue(seq, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief obtain queue attributes
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param q queue id to query
|
|
|
|
|
* \param info information returned
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_get_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && info);
|
|
|
|
|
info->queue = q;
|
|
|
|
|
return seq->ops->get_queue_info(seq, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief change the queue attributes
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param q queue id to change
|
|
|
|
|
* \param info information changed
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_set_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && info);
|
|
|
|
|
info->queue = q;
|
|
|
|
|
return seq->ops->set_queue_info(seq, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief query the matching queue with the specified name
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param name the name string to query
|
|
|
|
|
* \return the queue id if found or negative error code
|
|
|
|
|
*
|
|
|
|
|
* Searches the matching queue with the specified name string.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_query_named_queue(snd_seq_t *seq, const char *name)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
snd_seq_queue_info_t info;
|
|
|
|
|
assert(seq && name);
|
|
|
|
|
strncpy(info.name, name, sizeof(info.name));
|
|
|
|
|
err = seq->ops->get_named_queue(seq, &info);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
return info.queue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the queue usage flag to the client
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param q queue id
|
|
|
|
|
* \param client client id
|
|
|
|
|
* \return 1 = client is allowed to access the queue, 0 = not allowed,
|
|
|
|
|
* otherwise a negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_get_queue_usage(snd_seq_t *seq, int q)
|
|
|
|
|
{
|
|
|
|
|
struct sndrv_seq_queue_client info;
|
|
|
|
|
int err;
|
|
|
|
|
assert(seq);
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
|
info.queue = q;
|
|
|
|
|
info.client = seq->client;
|
|
|
|
|
if ((err = seq->ops->get_queue_client(seq, &info)) < 0)
|
|
|
|
|
return err;
|
|
|
|
|
return info.used;
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-11 15:48:27 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Set the queue usage flag to the client
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param q queue id
|
|
|
|
|
* \param client client id
|
|
|
|
|
* \param used non-zero if the client is allowed
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_set_queue_usage(snd_seq_t *seq, int q, int used)
|
|
|
|
|
{
|
|
|
|
|
struct sndrv_seq_queue_client info;
|
|
|
|
|
assert(seq);
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
|
info.queue = q;
|
|
|
|
|
info.client = seq->client;
|
|
|
|
|
info.used = used ? 1 : 0;
|
|
|
|
|
return seq->ops->set_queue_client(seq, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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 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)
|
|
|
|
|
{
|
|
|
|
|
assert(ptr);
|
|
|
|
|
*ptr = calloc(1, sizeof(snd_seq_queue_status_t));
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
free(obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief copy one #snd_seq_queue_status_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_status_copy(snd_seq_queue_status_t *dst, const snd_seq_queue_status_t *src)
|
|
|
|
|
{
|
|
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the queue id of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \return queue id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_queue_status_get_queue(const snd_seq_queue_status_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->queue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the number of events of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \return number of events
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_queue_status_get_events(const snd_seq_queue_status_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->events;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the tick time of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \return tick time
|
|
|
|
|
*/
|
|
|
|
|
snd_seq_tick_time_t snd_seq_queue_status_get_tick_time(const snd_seq_queue_status_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->tick;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the real time of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \param time real time
|
|
|
|
|
*/
|
|
|
|
|
const snd_seq_real_time_t *snd_seq_queue_status_get_real_time(const snd_seq_queue_status_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
return (snd_seq_real_time_t *)&info->time;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the running status bits of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \return running status bits
|
|
|
|
|
*/
|
|
|
|
|
unsigned int snd_seq_queue_status_get_status(const snd_seq_queue_status_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->running;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && status);
|
|
|
|
|
memset(status, 0, sizeof(snd_seq_queue_status_t));
|
|
|
|
|
status->queue = q;
|
|
|
|
|
return seq->ops->get_queue_status(seq, status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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 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));
|
|
|
|
|
if (!*ptr)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief frees a previously allocated #snd_seq_queue_tempo_t
|
|
|
|
|
* \param pointer to object to free
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_queue_tempo_free(snd_seq_queue_tempo_t *obj)
|
2000-09-05 17:15:11 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
free(obj);
|
2000-09-05 17:15:11 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief copy one #snd_seq_queue_tempo_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_queue_tempo_copy(snd_seq_queue_tempo_t *dst, const snd_seq_queue_tempo_t *src)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the queue id of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \return queue id
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_queue_tempo_get_queue(const snd_seq_queue_tempo_t *info)
|
1999-11-16 15:07:05 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return info->queue;
|
1999-11-16 15:07:05 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the tempo of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \return tempo value
|
|
|
|
|
*/
|
|
|
|
|
unsigned int snd_seq_queue_tempo_get_tempo(const snd_seq_queue_tempo_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->tempo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the ppq of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \return ppq value
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_queue_tempo_get_ppq(const snd_seq_queue_tempo_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->ppq;
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-10 16:45:05 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Get the timer skew value of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \return timer skew value
|
|
|
|
|
*/
|
|
|
|
|
unsigned int snd_seq_queue_tempo_get_skew(const snd_seq_queue_tempo_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->skew_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the timer skew base value of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \return timer skew base value
|
|
|
|
|
*/
|
|
|
|
|
unsigned int snd_seq_queue_tempo_get_skew_base(const snd_seq_queue_tempo_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->skew_base;
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Set the tempo of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \param tempo tempo value
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_tempo_set_tempo(snd_seq_queue_tempo_t *info, unsigned int tempo)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->tempo = tempo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the ppq of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \param ppq ppq value
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_tempo_set_ppq(snd_seq_queue_tempo_t *info, int ppq)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->ppq = ppq;
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-10 16:45:05 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Set the timer skew value of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \param skew timer skew value
|
|
|
|
|
*
|
|
|
|
|
* The skew of timer is calculated as skew / base.
|
|
|
|
|
* For example, to play with double speed, pass base * 2 as the skew value.
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_tempo_set_skew(snd_seq_queue_tempo_t *info, unsigned int skew)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->skew_value = skew;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the timer skew base value of a queue_status container
|
|
|
|
|
* \param info queue_status container
|
|
|
|
|
* \param base timer skew base value
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_tempo_set_skew_base(snd_seq_queue_tempo_t *info, unsigned int base)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->skew_base = base;
|
|
|
|
|
}
|
2001-07-04 13:54:13 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief obtain the current tempo of the queue
|
2001-06-06 17:50:16 +00:00
|
|
|
* \param seq sequencer handle
|
2001-07-04 13:54:13 +00:00
|
|
|
* \param q queue id to be queried
|
|
|
|
|
* \param tempo pointer to store the current tempo
|
2001-06-06 17:50:16 +00:00
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_get_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo)
|
1999-11-16 15:07:05 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(seq && tempo);
|
|
|
|
|
memset(tempo, 0, sizeof(snd_seq_queue_tempo_t));
|
|
|
|
|
tempo->queue = q;
|
|
|
|
|
return seq->ops->get_queue_tempo(seq, tempo);
|
1999-11-16 15:07:05 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief set the tempo of the queue
|
2001-06-06 17:50:16 +00:00
|
|
|
* \param seq sequencer handle
|
2001-07-04 13:54:13 +00:00
|
|
|
* \param q queue id to change the tempo
|
|
|
|
|
* \param tempo tempo information
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_set_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo)
|
1999-11-16 15:07:05 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(seq && tempo);
|
|
|
|
|
tempo->queue = q;
|
|
|
|
|
return seq->ops->set_queue_tempo(seq, tempo);
|
1999-11-16 15:07:05 +00:00
|
|
|
}
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
|
2000-03-18 18:03:50 +00:00
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \brief get size of #snd_seq_queue_timer_t
|
|
|
|
|
* \return size in bytes
|
2000-09-05 17:15:11 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
size_t snd_seq_queue_timer_sizeof()
|
|
|
|
|
{
|
|
|
|
|
return sizeof(snd_seq_queue_timer_t);
|
|
|
|
|
}
|
2000-09-05 17:15:11 +00:00
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief allocate an empty #snd_seq_queue_timer_t using standard malloc
|
|
|
|
|
* \param ptr returned pointer
|
|
|
|
|
* \return 0 on success otherwise negative error code
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_queue_timer_malloc(snd_seq_queue_timer_t **ptr)
|
2000-09-05 17:15:11 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(ptr);
|
|
|
|
|
*ptr = calloc(1, sizeof(snd_seq_queue_timer_t));
|
|
|
|
|
if (!*ptr)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2000-09-05 17:15:11 +00:00
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \brief frees a previously allocated #snd_seq_queue_timer_t
|
|
|
|
|
* \param pointer to object to free
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_timer_free(snd_seq_queue_timer_t *obj)
|
|
|
|
|
{
|
|
|
|
|
free(obj);
|
2000-09-05 17:15:11 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief copy one #snd_seq_queue_timer_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_queue_timer_copy(snd_seq_queue_timer_t *dst, const snd_seq_queue_timer_t *src)
|
2000-09-05 17:15:11 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
|
|
|
|
}
|
2000-09-05 17:15:11 +00:00
|
|
|
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Get the queue id of a queue_timer container
|
|
|
|
|
* \param info queue_timer container
|
|
|
|
|
* \return queue id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_queue_timer_get_queue(const snd_seq_queue_timer_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->queue;
|
2000-09-05 17:15:11 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the timer type of a queue_timer container
|
|
|
|
|
* \param info queue_timer container
|
|
|
|
|
* \return timer type
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-08-28 08:03:19 +00:00
|
|
|
snd_seq_queue_timer_type_t snd_seq_queue_timer_get_type(const snd_seq_queue_timer_t *info)
|
2000-09-05 17:15:11 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
2001-08-28 08:03:19 +00:00
|
|
|
return (snd_seq_queue_timer_type_t)info->type;
|
2000-09-05 17:15:11 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the timer id of a queue_timer container
|
|
|
|
|
* \param info queue_timer container
|
|
|
|
|
* \return timer id pointer
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
const snd_timer_id_t *snd_seq_queue_timer_get_id(const snd_seq_queue_timer_t *info)
|
2000-09-05 17:15:11 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
return &info->u.alsa.id;
|
|
|
|
|
}
|
2000-09-05 17:15:11 +00:00
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Get the timer resolution of a queue_timer container
|
|
|
|
|
* \param info queue_timer container
|
|
|
|
|
* \return timer resolution
|
|
|
|
|
*/
|
|
|
|
|
unsigned int snd_seq_queue_timer_get_resolution(const snd_seq_queue_timer_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->u.alsa.resolution;
|
2000-09-05 17:15:11 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Set the timer type of a queue_timer container
|
|
|
|
|
* \param info queue_timer container
|
|
|
|
|
* \param type timer type
|
|
|
|
|
*/
|
2001-08-28 08:03:19 +00:00
|
|
|
void snd_seq_queue_timer_set_type(snd_seq_queue_timer_t *info, snd_seq_queue_timer_type_t type)
|
2001-07-04 13:54:13 +00:00
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-28 08:03:19 +00:00
|
|
|
info->type = (int)type;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the timer id of a queue_timer container
|
|
|
|
|
* \param info queue_timer container
|
|
|
|
|
* \param id timer id pointer
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_queue_timer_set_id(snd_seq_queue_timer_t *info, const snd_timer_id_t *id)
|
2000-09-05 17:15:11 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info && id);
|
|
|
|
|
info->u.alsa.id = *id;
|
|
|
|
|
}
|
2000-09-05 17:15:11 +00:00
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Set the timer resolution of a queue_timer container
|
|
|
|
|
* \param info queue_timer container
|
|
|
|
|
* \param resolution timer resolution
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_queue_timer_set_resolution(snd_seq_queue_timer_t *info, unsigned int resolution)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->u.alsa.resolution = resolution;
|
2000-09-05 17:15:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \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
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_get_queue_timer(snd_seq_t *seq, int q, snd_seq_queue_timer_t * timer)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && timer);
|
|
|
|
|
memset(timer, 0, sizeof(snd_seq_queue_timer_t));
|
|
|
|
|
timer->queue = q;
|
|
|
|
|
return seq->ops->get_queue_timer(seq, timer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_set_queue_timer(snd_seq_t *seq, int q, snd_seq_queue_timer_t * timer)
|
|
|
|
|
{
|
|
|
|
|
assert(seq && timer);
|
|
|
|
|
timer->queue = q;
|
|
|
|
|
return seq->ops->set_queue_timer(seq, timer);
|
|
|
|
|
}
|
2000-09-05 17:15:11 +00:00
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief create an event cell
|
|
|
|
|
* \return the cell pointer allocated
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
1998-12-27 00:59:08 +00:00
|
|
|
snd_seq_event_t *snd_seq_create_event(void)
|
|
|
|
|
{
|
|
|
|
|
return (snd_seq_event_t *) calloc(1, sizeof(snd_seq_event_t));
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief free an event
|
|
|
|
|
*
|
|
|
|
|
* this is obsolete. only for compatibility
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2000-08-31 11:56:52 +00:00
|
|
|
int snd_seq_free_event(snd_seq_event_t *ev ATTRIBUTE_UNUSED)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief calculates the (encoded) byte-stream size of the event
|
|
|
|
|
* \param ev the event
|
|
|
|
|
* \return the size of decoded bytes
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2000-05-08 18:53:38 +00:00
|
|
|
ssize_t snd_seq_event_length(snd_seq_event_t *ev)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2000-05-08 18:53:38 +00:00
|
|
|
ssize_t len = sizeof(snd_seq_event_t);
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(ev);
|
2001-07-04 13:54:13 +00:00
|
|
|
if (sndrv_seq_ev_is_variable(ev))
|
1998-12-27 00:59:08 +00:00
|
|
|
len += ev->data.ext.len;
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-18 18:03:50 +00:00
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* output to sequencer
|
|
|
|
|
*/
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \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.
|
2001-09-26 15:32:06 +00:00
|
|
|
* The output buffer will be drained automatically if it becomes full.
|
2001-06-06 17:50:16 +00:00
|
|
|
*
|
2001-09-26 15:32:06 +00:00
|
|
|
* If events remain unprocessed on output buffer before drained,
|
2001-06-06 17:50:16 +00:00
|
|
|
* the size of total byte data on output buffer is returned.
|
|
|
|
|
* If the output buffer is empty, this returns zero.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
1999-06-15 22:26:21 +00:00
|
|
|
int snd_seq_event_output(snd_seq_t *seq, snd_seq_event_t *ev)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2000-03-18 18:03:50 +00:00
|
|
|
int result;
|
|
|
|
|
|
|
|
|
|
result = snd_seq_event_output_buffer(seq, ev);
|
|
|
|
|
if (result == -EAGAIN) {
|
2000-09-29 20:49:18 +00:00
|
|
|
result = snd_seq_drain_output(seq);
|
2000-03-18 18:03:50 +00:00
|
|
|
if (result < 0)
|
|
|
|
|
return result;
|
|
|
|
|
return snd_seq_event_output_buffer(seq, ev);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-09-26 15:32:06 +00:00
|
|
|
* \brief output an event onto the lib buffer without draining buffer
|
2001-06-06 17:50:16 +00:00
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param ev event ot be output
|
2001-09-26 15:32:06 +00:00
|
|
|
* \return the byte size of remaining events. \c -EAGAIN if the buffer becomes full.
|
|
|
|
|
*
|
|
|
|
|
* This function doesn't drain buffer unlike snd_seq_event_output().
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
|
|
|
|
int snd_seq_event_output_buffer(snd_seq_t *seq, snd_seq_event_t *ev)
|
|
|
|
|
{
|
|
|
|
|
int len;
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq && ev);
|
1998-12-27 00:59:08 +00:00
|
|
|
len = snd_seq_event_length(ev);
|
1999-12-30 15:21:52 +00:00
|
|
|
if (len < 0)
|
|
|
|
|
return -EINVAL;
|
2000-10-30 17:54:55 +00:00
|
|
|
if ((size_t) len >= seq->obufsize)
|
|
|
|
|
return -EINVAL;
|
2000-05-08 18:53:38 +00:00
|
|
|
if ((seq->obufsize - seq->obufused) < (size_t) len)
|
2000-03-18 18:03:50 +00:00
|
|
|
return -EAGAIN;
|
1998-12-27 00:59:08 +00:00
|
|
|
memcpy(seq->obuf + seq->obufused, ev, sizeof(snd_seq_event_t));
|
|
|
|
|
seq->obufused += sizeof(snd_seq_event_t);
|
2001-07-04 13:54:13 +00:00
|
|
|
if (sndrv_seq_ev_is_variable(ev)) {
|
1998-12-27 00:59:08 +00:00
|
|
|
memcpy(seq->obuf + seq->obufused, ev->data.ext.ptr, ev->data.ext.len);
|
|
|
|
|
seq->obufused += ev->data.ext.len;
|
|
|
|
|
}
|
|
|
|
|
return seq->obufused;
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-29 11:39:08 +00:00
|
|
|
/*
|
|
|
|
|
* allocate the temporary buffer
|
|
|
|
|
*/
|
|
|
|
|
static int alloc_tmpbuf(snd_seq_t *seq, size_t len)
|
|
|
|
|
{
|
|
|
|
|
size_t size = ((len + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t));
|
|
|
|
|
if (seq->tmpbuf == NULL) {
|
|
|
|
|
if (size > DEFAULT_TMPBUF_SIZE)
|
|
|
|
|
seq->tmpbufsize = size;
|
|
|
|
|
else
|
|
|
|
|
seq->tmpbufsize = DEFAULT_TMPBUF_SIZE;
|
|
|
|
|
seq->tmpbuf = malloc(seq->tmpbufsize * sizeof(snd_seq_event_t));
|
|
|
|
|
if (seq->tmpbuf == NULL)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
} else if (len > seq->tmpbufsize) {
|
|
|
|
|
seq->tmpbuf = realloc(seq->tmpbuf, size * sizeof(snd_seq_event_t));
|
|
|
|
|
if (seq->tmpbuf == NULL)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
seq->tmpbufsize = size;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief output an event directly to the sequencer NOT through output buffer
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
* \param ev event to be output
|
2001-09-26 15:32:06 +00:00
|
|
|
* \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.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
|
|
|
|
int snd_seq_event_output_direct(snd_seq_t *seq, snd_seq_event_t *ev)
|
|
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
ssize_t len;
|
2000-08-29 11:39:08 +00:00
|
|
|
void *buf;
|
2000-03-18 18:03:50 +00:00
|
|
|
|
|
|
|
|
len = snd_seq_event_length(ev);
|
2000-08-29 11:39:08 +00:00
|
|
|
if (len < 0)
|
|
|
|
|
return len;
|
|
|
|
|
else if (len == sizeof(*ev)) {
|
|
|
|
|
buf = ev;
|
2000-03-18 18:03:50 +00:00
|
|
|
} else {
|
2000-08-29 11:39:08 +00:00
|
|
|
if (alloc_tmpbuf(seq, (size_t)len) < 0)
|
2000-03-18 18:03:50 +00:00
|
|
|
return -ENOMEM;
|
2000-08-29 11:39:08 +00:00
|
|
|
*seq->tmpbuf = *ev;
|
|
|
|
|
memcpy(seq->tmpbuf + 1, ev->data.ext.ptr, ev->data.ext.len);
|
|
|
|
|
buf = seq->tmpbuf;
|
2000-03-18 18:03:50 +00:00
|
|
|
}
|
2001-03-29 17:50:28 +00:00
|
|
|
return seq->ops->write(seq, buf, (size_t) len);
|
2000-03-18 18:03:50 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief return the size of pending events on output buffer
|
|
|
|
|
* \param seq sequencer handle
|
2001-09-26 15:32:06 +00:00
|
|
|
* \return the byte size of total of pending events
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
|
|
|
|
int snd_seq_event_output_pending(snd_seq_t *seq)
|
|
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq);
|
2000-03-18 18:03:50 +00:00
|
|
|
return seq->obufused;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief drain output buffer to sequencer
|
|
|
|
|
* \param seq sequencer handle
|
2001-09-26 15:32:06 +00:00
|
|
|
* \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.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2000-09-29 20:49:18 +00:00
|
|
|
int snd_seq_drain_output(snd_seq_t *seq)
|
2000-03-18 18:03:50 +00:00
|
|
|
{
|
2001-09-26 15:32:06 +00:00
|
|
|
ssize_t result, processed = 0;
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq);
|
2000-03-18 18:03:50 +00:00
|
|
|
while (seq->obufused > 0) {
|
2000-11-20 20:10:46 +00:00
|
|
|
result = seq->ops->write(seq, seq->obuf, seq->obufused);
|
2001-09-26 15:32:06 +00:00
|
|
|
if (result < 0) {
|
|
|
|
|
if (result == -EAGAIN && processed)
|
|
|
|
|
return seq->obufused;
|
2001-09-06 09:09:24 +00:00
|
|
|
return result;
|
2001-09-26 15:32:06 +00:00
|
|
|
}
|
2000-05-08 18:53:38 +00:00
|
|
|
if ((size_t)result < seq->obufused)
|
2000-03-18 18:03:50 +00:00
|
|
|
memmove(seq->obuf, seq->obuf + result, seq->obufused - result);
|
|
|
|
|
seq->obufused -= result;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \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.
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
|
|
|
|
int snd_seq_extract_output(snd_seq_t *seq, snd_seq_event_t **ev_res)
|
|
|
|
|
{
|
2000-08-04 10:24:12 +00:00
|
|
|
size_t len, olen;
|
2000-08-29 11:39:08 +00:00
|
|
|
snd_seq_event_t ev;
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq);
|
2000-03-18 18:03:50 +00:00
|
|
|
if (ev_res)
|
|
|
|
|
*ev_res = NULL;
|
2000-08-29 11:39:08 +00:00
|
|
|
if ((olen = seq->obufused) < sizeof(snd_seq_event_t))
|
2000-03-18 18:03:50 +00:00
|
|
|
return -ENOENT;
|
2000-08-29 11:39:08 +00:00
|
|
|
memcpy(&ev, (snd_seq_event_t*)seq->obuf, sizeof(snd_seq_event_t));
|
|
|
|
|
len = snd_seq_event_length(&ev);
|
2000-03-18 18:03:50 +00:00
|
|
|
if (ev_res) {
|
|
|
|
|
/* extract the event */
|
2000-08-29 11:39:08 +00:00
|
|
|
if (alloc_tmpbuf(seq, len) < 0)
|
2000-03-18 18:03:50 +00:00
|
|
|
return -ENOMEM;
|
2000-08-29 11:39:08 +00:00
|
|
|
memcpy(seq->tmpbuf, seq->obuf, len);
|
|
|
|
|
*ev_res = seq->tmpbuf;
|
2000-03-18 18:03:50 +00:00
|
|
|
}
|
2000-08-29 11:39:08 +00:00
|
|
|
seq->obufused = olen - len;
|
|
|
|
|
memmove(seq->obuf, seq->obuf + len, seq->obufused);
|
2000-03-18 18:03:50 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* input from sequencer
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
2000-08-29 11:39:08 +00:00
|
|
|
* read from sequencer to input buffer
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2000-08-29 11:39:08 +00:00
|
|
|
static ssize_t snd_seq_event_read_buffer(snd_seq_t *seq)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2000-08-29 11:39:08 +00:00
|
|
|
ssize_t len;
|
2000-11-20 20:10:46 +00:00
|
|
|
len = seq->ops->read(seq, seq->ibuf, seq->ibufsize * sizeof(snd_seq_event_t));
|
2000-08-29 11:39:08 +00:00
|
|
|
if (len < 0)
|
2000-11-20 20:10:46 +00:00
|
|
|
return len;
|
2000-08-29 11:39:08 +00:00
|
|
|
seq->ibuflen = len / sizeof(snd_seq_event_t);
|
|
|
|
|
seq->ibufptr = 0;
|
|
|
|
|
return seq->ibuflen;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2000-08-29 11:39:08 +00:00
|
|
|
static int snd_seq_event_retrieve_buffer(snd_seq_t *seq, snd_seq_event_t **retp)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2000-08-31 11:56:52 +00:00
|
|
|
size_t ncells;
|
2000-08-29 11:39:08 +00:00
|
|
|
snd_seq_event_t *ev;
|
1998-12-27 00:59:08 +00:00
|
|
|
|
2000-08-29 11:39:08 +00:00
|
|
|
*retp = ev = &seq->ibuf[seq->ibufptr];
|
|
|
|
|
seq->ibufptr++;
|
|
|
|
|
seq->ibuflen--;
|
2001-07-04 13:54:13 +00:00
|
|
|
if (! sndrv_seq_ev_is_variable(ev))
|
2000-08-29 11:39:08 +00:00
|
|
|
return 1;
|
|
|
|
|
ncells = (ev->data.ext.len + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t);
|
|
|
|
|
if (seq->ibuflen < ncells) {
|
|
|
|
|
seq->ibuflen = 0; /* clear buffer */
|
|
|
|
|
*retp = NULL;
|
1998-12-27 00:59:08 +00:00
|
|
|
return -EINVAL;
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
}
|
2000-08-29 11:39:08 +00:00
|
|
|
ev->data.ext.ptr = ev + 1;
|
|
|
|
|
seq->ibuflen -= ncells;
|
|
|
|
|
seq->ibufptr += ncells;
|
|
|
|
|
return 1;
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \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 recives 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 succeedingly, events are extract 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.
|
|
|
|
|
*
|
2001-09-26 15:32:06 +00:00
|
|
|
* Function returns the byte size of remaining events on the input buffer
|
2001-06-06 17:50:16 +00:00
|
|
|
* if an event is successfully received.
|
|
|
|
|
* Application can determine from the returned value whether to call
|
|
|
|
|
* input once more or not.
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
*/
|
|
|
|
|
int snd_seq_event_input(snd_seq_t *seq, snd_seq_event_t **ev)
|
|
|
|
|
{
|
2000-08-29 11:39:08 +00:00
|
|
|
int err;
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq);
|
1998-12-27 00:59:08 +00:00
|
|
|
*ev = NULL;
|
2000-08-29 11:39:08 +00:00
|
|
|
if (seq->ibuflen <= 0) {
|
2000-08-31 11:56:52 +00:00
|
|
|
if ((err = snd_seq_event_read_buffer(seq)) < 0)
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-29 11:39:08 +00:00
|
|
|
return snd_seq_event_retrieve_buffer(seq, ev);
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* read input data from sequencer if available
|
|
|
|
|
*/
|
2000-11-20 20:10:46 +00:00
|
|
|
static int snd_seq_event_input_feed(snd_seq_t *seq, int timeout)
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
struct pollfd pfd;
|
|
|
|
|
int err;
|
|
|
|
|
pfd.fd = seq->poll_fd;
|
|
|
|
|
pfd.events = POLLIN;
|
|
|
|
|
err = poll(&pfd, 1, timeout);
|
|
|
|
|
if (err < 0) {
|
|
|
|
|
SYSERR("poll");
|
1998-12-27 00:59:08 +00:00
|
|
|
return -errno;
|
2000-11-20 20:10:46 +00:00
|
|
|
}
|
|
|
|
|
if (pfd.revents & POLLIN)
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
return snd_seq_event_read_buffer(seq);
|
2000-08-29 11:39:08 +00:00
|
|
|
return seq->ibuflen;
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-09-26 15:32:06 +00:00
|
|
|
* \brief check events in input buffer
|
|
|
|
|
* \return the byte size of remaining input events on input buffer.
|
2001-06-06 17:50:16 +00:00
|
|
|
*
|
|
|
|
|
* If events remain on the input buffer of user-space, function returns
|
2001-09-26 15:32:06 +00:00
|
|
|
* the total byte size of events on it.
|
2001-06-06 17:50:16 +00:00
|
|
|
* If fetch_sequencer argument is non-zero,
|
2001-09-26 15:32:06 +00:00
|
|
|
* 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.
|
2001-06-06 17:50:16 +00:00
|
|
|
* If fetch_sequencer argument is zero and
|
|
|
|
|
* no events remain on the input buffer, function simplly returns zero.
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
*/
|
|
|
|
|
int snd_seq_event_input_pending(snd_seq_t *seq, int fetch_sequencer)
|
|
|
|
|
{
|
2000-08-29 11:39:08 +00:00
|
|
|
if (seq->ibuflen == 0 && fetch_sequencer) {
|
2000-11-20 20:10:46 +00:00
|
|
|
return snd_seq_event_input_feed(seq, 0);
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
}
|
2000-08-29 11:39:08 +00:00
|
|
|
return seq->ibuflen;
|
1998-12-27 00:59:08 +00:00
|
|
|
}
|
|
|
|
|
|
2000-03-18 18:03:50 +00:00
|
|
|
/*----------------------------------------------------------------*/
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
|
|
|
|
|
/*
|
2000-03-18 18:03:50 +00:00
|
|
|
* clear event buffers
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
*/
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief remove all events on user-space output buffer
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
*
|
|
|
|
|
* Removes all events on user-space output buffer.
|
2001-09-26 15:32:06 +00:00
|
|
|
* Unlike snd_seq_drain_output(), this function doesn't remove
|
2001-06-06 17:50:16 +00:00
|
|
|
* events on output memory pool of sequencer.
|
1999-12-30 15:21:52 +00:00
|
|
|
*/
|
2000-09-29 20:49:18 +00:00
|
|
|
int snd_seq_drop_output_buffer(snd_seq_t *seq)
|
1999-12-30 15:21:52 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq);
|
1999-12-30 15:21:52 +00:00
|
|
|
seq->obufused = 0;
|
2000-01-03 10:25:56 +00:00
|
|
|
return 0;
|
1999-12-30 15:21:52 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief remove all events on user-space input FIFO
|
|
|
|
|
* \param seq sequencer handle
|
1999-12-30 15:21:52 +00:00
|
|
|
*/
|
2000-09-29 20:49:18 +00:00
|
|
|
int snd_seq_drop_input_buffer(snd_seq_t *seq)
|
1999-12-30 15:21:52 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq);
|
2000-08-29 11:39:08 +00:00
|
|
|
seq->ibufptr = 0;
|
|
|
|
|
seq->ibuflen = 0;
|
1999-12-30 15:21:52 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \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.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_drop_output(snd_seq_t *seq)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_remove_events_t rminfo;
|
|
|
|
|
assert(seq);
|
|
|
|
|
seq->obufused = 0; /* drain output buffer */
|
|
|
|
|
|
|
|
|
|
memset(&rminfo, 0, sizeof(rminfo));
|
|
|
|
|
rminfo.remove_mode = SNDRV_SEQ_REMOVE_OUTPUT;
|
|
|
|
|
|
|
|
|
|
return snd_seq_remove_events(seq, &rminfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief clear input buffer and and remove events in sequencer queue
|
|
|
|
|
* \param seq sequencer handle
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_drop_input(snd_seq_t *seq)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_remove_events_t rminfo;
|
|
|
|
|
assert(seq);
|
|
|
|
|
|
|
|
|
|
seq->ibufptr = 0; /* drain input buffer */
|
|
|
|
|
seq->ibuflen = 0;
|
|
|
|
|
|
|
|
|
|
memset(&rminfo, 0, sizeof(rminfo));
|
|
|
|
|
rminfo.remove_mode = SNDRV_SEQ_REMOVE_INPUT;
|
|
|
|
|
|
|
|
|
|
return snd_seq_remove_events(seq, &rminfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \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));
|
|
|
|
|
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 copy one #snd_seq_remove_events_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_remove_events_copy(snd_seq_remove_events_t *dst, const snd_seq_remove_events_t *src)
|
|
|
|
|
{
|
|
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the removal condition bits
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \return removal condition bits
|
|
|
|
|
*/
|
|
|
|
|
unsigned int snd_seq_remove_events_get_condition(const snd_seq_remove_events_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->remove_mode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the queue as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \return queue id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_remove_events_get_queue(const snd_seq_remove_events_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->queue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the event timestamp as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \return time stamp
|
|
|
|
|
*/
|
|
|
|
|
const snd_seq_timestamp_t *snd_seq_remove_events_get_time(const snd_seq_remove_events_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
return (snd_seq_timestamp_t *)&info->time;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the event destination address as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \return destination address
|
|
|
|
|
*/
|
|
|
|
|
const snd_seq_addr_t *snd_seq_remove_events_get_dest(const snd_seq_remove_events_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
return (snd_seq_addr_t *)&info->dest;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the event channel as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \return channel number
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_remove_events_get_channel(const snd_seq_remove_events_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->channel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the event type as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \return event type
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_remove_events_get_event_type(const snd_seq_remove_events_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the event tag id as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \return tag id
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_remove_events_get_tag(const snd_seq_remove_events_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->tag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the removal condition bits
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \param flags removal condition bits
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_remove_events_set_condition(snd_seq_remove_events_t *info, unsigned int flags)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->remove_mode = flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the queue as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \param queue queue id
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_remove_events_set_queue(snd_seq_remove_events_t *info, int queue)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->queue = queue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the timestamp as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \param time timestamp pointer
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_remove_events_set_time(snd_seq_remove_events_t *info, const snd_seq_timestamp_t *time)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
info->time = *(union sndrv_seq_timestamp *)time;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the destination address as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \param addr destination address
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_remove_events_set_dest(snd_seq_remove_events_t *info, const snd_seq_addr_t *addr)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
info->dest = *(struct sndrv_seq_addr *)addr;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the channel as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \param channel channel number
|
Takashi Iwai <iwai@ww.uni-erlangen.de>
Wed, 22 Dec 1999 15:51:37 +0100
Changes in alsa-driver:
1. SND_SEQ_DEST_DIRECT was removed. For direct dispatching, specify
the scheduling queue as SND_SEQ_QUEUE_DIRECT.
Source compatibility is kept if alsa-lib functions are used to set
or check direct mode.
Tested: pmidi, playmidi1, aconnect, aseqview, OSS emulation
2. The error event can be bounced to the sender as an encapsulated
event with SND_SEQ_EVENT_BOUNCE type. If the orignal event is
variable length (like SYSEX), the data body is added after the
copied event data. (To access to it, use
snd_seq_event_bounce_ext_data() macro.)
This feature is enabled only when the sender is opened with read
flag and has a client-filter flag SND_SEQ_FILTER_BOUNCE, so that
as default it is disabled.
3. Maximum size of VARIABLE length event is defined as 2048 bytes.
Larger events will be refused.
Note that this is not the size of VARUSR nor VARIPC event.
4. Return error code was revised.
Possible errors for read():
-ENXIO invalid client or file open mode
-ENOSPC FIFO overflow (the flag is cleared after this error report)
-EINVAL no enough user-space buffer to write the whole event
-EFAULT seg. fault during copy to user space
Possible errors for write():
-ENXIO invalid client or file open mode
-ENOMEM malloc failed
-EFAULT seg. fault during copy from user space
-EINVAL invalid event
-EAGAIN no space in output pool
-EINTR interrupts while sleep
-EMLINK too many hops
others depends on return value from driver event_input callback
Changes in alsa-lib:
5. Behavior of snd_seq_flush_output() was changed.
It flushes data in output buffer as much as possible. This has
two advantages. One is that most data can be sent at one call,
and another is that the error in write() can be detected directly
from this function.
The demerit of this implementation is that in non-blocking mode, it
tries twice write() even if write pool of sequencer is full, which
is not actually error. In this case, flush_output() always returns
-EAGAIN error code.
After an error is detected (except for -EAGAIN in non-blocking
mode), you should remove the error event via
snd_seq_extract_output() as below. Otherwise, it'll remain in
output buffer and cause the same error again.
6. Some functions were added:
snd_seq_exract_output(seq, &event)
This extracts the first event on *output* buffer. This will
be useful to know (and remove) the event which causes error in
write().
snd_seq_event_input_pending(seq, fetch)
Retunrs the number of events on input buffer.
If no events exist in input buffer, it fetches from sequencer
(only when flag is true).
snd_seq_event_input_selective(seq, &ev, type, blocking)
Retrieve the event from input with the given event type.
If blocking is true, it waits until the target event is
received. It'll be useful for checking bounced error or
waiting for hand-shake results (eg. loading insruments).
1999-12-22 15:05:51 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_remove_events_set_channel(snd_seq_remove_events_t *info, int channel)
|
1998-12-27 00:59:08 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
info->channel = channel;
|
1999-12-30 15:21:52 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Set the event type as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \param type event type
|
1999-12-30 15:21:52 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
void snd_seq_remove_events_set_event_type(snd_seq_remove_events_t *info, int type)
|
1999-12-30 15:21:52 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(info);
|
|
|
|
|
info->type = type;
|
|
|
|
|
}
|
1999-12-30 15:21:52 +00:00
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \brief Set the event tag as removal condition
|
|
|
|
|
* \param info remove_events container
|
|
|
|
|
* \param tag tag id
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_remove_events_set_tag(snd_seq_remove_events_t *info, int tag)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->tag = tag;
|
1999-08-19 16:35:48 +00:00
|
|
|
}
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
|
1999-08-19 16:35:48 +00:00
|
|
|
/* compare timestamp between events */
|
|
|
|
|
/* return 1 if a >= b; otherwise return 0 */
|
2001-08-20 13:15:30 +00:00
|
|
|
static inline int snd_seq_compare_tick_time(snd_seq_tick_time_t *a, snd_seq_tick_time_t *b)
|
1999-08-19 16:35:48 +00:00
|
|
|
{
|
|
|
|
|
/* compare ticks */
|
|
|
|
|
return (*a >= *b);
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-20 13:15:30 +00:00
|
|
|
static inline int snd_seq_compare_real_time(snd_seq_real_time_t *a, snd_seq_real_time_t *b)
|
1999-08-19 16:35:48 +00:00
|
|
|
{
|
|
|
|
|
/* compare real time */
|
|
|
|
|
if (a->tv_sec > b->tv_sec)
|
|
|
|
|
return 1;
|
|
|
|
|
if ((a->tv_sec == b->tv_sec) && (a->tv_nsec >= b->tv_nsec))
|
|
|
|
|
return 1;
|
1998-12-27 00:59:08 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-19 16:35:48 +00:00
|
|
|
/* Routine to match events to be removed */
|
2001-07-04 13:54:13 +00:00
|
|
|
static int remove_match(snd_seq_remove_events_t *info, snd_seq_event_t *ev)
|
1999-08-19 16:35:48 +00:00
|
|
|
{
|
|
|
|
|
int res;
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) {
|
1999-08-19 16:35:48 +00:00
|
|
|
if (ev->dest.client != info->dest.client ||
|
|
|
|
|
ev->dest.port != info->dest.port)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-07-04 13:54:13 +00:00
|
|
|
if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST_CHANNEL) {
|
|
|
|
|
if (! sndrv_seq_ev_is_channel_type(ev))
|
1999-12-15 18:34:12 +00:00
|
|
|
return 0;
|
|
|
|
|
/* data.note.channel and data.control.channel are identical */
|
|
|
|
|
if (ev->data.note.channel != info->channel)
|
1999-08-19 16:35:48 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2001-07-04 13:54:13 +00:00
|
|
|
if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_AFTER) {
|
|
|
|
|
if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
|
2001-08-20 13:15:30 +00:00
|
|
|
res = snd_seq_compare_tick_time(&ev->time.tick, (snd_seq_tick_time_t *)&info->time.tick);
|
1999-08-19 16:35:48 +00:00
|
|
|
else
|
2001-08-20 13:15:30 +00:00
|
|
|
res = snd_seq_compare_real_time(&ev->time.time, (snd_seq_real_time_t *)&info->time.time);
|
1999-08-19 16:35:48 +00:00
|
|
|
if (!res)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-07-04 13:54:13 +00:00
|
|
|
if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_BEFORE) {
|
|
|
|
|
if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
|
2001-08-20 13:15:30 +00:00
|
|
|
res = snd_seq_compare_tick_time(&ev->time.tick, (snd_seq_tick_time_t *)&info->time.tick);
|
1999-08-19 16:35:48 +00:00
|
|
|
else
|
2001-08-20 13:15:30 +00:00
|
|
|
res = snd_seq_compare_real_time(&ev->time.time, (snd_seq_real_time_t *)&info->time.time);
|
1999-08-19 16:35:48 +00:00
|
|
|
if (res)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-07-04 13:54:13 +00:00
|
|
|
if (info->remove_mode & SNDRV_SEQ_REMOVE_EVENT_TYPE) {
|
1999-08-19 16:35:48 +00:00
|
|
|
if (ev->type != info->type)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-07-04 13:54:13 +00:00
|
|
|
if (info->remove_mode & SNDRV_SEQ_REMOVE_IGNORE_OFF) {
|
1999-08-19 16:35:48 +00:00
|
|
|
/* Do not remove off events */
|
|
|
|
|
switch (ev->type) {
|
2001-07-04 13:54:13 +00:00
|
|
|
case SNDRV_SEQ_EVENT_NOTEOFF:
|
|
|
|
|
/* case SNDRV_SEQ_EVENT_SAMPLE_STOP: */
|
1999-08-19 16:35:48 +00:00
|
|
|
return 0;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-07-04 13:54:13 +00:00
|
|
|
if (info->remove_mode & SNDRV_SEQ_REMOVE_TAG_MATCH) {
|
1999-08-19 16:35:48 +00:00
|
|
|
if (info->tag != ev->tag)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief remove events on input/output buffers
|
|
|
|
|
* \param seq sequencer handle
|
2001-07-04 13:54:13 +00:00
|
|
|
* \param rmp remove event container
|
2001-06-06 17:50:16 +00:00
|
|
|
*
|
|
|
|
|
* Removes matching events with the given condition from input/output buffers.
|
|
|
|
|
* The removal condition is specified in rmp argument.
|
1999-08-19 16:35:48 +00:00
|
|
|
*/
|
|
|
|
|
int snd_seq_remove_events(snd_seq_t *seq, snd_seq_remove_events_t *rmp)
|
|
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
if (rmp->remove_mode & SNDRV_SEQ_REMOVE_INPUT) {
|
1999-08-19 16:35:48 +00:00
|
|
|
/*
|
|
|
|
|
* First deal with any events that are still buffered
|
|
|
|
|
* in the library.
|
|
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
snd_seq_drop_input_buffer(seq);
|
1999-08-19 16:35:48 +00:00
|
|
|
}
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
if (rmp->remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) {
|
1999-08-19 16:35:48 +00:00
|
|
|
/*
|
|
|
|
|
* First deal with any events that are still buffered
|
|
|
|
|
* in the library.
|
|
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
if (rmp->remove_mode & ~(SNDRV_SEQ_REMOVE_INPUT|SNDRV_SEQ_REMOVE_OUTPUT)) {
|
1999-12-30 15:21:52 +00:00
|
|
|
/* The simple case - remove all */
|
2000-09-29 20:49:18 +00:00
|
|
|
snd_seq_drop_output_buffer(seq);
|
1999-08-19 16:35:48 +00:00
|
|
|
} else {
|
|
|
|
|
char *ep;
|
2000-05-08 18:53:38 +00:00
|
|
|
size_t len;
|
1999-08-19 16:35:48 +00:00
|
|
|
snd_seq_event_t *ev;
|
|
|
|
|
|
|
|
|
|
ep = seq->obuf;
|
2000-05-08 18:53:38 +00:00
|
|
|
while (ep - seq->obuf < (ssize_t)seq->obufused) {
|
1999-08-19 16:35:48 +00:00
|
|
|
|
|
|
|
|
ev = (snd_seq_event_t *) ep;
|
|
|
|
|
len = snd_seq_event_length(ev);
|
|
|
|
|
|
|
|
|
|
if (remove_match(rmp, ev)) {
|
|
|
|
|
/* Remove event */
|
|
|
|
|
seq->obufused -= len;
|
1999-12-19 09:49:35 +00:00
|
|
|
memmove(ep, ep + len, seq->obufused - (ep - seq->obuf));
|
1999-08-19 16:35:48 +00:00
|
|
|
} else {
|
|
|
|
|
ep += len;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-11-20 20:10:46 +00:00
|
|
|
return seq->ops->remove_events(seq, rmp);
|
1999-08-19 16:35:48 +00:00
|
|
|
}
|
1998-12-27 00:59:08 +00:00
|
|
|
|
2000-03-18 18:03:50 +00:00
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* client memory pool
|
|
|
|
|
*/
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief get size of #snd_seq_client_pool_t
|
|
|
|
|
* \return size in bytes
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
size_t snd_seq_client_pool_sizeof()
|
1999-06-15 22:26:21 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
return sizeof(snd_seq_client_pool_t);
|
1999-06-15 22:26:21 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief allocate an empty #snd_seq_client_pool_t using standard malloc
|
|
|
|
|
* \param ptr returned pointer
|
|
|
|
|
* \return 0 on success otherwise negative error code
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_client_pool_malloc(snd_seq_client_pool_t **ptr)
|
1999-06-15 22:26:21 +00:00
|
|
|
{
|
2001-07-04 13:54:13 +00:00
|
|
|
assert(ptr);
|
|
|
|
|
*ptr = calloc(1, sizeof(snd_seq_client_pool_t));
|
|
|
|
|
if (!*ptr)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
return 0;
|
1999-06-15 22:26:21 +00:00
|
|
|
}
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \brief frees a previously allocated #snd_seq_client_pool_t
|
|
|
|
|
* \param pointer to object to free
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_client_pool_free(snd_seq_client_pool_t *obj)
|
|
|
|
|
{
|
|
|
|
|
free(obj);
|
|
|
|
|
}
|
2000-03-18 18:03:50 +00:00
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
/**
|
|
|
|
|
* \brief copy one #snd_seq_client_pool_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_client_pool_copy(snd_seq_client_pool_t *dst, const snd_seq_client_pool_t *src)
|
|
|
|
|
{
|
|
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the client id of a queue_info container
|
|
|
|
|
* \param info client_pool container
|
|
|
|
|
* \return client id
|
2000-03-18 18:03:50 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_client_pool_get_client(const snd_seq_client_pool_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->client;
|
|
|
|
|
}
|
2000-03-18 18:03:50 +00:00
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief Get the output pool size of a queue_info container
|
|
|
|
|
* \param info client_pool container
|
|
|
|
|
* \return output pool size
|
|
|
|
|
*/
|
|
|
|
|
size_t snd_seq_client_pool_get_output_pool(const snd_seq_client_pool_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->output_pool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the input pool size of a queue_info container
|
|
|
|
|
* \param info client_pool container
|
|
|
|
|
* \return input pool size
|
|
|
|
|
*/
|
|
|
|
|
size_t snd_seq_client_pool_get_input_pool(const snd_seq_client_pool_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->input_pool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the output room size of a queue_info container
|
|
|
|
|
* \param info client_pool container
|
|
|
|
|
* \return output room size
|
|
|
|
|
*/
|
|
|
|
|
size_t snd_seq_client_pool_get_output_room(const snd_seq_client_pool_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->output_room;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the available size on output pool of a queue_info container
|
|
|
|
|
* \param info client_pool container
|
|
|
|
|
* \return available output size
|
|
|
|
|
*/
|
|
|
|
|
size_t snd_seq_client_pool_get_output_free(const snd_seq_client_pool_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->output_free;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the available size on input pool of a queue_info container
|
|
|
|
|
* \param info client_pool container
|
|
|
|
|
* \return available input size
|
|
|
|
|
*/
|
|
|
|
|
size_t snd_seq_client_pool_get_input_free(const snd_seq_client_pool_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->input_free;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the output pool size of a queue_info container
|
|
|
|
|
* \param info client_pool container
|
|
|
|
|
* \param size output pool size
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_client_pool_set_output_pool(snd_seq_client_pool_t *info, size_t size)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->output_pool = size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the input pool size of a queue_info container
|
|
|
|
|
* \param info client_pool container
|
|
|
|
|
* \param size input pool size
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_client_pool_set_input_pool(snd_seq_client_pool_t *info, size_t size)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->input_pool = size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the output room size of a queue_info container
|
|
|
|
|
* \param info client_pool container
|
|
|
|
|
* \param size output room size
|
|
|
|
|
*/
|
|
|
|
|
void snd_seq_client_pool_set_output_room(snd_seq_client_pool_t *info, size_t size)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->output_room = size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief obtain the pool information of the current client
|
2001-06-06 17:50:16 +00:00
|
|
|
* \param seq sequencer handle
|
2001-07-04 13:54:13 +00:00
|
|
|
* \param info information to be stored
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_get_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info)
|
1999-08-26 10:23:28 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq && info);
|
2001-07-04 13:54:13 +00:00
|
|
|
info->client = seq->client;
|
|
|
|
|
return seq->ops->get_client_pool(seq, info);
|
1999-08-26 10:23:28 +00:00
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
2001-07-04 13:54:13 +00:00
|
|
|
* \brief set the pool information
|
2001-06-06 17:50:16 +00:00
|
|
|
* \param seq sequencer handle
|
2001-07-04 13:54:13 +00:00
|
|
|
* \param info information to update
|
|
|
|
|
*
|
|
|
|
|
* Sets the pool information of the current client.
|
|
|
|
|
* The client field in \a info is replaced automatically with the current id.
|
2001-06-06 17:50:16 +00:00
|
|
|
*/
|
2001-07-04 13:54:13 +00:00
|
|
|
int snd_seq_set_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info)
|
1999-08-26 10:23:28 +00:00
|
|
|
{
|
2000-11-20 20:10:46 +00:00
|
|
|
assert(seq && info);
|
2001-07-04 13:54:13 +00:00
|
|
|
info->client = seq->client;
|
|
|
|
|
return seq->ops->set_client_pool(seq, info);
|
1999-08-26 10:23:28 +00:00
|
|
|
}
|
|
|
|
|
|
2000-03-18 18:03:50 +00:00
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* misc.
|
|
|
|
|
*/
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief set a bit flag
|
|
|
|
|
*/
|
1998-12-27 00:59:08 +00:00
|
|
|
void snd_seq_set_bit(int nr, void *array)
|
|
|
|
|
{
|
|
|
|
|
((unsigned int *)array)[nr >> 5] |= 1UL << (nr & 31);
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief change a bit flag
|
|
|
|
|
*/
|
1998-12-27 00:59:08 +00:00
|
|
|
int snd_seq_change_bit(int nr, void *array)
|
|
|
|
|
{
|
|
|
|
|
int result;
|
|
|
|
|
|
|
|
|
|
result = ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0;
|
|
|
|
|
((unsigned int *)array)[nr >> 5] |= 1UL << (nr & 31);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-06 17:50:16 +00:00
|
|
|
/**
|
|
|
|
|
* \brief get a bit flag state
|
|
|
|
|
*/
|
1998-12-27 00:59:08 +00:00
|
|
|
int snd_seq_get_bit(int nr, void *array)
|
|
|
|
|
{
|
|
|
|
|
return ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-04 13:54:13 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* instrument layer
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief get size of #snd_instr_header_t
|
|
|
|
|
* \return size in bytes
|
|
|
|
|
*/
|
|
|
|
|
size_t snd_instr_header_sizeof(void)
|
|
|
|
|
{
|
|
|
|
|
return sizeof(snd_instr_header_t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief allocate an empty #snd_instr_header_t using standard malloc
|
|
|
|
|
* \param ptr returned pointer
|
|
|
|
|
* \param len additional data length
|
|
|
|
|
* \return 0 on success otherwise negative error code
|
|
|
|
|
*/
|
|
|
|
|
int snd_instr_header_malloc(snd_instr_header_t **ptr, size_t len)
|
|
|
|
|
{
|
|
|
|
|
assert(ptr);
|
|
|
|
|
*ptr = calloc(1, sizeof(snd_instr_header_t) + len);
|
|
|
|
|
if (!*ptr)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
(*ptr)->len = len;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief frees a previously allocated #snd_instr_header_t
|
|
|
|
|
* \param pointer to object to free
|
|
|
|
|
*/
|
|
|
|
|
void snd_instr_header_free(snd_instr_header_t *obj)
|
|
|
|
|
{
|
|
|
|
|
free(obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief copy one #snd_instr_header_t to another
|
|
|
|
|
* \param dst pointer to destination
|
|
|
|
|
* \param src pointer to source
|
|
|
|
|
*/
|
|
|
|
|
void snd_instr_header_copy(snd_instr_header_t *dst, const snd_instr_header_t *src)
|
|
|
|
|
{
|
|
|
|
|
assert(dst && src);
|
|
|
|
|
*dst = *src;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the instrument id of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \return instrument id pointer
|
|
|
|
|
*/
|
|
|
|
|
const snd_seq_instr_t *snd_instr_header_get_id(const snd_instr_header_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
return (snd_seq_instr_t *)&info->id.instr;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the cluster id of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \return cluster id
|
|
|
|
|
*/
|
|
|
|
|
snd_seq_instr_cluster_t snd_instr_header_get_cluster(const snd_instr_header_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->id.cluster;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the command of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \return command type
|
|
|
|
|
*/
|
|
|
|
|
unsigned int snd_instr_header_get_cmd(const snd_instr_header_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->cmd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the length of extra data of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \return the length in bytes
|
|
|
|
|
*/
|
|
|
|
|
size_t snd_instr_header_get_len(const snd_instr_header_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the data name of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \return the name string
|
|
|
|
|
*/
|
|
|
|
|
const char *snd_instr_header_get_name(const snd_instr_header_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->data.name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the data type of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \return the data type
|
|
|
|
|
*/
|
|
|
|
|
int snd_instr_header_get_type(const snd_instr_header_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->data.type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the data format of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \return the data format string
|
|
|
|
|
*/
|
|
|
|
|
const char *snd_instr_header_get_format(const snd_instr_header_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return info->data.data.format;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the data alias of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \return the data alias id
|
|
|
|
|
*/
|
|
|
|
|
const snd_seq_instr_t *snd_instr_header_get_alias(const snd_instr_header_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-08-20 13:15:30 +00:00
|
|
|
return (snd_seq_instr_t *)&info->data.data.alias;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the extra data pointer of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \return the extra data pointer
|
|
|
|
|
*/
|
|
|
|
|
void *snd_instr_header_get_data(const snd_instr_header_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return (void*)((char*)info + sizeof(*info));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Get the flag to follow alias of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \return 1 if follow alias
|
|
|
|
|
*/
|
|
|
|
|
int snd_instr_header_get_follow_alias(const snd_instr_header_t *info)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
return (info->flags & SNDRV_SEQ_INSTR_QUERY_FOLLOW_ALIAS) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the instrument id of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \param id instrumen id pointer
|
|
|
|
|
*/
|
|
|
|
|
void snd_instr_header_set_id(snd_instr_header_t *info, const snd_seq_instr_t *id)
|
|
|
|
|
{
|
|
|
|
|
assert(info && id);
|
2001-08-20 13:15:30 +00:00
|
|
|
info->id.instr = *(struct sndrv_seq_instr *)id;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the cluster id of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \param cluster cluster id
|
|
|
|
|
*/
|
|
|
|
|
void snd_instr_header_set_cluster(snd_instr_header_t *info, snd_seq_instr_cluster_t cluster)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->id.cluster = cluster;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the command of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \param cmd command type
|
|
|
|
|
*/
|
|
|
|
|
void snd_instr_header_set_cmd(snd_instr_header_t *info, unsigned int cmd)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->cmd = cmd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the length of extra data of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \param len size of extra data in bytes
|
|
|
|
|
*/
|
|
|
|
|
void snd_instr_header_set_len(snd_instr_header_t *info, size_t len)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->len = len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the data name of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \param name the name string
|
|
|
|
|
*/
|
|
|
|
|
void snd_instr_header_set_name(snd_instr_header_t *info, const char *name)
|
|
|
|
|
{
|
|
|
|
|
assert(info && name);
|
|
|
|
|
strncpy(info->data.name, name, sizeof(info->data.name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the data type of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \param type the data type
|
|
|
|
|
*/
|
|
|
|
|
void snd_instr_header_set_type(snd_instr_header_t *info, int type)
|
|
|
|
|
{
|
|
|
|
|
assert(info);
|
|
|
|
|
info->data.type = type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the data format of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \param format the data format string
|
|
|
|
|
*/
|
|
|
|
|
void snd_instr_header_set_format(snd_instr_header_t *info, const char *format)
|
|
|
|
|
{
|
|
|
|
|
assert(info && format);
|
|
|
|
|
strncpy(info->data.data.format, format, sizeof(info->data.data.format));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the data alias id of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
|
|
|
|
* \param instr alias instrument id
|
|
|
|
|
*/
|
|
|
|
|
void snd_instr_header_set_alias(snd_instr_header_t *info, const snd_seq_instr_t *instr)
|
|
|
|
|
{
|
|
|
|
|
assert(info && instr);
|
2001-08-20 13:15:30 +00:00
|
|
|
info->data.data.alias = *(struct sndrv_seq_instr *)instr;
|
2001-07-04 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Set the flag to follow alias of an instr_header container
|
|
|
|
|
* \param info instr_header container
|
2001-07-04 15:05:05 +00:00
|
|
|
* \param val 1 if follow alias
|
2001-07-04 13:54:13 +00:00
|
|
|
*/
|
2001-07-04 15:05:05 +00:00
|
|
|
void snd_instr_header_set_follow_alias(snd_instr_header_t *info, int val)
|
2001-07-04 13:54:13 +00:00
|
|
|
{
|
|
|
|
|
assert(info);
|
2001-07-04 15:05:05 +00:00
|
|
|
if (val)
|
2001-07-04 13:54:13 +00:00
|
|
|
info->flags |= SNDRV_SEQ_INSTR_QUERY_FOLLOW_ALIAS;
|
|
|
|
|
else
|
|
|
|
|
info->flags &= ~SNDRV_SEQ_INSTR_QUERY_FOLLOW_ALIAS;
|
|
|
|
|
}
|