@@ -279,6 +279,7 @@ enum PostPonedEventType {
279279 POSTPONED_PARAM_SET ,
280280 POSTPONED_AUDIO_MONITOR ,
281281 POSTPONED_OUTPUT_MONITOR ,
282+ POSTPONED_MIDI_CONTROL_CHANGE ,
282283 POSTPONED_MIDI_PROGRAM_CHANGE ,
283284 POSTPONED_MIDI_MAP ,
284285 POSTPONED_TRANSPORT ,
@@ -601,6 +602,12 @@ typedef struct POSTPONED_AUDIO_MONITOR_EVENT_T {
601602 float value ;
602603} postponed_audio_monitor_event_t ;
603604
605+ typedef struct POSTPONED_MIDI_CONTROL_CHANGE_EVENT_T {
606+ int8_t channel ;
607+ int8_t control ;
608+ int16_t value ;
609+ } postponed_midi_control_change_event_t ;
610+
604611typedef struct POSTPONED_MIDI_PROGRAM_CHANGE_EVENT_T {
605612 int8_t program ;
606613 int8_t channel ;
@@ -644,6 +651,7 @@ typedef struct POSTPONED_EVENT_T {
644651 union {
645652 postponed_parameter_event_t parameter ;
646653 postponed_audio_monitor_event_t audio_monitor ;
654+ postponed_midi_control_change_event_t control_change ;
647655 postponed_midi_program_change_event_t program_change ;
648656 postponed_midi_map_event_t midi_map ;
649657 postponed_transport_event_t transport ;
@@ -804,7 +812,8 @@ static LV2_Feature g_urid_unmap_feature = { LV2_URID__unmap, &g_urid_unmap };
804812/* MIDI Learn */
805813static pthread_mutex_t g_midi_learning_mutex ;
806814
807- /* MIDI program monitoring */
815+ /* MIDI control and program monitoring */
816+ static bool g_monitored_midi_controls [16 ];
808817static bool g_monitored_midi_programs [16 ];
809818
810819#ifdef HAVE_HYLIA
@@ -1371,6 +1380,16 @@ static void RunPostPonedEvents(int ignored_effect_id)
13711380 socket_send_feedback_debug (buf );
13721381 break ;
13731382
1383+ case POSTPONED_MIDI_CONTROL_CHANGE :
1384+ // TODO skip event if it matches previous one
1385+
1386+ snprintf (buf , FEEDBACK_BUF_SIZE , "midi_control_change %i %i %i" ,
1387+ eventptr -> event .control_change .channel ,
1388+ eventptr -> event .control_change .control ,
1389+ eventptr -> event .control_change .value );
1390+ socket_send_feedback_debug (buf );
1391+ break ;
1392+
13741393 case POSTPONED_MIDI_PROGRAM_CHANGE :
13751394 if (got_midi_program )
13761395 {
@@ -2586,7 +2605,7 @@ static int ProcessGlobalClient(jack_nframes_t nframes, void *arg)
25862605{
25872606 jack_midi_event_t event ;
25882607 uint8_t channel , controller ;
2589- uint8_t status_nibble , channel_nibble ;
2608+ uint8_t status_nibble ;
25902609 uint16_t mvalue ;
25912610 float value ;
25922611 double dvalue ;
@@ -2694,9 +2713,9 @@ static int ProcessGlobalClient(jack_nframes_t nframes, void *arg)
26942713 // Handle MIDI program change
26952714 if (status_nibble == 0xC0 )
26962715 {
2697- channel_nibble = (event .buffer [0 ] & 0x0F );
2716+ channel = (event .buffer [0 ] & 0x0F );
26982717
2699- if (g_monitored_midi_programs [channel_nibble ] && event .size == 2 )
2718+ if (g_monitored_midi_programs [channel ] && event .size == 2 )
27002719 {
27012720 // Append to the queue
27022721 postponed_event_list_data * const posteventptr = rtsafe_memory_pool_allocate_atomic (g_rtsafe_mem_pool );
@@ -2705,7 +2724,7 @@ static int ProcessGlobalClient(jack_nframes_t nframes, void *arg)
27052724 {
27062725 posteventptr -> event .type = POSTPONED_MIDI_PROGRAM_CHANGE ;
27072726 posteventptr -> event .program_change .program = event .buffer [1 ];
2708- posteventptr -> event .program_change .channel = channel_nibble ;
2727+ posteventptr -> event .program_change .channel = channel ;
27092728
27102729 pthread_mutex_lock (& g_rtsafe_mutex );
27112730 list_add_tail (& posteventptr -> siblings , & g_rtsafe_list );
@@ -2822,6 +2841,24 @@ static int ProcessGlobalClient(jack_nframes_t nframes, void *arg)
28222841 list_add_tail (& posteventptr -> siblings , & g_rtsafe_list );
28232842 pthread_mutex_unlock (& g_rtsafe_mutex );
28242843
2844+ needs_post = true;
2845+ }
2846+ }
2847+ else if (g_monitored_midi_programs [channel ])
2848+ {
2849+ postponed_event_list_data * const posteventptr = rtsafe_memory_pool_allocate_atomic (g_rtsafe_mem_pool );
2850+
2851+ if (posteventptr )
2852+ {
2853+ posteventptr -> event .type = POSTPONED_MIDI_MAP ;
2854+ posteventptr -> event .control_change .channel = channel ;
2855+ posteventptr -> event .control_change .control = controller ;
2856+ posteventptr -> event .control_change .value = mvalue ;
2857+
2858+ pthread_mutex_lock (& g_rtsafe_mutex );
2859+ list_add_tail (& posteventptr -> siblings , & g_rtsafe_list );
2860+ pthread_mutex_unlock (& g_rtsafe_mutex );
2861+
28252862 needs_post = true;
28262863 }
28272864 }
@@ -4505,6 +4542,7 @@ int effects_init(void* client)
45054542 }
45064543 g_midi_learning = NULL ;
45074544
4545+ memset (g_monitored_midi_controls , 0 , sizeof (g_monitored_midi_controls ));
45084546 memset (g_monitored_midi_programs , 0 , sizeof (g_monitored_midi_programs ));
45094547
45104548#ifdef HAVE_CONTROLCHAIN
@@ -8595,6 +8633,15 @@ int effects_monitor_audio_levels(const char *source_port_name, int enable)
85958633 return SUCCESS ;
85968634}
85978635
8636+ int effects_monitor_midi_control (int channel , int enable )
8637+ {
8638+ if (channel < 0 || channel > 15 )
8639+ return ERR_INVALID_OPERATION ;
8640+
8641+ g_monitored_midi_controls [channel ] = enable != 0 ;
8642+ return SUCCESS ;
8643+ }
8644+
85988645int effects_monitor_midi_program (int channel , int enable )
85998646{
86008647 if (channel < 0 || channel > 15 )
0 commit comments