alsa-lib/test/seq-decoder.c
Jaroslav Kysela 88e5e45151 Major change to sequencer API.
The sequencer API is totally recoded with the style of "encapsulation"
in other api.
The structure becomes opaque and accessed only via functions.

Other changes:
- There is no longer group in client and port info.
- snd_seq_query_subs_t is renamed to snd_seq_query_subscribe_t.
- snd_seq_delete_port takes only the port id argument instead of
  port_info structure.
- snd_seq_input/output_buffer_size are renamed
  as snd_seq_get_input/output_buffer_size.
  Similarly snd_seq_resize_input/output_buffer are renamed as
  snd_seq_set_input/output_buffer_size.
- snd_seq_get_named_queue is renamed to snd_seq_query_named_queue.
- Sync codes are removed temporarily from API.
- Subscription conditions are accessed via the corresponding functions.
  convert_time is named now as time_update.
- snd_seq_get/set_queue_owner are removed.
  Use snd_seq_get/set_queue_info instead.
- Instrument put/get/remove structure is unified as snd_instr_header_t.
2001-07-04 13:54:13 +00:00

346 lines
10 KiB
C

/*
* Simple event decoder
*/
static char *event_names[256] = {
[SND_SEQ_EVENT_SYSTEM]= "System",
[SND_SEQ_EVENT_RESULT]= "Result",
[SND_SEQ_EVENT_NOTE]= "Note",
[SND_SEQ_EVENT_NOTEON]= "Note On",
[SND_SEQ_EVENT_NOTEOFF]= "Note Off",
[SND_SEQ_EVENT_KEYPRESS]= "Key Pressure",
[SND_SEQ_EVENT_CONTROLLER]= "Controller",
[SND_SEQ_EVENT_PGMCHANGE]= "Program Change",
[SND_SEQ_EVENT_CHANPRESS]= "Channel Pressure",
[SND_SEQ_EVENT_PITCHBEND]= "Pitchbend",
[SND_SEQ_EVENT_CONTROL14]= "Control14",
[SND_SEQ_EVENT_NONREGPARAM]= "Nonregparam",
[SND_SEQ_EVENT_REGPARAM]= "Regparam",
[SND_SEQ_EVENT_SONGPOS]= "Song Position",
[SND_SEQ_EVENT_SONGSEL]= "Song Select",
[SND_SEQ_EVENT_QFRAME]= "Qframe",
[SND_SEQ_EVENT_TIMESIGN]= "SMF Time Signature",
[SND_SEQ_EVENT_KEYSIGN]= "SMF Key Signature",
[SND_SEQ_EVENT_START]= "Start",
[SND_SEQ_EVENT_CONTINUE]= "Continue",
[SND_SEQ_EVENT_STOP]= "Stop",
[SND_SEQ_EVENT_SETPOS_TICK]= "Set Position Tick",
[SND_SEQ_EVENT_SETPOS_TIME]= "Set Position Time",
[SND_SEQ_EVENT_TEMPO]= "Tempo",
[SND_SEQ_EVENT_CLOCK]= "Clock",
[SND_SEQ_EVENT_TICK]= "Tick",
[SND_SEQ_EVENT_SYNC]= "Sync",
[SND_SEQ_EVENT_SYNC_POS]= "Sync Position",
[SND_SEQ_EVENT_TUNE_REQUEST]= "Tune Request",
[SND_SEQ_EVENT_RESET]= "Reset",
[SND_SEQ_EVENT_SENSING]= "Active Sensing",
[SND_SEQ_EVENT_ECHO]= "Echo",
[SND_SEQ_EVENT_OSS]= "OSS",
[SND_SEQ_EVENT_CLIENT_START]= "Client Start",
[SND_SEQ_EVENT_CLIENT_EXIT]= "Client Exit",
[SND_SEQ_EVENT_CLIENT_CHANGE]= "Client Change",
[SND_SEQ_EVENT_PORT_START]= "Port Start",
[SND_SEQ_EVENT_PORT_EXIT]= "Port Exit",
[SND_SEQ_EVENT_PORT_CHANGE]= "Port Change",
[SND_SEQ_EVENT_PORT_SUBSCRIBED]= "Port Subscribed",
[SND_SEQ_EVENT_PORT_UNSUBSCRIBED]= "Port Unsubscribed",
[SND_SEQ_EVENT_SAMPLE]= "Sample",
[SND_SEQ_EVENT_SAMPLE_CLUSTER]= "Sample Cluster",
[SND_SEQ_EVENT_SAMPLE_START]= "Sample Start",
[SND_SEQ_EVENT_SAMPLE_STOP]= "Sample Stop",
[SND_SEQ_EVENT_SAMPLE_FREQ]= "Sample Freq",
[SND_SEQ_EVENT_SAMPLE_VOLUME]= "Sample Volume",
[SND_SEQ_EVENT_SAMPLE_LOOP]= "Sample Loop",
[SND_SEQ_EVENT_SAMPLE_POSITION]= "Sample Position",
[SND_SEQ_EVENT_SAMPLE_PRIVATE1]= "Sample Private1",
[SND_SEQ_EVENT_USR0]= "User 0",
[SND_SEQ_EVENT_USR1]= "User 1",
[SND_SEQ_EVENT_USR2]= "User 2",
[SND_SEQ_EVENT_USR3]= "User 3",
[SND_SEQ_EVENT_USR4]= "User 4",
[SND_SEQ_EVENT_USR5]= "User 5",
[SND_SEQ_EVENT_USR6]= "User 6",
[SND_SEQ_EVENT_USR7]= "User 7",
[SND_SEQ_EVENT_USR8]= "User 8",
[SND_SEQ_EVENT_USR9]= "User 9",
[SND_SEQ_EVENT_INSTR_BEGIN]= "Instr Begin",
[SND_SEQ_EVENT_INSTR_END]= "Instr End",
[SND_SEQ_EVENT_INSTR_INFO]= "Instr Info",
[SND_SEQ_EVENT_INSTR_INFO_RESULT]= "Instr Info Result",
[SND_SEQ_EVENT_INSTR_FINFO]= "Instr Font Info",
[SND_SEQ_EVENT_INSTR_FINFO_RESULT]= "Instr Font Info Result",
[SND_SEQ_EVENT_INSTR_RESET]= "Instr Reset",
[SND_SEQ_EVENT_INSTR_STATUS]= "Instr Status",
[SND_SEQ_EVENT_INSTR_STATUS_RESULT]= "Instr Status Result",
[SND_SEQ_EVENT_INSTR_PUT]= "Instr Put",
[SND_SEQ_EVENT_INSTR_GET]= "Instr Get",
[SND_SEQ_EVENT_INSTR_GET_RESULT]= "Instr Get Result",
[SND_SEQ_EVENT_INSTR_FREE]= "Instr Free",
[SND_SEQ_EVENT_INSTR_LIST]= "Instr List",
[SND_SEQ_EVENT_INSTR_LIST_RESULT]= "Instr List Result",
[SND_SEQ_EVENT_INSTR_CLUSTER]= "Instr Cluster",
[SND_SEQ_EVENT_INSTR_CLUSTER_GET]= "Instr Cluster Get",
[SND_SEQ_EVENT_INSTR_CLUSTER_RESULT]= "Instr Cluster Result",
[SND_SEQ_EVENT_INSTR_CHANGE]= "Instr Change",
[SND_SEQ_EVENT_SYSEX]= "Sysex",
[SND_SEQ_EVENT_BOUNCE]= "Bounce",
[SND_SEQ_EVENT_USR_VAR0]= "User Var0",
[SND_SEQ_EVENT_USR_VAR1]= "User Var1",
[SND_SEQ_EVENT_USR_VAR2]= "User Var2",
[SND_SEQ_EVENT_USR_VAR3]= "User Var3",
[SND_SEQ_EVENT_USR_VAR4]= "User Var4",
[SND_SEQ_EVENT_IPCSHM]= "IPC Shm",
[SND_SEQ_EVENT_USR_VARIPC0]= "User IPC0",
[SND_SEQ_EVENT_USR_VARIPC1]= "User IPC1",
[SND_SEQ_EVENT_USR_VARIPC2]= "User IPC2",
[SND_SEQ_EVENT_USR_VARIPC3]= "User IPC3",
[SND_SEQ_EVENT_USR_VARIPC4]= "User IPC4",
[SND_SEQ_EVENT_NONE]= "None",
};
int decode_event(snd_seq_event_t * ev)
{
char *space = " ";
printf("EVENT>>> Type = %d, flags = 0x%x", ev->type, ev->flags);
switch (ev->flags & SND_SEQ_TIME_STAMP_MASK) {
case SND_SEQ_TIME_STAMP_TICK:
printf(", time = %d ticks",
ev->time.tick);
break;
case SND_SEQ_TIME_STAMP_REAL:
printf(", time = %d.%09d",
(int)ev->time.time.tv_sec,
(int)ev->time.time.tv_nsec);
break;
}
printf("\n%sSource = %d.%d, dest = %d.%d, queue = %d\n",
space,
ev->source.client,
ev->source.port,
ev->dest.client,
ev->dest.port,
ev->queue);
if (event_names[ev->type])
printf("%sEvent = %s", space, event_names[ev->type]);
else
printf("%sEvent = Reserved %d\n", space, ev->type);
/* decode actual event data... */
switch (ev->type) {
case SND_SEQ_EVENT_NOTE:
printf("; ch=%d, note=%d, velocity=%d, off_velocity=%d, duration=%d\n",
ev->data.note.channel,
ev->data.note.note,
ev->data.note.velocity,
ev->data.note.off_velocity,
ev->data.note.duration);
break;
case SND_SEQ_EVENT_NOTEON:
case SND_SEQ_EVENT_NOTEOFF:
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_CONTROLLER:
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("; 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("; ch=%d, value=%i\n",
ev->data.control.channel,
ev->data.control.value);
break;
case SND_SEQ_EVENT_SYSEX:
{
unsigned char *sysex = (unsigned char *) ev + sizeof(snd_seq_event_t);
unsigned int c;
printf("; len=%d [", ev->data.ext.len);
for (c = 0; c < ev->data.ext.len; c++) {
printf("%02x%s", sysex[c], c < ev->data.ext.len - 1 ? ":" : "");
}
printf("]\n");
}
break;
case SND_SEQ_EVENT_QFRAME:
printf("; frame=0x%02x\n", ev->data.control.value);
break;
case SND_SEQ_EVENT_CLOCK:
case SND_SEQ_EVENT_START:
case SND_SEQ_EVENT_CONTINUE:
case SND_SEQ_EVENT_STOP:
printf("; queue = %i\n", ev->data.queue.queue);
break;
case SND_SEQ_EVENT_SENSING:
printf("\n");
break;
case SND_SEQ_EVENT_ECHO:
{
int i;
printf("; ");
for (i = 0; i < 8; i++) {
printf("%02i%s", ev->data.raw8.d[i], i < 7 ? ":" : "\n");
}
}
break;
case SND_SEQ_EVENT_CLIENT_START:
case SND_SEQ_EVENT_CLIENT_EXIT:
case SND_SEQ_EVENT_CLIENT_CHANGE:
printf("; client=%i\n", ev->data.addr.client);
break;
case SND_SEQ_EVENT_PORT_START:
case SND_SEQ_EVENT_PORT_EXIT:
case SND_SEQ_EVENT_PORT_CHANGE:
printf("; client=%i, port = %i\n", ev->data.addr.client, ev->data.addr.port);
break;
case SND_SEQ_EVENT_PORT_SUBSCRIBED:
case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
printf("; %i:%i -> %i:%i\n",
ev->data.connect.sender.client, ev->data.connect.sender.port,
ev->data.connect.dest.client, ev->data.connect.dest.port);
break;
default:
printf("; not implemented\n");
}
switch (ev->flags & SND_SEQ_EVENT_LENGTH_MASK) {
case SND_SEQ_EVENT_LENGTH_FIXED:
return sizeof(snd_seq_event_t);
case SND_SEQ_EVENT_LENGTH_VARIABLE:
return sizeof(snd_seq_event_t) + ev->data.ext.len;
}
return 0;
}
void event_decoder_start_timer(snd_seq_t *handle, int queue, int client, int port)
{
int err;
if ((err = snd_seq_start_queue(handle, queue, NULL))<0)
fprintf(stderr, "Timer event output error: %s\n", snd_strerror(err));
while (snd_seq_drain_output(handle)>0)
sleep(1);
}
void event_decoder(snd_seq_t *handle, int argc, char *argv[])
{
snd_seq_event_t *ev;
snd_seq_port_info_t *pinfo;
snd_seq_port_subscribe_t *sub;
snd_seq_addr_t addr;
int client, port, queue, max, err, v1, v2;
char *ptr;
struct pollfd *pfds;
if ((client = snd_seq_client_id(handle))<0) {
fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client));
return;
}
printf("Client ID = %i\n", client);
if ((queue = snd_seq_alloc_queue(handle))<0) {
fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue));
return;
}
printf("Queue ID = %i\n", queue);
if ((err = snd_seq_nonblock(handle, 1))<0)
fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err));
snd_seq_port_info_alloca(&pinfo);
snd_seq_port_info_set_name(pinfo, "Input");
snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_WRITE);
if ((err = snd_seq_create_port(handle, pinfo)) < 0) {
fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err));
return;
}
port = snd_seq_port_info_get_port(pinfo);
event_decoder_start_timer(handle, queue, client, port);
snd_seq_port_subscribe_alloca(&sub);
addr.client = SND_SEQ_CLIENT_SYSTEM;
addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
snd_seq_port_subscribe_set_sender(sub, &addr);
addr.client = client;
addr.port = port;
snd_seq_port_subscribe_set_dest(sub, &addr);
snd_seq_port_subscribe_set_queue(sub, queue);
snd_seq_port_subscribe_set_time_update(sub, 1);
snd_seq_port_subscribe_set_time_real(sub, 1);
if ((err = snd_seq_subscribe_port(handle, sub))<0) {
fprintf(stderr, "Cannot subscribe announce port: %s\n", snd_strerror(err));
return;
}
addr.client = SND_SEQ_CLIENT_SYSTEM;
addr.port = SND_SEQ_PORT_SYSTEM_TIMER;
snd_seq_port_subscribe_set_sender(sub, &addr);
if ((err = snd_seq_subscribe_port(handle, sub))<0) {
fprintf(stderr, "Cannot subscribe timer port: %s\n", snd_strerror(err));
return;
}
for (max = 0; max < argc; max++) {
ptr = argv[max];
if (!ptr)
continue;
snd_seq_port_subscribe_set_time_real(sub, 0);
if (tolower(*ptr) == 'r') {
snd_seq_port_subscribe_set_time_real(sub, 1);
ptr++;
}
if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) {
fprintf(stderr, "Wrong argument '%s'...\n", argv[max]);
return;
}
addr.client = v1;
addr.port = v2;
snd_seq_port_subscribe_set_sender(sub, &addr);
if ((err = snd_seq_subscribe_port(handle, sub))<0) {
fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err));
return;
}
}
max = snd_seq_poll_descriptors_count(handle, POLLIN);
pfds = alloca(sizeof(*pfds) * max);
while (1) {
snd_seq_poll_descriptors(handle, pfds, max, POLLIN);
if (poll(pfds, max, -1) < 0)
break;
do {
if ((err = snd_seq_event_input(handle, &ev))<0)
break;
if (!ev)
continue;
decode_event(ev);
snd_seq_free_event(ev);
} while (err > 0);
}
}