1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
4 * This file is part of gmidimonitor
6 * Copyright (C) 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 <jack/jack.h>
24 #include <jack/midiport.h>
34 #include "memory_atomic.h"
35 //#define LOG_LEVEL LOG_LEVEL_DEBUG
41 #include "jack_compat.h"
43 extern GtkBuilder
* g_builder
;
45 jack_client_t
* g_jack_client
;
46 jack_port_t
* g_jack_input_port
;
47 rtsafe_memory_handle g_memory
;
49 struct jack_midi_event_buffer
51 struct list_head siblings
;
53 unsigned char buffer
[0];
56 pthread_mutex_t g_jack_midi_mutex
;
57 //pthread_cond_t g_jack_midi_cond;
59 /* transfer from jack process callback to main thread */
60 /* new events are being put at list begining */
61 struct list_head g_jack_midi_events_pending
;
63 /* temporary storage used by jack process callback in case g_jack_midi_events_pending is locked by main thread */
64 /* new events are being put at list begining */
65 struct list_head g_jack_midi_events_pending_rt
;
67 pthread_t g_jack_midi_tid
; /* jack_midi_thread id */
69 gboolean g_jack_midi_thread_exit
; /* whther jack_midi_thread shoud exit */
72 jack_process(jack_nframes_t nframes
, void * context
)
76 jack_midi_event_t in_event
;
77 jack_nframes_t event_count
;
80 struct jack_midi_event_buffer
* event_buffer
;
82 port_buf
= jack_port_get_buffer(g_jack_input_port
, nframes
);
83 event_count
= jack_midi_get_event_count(port_buf
);
84 jack_transport_query(g_jack_client
, &pos
);
86 for (i
= 0 ; i
< event_count
; i
++)
88 jack_midi_event_get(&in_event
, port_buf
, i
);
90 LOG_DEBUG("midi event with size %u received. (jack_process)", (unsigned int)in_event
.size
);
92 /* allocate memory for buffer copy */
93 event_buffer
= rtsafe_memory_allocate(g_memory
, sizeof(struct jack_midi_event_buffer
) + in_event
.size
);
94 if (event_buffer
== NULL
)
96 LOG_ERROR("Ignored midi event with size %u because memory allocation failed.", (unsigned int)in_event
.size
);
100 /* copy buffer data */
101 memcpy(event_buffer
->buffer
, in_event
.buffer
, in_event
.size
);
102 event_buffer
->buffer_size
= in_event
.size
;
104 /* Add event buffer to g_jack_midi_events_pending_rt list */
105 list_add(&event_buffer
->siblings
, &g_jack_midi_events_pending_rt
);
108 ret
= pthread_mutex_trylock(&g_jack_midi_mutex
);
111 /* We are lucky and we got the lock */
114 /* Move pending events in g_jack_midi_events_pending_rt to begining of g_jack_midi_events_pending */
115 list_splice_init(&g_jack_midi_events_pending_rt
, &g_jack_midi_events_pending
);
117 /* wakeup jack_midi_thread */
118 //ret = pthread_cond_broadcast(&g_jack_midi_cond);
119 //LOG_DEBUG("pthread_cond_broadcast() result is %d", ret);
120 ret
= pthread_mutex_unlock(&g_jack_midi_mutex
);
121 //LOG_DEBUG("pthread_mutex_unlock() result is %d", ret);
125 /* We are not lucky, jack_midi_thread has locked the mutex */
126 LOG_DEBUG("Not lucky (%d)", ret
);
136 GString
* msg_str_ptr
,
137 GString
* channel_str_ptr
)
140 unsigned int channel
;
142 unsigned int velocity
;
143 const char * note_name
;
145 unsigned int controller
;
147 const char * controller_name
;
149 const char * drum_name
;
151 if (buffer_size
== 1 && buffer
[0] == 0xFE)
153 g_string_sprintf(msg_str_ptr
, "Active sensing");
154 return FALSE
; /* disable */
157 if (buffer_size
== 1 && buffer
[0] == 0xF8)
159 g_string_sprintf(msg_str_ptr
, "Timing Clock");
160 return FALSE
; /* disable */
163 if (buffer_size
== 3 && (buffer
[0] >> 4) == 0x08)
165 channel
= (buffer
[0] & 0x0F) + 1; /* 1 .. 16 */
166 assert(channel
>= 1 && channel
<= 16);
170 return FALSE
; /* ignore note off for drums */
179 velocity
= buffer
[2];
185 note_name
= g_note_names
[note
% 12];
186 octave
= note
/ 12 - 1;
188 g_string_sprintf(channel_str_ptr
, "%u", channel
);
192 "Note off, %s, octave %d, velocity %u",
200 if (buffer_size
== 3 && (buffer
[0] >> 4) == 0x09)
202 channel
= (buffer
[0] & 0x0F) + 1; /* 1 .. 16 */
203 assert(channel
>= 1 && channel
<= 16);
211 velocity
= buffer
[2];
217 note_name
= g_note_names
[note
% 12];
218 octave
= note
/ 12 - 1;
220 g_string_sprintf(channel_str_ptr
, "%u", channel
);
224 drum_name
= gm_get_drum_name(note
);
231 if (drum_name
!= NULL
)
235 return FALSE
; /* ignore note off for drums */
240 "Drum: %s (%s, octave %d, velocity %u)",
250 "Note on, %s, octave %d, velocity %u",
259 if (buffer_size
== 3 && (buffer
[0] >> 4) == 0x0A)
261 channel
= (buffer
[0] & 0x0F) + 1; /* 1 .. 16 */
262 assert(channel
>= 1 && channel
<= 16);
270 velocity
= buffer
[2];
276 note_name
= g_note_names
[note
% 12];
277 octave
= note
/ 12 - 1;
279 g_string_sprintf(channel_str_ptr
, "%u", channel
);
283 "Polyphonic Key Pressure (Aftertouch), %s, octave %d, velocity %u",
291 if (buffer_size
== 3 && (buffer
[0] >> 4) == 0x0B)
293 channel
= (buffer
[0] & 0x0F) + 1; /* 1 .. 16 */
294 assert(channel
>= 1 && channel
<= 16);
296 controller
= buffer
[1];
297 if (controller
> 127)
308 g_string_sprintf(channel_str_ptr
, "%u", channel
);
310 controller_name
= gm_get_controller_name(controller
);
312 if (controller_name
!= NULL
)
316 "CC %s (%u), value %u",
333 if (buffer_size
== 2 && (buffer
[0] >> 4) == 0x0C)
335 channel
= (buffer
[0] & 0x0F) + 1; /* 1 .. 16 */
336 assert(channel
>= 1 && channel
<= 16);
344 g_string_sprintf(channel_str_ptr
, "%u", channel
);
348 "Program change, %d (%s)",
350 gm_get_instrument_name(value
));
355 if (buffer_size
== 3 && (buffer
[0] >> 4) == 0x0E && buffer
[1] <= 127 && buffer
[2] <= 127)
357 channel
= (buffer
[0] & 0x0F) + 1; /* 1 .. 16 */
358 assert(channel
>= 1 && channel
<= 16);
361 pitch
|= (unsigned int)buffer
[2] << 7;
364 g_string_sprintf(channel_str_ptr
, "%u", channel
);
374 if (buffer_size
> 0 && buffer
[0] == 0xF0)
376 decode_sysex(buffer
, buffer_size
, msg_str_ptr
);
380 if (buffer_size
== 1 && buffer
[0] == 0xFF)
392 "unknown midi event with size %u bytes:",
393 (unsigned int)buffer_size
);
395 for (i
= 0 ; i
< buffer_size
; i
++)
397 g_string_append_printf(
400 (unsigned int)(buffer
[i
]));
406 /* The JACK MIDI input handling thread */
408 jack_midi_thread(void * context_ptr
)
410 struct jack_midi_event_buffer
* event_buffer
;
411 struct list_head
* node_ptr
;
412 GtkListStore
* list_store_ptr
;
413 GtkWidget
* child_ptr
;
415 GString
* time_str_ptr
;
416 GString
* msg_str_ptr
;
417 GString
* channel_str_ptr
;
419 LOG_DEBUG("jack_midi_thread started");
421 child_ptr
= GTK_WIDGET (gtk_builder_get_object (g_builder
, "list"));
423 list_store_ptr
= GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(child_ptr
)));
426 pthread_mutex_lock(&g_jack_midi_mutex
);
428 if (g_jack_midi_thread_exit
)
430 pthread_mutex_unlock(&g_jack_midi_mutex
);
432 LOG_DEBUG("jack_midi_thread exiting");
436 rtsafe_memory_sleepy(g_memory
);
438 //LOG_DEBUG("checking events...");
440 while (!list_empty(&g_jack_midi_events_pending
))
442 node_ptr
= g_jack_midi_events_pending
.prev
;
446 event_buffer
= list_entry(node_ptr
, struct jack_midi_event_buffer
, siblings
);
450 goto deallocate_event
;
453 LOG_DEBUG("midi event with size %u received.", (unsigned int)event_buffer
->buffer_size
);
455 time_str_ptr
= g_string_new("");
456 channel_str_ptr
= g_string_new("");
457 msg_str_ptr
= g_string_new("");
459 if (!jack_midi_decode(
460 event_buffer
->buffer
,
461 event_buffer
->buffer_size
,
465 /* ignoring specific event */
466 goto deallocate_strings
;
469 /* get GTK thread lock */
472 if (g_row_count
>= MAX_LIST_SIZE
)
474 gtk_tree_model_get_iter_first(
475 GTK_TREE_MODEL(list_store_ptr
),
478 gtk_list_store_remove(
483 /* Append an empty row to the list store. Iter will point to the new row */
484 gtk_list_store_append(list_store_ptr
, &iter
);
489 COL_TIME
, time_str_ptr
->str
,
490 COL_CHANNEL
, channel_str_ptr
->str
,
491 COL_MESSAGE
, msg_str_ptr
->str
,
494 gtk_tree_view_scroll_to_cell(
495 GTK_TREE_VIEW(child_ptr
),
496 gtk_tree_model_get_path(
497 gtk_tree_view_get_model(GTK_TREE_VIEW(child_ptr
)),
504 /* Force update of scroll position. */
505 /* Is it a bug that it does not update automagically ? */
506 gtk_container_check_resize(GTK_CONTAINER(child_ptr
));
510 /* release GTK thread lock */
514 g_string_free(channel_str_ptr
, TRUE
);
515 g_string_free(msg_str_ptr
, TRUE
);
516 g_string_free(time_str_ptr
, TRUE
);
519 rtsafe_memory_deallocate(event_buffer
);
522 pthread_mutex_unlock(&g_jack_midi_mutex
);
524 //LOG_DEBUG("waiting for more events...");
526 //pthread_cond_wait(&g_jack_midi_cond, &g_jack_midi_mutex);
533 jack_destroy_pending_events()
535 struct jack_midi_event_buffer
* event_buffer
;
536 struct list_head
* node_ptr
;
538 while (!list_empty(&g_jack_midi_events_pending
))
540 LOG_DEBUG("Destroying pending event");
541 node_ptr
= g_jack_midi_events_pending
.next
;
545 event_buffer
= list_entry(node_ptr
, struct jack_midi_event_buffer
, siblings
);
547 rtsafe_memory_deallocate(event_buffer
);
550 while (!list_empty(&g_jack_midi_events_pending_rt
))
552 LOG_DEBUG("Destroying realtime pending event");
553 node_ptr
= g_jack_midi_events_pending_rt
.next
;
557 event_buffer
= list_entry(node_ptr
, struct jack_midi_event_buffer
, siblings
);
559 rtsafe_memory_deallocate(event_buffer
);
564 jack_init(const char * name
)
568 LOG_DEBUG("jack_init(\"%s\") called.", name
);
570 if (!rtsafe_memory_init(
576 LOG_ERROR("RT-safe memory initialization failed.");
580 INIT_LIST_HEAD(&g_jack_midi_events_pending
);
581 INIT_LIST_HEAD(&g_jack_midi_events_pending_rt
);
583 ret
= pthread_mutex_init(&g_jack_midi_mutex
, NULL
);
586 LOG_ERROR("Cannot initialize mutex.");
587 goto fail_uninit_memory
;
590 /* ret = pthread_cond_init(&g_jack_midi_cond, NULL); */
593 /* LOG_ERROR("Cannot initialize condition (variable)."); */
594 /* goto fail_uninit_mutex; */
597 g_jack_midi_thread_exit
= FALSE
;
599 ret
= pthread_create(&g_jack_midi_tid
, NULL
, jack_midi_thread
, NULL
);
602 LOG_ERROR("Cannot start JACK MIDI thread.");
603 goto fail_uninit_cond
;
606 g_jack_client
= jack_client_open(name
, JackNoStartServer
, NULL
);
607 if (g_jack_client
== NULL
)
609 LOG_ERROR("Cannot create JACK client.");
610 goto fail_stop_thread
;
613 ret
= jack_set_process_callback(g_jack_client
, jack_process
, 0);
616 LOG_ERROR("Cannot set JACK process callback.");
620 g_jack_input_port
= jack_port_register(g_jack_client
, "midi_in", JACK_DEFAULT_MIDI_TYPE
, JackPortIsInput
, 0);
621 if (g_jack_input_port
== NULL
)
623 LOG_ERROR("Failed to create input JACK MIDI port");
627 ret
= jack_activate(g_jack_client
);
630 LOG_ERROR("Cannot activate JACK client.");
637 jack_client_close(g_jack_client
);
640 jack_destroy_pending_events();
642 /* Tell jack_midi_thread to exit */
643 pthread_mutex_lock(&g_jack_midi_mutex
);
644 g_jack_midi_thread_exit
= TRUE
;
645 pthread_mutex_unlock(&g_jack_midi_mutex
);
647 /* wakeup jack_midi_thread */
648 /* pthread_cond_broadcast(&g_jack_midi_cond); */
650 /* wait thread to finish */
651 pthread_join(g_jack_midi_tid
, NULL
);
654 /* pthread_cond_destroy(&g_jack_midi_cond); */
656 /* fail_uninit_mutex: */
657 pthread_mutex_destroy(&g_jack_midi_mutex
);
660 rtsafe_memory_uninit(g_memory
);
669 LOG_DEBUG("jack_uninit() called.");
671 jack_deactivate(g_jack_client
);
673 jack_client_close(g_jack_client
);
675 /* Tell jack_midi_thread to exit */
676 pthread_mutex_lock(&g_jack_midi_mutex
);
677 g_jack_midi_thread_exit
= TRUE
;
678 pthread_mutex_unlock(&g_jack_midi_mutex
);
680 /* wakeup jack_midi_thread */
681 /* pthread_cond_broadcast(&g_jack_midi_cond); */
683 /* wait thread to finish */
684 pthread_join(g_jack_midi_tid
, NULL
);
686 jack_destroy_pending_events();
688 /* pthread_cond_destroy(&g_jack_midi_cond); */
690 pthread_mutex_destroy(&g_jack_midi_mutex
);
692 rtsafe_memory_uninit(g_memory
);