@@ -300,6 +300,7 @@ enum PostPonedEventType {
300300 POSTPONED_PARAM_SET ,
301301 POSTPONED_PARAM_STATE ,
302302 POSTPONED_AUDIO_MONITOR ,
303+ POSTPONED_CPU_MONITOR ,
303304 POSTPONED_OUTPUT_MONITOR ,
304305 POSTPONED_MIDI_CONTROL_CHANGE ,
305306 POSTPONED_MIDI_PROGRAM_CHANGE ,
@@ -461,6 +462,10 @@ typedef struct EFFECT_T {
461462
462463 bool activated ;
463464
465+ bool monitor_cpu ;
466+ bool monitor_cpu_reset ;
467+ float cpu_load ;
468+
464469 // previous transport state
465470 bool transport_rolling ;
466471 uint32_t transport_frame ;
@@ -637,6 +642,11 @@ typedef struct POSTPONED_AUDIO_MONITOR_EVENT_T {
637642 float value ;
638643} postponed_audio_monitor_event_t ;
639644
645+ typedef struct POSTPONED_CPU_MONITOR_EVENT_T {
646+ int effect_id ;
647+ float cpu_load ;
648+ } postponed_cpu_monitor_event_t ;
649+
640650typedef struct POSTPONED_MIDI_CONTROL_CHANGE_EVENT_T {
641651 int8_t channel ;
642652 int8_t control ;
@@ -687,6 +697,7 @@ typedef struct POSTPONED_EVENT_T {
687697 postponed_parameter_event_t parameter ;
688698 postponed_parameter_state_t state ;
689699 postponed_audio_monitor_event_t audio_monitor ;
700+ postponed_cpu_monitor_event_t cpu_monitor ;
690701 postponed_midi_control_change_event_t control_change ;
691702 postponed_midi_program_change_event_t program_change ;
692703 postponed_midi_map_event_t midi_map ;
@@ -783,7 +794,7 @@ static jack_client_t *g_jack_global_client;
783794static jack_nframes_t g_sample_rate , g_max_allowed_midi_delta ;
784795static float g_sample_rate_f ;
785796static const char * * g_capture_ports , * * g_playback_ports ;
786- static int32_t g_midi_buffer_size , g_block_length ;
797+ static int32_t g_midi_buffer_size , g_block_length , g_block_time_us ;
787798static int32_t g_thread_policy , g_thread_priority ;
788799#ifdef MOD_IO_PROCESSING_ENABLED
789800static jack_port_t * g_audio_in1_port ;
@@ -1097,6 +1108,7 @@ static void AllocatePortBuffers(effect_t* effect, int in_size, int out_size)
10971108static int BufferSize (jack_nframes_t nframes , void * data )
10981109{
10991110 g_block_length = nframes ;
1111+ g_block_time_us = nframes * 1e6 / g_sample_rate ;
11001112 g_midi_buffer_size = jack_port_type_get_buffer_size (g_jack_global_client , JACK_DEFAULT_MIDI_TYPE );
11011113
11021114 if (data )
@@ -1347,10 +1359,11 @@ static void RunPostPonedEvents(int ignored_effect_id)
13471359 // cached data, to make sure we only handle similar events once
13481360 bool got_midi_program = false;
13491361 bool got_transport = false;
1350- postponed_cached_effect_events cached_audio_monitor , cached_process_out_buf ;
1362+ postponed_cached_effect_events cached_audio_monitor , cached_cpu_monitor , cached_process_out_buf ;
13511363 postponed_cached_symbol_events cached_param_set , cached_param_state , cached_output_mon ;
13521364
13531365 cached_audio_monitor .last_effect_id = -1 ;
1366+ cached_cpu_monitor .last_effect_id = -1 ;
13541367 cached_process_out_buf .last_effect_id = -1 ;
13551368 cached_param_set .last_effect_id = -1 ;
13561369 cached_param_set .last_symbol [0 ] = '\0' ;
@@ -1362,6 +1375,7 @@ static void RunPostPonedEvents(int ignored_effect_id)
13621375 cached_output_mon .last_symbol [0 ] = '\0' ;
13631376 cached_output_mon .last_symbol [MAX_CHAR_BUF_SIZE ] = '\0' ;
13641377 INIT_LIST_HEAD (& cached_audio_monitor .effects .siblings );
1378+ INIT_LIST_HEAD (& cached_cpu_monitor .effects .siblings );
13651379 INIT_LIST_HEAD (& cached_process_out_buf .effects .siblings );
13661380 INIT_LIST_HEAD (& cached_param_set .symbols .siblings );
13671381 INIT_LIST_HEAD (& cached_param_state .symbols .siblings );
@@ -1448,6 +1462,18 @@ static void RunPostPonedEvents(int ignored_effect_id)
14481462 cached_audio_monitor .last_effect_id = eventptr -> event .audio_monitor .index ;
14491463 break ;
14501464
1465+ case POSTPONED_CPU_MONITOR :
1466+ if (ShouldIgnorePostPonedEffectEvent (eventptr -> event .audio_monitor .index , & cached_audio_monitor ))
1467+ continue ;
1468+
1469+ snprintf (buf , FEEDBACK_BUF_SIZE , "cpu_monitor %i %f" , eventptr -> event .cpu_monitor .effect_id ,
1470+ eventptr -> event .cpu_monitor .cpu_load );
1471+ socket_send_feedback_debug (buf );
1472+
1473+ // save for fast checkup next time
1474+ cached_cpu_monitor .last_effect_id = eventptr -> event .cpu_monitor .effect_id ;
1475+ break ;
1476+
14511477 case POSTPONED_OUTPUT_MONITOR :
14521478 if (eventptr -> event .parameter .effect_id == ignored_effect_id )
14531479 continue ;
@@ -1744,6 +1770,11 @@ static void RunPostPonedEvents(int ignored_effect_id)
17441770 peffect = list_entry (it , postponed_cached_effect_list_data , siblings );
17451771 free (peffect );
17461772 }
1773+ list_for_each_safe (it , it2 , & cached_cpu_monitor .effects .siblings )
1774+ {
1775+ peffect = list_entry (it , postponed_cached_effect_list_data , siblings );
1776+ free (peffect );
1777+ }
17471778 list_for_each_safe (it , it2 , & cached_process_out_buf .effects .siblings )
17481779 {
17491780 peffect = list_entry (it , postponed_cached_effect_list_data , siblings );
@@ -2066,10 +2097,15 @@ static int ProcessPlugin(jack_nframes_t nframes, void *arg)
20662097 }
20672098
20682099 /* common variables */
2100+ const bool monitor_cpu = effect -> monitor_cpu ;
20692101 bool needs_post = false;
20702102 const float * buffer_in ;
20712103 float * buffer_out ;
20722104 float value ;
2105+ uint64_t time_start ;
2106+
2107+ if (monitor_cpu )
2108+ time_start = time_ns_get ();
20732109
20742110 /* transport */
20752111 uint8_t stack_buf [MAX_CHAR_BUF_SIZE + 1 ];
@@ -2611,6 +2647,37 @@ static int ProcessPlugin(jack_nframes_t nframes, void *arg)
26112647 if (effect -> hints & HINT_STATE_UNSAFE )
26122648 pthread_mutex_unlock (& effect -> state_restore_mutex );
26132649
2650+ if (monitor_cpu )
2651+ {
2652+ if (effect -> monitor_cpu_reset )
2653+ {
2654+ effect -> cpu_load = 0.f ;
2655+ effect -> monitor_cpu_reset = false;
2656+ }
2657+
2658+ float cpu_load = ((int32_t )(time_ns_get () - time_start ) / g_block_time_us ) * 0.001f ;
2659+
2660+ if (cpu_load > effect -> cpu_load )
2661+ {
2662+ effect -> cpu_load = cpu_load ;
2663+
2664+ postponed_event_list_data * const posteventptr = rtsafe_memory_pool_allocate_atomic (g_rtsafe_mem_pool );
2665+
2666+ if (posteventptr != NULL )
2667+ {
2668+ posteventptr -> event .type = POSTPONED_CPU_MONITOR ;
2669+ posteventptr -> event .cpu_monitor .effect_id = effect -> instance ;
2670+ posteventptr -> event .cpu_monitor .cpu_load = cpu_load ;
2671+
2672+ pthread_mutex_lock (& g_rtsafe_mutex );
2673+ list_add_tail (& posteventptr -> siblings , & g_rtsafe_list );
2674+ pthread_mutex_unlock (& g_rtsafe_mutex );
2675+
2676+ needs_post = true;
2677+ }
2678+ }
2679+ }
2680+
26142681 if (needs_post )
26152682 sem_post (& g_postevents_semaphore );
26162683
@@ -4453,6 +4520,8 @@ int effects_init(void* client)
44534520 return ERR_JACK_CLIENT_CREATION ;
44544521 }
44554522
4523+ time_ns_init ();
4524+
44564525 /* Register jack ports */
44574526 g_midi_in_port = jack_port_register (g_jack_global_client , "midi_in" , JACK_DEFAULT_MIDI_TYPE , JackPortIsInput , 0 );
44584527
@@ -4524,6 +4593,7 @@ int effects_init(void* client)
45244593 /* Get buffers size */
45254594 g_block_length = jack_get_buffer_size (g_jack_global_client );
45264595 g_sample_rate = jack_get_sample_rate (g_jack_global_client );
4596+ g_block_time_us = g_block_length * 1e6 / g_sample_rate ;
45274597 g_sample_rate_f = g_sample_rate ;
45284598 g_midi_buffer_size = jack_port_type_get_buffer_size (g_jack_global_client , JACK_DEFAULT_MIDI_TYPE );
45294599 g_max_allowed_midi_delta = (jack_nframes_t )(g_sample_rate * 0.2 ); // max 200ms of allowed delta
@@ -9467,6 +9537,30 @@ int effects_monitor_audio_levels(const char *source_port_name, int enable)
94679537 return SUCCESS ;
94689538}
94699539
9540+ int effects_monitor_cpu_load (int enable , int num_effects , int * effects )
9541+ {
9542+ if (num_effects <= 0 )
9543+ return ERR_INVALID_OPERATION ;
9544+
9545+ effect_t * effect ;
9546+
9547+ for (int i = 0 , effect_id ; i < num_effects ; i ++ )
9548+ {
9549+ effect_id = effects [i ];
9550+ if (InstanceExist (effect_id ))
9551+ {
9552+ effect = & g_effects [effect_id ];
9553+
9554+ if (enable != 0 )
9555+ effect -> monitor_cpu_reset = true;
9556+
9557+ effect -> monitor_cpu = enable != 0 ;
9558+ }
9559+ }
9560+
9561+ return SUCCESS ;
9562+ }
9563+
94709564int effects_monitor_midi_control (int channel , int enable )
94719565{
94729566 if (channel < 0 || channel > 15 )
@@ -9631,6 +9725,20 @@ void effects_output_data_ready(void)
96319725
96329726 if (! g_postevents_ready )
96339727 {
9728+ // recalculate max cpu usage again
9729+ for (int i = 0 ; i < MAX_PLUGIN_INSTANCES ; ++ i )
9730+ {
9731+ effect_t * effect = & g_effects [i ];
9732+
9733+ if (effect -> lilv_instance == NULL )
9734+ continue ;
9735+ if (effect -> lilv_plugin == NULL )
9736+ continue ;
9737+
9738+ if (effect -> monitor_cpu )
9739+ effect -> monitor_cpu_reset = true;
9740+ }
9741+
96349742 g_postevents_ready = true;
96359743 sem_post (& g_postevents_semaphore );
96369744 }
0 commit comments