1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
5 * gmidimonitor main code.
8 * GNU GENERAL PUBLIC LICENSE version 2
10 *****************************************************************************/
15 #include <alsa/asoundlib.h>
20 #include <lash/lash.h>
26 GtkWidget
* g_main_window_ptr
;
28 snd_seq_t
* g_seq_ptr
;
30 gboolean g_midi_ignore
= FALSE
;
35 lash_client_t
* g_lashc
;
38 static const char * g_note_names
[12] =
54 static const char * g_gm_instrument_names
[] =
56 "Acoustic Grand Piano", /* 1 */
57 "Bright Acoustic Piano", /* 2 */
58 "Electric Grand Piano", /* 3 */
59 "Honky-tonk Piano", /* 4 */
60 "Electric Piano 1", /* 5 */
61 "Electric Piano 2", /* 6 */
62 "Harpsichord", /* 7 */
65 "Glockenspiel", /* 10 */
67 "Vibraphone", /* 12 */
70 "Tubular Bells", /* 15 */
72 "Drawbar Organ", /* 17 */
73 "Percussive Organ", /* 18 */
74 "Rock Organ", /* 19 */
75 "Church Organ", /* 20 */
76 "Reed Organ", /* 21 */
79 "Tango Accordion", /* 24 */
80 "Acoustic Guitar (nylon)", /* 25 */
81 "Acoustic Guitar (steel)", /* 26 */
82 "Electric Guitar (jazz)", /* 27 */
83 "Electric Guitar (clean)", /* 28 */
84 "Electric Guitar (muted)", /* 29 */
85 "Overdriven Guitar", /* 30 */
86 "Distortion Guitar", /* 31 */
87 "Guitar harmonics", /* 32 */
88 "Acoustic Bass", /* 33 */
89 "Electric Bass (finger)", /* 34 */
90 "Electric Bass (pick)", /* 35 */
91 "Fretless Bass", /* 36 */
92 "Slap Bass 1", /* 37 */
93 "Slap Bass 2", /* 38 */
94 "Synth Bass 1", /* 39 */
95 "Synth Bass 2", /* 40 */
99 "Contrabass", /* 44 */
100 "Tremolo Strings", /* 45 */
101 "Pizzicato Strings", /* 46 */
102 "Orchestral Harp", /* 47 */
104 "String Ensemble 1", /* 49 */
105 "String Ensemble 2", /* 50 */
106 "SynthStrings 1", /* 51 */
107 "SynthStrings 2", /* 52 */
108 "Choir Aahs", /* 53 */
109 "Voice Oohs", /* 54 */
110 "Synth Voice", /* 55 */
111 "Orchestra Hit", /* 56 */
115 "Muted Trumpet", /* 60 */
116 "French Horn", /* 61 */
117 "Brass Section", /* 62 */
118 "SynthBrass 1", /* 63 */
119 "SynthBrass 2", /* 64 */
120 "Soprano Sax", /* 65 */
122 "Tenor Sax", /* 67 */
123 "Baritone Sax", /* 68 */
125 "English Horn", /* 70 */
131 "Pan Flute", /* 76 */
132 "Blown Bottle", /* 77 */
133 "Shakuhachi", /* 78 */
136 "Lead 1 (square)", /* 81 */
137 "Lead 2 (sawtooth)", /* 82 */
138 "Lead 3 (calliope)", /* 83 */
139 "Lead 4 (chiff)", /* 84 */
140 "Lead 5 (charang)", /* 85 */
141 "Lead 6 (voice)", /* 86 */
142 "Lead 7 (fifths)", /* 87 */
143 "Lead 8 (bass + lead)", /* 88 */
144 "Pad 1 (new age)", /* 89 */
145 "Pad 2 (warm)", /* 90 */
146 "Pad 3 (polysynth)", /* 91 */
147 "Pad 4 (choir)", /* 92 */
148 "Pad 5 (bowed)", /* 93 */
149 "Pad 6 (metallic)", /* 94 */
150 "Pad 7 (halo)", /* 95 */
151 "Pad 8 (sweep)", /* 96 */
152 "FX 1 (rain)", /* 97 */
153 "FX 2 (soundtrack)", /* 98 */
154 "FX 3 (crystal)", /* 99 */
155 "FX 4 (atmosphere)", /* 100 */
156 "FX 5 (brightness)", /* 101 */
157 "FX 6 (goblins)", /* 102 */
158 "FX 7 (echoes)", /* 103 */
159 "FX 8 (sci-fi)", /* 104 */
162 "Shamisen", /* 107 */
165 "Bag pipe", /* 110 */
168 "Tinkle Bell", /* 113 */
170 "Steel Drums", /* 115 */
171 "Woodblock", /* 116 */
172 "Taiko Drum", /* 117 */
173 "Melodic Tom", /* 118 */
174 "Synth Drum", /* 119 */
175 "Reverse Cymbal", /* 120 */
176 "Guitar Fret Noise", /* 121 */
177 "Breath Noise", /* 122 */
178 "Seashore", /* 123 */
179 "Bird Tweet", /* 124 */
180 "Telephone Ring", /* 125 */
181 "Helicopter", /* 126 */
182 "Applause", /* 127 */
186 static const char * g_gm_drum_names
[] =
188 "Acoustic Bass Drum", /* 35 */
189 "Bass Drum 1", /* 36 */
190 "Side Stick", /* 37 */
191 "Acoustic Snare", /* 38 */
192 "Hand Clap", /* 39 */
193 "Electric Snare", /* 40 */
194 "Low Floor Tom", /* 41 */
195 "Closed Hi-Hat", /* 42 */
196 "High Floor Tom", /* 43 */
197 "Pedal Hi-Hat", /* 44 */
199 "Open Hi-Hat", /* 46 */
200 "Low-Mid Tom", /* 47 */
201 "Hi-Mid Tom", /* 48 */
202 "Crash Cymbal 1", /* 49 */
204 "Ride Cymbal 1", /* 51 */
205 "Chinese Cymbal", /* 52 */
206 "Ride Bell", /* 53 */
207 "Tambourine", /* 54 */
208 "Splash Cymbal", /* 55 */
210 "Crash Cymbal 2", /* 57 */
211 "Vibraslap", /* 58 */
212 "Ride Cymbal 2", /* 59 */
214 "Low Bongo", /* 61 */
215 "Mute Hi Conga", /* 62 */
216 "Open Hi Conga", /* 63 */
217 "Low Conga", /* 64 */
218 "High Timbale", /* 65 */
219 "Low Timbale", /* 66 */
220 "High Agogo", /* 67 */
221 "Low Agogo", /* 68 */
224 "Short Whistle", /* 71 */
225 "Long Whistle", /* 72 */
226 "Short Guiro", /* 73 */
227 "Long Guiro", /* 74 */
229 "Hi Wood Block", /* 76 */
230 "Low Wood Block", /* 77 */
231 "Mute Cuica", /* 78 */
232 "Open Cuica", /* 79 */
233 "Mute Triangle", /* 80 */
234 "Open Triangle", /* 81 */
245 #define MAX_LIST_SIZE 2000
250 GtkWidget
* child_ptr
;
251 GtkListStore
* list_store_ptr
;
252 GtkTreeViewColumn
* column_ptr
;
253 GtkCellRenderer
* text_renderer_ptr
;
255 g_main_window_ptr
= construct_glade_widget("main_window");
257 child_ptr
= get_glade_widget_child(g_main_window_ptr
, "list");
259 text_renderer_ptr
= gtk_cell_renderer_text_new();
262 G_OBJECT(text_renderer_ptr
),
267 /* column_ptr = gtk_tree_view_column_new_with_attributes( */
269 /* text_renderer_ptr, */
270 /* "text", COL_TIME, */
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 column_ptr
= gtk_tree_view_column_new_with_attributes(
293 gtk_tree_view_append_column(
294 GTK_TREE_VIEW(child_ptr
),
297 gtk_widget_show_all(g_main_window_ptr
);
299 list_store_ptr
= gtk_list_store_new(
305 gtk_tree_view_set_model(GTK_TREE_VIEW(child_ptr
), GTK_TREE_MODEL(list_store_ptr
));
308 /* stop button toggle */
309 void on_button_stop_toggled(
310 GtkAction
* action_ptr
,
311 GtkWidget
* widget_ptr
)
313 GtkWidget
* child_ptr
;
315 child_ptr
= get_glade_widget_child(widget_ptr
, "button_stop");
317 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(child_ptr
)))
319 g_midi_ignore
= TRUE
;
323 g_midi_ignore
= FALSE
;
327 void on_clear_clicked
328 (GtkButton
*button
, gpointer user_data
)
330 gtk_list_store_clear(
332 gtk_tree_view_get_model(
334 get_glade_widget_child(
340 /* The midi input handling thread */
342 midi_thread(void * context_ptr
)
345 snd_seq_event_t
* event_ptr
;
346 GtkListStore
* list_store_ptr
;
347 GtkWidget
* child_ptr
;
348 GString
* time_str_ptr
;
349 GString
* msg_str_ptr
;
350 GString
* channel_str_ptr
;
351 const char * note_name
;
353 const char * drum_name
;
354 const char * cc_name
;
356 const char * mmc_command_name
;
358 child_ptr
= get_glade_widget_child(g_main_window_ptr
, "list");
360 list_store_ptr
= GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(child_ptr
)));
364 while (snd_seq_event_input(g_seq_ptr
, &event_ptr
) >= 0)
369 time_str_ptr
= g_string_new("");
373 (unsigned int)event_ptr
->time
.time
.tv_sec
,
374 (unsigned int)event_ptr
->time
.time
.tv_nsec
);
375 channel_str_ptr
= g_string_new("");
377 /* Workaround for compiler warnings... */
382 if (event_ptr
->type
== SND_SEQ_EVENT_NOTE
||
383 event_ptr
->type
== SND_SEQ_EVENT_NOTEON
||
384 event_ptr
->type
== SND_SEQ_EVENT_NOTEOFF
||
385 event_ptr
->type
== SND_SEQ_EVENT_KEYPRESS
)
390 (unsigned int)event_ptr
->data
.note
.channel
+1);
391 if (event_ptr
->data
.note
.channel
+1 == 10 &&
392 event_ptr
->data
.note
.note
>= 35 &&
393 event_ptr
->data
.note
.note
< 35 + sizeof(g_gm_drum_names
)/sizeof(g_gm_drum_names
[0]))
395 drum_name
= g_gm_drum_names
[event_ptr
->data
.note
.note
- 35];
402 note_name
= g_note_names
[event_ptr
->data
.note
.note
% 12];
403 octave
= event_ptr
->data
.note
.note
/ 12 - 1;
406 if (event_ptr
->type
== SND_SEQ_EVENT_CONTROLLER
||
407 event_ptr
->type
== SND_SEQ_EVENT_PGMCHANGE
||
408 event_ptr
->type
== SND_SEQ_EVENT_PITCHBEND
)
413 (unsigned int)event_ptr
->data
.control
.channel
+1);
416 msg_str_ptr
= g_string_new("unknown event");
418 switch (event_ptr
->type
)
420 case SND_SEQ_EVENT_SYSTEM
:
421 g_string_sprintf(msg_str_ptr
, "System event");
423 case SND_SEQ_EVENT_RESULT
:
424 g_string_sprintf(msg_str_ptr
, "Result status event");
426 case SND_SEQ_EVENT_NOTE
:
427 g_string_sprintf(msg_str_ptr
, "Note");
429 case SND_SEQ_EVENT_NOTEON
:
430 if (event_ptr
->data
.note
.velocity
!= 0)
432 if (drum_name
!= NULL
)
436 "Drum: %s (%s, octave %d, velocity %u)",
440 event_ptr
->data
.note
.velocity
);
446 "Note on , %s, octave %d, velocity %u",
449 event_ptr
->data
.note
.velocity
);
453 case SND_SEQ_EVENT_NOTEOFF
:
454 if (drum_name
!= NULL
) /* ignore note off for drums */
459 "Note off, %s, octave %d",
464 case SND_SEQ_EVENT_KEYPRESS
:
465 g_string_sprintf(msg_str_ptr
, "Key pressure change (aftertouch)");
467 case SND_SEQ_EVENT_CONTROLLER
:
469 switch (event_ptr
->data
.control
.param
)
471 case MIDI_CTL_MSB_BANK
:
472 cc_name
= "Bank selection";
474 case MIDI_CTL_MSB_MODWHEEL
:
475 cc_name
= "Modulation";
477 case MIDI_CTL_MSB_BREATH
:
480 case MIDI_CTL_MSB_FOOT
:
483 case MIDI_CTL_MSB_PORTAMENTO_TIME
:
484 cc_name
= "Portamento time";
486 case MIDI_CTL_MSB_DATA_ENTRY
:
487 cc_name
= "Data entry";
489 case MIDI_CTL_MSB_MAIN_VOLUME
:
490 cc_name
= "Main volume";
492 case MIDI_CTL_MSB_BALANCE
:
495 case MIDI_CTL_MSB_PAN
:
498 case MIDI_CTL_MSB_EXPRESSION
:
499 cc_name
= "Expression";
501 case MIDI_CTL_MSB_EFFECT1
:
504 case MIDI_CTL_MSB_EFFECT2
:
507 case MIDI_CTL_MSB_GENERAL_PURPOSE1
:
508 cc_name
= "General purpose 1";
510 case MIDI_CTL_MSB_GENERAL_PURPOSE2
:
511 cc_name
= "General purpose 2";
513 case MIDI_CTL_MSB_GENERAL_PURPOSE3
:
514 cc_name
= "General purpose 3";
516 case MIDI_CTL_MSB_GENERAL_PURPOSE4
:
517 cc_name
= "General purpose 4";
519 case MIDI_CTL_LSB_BANK
:
520 cc_name
= "Bank selection";
522 case MIDI_CTL_LSB_MODWHEEL
:
523 cc_name
= "Modulation";
525 case MIDI_CTL_LSB_BREATH
:
528 case MIDI_CTL_LSB_FOOT
:
531 case MIDI_CTL_LSB_PORTAMENTO_TIME
:
532 cc_name
= "Portamento time";
534 case MIDI_CTL_LSB_DATA_ENTRY
:
535 cc_name
= "Data entry";
537 case MIDI_CTL_LSB_MAIN_VOLUME
:
538 cc_name
= "Main volume";
540 case MIDI_CTL_LSB_BALANCE
:
543 case MIDI_CTL_LSB_PAN
:
546 case MIDI_CTL_LSB_EXPRESSION
:
547 cc_name
= "Expression";
549 case MIDI_CTL_LSB_EFFECT1
:
552 case MIDI_CTL_LSB_EFFECT2
:
555 case MIDI_CTL_LSB_GENERAL_PURPOSE1
:
556 cc_name
= "General purpose 1";
558 case MIDI_CTL_LSB_GENERAL_PURPOSE2
:
559 cc_name
= "General purpose 2";
561 case MIDI_CTL_LSB_GENERAL_PURPOSE3
:
562 cc_name
= "General purpose 3";
564 case MIDI_CTL_LSB_GENERAL_PURPOSE4
:
565 cc_name
= "General purpose 4";
567 case MIDI_CTL_SUSTAIN
:
568 cc_name
= "Sustain pedal";
570 case MIDI_CTL_PORTAMENTO
:
571 cc_name
= "Portamento";
573 case MIDI_CTL_SOSTENUTO
:
574 cc_name
= "Sostenuto";
576 case MIDI_CTL_SOFT_PEDAL
:
577 cc_name
= "Soft pedal";
579 case MIDI_CTL_LEGATO_FOOTSWITCH
:
580 cc_name
= "Legato foot switch";
585 case MIDI_CTL_SC1_SOUND_VARIATION
:
586 cc_name
= "SC1 Sound Variation";
588 case MIDI_CTL_SC2_TIMBRE
:
589 cc_name
= "SC2 Timbre";
591 case MIDI_CTL_SC3_RELEASE_TIME
:
592 cc_name
= "SC3 Release Time";
594 case MIDI_CTL_SC4_ATTACK_TIME
:
595 cc_name
= "SC4 Attack Time";
597 case MIDI_CTL_SC5_BRIGHTNESS
:
598 cc_name
= "SC5 Brightness";
615 case MIDI_CTL_GENERAL_PURPOSE5
:
616 cc_name
= "General purpose 5";
618 case MIDI_CTL_GENERAL_PURPOSE6
:
619 cc_name
= "General purpose 6";
621 case MIDI_CTL_GENERAL_PURPOSE7
:
622 cc_name
= "General purpose 7";
624 case MIDI_CTL_GENERAL_PURPOSE8
:
625 cc_name
= "General purpose 8";
627 case MIDI_CTL_PORTAMENTO_CONTROL
:
628 cc_name
= "Portamento control";
630 case MIDI_CTL_E1_REVERB_DEPTH
:
631 cc_name
= "E1 Reverb Depth";
633 case MIDI_CTL_E2_TREMOLO_DEPTH
:
634 cc_name
= "E2 Tremolo Depth";
636 case MIDI_CTL_E3_CHORUS_DEPTH
:
637 cc_name
= "E3 Chorus Depth";
639 case MIDI_CTL_E4_DETUNE_DEPTH
:
640 cc_name
= "E4 Detune Depth";
642 case MIDI_CTL_E5_PHASER_DEPTH
:
643 cc_name
= "E5 Phaser Depth";
645 case MIDI_CTL_DATA_INCREMENT
:
646 cc_name
= "Data Increment";
648 case MIDI_CTL_DATA_DECREMENT
:
649 cc_name
= "Data Decrement";
651 case MIDI_CTL_NONREG_PARM_NUM_LSB
:
652 cc_name
= "Non-registered parameter number";
654 case MIDI_CTL_NONREG_PARM_NUM_MSB
:
655 cc_name
= "Non-registered parameter number";
657 case MIDI_CTL_REGIST_PARM_NUM_LSB
:
658 cc_name
= "Registered parameter number";
660 case MIDI_CTL_REGIST_PARM_NUM_MSB
:
661 cc_name
= "Registered parameter number";
663 case MIDI_CTL_ALL_SOUNDS_OFF
:
664 cc_name
= "All sounds off";
666 case MIDI_CTL_RESET_CONTROLLERS
:
667 cc_name
= "Reset Controllers";
669 case MIDI_CTL_LOCAL_CONTROL_SWITCH
:
670 cc_name
= "Local control switch";
672 case MIDI_CTL_ALL_NOTES_OFF
:
673 cc_name
= "All notes off";
675 case MIDI_CTL_OMNI_OFF
:
676 cc_name
= "Omni off";
678 case MIDI_CTL_OMNI_ON
:
693 "CC %s (%u), value %u",
695 (unsigned int)event_ptr
->data
.control
.param
,
696 (unsigned int)event_ptr
->data
.control
.value
);
703 (unsigned int)event_ptr
->data
.control
.param
,
704 (unsigned int)event_ptr
->data
.control
.value
);
707 case SND_SEQ_EVENT_PGMCHANGE
:
710 "Program change, %d (%s)",
711 (unsigned int)event_ptr
->data
.control
.value
,
712 event_ptr
->data
.control
.value
>= sizeof(g_gm_instrument_names
)/sizeof(g_gm_instrument_names
[0])?
714 g_gm_instrument_names
[event_ptr
->data
.control
.value
]);
716 case SND_SEQ_EVENT_CHANPRESS
:
717 g_string_sprintf(msg_str_ptr
, "Channel pressure");
719 case SND_SEQ_EVENT_PITCHBEND
:
723 (unsigned int)event_ptr
->data
.control
.value
);
725 case SND_SEQ_EVENT_CONTROL14
:
726 g_string_sprintf(msg_str_ptr
, "14 bit controller value");
728 case SND_SEQ_EVENT_NONREGPARAM
:
729 g_string_sprintf(msg_str_ptr
, "NRPN");
731 case SND_SEQ_EVENT_REGPARAM
:
732 g_string_sprintf(msg_str_ptr
, "RPN");
734 case SND_SEQ_EVENT_SONGPOS
:
735 g_string_sprintf(msg_str_ptr
, "Song position");
737 case SND_SEQ_EVENT_SONGSEL
:
738 g_string_sprintf(msg_str_ptr
, "Song select");
740 case SND_SEQ_EVENT_QFRAME
:
741 g_string_sprintf(msg_str_ptr
, "midi time code quarter frame");
743 case SND_SEQ_EVENT_TIMESIGN
:
744 g_string_sprintf(msg_str_ptr
, "SMF Time Signature event");
746 case SND_SEQ_EVENT_KEYSIGN
:
747 g_string_sprintf(msg_str_ptr
, "SMF Key Signature event");
749 case SND_SEQ_EVENT_START
:
750 g_string_sprintf(msg_str_ptr
, "MIDI Real Time Start message");
752 case SND_SEQ_EVENT_CONTINUE
:
753 g_string_sprintf(msg_str_ptr
, "MIDI Real Time Continue message");
755 case SND_SEQ_EVENT_STOP
:
756 g_string_sprintf(msg_str_ptr
, "MIDI Real Time Stop message");
758 case SND_SEQ_EVENT_SETPOS_TICK
:
759 g_string_sprintf(msg_str_ptr
, "Set tick queue position");
761 case SND_SEQ_EVENT_SETPOS_TIME
:
762 g_string_sprintf(msg_str_ptr
, "Set real-time queue position");
764 case SND_SEQ_EVENT_TEMPO
:
765 g_string_sprintf(msg_str_ptr
, "(SMF) Tempo event");
767 case SND_SEQ_EVENT_CLOCK
:
768 g_string_sprintf(msg_str_ptr
, "MIDI Real Time Clock message");
770 case SND_SEQ_EVENT_TICK
:
771 g_string_sprintf(msg_str_ptr
, "MIDI Real Time Tick message");
773 case SND_SEQ_EVENT_QUEUE_SKEW
:
774 g_string_sprintf(msg_str_ptr
, "Queue timer skew");
776 case SND_SEQ_EVENT_SYNC_POS
:
777 g_string_sprintf(msg_str_ptr
, "Sync position changed");
779 case SND_SEQ_EVENT_TUNE_REQUEST
:
780 g_string_sprintf(msg_str_ptr
, "Tune request");
782 case SND_SEQ_EVENT_RESET
:
783 g_string_sprintf(msg_str_ptr
, "Reset");
785 case SND_SEQ_EVENT_SENSING
:
786 continue; /* disable */
787 g_string_sprintf(msg_str_ptr
, "Active sensing");
789 case SND_SEQ_EVENT_ECHO
:
790 g_string_sprintf(msg_str_ptr
, "Echo-back event");
792 case SND_SEQ_EVENT_OSS
:
793 g_string_sprintf(msg_str_ptr
, "OSS emulation raw event");
795 case SND_SEQ_EVENT_CLIENT_START
:
796 g_string_sprintf(msg_str_ptr
, "New client has connected");
798 case SND_SEQ_EVENT_CLIENT_EXIT
:
799 g_string_sprintf(msg_str_ptr
, "Client has left the system");
801 case SND_SEQ_EVENT_CLIENT_CHANGE
:
802 g_string_sprintf(msg_str_ptr
, "Client status/info has changed");
804 case SND_SEQ_EVENT_PORT_START
:
805 g_string_sprintf(msg_str_ptr
, "New port was created");
807 case SND_SEQ_EVENT_PORT_EXIT
:
808 g_string_sprintf(msg_str_ptr
, "Port was deleted from system");
810 case SND_SEQ_EVENT_PORT_CHANGE
:
811 g_string_sprintf(msg_str_ptr
, "Port status/info has changed");
813 case SND_SEQ_EVENT_PORT_SUBSCRIBED
:
814 g_string_sprintf(msg_str_ptr
, "Port connected");
816 case SND_SEQ_EVENT_PORT_UNSUBSCRIBED
:
817 g_string_sprintf(msg_str_ptr
, "Port disconnected");
819 case SND_SEQ_EVENT_SAMPLE
:
820 g_string_sprintf(msg_str_ptr
, "Sample select");
822 case SND_SEQ_EVENT_SAMPLE_CLUSTER
:
823 g_string_sprintf(msg_str_ptr
, "Sample cluster select");
825 case SND_SEQ_EVENT_SAMPLE_START
:
826 g_string_sprintf(msg_str_ptr
, "voice start");
828 case SND_SEQ_EVENT_SAMPLE_STOP
:
829 g_string_sprintf(msg_str_ptr
, "voice stop");
831 case SND_SEQ_EVENT_SAMPLE_FREQ
:
832 g_string_sprintf(msg_str_ptr
, "playback frequency");
834 case SND_SEQ_EVENT_SAMPLE_VOLUME
:
835 g_string_sprintf(msg_str_ptr
, "volume and balance");
837 case SND_SEQ_EVENT_SAMPLE_LOOP
:
838 g_string_sprintf(msg_str_ptr
, "sample loop");
840 case SND_SEQ_EVENT_SAMPLE_POSITION
:
841 g_string_sprintf(msg_str_ptr
, "sample position");
843 case SND_SEQ_EVENT_SAMPLE_PRIVATE1
:
844 g_string_sprintf(msg_str_ptr
, "private (hardware dependent) event");
846 case SND_SEQ_EVENT_USR0
:
847 g_string_sprintf(msg_str_ptr
, "user-defined event");
849 case SND_SEQ_EVENT_USR1
:
850 g_string_sprintf(msg_str_ptr
, "user-defined event");
852 case SND_SEQ_EVENT_USR2
:
853 g_string_sprintf(msg_str_ptr
, "user-defined event");
855 case SND_SEQ_EVENT_USR3
:
856 g_string_sprintf(msg_str_ptr
, "user-defined event");
858 case SND_SEQ_EVENT_USR4
:
859 g_string_sprintf(msg_str_ptr
, "user-defined event");
861 case SND_SEQ_EVENT_USR5
:
862 g_string_sprintf(msg_str_ptr
, "user-defined event");
864 case SND_SEQ_EVENT_USR6
:
865 g_string_sprintf(msg_str_ptr
, "user-defined event");
867 case SND_SEQ_EVENT_USR7
:
868 g_string_sprintf(msg_str_ptr
, "user-defined event");
870 case SND_SEQ_EVENT_USR8
:
871 g_string_sprintf(msg_str_ptr
, "user-defined event");
873 case SND_SEQ_EVENT_USR9
:
874 g_string_sprintf(msg_str_ptr
, "user-defined event");
876 case SND_SEQ_EVENT_INSTR_BEGIN
:
877 g_string_sprintf(msg_str_ptr
, "begin of instrument management");
879 case SND_SEQ_EVENT_INSTR_END
:
880 g_string_sprintf(msg_str_ptr
, "end of instrument management");
882 case SND_SEQ_EVENT_INSTR_INFO
:
883 g_string_sprintf(msg_str_ptr
, "query instrument interface info");
885 case SND_SEQ_EVENT_INSTR_INFO_RESULT
:
886 g_string_sprintf(msg_str_ptr
, "result of instrument interface info");
888 case SND_SEQ_EVENT_INSTR_FINFO
:
889 g_string_sprintf(msg_str_ptr
, "query instrument format info");
891 case SND_SEQ_EVENT_INSTR_FINFO_RESULT
:
892 g_string_sprintf(msg_str_ptr
, "result of instrument format info");
894 case SND_SEQ_EVENT_INSTR_RESET
:
895 g_string_sprintf(msg_str_ptr
, "reset instrument instrument memory");
897 case SND_SEQ_EVENT_INSTR_STATUS
:
898 g_string_sprintf(msg_str_ptr
, "get instrument interface status");
900 case SND_SEQ_EVENT_INSTR_STATUS_RESULT
:
901 g_string_sprintf(msg_str_ptr
, "result of instrument interface status");
903 case SND_SEQ_EVENT_INSTR_PUT
:
904 g_string_sprintf(msg_str_ptr
, "put an instrument to port");
906 case SND_SEQ_EVENT_INSTR_GET
:
907 g_string_sprintf(msg_str_ptr
, "get an instrument from port");
909 case SND_SEQ_EVENT_INSTR_GET_RESULT
:
910 g_string_sprintf(msg_str_ptr
, "result of instrument query");
912 case SND_SEQ_EVENT_INSTR_FREE
:
913 g_string_sprintf(msg_str_ptr
, "free instrument(s)");
915 case SND_SEQ_EVENT_INSTR_LIST
:
916 g_string_sprintf(msg_str_ptr
, "get instrument list");
918 case SND_SEQ_EVENT_INSTR_LIST_RESULT
:
919 g_string_sprintf(msg_str_ptr
, "result of instrument list");
921 case SND_SEQ_EVENT_INSTR_CLUSTER
:
922 g_string_sprintf(msg_str_ptr
, "set cluster parameters");
924 case SND_SEQ_EVENT_INSTR_CLUSTER_GET
:
925 g_string_sprintf(msg_str_ptr
, "get cluster parameters");
927 case SND_SEQ_EVENT_INSTR_CLUSTER_RESULT
:
928 g_string_sprintf(msg_str_ptr
, "result of cluster parameters");
930 case SND_SEQ_EVENT_INSTR_CHANGE
:
931 g_string_sprintf(msg_str_ptr
, "instrument change");
933 case SND_SEQ_EVENT_SYSEX
:
934 /* General MMC decoding, as seen at http://www.borg.com/~jglatt/tech/mmc.htm and
935 extended from "Advanced User Guide for MK-449C MIDI keyboard" info */
936 if (event_ptr
->data
.ext
.len
== 6 &&
937 ((guint8
*)event_ptr
->data
.ext
.ptr
)[0] == 0xF0 &&
938 ((guint8
*)event_ptr
->data
.ext
.ptr
)[1] == 0x7F &&
939 ((guint8
*)event_ptr
->data
.ext
.ptr
)[3] == 0x06 &&
940 ((guint8
*)event_ptr
->data
.ext
.ptr
)[5] == 0xF7)
942 switch (((guint8
*)event_ptr
->data
.ext
.ptr
)[4])
945 mmc_command_name
= "Stop";
948 mmc_command_name
= "Play";
951 mmc_command_name
= "Deferred Play";
954 mmc_command_name
= "Fast Forward";
957 mmc_command_name
= "Rewind";
960 mmc_command_name
= "Record Strobe (Punch In)";
963 mmc_command_name
= "Record Exit (Punch Out)";
966 mmc_command_name
= "Record Pause";
969 mmc_command_name
= "Pause";
972 mmc_command_name
= "Eject";
975 mmc_command_name
= "Chase";
978 mmc_command_name
= "Command Error Reset";
981 mmc_command_name
= "Reset";
991 if (((guint8
*)event_ptr
->data
.ext
.ptr
)[2] == 127)
999 g_string_append_printf(
1002 (unsigned int)(((guint8
*)event_ptr
->data
.ext
.ptr
)[2]));
1005 /* The goto MMC message, as seen at http://www.borg.com/~jglatt/tech/mmc.htm*/
1006 else if (event_ptr
->data
.ext
.len
== 13 &&
1007 ((guint8
*)event_ptr
->data
.ext
.ptr
)[0] == 0xF0 &&
1008 ((guint8
*)event_ptr
->data
.ext
.ptr
)[1] == 0x7F &&
1009 ((guint8
*)event_ptr
->data
.ext
.ptr
)[3] == 0x06 &&
1010 ((guint8
*)event_ptr
->data
.ext
.ptr
)[4] == 0x44 &&
1011 ((guint8
*)event_ptr
->data
.ext
.ptr
)[5] == 0x06 &&
1012 ((guint8
*)event_ptr
->data
.ext
.ptr
)[6] == 0x01 &&
1013 ((guint8
*)event_ptr
->data
.ext
.ptr
)[12] == 0xF7)
1017 "MMC goto %u:%u:%u/%u:%u",
1018 (unsigned int)(((guint8
*)event_ptr
->data
.ext
.ptr
)[7] & 0x1F), /* fps encoding */
1019 (unsigned int)(((guint8
*)event_ptr
->data
.ext
.ptr
)[8]),
1020 (unsigned int)(((guint8
*)event_ptr
->data
.ext
.ptr
)[9]),
1021 (unsigned int)(((guint8
*)event_ptr
->data
.ext
.ptr
)[10] & 0x1F), /* no fps > 32, but bit 5 looks
1022 used for something */
1023 (unsigned int)(((guint8
*)event_ptr
->data
.ext
.ptr
)[11]));
1025 switch (((guint8
*)event_ptr
->data
.ext
.ptr
)[7] & 0x60)
1049 if (((guint8
*)event_ptr
->data
.ext
.ptr
)[2] == 127)
1053 ", for all devices");
1057 g_string_append_printf(
1060 (unsigned int)(((guint8
*)event_ptr
->data
.ext
.ptr
)[2]));
1068 "SYSEX with size %u:",
1069 (unsigned int)event_ptr
->data
.ext
.len
);
1070 for (i
= 0 ; i
< event_ptr
->data
.ext
.len
; i
++)
1072 g_string_append_printf(
1075 (unsigned int)(((guint8
*)event_ptr
->data
.ext
.ptr
)[i
]));
1079 case SND_SEQ_EVENT_BOUNCE
:
1080 g_string_sprintf(msg_str_ptr
, "error event");
1082 case SND_SEQ_EVENT_USR_VAR0
:
1083 g_string_sprintf(msg_str_ptr
, "reserved for user apps");
1085 case SND_SEQ_EVENT_USR_VAR1
:
1086 g_string_sprintf(msg_str_ptr
, "reserved for user apps");
1088 case SND_SEQ_EVENT_USR_VAR2
:
1089 g_string_sprintf(msg_str_ptr
, "reserved for user apps");
1091 case SND_SEQ_EVENT_USR_VAR3
:
1092 g_string_sprintf(msg_str_ptr
, "reserved for user apps");
1094 case SND_SEQ_EVENT_USR_VAR4
:
1095 g_string_sprintf(msg_str_ptr
, "reserved for user apps");
1099 /* get GTK thread lock */
1100 gdk_threads_enter();
1102 if (g_row_count
>= MAX_LIST_SIZE
)
1104 gtk_tree_model_get_iter_first(
1105 GTK_TREE_MODEL(list_store_ptr
),
1108 gtk_list_store_remove(
1113 /* Append an empty row to the list store. Iter will point to the new row */
1114 gtk_list_store_append(list_store_ptr
, &iter
);
1119 COL_TIME
, time_str_ptr
->str
,
1120 COL_CHANNEL
, channel_str_ptr
->str
,
1121 COL_MESSAGE
, msg_str_ptr
->str
,
1124 g_string_free(channel_str_ptr
, TRUE
);
1125 g_string_free(msg_str_ptr
, TRUE
);
1127 gtk_tree_view_scroll_to_cell(
1128 GTK_TREE_VIEW(child_ptr
),
1129 gtk_tree_model_get_path(
1130 gtk_tree_view_get_model(GTK_TREE_VIEW(child_ptr
)),
1137 /* Force update of scroll position. */
1138 /* Is it a bug that it does not update automagically ? */
1139 gtk_container_check_resize(GTK_CONTAINER(child_ptr
));
1141 /* release GTK thread lock */
1142 gdk_threads_leave();
1153 process_lash_event(lash_event_t
* event_ptr
)
1155 enum LASH_Event_Type type
;
1158 type
= lash_event_get_type(event_ptr
);
1159 str
= lash_event_get_string(event_ptr
);
1164 g_warning("LASH_Quit received.\n");
1168 case LASH_Save_File
:
1169 case LASH_Restore_File
:
1170 case LASH_Save_Data_Set
:
1172 g_warning("LASH Event. Type = %u, string = \"%s\"\n",
1174 (str
== NULL
)?"":str
);
1179 process_lash_config(lash_config_t
* config_ptr
)
1185 key
= lash_config_get_key(config_ptr
);
1186 data
= lash_config_get_value(config_ptr
);
1187 data_size
= lash_config_get_value_size(config_ptr
);
1189 g_warning("LASH Config. Key = \"%s\"\n", key
);
1192 /* process lash events callback */
1194 process_lash_events(gpointer data
)
1196 lash_event_t
* event_ptr
;
1197 lash_config_t
* config_ptr
;
1199 /* Process events */
1200 while ((event_ptr
= lash_get_event(g_lashc
)) != NULL
)
1202 process_lash_event(event_ptr
);
1203 lash_event_destroy(event_ptr
);
1206 /* Process configs */
1207 while ((config_ptr
= lash_get_config(g_lashc
)) != NULL
)
1209 process_lash_config(config_ptr
);
1210 lash_config_destroy(config_ptr
);
1216 #endif /* #ifdef HAVE_LASH */
1219 main(int argc
, char *argv
[])
1222 snd_seq_port_info_t
* port_info
= NULL
;
1225 lash_event_t
* lash_event_ptr
;
1227 GString
* seq_client_name_str_ptr
;
1230 g_thread_init(NULL
);
1232 gdk_threads_enter();
1234 gtk_init(&argc
, &argv
);
1239 g_lashc
= lash_init(
1240 lash_extract_args(&argc
, &argv
),
1243 LASH_PROTOCOL_VERSION
);
1245 if (g_lashc
== NULL
)
1247 g_warning("Failed to connect to LASH. Session management will not occur.\n");
1251 lash_event_ptr
= lash_event_new_with_type(LASH_Client_Name
);
1252 lash_event_set_string(lash_event_ptr
, "GMIDImonitor");
1253 lash_send_event(g_lashc
, lash_event_ptr
);
1254 g_timeout_add(250, process_lash_events
, NULL
);
1258 /* interface creation */
1259 create_mainwindow();
1261 /* initialisation */
1269 g_warning("Cannot open sequncer, %s\n", snd_strerror(ret
));
1273 seq_client_name_str_ptr
= g_string_new("");
1274 g_string_sprintf(seq_client_name_str_ptr
, "MIDI monitor (%u)", (unsigned int)getpid());
1275 snd_seq_set_client_name(g_seq_ptr
, seq_client_name_str_ptr
->str
);
1278 lash_alsa_client_id(g_lashc
, snd_seq_client_id(g_seq_ptr
));
1281 snd_seq_port_info_alloca(&port_info
);
1283 snd_seq_port_info_set_capability(
1285 SND_SEQ_PORT_CAP_WRITE
|
1286 SND_SEQ_PORT_CAP_SUBS_WRITE
);
1287 snd_seq_port_info_set_type(
1289 SND_SEQ_PORT_TYPE_APPLICATION
);
1290 snd_seq_port_info_set_midi_channels(port_info
, 16);
1291 snd_seq_port_info_set_port_specified(port_info
, 1);
1293 snd_seq_port_info_set_name(port_info
, "midi in");
1294 snd_seq_port_info_set_port(port_info
, 0);
1296 ret
= snd_seq_create_port(g_seq_ptr
, port_info
);
1299 g_warning("Error creating ALSA sequencer port, %s\n", snd_strerror(ret
));
1303 /* Start midi thread */
1304 ret
= pthread_create(&midi_tid
, NULL
, midi_thread
, NULL
);
1309 /* Cancel the thread. Don't know better way.
1310 Poll or unblock mechanisms seem to not be
1311 available for alsa sequencer */
1312 pthread_cancel(midi_tid
);
1314 /* Wait midi thread to finish */
1315 ret
= pthread_join(midi_tid
, NULL
);
1317 gdk_threads_leave();
1320 ret
= snd_seq_close(g_seq_ptr
);
1323 g_warning("Cannot close sequncer, %s\n", snd_strerror(ret
));