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