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