update the website url
[gmidimonitor.git] / alsa.c
blob6a35aaeb0a50f5a52c5d55d51f55dd5566108453
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
4 * This file is part of gmidimonitor
6 * Copyright (C) 2005,2006,2007,2008,2011 Nedko Arnaudov <nedko@arnaudov.name>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *****************************************************************************/
23 #include <alsa/asoundlib.h>
24 #include <gtk/gtk.h>
25 #include <pthread.h>
27 #include "common.h"
28 #include "alsa.h"
29 #include "glade.h"
30 #include "gm.h"
31 #include "sysex.h"
33 /* TODO: this must be detected at configure stage */
34 #define OLD_ALSA 0
36 snd_seq_t * g_seq_ptr;
37 pthread_t g_alsa_midi_tid; /* alsa_midi_thread id */
39 /* The ALSA MIDI input handling thread */
40 void *
41 alsa_midi_thread(void * context_ptr)
43 GtkTreeIter iter;
44 snd_seq_event_t * event_ptr;
45 GtkListStore * list_store_ptr;
46 GtkWidget * child_ptr;
47 GString * time_str_ptr;
48 GString * msg_str_ptr;
49 GString * channel_str_ptr;
50 const char * note_name;
51 int octave;
52 const char * drum_name;
53 const char * cc_name;
55 child_ptr = get_glade_widget_child(g_main_window_ptr, "list");
57 list_store_ptr = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(child_ptr)));
59 while (snd_seq_event_input(g_seq_ptr, &event_ptr) >= 0)
61 if (g_midi_ignore)
62 continue;
64 time_str_ptr = g_string_new("");
65 g_string_sprintf(
66 time_str_ptr,
67 "%u:%u",
68 (unsigned int)event_ptr->time.time.tv_sec,
69 (unsigned int)event_ptr->time.time.tv_nsec);
70 channel_str_ptr = g_string_new("");
72 /* Workaround for compiler warnings... */
73 drum_name = NULL;
74 note_name = NULL;
75 octave = 0;
77 if (event_ptr->type == SND_SEQ_EVENT_NOTE ||
78 event_ptr->type == SND_SEQ_EVENT_NOTEON ||
79 event_ptr->type == SND_SEQ_EVENT_NOTEOFF ||
80 event_ptr->type == SND_SEQ_EVENT_KEYPRESS)
82 g_string_sprintf(
83 channel_str_ptr,
84 "%u",
85 (unsigned int)event_ptr->data.note.channel+1);
86 if (event_ptr->data.note.channel + 1 == 10)
88 drum_name = gm_get_drum_name(event_ptr->data.note.note);
90 else
92 drum_name = NULL;
95 note_name = g_note_names[event_ptr->data.note.note % 12];
96 octave = event_ptr->data.note.note / 12 - 1;
99 if (event_ptr->type == SND_SEQ_EVENT_CONTROLLER ||
100 event_ptr->type == SND_SEQ_EVENT_PGMCHANGE ||
101 event_ptr->type == SND_SEQ_EVENT_PITCHBEND)
103 g_string_sprintf(
104 channel_str_ptr,
105 "%u",
106 (unsigned int)event_ptr->data.control.channel+1);
109 msg_str_ptr = g_string_new("unknown event");
111 switch (event_ptr->type)
113 case SND_SEQ_EVENT_SYSTEM:
114 g_string_sprintf(msg_str_ptr, "System event");
115 break;
116 case SND_SEQ_EVENT_RESULT:
117 g_string_sprintf(msg_str_ptr, "Result status event");
118 break;
119 case SND_SEQ_EVENT_NOTE:
120 g_string_sprintf(msg_str_ptr, "Note");
121 break;
122 case SND_SEQ_EVENT_NOTEON:
123 if (event_ptr->data.note.velocity != 0)
125 if (drum_name != NULL)
127 g_string_sprintf(
128 msg_str_ptr,
129 "Drum: %s (%s, octave %d, velocity %u)",
130 drum_name,
131 note_name,
132 octave,
133 event_ptr->data.note.velocity);
135 else
137 g_string_sprintf(
138 msg_str_ptr,
139 "Note on, %s, octave %d, velocity %u",
140 note_name,
141 octave,
142 event_ptr->data.note.velocity);
144 break;
146 case SND_SEQ_EVENT_NOTEOFF:
147 if (drum_name != NULL) /* ignore note off for drums */
148 continue;
150 g_string_sprintf(
151 msg_str_ptr,
152 "Note off, %s, octave %d",
153 note_name,
154 octave);
156 break;
157 case SND_SEQ_EVENT_KEYPRESS:
158 g_string_sprintf(msg_str_ptr, "Key pressure change (aftertouch)");
159 break;
160 case SND_SEQ_EVENT_CONTROLLER:
161 cc_name = NULL;
162 switch (event_ptr->data.control.param)
164 case MIDI_CTL_MSB_BANK:
165 cc_name = "Bank selection";
166 break;
167 case MIDI_CTL_MSB_MODWHEEL:
168 cc_name = "Modulation";
169 break;
170 case MIDI_CTL_MSB_BREATH:
171 cc_name = "Breath";
172 break;
173 case MIDI_CTL_MSB_FOOT:
174 cc_name = "Foot";
175 break;
176 case MIDI_CTL_MSB_PORTAMENTO_TIME:
177 cc_name = "Portamento time";
178 break;
179 case MIDI_CTL_MSB_DATA_ENTRY:
180 cc_name = "Data entry";
181 break;
182 case MIDI_CTL_MSB_MAIN_VOLUME:
183 cc_name = "Main volume";
184 break;
185 case MIDI_CTL_MSB_BALANCE:
186 cc_name = "Balance";
187 break;
188 case MIDI_CTL_MSB_PAN:
189 cc_name = "Panpot";
190 break;
191 case MIDI_CTL_MSB_EXPRESSION:
192 cc_name = "Expression";
193 break;
194 case MIDI_CTL_MSB_EFFECT1:
195 cc_name = "Effect1";
196 break;
197 case MIDI_CTL_MSB_EFFECT2:
198 cc_name = "Effect2";
199 break;
200 case MIDI_CTL_MSB_GENERAL_PURPOSE1:
201 cc_name = "General purpose 1";
202 break;
203 case MIDI_CTL_MSB_GENERAL_PURPOSE2:
204 cc_name = "General purpose 2";
205 break;
206 case MIDI_CTL_MSB_GENERAL_PURPOSE3:
207 cc_name = "General purpose 3";
208 break;
209 case MIDI_CTL_MSB_GENERAL_PURPOSE4:
210 cc_name = "General purpose 4";
211 break;
212 case MIDI_CTL_LSB_BANK:
213 cc_name = "Bank selection";
214 break;
215 case MIDI_CTL_LSB_MODWHEEL:
216 cc_name = "Modulation";
217 break;
218 case MIDI_CTL_LSB_BREATH:
219 cc_name = "Breath";
220 break;
221 case MIDI_CTL_LSB_FOOT:
222 cc_name = "Foot";
223 break;
224 case MIDI_CTL_LSB_PORTAMENTO_TIME:
225 cc_name = "Portamento time";
226 break;
227 case MIDI_CTL_LSB_DATA_ENTRY:
228 cc_name = "Data entry";
229 break;
230 case MIDI_CTL_LSB_MAIN_VOLUME:
231 cc_name = "Main volume";
232 break;
233 case MIDI_CTL_LSB_BALANCE:
234 cc_name = "Balance";
235 break;
236 case MIDI_CTL_LSB_PAN:
237 cc_name = "Panpot";
238 break;
239 case MIDI_CTL_LSB_EXPRESSION:
240 cc_name = "Expression";
241 break;
242 case MIDI_CTL_LSB_EFFECT1:
243 cc_name = "Effect1";
244 break;
245 case MIDI_CTL_LSB_EFFECT2:
246 cc_name = "Effect2";
247 break;
248 case MIDI_CTL_LSB_GENERAL_PURPOSE1:
249 cc_name = "General purpose 1";
250 break;
251 case MIDI_CTL_LSB_GENERAL_PURPOSE2:
252 cc_name = "General purpose 2";
253 break;
254 case MIDI_CTL_LSB_GENERAL_PURPOSE3:
255 cc_name = "General purpose 3";
256 break;
257 case MIDI_CTL_LSB_GENERAL_PURPOSE4:
258 cc_name = "General purpose 4";
259 break;
260 case MIDI_CTL_SUSTAIN:
261 cc_name = "Sustain pedal";
262 break;
263 case MIDI_CTL_PORTAMENTO:
264 cc_name = "Portamento";
265 break;
266 case MIDI_CTL_SOSTENUTO:
267 cc_name = "Sostenuto";
268 break;
269 case MIDI_CTL_SOFT_PEDAL:
270 cc_name = "Soft pedal";
271 break;
272 case MIDI_CTL_LEGATO_FOOTSWITCH:
273 cc_name = "Legato foot switch";
274 break;
275 case MIDI_CTL_HOLD2:
276 cc_name = "Hold2";
277 break;
278 case MIDI_CTL_SC1_SOUND_VARIATION:
279 cc_name = "SC1 Sound Variation";
280 break;
281 case MIDI_CTL_SC2_TIMBRE:
282 cc_name = "SC2 Timbre";
283 break;
284 case MIDI_CTL_SC3_RELEASE_TIME:
285 cc_name = "SC3 Release Time";
286 break;
287 case MIDI_CTL_SC4_ATTACK_TIME:
288 cc_name = "SC4 Attack Time";
289 break;
290 case MIDI_CTL_SC5_BRIGHTNESS:
291 cc_name = "SC5 Brightness";
292 break;
293 case MIDI_CTL_SC6:
294 cc_name = "SC6";
295 break;
296 case MIDI_CTL_SC7:
297 cc_name = "SC7";
298 break;
299 case MIDI_CTL_SC8:
300 cc_name = "SC8";
301 break;
302 case MIDI_CTL_SC9:
303 cc_name = "SC9";
304 break;
305 case MIDI_CTL_SC10:
306 cc_name = "SC10";
307 break;
308 case MIDI_CTL_GENERAL_PURPOSE5:
309 cc_name = "General purpose 5";
310 break;
311 case MIDI_CTL_GENERAL_PURPOSE6:
312 cc_name = "General purpose 6";
313 break;
314 case MIDI_CTL_GENERAL_PURPOSE7:
315 cc_name = "General purpose 7";
316 break;
317 case MIDI_CTL_GENERAL_PURPOSE8:
318 cc_name = "General purpose 8";
319 break;
320 case MIDI_CTL_PORTAMENTO_CONTROL:
321 cc_name = "Portamento control";
322 break;
323 case MIDI_CTL_E1_REVERB_DEPTH:
324 cc_name = "E1 Reverb Depth";
325 break;
326 case MIDI_CTL_E2_TREMOLO_DEPTH:
327 cc_name = "E2 Tremolo Depth";
328 break;
329 case MIDI_CTL_E3_CHORUS_DEPTH:
330 cc_name = "E3 Chorus Depth";
331 break;
332 case MIDI_CTL_E4_DETUNE_DEPTH:
333 cc_name = "E4 Detune Depth";
334 break;
335 case MIDI_CTL_E5_PHASER_DEPTH:
336 cc_name = "E5 Phaser Depth";
337 break;
338 case MIDI_CTL_DATA_INCREMENT:
339 cc_name = "Data Increment";
340 break;
341 case MIDI_CTL_DATA_DECREMENT:
342 cc_name = "Data Decrement";
343 break;
344 case MIDI_CTL_NONREG_PARM_NUM_LSB:
345 cc_name = "Non-registered parameter number";
346 break;
347 case MIDI_CTL_NONREG_PARM_NUM_MSB:
348 cc_name = "Non-registered parameter number";
349 break;
350 case MIDI_CTL_REGIST_PARM_NUM_LSB:
351 cc_name = "Registered parameter number";
352 break;
353 case MIDI_CTL_REGIST_PARM_NUM_MSB:
354 cc_name = "Registered parameter number";
355 break;
356 case MIDI_CTL_ALL_SOUNDS_OFF:
357 cc_name = "All sounds off";
358 break;
359 case MIDI_CTL_RESET_CONTROLLERS:
360 cc_name = "Reset Controllers";
361 break;
362 case MIDI_CTL_LOCAL_CONTROL_SWITCH:
363 cc_name = "Local control switch";
364 break;
365 case MIDI_CTL_ALL_NOTES_OFF:
366 cc_name = "All notes off";
367 break;
368 case MIDI_CTL_OMNI_OFF:
369 cc_name = "Omni off";
370 break;
371 case MIDI_CTL_OMNI_ON:
372 cc_name = "Omni on";
373 break;
374 case MIDI_CTL_MONO1:
375 cc_name = "Mono1";
376 break;
377 case MIDI_CTL_MONO2:
378 cc_name = "Mono2";
379 break;
382 if (cc_name != NULL)
384 g_string_sprintf(
385 msg_str_ptr,
386 "CC %s (%u), value %u",
387 cc_name,
388 (unsigned int)event_ptr->data.control.param,
389 (unsigned int)event_ptr->data.control.value);
391 else
393 g_string_sprintf(
394 msg_str_ptr,
395 "CC %u, value %u",
396 (unsigned int)event_ptr->data.control.param,
397 (unsigned int)event_ptr->data.control.value);
399 break;
400 case SND_SEQ_EVENT_PGMCHANGE:
401 g_string_sprintf(
402 msg_str_ptr,
403 "Program change, %d (%s)",
404 (unsigned int)event_ptr->data.control.value,
405 event_ptr->data.control.value > 127 || event_ptr->data.control.value < 0 ? "???": gm_get_instrument_name(event_ptr->data.control.value));
406 break;
407 case SND_SEQ_EVENT_CHANPRESS:
408 g_string_sprintf(msg_str_ptr, "Channel pressure");
409 break;
410 case SND_SEQ_EVENT_PITCHBEND:
411 g_string_sprintf(
412 msg_str_ptr,
413 "Pitchwheel, %d",
414 (signed int)event_ptr->data.control.value);
415 break;
416 case SND_SEQ_EVENT_CONTROL14:
417 g_string_sprintf(msg_str_ptr, "14 bit controller value");
418 break;
419 case SND_SEQ_EVENT_NONREGPARAM:
420 g_string_sprintf(msg_str_ptr, "NRPN");
421 break;
422 case SND_SEQ_EVENT_REGPARAM:
423 g_string_sprintf(msg_str_ptr, "RPN");
424 break;
425 case SND_SEQ_EVENT_SONGPOS:
426 g_string_sprintf(msg_str_ptr, "Song position");
427 break;
428 case SND_SEQ_EVENT_SONGSEL:
429 g_string_sprintf(msg_str_ptr, "Song select");
430 break;
431 case SND_SEQ_EVENT_QFRAME:
432 g_string_sprintf(msg_str_ptr, "midi time code quarter frame");
433 break;
434 case SND_SEQ_EVENT_TIMESIGN:
435 g_string_sprintf(msg_str_ptr, "SMF Time Signature event");
436 break;
437 case SND_SEQ_EVENT_KEYSIGN:
438 g_string_sprintf(msg_str_ptr, "SMF Key Signature event");
439 break;
440 case SND_SEQ_EVENT_START:
441 g_string_sprintf(msg_str_ptr, "MIDI Real Time Start message");
442 break;
443 case SND_SEQ_EVENT_CONTINUE:
444 g_string_sprintf(msg_str_ptr, "MIDI Real Time Continue message");
445 break;
446 case SND_SEQ_EVENT_STOP:
447 g_string_sprintf(msg_str_ptr, "MIDI Real Time Stop message");
448 break;
449 case SND_SEQ_EVENT_SETPOS_TICK:
450 g_string_sprintf(msg_str_ptr, "Set tick queue position");
451 break;
452 case SND_SEQ_EVENT_SETPOS_TIME:
453 g_string_sprintf(msg_str_ptr, "Set real-time queue position");
454 break;
455 case SND_SEQ_EVENT_TEMPO:
456 g_string_sprintf(msg_str_ptr, "(SMF) Tempo event");
457 break;
458 case SND_SEQ_EVENT_CLOCK:
459 g_string_sprintf(msg_str_ptr, "MIDI Real Time Clock message");
460 break;
461 case SND_SEQ_EVENT_TICK:
462 g_string_sprintf(msg_str_ptr, "MIDI Real Time Tick message");
463 break;
464 case SND_SEQ_EVENT_QUEUE_SKEW:
465 g_string_sprintf(msg_str_ptr, "Queue timer skew");
466 break;
467 case SND_SEQ_EVENT_SYNC_POS:
468 g_string_sprintf(msg_str_ptr, "Sync position changed");
469 break;
470 case SND_SEQ_EVENT_TUNE_REQUEST:
471 g_string_sprintf(msg_str_ptr, "Tune request");
472 break;
473 case SND_SEQ_EVENT_RESET:
474 g_string_sprintf(msg_str_ptr, "Reset");
475 break;
476 case SND_SEQ_EVENT_SENSING:
477 continue; /* disable */
478 g_string_sprintf(msg_str_ptr, "Active sensing");
479 break;
480 case SND_SEQ_EVENT_ECHO:
481 g_string_sprintf(msg_str_ptr, "Echo-back event");
482 break;
483 case SND_SEQ_EVENT_OSS:
484 g_string_sprintf(msg_str_ptr, "OSS emulation raw event");
485 break;
486 case SND_SEQ_EVENT_CLIENT_START:
487 g_string_sprintf(msg_str_ptr, "New client has connected");
488 break;
489 case SND_SEQ_EVENT_CLIENT_EXIT:
490 g_string_sprintf(msg_str_ptr, "Client has left the system");
491 break;
492 case SND_SEQ_EVENT_CLIENT_CHANGE:
493 g_string_sprintf(msg_str_ptr, "Client status/info has changed");
494 break;
495 case SND_SEQ_EVENT_PORT_START:
496 g_string_sprintf(msg_str_ptr, "New port was created");
497 break;
498 case SND_SEQ_EVENT_PORT_EXIT:
499 g_string_sprintf(msg_str_ptr, "Port was deleted from system");
500 break;
501 case SND_SEQ_EVENT_PORT_CHANGE:
502 g_string_sprintf(msg_str_ptr, "Port status/info has changed");
503 break;
504 case SND_SEQ_EVENT_PORT_SUBSCRIBED:
505 g_string_sprintf(msg_str_ptr, "Port connected");
506 break;
507 case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
508 g_string_sprintf(msg_str_ptr, "Port disconnected");
509 break;
510 #if OLD_ALSA
511 case SND_SEQ_EVENT_SAMPLE:
512 g_string_sprintf(msg_str_ptr, "Sample select");
513 break;
514 case SND_SEQ_EVENT_SAMPLE_CLUSTER:
515 g_string_sprintf(msg_str_ptr, "Sample cluster select");
516 break;
517 case SND_SEQ_EVENT_SAMPLE_START:
518 g_string_sprintf(msg_str_ptr, "voice start");
519 break;
520 case SND_SEQ_EVENT_SAMPLE_STOP:
521 g_string_sprintf(msg_str_ptr, "voice stop");
522 break;
523 case SND_SEQ_EVENT_SAMPLE_FREQ:
524 g_string_sprintf(msg_str_ptr, "playback frequency");
525 break;
526 case SND_SEQ_EVENT_SAMPLE_VOLUME:
527 g_string_sprintf(msg_str_ptr, "volume and balance");
528 break;
529 case SND_SEQ_EVENT_SAMPLE_LOOP:
530 g_string_sprintf(msg_str_ptr, "sample loop");
531 break;
532 case SND_SEQ_EVENT_SAMPLE_POSITION:
533 g_string_sprintf(msg_str_ptr, "sample position");
534 break;
535 case SND_SEQ_EVENT_SAMPLE_PRIVATE1:
536 g_string_sprintf(msg_str_ptr, "private (hardware dependent) event");
537 break;
538 #endif
539 case SND_SEQ_EVENT_USR0:
540 g_string_sprintf(msg_str_ptr, "user-defined event");
541 break;
542 case SND_SEQ_EVENT_USR1:
543 g_string_sprintf(msg_str_ptr, "user-defined event");
544 break;
545 case SND_SEQ_EVENT_USR2:
546 g_string_sprintf(msg_str_ptr, "user-defined event");
547 break;
548 case SND_SEQ_EVENT_USR3:
549 g_string_sprintf(msg_str_ptr, "user-defined event");
550 break;
551 case SND_SEQ_EVENT_USR4:
552 g_string_sprintf(msg_str_ptr, "user-defined event");
553 break;
554 case SND_SEQ_EVENT_USR5:
555 g_string_sprintf(msg_str_ptr, "user-defined event");
556 break;
557 case SND_SEQ_EVENT_USR6:
558 g_string_sprintf(msg_str_ptr, "user-defined event");
559 break;
560 case SND_SEQ_EVENT_USR7:
561 g_string_sprintf(msg_str_ptr, "user-defined event");
562 break;
563 case SND_SEQ_EVENT_USR8:
564 g_string_sprintf(msg_str_ptr, "user-defined event");
565 break;
566 case SND_SEQ_EVENT_USR9:
567 g_string_sprintf(msg_str_ptr, "user-defined event");
568 break;
569 #if OLD_ALSA
570 case SND_SEQ_EVENT_INSTR_BEGIN:
571 g_string_sprintf(msg_str_ptr, "begin of instrument management");
572 break;
573 case SND_SEQ_EVENT_INSTR_END:
574 g_string_sprintf(msg_str_ptr, "end of instrument management");
575 break;
576 case SND_SEQ_EVENT_INSTR_INFO:
577 g_string_sprintf(msg_str_ptr, "query instrument interface info");
578 break;
579 case SND_SEQ_EVENT_INSTR_INFO_RESULT:
580 g_string_sprintf(msg_str_ptr, "result of instrument interface info");
581 break;
582 case SND_SEQ_EVENT_INSTR_FINFO:
583 g_string_sprintf(msg_str_ptr, "query instrument format info");
584 break;
585 case SND_SEQ_EVENT_INSTR_FINFO_RESULT:
586 g_string_sprintf(msg_str_ptr, "result of instrument format info");
587 break;
588 case SND_SEQ_EVENT_INSTR_RESET:
589 g_string_sprintf(msg_str_ptr, "reset instrument instrument memory");
590 break;
591 case SND_SEQ_EVENT_INSTR_STATUS:
592 g_string_sprintf(msg_str_ptr, "get instrument interface status");
593 break;
594 case SND_SEQ_EVENT_INSTR_STATUS_RESULT:
595 g_string_sprintf(msg_str_ptr, "result of instrument interface status");
596 break;
597 case SND_SEQ_EVENT_INSTR_PUT:
598 g_string_sprintf(msg_str_ptr, "put an instrument to port");
599 break;
600 case SND_SEQ_EVENT_INSTR_GET:
601 g_string_sprintf(msg_str_ptr, "get an instrument from port");
602 break;
603 case SND_SEQ_EVENT_INSTR_GET_RESULT:
604 g_string_sprintf(msg_str_ptr, "result of instrument query");
605 break;
606 case SND_SEQ_EVENT_INSTR_FREE:
607 g_string_sprintf(msg_str_ptr, "free instrument(s)");
608 break;
609 case SND_SEQ_EVENT_INSTR_LIST:
610 g_string_sprintf(msg_str_ptr, "get instrument list");
611 break;
612 case SND_SEQ_EVENT_INSTR_LIST_RESULT:
613 g_string_sprintf(msg_str_ptr, "result of instrument list");
614 break;
615 case SND_SEQ_EVENT_INSTR_CLUSTER:
616 g_string_sprintf(msg_str_ptr, "set cluster parameters");
617 break;
618 case SND_SEQ_EVENT_INSTR_CLUSTER_GET:
619 g_string_sprintf(msg_str_ptr, "get cluster parameters");
620 break;
621 case SND_SEQ_EVENT_INSTR_CLUSTER_RESULT:
622 g_string_sprintf(msg_str_ptr, "result of cluster parameters");
623 break;
624 case SND_SEQ_EVENT_INSTR_CHANGE:
625 g_string_sprintf(msg_str_ptr, "instrument change");
626 break;
627 #endif
628 case SND_SEQ_EVENT_SYSEX:
629 decode_sysex(
630 (guint8 *)event_ptr->data.ext.ptr,
631 event_ptr->data.ext.len,
632 msg_str_ptr);
633 break;
634 case SND_SEQ_EVENT_BOUNCE:
635 g_string_sprintf(msg_str_ptr, "error event");
636 break;
637 case SND_SEQ_EVENT_USR_VAR0:
638 g_string_sprintf(msg_str_ptr, "reserved for user apps");
639 break;
640 case SND_SEQ_EVENT_USR_VAR1:
641 g_string_sprintf(msg_str_ptr, "reserved for user apps");
642 break;
643 case SND_SEQ_EVENT_USR_VAR2:
644 g_string_sprintf(msg_str_ptr, "reserved for user apps");
645 break;
646 case SND_SEQ_EVENT_USR_VAR3:
647 g_string_sprintf(msg_str_ptr, "reserved for user apps");
648 break;
649 case SND_SEQ_EVENT_USR_VAR4:
650 g_string_sprintf(msg_str_ptr, "reserved for user apps");
651 break;
654 /* get GTK thread lock */
655 gdk_threads_enter();
657 if (g_row_count >= MAX_LIST_SIZE)
659 gtk_tree_model_get_iter_first(
660 GTK_TREE_MODEL(list_store_ptr),
661 &iter);
663 gtk_list_store_remove(
664 list_store_ptr,
665 &iter);
668 /* Append an empty row to the list store. Iter will point to the new row */
669 gtk_list_store_append(list_store_ptr, &iter);
671 gtk_list_store_set(
672 list_store_ptr,
673 &iter,
674 COL_TIME, time_str_ptr->str,
675 COL_CHANNEL, channel_str_ptr->str,
676 COL_MESSAGE, msg_str_ptr->str,
677 -1);
679 gtk_tree_view_scroll_to_cell(
680 GTK_TREE_VIEW(child_ptr),
681 gtk_tree_model_get_path(
682 gtk_tree_view_get_model(GTK_TREE_VIEW(child_ptr)),
683 &iter),
684 NULL,
685 TRUE,
686 0.0,
687 1.0);
689 /* Force update of scroll position. */
690 /* Is it a bug that it does not update automagically ? */
691 gtk_container_check_resize(GTK_CONTAINER(child_ptr));
693 g_row_count++;
695 /* release GTK thread lock */
696 gdk_threads_leave();
698 g_string_free(channel_str_ptr, TRUE);
699 g_string_free(msg_str_ptr, TRUE);
700 g_string_free(time_str_ptr, TRUE);
703 return NULL;
706 gboolean
707 alsa_init(const char * name)
709 int ret;
710 snd_seq_port_info_t * port_info = NULL;
712 ret = snd_seq_open(
713 &g_seq_ptr,
714 "default",
715 SND_SEQ_OPEN_INPUT,
717 if (ret < 0)
719 g_warning("Cannot open sequncer, %s\n", snd_strerror(ret));
720 goto fail;
723 snd_seq_set_client_name(g_seq_ptr, name);
725 #ifdef HAVE_LASH_1_0
726 lash_alsa_client_id(g_lashc, snd_seq_client_id(g_seq_ptr));
727 #endif
729 snd_seq_port_info_alloca(&port_info);
731 snd_seq_port_info_set_capability(
732 port_info,
733 SND_SEQ_PORT_CAP_WRITE |
734 SND_SEQ_PORT_CAP_SUBS_WRITE);
735 snd_seq_port_info_set_type(
736 port_info,
737 SND_SEQ_PORT_TYPE_APPLICATION);
738 snd_seq_port_info_set_midi_channels(port_info, 16);
739 snd_seq_port_info_set_port_specified(port_info, 1);
741 snd_seq_port_info_set_name(port_info, "midi in");
742 snd_seq_port_info_set_port(port_info, 0);
744 ret = snd_seq_create_port(g_seq_ptr, port_info);
745 if (ret < 0)
747 g_warning("Error creating ALSA sequencer port, %s\n", snd_strerror(ret));
748 goto fail_close_seq;
751 /* Start midi thread */
752 ret = pthread_create(&g_alsa_midi_tid, NULL, alsa_midi_thread, NULL);
754 return TRUE;
756 fail_close_seq:
757 ret = snd_seq_close(g_seq_ptr);
758 if (ret < 0)
760 g_warning("Cannot close sequncer, %s\n", snd_strerror(ret));
763 fail:
764 return FALSE;
767 void
768 alsa_uninit()
770 int ret;
772 /* Cancel the thread. Don't know better way.
773 Poll or unblock mechanisms seem to not be
774 available for alsa sequencer */
775 pthread_cancel(g_alsa_midi_tid);
777 /* Wait midi thread to finish */
778 ret = pthread_join(g_alsa_midi_tid, NULL);
780 ret = snd_seq_close(g_seq_ptr);
781 if (ret < 0)
783 g_warning("Cannot close sequncer, %s\n", snd_strerror(ret));