Home | History | Annotate | Download | only in test
      1 /*
      2  *  Simple event decoder
      3  */
      4 
      5 static char *event_names[256] = {
      6 	[SND_SEQ_EVENT_SYSTEM]=	"System",
      7 	[SND_SEQ_EVENT_RESULT]=	"Result",
      8 	[SND_SEQ_EVENT_NOTE]=	"Note",
      9 	[SND_SEQ_EVENT_NOTEON]=	"Note On",
     10 	[SND_SEQ_EVENT_NOTEOFF]=	"Note Off",
     11 	[SND_SEQ_EVENT_KEYPRESS]=	"Key Pressure",
     12 	[SND_SEQ_EVENT_CONTROLLER]=	"Controller",
     13 	[SND_SEQ_EVENT_PGMCHANGE]=	"Program Change",
     14 	[SND_SEQ_EVENT_CHANPRESS]=	"Channel Pressure",
     15 	[SND_SEQ_EVENT_PITCHBEND]=	"Pitchbend",
     16 	[SND_SEQ_EVENT_CONTROL14]=	"Control14",
     17 	[SND_SEQ_EVENT_NONREGPARAM]=	"Nonregparam",
     18 	[SND_SEQ_EVENT_REGPARAM]=		"Regparam",
     19 	[SND_SEQ_EVENT_SONGPOS]=	"Song Position",
     20 	[SND_SEQ_EVENT_SONGSEL]=	"Song Select",
     21 	[SND_SEQ_EVENT_QFRAME]=	"Qframe",
     22 	[SND_SEQ_EVENT_TIMESIGN]=	"SMF Time Signature",
     23 	[SND_SEQ_EVENT_KEYSIGN]=	"SMF Key Signature",
     24 	[SND_SEQ_EVENT_START]=	"Start",
     25 	[SND_SEQ_EVENT_CONTINUE]=	"Continue",
     26 	[SND_SEQ_EVENT_STOP]=	"Stop",
     27 	[SND_SEQ_EVENT_SETPOS_TICK]=	"Set Position Tick",
     28 	[SND_SEQ_EVENT_SETPOS_TIME]=	"Set Position Time",
     29 	[SND_SEQ_EVENT_TEMPO]=	"Tempo",
     30 	[SND_SEQ_EVENT_CLOCK]=	"Clock",
     31 	[SND_SEQ_EVENT_TICK]=	"Tick",
     32 	[SND_SEQ_EVENT_TUNE_REQUEST]=	"Tune Request",
     33 	[SND_SEQ_EVENT_RESET]=	"Reset",
     34 	[SND_SEQ_EVENT_SENSING]=	"Active Sensing",
     35 	[SND_SEQ_EVENT_ECHO]=	"Echo",
     36 	[SND_SEQ_EVENT_OSS]=	"OSS",
     37 	[SND_SEQ_EVENT_CLIENT_START]=	"Client Start",
     38 	[SND_SEQ_EVENT_CLIENT_EXIT]=	"Client Exit",
     39 	[SND_SEQ_EVENT_CLIENT_CHANGE]=	"Client Change",
     40 	[SND_SEQ_EVENT_PORT_START]=	"Port Start",
     41 	[SND_SEQ_EVENT_PORT_EXIT]=	"Port Exit",
     42 	[SND_SEQ_EVENT_PORT_CHANGE]=	"Port Change",
     43 	[SND_SEQ_EVENT_PORT_SUBSCRIBED]=	"Port Subscribed",
     44 	[SND_SEQ_EVENT_PORT_UNSUBSCRIBED]=	"Port Unsubscribed",
     45 #if 0
     46 	[SND_SEQ_EVENT_SAMPLE]=	"Sample",
     47 	[SND_SEQ_EVENT_SAMPLE_CLUSTER]=	"Sample Cluster",
     48 	[SND_SEQ_EVENT_SAMPLE_START]=	"Sample Start",
     49 	[SND_SEQ_EVENT_SAMPLE_STOP]=	"Sample Stop",
     50 	[SND_SEQ_EVENT_SAMPLE_FREQ]=	"Sample Freq",
     51 	[SND_SEQ_EVENT_SAMPLE_VOLUME]=	"Sample Volume",
     52 	[SND_SEQ_EVENT_SAMPLE_LOOP]=	"Sample Loop",
     53 	[SND_SEQ_EVENT_SAMPLE_POSITION]=	"Sample Position",
     54 	[SND_SEQ_EVENT_SAMPLE_PRIVATE1]=	"Sample Private1",
     55 #endif
     56 	[SND_SEQ_EVENT_USR0]=	"User 0",
     57 	[SND_SEQ_EVENT_USR1]=	"User 1",
     58 	[SND_SEQ_EVENT_USR2]=	"User 2",
     59 	[SND_SEQ_EVENT_USR3]=	"User 3",
     60 	[SND_SEQ_EVENT_USR4]=	"User 4",
     61 	[SND_SEQ_EVENT_USR5]=	"User 5",
     62 	[SND_SEQ_EVENT_USR6]=	"User 6",
     63 	[SND_SEQ_EVENT_USR7]=	"User 7",
     64 	[SND_SEQ_EVENT_USR8]=	"User 8",
     65 	[SND_SEQ_EVENT_USR9]=	"User 9",
     66 #if 0
     67 	[SND_SEQ_EVENT_INSTR_BEGIN]=	"Instr Begin",
     68 	[SND_SEQ_EVENT_INSTR_END]=	"Instr End",
     69 	[SND_SEQ_EVENT_INSTR_INFO]=	"Instr Info",
     70 	[SND_SEQ_EVENT_INSTR_INFO_RESULT]=	"Instr Info Result",
     71 	[SND_SEQ_EVENT_INSTR_FINFO]=	"Instr Font Info",
     72 	[SND_SEQ_EVENT_INSTR_FINFO_RESULT]=	"Instr Font Info Result",
     73 	[SND_SEQ_EVENT_INSTR_RESET]=	"Instr Reset",
     74 	[SND_SEQ_EVENT_INSTR_STATUS]=	"Instr Status",
     75 	[SND_SEQ_EVENT_INSTR_STATUS_RESULT]=	"Instr Status Result",
     76 	[SND_SEQ_EVENT_INSTR_PUT]=	"Instr Put",
     77 	[SND_SEQ_EVENT_INSTR_GET]=	"Instr Get",
     78 	[SND_SEQ_EVENT_INSTR_GET_RESULT]=	"Instr Get Result",
     79 	[SND_SEQ_EVENT_INSTR_FREE]=	"Instr Free",
     80 	[SND_SEQ_EVENT_INSTR_LIST]=	"Instr List",
     81 	[SND_SEQ_EVENT_INSTR_LIST_RESULT]=	"Instr List Result",
     82 	[SND_SEQ_EVENT_INSTR_CLUSTER]=	"Instr Cluster",
     83 	[SND_SEQ_EVENT_INSTR_CLUSTER_GET]=	"Instr Cluster Get",
     84 	[SND_SEQ_EVENT_INSTR_CLUSTER_RESULT]=	"Instr Cluster Result",
     85 	[SND_SEQ_EVENT_INSTR_CHANGE]=	"Instr Change",
     86 #endif
     87 	[SND_SEQ_EVENT_SYSEX]=	"Sysex",
     88 	[SND_SEQ_EVENT_BOUNCE]=	"Bounce",
     89 	[SND_SEQ_EVENT_USR_VAR0]=	"User Var0",
     90 	[SND_SEQ_EVENT_USR_VAR1]=	"User Var1",
     91 	[SND_SEQ_EVENT_USR_VAR2]=	"User Var2",
     92 	[SND_SEQ_EVENT_USR_VAR3]=	"User Var3",
     93 	[SND_SEQ_EVENT_USR_VAR4]=	"User Var4",
     94 #if 0
     95 	[SND_SEQ_EVENT_IPCSHM]=	"IPC Shm",
     96 	[SND_SEQ_EVENT_USR_VARIPC0]=	"User IPC0",
     97 	[SND_SEQ_EVENT_USR_VARIPC1]=	"User IPC1",
     98 	[SND_SEQ_EVENT_USR_VARIPC2]=	"User IPC2",
     99 	[SND_SEQ_EVENT_USR_VARIPC3]=	"User IPC3",
    100 	[SND_SEQ_EVENT_USR_VARIPC4]=	"User IPC4",
    101 #endif
    102 	[SND_SEQ_EVENT_NONE]=	"None",
    103 };
    104 
    105 int decode_event(snd_seq_event_t * ev)
    106 {
    107 	char *space = "         ";
    108 
    109 	printf("EVENT>>> Type = %d, flags = 0x%x", ev->type, ev->flags);
    110 	switch (ev->flags & SND_SEQ_TIME_STAMP_MASK) {
    111 	case SND_SEQ_TIME_STAMP_TICK:
    112 		printf(", time = %d ticks",
    113 		       ev->time.tick);
    114 		break;
    115 	case SND_SEQ_TIME_STAMP_REAL:
    116 		printf(", time = %d.%09d",
    117 		       (int)ev->time.time.tv_sec,
    118 		       (int)ev->time.time.tv_nsec);
    119 		break;
    120 	}
    121 	printf("\n%sSource = %d.%d, dest = %d.%d, queue = %d\n",
    122 	       space,
    123 	       ev->source.client,
    124 	       ev->source.port,
    125 	       ev->dest.client,
    126 	       ev->dest.port,
    127 	       ev->queue);
    128 
    129 	if (event_names[ev->type])
    130 		printf("%sEvent = %s", space, event_names[ev->type]);
    131 	else
    132 		printf("%sEvent = Reserved %d\n", space, ev->type);
    133 	/* decode the actual event data... */
    134 	switch (ev->type) {
    135 	case SND_SEQ_EVENT_NOTE:
    136 		printf("; ch=%d, note=%d, velocity=%d, off_velocity=%d, duration=%d\n",
    137 		       ev->data.note.channel,
    138 		       ev->data.note.note,
    139 		       ev->data.note.velocity,
    140 		       ev->data.note.off_velocity,
    141 		       ev->data.note.duration);
    142 		break;
    143 
    144 	case SND_SEQ_EVENT_NOTEON:
    145 	case SND_SEQ_EVENT_NOTEOFF:
    146 	case SND_SEQ_EVENT_KEYPRESS:
    147 		printf("; ch=%d, note=%d, velocity=%d\n",
    148 		       ev->data.note.channel,
    149 		       ev->data.note.note,
    150 		       ev->data.note.velocity);
    151 		break;
    152 
    153 	case SND_SEQ_EVENT_CONTROLLER:
    154 		printf("; ch=%d, param=%i, value=%i\n",
    155 		       ev->data.control.channel,
    156 		       ev->data.control.param,
    157 		       ev->data.control.value);
    158 		break;
    159 
    160 	case SND_SEQ_EVENT_PGMCHANGE:
    161 		printf("; ch=%d, program=%i\n",
    162 		       ev->data.control.channel,
    163 		       ev->data.control.value);
    164 		break;
    165 
    166 	case SND_SEQ_EVENT_CHANPRESS:
    167 	case SND_SEQ_EVENT_PITCHBEND:
    168 		printf("; ch=%d, value=%i\n",
    169 		       ev->data.control.channel,
    170 		       ev->data.control.value);
    171 		break;
    172 
    173 	case SND_SEQ_EVENT_SYSEX:
    174 		{
    175 			unsigned char *sysex = (unsigned char *) ev + sizeof(snd_seq_event_t);
    176 			unsigned int c;
    177 
    178 			printf("; len=%d [", ev->data.ext.len);
    179 
    180 			for (c = 0; c < ev->data.ext.len; c++) {
    181 				printf("%02x%s", sysex[c], c < ev->data.ext.len - 1 ? ":" : "");
    182 			}
    183 			printf("]\n");
    184 		}
    185 		break;
    186 
    187 	case SND_SEQ_EVENT_QFRAME:
    188 		printf("; frame=0x%02x\n", ev->data.control.value);
    189 		break;
    190 
    191 	case SND_SEQ_EVENT_CLOCK:
    192 	case SND_SEQ_EVENT_START:
    193 	case SND_SEQ_EVENT_CONTINUE:
    194 	case SND_SEQ_EVENT_STOP:
    195 		printf("; queue = %i\n", ev->data.queue.queue);
    196 		break;
    197 
    198 	case SND_SEQ_EVENT_SENSING:
    199 		printf("\n");
    200 		break;
    201 
    202 	case SND_SEQ_EVENT_ECHO:
    203 		{
    204 			int i;
    205 
    206 			printf("; ");
    207 			for (i = 0; i < 8; i++) {
    208 				printf("%02i%s", ev->data.raw8.d[i], i < 7 ? ":" : "\n");
    209 			}
    210 		}
    211 		break;
    212 
    213 	case SND_SEQ_EVENT_CLIENT_START:
    214 	case SND_SEQ_EVENT_CLIENT_EXIT:
    215 	case SND_SEQ_EVENT_CLIENT_CHANGE:
    216 		printf("; client=%i\n", ev->data.addr.client);
    217 		break;
    218 
    219 	case SND_SEQ_EVENT_PORT_START:
    220 	case SND_SEQ_EVENT_PORT_EXIT:
    221 	case SND_SEQ_EVENT_PORT_CHANGE:
    222 		printf("; client=%i, port = %i\n", ev->data.addr.client, ev->data.addr.port);
    223 		break;
    224 
    225 	case SND_SEQ_EVENT_PORT_SUBSCRIBED:
    226 	case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
    227 		printf("; %i:%i -> %i:%i\n",
    228 		       ev->data.connect.sender.client, ev->data.connect.sender.port,
    229 		       ev->data.connect.dest.client, ev->data.connect.dest.port);
    230 		break;
    231 
    232 	default:
    233 		printf("; not implemented\n");
    234 	}
    235 
    236 
    237 	switch (ev->flags & SND_SEQ_EVENT_LENGTH_MASK) {
    238 	case SND_SEQ_EVENT_LENGTH_FIXED:
    239 		return sizeof(snd_seq_event_t);
    240 
    241 	case SND_SEQ_EVENT_LENGTH_VARIABLE:
    242 		return sizeof(snd_seq_event_t) + ev->data.ext.len;
    243 	}
    244 
    245 	return 0;
    246 }
    247 
    248 void event_decoder_start_timer(snd_seq_t *handle, int queue,
    249 			       int client ATTRIBUTE_UNUSED,
    250 			       int port ATTRIBUTE_UNUSED)
    251 {
    252 	int err;
    253 
    254 	if ((err = snd_seq_start_queue(handle, queue, NULL))<0)
    255 		fprintf(stderr, "Timer event output error: %s\n", snd_strerror(err));
    256 	while (snd_seq_drain_output(handle)>0)
    257 		sleep(1);
    258 }
    259 
    260 void event_decoder(snd_seq_t *handle, int argc, char *argv[])
    261 {
    262 	snd_seq_event_t *ev;
    263 	snd_seq_port_info_t *pinfo;
    264 	snd_seq_port_subscribe_t *sub;
    265 	snd_seq_addr_t addr;
    266 	int client, port, queue, max, err, v1, v2;
    267 	char *ptr;
    268 	struct pollfd *pfds;
    269 
    270 	if ((client = snd_seq_client_id(handle))<0) {
    271 		fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client));
    272 		return;
    273 	}
    274 	printf("Client ID = %i\n", client);
    275 	if ((queue = snd_seq_alloc_queue(handle))<0) {
    276 		fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue));
    277 		return;
    278 	}
    279 	printf("Queue ID = %i\n", queue);
    280 	if ((err = snd_seq_nonblock(handle, 1))<0)
    281 		fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err));
    282 	snd_seq_port_info_alloca(&pinfo);
    283 	snd_seq_port_info_set_name(pinfo, "Input");
    284 	snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC);
    285 	snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_WRITE);
    286 	if ((err = snd_seq_create_port(handle, pinfo)) < 0) {
    287 		fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err));
    288 		return;
    289 	}
    290 	port = snd_seq_port_info_get_port(pinfo);
    291 	event_decoder_start_timer(handle, queue, client, port);
    292 
    293 	snd_seq_port_subscribe_alloca(&sub);
    294 	addr.client = SND_SEQ_CLIENT_SYSTEM;
    295 	addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
    296 	snd_seq_port_subscribe_set_sender(sub, &addr);
    297 	addr.client = client;
    298 	addr.port = port;
    299 	snd_seq_port_subscribe_set_dest(sub, &addr);
    300 	snd_seq_port_subscribe_set_queue(sub, queue);
    301 	snd_seq_port_subscribe_set_time_update(sub, 1);
    302 	snd_seq_port_subscribe_set_time_real(sub, 1);
    303 	if ((err = snd_seq_subscribe_port(handle, sub))<0) {
    304 		fprintf(stderr, "Cannot subscribe announce port: %s\n", snd_strerror(err));
    305 		return;
    306 	}
    307 
    308 	addr.client = SND_SEQ_CLIENT_SYSTEM;
    309 	addr.port = SND_SEQ_PORT_SYSTEM_TIMER;
    310 	snd_seq_port_subscribe_set_sender(sub, &addr);
    311 	if ((err = snd_seq_subscribe_port(handle, sub))<0) {
    312 		fprintf(stderr, "Cannot subscribe timer port: %s\n", snd_strerror(err));
    313 		return;
    314 	}
    315 
    316 	for (max = 0; max < argc; max++) {
    317 		ptr = argv[max];
    318 		if (!ptr)
    319 			continue;
    320 		snd_seq_port_subscribe_set_time_real(sub, 0);
    321 		if (tolower(*ptr) == 'r') {
    322 			snd_seq_port_subscribe_set_time_real(sub, 1);
    323 			ptr++;
    324 		}
    325 		if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) {
    326 			fprintf(stderr, "Wrong argument '%s'...\n", argv[max]);
    327 			return;
    328 		}
    329 		addr.client = v1;
    330 		addr.port = v2;
    331 		snd_seq_port_subscribe_set_sender(sub, &addr);
    332 		if ((err = snd_seq_subscribe_port(handle, sub))<0) {
    333 			fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err));
    334 			return;
    335 		}
    336 	}
    337 
    338 	max = snd_seq_poll_descriptors_count(handle, POLLIN);
    339 	pfds = alloca(sizeof(*pfds) * max);
    340 	while (1) {
    341 		snd_seq_poll_descriptors(handle, pfds, max, POLLIN);
    342 		if (poll(pfds, max, -1) < 0)
    343 			break;
    344 		do {
    345 			if ((err = snd_seq_event_input(handle, &ev))<0)
    346 				break;
    347 			if (!ev)
    348 				continue;
    349 			decode_event(ev);
    350 			snd_seq_free_event(ev);
    351 		} while (err > 0);
    352 	}
    353 }
    354