1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
5 * gmidimonitor main code.
8 * GNU GENERAL PUBLIC LICENSE version 2
10 *****************************************************************************/
13 #include <alsa/asoundlib.h>
20 GtkWidget
* g_main_window_ptr
;
22 snd_seq_t
* g_seq_ptr
;
24 gboolean g_midi_ignore
= FALSE
;
28 static const char * g_note_names
[12] =
44 static const char * g_gm_instrument_names
[] =
46 "Acoustic Grand Piano", /* 1 */
47 "Bright Acoustic Piano", /* 2 */
48 "Electric Grand Piano", /* 3 */
49 "Honky-tonk Piano", /* 4 */
50 "Electric Piano 1", /* 5 */
51 "Electric Piano 2", /* 6 */
52 "Harpsichord", /* 7 */
55 "Glockenspiel", /* 10 */
57 "Vibraphone", /* 12 */
60 "Tubular Bells", /* 15 */
62 "Drawbar Organ", /* 17 */
63 "Percussive Organ", /* 18 */
64 "Rock Organ", /* 19 */
65 "Church Organ", /* 20 */
66 "Reed Organ", /* 21 */
69 "Tango Accordion", /* 24 */
70 "Acoustic Guitar (nylon)", /* 25 */
71 "Acoustic Guitar (steel)", /* 26 */
72 "Electric Guitar (jazz)", /* 27 */
73 "Electric Guitar (clean)", /* 28 */
74 "Electric Guitar (muted)", /* 29 */
75 "Overdriven Guitar", /* 30 */
76 "Distortion Guitar", /* 31 */
77 "Guitar harmonics", /* 32 */
78 "Acoustic Bass", /* 33 */
79 "Electric Bass (finger)", /* 34 */
80 "Electric Bass (pick)", /* 35 */
81 "Fretless Bass", /* 36 */
82 "Slap Bass 1", /* 37 */
83 "Slap Bass 2", /* 38 */
84 "Synth Bass 1", /* 39 */
85 "Synth Bass 2", /* 40 */
89 "Contrabass", /* 44 */
90 "Tremolo Strings", /* 45 */
91 "Pizzicato Strings", /* 46 */
92 "Orchestral Harp", /* 47 */
94 "String Ensemble 1", /* 49 */
95 "String Ensemble 2", /* 50 */
96 "SynthStrings 1", /* 51 */
97 "SynthStrings 2", /* 52 */
98 "Choir Aahs", /* 53 */
99 "Voice Oohs", /* 54 */
100 "Synth Voice", /* 55 */
101 "Orchestra Hit", /* 56 */
105 "Muted Trumpet", /* 60 */
106 "French Horn", /* 61 */
107 "Brass Section", /* 62 */
108 "SynthBrass 1", /* 63 */
109 "SynthBrass 2", /* 64 */
110 "Soprano Sax", /* 65 */
112 "Tenor Sax", /* 67 */
113 "Baritone Sax", /* 68 */
115 "English Horn", /* 70 */
121 "Pan Flute", /* 76 */
122 "Blown Bottle", /* 77 */
123 "Shakuhachi", /* 78 */
126 "Lead 1 (square)", /* 81 */
127 "Lead 2 (sawtooth)", /* 82 */
128 "Lead 3 (calliope)", /* 83 */
129 "Lead 4 (chiff)", /* 84 */
130 "Lead 5 (charang)", /* 85 */
131 "Lead 6 (voice)", /* 86 */
132 "Lead 7 (fifths)", /* 87 */
133 "Lead 8 (bass + lead)", /* 88 */
134 "Pad 1 (new age)", /* 89 */
135 "Pad 2 (warm)", /* 90 */
136 "Pad 3 (polysynth)", /* 91 */
137 "Pad 4 (choir)", /* 92 */
138 "Pad 5 (bowed)", /* 93 */
139 "Pad 6 (metallic)", /* 94 */
140 "Pad 7 (halo)", /* 95 */
141 "Pad 8 (sweep)", /* 96 */
142 "FX 1 (rain)", /* 97 */
143 "FX 2 (soundtrack)", /* 98 */
144 "FX 3 (crystal)", /* 99 */
145 "FX 4 (atmosphere)", /* 100 */
146 "FX 5 (brightness)", /* 101 */
147 "FX 6 (goblins)", /* 102 */
148 "FX 7 (echoes)", /* 103 */
149 "FX 8 (sci-fi)", /* 104 */
152 "Shamisen", /* 107 */
155 "Bag pipe", /* 110 */
158 "Tinkle Bell", /* 113 */
160 "Steel Drums", /* 115 */
161 "Woodblock", /* 116 */
162 "Taiko Drum", /* 117 */
163 "Melodic Tom", /* 118 */
164 "Synth Drum", /* 119 */
165 "Reverse Cymbal", /* 120 */
166 "Guitar Fret Noise", /* 121 */
167 "Breath Noise", /* 122 */
168 "Seashore", /* 123 */
169 "Bird Tweet", /* 124 */
170 "Telephone Ring", /* 125 */
171 "Helicopter", /* 126 */
172 "Applause", /* 127 */
176 static const char * g_gm_drum_names
[] =
178 "Acoustic Bass Drum", /* 35 */
179 "Bass Drum 1", /* 36 */
180 "Side Stick", /* 37 */
181 "Acoustic Snare", /* 38 */
182 "Hand Clap", /* 39 */
183 "Electric Snare", /* 40 */
184 "Low Floor Tom", /* 41 */
185 "Closed Hi-Hat", /* 42 */
186 "High Floor Tom", /* 43 */
187 "Pedal Hi-Hat", /* 44 */
189 "Open Hi-Hat", /* 46 */
190 "Low-Mid Tom", /* 47 */
191 "Hi-Mid Tom", /* 48 */
192 "Crash Cymbal 1", /* 49 */
194 "Ride Cymbal 1", /* 51 */
195 "Chinese Cymbal", /* 52 */
196 "Ride Bell", /* 53 */
197 "Tambourine", /* 54 */
198 "Splash Cymbal", /* 55 */
200 "Crash Cymbal 2", /* 57 */
201 "Vibraslap", /* 58 */
202 "Ride Cymbal 2", /* 59 */
204 "Low Bongo", /* 61 */
205 "Mute Hi Conga", /* 62 */
206 "Open Hi Conga", /* 63 */
207 "Low Conga", /* 64 */
208 "High Timbale", /* 65 */
209 "Low Timbale", /* 66 */
210 "High Agogo", /* 67 */
211 "Low Agogo", /* 68 */
214 "Short Whistle", /* 71 */
215 "Long Whistle", /* 72 */
216 "Short Guiro", /* 73 */
217 "Long Guiro", /* 74 */
219 "Hi Wood Block", /* 76 */
220 "Low Wood Block", /* 77 */
221 "Mute Cuica", /* 78 */
222 "Open Cuica", /* 79 */
223 "Mute Triangle", /* 80 */
224 "Open Triangle", /* 81 */
235 #define MAX_LIST_SIZE 2000
240 GtkWidget
* child_ptr
;
241 GtkListStore
* list_store_ptr
;
242 GtkTreeViewColumn
* column_ptr
;
243 GtkCellRenderer
* text_renderer_ptr
;
245 g_main_window_ptr
= construct_glade_widget("main_window");
247 child_ptr
= get_glade_widget_child(g_main_window_ptr
, "list");
249 text_renderer_ptr
= gtk_cell_renderer_text_new();
252 G_OBJECT(text_renderer_ptr
),
257 /* column_ptr = gtk_tree_view_column_new_with_attributes( */
259 /* text_renderer_ptr, */
260 /* "text", COL_TIME, */
263 /* gtk_tree_view_append_column( */
264 /* GTK_TREE_VIEW(child_ptr), */
267 column_ptr
= gtk_tree_view_column_new_with_attributes(
273 gtk_tree_view_append_column(
274 GTK_TREE_VIEW(child_ptr
),
277 column_ptr
= gtk_tree_view_column_new_with_attributes(
283 gtk_tree_view_append_column(
284 GTK_TREE_VIEW(child_ptr
),
287 gtk_widget_show_all(g_main_window_ptr
);
289 list_store_ptr
= gtk_list_store_new(
295 gtk_tree_view_set_model(GTK_TREE_VIEW(child_ptr
), GTK_TREE_MODEL(list_store_ptr
));
298 /* stop button toggle */
299 void on_button_stop_toggled(
300 GtkAction
* action_ptr
,
301 GtkWidget
* widget_ptr
)
303 GtkWidget
* child_ptr
;
305 child_ptr
= get_glade_widget_child(widget_ptr
, "button_stop");
307 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(child_ptr
)))
309 g_midi_ignore
= TRUE
;
313 g_midi_ignore
= FALSE
;
317 void on_clear_clicked
318 (GtkButton
*button
, gpointer user_data
)
320 gtk_list_store_clear(
322 gtk_tree_view_get_model(
324 get_glade_widget_child(
330 /* The midi input handling thread */
332 midi_thread(void * context_ptr
)
335 snd_seq_event_t
* event_ptr
;
336 GtkListStore
* list_store_ptr
;
337 GtkWidget
* child_ptr
;
338 GString
* time_str_ptr
;
339 GString
* msg_str_ptr
;
340 GString
* channel_str_ptr
;
341 const char * note_name
;
343 const char * drum_name
;
344 const char * cc_name
;
346 child_ptr
= get_glade_widget_child(g_main_window_ptr
, "list");
348 list_store_ptr
= GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(child_ptr
)));
352 while (snd_seq_event_input(g_seq_ptr
, &event_ptr
) >= 0)
357 time_str_ptr
= g_string_new("");
361 (unsigned int)event_ptr
->time
.time
.tv_sec
,
362 (unsigned int)event_ptr
->time
.time
.tv_nsec
);
363 channel_str_ptr
= g_string_new("");
365 if (event_ptr
->type
== SND_SEQ_EVENT_NOTE
||
366 event_ptr
->type
== SND_SEQ_EVENT_NOTEON
||
367 event_ptr
->type
== SND_SEQ_EVENT_NOTEOFF
||
368 event_ptr
->type
== SND_SEQ_EVENT_KEYPRESS
)
373 (unsigned int)event_ptr
->data
.note
.channel
+1);
374 if (event_ptr
->data
.note
.channel
+1 == 10 &&
375 event_ptr
->data
.note
.note
>= 35 &&
376 event_ptr
->data
.note
.note
< 35 + sizeof(g_gm_drum_names
)/sizeof(g_gm_drum_names
[0]))
378 drum_name
= g_gm_drum_names
[event_ptr
->data
.note
.note
- 35];
385 note_name
= g_note_names
[event_ptr
->data
.note
.note
% 12];
386 octave
= event_ptr
->data
.note
.note
/ 12 - 1;
389 if (event_ptr
->type
== SND_SEQ_EVENT_CONTROLLER
||
390 event_ptr
->type
== SND_SEQ_EVENT_PGMCHANGE
||
391 event_ptr
->type
== SND_SEQ_EVENT_PITCHBEND
)
396 (unsigned int)event_ptr
->data
.control
.channel
+1);
399 msg_str_ptr
= g_string_new("unknown event");
401 switch (event_ptr
->type
)
403 case SND_SEQ_EVENT_SYSTEM
:
404 g_string_sprintf(msg_str_ptr
, "System event");
406 case SND_SEQ_EVENT_RESULT
:
407 g_string_sprintf(msg_str_ptr
, "Result status event");
409 case SND_SEQ_EVENT_NOTE
:
410 g_string_sprintf(msg_str_ptr
, "Note");
412 case SND_SEQ_EVENT_NOTEON
:
413 if (event_ptr
->data
.note
.velocity
!= 0)
415 if (drum_name
!= NULL
)
419 "Drum: %s (%s, octave %d, velocity %u)",
423 event_ptr
->data
.note
.velocity
);
429 "Note on , %s, octave %d, velocity %u",
432 event_ptr
->data
.note
.velocity
);
436 case SND_SEQ_EVENT_NOTEOFF
:
437 if (drum_name
!= NULL
) /* ignore note off for drums */
442 "Note off, %s, octave %d",
447 case SND_SEQ_EVENT_KEYPRESS
:
448 g_string_sprintf(msg_str_ptr
, "Key pressure change (aftertouch)");
450 case SND_SEQ_EVENT_CONTROLLER
:
452 switch (event_ptr
->data
.control
.param
)
454 case MIDI_CTL_MSB_BANK
:
455 cc_name
= "Bank selection";
457 case MIDI_CTL_MSB_MODWHEEL
:
458 cc_name
= "Modulation";
460 case MIDI_CTL_MSB_BREATH
:
463 case MIDI_CTL_MSB_FOOT
:
466 case MIDI_CTL_MSB_PORTAMENTO_TIME
:
467 cc_name
= "Portamento time";
469 case MIDI_CTL_MSB_DATA_ENTRY
:
470 cc_name
= "Data entry";
472 case MIDI_CTL_MSB_MAIN_VOLUME
:
473 cc_name
= "Main volume";
475 case MIDI_CTL_MSB_BALANCE
:
478 case MIDI_CTL_MSB_PAN
:
481 case MIDI_CTL_MSB_EXPRESSION
:
482 cc_name
= "Expression";
484 case MIDI_CTL_MSB_EFFECT1
:
487 case MIDI_CTL_MSB_EFFECT2
:
490 case MIDI_CTL_MSB_GENERAL_PURPOSE1
:
491 cc_name
= "General purpose 1";
493 case MIDI_CTL_MSB_GENERAL_PURPOSE2
:
494 cc_name
= "General purpose 2";
496 case MIDI_CTL_MSB_GENERAL_PURPOSE3
:
497 cc_name
= "General purpose 3";
499 case MIDI_CTL_MSB_GENERAL_PURPOSE4
:
500 cc_name
= "General purpose 4";
502 case MIDI_CTL_LSB_BANK
:
503 cc_name
= "Bank selection";
505 case MIDI_CTL_LSB_MODWHEEL
:
506 cc_name
= "Modulation";
508 case MIDI_CTL_LSB_BREATH
:
511 case MIDI_CTL_LSB_FOOT
:
514 case MIDI_CTL_LSB_PORTAMENTO_TIME
:
515 cc_name
= "Portamento time";
517 case MIDI_CTL_LSB_DATA_ENTRY
:
518 cc_name
= "Data entry";
520 case MIDI_CTL_LSB_MAIN_VOLUME
:
521 cc_name
= "Main volume";
523 case MIDI_CTL_LSB_BALANCE
:
526 case MIDI_CTL_LSB_PAN
:
529 case MIDI_CTL_LSB_EXPRESSION
:
530 cc_name
= "Expression";
532 case MIDI_CTL_LSB_EFFECT1
:
535 case MIDI_CTL_LSB_EFFECT2
:
538 case MIDI_CTL_LSB_GENERAL_PURPOSE1
:
539 cc_name
= "General purpose 1";
541 case MIDI_CTL_LSB_GENERAL_PURPOSE2
:
542 cc_name
= "General purpose 2";
544 case MIDI_CTL_LSB_GENERAL_PURPOSE3
:
545 cc_name
= "General purpose 3";
547 case MIDI_CTL_LSB_GENERAL_PURPOSE4
:
548 cc_name
= "General purpose 4";
550 case MIDI_CTL_SUSTAIN
:
551 cc_name
= "Sustain pedal";
553 case MIDI_CTL_PORTAMENTO
:
554 cc_name
= "Portamento";
556 case MIDI_CTL_SOSTENUTO
:
557 cc_name
= "Sostenuto";
559 case MIDI_CTL_SOFT_PEDAL
:
560 cc_name
= "Soft pedal";
562 case MIDI_CTL_LEGATO_FOOTSWITCH
:
563 cc_name
= "Legato foot switch";
568 case MIDI_CTL_SC1_SOUND_VARIATION
:
569 cc_name
= "SC1 Sound Variation";
571 case MIDI_CTL_SC2_TIMBRE
:
572 cc_name
= "SC2 Timbre";
574 case MIDI_CTL_SC3_RELEASE_TIME
:
575 cc_name
= "SC3 Release Time";
577 case MIDI_CTL_SC4_ATTACK_TIME
:
578 cc_name
= "SC4 Attack Time";
580 case MIDI_CTL_SC5_BRIGHTNESS
:
581 cc_name
= "SC5 Brightness";
598 case MIDI_CTL_GENERAL_PURPOSE5
:
599 cc_name
= "General purpose 5";
601 case MIDI_CTL_GENERAL_PURPOSE6
:
602 cc_name
= "General purpose 6";
604 case MIDI_CTL_GENERAL_PURPOSE7
:
605 cc_name
= "General purpose 7";
607 case MIDI_CTL_GENERAL_PURPOSE8
:
608 cc_name
= "General purpose 8";
610 case MIDI_CTL_PORTAMENTO_CONTROL
:
611 cc_name
= "Portamento control";
613 case MIDI_CTL_E1_REVERB_DEPTH
:
614 cc_name
= "E1 Reverb Depth";
616 case MIDI_CTL_E2_TREMOLO_DEPTH
:
617 cc_name
= "E2 Tremolo Depth";
619 case MIDI_CTL_E3_CHORUS_DEPTH
:
620 cc_name
= "E3 Chorus Depth";
622 case MIDI_CTL_E4_DETUNE_DEPTH
:
623 cc_name
= "E4 Detune Depth";
625 case MIDI_CTL_E5_PHASER_DEPTH
:
626 cc_name
= "E5 Phaser Depth";
628 case MIDI_CTL_DATA_INCREMENT
:
629 cc_name
= "Data Increment";
631 case MIDI_CTL_DATA_DECREMENT
:
632 cc_name
= "Data Decrement";
634 case MIDI_CTL_NONREG_PARM_NUM_LSB
:
635 cc_name
= "Non-registered parameter number";
637 case MIDI_CTL_NONREG_PARM_NUM_MSB
:
638 cc_name
= "Non-registered parameter number";
640 case MIDI_CTL_REGIST_PARM_NUM_LSB
:
641 cc_name
= "Registered parameter number";
643 case MIDI_CTL_REGIST_PARM_NUM_MSB
:
644 cc_name
= "Registered parameter number";
646 case MIDI_CTL_ALL_SOUNDS_OFF
:
647 cc_name
= "All sounds off";
649 case MIDI_CTL_RESET_CONTROLLERS
:
650 cc_name
= "Reset Controllers";
652 case MIDI_CTL_LOCAL_CONTROL_SWITCH
:
653 cc_name
= "Local control switch";
655 case MIDI_CTL_ALL_NOTES_OFF
:
656 cc_name
= "All notes off";
658 case MIDI_CTL_OMNI_OFF
:
659 cc_name
= "Omni off";
661 case MIDI_CTL_OMNI_ON
:
676 "CC %s (%u), value %u",
678 (unsigned int)event_ptr
->data
.control
.param
,
679 (unsigned int)event_ptr
->data
.control
.value
);
686 (unsigned int)event_ptr
->data
.control
.param
,
687 (unsigned int)event_ptr
->data
.control
.value
);
690 case SND_SEQ_EVENT_PGMCHANGE
:
693 "Program change, %d (%s)",
694 (unsigned int)event_ptr
->data
.control
.value
,
695 event_ptr
->data
.control
.value
>= sizeof(g_gm_instrument_names
)/sizeof(g_gm_instrument_names
[0])?
697 g_gm_instrument_names
[event_ptr
->data
.control
.value
]);
699 case SND_SEQ_EVENT_CHANPRESS
:
700 g_string_sprintf(msg_str_ptr
, "Channel pressure");
702 case SND_SEQ_EVENT_PITCHBEND
:
706 (unsigned int)event_ptr
->data
.control
.value
);
708 case SND_SEQ_EVENT_CONTROL14
:
709 g_string_sprintf(msg_str_ptr
, "14 bit controller value");
711 case SND_SEQ_EVENT_NONREGPARAM
:
712 g_string_sprintf(msg_str_ptr
, "NRPN");
714 case SND_SEQ_EVENT_REGPARAM
:
715 g_string_sprintf(msg_str_ptr
, "RPN");
717 case SND_SEQ_EVENT_SONGPOS
:
718 g_string_sprintf(msg_str_ptr
, "Song position");
720 case SND_SEQ_EVENT_SONGSEL
:
721 g_string_sprintf(msg_str_ptr
, "Song select");
723 case SND_SEQ_EVENT_QFRAME
:
724 g_string_sprintf(msg_str_ptr
, "midi time code quarter frame");
726 case SND_SEQ_EVENT_TIMESIGN
:
727 g_string_sprintf(msg_str_ptr
, "SMF Time Signature event");
729 case SND_SEQ_EVENT_KEYSIGN
:
730 g_string_sprintf(msg_str_ptr
, "SMF Key Signature event");
732 case SND_SEQ_EVENT_START
:
733 g_string_sprintf(msg_str_ptr
, "MIDI Real Time Start message");
735 case SND_SEQ_EVENT_CONTINUE
:
736 g_string_sprintf(msg_str_ptr
, "MIDI Real Time Continue message");
738 case SND_SEQ_EVENT_STOP
:
739 g_string_sprintf(msg_str_ptr
, "MIDI Real Time Stop message");
741 case SND_SEQ_EVENT_SETPOS_TICK
:
742 g_string_sprintf(msg_str_ptr
, "Set tick queue position");
744 case SND_SEQ_EVENT_SETPOS_TIME
:
745 g_string_sprintf(msg_str_ptr
, "Set real-time queue position");
747 case SND_SEQ_EVENT_TEMPO
:
748 g_string_sprintf(msg_str_ptr
, "(SMF) Tempo event");
750 case SND_SEQ_EVENT_CLOCK
:
751 g_string_sprintf(msg_str_ptr
, "MIDI Real Time Clock message");
753 case SND_SEQ_EVENT_TICK
:
754 g_string_sprintf(msg_str_ptr
, "MIDI Real Time Tick message");
756 case SND_SEQ_EVENT_QUEUE_SKEW
:
757 g_string_sprintf(msg_str_ptr
, "Queue timer skew");
759 case SND_SEQ_EVENT_SYNC_POS
:
760 g_string_sprintf(msg_str_ptr
, "Sync position changed");
762 case SND_SEQ_EVENT_TUNE_REQUEST
:
763 g_string_sprintf(msg_str_ptr
, "Tune request");
765 case SND_SEQ_EVENT_RESET
:
766 g_string_sprintf(msg_str_ptr
, "Reset");
768 case SND_SEQ_EVENT_SENSING
:
769 continue; /* disable */
770 g_string_sprintf(msg_str_ptr
, "Active sensing");
772 case SND_SEQ_EVENT_ECHO
:
773 g_string_sprintf(msg_str_ptr
, "Echo-back event");
775 case SND_SEQ_EVENT_OSS
:
776 g_string_sprintf(msg_str_ptr
, "OSS emulation raw event");
778 case SND_SEQ_EVENT_CLIENT_START
:
779 g_string_sprintf(msg_str_ptr
, "New client has connected");
781 case SND_SEQ_EVENT_CLIENT_EXIT
:
782 g_string_sprintf(msg_str_ptr
, "Client has left the system");
784 case SND_SEQ_EVENT_CLIENT_CHANGE
:
785 g_string_sprintf(msg_str_ptr
, "Client status/info has changed");
787 case SND_SEQ_EVENT_PORT_START
:
788 g_string_sprintf(msg_str_ptr
, "New port was created");
790 case SND_SEQ_EVENT_PORT_EXIT
:
791 g_string_sprintf(msg_str_ptr
, "Port was deleted from system");
793 case SND_SEQ_EVENT_PORT_CHANGE
:
794 g_string_sprintf(msg_str_ptr
, "Port status/info has changed");
796 case SND_SEQ_EVENT_PORT_SUBSCRIBED
:
797 g_string_sprintf(msg_str_ptr
, "Port connected");
799 case SND_SEQ_EVENT_PORT_UNSUBSCRIBED
:
800 g_string_sprintf(msg_str_ptr
, "Port disconnected");
802 case SND_SEQ_EVENT_SAMPLE
:
803 g_string_sprintf(msg_str_ptr
, "Sample select");
805 case SND_SEQ_EVENT_SAMPLE_CLUSTER
:
806 g_string_sprintf(msg_str_ptr
, "Sample cluster select");
808 case SND_SEQ_EVENT_SAMPLE_START
:
809 g_string_sprintf(msg_str_ptr
, "voice start");
811 case SND_SEQ_EVENT_SAMPLE_STOP
:
812 g_string_sprintf(msg_str_ptr
, "voice stop");
814 case SND_SEQ_EVENT_SAMPLE_FREQ
:
815 g_string_sprintf(msg_str_ptr
, "playback frequency");
817 case SND_SEQ_EVENT_SAMPLE_VOLUME
:
818 g_string_sprintf(msg_str_ptr
, "volume and balance");
820 case SND_SEQ_EVENT_SAMPLE_LOOP
:
821 g_string_sprintf(msg_str_ptr
, "sample loop");
823 case SND_SEQ_EVENT_SAMPLE_POSITION
:
824 g_string_sprintf(msg_str_ptr
, "sample position");
826 case SND_SEQ_EVENT_SAMPLE_PRIVATE1
:
827 g_string_sprintf(msg_str_ptr
, "private (hardware dependent) event");
829 case SND_SEQ_EVENT_USR0
:
830 g_string_sprintf(msg_str_ptr
, "user-defined event");
832 case SND_SEQ_EVENT_USR1
:
833 g_string_sprintf(msg_str_ptr
, "user-defined event");
835 case SND_SEQ_EVENT_USR2
:
836 g_string_sprintf(msg_str_ptr
, "user-defined event");
838 case SND_SEQ_EVENT_USR3
:
839 g_string_sprintf(msg_str_ptr
, "user-defined event");
841 case SND_SEQ_EVENT_USR4
:
842 g_string_sprintf(msg_str_ptr
, "user-defined event");
844 case SND_SEQ_EVENT_USR5
:
845 g_string_sprintf(msg_str_ptr
, "user-defined event");
847 case SND_SEQ_EVENT_USR6
:
848 g_string_sprintf(msg_str_ptr
, "user-defined event");
850 case SND_SEQ_EVENT_USR7
:
851 g_string_sprintf(msg_str_ptr
, "user-defined event");
853 case SND_SEQ_EVENT_USR8
:
854 g_string_sprintf(msg_str_ptr
, "user-defined event");
856 case SND_SEQ_EVENT_USR9
:
857 g_string_sprintf(msg_str_ptr
, "user-defined event");
859 case SND_SEQ_EVENT_INSTR_BEGIN
:
860 g_string_sprintf(msg_str_ptr
, "begin of instrument management");
862 case SND_SEQ_EVENT_INSTR_END
:
863 g_string_sprintf(msg_str_ptr
, "end of instrument management");
865 case SND_SEQ_EVENT_INSTR_INFO
:
866 g_string_sprintf(msg_str_ptr
, "query instrument interface info");
868 case SND_SEQ_EVENT_INSTR_INFO_RESULT
:
869 g_string_sprintf(msg_str_ptr
, "result of instrument interface info");
871 case SND_SEQ_EVENT_INSTR_FINFO
:
872 g_string_sprintf(msg_str_ptr
, "query instrument format info");
874 case SND_SEQ_EVENT_INSTR_FINFO_RESULT
:
875 g_string_sprintf(msg_str_ptr
, "result of instrument format info");
877 case SND_SEQ_EVENT_INSTR_RESET
:
878 g_string_sprintf(msg_str_ptr
, "reset instrument instrument memory");
880 case SND_SEQ_EVENT_INSTR_STATUS
:
881 g_string_sprintf(msg_str_ptr
, "get instrument interface status");
883 case SND_SEQ_EVENT_INSTR_STATUS_RESULT
:
884 g_string_sprintf(msg_str_ptr
, "result of instrument interface status");
886 case SND_SEQ_EVENT_INSTR_PUT
:
887 g_string_sprintf(msg_str_ptr
, "put an instrument to port");
889 case SND_SEQ_EVENT_INSTR_GET
:
890 g_string_sprintf(msg_str_ptr
, "get an instrument from port");
892 case SND_SEQ_EVENT_INSTR_GET_RESULT
:
893 g_string_sprintf(msg_str_ptr
, "result of instrument query");
895 case SND_SEQ_EVENT_INSTR_FREE
:
896 g_string_sprintf(msg_str_ptr
, "free instrument(s)");
898 case SND_SEQ_EVENT_INSTR_LIST
:
899 g_string_sprintf(msg_str_ptr
, "get instrument list");
901 case SND_SEQ_EVENT_INSTR_LIST_RESULT
:
902 g_string_sprintf(msg_str_ptr
, "result of instrument list");
904 case SND_SEQ_EVENT_INSTR_CLUSTER
:
905 g_string_sprintf(msg_str_ptr
, "set cluster parameters");
907 case SND_SEQ_EVENT_INSTR_CLUSTER_GET
:
908 g_string_sprintf(msg_str_ptr
, "get cluster parameters");
910 case SND_SEQ_EVENT_INSTR_CLUSTER_RESULT
:
911 g_string_sprintf(msg_str_ptr
, "result of cluster parameters");
913 case SND_SEQ_EVENT_INSTR_CHANGE
:
914 g_string_sprintf(msg_str_ptr
, "instrument change");
916 case SND_SEQ_EVENT_SYSEX
:
917 g_string_sprintf(msg_str_ptr
, "system exclusive data (variable length)");
919 case SND_SEQ_EVENT_BOUNCE
:
920 g_string_sprintf(msg_str_ptr
, "error event");
922 case SND_SEQ_EVENT_USR_VAR0
:
923 g_string_sprintf(msg_str_ptr
, "reserved for user apps");
925 case SND_SEQ_EVENT_USR_VAR1
:
926 g_string_sprintf(msg_str_ptr
, "reserved for user apps");
928 case SND_SEQ_EVENT_USR_VAR2
:
929 g_string_sprintf(msg_str_ptr
, "reserved for user apps");
931 case SND_SEQ_EVENT_USR_VAR3
:
932 g_string_sprintf(msg_str_ptr
, "reserved for user apps");
934 case SND_SEQ_EVENT_USR_VAR4
:
935 g_string_sprintf(msg_str_ptr
, "reserved for user apps");
939 /* get GTK thread lock */
942 if (g_row_count
>= MAX_LIST_SIZE
)
944 gtk_tree_model_get_iter_first(
945 GTK_TREE_MODEL(list_store_ptr
),
948 gtk_list_store_remove(
953 /* Append an empty row to the list store. Iter will point to the new row */
954 gtk_list_store_append(list_store_ptr
, &iter
);
959 COL_TIME
, time_str_ptr
->str
,
960 COL_CHANNEL
, channel_str_ptr
->str
,
961 COL_MESSAGE
, msg_str_ptr
->str
,
964 g_string_free(channel_str_ptr
, TRUE
);
965 g_string_free(msg_str_ptr
, TRUE
);
967 gtk_tree_view_scroll_to_cell(
968 GTK_TREE_VIEW(child_ptr
),
969 gtk_tree_model_get_path(
970 gtk_tree_view_get_model(GTK_TREE_VIEW(child_ptr
)),
977 /* Force update of scroll position. */
978 /* Is it a bug that it does not update automagically ? */
979 gtk_container_check_resize(GTK_CONTAINER(child_ptr
));
981 /* release GTK thread lock */
991 main(int argc
, char *argv
[])
994 snd_seq_port_info_t
* port_info
= NULL
;
1000 gdk_threads_enter();
1002 gtk_init(&argc
, &argv
);
1006 /* interface creation */
1007 create_mainwindow();
1009 /* initialisation */
1017 g_warning("Cannot open sequncer, %s\n", snd_strerror(ret
));
1021 snd_seq_set_client_name(g_seq_ptr
, "MIDI monitor");
1023 snd_seq_port_info_alloca(&port_info
);
1025 snd_seq_port_info_set_capability(
1027 SND_SEQ_PORT_CAP_WRITE
|
1028 SND_SEQ_PORT_CAP_SUBS_WRITE
);
1029 snd_seq_port_info_set_type(
1031 SND_SEQ_PORT_TYPE_APPLICATION
);
1032 snd_seq_port_info_set_midi_channels(port_info
, 16);
1033 snd_seq_port_info_set_port_specified(port_info
, 1);
1035 snd_seq_port_info_set_name(port_info
, "midi in");
1036 snd_seq_port_info_set_port(port_info
, 0);
1038 ret
= snd_seq_create_port(g_seq_ptr
, port_info
);
1041 g_warning("Error creating ALSA sequencer port, %s\n", snd_strerror(ret
));
1045 /* Start midi thread */
1046 ret
= pthread_create(&midi_tid
, NULL
, midi_thread
, NULL
);
1051 /* Cancel the thread. Don't know better way.
1052 Poll or unblock mechanisms seem to not be
1053 available for alsa sequencer */
1054 pthread_cancel(midi_tid
);
1056 /* Wait midi thread to finish */
1057 ret
= pthread_join(midi_tid
, NULL
);
1059 gdk_threads_leave();
1062 ret
= snd_seq_close(g_seq_ptr
);
1065 g_warning("Cannot close sequncer, %s\n", snd_strerror(ret
));