From: DeltaMikeCharlie <127641886+DeltaMikeCharlie@users.noreply.github.com> Date: Sun, 1 Jun 2025 22:27:58 +0000 (+1000) Subject: Add API call 'status/activity'. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8d469350fa67cb1ce923ecaf303d5ba3bf5c1518;p=thirdparty%2Ftvheadend.git Add API call 'status/activity'. --- diff --git a/src/api/api_status.c b/src/api/api_status.c index 9b8e5c99a..cd48e88ba 100644 --- a/src/api/api_status.c +++ b/src/api/api_status.c @@ -26,6 +26,8 @@ #include "api.h" #include "tcp.h" #include "input.h" +#include "epggrab.h" //Needed to get the next EPG grab times +#include "dvr/dvr.h" //Needed to get the next schedule dvr time static int api_status_inputs @@ -171,6 +173,75 @@ api_status_input_clear_stats return 0; } +static int +api_status_activity + ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp ) +{ + htsmsg_t *cats; + time_t temp_earliest = 0; + time_t temp_dvr = 0; + time_t temp_ota = 0; + time_t temp_int = 0; + time_t temp_mux = 0; + th_subscription_t *ths; + uint32_t subscriptionCount = 0; + + temp_dvr = dvr_entry_find_earliest(); + + //Only evaluate the OTA grabber cron if there are active OTA modules. + if(epggrab_count_type(EPGGRAB_OTA)) + { + temp_ota = epggrab_get_next_ota(); + } + + //Only evaluate the internal grabber cron if there are active internal modules. + if(epggrab_count_type(EPGGRAB_INT)) + { + temp_int = epggrab_get_next_int(); + } + + temp_mux = mpegts_mux_sched_next(); + + temp_earliest = temp_dvr; + + if(temp_ota && ((temp_ota < temp_earliest) || (temp_earliest == 0))) + { + temp_earliest = temp_ota; + } + + if(temp_int && ((temp_int < temp_earliest) || (temp_earliest == 0))) + { + temp_earliest = temp_int; + } + + if(temp_mux && ((temp_mux < temp_earliest) || (temp_earliest == 0))) + { + temp_earliest = temp_mux; + } + + cats = htsmsg_create_map(); + htsmsg_add_s64(cats, "dvr", temp_dvr); + htsmsg_add_s64(cats, "ota_grabber", temp_ota); + htsmsg_add_s64(cats, "int_grabber", temp_int); + htsmsg_add_s64(cats, "mux_scheduler", temp_mux); + + tvh_mutex_lock(&global_lock); + LIST_FOREACH(ths, &subscriptions, ths_global_link) { + subscriptionCount++; + } + tvh_mutex_unlock(&global_lock); + + *resp = htsmsg_create_map(); + htsmsg_add_s64(*resp, "current_time", gclk()); + htsmsg_add_s64(*resp, "next_activity", temp_earliest); + htsmsg_add_msg(*resp, "activities", cats); + htsmsg_add_u32(*resp, "subscription_count", subscriptionCount); + htsmsg_add_u32(*resp, "connection_count", tcp_server_connections_count()); + + return 0; + +} + void api_status_init ( void ) { static api_hook_t ah[] = { @@ -178,6 +249,7 @@ void api_status_init ( void ) { "status/subscriptions", ACCESS_ADMIN, api_status_subscriptions, NULL }, { "status/inputs", ACCESS_ADMIN, api_status_inputs, NULL }, { "status/inputclrstats", ACCESS_ADMIN, api_status_input_clear_stats, NULL }, + { "status/activity", ACCESS_ADMIN, api_status_activity, NULL }, { "connections/cancel", ACCESS_ADMIN, api_connections_cancel, NULL }, { NULL }, }; diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index 13dc60743..e07b68119 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -626,6 +626,8 @@ int dvr_entry_assign_broadcast(dvr_entry_t *de, epg_broadcast_t *bcast); dvr_entry_t *dvr_entry_find_by_id(int id); +time_t dvr_entry_find_earliest(void); + static inline dvr_entry_t *dvr_entry_find_by_uuid(const char *uuid) { return (dvr_entry_t*)idnode_find(uuid, &dvr_entry_class, NULL); } diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 4a64eb4bf..431b820c2 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -3072,6 +3072,35 @@ dvr_entry_find_by_id(int id) return de; } +/** + * Find the earliest scheduled dvr entry + */ +time_t +dvr_entry_find_earliest(void) +{ + time_t start; + time_t earliest = 0; + dvr_entry_t *de; + + LIST_FOREACH(de, &dvrentries, de_global_link) + { + if(dvr_entry_is_upcoming(de) && de->de_enabled) + { + start = dvr_entry_get_start_time(de, 1); + if(earliest == 0) + { + earliest = start; + } + else if(start < earliest) + { + earliest = start; + } + } + }//END FOREACH + + return earliest; + +} /** * Unconditionally remove an entry diff --git a/src/epggrab.c b/src/epggrab.c index 06073e981..20a1edddb 100644 --- a/src/epggrab.c +++ b/src/epggrab.c @@ -509,6 +509,44 @@ const idclass_t epggrab_class = { } }; +/* ************************************************************************** + * Get the time for the next scheduled internal grabber + * *************************************************************************/ +time_t epggrab_get_next_int(void) +{ + time_t ret_time; + struct timespec current_time; + + clock_gettime(CLOCK_REALTIME, ¤t_time); + if(!cron_multi_next(epggrab_cron_multi, current_time.tv_sec, &ret_time)) + { + return ret_time; + } + else + { + return 0; + } +} + +/* ************************************************************************** + * Count the number of EPG grabbers of a specified type + * *************************************************************************/ +int epggrab_count_type(int grabberType) +{ + epggrab_module_t *mod; + int temp_count = 0; + + LIST_FOREACH(mod, &epggrab_modules, link) { + if(mod->enabled && mod->type == grabberType) + { + temp_count++; + } + } + + return temp_count; + +} + /* ************************************************************************** * Initialisation * *************************************************************************/ diff --git a/src/epggrab.h b/src/epggrab.h index 62020a49a..590df45df 100644 --- a/src/epggrab.h +++ b/src/epggrab.h @@ -406,6 +406,16 @@ const char *epggrab_ota_check_module_id( const char *id ); */ extern unsigned char *epggrab_ota_genre_translation; +/* + * Get the next execution times + */ +time_t epggrab_get_next_int(void); +time_t epggrab_get_next_ota(void); +/* + * Count active grabbers for a given type + */ +int epggrab_count_type(int grabberType); + #endif /* __EPGGRAB_H__ */ /* ************************************************************************** diff --git a/src/epggrab/otamux.c b/src/epggrab/otamux.c index aa7d94c81..0a5dc9345 100644 --- a/src/epggrab/otamux.c +++ b/src/epggrab/otamux.c @@ -1141,6 +1141,23 @@ epggrab_ota_set_genre_translation ( void ) tvh_mutex_unlock(&epggrab_ota_mutex); } +/* ************************************************************************** + * Get the time for the next scheduled ota grabber + * *************************************************************************/ +time_t epggrab_get_next_ota(void) +{ + time_t ret_time = 0; + + if(!cron_multi_next(epggrab_ota_cron_multi, gclk(), &ret_time)) + { + return ret_time; + } + else + { + return 0; + } +} + /****************************************************************************** * Editor Configuration * diff --git a/src/input/mpegts/mpegts_mux_sched.c b/src/input/mpegts/mpegts_mux_sched.c index c7a1a4d41..1c30efc9f 100644 --- a/src/input/mpegts/mpegts_mux_sched.c +++ b/src/input/mpegts/mpegts_mux_sched.c @@ -383,6 +383,33 @@ mpegts_mux_sched_done ( void ) tvh_mutex_unlock(&global_lock); } +/* + * Earliest Mux scheduler + */ +time_t mpegts_mux_sched_next(void) +{ + time_t earliest = 0; + mpegts_mux_sched_t *mms; + + LIST_FOREACH(mms, &mpegts_mux_sched_all, mms_link) + { + if(mms->mms_enabled) //Only process 'enabled' items. + { + if(!earliest) + { + earliest = mms->mms_start; + } + else if(mms->mms_start < earliest) + { + earliest = mms->mms_start; + } + } + }//END FOREACH + + return earliest; + +} + /****************************************************************************** * Editor Configuration * diff --git a/src/input/mpegts/mpegts_mux_sched.h b/src/input/mpegts/mpegts_mux_sched.h index b5e664f08..80c01b762 100644 --- a/src/input/mpegts/mpegts_mux_sched.h +++ b/src/input/mpegts/mpegts_mux_sched.h @@ -72,6 +72,7 @@ void mpegts_mux_sched_delete ( mpegts_mux_sched_t *mms, int delconf ); void mpegts_mux_sched_init ( void ); void mpegts_mux_sched_done ( void ); +time_t mpegts_mux_sched_next(void); #endif /* __TVH_MPEGTS_H__ */ diff --git a/src/tcp.c b/src/tcp.c index 8ff558730..0c86146a8 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -1156,6 +1156,23 @@ tcp_server_connections ( void ) return m; } +/* + * Connections count + */ +int +tcp_server_connections_count ( void ) +{ + tcp_server_launch_t *tsl; + int c = 0; + + /* Count connections */ + LIST_FOREACH(tsl, &tcp_server_launches, link) { + if (!tsl->status) continue; + c++; + } + + return c; +} /** * */ diff --git a/src/tcp.h b/src/tcp.h index 5d32b8926..2ae9c1d39 100644 --- a/src/tcp.h +++ b/src/tcp.h @@ -164,5 +164,6 @@ void tcp_connection_cancel(uint32_t id); void tcp_connection_cancel_all(void); htsmsg_t *tcp_server_connections ( void ); +int tcp_server_connections_count ( void ); #endif /* TCP_H_ */