1999-09-17 16:17:21 +00:00
|
|
|
/*
|
|
|
|
|
* Sequencer Interface - middle-level routines
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 1999 by Takashi Iwai <iwai@ww.uni-erlangen.de>
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU Library General Public License as
|
|
|
|
|
* published by the Free Software Foundation; either version 2 of
|
|
|
|
|
* the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU Library General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <sys/ioctl.h>
|
2000-11-20 20:10:46 +00:00
|
|
|
#include "seq_local.h"
|
1999-09-17 16:17:21 +00:00
|
|
|
|
|
|
|
|
/* direct passing (without queued) */
|
|
|
|
|
void snd_seq_ev_set_direct(snd_seq_event_t *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
|
|
|
ev->queue = SND_SEQ_QUEUE_DIRECT;
|
1999-09-17 16:17:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* queued on tick */
|
|
|
|
|
void snd_seq_ev_schedule_tick(snd_seq_event_t *ev, int q, int relative,
|
1999-12-15 18:34:12 +00:00
|
|
|
snd_seq_tick_time_t tick)
|
1999-09-17 16:17:21 +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
|
|
|
ev->flags &= ~(SND_SEQ_TIME_STAMP_MASK | SND_SEQ_TIME_MODE_MASK);
|
1999-09-17 16:17:21 +00:00
|
|
|
ev->flags |= SND_SEQ_TIME_STAMP_TICK;
|
|
|
|
|
ev->flags |= relative ? SND_SEQ_TIME_MODE_REL : SND_SEQ_TIME_MODE_ABS;
|
|
|
|
|
ev->time.tick = tick;
|
1999-12-15 23:37:12 +00:00
|
|
|
ev->queue = q;
|
1999-09-17 16:17:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* queued on real-time */
|
|
|
|
|
void snd_seq_ev_schedule_real(snd_seq_event_t *ev, int q, int relative,
|
2001-03-29 17:50:28 +00:00
|
|
|
snd_seq_real_time_t *_time)
|
1999-09-17 16:17:21 +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
|
|
|
ev->flags &= ~( SND_SEQ_TIME_STAMP_MASK | SND_SEQ_TIME_MODE_MASK);
|
1999-09-17 16:17:21 +00:00
|
|
|
ev->flags |= SND_SEQ_TIME_STAMP_REAL;
|
|
|
|
|
ev->flags |= relative ? SND_SEQ_TIME_MODE_REL : SND_SEQ_TIME_MODE_ABS;
|
2001-03-29 17:50:28 +00:00
|
|
|
ev->time.time = *_time;
|
1999-12-15 23:37:12 +00:00
|
|
|
ev->queue = q;
|
1999-09-17 16:17:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set event priority */
|
|
|
|
|
void snd_seq_ev_set_priority(snd_seq_event_t *ev, int high_prior)
|
|
|
|
|
{
|
|
|
|
|
ev->flags &= ~SND_SEQ_PRIORITY_MASK;
|
|
|
|
|
ev->flags |= high_prior ? SND_SEQ_PRIORITY_HIGH : SND_SEQ_PRIORITY_NORMAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set fixed data */
|
|
|
|
|
void snd_seq_ev_set_fixed(snd_seq_event_t *ev)
|
|
|
|
|
{
|
|
|
|
|
ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
|
|
|
|
|
ev->flags |= SND_SEQ_EVENT_LENGTH_FIXED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set variable data */
|
|
|
|
|
void snd_seq_ev_set_variable(snd_seq_event_t *ev, int len, void *ptr)
|
|
|
|
|
{
|
|
|
|
|
ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
|
|
|
|
|
ev->flags |= SND_SEQ_EVENT_LENGTH_VARIABLE;
|
|
|
|
|
ev->data.ext.len = len;
|
2000-06-08 10:55:34 +00:00
|
|
|
ev->data.ext.ptr = ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set varusr data */
|
|
|
|
|
void snd_seq_ev_set_varusr(snd_seq_event_t *ev, int len, void *ptr)
|
|
|
|
|
{
|
|
|
|
|
ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
|
|
|
|
|
ev->flags |= SND_SEQ_EVENT_LENGTH_VARUSR;
|
|
|
|
|
ev->data.ext.len = len;
|
1999-09-17 16:17:21 +00:00
|
|
|
ev->data.ext.ptr = ptr;
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-15 18:34:12 +00:00
|
|
|
|
|
|
|
|
/* use or unuse a queue */
|
|
|
|
|
int snd_seq_use_queue(snd_seq_t *seq, int q, int use)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_queue_client_t info;
|
|
|
|
|
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
|
info.used = use;
|
|
|
|
|
return snd_seq_set_queue_client(seq, q, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1999-09-17 16:17:21 +00:00
|
|
|
/* queue controls - start/stop/continue */
|
|
|
|
|
/* if ev is NULL, send events immediately.
|
1999-12-15 18:34:12 +00:00
|
|
|
otherwise, duplicate the given event data. */
|
1999-09-17 16:17:21 +00:00
|
|
|
int snd_seq_control_queue(snd_seq_t *seq, int q, int type, int value, snd_seq_event_t *ev)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_event_t tmpev;
|
|
|
|
|
if (ev == NULL) {
|
|
|
|
|
snd_seq_ev_clear(&tmpev);
|
|
|
|
|
ev = &tmpev;
|
|
|
|
|
snd_seq_ev_set_direct(ev);
|
|
|
|
|
}
|
1999-12-15 18:34:12 +00:00
|
|
|
snd_seq_ev_set_queue_control(ev, type, q, value);
|
1999-09-17 16:17:21 +00:00
|
|
|
return snd_seq_event_output(seq, ev);
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-15 18:34:12 +00:00
|
|
|
/* reset queue position:
|
|
|
|
|
* new values of both real-time and tick values must be given.
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_setpos_queue(snd_seq_t *seq, int q, snd_seq_timestamp_t *rtime, snd_seq_event_t *ev)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_event_t tmpev;
|
|
|
|
|
int result;
|
|
|
|
|
|
|
|
|
|
if (ev == NULL) {
|
|
|
|
|
snd_seq_ev_clear(&tmpev);
|
|
|
|
|
ev = &tmpev;
|
|
|
|
|
snd_seq_ev_set_direct(ev);
|
|
|
|
|
}
|
|
|
|
|
/* stop the timer */
|
|
|
|
|
result = snd_seq_stop_queue(seq, q, ev);
|
|
|
|
|
/* reset queue position */
|
2000-01-20 12:14:50 +00:00
|
|
|
snd_seq_ev_set_queue_pos_real(ev, q, &rtime->time);
|
1999-12-15 18:34:12 +00:00
|
|
|
result = snd_seq_event_output(seq, ev);
|
|
|
|
|
snd_seq_ev_set_queue_pos_tick(ev, q, rtime->tick);
|
|
|
|
|
result = snd_seq_event_output(seq, ev);
|
|
|
|
|
/* continue the timer */
|
|
|
|
|
result = snd_seq_continue_queue(seq, q, ev);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
1999-09-17 16:17:21 +00:00
|
|
|
|
|
|
|
|
/* create a port - simple version
|
|
|
|
|
* return the port number
|
|
|
|
|
*/
|
2001-02-11 15:45:35 +00:00
|
|
|
int snd_seq_create_simple_port(snd_seq_t *seq, const char *name,
|
1999-09-17 16:17:21 +00:00
|
|
|
unsigned int caps, unsigned int type)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_port_info_t pinfo;
|
|
|
|
|
int result;
|
|
|
|
|
|
|
|
|
|
memset(&pinfo, 0, sizeof(pinfo));
|
|
|
|
|
if (name)
|
|
|
|
|
strncpy(pinfo.name, name, sizeof(pinfo.name) - 1);
|
|
|
|
|
pinfo.capability = caps;
|
|
|
|
|
pinfo.cap_group = caps;
|
|
|
|
|
pinfo.type = type;
|
|
|
|
|
pinfo.midi_channels = 16;
|
|
|
|
|
pinfo.midi_voices = 64; /* XXX */
|
|
|
|
|
pinfo.synth_voices = 0; /* XXX */
|
|
|
|
|
pinfo.kernel = NULL;
|
|
|
|
|
|
|
|
|
|
result = snd_seq_create_port(seq, &pinfo);
|
|
|
|
|
if (result < 0)
|
|
|
|
|
return result;
|
|
|
|
|
else
|
|
|
|
|
return pinfo.port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* delete the port */
|
|
|
|
|
int snd_seq_delete_simple_port(snd_seq_t *seq, int port)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_port_info_t pinfo;
|
|
|
|
|
|
|
|
|
|
memset(&pinfo, 0, sizeof(pinfo));
|
|
|
|
|
pinfo.port = port;
|
|
|
|
|
|
|
|
|
|
return snd_seq_delete_port(seq, &pinfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* sipmle subscription (w/o exclusive & time conversion)
|
|
|
|
|
*/
|
|
|
|
|
int snd_seq_connect_from(snd_seq_t *seq, int myport, int src_client, int src_port)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_port_subscribe_t subs;
|
|
|
|
|
|
|
|
|
|
memset(&subs, 0, sizeof(subs));
|
|
|
|
|
subs.sender.client = src_client;
|
|
|
|
|
subs.sender.port = src_port;
|
|
|
|
|
/*subs.dest.client = seq->client;*/
|
|
|
|
|
subs.dest.client = snd_seq_client_id(seq);
|
|
|
|
|
subs.dest.port = myport;
|
|
|
|
|
|
|
|
|
|
return snd_seq_subscribe_port(seq, &subs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int snd_seq_connect_to(snd_seq_t *seq, int myport, int dest_client, int dest_port)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_port_subscribe_t subs;
|
|
|
|
|
|
|
|
|
|
memset(&subs, 0, sizeof(subs));
|
|
|
|
|
/*subs.sender.client = seq->client;*/
|
|
|
|
|
subs.sender.client = snd_seq_client_id(seq);
|
|
|
|
|
subs.sender.port = myport;
|
|
|
|
|
subs.dest.client = dest_client;
|
|
|
|
|
subs.dest.port = dest_port;
|
|
|
|
|
|
|
|
|
|
return snd_seq_subscribe_port(seq, &subs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int snd_seq_disconnect_from(snd_seq_t *seq, int myport, int src_client, int src_port)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_port_subscribe_t subs;
|
|
|
|
|
|
|
|
|
|
memset(&subs, 0, sizeof(subs));
|
|
|
|
|
subs.sender.client = src_client;
|
|
|
|
|
subs.sender.port = src_port;
|
|
|
|
|
/*subs.dest.client = seq->client;*/
|
|
|
|
|
subs.dest.client = snd_seq_client_id(seq);
|
|
|
|
|
subs.dest.port = myport;
|
|
|
|
|
|
|
|
|
|
return snd_seq_unsubscribe_port(seq, &subs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int snd_seq_disconnect_to(snd_seq_t *seq, int myport, int dest_client, int dest_port)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_port_subscribe_t subs;
|
|
|
|
|
|
|
|
|
|
memset(&subs, 0, sizeof(subs));
|
|
|
|
|
/*subs.sender.client = seq->client;*/
|
|
|
|
|
subs.sender.client = snd_seq_client_id(seq);
|
|
|
|
|
subs.sender.port = myport;
|
|
|
|
|
subs.dest.client = dest_client;
|
|
|
|
|
subs.dest.port = dest_port;
|
|
|
|
|
|
|
|
|
|
return snd_seq_unsubscribe_port(seq, &subs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* set client information
|
|
|
|
|
*/
|
2001-02-11 15:45:35 +00:00
|
|
|
int snd_seq_set_client_name(snd_seq_t *seq, const char *name)
|
1999-09-17 16:17:21 +00:00
|
|
|
{
|
|
|
|
|
snd_seq_client_info_t info;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if ((err = snd_seq_get_client_info(seq, &info)) < 0)
|
|
|
|
|
return err;
|
|
|
|
|
strncpy(info.name, name, sizeof(info.name) - 1);
|
|
|
|
|
return snd_seq_set_client_info(seq, &info);
|
|
|
|
|
}
|
|
|
|
|
|
2001-02-11 15:45:35 +00:00
|
|
|
int snd_seq_set_client_group(snd_seq_t *seq, const char *name)
|
1999-09-17 16:17:21 +00:00
|
|
|
{
|
|
|
|
|
snd_seq_client_info_t info;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if ((err = snd_seq_get_client_info(seq, &info)) < 0)
|
|
|
|
|
return err;
|
|
|
|
|
strncpy(info.group, name, sizeof(info.group) - 1);
|
|
|
|
|
return snd_seq_set_client_info(seq, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int snd_seq_set_client_filter(snd_seq_t *seq, unsigned int filter)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_client_info_t info;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if ((err = snd_seq_get_client_info(seq, &info)) < 0)
|
|
|
|
|
return err;
|
|
|
|
|
info.filter = filter;
|
|
|
|
|
return snd_seq_set_client_info(seq, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int snd_seq_set_client_event_filter(snd_seq_t *seq, int event_type)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_client_info_t info;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if ((err = snd_seq_get_client_info(seq, &info)) < 0)
|
|
|
|
|
return err;
|
|
|
|
|
info.filter |= SND_SEQ_FILTER_USE_EVENT;
|
|
|
|
|
snd_seq_set_bit(event_type, info.event_filter);
|
|
|
|
|
return snd_seq_set_client_info(seq, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int snd_seq_set_client_pool_output(snd_seq_t *seq, int size)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_client_pool_t info;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if ((err = snd_seq_get_client_pool(seq, &info)) < 0)
|
|
|
|
|
return err;
|
|
|
|
|
info.output_pool = size;
|
|
|
|
|
return snd_seq_set_client_pool(seq, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int snd_seq_set_client_pool_output_room(snd_seq_t *seq, int size)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_client_pool_t info;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if ((err = snd_seq_get_client_pool(seq, &info)) < 0)
|
|
|
|
|
return err;
|
|
|
|
|
info.output_room = size;
|
|
|
|
|
return snd_seq_set_client_pool(seq, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int snd_seq_set_client_pool_input(snd_seq_t *seq, int size)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_client_pool_t info;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if ((err = snd_seq_get_client_pool(seq, &info)) < 0)
|
|
|
|
|
return err;
|
|
|
|
|
info.input_pool = size;
|
|
|
|
|
return snd_seq_set_client_pool(seq, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* reset client input/output pool
|
1999-12-15 18:34:12 +00:00
|
|
|
* use REMOVE_EVENTS ioctl
|
1999-09-17 16:17:21 +00:00
|
|
|
*/
|
|
|
|
|
int snd_seq_reset_pool_output(snd_seq_t *seq)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_remove_events_t rmp;
|
|
|
|
|
|
|
|
|
|
memset(&rmp, 0, sizeof(rmp));
|
|
|
|
|
rmp.output = 1;
|
|
|
|
|
rmp.remove_mode = 0; /* remove all */
|
|
|
|
|
return snd_seq_remove_events(seq, &rmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int snd_seq_reset_pool_input(snd_seq_t *seq)
|
|
|
|
|
{
|
|
|
|
|
snd_seq_remove_events_t rmp;
|
|
|
|
|
|
|
|
|
|
memset(&rmp, 0, sizeof(rmp));
|
|
|
|
|
rmp.input = 1;
|
|
|
|
|
rmp.remove_mode = 0; /* remove all */
|
|
|
|
|
return snd_seq_remove_events(seq, &rmp);
|
|
|
|
|
}
|
|
|
|
|
|