mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Takashi Iwai <iwai@ww.uni-erlangen.de>
Frank van de Pol <frank@vande-pol.demon.nl> Major sequencer changes and cleanups for 1.0.0.
This commit is contained in:
parent
7b0898c17d
commit
a3aaf0582a
8 changed files with 176 additions and 121 deletions
|
|
@ -78,10 +78,16 @@ static void list_each_subs(snd_seq_t *seq, snd_seq_query_subs_t *subs, int type,
|
|||
subs->index = 0;
|
||||
while (snd_seq_query_port_subscribers(seq, subs) >= 0) {
|
||||
if (subs->index == 0)
|
||||
printf("\t%s: %d:%d:%d", msg,
|
||||
subs->addr.queue, subs->addr.client, subs->addr.port);
|
||||
printf("\t%s: ", msg);
|
||||
else
|
||||
printf(", %d:%d:%d", subs->addr.queue, subs->addr.client, subs->addr.port);
|
||||
printf(", ");
|
||||
printf("%d:%d", subs->addr.client, subs->addr.port);
|
||||
if (subs->exclusive)
|
||||
printf("[ex]");
|
||||
if (subs->convert_time)
|
||||
printf("[%s:%d]",
|
||||
(subs->realtime ? "real" : "tick"),
|
||||
subs->queue);
|
||||
subs->index++;
|
||||
}
|
||||
if (subs->index)
|
||||
|
|
@ -228,7 +234,7 @@ int main(int argc, char **argv)
|
|||
memset(&subs, 0, sizeof(subs));
|
||||
parse_address(&subs.sender, argv[optind]);
|
||||
parse_address(&subs.dest, argv[optind + 1]);
|
||||
subs.sender.queue = subs.dest.queue = queue;
|
||||
subs.queue = queue;
|
||||
subs.exclusive = 0;
|
||||
subs.convert_time = 0;
|
||||
subs.realtime = 0;
|
||||
|
|
|
|||
|
|
@ -438,7 +438,7 @@ static void wait_start(void)
|
|||
printf("wait_start got event. type=%d, flags=%d\n",
|
||||
input_event->type, input_event->flags);
|
||||
if (input_event->type == SND_SEQ_EVENT_START &&
|
||||
input_event->data.addr.queue == dest_queue) {
|
||||
input_event->data.queue.queue == dest_queue) {
|
||||
snd_seq_free_event(input_event);
|
||||
break;
|
||||
}
|
||||
|
|
@ -458,7 +458,7 @@ static void usage(void)
|
|||
fprintf(stderr, " -v: verbose mode\n");
|
||||
fprintf(stderr, " -a client:port : set destination address (default=%d:%d)\n",
|
||||
DEST_CLIENT_NUMBER, DEST_PORT_NUMBER);
|
||||
fprintf(stderr, " -s: slave mode (allow external clock synchronisation)\n");
|
||||
fprintf(stderr, " -s queue: slave mode (allow external clock synchronisation)\n");
|
||||
}
|
||||
|
||||
/* parse destination address (-a option) */
|
||||
|
|
@ -476,7 +476,7 @@ int main(int argc, char *argv[])
|
|||
int tmp;
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "sa:v")) != -1) {
|
||||
while ((c = getopt(argc, argv, "s:a:v")) != -1) {
|
||||
switch (c) {
|
||||
case 'v':
|
||||
verbose++;
|
||||
|
|
@ -486,6 +486,11 @@ int main(int argc, char *argv[])
|
|||
break;
|
||||
case 's':
|
||||
slave = 1;
|
||||
dest_queue = atoi(optarg);
|
||||
if (dest_queue < 0) {
|
||||
fprintf(stderr, "invalid queue number %d\n", dest_queue);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
|
|
@ -525,7 +530,7 @@ int main(int argc, char *argv[])
|
|||
/* if running in slave mode also listen for START event */
|
||||
snd_seq_set_client_event_filter(seq_handle, SND_SEQ_EVENT_ECHO);
|
||||
if (slave)
|
||||
snd_seq_set_client_event_filter(seq_handle, SND_SEQ_EVENT_ECHO);
|
||||
snd_seq_set_client_event_filter(seq_handle, SND_SEQ_EVENT_START);
|
||||
snd_seq_set_client_name(seq_handle, "MIDI file player");
|
||||
|
||||
/* create port */
|
||||
|
|
@ -539,10 +544,14 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
/* setup queue */
|
||||
dest_queue = snd_seq_alloc_queue(seq_handle);
|
||||
if (dest_queue < 0) {
|
||||
perror("alloc queue");
|
||||
exit(1);
|
||||
if (slave) {
|
||||
snd_seq_use_queue(seq_handle, dest_queue, 1);
|
||||
} else {
|
||||
dest_queue = snd_seq_alloc_queue(seq_handle);
|
||||
if (dest_queue < 0) {
|
||||
perror("alloc queue");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* setup subscriber */
|
||||
|
|
|
|||
|
|
@ -287,22 +287,20 @@ int decode_event(snd_seq_event_t * ev)
|
|||
(int)ev->time.real.tv_nsec);
|
||||
break;
|
||||
}
|
||||
printf("\n%sSource = %d.%d.%d.%d, dest = %d.%d.%d.%d\n",
|
||||
printf("\n%sSource = %d.%d, dest = %d.%d, queue = %d\n",
|
||||
space,
|
||||
ev->source.queue,
|
||||
ev->source.client,
|
||||
ev->source.port,
|
||||
ev->source.channel,
|
||||
ev->dest.queue,
|
||||
ev->dest.client,
|
||||
ev->dest.port,
|
||||
ev->dest.channel);
|
||||
ev->queue);
|
||||
|
||||
printf("%sEvent = %s", space, event_names[ev->type]);
|
||||
/* decode actual event data... */
|
||||
switch (ev->type) {
|
||||
case SND_SEQ_EVENT_NOTE:
|
||||
printf("; note=%d, velocity=%d, duration=%d\n",
|
||||
printf("; ch=%d, note=%d, velocity=%d, duration=%d\n",
|
||||
ev->data.note.channel,
|
||||
ev->data.note.note,
|
||||
ev->data.note.velocity,
|
||||
ev->data.note.duration);
|
||||
|
|
@ -310,25 +308,31 @@ int decode_event(snd_seq_event_t * ev)
|
|||
|
||||
case SND_SEQ_EVENT_NOTEON:
|
||||
case SND_SEQ_EVENT_NOTEOFF:
|
||||
printf("; note=%d, velocity=%d\n",
|
||||
case SND_SEQ_EVENT_KEYPRESS:
|
||||
printf("; ch=%d, note=%d, velocity=%d\n",
|
||||
ev->data.note.channel,
|
||||
ev->data.note.note,
|
||||
ev->data.note.velocity);
|
||||
break;
|
||||
|
||||
case SND_SEQ_EVENT_KEYPRESS:
|
||||
case SND_SEQ_EVENT_CONTROLLER:
|
||||
printf("; param=%i, value=%i\n",
|
||||
ev->data.control.param,
|
||||
ev->data.control.value);
|
||||
printf("; ch=%d, param=%i, value=%i\n",
|
||||
ev->data.control.channel,
|
||||
ev->data.control.param,
|
||||
ev->data.control.value);
|
||||
break;
|
||||
|
||||
case SND_SEQ_EVENT_PGMCHANGE:
|
||||
printf("; program=%i\n", ev->data.control.value);
|
||||
printf("; ch=%d, program=%i\n",
|
||||
ev->data.control.channel,
|
||||
ev->data.control.value);
|
||||
break;
|
||||
|
||||
case SND_SEQ_EVENT_CHANPRESS:
|
||||
case SND_SEQ_EVENT_PITCHBEND:
|
||||
printf("; value=%i\n", ev->data.control.value);
|
||||
printf("; ch=%d, value=%i\n",
|
||||
ev->data.control.channel,
|
||||
ev->data.control.value);
|
||||
break;
|
||||
|
||||
case SND_SEQ_EVENT_SYSEX:
|
||||
|
|
@ -353,10 +357,10 @@ int decode_event(snd_seq_event_t * ev)
|
|||
case SND_SEQ_EVENT_START:
|
||||
case SND_SEQ_EVENT_CONTINUE:
|
||||
case SND_SEQ_EVENT_STOP:
|
||||
printf("; queue = %i, client = %i\n", ev->data.addr.queue, ev->data.addr.client);
|
||||
printf("; queue = %i\n", ev->data.queue.queue);
|
||||
break;
|
||||
|
||||
case SND_SEQ_EVENT_HEARTBEAT:
|
||||
case SND_SEQ_EVENT_SENSING:
|
||||
printf("\n");
|
||||
break;
|
||||
|
||||
|
|
@ -402,18 +406,8 @@ int decode_event(snd_seq_event_t * ev)
|
|||
void event_decoder_start_timer(snd_seq_t *handle, int queue, int client, int port)
|
||||
{
|
||||
int err;
|
||||
snd_seq_event_t ev;
|
||||
|
||||
bzero(&ev, sizeof(ev));
|
||||
ev.source.queue = queue;
|
||||
ev.source.client = client;
|
||||
ev.source.port = 0;
|
||||
ev.dest.queue = queue;
|
||||
ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
|
||||
ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
|
||||
ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_REL;
|
||||
ev.type = SND_SEQ_EVENT_START;
|
||||
if ((err = snd_seq_event_output(handle, &ev))<0)
|
||||
|
||||
if ((err = snd_seq_start_queue(handle, queue, NULL))<0)
|
||||
fprintf(stderr, "Timer event output error: %s\n", snd_strerror(err));
|
||||
while (snd_seq_flush_output(handle)>0)
|
||||
sleep(1);
|
||||
|
|
@ -442,7 +436,7 @@ void event_decoder(snd_seq_t *handle, int argc, char *argv[])
|
|||
fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err));
|
||||
bzero(&port, sizeof(port));
|
||||
strcpy(port.name, "Input");
|
||||
port.capability = SND_SEQ_PORT_CAP_WRITE;
|
||||
port.capability = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ;
|
||||
if ((err = snd_seq_create_port(handle, &port)) < 0) {
|
||||
fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err));
|
||||
return;
|
||||
|
|
@ -450,10 +444,8 @@ void event_decoder(snd_seq_t *handle, int argc, char *argv[])
|
|||
event_decoder_start_timer(handle, queue, client, port.port);
|
||||
|
||||
bzero(&sub, sizeof(sub));
|
||||
sub.sender.queue = queue;
|
||||
sub.sender.client = SND_SEQ_CLIENT_SYSTEM;
|
||||
sub.sender.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
|
||||
sub.dest.queue = queue;
|
||||
sub.dest.client = client;
|
||||
sub.dest.port = port.port;
|
||||
sub.exclusive = 0;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
|
||||
#ifdef USE_PCM
|
||||
/*
|
||||
* PCM timer layer
|
||||
*/
|
||||
|
|
@ -50,7 +52,7 @@ void show_playback_status(snd_pcm_t *phandle)
|
|||
printf(" Fragments : %i\n", pstatus.fragments);
|
||||
printf(" Fragment size : %i\n", pstatus.fragment_size);
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Simple event sender
|
||||
*/
|
||||
|
|
@ -58,8 +60,8 @@ void show_playback_status(snd_pcm_t *phandle)
|
|||
void event_sender_start_timer(snd_seq_t *handle, int client, int queue, snd_pcm_t *phandle)
|
||||
{
|
||||
int err;
|
||||
snd_seq_event_t ev;
|
||||
|
||||
#ifdef USE_PCM
|
||||
if (phandle) {
|
||||
snd_pcm_playback_info_t pinfo;
|
||||
snd_seq_queue_timer_t qtimer;
|
||||
|
|
@ -78,16 +80,8 @@ void event_sender_start_timer(snd_seq_t *handle, int client, int queue, snd_pcm_
|
|||
exit(0);
|
||||
}
|
||||
}
|
||||
bzero(&ev, sizeof(ev));
|
||||
ev.source.queue = queue;
|
||||
ev.source.client = client;
|
||||
ev.source.port = 0;
|
||||
ev.dest.queue = queue;
|
||||
ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
|
||||
ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
|
||||
ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_REL;
|
||||
ev.type = SND_SEQ_EVENT_START;
|
||||
if ((err = snd_seq_event_output(handle, &ev))<0)
|
||||
#endif
|
||||
if ((err = snd_seq_start_queue(handle, queue, NULL))<0)
|
||||
fprintf(stderr, "Timer event output error: %s\n", snd_strerror(err));
|
||||
/* ugly, but working */
|
||||
while (snd_seq_flush_output(handle)>0)
|
||||
|
|
@ -119,7 +113,7 @@ void send_event(snd_seq_t *handle, int queue, int client, int port,
|
|||
snd_seq_event_t ev;
|
||||
|
||||
bzero(&ev, sizeof(ev));
|
||||
ev.source.queue = ev.dest.queue = queue;
|
||||
ev.queue = queue;
|
||||
ev.source.client = ev.dest.client = client;
|
||||
ev.source.port = ev.dest.port = port;
|
||||
ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_ABS;
|
||||
|
|
@ -129,10 +123,11 @@ void send_event(snd_seq_t *handle, int queue, int client, int port,
|
|||
fprintf(stderr, "Event output error: %s\n", snd_strerror(err));
|
||||
ev.dest.client = sub->dest.client;
|
||||
ev.dest.port = sub->dest.port;
|
||||
ev.dest.channel = 0;
|
||||
ev.type = SND_SEQ_EVENT_NOTE;
|
||||
ev.data.note.channel = 0;
|
||||
ev.data.note.note = 64 + (queue*2);
|
||||
ev.data.note.velocity = 127;
|
||||
ev.data.note.off_velocity = 127;
|
||||
ev.data.note.duration = 500; /* 0.5sec */
|
||||
if ((err = snd_seq_event_output(handle, &ev))<0)
|
||||
fprintf(stderr, "Event output error: %s\n", snd_strerror(err));
|
||||
|
|
@ -178,10 +173,8 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[])
|
|||
}
|
||||
|
||||
bzero(&sub, sizeof(sub));
|
||||
sub.sender.queue = queue;
|
||||
sub.sender.client = client;
|
||||
sub.sender.port = port.port;
|
||||
sub.dest.queue = queue;
|
||||
sub.exclusive = 0;
|
||||
|
||||
for (max = 0; max < argc; max++) {
|
||||
|
|
@ -206,6 +199,7 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[])
|
|||
|
||||
printf("Destonation client = %i, port = %i\n", sub.dest.client, sub.dest.port);
|
||||
|
||||
#ifdef USE_PCM
|
||||
if (pcm_flag) {
|
||||
if ((err = snd_pcm_open(&phandle, pcard, pdevice, SND_PCM_OPEN_PLAYBACK)) < 0) {
|
||||
fprintf(stderr, "Playback open error: %s\n", snd_strerror(err));
|
||||
|
|
@ -220,6 +214,7 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[])
|
|||
exit(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
event_sender_start_timer(handle, client, queue, phandle);
|
||||
|
||||
first = 1;
|
||||
|
|
@ -229,19 +224,23 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[])
|
|||
max = snd_seq_file_descriptor(handle);
|
||||
FD_SET(snd_seq_file_descriptor(handle), &out);
|
||||
FD_SET(snd_seq_file_descriptor(handle), &in);
|
||||
#ifdef USE_PCM
|
||||
if (phandle) {
|
||||
if (snd_pcm_file_descriptor(phandle) > max)
|
||||
max = snd_pcm_file_descriptor(phandle);
|
||||
FD_SET(snd_pcm_file_descriptor(phandle), &out);
|
||||
}
|
||||
#endif
|
||||
if (select(max + 1, &in, &out, NULL, NULL) < 0)
|
||||
break;
|
||||
#ifdef USE_PCM
|
||||
if (phandle && FD_ISSET(snd_pcm_file_descriptor(phandle), &out)) {
|
||||
if (snd_pcm_write(phandle, pbuf, pfragment_size) != pfragment_size) {
|
||||
fprintf(stderr, "Playback write error!!\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (FD_ISSET(snd_seq_file_descriptor(handle), &out)) {
|
||||
if (first) {
|
||||
send_event(handle, queue, client, port.port, &sub, &time);
|
||||
|
|
|
|||
|
|
@ -151,6 +151,8 @@ int main(int argc, char *argv[])
|
|||
{"version", 0, NULL, HELPID_VERSION},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
|
||||
morehelp = 0;
|
||||
|
||||
while (1) {
|
||||
int c;
|
||||
|
|
@ -193,6 +195,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
set_name(handle);
|
||||
system_info(handle);
|
||||
|
||||
if (!strcmp(argv[optind], "system")) {
|
||||
show_system_info(handle);
|
||||
} else if (!strcmp(argv[optind], "queue")) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue