From 738866a62561046f5ab2b3881cca4c35cde5f171 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Sun, 31 Aug 2025 02:22:50 -0400 Subject: [PATCH] improve audio progress report with 1 sec updating --- lib/raop.h | 2 +- lib/raop_handlers.h | 5 +++-- lib/raop_rtp.c | 16 +++++++------- lib/raop_rtp.h | 2 +- lib/stream.h | 2 +- uxplay.cpp | 51 ++++++++++++++++++++++++++++++++++++++------- 6 files changed, 58 insertions(+), 20 deletions(-) diff --git a/lib/raop.h b/lib/raop.h index 87f486b..3eb1054 100644 --- a/lib/raop.h +++ b/lib/raop.h @@ -84,7 +84,7 @@ struct raop_callbacks_s { void (*audio_set_coverart)(void *cls, const void *buffer, int buflen); void (*audio_stop_coverart_rendering) (void* cls); void (*audio_remote_control_id)(void *cls, const char *dacp_id, const char *active_remote_header); - void (*audio_set_progress)(void *cls, unsigned int start, unsigned int curr, unsigned int end); + void (*audio_set_progress)(void *cls, uint32_t *start, uint32_t *curr, uint32_t *end); void (*audio_get_format)(void *cls, unsigned char *ct, unsigned short *spf, bool *usingScreen, bool *isMedia, uint64_t *audioFormat); void (*video_report_size)(void *cls, float *width_source, float *height_source, float *width, float *height); void (*mirror_video_activity)(void *cls, double *txusage); diff --git a/lib/raop_handlers.h b/lib/raop_handlers.h index 4d7af19..a3ada61 100644 --- a/lib/raop_handlers.h +++ b/lib/raop_handlers.h @@ -22,6 +22,7 @@ #include "utils.h" #include #include +#include #include #define AUDIO_SAMPLE_RATE 44100 /* all supported AirPlay audio format use this sample rate */ #define SECOND_IN_USECS 1000000 @@ -1091,8 +1092,8 @@ raop_handler_set_parameter(raop_conn_t *conn, sscanf(datastr+8, "%f", &vol); raop_rtp_set_volume(conn->raop_rtp, vol); } else if ((datalen >= 10) && !strncmp(datastr, "progress: ", 10)) { - unsigned int start, curr, end; - sscanf(datastr+10, "%u/%u/%u", &start, &curr, &end); + uint32_t start, curr, end; + sscanf(datastr+10, "%"PRIu32"/%"PRIu32"/%"PRIu32, &start, &curr, &end); raop_rtp_set_progress(conn->raop_rtp, start, curr, end); } } else if (!conn->raop_rtp) { diff --git a/lib/raop_rtp.c b/lib/raop_rtp.c index e76e90f..d36b47a 100644 --- a/lib/raop_rtp.c +++ b/lib/raop_rtp.c @@ -93,9 +93,9 @@ struct raop_rtp_s { int coverart_len; char *dacp_id; char *active_remote_header; - unsigned int progress_start; - unsigned int progress_curr; - unsigned int progress_end; + uint32_t progress_start; + uint32_t progress_curr; + uint32_t progress_end; int progress_changed; int flush; @@ -287,9 +287,9 @@ raop_rtp_process_events(raop_rtp_t *raop_rtp, void *cb_data) int coverart_len; char *dacp_id; char *active_remote_header; - unsigned int progress_start; - unsigned int progress_curr; - unsigned int progress_end; + uint32_t progress_start; + uint32_t progress_curr; + uint32_t progress_end; int progress_changed; assert(raop_rtp); @@ -378,7 +378,7 @@ raop_rtp_process_events(raop_rtp_t *raop_rtp, void *cb_data) if (progress_changed) { if (raop_rtp->callbacks.audio_set_progress) { - raop_rtp->callbacks.audio_set_progress(raop_rtp->callbacks.cls, progress_start, progress_curr, progress_end); + raop_rtp->callbacks.audio_set_progress(raop_rtp->callbacks.cls, &progress_start, &progress_curr, &progress_end); } } return 0; @@ -805,7 +805,7 @@ raop_rtp_remote_control_id(raop_rtp_t *raop_rtp, const char *dacp_id, const char } void -raop_rtp_set_progress(raop_rtp_t *raop_rtp, unsigned int start, unsigned int curr, unsigned int end) +raop_rtp_set_progress(raop_rtp_t *raop_rtp, uint32_t start, uint32_t curr, uint32_t end) { assert(raop_rtp); diff --git a/lib/raop_rtp.h b/lib/raop_rtp.h index e1276bd..d9f5476 100644 --- a/lib/raop_rtp.h +++ b/lib/raop_rtp.h @@ -39,7 +39,7 @@ void raop_rtp_set_volume(raop_rtp_t *raop_rtp, float volume); void raop_rtp_set_metadata(raop_rtp_t *raop_rtp, const char *data, int datalen); void raop_rtp_set_coverart(raop_rtp_t *raop_rtp, const char *data, int datalen); void raop_rtp_remote_control_id(raop_rtp_t *raop_rtp, const char *dacp_id, const char *active_remote_header); -void raop_rtp_set_progress(raop_rtp_t *raop_rtp, unsigned int start, unsigned int curr, unsigned int end); +void raop_rtp_set_progress(raop_rtp_t *raop_rtp, uint32_t start, uint32_t curr, uint32_t end); void raop_rtp_flush(raop_rtp_t *raop_rtp, int next_seq); void raop_rtp_stop(raop_rtp_t *raop_rtp); int raop_rtp_is_running(raop_rtp_t *raop_rtp); diff --git a/lib/stream.h b/lib/stream.h index 6905dcd..c544886 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -37,7 +37,7 @@ typedef struct { int sync_status; uint64_t ntp_time_local; uint64_t ntp_time_remote; - uint64_t rtp_time; + uint32_t rtp_time; unsigned short seqnum; } audio_decode_struct; diff --git a/uxplay.cpp b/uxplay.cpp index 459e3f1..082339c 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -174,12 +174,17 @@ static int n_audio_renderers = 0; static bool hls_support = false; static std::string url = ""; static guint gst_x11_window_id = 0; +static guint progress_id = 0; static guint gst_hls_position_id = 0; static bool preserve_connections = false; static guint missed_feedback_limit = MISSED_FEEDBACK_LIMIT; static guint missed_feedback = 0; static guint playbin_version = DEFAULT_PLAYBIN_VERSION; static bool reset_httpd = false; +static bool monitor_progress = false; +static uint32_t rtptime; +static uint32_t rtptime_start; +static uint32_t rtptime_end; //Support for D-Bus-based screensaver inhibition (org.freedesktop.ScreenSaver) static unsigned int scrsv; @@ -558,6 +563,30 @@ static guint g_unix_signal_add(gint signum, GSourceFunc handler, gpointer user_d } #endif +static void display_progress(uint32_t start, uint32_t curr, uint32_t end) { + if (curr < start || curr > end) { + return; + } + int duration = (int) (end - start)/44100; + int position = (int) (curr - start)/44100; + int remain = duration - position; + printf("audio progress (min:sec): %3d:%2.2d; remaining: %3d:%2.2d; track length %d:%2.2d\r", + position/60, position%60, remain/60, remain%60, duration/60, duration%60); + fflush(NULL); +} + +static gboolean progress_callback (gpointer loop) { + if (monitor_progress) { + if (rtptime_start || rtptime_end) { + display_progress(rtptime_start, rtptime, rtptime_end); + } + return TRUE; + } else { + progress_id = 0; + return FALSE; + } +} + #define MAX_VIDEO_RENDERERS 3 #define MAX_AUDIO_RENDERERS 2 static void main_loop() { @@ -565,6 +594,7 @@ static void main_loop() { guint gst_audio_bus_watch_id[MAX_AUDIO_RENDERERS] = { 0 }; GMainLoop *loop = g_main_loop_new(NULL,FALSE); relaunch_video = false; + monitor_progress = false; reset_loop = false; reset_httpd = false; preserve_connections = false; @@ -593,6 +623,10 @@ static void main_loop() { } } if (use_audio) { + rtptime_start = 0; + rtptime_end = 0; + monitor_progress = true; + progress_id = g_timeout_add_seconds(1,(GSourceFunc) progress_callback, (gpointer) loop); n_audio_renderers = 2; g_assert(n_audio_renderers <= MAX_AUDIO_RENDERERS); for (int i = 0; i < n_audio_renderers; i++) { @@ -618,6 +652,7 @@ static void main_loop() { if (sigint_watch_id > 0) g_source_remove(sigint_watch_id); if (sigterm_watch_id > 0) g_source_remove(sigterm_watch_id); if (reset_watch_id > 0) g_source_remove(reset_watch_id); + if (progress_id > 0) g_source_remove(progress_id); if (video_reset_watch_id > 0) g_source_remove(video_reset_watch_id); if (feedback_watch_id > 0) g_source_remove(feedback_watch_id); g_main_loop_unref(loop); @@ -1944,12 +1979,15 @@ extern "C" void audio_process (void *cls, raop_ntp_t *ntp, audio_decode_struct * data->ntp_time_remote = data->ntp_time_remote + remote_clock_offset; switch (data->ct) { case 2: + /* for progress monitor (ALAC audio only) */ + rtptime = data->rtp_time; if (audio_delay_alac) { data->ntp_time_remote = (uint64_t) ((int64_t) data->ntp_time_remote + audio_delay_alac); } break; case 4: case 8: + monitor_progress = false; if (audio_delay_aac) { data->ntp_time_remote = (uint64_t) ((int64_t) data->ntp_time_remote + audio_delay_aac); } @@ -2133,12 +2171,11 @@ extern "C" void audio_stop_coverart_rendering(void *cls) { } } -extern "C" void audio_set_progress(void *cls, unsigned int start, unsigned int curr, unsigned int end) { - int duration = (int) (end - start)/44100; - int position = (int) (curr - start)/44100; - int remain = duration - position; - printf("audio progress (min:sec): %d:%2.2d; remaining: %d:%2.2d; track length %d:%2.2d\n", - position/60, position%60, remain/60, remain%60, duration/60, duration%60); +extern "C" void audio_set_progress(void *cls, uint32_t *start, uint32_t *curr, uint32_t *end) { + rtptime_start = *start; + rtptime = *curr; + rtptime_end = *end; + display_progress(rtptime_start, rtptime, rtptime_end); } extern "C" void audio_set_metadata(void *cls, const void *buffer, int buflen) { @@ -2147,7 +2184,7 @@ extern "C" void audio_set_metadata(void *cls, const void *buffer, int buflen) { int datalen; int count = 0; - printf("==============Audio Metadata=============\n"); + printf("====================Audio Metadata==================\n"); if (buflen < 8) { LOGE("received invalid metadata, length %d < 8", buflen);