mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Experimental synchronization support on ALSA sequencer
This commit is contained in:
parent
761d5e6442
commit
d1d906e295
3 changed files with 201 additions and 60 deletions
|
|
@ -49,6 +49,9 @@ int snd_seq_set_queue_client(snd_seq_t *handle, int q, snd_seq_queue_client_t *q
|
||||||
int snd_seq_create_queue(snd_seq_t *seq, snd_seq_queue_info_t *info);
|
int snd_seq_create_queue(snd_seq_t *seq, snd_seq_queue_info_t *info);
|
||||||
int snd_seq_alloc_named_queue(snd_seq_t *seq, char *name);
|
int snd_seq_alloc_named_queue(snd_seq_t *seq, char *name);
|
||||||
int snd_seq_alloc_queue(snd_seq_t *handle);
|
int snd_seq_alloc_queue(snd_seq_t *handle);
|
||||||
|
#ifdef SND_SEQ_SYNC_SUPPORT
|
||||||
|
int snd_seq_alloc_sync_queue(snd_seq_t *seq, char *name);
|
||||||
|
#endif
|
||||||
int snd_seq_free_queue(snd_seq_t *handle, int q);
|
int snd_seq_free_queue(snd_seq_t *handle, int q);
|
||||||
int snd_seq_get_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info);
|
int snd_seq_get_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info);
|
||||||
int snd_seq_set_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info);
|
int snd_seq_set_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info);
|
||||||
|
|
@ -57,6 +60,17 @@ int snd_seq_get_client_pool(snd_seq_t *handle, snd_seq_client_pool_t * info);
|
||||||
int snd_seq_set_client_pool(snd_seq_t *handle, snd_seq_client_pool_t * info);
|
int snd_seq_set_client_pool(snd_seq_t *handle, snd_seq_client_pool_t * info);
|
||||||
int snd_seq_query_next_client(snd_seq_t *handle, snd_seq_client_info_t * info);
|
int snd_seq_query_next_client(snd_seq_t *handle, snd_seq_client_info_t * info);
|
||||||
int snd_seq_query_next_port(snd_seq_t *handle, snd_seq_port_info_t * info);
|
int snd_seq_query_next_port(snd_seq_t *handle, snd_seq_port_info_t * info);
|
||||||
|
#ifdef SND_SEQ_SYNC_SUPPORT
|
||||||
|
int snd_seq_add_sync_master(snd_seq_t *seq, int queue, snd_seq_addr_t *dest, snd_seq_queue_sync_t *info);
|
||||||
|
int snd_seq_remove_sync_master(snd_seq_t *seq, int queue, snd_seq_addr_t *dest);
|
||||||
|
int snd_seq_add_sync_std_master(snd_seq_t *seq, int queue, snd_seq_addr_t *dest, int format, int time_format, unsigned char *opt_info);
|
||||||
|
#define snd_seq_add_sync_master_clock(seq,q,dest) snd_seq_add_sync_std_master(seq, q, dest, SND_SEQ_SYNC_FMT_MIDI_CLOCK, 0, 0)
|
||||||
|
#define snd_seq_add_sync_master_mtc(seq,q,dest,tfmt) snd_seq_add_sync_std_master(seq, q, dest, SND_SEQ_SYNC_FMT_MTC, tfmt, 0)
|
||||||
|
|
||||||
|
int snd_seq_set_sync_slave(snd_seq_t *seq, int queue, snd_seq_addr_t *src, snd_seq_queue_sync_t *info);
|
||||||
|
int snd_seq_reset_sync_slave(snd_seq_t *seq, int queue, snd_seq_addr_t *src);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* event routines */
|
/* event routines */
|
||||||
snd_seq_event_t *snd_seq_create_event(void);
|
snd_seq_event_t *snd_seq_create_event(void);
|
||||||
|
|
|
||||||
112
src/seq/seq.c
112
src/seq/seq.c
|
|
@ -504,6 +504,23 @@ int snd_seq_alloc_queue(snd_seq_t *seq)
|
||||||
return snd_seq_alloc_named_queue(seq, NULL);
|
return snd_seq_alloc_named_queue(seq, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SND_SEQ_SYNC_SUPPORT
|
||||||
|
int snd_seq_alloc_sync_queue(snd_seq_t *seq, char *name)
|
||||||
|
{
|
||||||
|
snd_seq_queue_info_t info;
|
||||||
|
|
||||||
|
if (!seq)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
info.locked = 1;
|
||||||
|
if (name)
|
||||||
|
strncpy(info.name, name, sizeof(info.name) - 1);
|
||||||
|
info.flags = SND_SEQ_QUEUE_FLG_SYNC;
|
||||||
|
return snd_seq_create_queue(seq, &info);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int snd_seq_free_queue(snd_seq_t *seq, int q)
|
int snd_seq_free_queue(snd_seq_t *seq, int q)
|
||||||
{
|
{
|
||||||
snd_seq_queue_info_t info;
|
snd_seq_queue_info_t info;
|
||||||
|
|
@ -553,6 +570,101 @@ int snd_seq_get_named_queue(snd_seq_t *seq, char *name)
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef SND_SEQ_SYNC_SUPPORT
|
||||||
|
/*
|
||||||
|
* sync stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
int snd_seq_add_sync_master(snd_seq_t *seq,
|
||||||
|
int queue,
|
||||||
|
snd_seq_addr_t *dest,
|
||||||
|
snd_seq_queue_sync_t *info)
|
||||||
|
{
|
||||||
|
snd_seq_port_subscribe_t subs;
|
||||||
|
|
||||||
|
memset(&subs, 0, sizeof(subs));
|
||||||
|
subs.convert_time = 1;
|
||||||
|
if (info->format & SND_SEQ_SYNC_TIME)
|
||||||
|
subs.realtime = 1;
|
||||||
|
subs.sync = 1;
|
||||||
|
subs.sender.client = SND_SEQ_CLIENT_SYSTEM;
|
||||||
|
subs.sender.port = snd_seq_queue_sync_port(queue);
|
||||||
|
subs.dest = *dest;
|
||||||
|
subs.queue = queue;
|
||||||
|
subs.opt.sync_info = *info;
|
||||||
|
return snd_seq_subscribe_port(seq, &subs);
|
||||||
|
}
|
||||||
|
|
||||||
|
int snd_seq_add_sync_std_master(snd_seq_t *seq,
|
||||||
|
int queue,
|
||||||
|
snd_seq_addr_t *dest,
|
||||||
|
int format, int time_format,
|
||||||
|
unsigned char *optinfo)
|
||||||
|
{
|
||||||
|
snd_seq_queue_sync_t sync_info;
|
||||||
|
|
||||||
|
memset(&sync_info, 0, sizeof(sync_info));
|
||||||
|
sync_info.format = format;
|
||||||
|
sync_info.time_format = time_format;
|
||||||
|
if (optinfo)
|
||||||
|
memcpy(sync_info.info, optinfo, sizeof(sync_info.info));
|
||||||
|
|
||||||
|
return snd_seq_add_sync_master(seq, queue, dest, &sync_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int snd_seq_remove_sync_master(snd_seq_t *seq, int queue, snd_seq_addr_t *dest)
|
||||||
|
{
|
||||||
|
snd_seq_port_subscribe_t subs;
|
||||||
|
|
||||||
|
memset(&subs, 0, sizeof(subs));
|
||||||
|
subs.sync = 1;
|
||||||
|
subs.sender.client = SND_SEQ_CLIENT_SYSTEM;
|
||||||
|
subs.sender.port = snd_seq_queue_sync_port(queue);
|
||||||
|
subs.dest = *dest;
|
||||||
|
subs.queue = queue;
|
||||||
|
return snd_seq_unsubscribe_port(seq, &subs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int snd_seq_set_sync_slave(snd_seq_t *seq,
|
||||||
|
int queue,
|
||||||
|
snd_seq_addr_t *src,
|
||||||
|
snd_seq_queue_sync_t *info)
|
||||||
|
{
|
||||||
|
snd_seq_port_subscribe_t subs;
|
||||||
|
|
||||||
|
memset(&subs, 0, sizeof(subs));
|
||||||
|
subs.convert_time = 1;
|
||||||
|
if (info->format & SND_SEQ_SYNC_TIME)
|
||||||
|
subs.realtime = 1;
|
||||||
|
subs.sync = 1;
|
||||||
|
subs.sender = *src;
|
||||||
|
subs.dest.client = SND_SEQ_CLIENT_SYSTEM;
|
||||||
|
subs.dest.port = snd_seq_queue_sync_port(queue);
|
||||||
|
subs.queue = queue;
|
||||||
|
subs.opt.sync_info = *info;
|
||||||
|
return snd_seq_subscribe_port(seq, &subs);
|
||||||
|
}
|
||||||
|
|
||||||
|
int snd_seq_reset_sync_slave(snd_seq_t *seq, int queue, snd_seq_addr_t *src)
|
||||||
|
{
|
||||||
|
snd_seq_port_subscribe_t subs;
|
||||||
|
|
||||||
|
memset(&subs, 0, sizeof(subs));
|
||||||
|
subs.sync = 1;
|
||||||
|
subs.sender = *src;
|
||||||
|
subs.dest.client = SND_SEQ_CLIENT_SYSTEM;
|
||||||
|
subs.dest.port = snd_seq_queue_sync_port(queue);
|
||||||
|
subs.queue = queue;
|
||||||
|
return snd_seq_unsubscribe_port(seq, &subs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* create an event cell
|
* create an event cell
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
135
test/playmidi1.c
135
test/playmidi1.c
|
|
@ -48,11 +48,11 @@
|
||||||
|
|
||||||
#include "../include/asoundlib.h"
|
#include "../include/asoundlib.h"
|
||||||
|
|
||||||
/* define this if you want to send real-time time stamps instead of midi ticks to the ALSA sequencer */
|
/* send real-time time stamps instead of midi ticks to the ALSA sequencer */
|
||||||
/* #define USE_REALTIME */
|
static int use_realtime = 0;
|
||||||
|
|
||||||
/* define this if you want to control event buffering by blocking mode */
|
/* control event buffering by blocking mode */
|
||||||
#define USE_BLOCKING_MODE
|
static int use_blocking_mode = 1;
|
||||||
|
|
||||||
/* default destination queue, client and port numbers */
|
/* default destination queue, client and port numbers */
|
||||||
#define DEST_CLIENT_NUMBER 65
|
#define DEST_CLIENT_NUMBER 65
|
||||||
|
|
@ -66,12 +66,13 @@
|
||||||
static FILE *F;
|
static FILE *F;
|
||||||
static snd_seq_t *seq_handle = NULL;
|
static snd_seq_t *seq_handle = NULL;
|
||||||
static int ppq = 96;
|
static int ppq = 96;
|
||||||
|
static int slave_ppq = 96;
|
||||||
|
|
||||||
static double local_secs = 0;
|
static double local_secs = 0;
|
||||||
static int local_ticks = 0;
|
static int local_ticks = 0;
|
||||||
static int local_tempo = 500000;
|
static int local_tempo = 500000;
|
||||||
|
|
||||||
static int dest_queue = 0;
|
static int dest_queue = -1;
|
||||||
static int dest_client = DEST_CLIENT_NUMBER;
|
static int dest_client = DEST_CLIENT_NUMBER;
|
||||||
static int dest_port = DEST_PORT_NUMBER;
|
static int dest_port = DEST_PORT_NUMBER;
|
||||||
static int my_port = 0;
|
static int my_port = 0;
|
||||||
|
|
@ -93,33 +94,25 @@ static inline double tick2time_dbl(int tick)
|
||||||
return local_secs + ((double) (tick - local_ticks) * (double) local_tempo * 1.0E-6 / (double) ppq);
|
return local_secs + ((double) (tick - local_ticks) * (double) local_tempo * 1.0E-6 / (double) ppq);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_REALTIME
|
|
||||||
static void tick2time(snd_seq_real_time_t * tm, int tick)
|
static void tick2time(snd_seq_real_time_t * tm, int tick)
|
||||||
{
|
{
|
||||||
double secs = tick2time_dbl(tick);
|
double secs = tick2time_dbl(tick);
|
||||||
tm->tv_sec = secs;
|
tm->tv_sec = secs;
|
||||||
tm->tv_nsec = (secs - tm->tv_sec) * 1.0E9;
|
tm->tv_nsec = (secs - tm->tv_sec) * 1.0E9;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_BLOCKING_MODE
|
|
||||||
/* write event - using blocking mode */
|
|
||||||
static void write_ev(snd_seq_event_t *ev)
|
|
||||||
{
|
|
||||||
int written;
|
|
||||||
|
|
||||||
written = snd_seq_event_output(seq_handle, ev);
|
|
||||||
if (written < 0) {
|
|
||||||
printf("written = %i (%s)\n", written, snd_strerror(written));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* write event - using select syscall */
|
|
||||||
static void write_ev(snd_seq_event_t *ev)
|
static void write_ev(snd_seq_event_t *ev)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (use_blocking_mode) {
|
||||||
|
rc = snd_seq_event_output(seq_handle, ev);
|
||||||
|
if (rc < 0) {
|
||||||
|
printf("written = %i (%s)\n", rc, snd_strerror(rc));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
while ((rc = snd_seq_event_output(seq_handle, ev)) < 0) {
|
while ((rc = snd_seq_event_output(seq_handle, ev)) < 0) {
|
||||||
int seqfd;
|
int seqfd;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
|
|
@ -132,7 +125,6 @@ static void write_ev(snd_seq_event_t *ev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* read byte */
|
/* read byte */
|
||||||
static int mygetc(void)
|
static int mygetc(void)
|
||||||
|
|
@ -173,12 +165,16 @@ static void do_header(int format, int ntracks, int division)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (tempo.ppq != ppq) {
|
if (tempo.ppq != ppq) {
|
||||||
|
slave_ppq = tempo.ppq;
|
||||||
tempo.ppq = ppq;
|
tempo.ppq = ppq;
|
||||||
if (snd_seq_set_queue_tempo(seq_handle, dest_queue, &tempo) < 0) {
|
if (snd_seq_set_queue_tempo(seq_handle, dest_queue, &tempo) < 0) {
|
||||||
perror("set_queue_tempo");
|
perror("set_queue_tempo");
|
||||||
if (!slave)
|
if (!slave)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
else
|
||||||
|
printf("different PPQ %d in SMF from queue PPQ %d\n", ppq, slave_ppq);
|
||||||
|
} else
|
||||||
|
slave_ppq = ppq;
|
||||||
if (verbose >= VERB_INFO)
|
if (verbose >= VERB_INFO)
|
||||||
printf("ALSA Timer updated, PPQ = %d\n", tempo.ppq);
|
printf("ALSA Timer updated, PPQ = %d\n", tempo.ppq);
|
||||||
}
|
}
|
||||||
|
|
@ -197,13 +193,17 @@ static void do_header(int format, int ntracks, int division)
|
||||||
/* fill time */
|
/* fill time */
|
||||||
static void set_event_time(snd_seq_event_t *ev, unsigned int currtime)
|
static void set_event_time(snd_seq_event_t *ev, unsigned int currtime)
|
||||||
{
|
{
|
||||||
#ifdef USE_REALTIME
|
if (use_realtime) {
|
||||||
snd_seq_real_time_t rtime;
|
snd_seq_real_time_t rtime;
|
||||||
tick2time(&rtime, currtime);
|
if (ppq != slave_ppq)
|
||||||
snd_seq_ev_schedule_real(ev, dest_queue, 0, &rtime);
|
currtime = (currtime * slave_ppq) / ppq;
|
||||||
#else
|
tick2time(&rtime, currtime);
|
||||||
snd_seq_ev_schedule_tick(ev, dest_queue, 0, currtime);
|
snd_seq_ev_schedule_real(ev, dest_queue, 0, &rtime);
|
||||||
#endif
|
} else {
|
||||||
|
if (ppq != slave_ppq)
|
||||||
|
currtime = (currtime * slave_ppq) / ppq;
|
||||||
|
snd_seq_ev_schedule_tick(ev, dest_queue, 0, currtime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill normal event header */
|
/* fill normal event header */
|
||||||
|
|
@ -357,24 +357,25 @@ static snd_seq_event_t *wait_for_event(void)
|
||||||
int left;
|
int left;
|
||||||
snd_seq_event_t *input_event;
|
snd_seq_event_t *input_event;
|
||||||
|
|
||||||
#ifdef USE_BLOCKING_MODE
|
if (use_blocking_mode) {
|
||||||
/* read event - blocked until any event is read */
|
/* read event - blocked until any event is read */
|
||||||
left = snd_seq_event_input(seq_handle, &input_event);
|
left = snd_seq_event_input(seq_handle, &input_event);
|
||||||
#else
|
} else {
|
||||||
/* read event - using select syscall */
|
/* read event - using select syscall */
|
||||||
while ((left = snd_seq_event_input(seq_handle, &input_event)) >= 0 &&
|
while ((left = snd_seq_event_input(seq_handle, &input_event)) >= 0 &&
|
||||||
input_event == NULL) {
|
input_event == NULL) {
|
||||||
int seqfd;
|
int seqfd;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
seqfd = snd_seq_file_descriptor(seq_handle);
|
seqfd = snd_seq_file_descriptor(seq_handle);
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(seqfd, &fds);
|
FD_SET(seqfd, &fds);
|
||||||
if ((left = select(seqfd + 1, &fds, NULL, NULL, NULL)) < 0) {
|
if ((left = select(seqfd + 1, &fds, NULL, NULL, NULL)) < 0) {
|
||||||
printf("select error = %i (%s)\n", left, snd_strerror(left));
|
printf("select error = %i (%s)\n", left, snd_strerror(left));
|
||||||
exit(1);
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (left < 0) {
|
if (left < 0) {
|
||||||
printf("alsa_sync error!:%s\n", snd_strerror(left));
|
printf("alsa_sync error!:%s\n", snd_strerror(left));
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -458,7 +459,10 @@ static void usage(void)
|
||||||
fprintf(stderr, " -v: verbose mode\n");
|
fprintf(stderr, " -v: verbose mode\n");
|
||||||
fprintf(stderr, " -a client:port : set destination address (default=%d:%d)\n",
|
fprintf(stderr, " -a client:port : set destination address (default=%d:%d)\n",
|
||||||
DEST_CLIENT_NUMBER, DEST_PORT_NUMBER);
|
DEST_CLIENT_NUMBER, DEST_PORT_NUMBER);
|
||||||
|
fprintf(stderr, " -q queue: use the specified queue\n");
|
||||||
fprintf(stderr, " -s queue: slave mode (allow external clock synchronisation)\n");
|
fprintf(stderr, " -s queue: slave mode (allow external clock synchronisation)\n");
|
||||||
|
fprintf(stderr, " -r : play on real-time mode\n");
|
||||||
|
fprintf(stderr, " -b : play on non-blocking mode\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse destination address (-a option) */
|
/* parse destination address (-a option) */
|
||||||
|
|
@ -476,7 +480,7 @@ int main(int argc, char *argv[])
|
||||||
int tmp;
|
int tmp;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "s:a:v")) != -1) {
|
while ((c = getopt(argc, argv, "s:a:q:vrb")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose++;
|
verbose++;
|
||||||
|
|
@ -484,6 +488,13 @@ int main(int argc, char *argv[])
|
||||||
case 'a':
|
case 'a':
|
||||||
parse_address(optarg, &dest_client, &dest_port);
|
parse_address(optarg, &dest_client, &dest_port);
|
||||||
break;
|
break;
|
||||||
|
case 'q':
|
||||||
|
dest_queue = atoi(optarg);
|
||||||
|
if (dest_queue < 0) {
|
||||||
|
fprintf(stderr, "invalid queue number %d\n", dest_queue);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
slave = 1;
|
slave = 1;
|
||||||
dest_queue = atoi(optarg);
|
dest_queue = atoi(optarg);
|
||||||
|
|
@ -492,6 +503,12 @@ int main(int argc, char *argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
use_realtime = 1;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
use_blocking_mode = 0;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -499,11 +516,10 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose >= VERB_INFO) {
|
if (verbose >= VERB_INFO) {
|
||||||
#ifdef USE_REALTIME
|
if (use_realtime)
|
||||||
printf("ALSA MIDI Player, feeding events to real-time queue\n");
|
printf("ALSA MIDI Player, feeding events to real-time queue\n");
|
||||||
#else
|
else
|
||||||
printf("ALSA MIDI Player, feeding events to song queue\n");
|
printf("ALSA MIDI Player, feeding events to song queue\n");
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open sequencer device */
|
/* open sequencer device */
|
||||||
|
|
@ -515,11 +531,7 @@ int main(int argc, char *argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_BLOCKING_MODE
|
tmp = snd_seq_block_mode(seq_handle, use_blocking_mode);
|
||||||
tmp = snd_seq_block_mode(seq_handle, 1);
|
|
||||||
#else
|
|
||||||
tmp = snd_seq_block_mode(seq_handle, 0);
|
|
||||||
#endif
|
|
||||||
if (tmp < 0) {
|
if (tmp < 0) {
|
||||||
perror("block_mode");
|
perror("block_mode");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -544,8 +556,11 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setup queue */
|
/* setup queue */
|
||||||
if (slave) {
|
if (dest_queue >= 0) {
|
||||||
snd_seq_use_queue(seq_handle, dest_queue, 1);
|
if (snd_seq_use_queue(seq_handle, dest_queue, 1) < 0) {
|
||||||
|
perror("use queue");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dest_queue = snd_seq_alloc_queue(seq_handle);
|
dest_queue = snd_seq_alloc_queue(seq_handle);
|
||||||
if (dest_queue < 0) {
|
if (dest_queue < 0) {
|
||||||
|
|
@ -565,7 +580,7 @@ int main(int argc, char *argv[])
|
||||||
if (slave) {
|
if (slave) {
|
||||||
tmp = snd_seq_connect_from(seq_handle, my_port,
|
tmp = snd_seq_connect_from(seq_handle, my_port,
|
||||||
SND_SEQ_CLIENT_SYSTEM,
|
SND_SEQ_CLIENT_SYSTEM,
|
||||||
SND_SEQ_PORT_SYSTEM_TIMER);
|
snd_seq_queue_sync_port(dest_queue));
|
||||||
if (tmp < 0) {
|
if (tmp < 0) {
|
||||||
perror("subscribe");
|
perror("subscribe");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue