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