alsa-lib/src/seq/seqmid.c

345 lines
8.6 KiB
C
Raw Normal View History

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