@@ -279,6 +279,7 @@ enum PostPonedEventType {
279
279
POSTPONED_PARAM_SET ,
280
280
POSTPONED_AUDIO_MONITOR ,
281
281
POSTPONED_OUTPUT_MONITOR ,
282
+ POSTPONED_MIDI_CONTROL_CHANGE ,
282
283
POSTPONED_MIDI_PROGRAM_CHANGE ,
283
284
POSTPONED_MIDI_MAP ,
284
285
POSTPONED_TRANSPORT ,
@@ -601,6 +602,12 @@ typedef struct POSTPONED_AUDIO_MONITOR_EVENT_T {
601
602
float value ;
602
603
} postponed_audio_monitor_event_t ;
603
604
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
+
604
611
typedef struct POSTPONED_MIDI_PROGRAM_CHANGE_EVENT_T {
605
612
int8_t program ;
606
613
int8_t channel ;
@@ -644,6 +651,7 @@ typedef struct POSTPONED_EVENT_T {
644
651
union {
645
652
postponed_parameter_event_t parameter ;
646
653
postponed_audio_monitor_event_t audio_monitor ;
654
+ postponed_midi_control_change_event_t control_change ;
647
655
postponed_midi_program_change_event_t program_change ;
648
656
postponed_midi_map_event_t midi_map ;
649
657
postponed_transport_event_t transport ;
@@ -804,7 +812,8 @@ static LV2_Feature g_urid_unmap_feature = { LV2_URID__unmap, &g_urid_unmap };
804
812
/* MIDI Learn */
805
813
static pthread_mutex_t g_midi_learning_mutex ;
806
814
807
- /* MIDI program monitoring */
815
+ /* MIDI control and program monitoring */
816
+ static bool g_monitored_midi_controls [16 ];
808
817
static bool g_monitored_midi_programs [16 ];
809
818
810
819
#ifdef HAVE_HYLIA
@@ -1371,6 +1380,16 @@ static void RunPostPonedEvents(int ignored_effect_id)
1371
1380
socket_send_feedback_debug (buf );
1372
1381
break ;
1373
1382
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
+
1374
1393
case POSTPONED_MIDI_PROGRAM_CHANGE :
1375
1394
if (got_midi_program )
1376
1395
{
@@ -2586,7 +2605,7 @@ static int ProcessGlobalClient(jack_nframes_t nframes, void *arg)
2586
2605
{
2587
2606
jack_midi_event_t event ;
2588
2607
uint8_t channel , controller ;
2589
- uint8_t status_nibble , channel_nibble ;
2608
+ uint8_t status_nibble ;
2590
2609
uint16_t mvalue ;
2591
2610
float value ;
2592
2611
double dvalue ;
@@ -2694,9 +2713,9 @@ static int ProcessGlobalClient(jack_nframes_t nframes, void *arg)
2694
2713
// Handle MIDI program change
2695
2714
if (status_nibble == 0xC0 )
2696
2715
{
2697
- channel_nibble = (event .buffer [0 ] & 0x0F );
2716
+ channel = (event .buffer [0 ] & 0x0F );
2698
2717
2699
- if (g_monitored_midi_programs [channel_nibble ] && event .size == 2 )
2718
+ if (g_monitored_midi_programs [channel ] && event .size == 2 )
2700
2719
{
2701
2720
// Append to the queue
2702
2721
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)
2705
2724
{
2706
2725
posteventptr -> event .type = POSTPONED_MIDI_PROGRAM_CHANGE ;
2707
2726
posteventptr -> event .program_change .program = event .buffer [1 ];
2708
- posteventptr -> event .program_change .channel = channel_nibble ;
2727
+ posteventptr -> event .program_change .channel = channel ;
2709
2728
2710
2729
pthread_mutex_lock (& g_rtsafe_mutex );
2711
2730
list_add_tail (& posteventptr -> siblings , & g_rtsafe_list );
@@ -2822,6 +2841,24 @@ static int ProcessGlobalClient(jack_nframes_t nframes, void *arg)
2822
2841
list_add_tail (& posteventptr -> siblings , & g_rtsafe_list );
2823
2842
pthread_mutex_unlock (& g_rtsafe_mutex );
2824
2843
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
+
2825
2862
needs_post = true;
2826
2863
}
2827
2864
}
@@ -4505,6 +4542,7 @@ int effects_init(void* client)
4505
4542
}
4506
4543
g_midi_learning = NULL ;
4507
4544
4545
+ memset (g_monitored_midi_controls , 0 , sizeof (g_monitored_midi_controls ));
4508
4546
memset (g_monitored_midi_programs , 0 , sizeof (g_monitored_midi_programs ));
4509
4547
4510
4548
#ifdef HAVE_CONTROLCHAIN
@@ -8595,6 +8633,15 @@ int effects_monitor_audio_levels(const char *source_port_name, int enable)
8595
8633
return SUCCESS ;
8596
8634
}
8597
8635
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
+
8598
8645
int effects_monitor_midi_program (int channel , int enable )
8599
8646
{
8600
8647
if (channel < 0 || channel > 15 )
0 commit comments