From 2b0da9125a97cc5f6e1f4f127a7cd74768bcc3c3 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Wed, 6 Aug 2025 07:14:33 -0400 Subject: [PATCH 01/58] cleanup the -pw (no argument) random pw option --- lib/httpd.c | 6 +++--- lib/raop_handlers.h | 34 ++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/lib/httpd.c b/lib/httpd.c index 9a4b990..bfc554b 100644 --- a/lib/httpd.c +++ b/lib/httpd.c @@ -216,6 +216,8 @@ httpd_remove_connection(httpd_t *httpd, http_connection_t *connection) int ret = closesocket(connection->socket_fd); if (ret == -1) { logger_log(httpd->logger, LOGGER_ERR, "httpd error in closesocket (close): %d %s", errno, strerror(errno)); + } else { + logger_log(httpd->logger, LOGGER_INFO, "Connection closed on socket %d", connection->socket_fd); } connection->socket_fd = 0; } @@ -464,7 +466,7 @@ httpd_thread(void *arg) while (readstart < 8) { ret = recv(connection->socket_fd, buffer + readstart, sizeof(buffer) - 1 - readstart, 0); if (ret == 0) { - logger_log(httpd->logger, LOGGER_INFO, "Connection closed for socket %d", + logger_log(httpd->logger, LOGGER_DEBUG, "client closed connection on socket %d", connection->socket_fd); break; } else if (ret == -1) { @@ -487,8 +489,6 @@ httpd_thread(void *arg) } else { ret = recv(connection->socket_fd, buffer, sizeof(buffer) - 1, 0); if (ret == 0) { - logger_log(httpd->logger, LOGGER_INFO, "Connection closed for socket %d", - connection->socket_fd); httpd_remove_connection(httpd, connection); continue; } diff --git a/lib/raop_handlers.h b/lib/raop_handlers.h index 4dcfbab..00ce5ac 100644 --- a/lib/raop_handlers.h +++ b/lib/raop_handlers.h @@ -26,7 +26,7 @@ #define AUDIO_SAMPLE_RATE 44100 /* all supported AirPlay audio format use this sample rate */ #define SECOND_IN_USECS 1000000 #define SECOND_IN_NSECS 1000000000 -#define MAX_PW_ATTEMPTS 5 +#define MAX_PW_ATTEMPTS 3 typedef void (*raop_handler_t)(raop_conn_t *, http_request_t *, http_response_t *, char **, int *); @@ -593,15 +593,21 @@ raop_handler_setup(raop_conn_t *conn, /* RFC2617 Digest authentication (md5 hash) of uxplay client-access password, if set */ if (!conn->authenticated && conn->raop->callbacks.passwd) { size_t pin_len = 4; - if (conn->raop->random_pw && strncmp(conn->raop->random_pw + pin_len + 1, deviceID, 17)) { - conn->raop->auth_fail_count = MAX_PW_ATTEMPTS; + const char *authorization = NULL; + authorization = http_request_get_header(request, "Authorization"); + if (!authorization) { + // if random_pw is set, but client has changed, unset it + if (conn->raop->random_pw && strncmp(conn->raop->random_pw + pin_len + 1, deviceID, 17)) { + free(conn->raop->random_pw); + conn->raop->random_pw = NULL; + } } int len; const char *password = conn->raop->callbacks.passwd(conn->raop->callbacks.cls, &len); // len = -1 means use a random password for this connection; len = 0 means no password if (len == -1 && conn->raop->random_pw && conn->raop->auth_fail_count >= MAX_PW_ATTEMPTS) { // change random_pw after MAX_PW_ATTEMPTS failed authentication attempts - logger_log(conn->raop->logger, LOGGER_INFO, "Too many authentication failures or new client: generate new random password"); + logger_log(conn->raop->logger, LOGGER_INFO, "Too many authentication failures: generate new random password"); free(conn->raop->random_pw); conn->raop->random_pw = NULL; } @@ -618,10 +624,13 @@ raop_handler_setup(raop_conn_t *conn, pin[pin_len] = '\0'; snprintf(pin + pin_len + 1, 18, "%s", deviceID); conn->raop->auth_fail_count = 0; + } + if (len == -1 && !authorization && conn->raop->random_pw) { if (conn->raop->callbacks.display_pin) { - conn->raop->callbacks.display_pin(conn->raop->callbacks.cls, pin); + conn->raop->callbacks.display_pin(conn->raop->callbacks.cls, conn->raop->random_pw); } - logger_log(conn->raop->logger, LOGGER_INFO, "*** CLIENT MUST NOW ENTER PIN = \"%s\" AS AIRPLAY PASSWORD", pin); + logger_log(conn->raop->logger, LOGGER_INFO, "*** CLIENT MUST NOW ENTER PIN = \"%s\" AS AIRPLAY PASSWORD", conn->raop->random_pw); + conn->raop->auth_fail_count++; } if (len && !conn->authenticated) { if (len == -1) { @@ -629,20 +638,17 @@ raop_handler_setup(raop_conn_t *conn, } char nonce_string[33] = { '\0' }; //bool stale = false; //not implemented - const char *authorization = NULL; - authorization = http_request_get_header(request, "Authorization"); - if (authorization) { + if (len && authorization) { char *ptr = strstr(authorization, "nonce=\"") + strlen("nonce=\""); strncpy(nonce_string, ptr, 32); const char *method = http_request_get_method(request); conn->authenticated = pairing_digest_verify(method, authorization, password); if (!conn->authenticated) { - conn->raop->auth_fail_count++; - logger_log(conn->raop->logger, LOGGER_INFO, "*** authentication failure: count = %u", conn->raop->auth_fail_count); - if (conn->raop->callbacks.display_pin && conn->raop->auth_fail_count > 1) { - conn->raop->callbacks.display_pin(conn->raop->callbacks.cls, conn->raop->random_pw); + // if random_pw is used, the auth_fail_count will be the number of times it is displayed after creation + if (len != -1) { + conn->raop->auth_fail_count++; } - logger_log(conn->raop->logger, LOGGER_INFO, "*** CLIENT MUST NOW ENTER PIN = \"%s\" AS AIRPLAY PASSWORD", conn->raop->random_pw); + logger_log(conn->raop->logger, LOGGER_INFO, "*** authentication failure: count = %u", conn->raop->auth_fail_count); } if (conn->authenticated) { //printf("initial authenticatication OK\n"); From 2436081088b2965a13773703e88a25792d034ec3 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Wed, 6 Aug 2025 09:23:35 -0400 Subject: [PATCH 02/58] README update to document -pw changes --- README.html | 27 +++++++++++++++++---------- README.md | 20 +++++++++++++++----- README.txt | 25 ++++++++++++++++--------- 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/README.html b/README.html index d647f50..6aeef12 100644 --- a/README.html +++ b/README.html @@ -1069,16 +1069,23 @@ options -restrict, -block, -allow for more ways to control client access). (Add a line “reg” in the startup file if you wish to use this feature.)

-pw [pwd]. (since 1.72). As an alternative -to -pin, client access can be controlled with a password set when uxplay -starts (set it in the .uxplay startup file, where it is stored as -cleartext.) All users must then know this password. This uses HTTP md5 -Digest authentication, which is now regarded as providing weak security, -but it is only used to validate the uxplay password, and no user -credentials are exposed. If pwd is not -specified, a random 4-digit pin code is displayed, and must be entered -on the client at each new connection. Note: -pin -and -pw are alternatives: if both are specified at startup, the earlier -of these two options is discarded.

+to -pin, client access can be controlled with a password. If a password +pwd (of length at least six characters) is set when uxplay +starts (usually set in the startup file, where it is stored as +cleartext), all users must know this password to connect to UxPlay (the +client prompts for it). This method uses HTTP md5 Digest authentication, +which is now regarded as providing weak security, but it is only used to +validate the uxplay password, and no user credentials are exposed. After +a successful authentication, the client stores the password, and will +use it initially for future authentications without prompting, so long +as the UxPlay deviceID has not changed (this initial authentication will +fail if the UxPlay password has changed). If pwd is +not specified with the -pw option when UxPlay starts, a +new random 4-digit pin code is generated and displayed on the UxPlay +terminal for each new connection, and must be entered +on the client (there are three chances to enter it, before it is +changed). Note: -pin and -pw are alternatives: if both are specified +at startup, the earlier of these two options is discarded.

-vsync [x] (In Mirror mode:) this option (now the default) uses timestamps to synchronize audio with video on the server, with an optional audio delay in (decimal) diff --git a/README.md b/README.md index 2821164..2817808 100644 --- a/README.md +++ b/README.md @@ -1064,13 +1064,23 @@ deregisters the corresponding client (see options -restrict, -block, the startup file if you wish to use this feature.)* **-pw** [*pwd*]. (since 1.72). As an alternative to -pin, client access -can be controlled with a password set when uxplay starts (set it in -the .uxplay startup file, where it is stored as cleartext.) All users must -then know this password. This uses HTTP md5 Digest authentication, +can be controlled with a password. If a password *pwd* (of length at least +six characters) is set when uxplay +starts (usually set in the startup file, where it is stored as +cleartext), all users must know this password to connect to UxPlay +(the client prompts for it). +This method uses HTTP md5 Digest authentication, which is now regarded as providing weak security, but it is only used to validate the uxplay password, and no user credentials are exposed. -If *pwd* is **not** specified, a random 4-digit pin code is displayed, and must -be entered on the client at **each** new connection. +After a successful authentication, the client stores the password, and will use +it initially for future authentications without prompting, so long as +the UxPlay deviceID has not changed (this initial authentication will fail +if the UxPlay password has changed). +If *pwd* is **not** specified with the -pw option when UxPlay starts, a +new random 4-digit pin code is generated and displayed on the UxPlay terminal +for **each** new connection, and must +be entered on the client (there are three +chances to enter it, before it is changed). _Note: -pin and -pw are alternatives: if both are specified at startup, the earlier of these two options is discarded._ diff --git a/README.txt b/README.txt index c2283ef..8e84d2d 100644 --- a/README.txt +++ b/README.txt @@ -1083,15 +1083,22 @@ deregisters the corresponding client (see options -restrict, -block, the startup file if you wish to use this feature.)* **-pw** \[*pwd*\]. (since 1.72). As an alternative to -pin, client -access can be controlled with a password set when uxplay starts (set it -in the .uxplay startup file, where it is stored as cleartext.) All users -must then know this password. This uses HTTP md5 Digest authentication, -which is now regarded as providing weak security, but it is only used to -validate the uxplay password, and no user credentials are exposed. If -*pwd* is **not** specified, a random 4-digit pin code is displayed, and -must be entered on the client at **each** new connection. *Note: -pin -and -pw are alternatives: if both are specified at startup, the earlier -of these two options is discarded.* +access can be controlled with a password. If a password *pwd* (of length +at least six characters) is set when uxplay starts (usually set in the +startup file, where it is stored as cleartext), all users must know this +password to connect to UxPlay (the client prompts for it). This method +uses HTTP md5 Digest authentication, which is now regarded as providing +weak security, but it is only used to validate the uxplay password, and +no user credentials are exposed. After a successful authentication, the +client stores the password, and will use it initially for future +authentications without prompting, so long as the UxPlay deviceID has +not changed (this initial authentication will fail if the UxPlay +password has changed). If *pwd* is **not** specified with the -pw option +when UxPlay starts, a new random 4-digit pin code is generated and +displayed on the UxPlay terminal for **each** new connection, and must +be entered on the client (there are three chances to enter it, before it +is changed). *Note: -pin and -pw are alternatives: if both are specified +at startup, the earlier of these two options is discarded.* **-vsync \[x\]** (In Mirror mode:) this option (**now the default**) uses timestamps to synchronize audio with video on the server, with an From 93b2612477b1086262fd1b83be651c35274156a3 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Wed, 6 Aug 2025 16:29:11 -0400 Subject: [PATCH 03/58] uxplay.cpp update number of bus watches for jpeg renderer --- uxplay.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/uxplay.cpp b/uxplay.cpp index 48f3a3b..f12e1ec 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -464,8 +464,8 @@ static guint g_unix_signal_add(gint signum, GSourceFunc handler, gpointer user_d #endif static void main_loop() { - guint gst_bus_watch_id[2] = { 0 }; - g_assert(n_renderers <= 2); + guint gst_bus_watch_id[3] = { 0 }; + g_assert(n_renderers <= 3); GMainLoop *loop = g_main_loop_new(NULL,FALSE); relaunch_video = false; reset_loop = false; @@ -474,10 +474,11 @@ static void main_loop() { if (use_video) { relaunch_video = true; if (url.empty()) { - n_renderers = h265_support ? 2 : 1; + /* renderer[0] : jpeg coverart; renderer[1] h264 video; renderer[2] h265 video (optional) */ + n_renderers = h265_support ? 3 : 2; gst_x11_window_id = 0; } else { - /* hls video will be rendered */ + /* hls video will be rendered: renderer[0] : hls */ n_renderers = 1; url.erase(); gst_x11_window_id = g_timeout_add(100, (GSourceFunc) x11_window_callback, (gpointer) loop); From 532ac612f35af96cff28ecd8384d7c7f0cd87fd0 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Thu, 7 Aug 2025 06:10:19 -0400 Subject: [PATCH 04/58] add message handler for audio pipeline bus --- renderers/audio_renderer.c | 43 +++++++++++++++++++++++++++++++++++++- renderers/audio_renderer.h | 2 +- renderers/video_renderer.c | 8 +++---- uxplay.cpp | 31 +++++++++++++++++++-------- 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/renderers/audio_renderer.c b/renderers/audio_renderer.c index c390e68..5075018 100644 --- a/renderers/audio_renderer.c +++ b/renderers/audio_renderer.c @@ -45,6 +45,7 @@ typedef struct audio_renderer_s { GstElement *appsrc; GstElement *pipeline; GstElement *volume; + GstBus *bus; unsigned char ct; } audio_renderer_t ; static audio_renderer_t *renderer_type[NFORMATS]; @@ -186,7 +187,7 @@ void audio_renderer_init(logger_t *render_logger, const char* audiosink, const b g_assert (renderer_type[i]->pipeline); gst_pipeline_use_clock(GST_PIPELINE_CAST(renderer_type[i]->pipeline), clock); - + renderer_type[i]->bus = gst_element_get_bus(renderer_type[i]->pipeline); renderer_type[i]->appsrc = gst_bin_get_by_name (GST_BIN (renderer_type[i]->pipeline), "audio_source"); renderer_type[i]->volume = gst_bin_get_by_name (GST_BIN (renderer_type[i]->pipeline), "volume"); switch (i) { @@ -367,6 +368,8 @@ void audio_renderer_flush() { void audio_renderer_destroy() { audio_renderer_stop(); for (int i = 0; i < NFORMATS ; i++ ) { + gst_object_unref (renderer_type[i]->bus); + renderer_type[i]->bus = NULL; gst_object_unref (renderer_type[i]->volume); renderer_type[i]->volume = NULL; gst_object_unref (renderer_type[i]->appsrc); @@ -376,3 +379,41 @@ void audio_renderer_destroy() { free(renderer_type[i]); } } + +static gboolean gstreamer_audio_pipeline_bus_callback(GstBus *bus, GstMessage *message, void *loop) { + switch (GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_ERROR: { + GError *err; + gchar *debug; + gst_message_parse_error (message, &err, &debug); + logger_log(logger, LOGGER_INFO, "GStreamer error (audio): %s %s", GST_MESSAGE_SRC_NAME(message),err->message); + g_error_free(err); + g_free(debug); + if (renderer->appsrc) { + gst_app_src_end_of_stream (GST_APP_SRC(renderer->appsrc)); + } + gst_bus_set_flushing(bus, TRUE); + gst_element_set_state (renderer->pipeline, GST_STATE_READY); + g_main_loop_quit( (GMainLoop *) loop); + break; + } + case GST_MESSAGE_EOS: + logger_log(logger, LOGGER_INFO, "GStreamer: End-Of-Stream (audio)"); + break; + case GST_MESSAGE_ELEMENT: + // many "level" messages may be sent + break; + default: + /* unhandled message */ + logger_log(logger, LOGGER_DEBUG,"GStreamer unhandled audio bus message: src = %s type = %s", + GST_MESSAGE_SRC_NAME(message), GST_MESSAGE_TYPE_NAME(message)); + break; + } + return TRUE; +} + +unsigned int audio_renderer_listen(void *loop, int id) { + g_assert(id >= 0 && id < NFORMATS); + return (unsigned int) gst_bus_add_watch(renderer_type[id]->bus,(GstBusFunc) + gstreamer_audio_pipeline_bus_callback, (gpointer) loop); +} diff --git a/renderers/audio_renderer.h b/renderers/audio_renderer.h index 232da28..d981e20 100644 --- a/renderers/audio_renderer.h +++ b/renderers/audio_renderer.h @@ -40,7 +40,7 @@ void audio_renderer_render_buffer(unsigned char* data, int *data_len, unsigned s void audio_renderer_set_volume(double volume); void audio_renderer_flush(); void audio_renderer_destroy(); - +unsigned int audio_renderer_listen(void *loop, int id); #ifdef __cplusplus } #endif diff --git a/renderers/video_renderer.c b/renderers/video_renderer.c index c701c88..7e04753 100644 --- a/renderers/video_renderer.c +++ b/renderers/video_renderer.c @@ -647,7 +647,7 @@ static void get_stream_status_name(GstStreamStatusType type, char *name, size_t } } -gboolean gstreamer_pipeline_bus_callback(GstBus *bus, GstMessage *message, void *loop) { +static gboolean gstreamer_video_pipeline_bus_callback(GstBus *bus, GstMessage *message, void *loop) { GstState old_state, new_state; const gchar no_state[] = ""; const gchar *old_state_name = no_state, *new_state_name = no_state; @@ -756,7 +756,7 @@ gboolean gstreamer_pipeline_bus_callback(GstBus *bus, GstMessage *message, void gchar *debug; gboolean flushing; gst_message_parse_error (message, &err, &debug); - logger_log(logger, LOGGER_INFO, "GStreamer error: %s %s", GST_MESSAGE_SRC_NAME(message),err->message); + logger_log(logger, LOGGER_INFO, "GStreamer error (video): %s %s", GST_MESSAGE_SRC_NAME(message),err->message); if (!hls_video && strstr(err->message,"Internal data stream error")) { logger_log(logger, LOGGER_INFO, "*** This is a generic GStreamer error that usually means that GStreamer\n" @@ -780,7 +780,7 @@ gboolean gstreamer_pipeline_bus_callback(GstBus *bus, GstMessage *message, void } case GST_MESSAGE_EOS: /* end-of-stream */ - logger_log(logger, LOGGER_INFO, "GStreamer: End-Of-Stream"); + logger_log(logger, LOGGER_INFO, "GStreamer: End-Of-Stream (video)"); if (hls_video) { gst_bus_set_flushing(bus, TRUE); gst_element_set_state (renderer_type[type]->pipeline, GST_STATE_READY); @@ -1007,5 +1007,5 @@ void video_renderer_seek(float position) { unsigned int video_renderer_listen(void *loop, int id) { g_assert(id >= 0 && id < n_renderers); return (unsigned int) gst_bus_add_watch(renderer_type[id]->bus,(GstBusFunc) - gstreamer_pipeline_bus_callback, (gpointer) loop); + gstreamer_video_pipeline_bus_callback, (gpointer) loop); } diff --git a/uxplay.cpp b/uxplay.cpp index f12e1ec..c3b41fb 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -164,7 +164,8 @@ static double db_high = 0.0; static bool taper_volume = false; static double initial_volume = 0.0; static bool h265_support = false; -static int n_renderers = 0; +static int n_video_renderers = 0; +static int n_audio_renderers = 0; static bool hls_support = false; static std::string url = ""; static guint gst_x11_window_id = 0; @@ -464,8 +465,10 @@ static guint g_unix_signal_add(gint signum, GSourceFunc handler, gpointer user_d #endif static void main_loop() { - guint gst_bus_watch_id[3] = { 0 }; - g_assert(n_renderers <= 3); + guint gst_video_bus_watch_id[3] = { 0 }; + g_assert(n_video_renderers <= 3); + guint gst_audio_bus_watch_id[2] = { 0 }; + g_assert(n_audio_renderers <= 2); GMainLoop *loop = g_main_loop_new(NULL,FALSE); relaunch_video = false; reset_loop = false; @@ -475,18 +478,25 @@ static void main_loop() { relaunch_video = true; if (url.empty()) { /* renderer[0] : jpeg coverart; renderer[1] h264 video; renderer[2] h265 video (optional) */ - n_renderers = h265_support ? 3 : 2; + n_video_renderers = h265_support ? 3 : 2; gst_x11_window_id = 0; } else { /* hls video will be rendered: renderer[0] : hls */ - n_renderers = 1; + n_video_renderers = 1; url.erase(); gst_x11_window_id = g_timeout_add(100, (GSourceFunc) x11_window_callback, (gpointer) loop); } - for (int i = 0; i < n_renderers; i++) { - gst_bus_watch_id[i] = (guint) video_renderer_listen((void *)loop, i); + for (int i = 0; i < n_video_renderers; i++) { + gst_video_bus_watch_id[i] = (guint) video_renderer_listen((void *)loop, i); } } + if (use_audio) { + n_audio_renderers = 2; + for (int i = 0; i < n_audio_renderers; i++) { + gst_audio_bus_watch_id[i] = (guint) audio_renderer_listen((void *)loop, i); + } + } + missed_feedback = 0; guint feedback_watch_id = g_timeout_add_seconds(1, (GSourceFunc) feedback_callback, (gpointer) loop); guint reset_watch_id = g_timeout_add(100, (GSourceFunc) reset_callback, (gpointer) loop); @@ -495,8 +505,11 @@ static void main_loop() { guint sigint_watch_id = g_unix_signal_add(SIGINT, (GSourceFunc) sigint_callback, (gpointer) loop); g_main_loop_run(loop); - for (int i = 0; i < n_renderers; i++) { - if (gst_bus_watch_id[i] > 0) g_source_remove(gst_bus_watch_id[i]); + for (int i = 0; i < n_video_renderers; i++) { + if (gst_video_bus_watch_id[i] > 0) g_source_remove(gst_video_bus_watch_id[i]); + } + for (int i = 0; i < n_audio_renderers; i++) { + if (gst_audio_bus_watch_id[i] > 0) g_source_remove(gst_audio_bus_watch_id[i]); } if (gst_x11_window_id > 0) g_source_remove(gst_x11_window_id); if (sigint_watch_id > 0) g_source_remove(sigint_watch_id); From 56bdfbbda8731d6186c9ca5faea9a2b523cca2fa Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Thu, 7 Aug 2025 07:09:56 -0400 Subject: [PATCH 05/58] video_renderer.c: add bus to renderer in video_renderer_init --- renderers/video_renderer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/renderers/video_renderer.c b/renderers/video_renderer.c index 7e04753..1ba220f 100644 --- a/renderers/video_renderer.c +++ b/renderers/video_renderer.c @@ -267,6 +267,7 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, vide renderer_type[i]->autovideo = auto_videosink; renderer_type[i]->id = i; renderer_type[i]->bus = NULL; + renderer_type[i]->appsrc = NULL; if (hls_video) { /* use playbin3 to play HLS video: replace "playbin3" by "playbin" to use playbin2 */ switch (playbin_version) { @@ -282,7 +283,6 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, vide } logger_log(logger, LOGGER_INFO, "Will use GStreamer playbin version %u to play HLS streamed video", playbin_version); g_assert(renderer_type[i]->pipeline); - renderer_type[i]->appsrc = NULL; renderer_type[i]->codec = hls; /* if we are not using an autovideosink, build a videosink based on the string "videosink" */ if (!auto_videosink) { @@ -377,7 +377,6 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, vide g_clear_error (&error); } g_assert (renderer_type[i]->pipeline); - GstClock *clock = gst_system_clock_obtain(); g_object_set(clock, "clock-type", GST_CLOCK_TYPE_REALTIME, NULL); gst_pipeline_use_clock(GST_PIPELINE_CAST(renderer_type[i]->pipeline), clock); @@ -417,6 +416,7 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, vide } } #endif + renderer_type[i]->bus = gst_element_get_bus(renderer_type[i]->pipeline); gst_element_set_state (renderer_type[i]->pipeline, GST_STATE_READY); GstState state; if (gst_element_get_state (renderer_type[i]->pipeline, &state, NULL, 100 * GST_MSECOND)) { @@ -461,7 +461,6 @@ void video_renderer_start() { GstState state; const gchar *state_name; if (hls_video) { - renderer->bus = gst_element_get_bus(renderer->pipeline); gst_element_set_state (renderer->pipeline, GST_STATE_PAUSED); gst_element_get_state(renderer->pipeline, &state, NULL, 1000 * GST_MSECOND); state_name= gst_element_state_get_name(state); @@ -470,7 +469,6 @@ void video_renderer_start() { } /* when not hls, start both h264 and h265 pipelines; will shut down the "wrong" one when we know the codec */ for (int i = 0; i < n_renderers; i++) { - renderer_type[i]->bus = gst_element_get_bus(renderer_type[i]->pipeline); gst_element_set_state (renderer_type[i]->pipeline, GST_STATE_PAUSED); gst_element_get_state(renderer_type[i]->pipeline, &state, NULL, 1000 * GST_MSECOND); state_name= gst_element_state_get_name(state); From 3e1d83d7d68a63c5df7b2ad1b8747c9b0adfdd67 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Thu, 7 Aug 2025 16:14:18 -0400 Subject: [PATCH 06/58] cleanup in video_renderer.c --- renderers/video_renderer.c | 27 +++++++++++++++++---------- uxplay.cpp | 2 +- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/renderers/video_renderer.c b/renderers/video_renderer.c index 1ba220f..4086312 100644 --- a/renderers/video_renderer.c +++ b/renderers/video_renderer.c @@ -472,7 +472,7 @@ void video_renderer_start() { gst_element_set_state (renderer_type[i]->pipeline, GST_STATE_PAUSED); gst_element_get_state(renderer_type[i]->pipeline, &state, NULL, 1000 * GST_MSECOND); state_name= gst_element_state_get_name(state); - logger_log(logger, LOGGER_DEBUG, "video renderer_start: renderer %d state %s", i, state_name); + logger_log(logger, LOGGER_DEBUG, "video renderer_start: renderer %d %p state %s", i, renderer_type[i], state_name); } renderer = NULL; first_packet = true; @@ -537,6 +537,10 @@ uint64_t video_renderer_render_buffer(unsigned char* data, int *data_len, int *n logger_log(logger, LOGGER_INFO, "Begin streaming to GStreamer video pipeline"); first_packet = false; } + if (!renderer || !(renderer->appsrc)) { + logger_log(logger, LOGGER_DEBUG, "*** no video renderer found"); + return 0; + } buffer = gst_buffer_new_allocate(NULL, *data_len, NULL); g_assert(buffer != NULL); //g_print("video latency %8.6f\n", (double) latency / SECOND_IN_NSECS); @@ -582,21 +586,23 @@ static void video_renderer_destroy_instance(video_renderer_t *renderer) { GstState state; GstStateChangeReturn ret; gst_element_get_state(renderer->pipeline, &state, NULL, 100 * GST_MSECOND); - logger_log(logger, LOGGER_DEBUG,"pipeline state is %s", gst_element_state_get_name(state)); + logger_log(logger, LOGGER_DEBUG,"pipeline state is %s", gst_element_state_get_name(state)); if (state != GST_STATE_NULL) { if (!hls_video) { gst_app_src_end_of_stream (GST_APP_SRC(renderer->appsrc)); } ret = gst_element_set_state (renderer->pipeline, GST_STATE_NULL); - logger_log(logger, LOGGER_DEBUG,"pipeline_state_change_return: %s", - gst_element_state_change_return_get_name(ret)); - gst_element_get_state(renderer->pipeline, NULL, NULL, 1000 * GST_MSECOND); + logger_log(logger, LOGGER_DEBUG,"pipeline_state_change_return: %s", + gst_element_state_change_return_get_name(ret)); + gst_element_get_state(renderer->pipeline, &state, NULL, 1000 * GST_MSECOND); + logger_log(logger, LOGGER_DEBUG,"pipeline state is %s", gst_element_state_get_name(state)); + } + if (renderer->appsrc) { + gst_object_unref (renderer->appsrc); + renderer->appsrc = NULL; } gst_object_unref(renderer->bus); - if (renderer->appsrc) { - gst_object_unref (renderer->appsrc); - } - gst_object_unref (renderer->pipeline); + gst_object_unref(renderer->pipeline); #ifdef X_DISPLAY_FIX if (renderer->gst_window) { free(renderer->gst_window); @@ -605,6 +611,7 @@ static void video_renderer_destroy_instance(video_renderer_t *renderer) { #endif free (renderer); renderer = NULL; + logger_log(logger, LOGGER_DEBUG,"renderer destroyed\n"); } } @@ -908,7 +915,7 @@ int video_renderer_choose_codec (bool video_is_jpeg, bool video_is_h265) { logger_log(logger, LOGGER_INFO, "*** video format is h265 high definition (HD/4K) video %dx%d", width, height); } /* destroy unused renderers */ - for (int i = 1; i < n_renderers; i++) { + for (int i = 0; i < n_renderers; i++) { if (renderer_type[i] == renderer) { continue; } diff --git a/uxplay.cpp b/uxplay.cpp index c3b41fb..c276103 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -2632,7 +2632,7 @@ int main (int argc, char *argv[]) { url.erase(); raop_remove_known_connections(raop); } - const char *uri = (url.empty() ? NULL : url.c_str()); + const char *uri = (url.empty() ? NULL : url.c_str()); video_renderer_init(render_logger, server_name.c_str(), videoflip, video_parser.c_str(), video_decoder.c_str(), video_converter.c_str(), videosink.c_str(), videosink_options.c_str(), fullscreen, video_sync, h265_support, playbin_version, uri); From c8ce350226473576959ea1165cdc2ad03394372f Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Fri, 8 Aug 2025 11:03:47 -0400 Subject: [PATCH 07/58] raop : whitespace cleanup --- lib/raop_handlers.h | 365 +++++++++++++++++++++--------------------- lib/raop_ntp.c | 2 +- lib/raop_rtp.c | 45 +++--- lib/raop_rtp_mirror.c | 52 +++--- 4 files changed, 233 insertions(+), 231 deletions(-) diff --git a/lib/raop_handlers.h b/lib/raop_handlers.h index 00ce5ac..1e7649b 100644 --- a/lib/raop_handlers.h +++ b/lib/raop_handlers.h @@ -60,9 +60,9 @@ raop_handler_info(raop_conn_t *conn, printf("qualifier: %s\n", qualifier_string); txtAirPlay = true; } - if (qualifier_string) { + if (qualifier_string) { free(qualifier_string); - } + } } #endif plist_t res_node = plist_new_dict(); @@ -265,9 +265,9 @@ raop_handler_pairsetup_pin(raop_conn_t *conn, if (PLIST_IS_STRING(req_method_node) && PLIST_IS_STRING(req_user_node)) { /* this is the initial pair-setup-pin request */ const char *salt; - char pin[6]; - const char *pk; - int len_pk, len_salt; + char pin[6]; + const char *pk; + int len_pk, len_salt; char *method = NULL; char *user = NULL; plist_get_string_val(req_method_node, &method); @@ -280,13 +280,13 @@ raop_handler_pairsetup_pin(raop_conn_t *conn, return; } free (method); - plist_get_string_val(req_user_node, &user); + plist_get_string_val(req_user_node, &user); logger_log(conn->raop->logger, LOGGER_INFO, "pair-setup-pin: device_id = %s", user); snprintf(pin, 6, "%04u", conn->raop->pin % 10000); if (conn->raop->pin < 10000) { conn->raop->pin = 0; } - int ret = srp_new_user(conn->session, conn->raop->pairing, (const char *) user, + int ret = srp_new_user(conn->session, conn->raop->pairing, (const char *) user, (const char *) pin, &salt, &len_salt, &pk, &len_pk); free(user); plist_free(req_root_node); @@ -302,19 +302,19 @@ raop_handler_pairsetup_pin(raop_conn_t *conn, plist_to_bin(res_root_node, response_data, (uint32_t*) response_datalen); plist_free(res_root_node); http_response_add_header(response, "Content-Type", "application/x-apple-binary-plist"); - return; + return; } else if (PLIST_IS_DATA(req_pk_node) && PLIST_IS_DATA(req_proof_node)) { /* this is the second part of pair-setup-pin request */ char *client_pk = NULL; char *client_proof = NULL; - unsigned char proof[64]; - memset(proof, 0, sizeof(proof)); + unsigned char proof[64]; + memset(proof, 0, sizeof(proof)); uint64_t client_pk_len; uint64_t client_proof_len; plist_get_data_val(req_pk_node, &client_pk, &client_pk_len); plist_get_data_val(req_proof_node, &client_proof, &client_proof_len); if (logger_debug) { - char *str = utils_data_to_string((const unsigned char *) client_proof, client_proof_len, 20); + char *str = utils_data_to_string((const unsigned char *) client_proof, client_proof_len, 20); logger_log(conn->raop->logger, LOGGER_DEBUG, "client SRP6a proof :\n%s", str); free (str); } @@ -339,7 +339,7 @@ raop_handler_pairsetup_pin(raop_conn_t *conn, plist_to_bin(res_root_node, response_data, (uint32_t*) response_datalen); plist_free(res_root_node); http_response_add_header(response, "Content-Type", "application/x-apple-binary-plist"); - return; + return; } else if (PLIST_IS_DATA(req_epk_node) && PLIST_IS_DATA(req_authtag_node)) { /* this is the third part of pair-setup-pin request */ char *client_epk = NULL; @@ -347,25 +347,25 @@ raop_handler_pairsetup_pin(raop_conn_t *conn, uint64_t client_epk_len; uint64_t client_authtag_len; unsigned char epk[ED25519_KEY_SIZE]; - unsigned char authtag[GCM_AUTHTAG_SIZE]; - int ret; + unsigned char authtag[GCM_AUTHTAG_SIZE]; + int ret; plist_get_data_val(req_epk_node, &client_epk, &client_epk_len); plist_get_data_val(req_authtag_node, &client_authtag, &client_authtag_len); - if (logger_debug) { + if (logger_debug) { char *str = utils_data_to_string((const unsigned char *) client_epk, client_epk_len, 16); logger_log(conn->raop->logger, LOGGER_DEBUG, "client_epk %d:\n%s\n", (int) client_epk_len, str); str = utils_data_to_string((const unsigned char *) client_authtag, client_authtag_len, 16); logger_log(conn->raop->logger, LOGGER_DEBUG, "client_authtag %d:\n%s\n", (int) client_authtag_len, str); free (str); - } + } - memcpy(epk, client_epk, ED25519_KEY_SIZE); - memcpy(authtag, client_authtag, GCM_AUTHTAG_SIZE); + memcpy(epk, client_epk, ED25519_KEY_SIZE); + memcpy(authtag, client_authtag, GCM_AUTHTAG_SIZE); free (client_authtag); free (client_epk); plist_free(req_root_node); - ret = srp_confirm_pair_setup(conn->session, conn->raop->pairing, epk, authtag); + ret = srp_confirm_pair_setup(conn->session, conn->raop->pairing, epk, authtag); if (ret < 0) { logger_log(conn->raop->logger, LOGGER_ERR, "pair-pin-setup (step 3): client authentication failed\n"); goto authentication_failed; @@ -375,13 +375,13 @@ raop_handler_pairsetup_pin(raop_conn_t *conn, pairing_session_set_setup_status(conn->session); plist_t res_root_node = plist_new_dict(); plist_t res_epk_node = plist_new_data((const char *) epk, 32); - plist_t res_authtag_node = plist_new_data((const char *) authtag, 16); + plist_t res_authtag_node = plist_new_data((const char *) authtag, 16); plist_dict_set_item(res_root_node, "epk", res_epk_node); plist_dict_set_item(res_root_node, "authTag", res_authtag_node); plist_to_bin(res_root_node, response_data, (uint32_t*) response_datalen); plist_free(res_root_node); http_response_add_header(response, "Content-Type", "application/x-apple-binary-plist"); - return; + return; } authentication_failed:; http_response_init(response, "RTSP/1.0", 470, "Client Authentication Failure"); @@ -439,58 +439,58 @@ raop_handler_pairverify(raop_conn_t *conn, return; } switch (data[0]) { - case 1: - if (datalen != 4 + X25519_KEY_SIZE + ED25519_KEY_SIZE) { - logger_log(conn->raop->logger, LOGGER_ERR, "Invalid pair-verify data"); - return; - } - /* We can fall through these errors, the result will just be garbage... */ - if (pairing_session_handshake(conn->session, data + 4, data + 4 + X25519_KEY_SIZE)) { - logger_log(conn->raop->logger, LOGGER_ERR, "Error initializing pair-verify handshake"); - } - if (pairing_session_get_public_key(conn->session, public_key)) { - logger_log(conn->raop->logger, LOGGER_ERR, "Error getting ECDH public key"); - } - if (pairing_session_get_signature(conn->session, signature)) { - logger_log(conn->raop->logger, LOGGER_ERR, "Error getting ED25519 signature"); - } - if (register_check) { - bool registered_client = true; - if (conn->raop->callbacks.check_register) { - const unsigned char *pk = data + 4 + X25519_KEY_SIZE; - char *pk64; - ed25519_pk_to_base64(pk, &pk64); - registered_client = conn->raop->callbacks.check_register(conn->raop->callbacks.cls, pk64); - free (pk64); - } - - if (!registered_client) { - return; - } - } - *response_data = malloc(sizeof(public_key) + sizeof(signature)); - if (*response_data) { - http_response_add_header(response, "Content-Type", "application/octet-stream"); - memcpy(*response_data, public_key, sizeof(public_key)); - memcpy(*response_data + sizeof(public_key), signature, sizeof(signature)); - *response_datalen = sizeof(public_key) + sizeof(signature); - } - break; - case 0: - logger_log(conn->raop->logger, LOGGER_DEBUG, "2nd pair-verify step: checking signature"); - if (datalen != 4 + PAIRING_SIG_SIZE) { - logger_log(conn->raop->logger, LOGGER_ERR, "Invalid pair-verify data"); - return; + case 1: + if (datalen != 4 + X25519_KEY_SIZE + ED25519_KEY_SIZE) { + logger_log(conn->raop->logger, LOGGER_ERR, "Invalid pair-verify data"); + return; + } + /* We can fall through these errors, the result will just be garbage... */ + if (pairing_session_handshake(conn->session, data + 4, data + 4 + X25519_KEY_SIZE)) { + logger_log(conn->raop->logger, LOGGER_ERR, "Error initializing pair-verify handshake"); + } + if (pairing_session_get_public_key(conn->session, public_key)) { + logger_log(conn->raop->logger, LOGGER_ERR, "Error getting ECDH public key"); + } + if (pairing_session_get_signature(conn->session, signature)) { + logger_log(conn->raop->logger, LOGGER_ERR, "Error getting ED25519 signature"); + } + if (register_check) { + bool registered_client = true; + if (conn->raop->callbacks.check_register) { + const unsigned char *pk = data + 4 + X25519_KEY_SIZE; + char *pk64; + ed25519_pk_to_base64(pk, &pk64); + registered_client = conn->raop->callbacks.check_register(conn->raop->callbacks.cls, pk64); + free (pk64); } - if (pairing_session_finish(conn->session, data + 4)) { - logger_log(conn->raop->logger, LOGGER_ERR, "Incorrect pair-verify signature"); - http_response_set_disconnect(response, 1); + if (!registered_client) { return; } - logger_log(conn->raop->logger, LOGGER_DEBUG, "pair-verify: signature is verified"); + } + *response_data = malloc(sizeof(public_key) + sizeof(signature)); + if (*response_data) { http_response_add_header(response, "Content-Type", "application/octet-stream"); - break; + memcpy(*response_data, public_key, sizeof(public_key)); + memcpy(*response_data + sizeof(public_key), signature, sizeof(signature)); + *response_datalen = sizeof(public_key) + sizeof(signature); + } + break; + case 0: + logger_log(conn->raop->logger, LOGGER_DEBUG, "2nd pair-verify step: checking signature"); + if (datalen != 4 + PAIRING_SIG_SIZE) { + logger_log(conn->raop->logger, LOGGER_ERR, "Invalid pair-verify data"); + return; + } + + if (pairing_session_finish(conn->session, data + 4)) { + logger_log(conn->raop->logger, LOGGER_ERR, "Incorrect pair-verify signature"); + http_response_set_disconnect(response, 1); + return; + } + logger_log(conn->raop->logger, LOGGER_DEBUG, "pair-verify: signature is verified"); + http_response_add_header(response, "Content-Type", "application/octet-stream"); + break; } } @@ -618,7 +618,7 @@ raop_handler_setup(raop_conn_t *conn, logger_log(conn->raop->logger, LOGGER_ERR, "Failed to generate random pin"); pin_4 = 1234; } - conn->raop->random_pw = (char *) malloc(pin_len + 1 + 18); + conn->raop->random_pw = (char *) malloc(pin_len + 1 + 18); char *pin = conn->raop->random_pw; snprintf(pin, pin_len + 1, "%04u", pin_4 % 10000); pin[pin_len] = '\0'; @@ -661,7 +661,7 @@ raop_handler_setup(raop_conn_t *conn, if (conn->authenticated && conn->raop->random_pw) { free (conn->raop->random_pw); conn->raop->random_pw = NULL; - } + } if (conn->raop->nonce) { free(conn->raop->nonce); conn->raop->nonce = NULL; @@ -691,17 +691,17 @@ raop_handler_setup(raop_conn_t *conn, char* eiv = NULL; uint64_t eiv_len = 0; - char *model = NULL; + char *model = NULL; char *name = NULL; bool admit_client = true; plist_t req_model_node = plist_dict_get_item(req_root_node, "model"); plist_get_string_val(req_model_node, &model); plist_t req_name_node = plist_dict_get_item(req_root_node, "name"); plist_get_string_val(req_name_node, &name); - if (conn->raop->callbacks.report_client_request) { + if (conn->raop->callbacks.report_client_request) { conn->raop->callbacks.report_client_request(conn->raop->callbacks.cls, deviceID, model, name, &admit_client); } - if (admit_client && deviceID && name && conn->raop->callbacks.register_client) { + if (admit_client && deviceID && name && conn->raop->callbacks.register_client) { char *client_device_id = NULL; char *client_pk = NULL; /* encoded as null-terminated base64 string, must be freed*/ get_pairing_session_client_data(conn->session, &client_device_id, &client_pk); @@ -709,7 +709,7 @@ raop_handler_setup(raop_conn_t *conn, conn->raop->callbacks.register_client(conn->raop->callbacks.cls, client_device_id, client_pk, name); free (client_pk); } - } + } if (deviceID) { free (deviceID); deviceID = NULL; @@ -727,17 +727,17 @@ raop_handler_setup(raop_conn_t *conn, plist_free(res_root_node); plist_free(req_root_node); return; - } + } plist_get_data_val(req_eiv_node, &eiv, &eiv_len); memcpy(aesiv, eiv, 16); free(eiv); logger_log(conn->raop->logger, LOGGER_DEBUG, "eiv_len = %llu", eiv_len); - if (logger_debug) { + if (logger_debug) { char* str = utils_data_to_string(aesiv, 16, 16); logger_log(conn->raop->logger, LOGGER_DEBUG, "16 byte aesiv (needed for AES-CBC audio decryption iv):\n%s", str); free(str); - } + } char* ekey = NULL; uint64_t ekey_len = 0; @@ -746,7 +746,7 @@ raop_handler_setup(raop_conn_t *conn, free(ekey); logger_log(conn->raop->logger, LOGGER_DEBUG, "ekey_len = %llu", ekey_len); // eaeskey is 72 bytes, aeskey is 16 bytes - if (logger_debug) { + if (logger_debug) { char *str = utils_data_to_string((unsigned char *) eaeskey, ekey_len, 16); logger_log(conn->raop->logger, LOGGER_DEBUG, "ekey:\n%s", str); free (str); @@ -814,9 +814,9 @@ raop_handler_setup(raop_conn_t *conn, logger_log(conn->raop->logger, LOGGER_ERR, "Client specified AirPlay2 \"Remote Control\" protocol\n" " Only AirPlay v1 protocol (using NTP and timing port) is supported"); } - } + } char *timing_protocol = NULL; - timing_protocol_t time_protocol = TP_NONE; + timing_protocol_t time_protocol = TP_NONE; plist_t req_timing_protocol_node = plist_dict_get_item(req_root_node, "timingProtocol"); plist_get_string_val(req_timing_protocol_node, &timing_protocol); if (timing_protocol) { @@ -841,7 +841,7 @@ raop_handler_setup(raop_conn_t *conn, } uint64_t timing_rport = 0; plist_t req_timing_port_node = plist_dict_get_item(req_root_node, "timingPort"); - if (req_timing_port_node) { + if (req_timing_port_node) { plist_get_uint_val(req_timing_port_node, &timing_rport); } if (timing_rport) { @@ -897,106 +897,107 @@ raop_handler_setup(raop_conn_t *conn, logger_log(conn->raop->logger, LOGGER_DEBUG, "type = %llu", type); switch (type) { - case 110: { - // Mirroring - unsigned short dport = conn->raop->mirror_data_lport; - plist_t stream_id_node = plist_dict_get_item(req_stream_node, "streamConnectionID"); - uint64_t stream_connection_id = 0; - plist_get_uint_val(stream_id_node, &stream_connection_id); - logger_log(conn->raop->logger, LOGGER_DEBUG, "streamConnectionID (needed for AES-CTR video decryption" - " key and iv): %llu", stream_connection_id); + case 110: { + // Mirroring + unsigned short dport = conn->raop->mirror_data_lport; + plist_t stream_id_node = plist_dict_get_item(req_stream_node, "streamConnectionID"); + uint64_t stream_connection_id = 0; + plist_get_uint_val(stream_id_node, &stream_connection_id); + logger_log(conn->raop->logger, LOGGER_DEBUG, "streamConnectionID (needed for AES-CTR video decryption" + " key and iv): %llu", stream_connection_id); - if (conn->raop_rtp_mirror) { - raop_rtp_mirror_init_aes(conn->raop_rtp_mirror, &stream_connection_id); - raop_rtp_mirror_start(conn->raop_rtp_mirror, &dport, conn->raop->clientFPSdata); - logger_log(conn->raop->logger, LOGGER_DEBUG, "Mirroring initialized successfully"); - } else { - logger_log(conn->raop->logger, LOGGER_ERR, "Mirroring not initialized at SETUP, playing will fail!"); - http_response_set_disconnect(response, 1); - } - - plist_t res_stream_node = plist_new_dict(); - plist_t res_stream_data_port_node = plist_new_uint(dport); - plist_t res_stream_type_node = plist_new_uint(110); - plist_dict_set_item(res_stream_node, "dataPort", res_stream_data_port_node); - plist_dict_set_item(res_stream_node, "type", res_stream_type_node); - plist_array_append_item(res_streams_node, res_stream_node); - - break; - } case 96: { - // Audio - unsigned short cport = conn->raop->control_lport, dport = conn->raop->data_lport; - unsigned short remote_cport = 0; - unsigned char ct = 0; - unsigned int sr = AUDIO_SAMPLE_RATE; /* all AirPlay audio formats supported so far have sample rate 44.1kHz */ - - uint64_t uint_val = 0; - plist_t req_stream_control_port_node = plist_dict_get_item(req_stream_node, "controlPort"); - plist_get_uint_val(req_stream_control_port_node, &uint_val); - remote_cport = (unsigned short) uint_val; /* must != 0 to activate audio resend requests */ - - plist_t req_stream_ct_node = plist_dict_get_item(req_stream_node, "ct"); - plist_get_uint_val(req_stream_ct_node, &uint_val); - ct = (unsigned char) uint_val; - - if (conn->raop->callbacks.audio_get_format) { - /* get additional audio format parameters */ - uint64_t audioFormat = 0; - unsigned short spf = 0; - bool isMedia = false; - bool usingScreen = false; - uint8_t bool_val = 0; - - plist_t req_stream_spf_node = plist_dict_get_item(req_stream_node, "spf"); - plist_get_uint_val(req_stream_spf_node, &uint_val); - spf = (unsigned short) uint_val; - - plist_t req_stream_audio_format_node = plist_dict_get_item(req_stream_node, "audioFormat"); - plist_get_uint_val(req_stream_audio_format_node, &audioFormat); - - plist_t req_stream_is_media_node = plist_dict_get_item(req_stream_node, "isMedia"); - if (req_stream_is_media_node) { - plist_get_bool_val(req_stream_is_media_node, &bool_val); - isMedia = (bool) bool_val; - } else { - isMedia = false; - } - - plist_t req_stream_using_screen_node = plist_dict_get_item(req_stream_node, "usingScreen"); - if (req_stream_using_screen_node) { - plist_get_bool_val(req_stream_using_screen_node, &bool_val); - usingScreen = (bool) bool_val; - } else { - usingScreen = false; - } - - conn->raop->callbacks.audio_get_format(conn->raop->callbacks.cls, &ct, &spf, &usingScreen, &isMedia, &audioFormat); - } - - if (conn->raop_rtp) { - raop_rtp_start_audio(conn->raop_rtp, &remote_cport, &cport, &dport, &ct, &sr); - logger_log(conn->raop->logger, LOGGER_DEBUG, "RAOP initialized success"); - } else { - logger_log(conn->raop->logger, LOGGER_ERR, "RAOP not initialized at SETUP, playing will fail!"); - http_response_set_disconnect(response, 1); - } - - plist_t res_stream_node = plist_new_dict(); - plist_t res_stream_data_port_node = plist_new_uint(dport); - plist_t res_stream_control_port_node = plist_new_uint(cport); - plist_t res_stream_type_node = plist_new_uint(96); - plist_dict_set_item(res_stream_node, "dataPort", res_stream_data_port_node); - plist_dict_set_item(res_stream_node, "controlPort", res_stream_control_port_node); - plist_dict_set_item(res_stream_node, "type", res_stream_type_node); - plist_array_append_item(res_streams_node, res_stream_node); - - break; + if (conn->raop_rtp_mirror) { + raop_rtp_mirror_init_aes(conn->raop_rtp_mirror, &stream_connection_id); + raop_rtp_mirror_start(conn->raop_rtp_mirror, &dport, conn->raop->clientFPSdata); + logger_log(conn->raop->logger, LOGGER_DEBUG, "Mirroring initialized successfully"); + } else { + logger_log(conn->raop->logger, LOGGER_ERR, "Mirroring not initialized at SETUP, playing will fail!"); + http_response_set_disconnect(response, 1); } - default: - logger_log(conn->raop->logger, LOGGER_ERR, "SETUP tries to setup stream of unknown type %llu", type); + plist_t res_stream_node = plist_new_dict(); + plist_t res_stream_data_port_node = plist_new_uint(dport); + plist_t res_stream_type_node = plist_new_uint(110); + plist_dict_set_item(res_stream_node, "dataPort", res_stream_data_port_node); + plist_dict_set_item(res_stream_node, "type", res_stream_type_node); + plist_array_append_item(res_streams_node, res_stream_node); + + break; + } + case 96: { + // Audio + unsigned short cport = conn->raop->control_lport, dport = conn->raop->data_lport; + unsigned short remote_cport = 0; + unsigned char ct = 0; + unsigned int sr = AUDIO_SAMPLE_RATE; /* all AirPlay audio formats supported so far have sample rate 44.1kHz */ + + uint64_t uint_val = 0; + plist_t req_stream_control_port_node = plist_dict_get_item(req_stream_node, "controlPort"); + plist_get_uint_val(req_stream_control_port_node, &uint_val); + remote_cport = (unsigned short) uint_val; /* must != 0 to activate audio resend requests */ + + plist_t req_stream_ct_node = plist_dict_get_item(req_stream_node, "ct"); + plist_get_uint_val(req_stream_ct_node, &uint_val); + ct = (unsigned char) uint_val; + + if (conn->raop->callbacks.audio_get_format) { + /* get additional audio format parameters */ + uint64_t audioFormat = 0; + unsigned short spf = 0; + bool isMedia = false; + bool usingScreen = false; + uint8_t bool_val = 0; + + plist_t req_stream_spf_node = plist_dict_get_item(req_stream_node, "spf"); + plist_get_uint_val(req_stream_spf_node, &uint_val); + spf = (unsigned short) uint_val; + + plist_t req_stream_audio_format_node = plist_dict_get_item(req_stream_node, "audioFormat"); + plist_get_uint_val(req_stream_audio_format_node, &audioFormat); + + plist_t req_stream_is_media_node = plist_dict_get_item(req_stream_node, "isMedia"); + if (req_stream_is_media_node) { + plist_get_bool_val(req_stream_is_media_node, &bool_val); + isMedia = (bool) bool_val; + } else { + isMedia = false; + } + + plist_t req_stream_using_screen_node = plist_dict_get_item(req_stream_node, "usingScreen"); + if (req_stream_using_screen_node) { + plist_get_bool_val(req_stream_using_screen_node, &bool_val); + usingScreen = (bool) bool_val; + } else { + usingScreen = false; + } + + conn->raop->callbacks.audio_get_format(conn->raop->callbacks.cls, &ct, &spf, &usingScreen, &isMedia, &audioFormat); + } + + if (conn->raop_rtp) { + raop_rtp_start_audio(conn->raop_rtp, &remote_cport, &cport, &dport, &ct, &sr); + logger_log(conn->raop->logger, LOGGER_DEBUG, "RAOP initialized success"); + } else { + logger_log(conn->raop->logger, LOGGER_ERR, "RAOP not initialized at SETUP, playing will fail!"); http_response_set_disconnect(response, 1); - break; + } + + plist_t res_stream_node = plist_new_dict(); + plist_t res_stream_data_port_node = plist_new_uint(dport); + plist_t res_stream_control_port_node = plist_new_uint(cport); + plist_t res_stream_type_node = plist_new_uint(96); + plist_dict_set_item(res_stream_node, "dataPort", res_stream_data_port_node); + plist_dict_set_item(res_stream_node, "controlPort", res_stream_control_port_node); + plist_dict_set_item(res_stream_node, "type", res_stream_type_node); + plist_array_append_item(res_streams_node, res_stream_node); + + break; + } + + default: + logger_log(conn->raop->logger, LOGGER_ERR, "SETUP tries to setup stream of unknown type %llu", type); + http_response_set_disconnect(response, 1); + break; } } @@ -1036,7 +1037,7 @@ raop_handler_get_parameter(raop_conn_t *conn, char volume[25] = "volume: 0.0\r\n"; if (conn->raop->callbacks.audio_set_client_volume) { snprintf(volume, 25, "volume: %9.6f\r\n", conn->raop->callbacks.audio_set_client_volume(conn->raop->callbacks.cls)); - } + } http_response_add_header(response, "Content-Type", "text/parameters"); *response_data = strdup(volume); if (*response_data) { @@ -1045,9 +1046,11 @@ raop_handler_get_parameter(raop_conn_t *conn, return; } - for (next = current ; (datalen - (next - data) > 0) ; ++next) - if (*next == '\r') + for (next = current ; (datalen - (next - data) > 0) ; ++next) { + if (*next == '\r') { break; + } + } if ((datalen - (next - data) >= 2) && !strncmp(next, "\r\n", 2)) { if ((next - current) > 0) { @@ -1187,7 +1190,7 @@ raop_handler_teardown(raop_conn_t *conn, if (val == 96) { teardown_96 = true; } else if (val == 110) { - teardown_110 = true; + teardown_110 = true; } } } diff --git a/lib/raop_ntp.c b/lib/raop_ntp.c index 2264883..7d9c225 100644 --- a/lib/raop_ntp.c +++ b/lib/raop_ntp.c @@ -352,7 +352,7 @@ raop_ntp_thread(void *arg) (double) t2 / SECOND_IN_NSECS, str); free(str); } - // The iOS client device sends its time in seconds relative to an arbitrary Epoch (the last boot). + // The iOS client device sends its time in seconds relative to an arbitrary Epoch (the last boot). // For a little bonus confusion, they add SECONDS_FROM_1900_TO_1970. // This means we have to expect some rather huge offset, but its growth or shrink over time should be small. diff --git a/lib/raop_rtp.c b/lib/raop_rtp.c index f51eeab..51c304e 100644 --- a/lib/raop_rtp.c +++ b/lib/raop_rtp.c @@ -195,7 +195,6 @@ raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, co return raop_rtp; } - void raop_rtp_destroy(raop_rtp_t *raop_rtp) { @@ -515,7 +514,7 @@ raop_rtp_thread_udp(void *arg) } else { client_ntp_sync_prev = raop_rtp->client_ntp_sync; rtp_sync_prev = raop_rtp->rtp_sync; - } + } raop_rtp->rtp_sync = byteutils_get_int_be(packet, 4); uint64_t sync_ntp_raw = byteutils_get_long_be(packet, 8); raop_rtp->client_ntp_sync = raop_remote_timestamp_to_nano_seconds(raop_rtp->ntp, sync_ntp_raw); @@ -564,20 +563,20 @@ raop_rtp_thread_udp(void *arg) * three times; the secnum and rtp_timestamp increment according to the same pattern as * AAC-ELD packets with audio content.*/ - /* When the ALAC audio stream starts, the initial packets are length-44 packets with - * the same 32-byte encrypted payload which after decryption is the beginning of a - * 32-byte ALAC packet, presumably with format information, but not actual audio data. - * The secnum and rtp_timestamp in the packet header increment according to the same - * pattern as ALAC packets with audio content */ + /* When the ALAC audio stream starts, the initial packets are length-44 packets with + * the same 32-byte encrypted payload which after decryption is the beginning of a + * 32-byte ALAC packet, presumably with format information, but not actual audio data. + * The secnum and rtp_timestamp in the packet header increment according to the same + * pattern as ALAC packets with audio content */ - /* The first ALAC packet with data seems to be decoded just before the first sync event - * so its dequeuing should be delayed until the first rtp sync has occurred */ + /* The first ALAC packet with data seems to be decoded just before the first sync event + * so its dequeuing should be delayed until the first rtp sync has occurred */ - if (FD_ISSET(raop_rtp->dsock, &rfds)) { - if (!raop_rtp->initial_sync && !video_arrival_offset) { + if (FD_ISSET(raop_rtp->dsock, &rfds)) { + if (!raop_rtp->initial_sync && !video_arrival_offset) { video_arrival_offset = raop_ntp_get_video_arrival_offset(raop_rtp->ntp); - } + } //logger_log(raop_rtp->logger, LOGGER_INFO, "Would have data packet in queue"); // Receiving audio data here saddrlen = sizeof(saddr); @@ -594,17 +593,17 @@ raop_rtp_thread_udp(void *arg) free (str); } continue; - } + } - if (!raop_rtp->initial_sync && raop_rtp->ct == 8 && video_arrival_offset) { + if (!raop_rtp->initial_sync && raop_rtp->ct == 8 && video_arrival_offset) { /* estimate a fake initial remote timestamp for video synchronization with AAC audio before the first rtp sync */ - uint64_t ts = raop_ntp_get_local_time() - video_arrival_offset; - double delay = DELAY_AAC; - ts += (uint64_t) (delay * SEC); - raop_rtp->client_ntp_sync = ts; - raop_rtp->rtp_sync = byteutils_get_int_be(packet, 4); - raop_rtp->initial_sync = true; - } + uint64_t ts = raop_ntp_get_local_time() - video_arrival_offset; + double delay = DELAY_AAC; + ts += (uint64_t) (delay * SEC); + raop_rtp->client_ntp_sync = ts; + raop_rtp->rtp_sync = byteutils_get_int_be(packet, 4); + raop_rtp->initial_sync = true; + } if (packetlen == 16 && memcmp(packet + 12, no_data_marker, 4) == 0) { /* this is a "no data" packet */ @@ -612,12 +611,12 @@ raop_rtp_thread_udp(void *arg) continue; } - if (raop_rtp->ct == 2 && packetlen == 44) continue; /* ignore the ALAC packets with format information only. */ + if (raop_rtp->ct == 2 && packetlen == 44) continue; /* ignore the ALAC packets with format information only. */ int result = raop_buffer_enqueue(raop_rtp->buffer, packet, packetlen, 1); assert(result >= 0); - if (!raop_rtp->initial_sync) { + if (!raop_rtp->initial_sync) { /* wait until the first sync before dequeing ALAC */ continue; } else { diff --git a/lib/raop_rtp_mirror.c b/lib/raop_rtp_mirror.c index 82c55df..029c6d5 100644 --- a/lib/raop_rtp_mirror.c +++ b/lib/raop_rtp_mirror.c @@ -330,13 +330,13 @@ raop_rtp_mirror_thread(void *arg) /*packet[0:3] contains the payload size */ int payload_size = byteutils_get_int(packet, 0); char packet_description[13] = {0}; - char *p = packet_description; + char *p = packet_description; int n = sizeof(packet_description); - for (int i = 4; i < 8; i++) { + for (int i = 4; i < 8; i++) { snprintf(p, n, "%2.2x ", (unsigned int) packet[i]); n -= 3; p += 3; - } + } ntp_timestamp_raw = byteutils_get_long(packet, 8); ntp_timestamp_remote = raop_ntp_timestamp_to_nano_seconds(ntp_timestamp_raw, false); if (first_packet) { @@ -345,14 +345,14 @@ raop_rtp_mirror_thread(void *arg) first_packet = false; } - /* packet[4] + packet[5] identify the payload type: values seen are: * + /* packet[4] + packet[5] identify the payload type: values seen are: * * 0x00 0x00: encrypted packet containing a non-IDR type 1 VCL NAL unit * * 0x00 0x10: encrypted packet containing an IDR type 5 VCL NAL unit * * 0x01 0x00: unencrypted packet containing a type 7 SPS NAL + a type 8 PPS NAL unit * * 0x02 0x00: unencrypted packet (old protocol) no payload, sent once every second * * 0x05 0x00 unencrypted packet with a "streaming report", sent once per second. */ - /* packet[6] + packet[7] may list a payload "option": values seen are: * + /* packet[6] + packet[7] may list a payload "option": values seen are: * * 0x00 0x00 : encrypted and "streaming report" packets * * 0x1e 0x00 : old protocol (seen in AirMyPC) no-payload once-per-second packets * * 0x16 0x01 : seen in most unencrypted h264 SPS+PPS packets * @@ -395,7 +395,7 @@ raop_rtp_mirror_thread(void *arg) break; } - switch (packet[4]) { + switch (packet[4]) { case 0x00: // Normal video data (VCL NAL) @@ -415,7 +415,7 @@ raop_rtp_mirror_thread(void *arg) } unsigned char* payload_out; - unsigned char* payload_decrypted; + unsigned char* payload_decrypted; /* * nal_types:1 Coded non-partitioned slice of a non-IDR picture * 5 Coded non-partitioned slice of an IDR picture @@ -437,7 +437,7 @@ raop_rtp_mirror_thread(void *arg) "raop_rtp_mirror: prepended sps_pps timestamp does not match timestamp of " "video payload\n%llu\n%llu , discarding", ntp_timestamp_raw, ntp_timestamp_nal); free (sps_pps); - sps_pps = NULL; + sps_pps = NULL; prepend_sps_pps = false; } @@ -447,7 +447,7 @@ raop_rtp_mirror_thread(void *arg) payload_decrypted = payload_out + sps_pps_len; memcpy(payload_out, sps_pps, sps_pps_len); free (sps_pps); - sps_pps = NULL; + sps_pps = NULL; } else { payload_out = (unsigned char*) malloc(payload_size); payload_decrypted = payload_out; @@ -474,11 +474,11 @@ raop_rtp_mirror_thread(void *arg) valid_data = false; break; } - int nalu_type; - if (h265_video) { + int nalu_type; + if (h265_video) { nalu_type = payload_decrypted[nalu_size] & 0x7e >> 1;; //logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG," h265 video, NALU type %d, size %d", nalu_type, nc_len); - } else { + } else { nalu_type = payload_decrypted[nalu_size] & 0x1f; int ref_idc = (payload_decrypted[nalu_size] >> 5); switch (nalu_type) { @@ -486,7 +486,7 @@ raop_rtp_mirror_thread(void *arg) case 5: /*IDR, slice_layer_without_partitioning */ case 1: /*non-IDR, slice_layer_without_partitioning */ break; - case 2: /* slice data partition A */ + case 2: /* slice data partition A */ case 3: /* slice data partition B */ case 4: /* slice data partition C */ logger_log(raop_rtp_mirror->logger, LOGGER_INFO, @@ -526,9 +526,9 @@ raop_rtp_mirror_thread(void *arg) "unexpected non-VCL NAL unit: nalu_type = %d, ref_idc = %d, nalu_size = %d," "processed bytes %d, payloadsize = %d nalus_count = %d", nalu_type, ref_idc, nc_len, nalu_size, payload_size, nalus_count); - break; - } - } + break; + } + } nalu_size += nc_len; } if (nalu_size != payload_size) valid_data = false; @@ -540,7 +540,7 @@ raop_rtp_mirror_thread(void *arg) payload_decrypted = NULL; video_decode_struct video_data; - video_data.is_h265 = h265_video; + video_data.is_h265 = h265_video; video_data.ntp_time_local = ntp_timestamp_local; video_data.ntp_time_remote = ntp_timestamp_remote; video_data.nal_count = nalus_count; /*nal_count will be the number of nal units in the packet */ @@ -571,13 +571,13 @@ raop_rtp_mirror_thread(void *arg) bytes 56-59 width bytes 60-63 height bytes 64-127 all 0x0 - */ + */ // The information in the payload contains an SPS and a PPS NAL // The sps_pps is not encrypted logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "\nReceived unencrypted codec packet from client:" " payload_size %d header %s ts_client = %8.6f", - payload_size, packet_description, (double) ntp_timestamp_remote / SEC); + payload_size, packet_description, (double) ntp_timestamp_remote / SEC); if (packet[6] == 0x56 || packet[6] == 0x5e) { logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "This packet indicates video stream is stopping"); @@ -614,7 +614,7 @@ raop_rtp_mirror_thread(void *arg) logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror width_source = %f height_source = %f width = %f height = %f", width_source, height_source, width, height); - if (payload_size == 0) { + if (payload_size == 0) { logger_log(raop_rtp_mirror->logger, LOGGER_ERR, "raop_rtp_mirror: received type 0x01 packet with no payload:\n" "this indicates non-h264 video but Airplay features bit 42 (SupportsScreenMultiCodec) is not set\n" "use startup option \"-h265\" to set this bit and support h265 (4K) video"); @@ -625,7 +625,7 @@ raop_rtp_mirror_thread(void *arg) free(sps_pps); sps_pps = NULL; } - /* test for a H265 VPS/SPS/PPS */ + /* test for a H265 VPS/SPS/PPS */ unsigned char hvc1[] = { 0x68, 0x76, 0x63, 0x31 }; if (!memcmp(payload + 4, hvc1, 4)) { @@ -677,7 +677,7 @@ raop_rtp_mirror_thread(void *arg) break; } sps_size = byteutils_get_short_be(ptr, 3); - ptr += 5; + ptr += 5; sps = ptr; if (logger_debug) { char *str = utils_data_to_string(sps, sps_size, 16); @@ -690,12 +690,12 @@ raop_rtp_mirror_thread(void *arg) raop_rtp_mirror->callbacks.video_pause(raop_rtp_mirror->callbacks.cls); break; } - pps_size = byteutils_get_short_be(ptr, 3); + pps_size = byteutils_get_short_be(ptr, 3); ptr += 5; pps = ptr; if (logger_debug) { char *str = utils_data_to_string(pps, pps_size, 16); - logger_log(raop_rtp_mirror->logger, LOGGER_INFO, "h265 pps size %d\n%s",pps_size, str); + logger_log(raop_rtp_mirror->logger, LOGGER_INFO, "h265 pps size %d\n%s",pps_size, str); free(str); } @@ -802,7 +802,7 @@ raop_rtp_mirror_thread(void *arg) int plist_size = payload_size; if (payload_size > 25000) { - plist_size = payload_size - 25000; + plist_size = payload_size - 25000; if (logger_debug) { char *str = utils_data_to_string(payload + plist_size, 16, 16); logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, @@ -848,7 +848,7 @@ raop_rtp_mirror_thread(void *arg) logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror exiting TCP thread"); if (conn_reset&& raop_rtp_mirror->callbacks.conn_reset) { - raop_rtp_mirror->callbacks.conn_reset(raop_rtp_mirror->callbacks.cls, 1); + raop_rtp_mirror->callbacks.conn_reset(raop_rtp_mirror->callbacks.cls, 1); } if (unsupported_codec) { From 32d5de23c8b0d6b8c61f01e43f48b9827daae7ca Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Fri, 8 Aug 2025 15:42:07 -0400 Subject: [PATCH 08/58] whitespace cleanup --- lib/airplay_video.c | 25 ++++++------ lib/dnssd.c | 28 +++++++------- lib/http_handlers.h | 93 ++++++++++++++++++++++----------------------- lib/http_request.c | 20 +++++----- lib/raop.c | 34 ++++++++--------- lib/utils.c | 10 ++--- 6 files changed, 103 insertions(+), 107 deletions(-) diff --git a/lib/airplay_video.c b/lib/airplay_video.c index 9b0ccd2..dfcea64 100644 --- a/lib/airplay_video.c +++ b/lib/airplay_video.c @@ -58,7 +58,7 @@ int airplay_video_service_init(raop_t *raop, unsigned short http_port, airplay_video_t *airplay_video = deregister_airplay_video(raop); if (airplay_video) { - airplay_video_service_destroy(airplay_video); + airplay_video_service_destroy(airplay_video); } /* calloc guarantees that the 36-character strings apple_session_id and @@ -74,11 +74,11 @@ int airplay_video_service_init(raop_t *raop, unsigned short http_port, snprintf(ptr, 6, "%-5u", http_port); ptr = strstr(airplay_video->local_uri_prefix, " "); if (ptr) { - *ptr = '\0'; + *ptr = '\0'; } if (!register_airplay_video(raop, airplay_video)) { - return -2; + return -2; } //printf(" %p %p\n", airplay_video, get_airplay_video(raop)); @@ -118,7 +118,6 @@ airplay_video_service_destroy(airplay_video_t *airplay_video) free (airplay_video->master_playlist); } - free (airplay_video); } @@ -146,19 +145,19 @@ const char *get_playback_uuid(airplay_video_t *airplay_video) { } void set_uri_prefix(airplay_video_t *airplay_video, char *uri_prefix, int uri_prefix_len) { - if (airplay_video->uri_prefix) { - free (airplay_video->uri_prefix); - } - airplay_video->uri_prefix = (char *) calloc(uri_prefix_len + 1, sizeof(char)); - memcpy(airplay_video->uri_prefix, uri_prefix, uri_prefix_len); + if (airplay_video->uri_prefix) { + free (airplay_video->uri_prefix); + } + airplay_video->uri_prefix = (char *) calloc(uri_prefix_len + 1, sizeof(char)); + memcpy(airplay_video->uri_prefix, uri_prefix, uri_prefix_len); } char *get_uri_prefix(airplay_video_t *airplay_video) { - return airplay_video->uri_prefix; + return airplay_video->uri_prefix; } char *get_uri_local_prefix(airplay_video_t *airplay_video) { - return airplay_video->local_uri_prefix; + return airplay_video->local_uri_prefix; } char *get_master_uri(airplay_video_t *airplay_video) { @@ -198,7 +197,7 @@ void destroy_media_data_store(airplay_video_t *airplay_video) { media_item_t *media_data_store = airplay_video->media_data_store; if (media_data_store) { for (int i = 0; i < airplay_video->num_uri ; i ++ ) { - if (media_data_store[i].uri) { + if (media_data_store[i].uri) { free (media_data_store[i].uri); } if (media_data_store[i].playlist) { @@ -336,7 +335,7 @@ char *adjust_master_playlist (char *fcup_response_data, int fcup_response_datale while (ptr != NULL) { counter++; ptr++; - ptr = strstr(ptr, uri_prefix); + ptr = strstr(ptr, uri_prefix); } size_t len = uri_local_prefix_len - uri_prefix_len; diff --git a/lib/dnssd.c b/lib/dnssd.c index b66563c..23d3143 100644 --- a/lib/dnssd.c +++ b/lib/dnssd.c @@ -310,16 +310,16 @@ dnssd_register_raop(dnssd_t *dnssd, unsigned short port) case 2: case 3: dnssd->TXTRecordSetValue(&dnssd->raop_record, "pw", strlen("true"), "true"); - dnssd->TXTRecordSetValue(&dnssd->raop_record, "sf", 4, "0x84"); - break; + dnssd->TXTRecordSetValue(&dnssd->raop_record, "sf", 4, "0x84"); + break; case 1: dnssd->TXTRecordSetValue(&dnssd->raop_record, "pw", strlen("true"), "true"); - dnssd->TXTRecordSetValue(&dnssd->raop_record, "sf", 3, "0x8c"); - break; + dnssd->TXTRecordSetValue(&dnssd->raop_record, "sf", 3, "0x8c"); + break; default: dnssd->TXTRecordSetValue(&dnssd->raop_record, "pw", strlen("false"), "false"); - dnssd->TXTRecordSetValue(&dnssd->raop_record, "sf", strlen(RAOP_SF), RAOP_SF); - break; + dnssd->TXTRecordSetValue(&dnssd->raop_record, "sf", strlen(RAOP_SF), RAOP_SF); + break; } dnssd->TXTRecordSetValue(&dnssd->raop_record, "sr", strlen(RAOP_SR), RAOP_SR); dnssd->TXTRecordSetValue(&dnssd->raop_record, "ss", strlen(RAOP_SS), RAOP_SS); @@ -382,8 +382,8 @@ dnssd_register_airplay(dnssd_t *dnssd, unsigned short port) switch (dnssd->pin_pw) { case 1: // display onscreen pin dnssd->TXTRecordSetValue(&dnssd->airplay_record, "pw", strlen("true"), "true"); - dnssd->TXTRecordSetValue(&dnssd->airplay_record, "flags", 3, "0x4"); - break; + dnssd->TXTRecordSetValue(&dnssd->airplay_record, "flags", 3, "0x4"); + break; case 2: // require password case 3: dnssd->TXTRecordSetValue(&dnssd->airplay_record, "pw", strlen("true"), "true"); @@ -476,13 +476,13 @@ dnssd_unregister_airplay(dnssd_t *dnssd) } uint64_t dnssd_get_airplay_features(dnssd_t *dnssd) { - uint64_t features = ((uint64_t) dnssd->features2) << 32; - features += (uint64_t) dnssd->features1; - return features; + uint64_t features = ((uint64_t) dnssd->features2) << 32; + features += (uint64_t) dnssd->features1; + return features; } void dnssd_set_pk(dnssd_t *dnssd, char * pk_str) { - dnssd->pk = pk_str; + dnssd->pk = pk_str; } void dnssd_set_airplay_features(dnssd_t *dnssd, int bit, int val) { @@ -498,8 +498,8 @@ void dnssd_set_airplay_features(dnssd_t *dnssd, int bit, int val) { features = &(dnssd->features1); } if (val) { - *features = *features | mask; + *features = *features | mask; } else { - *features = *features & ~mask; + *features = *features & ~mask; } } diff --git a/lib/http_handlers.h b/lib/http_handlers.h index 25c83d9..1c17717 100644 --- a/lib/http_handlers.h +++ b/lib/http_handlers.h @@ -124,7 +124,7 @@ http_handler_rate(raop_conn_t *conn, http_request_t *request, http_response_t *r if (end && end != rate) { rate_value = value; logger_log(conn->raop->logger, LOGGER_DEBUG, "http_handler_rate: got rate = %.6f", rate_value); - } + } } conn->raop->callbacks.on_video_rate(conn->raop->callbacks.cls, rate_value); } @@ -142,7 +142,7 @@ http_handler_stop(raop_conn_t *conn, http_request_t *request, http_response_t *r static void http_handler_set_property(raop_conn_t *conn, http_request_t *request, http_response_t *response, - char **response_data, int *response_datalen) { + char **response_data, int *response_datalen) { const char *url = http_request_get_url(request); const char *property = url + strlen("/setProperty?"); @@ -247,12 +247,12 @@ int create_playback_info_plist_xml(playback_info_t *playback_info, char **plist_ plist_t loaded_time_ranges_node = plist_new_array(); time_range_to_plist(playback_info->loadedTimeRanges, playback_info->num_loaded_time_ranges, - loaded_time_ranges_node); + loaded_time_ranges_node); plist_dict_set_item(res_root_node, "loadedTimeRanges", loaded_time_ranges_node); plist_t seekable_time_ranges_node = plist_new_array(); time_range_to_plist(playback_info->seekableTimeRanges, playback_info->num_seekable_time_ranges, - seekable_time_ranges_node); + seekable_time_ranges_node); plist_dict_set_item(res_root_node, "seekableTimeRanges", seekable_time_ranges_node); int len; @@ -264,7 +264,6 @@ int create_playback_info_plist_xml(playback_info_t *playback_info, char **plist_ return len; } - /* this handles requests from the Client for "Playback information" while the Media is playing on the Media Player. (The Server gets this information by monitoring the Media Player). The Client could use the information to e.g. update the slider it shows with progress to the player (0%-100%). @@ -287,11 +286,11 @@ http_handler_playback_info(raop_conn_t *conn, http_request_t *request, http_resp conn->raop->callbacks.on_video_acquire_playback_info(conn->raop->callbacks.cls, &playback_info); if (playback_info.duration == -1.0) { /* video has finished, reset */ - logger_log(conn->raop->logger, LOGGER_DEBUG, "playback_info not available (finishing)"); - //httpd_remove_known_connections(conn->raop->httpd); - http_response_set_disconnect(response,1); - conn->raop->callbacks.video_reset(conn->raop->callbacks.cls); - return; + logger_log(conn->raop->logger, LOGGER_DEBUG, "playback_info not available (finishing)"); + //httpd_remove_known_connections(conn->raop->httpd); + http_response_set_disconnect(response,1); + conn->raop->callbacks.video_reset(conn->raop->callbacks.cls); + return; } else if (playback_info.position == -1.0) { logger_log(conn->raop->logger, LOGGER_DEBUG, "playback_info not available"); return; @@ -345,9 +344,8 @@ http_handler_reverse(raop_conn_t *conn, http_request_t *request, http_response_t if (type_PTTH == 1) { logger_log(conn->raop->logger, LOGGER_DEBUG, "will use socket %d for %s connections", socket_fd, purpose); http_response_init(response, "HTTP/1.1", 101, "Switching Protocols"); - http_response_add_header(response, "Connection", "Upgrade"); - http_response_add_header(response, "Upgrade", "PTTH/1.0"); - + http_response_add_header(response, "Connection", "Upgrade"); + http_response_add_header(response, "Upgrade", "PTTH/1.0"); } else { logger_log(conn->raop->logger, LOGGER_ERR, "multiple TPPH connections (%d) are forbidden", type_PTTH ); } @@ -368,7 +366,6 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t int request_id = 0; int fcup_response_statuscode = 0; bool logger_debug = (logger_get_level(conn->raop->logger) >= LOGGER_DEBUG); - const char* session_id = http_request_get_header(request, "X-Apple-Session-ID"); if (!session_id) { @@ -405,7 +402,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t /* determine type of data */ plist_t req_type_node = plist_dict_get_item(req_root_node, "type"); if (!PLIST_IS_STRING(req_type_node)) { - goto post_action_error; + goto post_action_error; } plist_t req_params_node = NULL; @@ -431,15 +428,15 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t } plist_t req_params_item_uuid_node = plist_dict_get_item(req_params_item_node, "uuid"); char* remove_uuid = NULL; - plist_get_string_val(req_params_item_uuid_node, &remove_uuid); + plist_get_string_val(req_params_item_uuid_node, &remove_uuid); const char *playback_uuid = get_playback_uuid(conn->raop->airplay_video); - if (strcmp(remove_uuid, playback_uuid)) { + if (strcmp(remove_uuid, playback_uuid)) { logger_log(conn->raop->logger, LOGGER_ERR, "uuid of playlist removal action request did not match current playlist:\n" " current: %s\n remove: %s", playback_uuid, remove_uuid); } else { logger_log(conn->raop->logger, LOGGER_DEBUG, "removal_uuid matches playback_uuid\n"); - } - free (remove_uuid); + } + free (remove_uuid); } logger_log(conn->raop->logger, LOGGER_ERR, "FIXME: playlist removal not yet implemented"); goto finish; @@ -531,11 +528,11 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t if (logger_debug) { logger_log(conn->raop->logger, LOGGER_DEBUG, "FCUP_Response datalen = %d", fcup_response_datalen); - char *data = malloc(fcup_response_datalen + 1); - memcpy(data, fcup_response_data, fcup_response_datalen); - data[fcup_response_datalen] = '\0'; - logger_log(conn->raop->logger, LOGGER_DEBUG, "begin FCUP Response data:\n%s\nend FCUP Response data",data); - free (data); + char *data = malloc(fcup_response_datalen + 1); + memcpy(data, fcup_response_data, fcup_response_datalen); + data[fcup_response_datalen] = '\0'; + logger_log(conn->raop->logger, LOGGER_DEBUG, "begin FCUP Response data:\n%s\nend FCUP Response data",data); + free (data); } @@ -543,24 +540,24 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t if (ptr) { /* this is a master playlist */ char *uri_prefix = get_uri_prefix(conn->raop->airplay_video); - char ** media_data_store = NULL; + char ** media_data_store = NULL; int num_uri = 0; char *uri_local_prefix = get_uri_local_prefix(conn->raop->airplay_video); char *new_master = adjust_master_playlist (fcup_response_data, fcup_response_datalen, uri_prefix, uri_local_prefix); store_master_playlist(conn->raop->airplay_video, new_master); create_media_uri_table(uri_prefix, fcup_response_data, fcup_response_datalen, &media_data_store, &num_uri); - create_media_data_store(conn->raop->airplay_video, media_data_store, num_uri); - num_uri = get_num_media_uri(conn->raop->airplay_video); - set_next_media_uri_id(conn->raop->airplay_video, 0); + create_media_data_store(conn->raop->airplay_video, media_data_store, num_uri); + num_uri = get_num_media_uri(conn->raop->airplay_video); + set_next_media_uri_id(conn->raop->airplay_video, 0); } else { /* this is a media playlist */ assert(fcup_response_data); - char *playlist = (char *) calloc(fcup_response_datalen + 1, sizeof(char)); - memcpy(playlist, fcup_response_data, fcup_response_datalen); + char *playlist = (char *) calloc(fcup_response_datalen + 1, sizeof(char)); + memcpy(playlist, fcup_response_data, fcup_response_datalen); int uri_num = get_next_media_uri_id(conn->raop->airplay_video); - --uri_num; // (next num is current num + 1) - store_media_playlist(conn->raop->airplay_video, playlist, uri_num); + --uri_num; // (next num is current num + 1) + store_media_playlist(conn->raop->airplay_video, playlist, uri_num); float duration = 0.0f; int count = analyze_media_playlist(playlist, &duration); if (count) { @@ -583,7 +580,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t fcup_request((void *) conn, get_media_uri_by_num(conn->raop->airplay_video, uri_num), apple_session_id, get_next_FCUP_RequestID(conn->raop->airplay_video)); - set_next_media_uri_id(conn->raop->airplay_video, ++uri_num); + set_next_media_uri_id(conn->raop->airplay_video, ++uri_num); } else { char * uri_local_prefix = get_uri_local_prefix(conn->raop->airplay_video); conn->raop->callbacks.on_video_play(conn->raop->callbacks.cls, @@ -599,7 +596,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t http_response_init(response, "HTTP/1.1", 400, "Bad Request"); if (req_root_node) { - plist_free(req_root_node); + plist_free(req_root_node); } } @@ -643,23 +640,23 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r char *header_str = NULL; http_request_get_header_string(request, &header_str); logger_log(conn->raop->logger, LOGGER_DEBUG, "request header:\n%s", header_str); - data_is_binary_plist = (strstr(header_str, "x-apple-binary-plist") != NULL); - data_is_text = (strstr(header_str, "text/parameters") != NULL); - data_is_octet = (strstr(header_str, "octet-stream") != NULL); - free (header_str); + data_is_binary_plist = (strstr(header_str, "x-apple-binary-plist") != NULL); + data_is_text = (strstr(header_str, "text/parameters") != NULL); + data_is_octet = (strstr(header_str, "octet-stream") != NULL); + free (header_str); } if (!data_is_text && !data_is_octet && !data_is_binary_plist) { - goto play_error; + goto play_error; } if (data_is_text) { logger_log(conn->raop->logger, LOGGER_ERR, "Play request Content is text (unsupported)"); - goto play_error; + goto play_error; } if (data_is_octet) { logger_log(conn->raop->logger, LOGGER_ERR, "Play request Content is octet-stream (unsupported)"); - goto play_error; + goto play_error; } if (data_is_binary_plist) { @@ -671,9 +668,9 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r } else { char* playback_uuid = NULL; plist_get_string_val(req_uuid_node, &playback_uuid); - set_playback_uuid(conn->raop->airplay_video, playback_uuid); + set_playback_uuid(conn->raop->airplay_video, playback_uuid); free (playback_uuid); - } + } plist_t req_content_location_node = plist_dict_get_item(req_root_node, "Content-Location"); if (!req_content_location_node) { @@ -696,18 +693,18 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r plist_t req_start_position_seconds_node = plist_dict_get_item(req_root_node, "Start-Position-Seconds"); if (!req_start_position_seconds_node) { logger_log(conn->raop->logger, LOGGER_INFO, "No Start-Position-Seconds in Play request"); - } else { + } else { double start_position = 0.0; plist_get_real_val(req_start_position_seconds_node, &start_position); - start_position_seconds = (float) start_position; + start_position_seconds = (float) start_position; } - set_start_position_seconds(conn->raop->airplay_video, (float) start_position_seconds); + set_start_position_seconds(conn->raop->airplay_video, (float) start_position_seconds); } char *ptr = strstr(playback_location, "/master.m3u8"); if (!ptr) { logger_log(conn->raop->logger, LOGGER_ERR, "Content-Location has unsupported form:\n%s\n", playback_location); - goto play_error; + goto play_error; } int prefix_len = (int) (ptr - playback_location); set_uri_prefix(conn->raop->airplay_video, playback_location, prefix_len); @@ -760,7 +757,7 @@ http_handler_hls(raop_conn_t *conn, http_request_t *request, http_response_t *r if (!strcmp(url, "/master.m3u8")){ char * master_playlist = get_master_playlist(conn->raop->airplay_video); - if (master_playlist) { + if (master_playlist) { size_t len = strlen(master_playlist); char * data = (char *) malloc(len + 1); memcpy(data, master_playlist, len); diff --git a/lib/http_request.c b/lib/http_request.c index 76bece6..d7e800e 100644 --- a/lib/http_request.c +++ b/lib/http_request.c @@ -81,11 +81,11 @@ on_header_field(llhttp_t *parser, const char *at, size_t length) /* Allocate space in the current header string */ if (request->headers[request->headers_index] == NULL) { - request->headers[request->headers_index] = calloc(1, length+1); + request->headers[request->headers_index] = calloc(1, length + 1); } else { request->headers[request->headers_index] = realloc( request->headers[request->headers_index], - strlen(request->headers[request->headers_index])+length+1 + strlen(request->headers[request->headers_index]) + length + 1 ); } assert(request->headers[request->headers_index]); @@ -106,11 +106,11 @@ on_header_value(llhttp_t *parser, const char *at, size_t length) /* Allocate space in the current header string */ if (request->headers[request->headers_index] == NULL) { - request->headers[request->headers_index] = calloc(1, length+1); + request->headers[request->headers_index] = calloc(1, length + 1); } else { request->headers[request->headers_index] = realloc( request->headers[request->headers_index], - strlen(request->headers[request->headers_index])+length+1 + strlen(request->headers[request->headers_index]) + length + 1 ); } assert(request->headers[request->headers_index]); @@ -124,7 +124,7 @@ on_body(llhttp_t *parser, const char *at, size_t length) { http_request_t *request = parser->data; - request->data = realloc(request->data, request->datalen+length); + request->data = realloc(request->data, request->datalen + length); assert(request->data); memcpy(request->data+request->datalen, at, length); @@ -172,7 +172,7 @@ http_request_destroy(http_request_t *request) if (request) { free(request->url); - for (i=0; iheaders_size; i++) { + for (i = 0; i < request->headers_size; i++) { free(request->headers[i]); } free(request->headers); @@ -273,7 +273,7 @@ http_request_get_header(http_request_t *request, const char *name) return NULL; } - for (i=0; iheaders_size; i+=2) { + for (i = 0; i < request->headers_size; i += 2) { if (!strcmp(request->headers[i], name)) { return request->headers[i+1]; } @@ -305,7 +305,7 @@ http_request_get_header_string(http_request_t *request, char **header_str) int len = 0; for (int i = 0; i < request->headers_size; i++) { len += strlen(request->headers[i]); - if (i%2 == 0) { + if (i % 2 == 0) { len += 2; } else { len++; @@ -321,12 +321,12 @@ http_request_get_header_string(http_request_t *request, char **header_str) snprintf(p, n, "%s", request->headers[i]); n -= hlen; p += hlen; - if (i%2 == 0) { + if (i % 2 == 0) { snprintf(p, n, ": "); n -= 2; p += 2; } else { - snprintf(p, n, "\n"); + snprintf(p, n, "\n"); n--; p++; } diff --git a/lib/raop.c b/lib/raop.c index d9939ba..95700f6 100644 --- a/lib/raop.c +++ b/lib/raop.c @@ -225,8 +225,8 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { logger_log(conn->raop->logger, LOGGER_INFO, "\"nohold\" feature: switch to new connection request from %s", ipaddr); if (conn->raop->callbacks.video_reset) { conn->raop->callbacks.video_reset(conn->raop->callbacks.cls); - } - httpd_remove_known_connections(conn->raop->httpd); + } + httpd_remove_known_connections(conn->raop->httpd); } else { logger_log(conn->raop->logger, LOGGER_WARNING, "rejecting new connection request from %s", ipaddr); *response = http_response_create(); @@ -245,7 +245,7 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { conn->client_session_id = (char *) malloc(len); strncpy(conn->client_session_id, client_session_id, len); /* airplay video has been requested: shut down any running RAOP udp services */ - raop_conn_t *raop_conn = (raop_conn_t *) httpd_get_connection_by_type(conn->raop->httpd, CONNECTION_TYPE_RAOP, 1); + raop_conn_t *raop_conn = (raop_conn_t *) httpd_get_connection_by_type(conn->raop->httpd, CONNECTION_TYPE_RAOP, 1); if (raop_conn) { raop_rtp_mirror_t *raop_rtp_mirror = raop_conn->raop_rtp_mirror; if (raop_rtp_mirror) { @@ -273,7 +273,7 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { httpd_set_connection_type(conn->raop->httpd, ptr, CONNECTION_TYPE_HLS); conn->connection_type = CONNECTION_TYPE_HLS; } else { - logger_log(conn->raop->logger, LOGGER_WARNING, "connection from unknown connection type"); + logger_log(conn->raop->logger, LOGGER_WARNING, "connection from unknown connection type"); } } @@ -310,9 +310,9 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { if (request_data && logger_debug) { if (request_datalen > 0) { /* logger has a buffer limit of 4096 */ - if (data_is_plist) { - plist_t req_root_node = NULL; - plist_from_bin(request_data, request_datalen, &req_root_node); + if (data_is_plist) { + plist_t req_root_node = NULL; + plist_from_bin(request_data, request_datalen, &req_root_node); char * plist_xml = NULL; char * stripped_xml = NULL; uint32_t plist_len; @@ -353,7 +353,7 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { if (!strcmp(method, "POST")) { if (!strcmp(url, "/feedback")) { handler = &raop_handler_feedback; - } else if (!strcmp(url, "/pair-pin-start")) { + } else if (!strcmp(url, "/pair-pin-start")) { handler = &raop_handler_pairpinstart; } else if (!strcmp(url, "/pair-setup-pin")) { handler = &raop_handler_pairsetup_pin; @@ -388,7 +388,7 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { handler = &raop_handler_teardown; } else { http_response_init(*response, protocol, 501, "Not Implemented"); - } + } } else if (!hls_request && !strcmp(protocol, "HTTP/1.1")) { if (!strcmp(method, "POST")) { if (!strcmp(url, "/reverse")) { @@ -415,9 +415,9 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { handler = &http_handler_playback_info; } } else if (!strcmp(method, "PUT")) { - if (!strncmp (url, "/setProperty?", strlen("/setProperty?"))) { + if (!strncmp (url, "/setProperty?", strlen("/setProperty?"))) { handler = &http_handler_set_property; - } + } } } else if (hls_request) { handler = &http_handler_hls; @@ -426,8 +426,8 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { if (handler != NULL) { handler(conn, request, *response, &response_data, &response_datalen); } else { - logger_log(conn->raop->logger, LOGGER_INFO, - "Unhandled Client Request: %s %s %s", method, url, protocol); + logger_log(conn->raop->logger, LOGGER_INFO, + "Unhandled Client Request: %s %s %s", method, url, protocol); } finish:; @@ -435,7 +435,7 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { http_response_add_header(*response, "Server", "AirTunes/"GLOBAL_VERSION); if (cseq) { http_response_add_header(*response, "CSeq", cseq); - } + } } http_response_finish(*response, response_data, response_datalen); @@ -488,7 +488,7 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { } if (response_data) { free(response_data); - } + } } } @@ -646,10 +646,10 @@ raop_destroy(raop_t *raop) { pairing_destroy(raop->pairing); httpd_destroy(raop->httpd); logger_destroy(raop->logger); - if (raop->nonce) { + if (raop->nonce) { free(raop->nonce); } - if (raop->random_pw) { + if (raop->random_pw) { free(raop->random_pw); } diff --git a/lib/utils.c b/lib/utils.c index ce2623e..f354b66 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -312,20 +312,20 @@ char *utils_strip_data_from_plist_xml(char *plist_xml) { nchars = eol + 1 - ptr1; memcpy(ptr2, ptr1, nchars); ptr2 += nchars; - ptr1 += nchars; + ptr1 += nchars; end = strstr(ptr1, ""); - assert(end); + assert(end); count = 0; do { eol_data = eol; eol = strchr(eol + 1, '\n'); count++; } while (eol < end); - count--; // last '\n' counted ends the first non-data line (contains "") - if (count > 1) { + count--; // last '\n' counted ends the first non-data line (contains "") + if (count > 1) { snprintf(line, sizeof(line), " (%d lines data omitted, 64 chars/line)\n", count); nchars = strlen(line); - memcpy(ptr2, line, nchars); + memcpy(ptr2, line, nchars); ptr2 += nchars; ptr1 = eol_data + 1; } else { From b5e083b1071afb7e2a80deac433160fe49952c4d Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Fri, 8 Aug 2025 17:06:14 -0400 Subject: [PATCH 09/58] whitespace cleanup --- renderers/audio_renderer.c | 24 ++++++++-------- renderers/video_renderer.c | 58 +++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/renderers/audio_renderer.c b/renderers/audio_renderer.c index 5075018..9a669d3 100644 --- a/renderers/audio_renderer.c +++ b/renderers/audio_renderer.c @@ -103,15 +103,15 @@ static gboolean check_plugin_feature (const gchar *needed_feature) plugin_feature = gst_registry_find_feature (registry, needed_feature, GST_TYPE_ELEMENT_FACTORY); if (!plugin_feature) { - g_print ("Required gstreamer libav plugin feature '%s' not found:\n\n" - "This may be missing because the FFmpeg package used by GStreamer-1.x-libav is incomplete.\n" - "(Some distributions provide an incomplete FFmpeg due to License or Patent issues:\n" - "in such cases a complete version for that distribution is usually made available elsewhere)\n", - needed_feature); - ret = FALSE; + g_print ("Required gstreamer libav plugin feature '%s' not found:\n\n" + "This may be missing because the FFmpeg package used by GStreamer-1.x-libav is incomplete.\n" + "(Some distributions provide an incomplete FFmpeg due to License or Patent issues:\n" + "in such cases a complete version for that distribution is usually made available elsewhere)\n", + needed_feature); + ret = FALSE; } else { - gst_object_unref (plugin_feature); - plugin_feature = NULL; + gst_object_unref (plugin_feature); + plugin_feature = NULL; } if (ret == FALSE) { g_print ("\nif the plugin feature is installed, but not found, your gstreamer registry may have been corrupted.\n" @@ -187,7 +187,7 @@ void audio_renderer_init(logger_t *render_logger, const char* audiosink, const b g_assert (renderer_type[i]->pipeline); gst_pipeline_use_clock(GST_PIPELINE_CAST(renderer_type[i]->pipeline), clock); - renderer_type[i]->bus = gst_element_get_bus(renderer_type[i]->pipeline); + renderer_type[i]->bus = gst_element_get_bus(renderer_type[i]->pipeline); renderer_type[i]->appsrc = gst_bin_get_by_name (GST_BIN (renderer_type[i]->pipeline), "audio_source"); renderer_type[i]->volume = gst_bin_get_by_name (GST_BIN (renderer_type[i]->pipeline), "volume"); switch (i) { @@ -369,12 +369,12 @@ void audio_renderer_destroy() { audio_renderer_stop(); for (int i = 0; i < NFORMATS ; i++ ) { gst_object_unref (renderer_type[i]->bus); - renderer_type[i]->bus = NULL; + renderer_type[i]->bus = NULL; gst_object_unref (renderer_type[i]->volume); - renderer_type[i]->volume = NULL; + renderer_type[i]->volume = NULL; gst_object_unref (renderer_type[i]->appsrc); renderer_type[i]->appsrc = NULL; - gst_object_unref (renderer_type[i]->pipeline); + gst_object_unref (renderer_type[i]->pipeline); renderer_type[i]->pipeline = NULL; free(renderer_type[i]); } diff --git a/renderers/video_renderer.c b/renderers/video_renderer.c index 4086312..979c53f 100644 --- a/renderers/video_renderer.c +++ b/renderers/video_renderer.c @@ -211,8 +211,8 @@ GstElement *make_video_sink(const char *videosink, const char *videosink_options pval++; const gchar *property_name = (const gchar *) token; const gchar *value = (const gchar *) pval; - g_print("playbin_videosink property: \"%s\" \"%s\"\n", property_name, value); - gst_util_set_object_arg(G_OBJECT (video_sink), property_name, value); + g_print("playbin_videosink property: \"%s\" \"%s\"\n", property_name, value); + gst_util_set_object_arg(G_OBJECT (video_sink), property_name, value); } } free(options); @@ -283,7 +283,7 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, vide } logger_log(logger, LOGGER_INFO, "Will use GStreamer playbin version %u to play HLS streamed video", playbin_version); g_assert(renderer_type[i]->pipeline); - renderer_type[i]->codec = hls; + renderer_type[i]->codec = hls; /* if we are not using an autovideosink, build a videosink based on the string "videosink" */ if (!auto_videosink) { GstElement *playbin_videosink = make_video_sink(videosink, videosink_options); @@ -297,9 +297,9 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, vide gint flags; g_object_get(renderer_type[i]->pipeline, "flags", &flags, NULL); flags |= GST_PLAY_FLAG_DOWNLOAD; - flags |= GST_PLAY_FLAG_BUFFERING; // set by default in playbin3, but not in playbin2; is it needed? + flags |= GST_PLAY_FLAG_BUFFERING; // set by default in playbin3, but not in playbin2; is it needed? g_object_set(renderer_type[i]->pipeline, "flags", flags, NULL); - g_object_set (G_OBJECT (renderer_type[i]->pipeline), "uri", uri, NULL); + g_object_set (G_OBJECT (renderer_type[i]->pipeline), "uri", uri, NULL); } else { bool jpeg_pipeline = false; switch (i) { @@ -320,9 +320,9 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, vide g_assert(0); } GString *launch = g_string_new("appsrc name=video_source ! "); - if (jpeg_pipeline) { + if (jpeg_pipeline) { g_string_append(launch, "jpegdec "); - } else { + } else { g_string_append(launch, "queue ! "); g_string_append(launch, parser); g_string_append(launch, " ! "); @@ -370,7 +370,7 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, vide logger_log(logger, LOGGER_ERR, "GStreamer gst_parse_launch failed to create video pipeline %d\n" "*** error message from gst_parse_launch was:\n%s\n" "launch string parsed was \n[%s]", i + 1, error->message, launch->str); - if (strstr(error->message, "no element")) { + if (strstr(error->message, "no element")) { logger_log(logger, LOGGER_ERR, "This error usually means that a uxplay option was mistyped\n" " or some requested part of GStreamer is not installed\n"); } @@ -385,7 +385,7 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, vide g_object_set(renderer_type[i]->appsrc, "caps", caps, "stream-type", 0, "is-live", TRUE, "format", GST_FORMAT_TIME, NULL); g_string_free(launch, TRUE); gst_caps_unref(caps); - gst_object_unref(clock); + gst_object_unref(clock); } #ifdef X_DISPLAY_FIX use_x11 = (strstr(videosink, "xvimagesink") || strstr(videosink, "ximagesink") || auto_videosink); @@ -704,9 +704,9 @@ static gboolean gstreamer_video_pipeline_bus_callback(GstBus *bus, GstMessage *m g_print("GStreamer %s bus message %s %s %s %s\n", renderer_type[type]->codec, GST_MESSAGE_SRC_NAME(message), GST_MESSAGE_TYPE_NAME(message), old_state_name, new_state_name); } - if (name) { - g_free(name); - } + if (name) { + g_free(name); + } } /* monitor hls video position until seek to hls_start_position is achieved */ @@ -716,21 +716,21 @@ static gboolean gstreamer_video_pipeline_bus_callback(GstBus *bus, GstMessage *m if (!GST_CLOCK_TIME_IS_VALID(hls_duration)) { gst_element_query_duration (renderer->pipeline, GST_FORMAT_TIME, &hls_duration); } - gst_element_query_position (renderer_type[type]->pipeline, GST_FORMAT_TIME, &pos); + gst_element_query_position (renderer_type[type]->pipeline, GST_FORMAT_TIME, &pos); //g_print("HLS position %" GST_TIME_FORMAT " requested_start_position %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT " %s\n", // GST_TIME_ARGS(pos), GST_TIME_ARGS(hls_requested_start_position), GST_TIME_ARGS(hls_duration), // (hls_seek_enabled ? "seek enabled" : "seek not enabled")); if (pos > hls_requested_start_position) { hls_requested_start_position = 0; } - if ( hls_requested_start_position && pos < hls_requested_start_position && hls_seek_enabled) { + if ( hls_requested_start_position && pos < hls_requested_start_position && hls_seek_enabled) { g_print("***************** seek to hls_requested_start_position %" GST_TIME_FORMAT "\n", GST_TIME_ARGS(hls_requested_start_position)); if (gst_element_seek_simple (renderer_type[type]->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, hls_requested_start_position)) { hls_requested_start_position = 0; } - } - } + } + } } switch (GST_MESSAGE_TYPE (message)) { @@ -742,8 +742,8 @@ static gboolean gstreamer_video_pipeline_bus_callback(GstBus *bus, GstMessage *m gint percent = -1; gst_message_parse_buffering(message, &percent); hls_buffer_empty = TRUE; - hls_buffer_full = FALSE; - if (percent > 0) { + hls_buffer_full = FALSE; + if (percent > 0) { hls_buffer_empty = FALSE; renderer_type[type]->buffering_level = percent; logger_log(logger, LOGGER_DEBUG, "Buffering :%d percent done", percent); @@ -772,11 +772,11 @@ static gboolean gstreamer_video_pipeline_bus_callback(GstBus *bus, GstMessage *m "*** to select a videosink of your choice (see \"man uxplay\").\n\n" "*** Raspberry Pi models 4B and earlier using Video4Linux2 may need \"-bt709\" uxplay option"); } - g_error_free (err); + g_error_free (err); g_free (debug); - if (renderer_type[type]->appsrc) { + if (renderer_type[type]->appsrc) { gst_app_src_end_of_stream (GST_APP_SRC(renderer_type[type]->appsrc)); - } + } gst_bus_set_flushing(bus, TRUE); gst_element_set_state (renderer_type[type]->pipeline, GST_STATE_READY); renderer_type[type]->terminate = TRUE; @@ -789,7 +789,7 @@ static gboolean gstreamer_video_pipeline_bus_callback(GstBus *bus, GstMessage *m if (hls_video) { gst_bus_set_flushing(bus, TRUE); gst_element_set_state (renderer_type[type]->pipeline, GST_STATE_READY); - renderer_type[type]->terminate = TRUE; + renderer_type[type]->terminate = TRUE; g_main_loop_quit( (GMainLoop *) loop); } break; @@ -824,14 +824,14 @@ static gboolean gstreamer_video_pipeline_bus_callback(GstBus *bus, GstMessage *m char *sink = strstr(GST_MESSAGE_SRC_NAME(message), "-actual-sink-"); if (sink) { sink += strlen("-actual-sink-"); - if (strstr(GST_MESSAGE_SRC_NAME(message), renderer_type[type]->codec)) { + if (strstr(GST_MESSAGE_SRC_NAME(message), renderer_type[type]->codec)) { logger_log(logger, LOGGER_DEBUG, "GStreamer: automatically-selected videosink" " (renderer %d: %s) is \"%ssink\"", renderer_type[type]->id + 1, renderer_type[type]->codec, sink); #ifdef X_DISPLAY_FIX renderer_type[type]->use_x11 = (strstr(sink, "ximage") || strstr(sink, "xvimage")); #endif - renderer_type[type]->autovideo = false; + renderer_type[type]->autovideo = false; } } } @@ -889,7 +889,7 @@ int video_renderer_choose_codec (bool video_is_jpeg, bool video_is_h265) { if (video_is_h265) { logger_log(logger, LOGGER_ERR, "video is h265 but the -h265 option was not used"); return -1; - } + } renderer_used = renderer_type[1]; } else { renderer_used = video_is_h265 ? renderer_type[2] : renderer_type[1]; @@ -906,7 +906,7 @@ int video_renderer_choose_codec (bool video_is_jpeg, bool video_is_h265) { GstState old_state, new_state; if (gst_element_get_state(renderer->pipeline, &old_state, &new_state, 100 * GST_MSECOND) == GST_STATE_CHANGE_FAILURE) { g_error("video pipeline failed to go into playing state"); - return -1; + return -1; } logger_log(logger, LOGGER_DEBUG, "video_pipeline state change from %s to %s\n", gst_element_state_get_name (old_state),gst_element_state_get_name (new_state)); @@ -932,12 +932,12 @@ unsigned int video_reset_callback(void * loop) { if (video_terminate) { video_terminate = false; if (renderer->appsrc) { - gst_app_src_end_of_stream (GST_APP_SRC(renderer->appsrc)); + gst_app_src_end_of_stream (GST_APP_SRC(renderer->appsrc)); } gboolean flushing = TRUE; gst_bus_set_flushing(renderer->bus, flushing); - gst_element_set_state (renderer->pipeline, GST_STATE_NULL); - g_main_loop_quit( (GMainLoop *) loop); + gst_element_set_state (renderer->pipeline, GST_STATE_NULL); + g_main_loop_quit( (GMainLoop *) loop); } return (unsigned int) TRUE; } From 250b8645f875e7b39192ed985e58e287f905b55c Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Fri, 8 Aug 2025 18:09:25 -0400 Subject: [PATCH 10/58] whitespace uxplay.cpp --- uxplay.cpp | 172 ++++++++++++++++++++++++++--------------------------- 1 file changed, 84 insertions(+), 88 deletions(-) diff --git a/uxplay.cpp b/uxplay.cpp index c276103..4a9abe4 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -372,7 +372,7 @@ static void dump_video_to_file(unsigned char *data, int datalen) { video_dumpfile_count++; snprintf(suffix, sizeof(suffix), ".%d", video_dumpfile_count); fn.append(suffix); - } + } fn.append(".h264"); video_dumpfile = fopen (fn.c_str(),"w"); if (video_dumpfile == NULL) { @@ -848,17 +848,17 @@ static bool get_ports (int nports, std::string option, const char * value, unsig static bool get_videoflip (const char *str, videoflip_t *videoflip) { if (strlen(str) > 1) return false; switch (str[0]) { - case 'I': - *videoflip = INVERT; - break; - case 'H': - *videoflip = HFLIP; - break; - case 'V': - *videoflip = VFLIP; - break; - default: - return false; + case 'I': + *videoflip = INVERT; + break; + case 'H': + *videoflip = HFLIP; + break; + case 'V': + *videoflip = VFLIP; + break; + default: + return false; } return true; } @@ -866,14 +866,14 @@ static bool get_videoflip (const char *str, videoflip_t *videoflip) { static bool get_videorotate (const char *str, videoflip_t *videoflip) { if (strlen(str) > 1) return false; switch (str[0]) { - case 'L': - *videoflip = LEFT; - break; - case 'R': - *videoflip = RIGHT; - break; - default: - return false; + case 'L': + *videoflip = LEFT; + break; + case 'R': + *videoflip = RIGHT; + break; + default: + return false; } return true; } @@ -903,17 +903,17 @@ static void parse_arguments (int argc, char *argv[]) { // Parse arguments for (int i = 1; i < argc; i++) { std::string arg(argv[i]); - if (arg == "-rc") { + if (arg == "-rc") { i++; //specifies startup file: has already been processed } else if (arg == "-allow") { if (!option_has_value(i, argc, arg, argv[i+1])) exit(1); i++; - allowed_clients.push_back(argv[i]); - } else if (arg == "-block") { + allowed_clients.push_back(argv[i]); + } else if (arg == "-block") { if (!option_has_value(i, argc, arg, argv[i+1])) exit(1); i++; - blocked_clients.push_back(argv[i]); - } else if (arg == "-restrict") { + blocked_clients.push_back(argv[i]); + } else if (arg == "-restrict") { if (i < argc - 1) { if (strlen(argv[i+1]) == 2 && strncmp(argv[i+1], "no", 2) == 0) { restrict_clients = false; @@ -942,7 +942,7 @@ static void parse_arguments (int argc, char *argv[]) { if (n > -SECOND_IN_USECS && n < SECOND_IN_USECS) { audio_delay_alac = n * 1000; /* units are nsecs */ } else { - fprintf(stderr, "invalid -async %s: requested delays must be smaller than +/- 1000 millisecs\n", argv[i] ); + fprintf(stderr, "invalid -async %s: requested delays must be smaller than +/- 1000 millisecs\n", argv[i] ); exit (1); } } @@ -962,7 +962,7 @@ static void parse_arguments (int argc, char *argv[]) { if (n > -SECOND_IN_USECS && n < SECOND_IN_USECS) { audio_delay_aac = n * 1000; /* units are nsecs */ } else { - fprintf(stderr, "invalid -vsync %s: requested delays must be smaller than +/- 1000 millisecs\n", argv[i]); + fprintf(stderr, "invalid -vsync %s: requested delays must be smaller than +/- 1000 millisecs\n", argv[i]); exit (1); } } @@ -1017,7 +1017,7 @@ static void parse_arguments (int argc, char *argv[]) { } } } else if (arg == "-m") { - if (i < argc - 1 && *argv[i+1] != '-') { + if (i < argc - 1 && *argv[i+1] != '-') { if (validate_mac(argv[++i])) { mac_address.erase(); mac_address = argv[i]; @@ -1033,18 +1033,18 @@ static void parse_arguments (int argc, char *argv[]) { } else if (arg == "-a") { use_audio = false; } else if (arg == "-d") { - if (i < argc - 1 && *argv[i+1] != '-') { + if (i < argc - 1 && *argv[i+1] != '-') { unsigned int n = 1; if (!get_value(argv[++i], &n)) { fprintf(stderr, "invalid \"-d %s\"; -d n : max n=1 (suppress packet data in debug output)\n", argv[i]); exit(1); } debug_log = true; - suppress_packet_debug_data = true; - } else { + suppress_packet_debug_data = true; + } else { debug_log = !debug_log; - suppress_packet_debug_data = false; - } + suppress_packet_debug_data = false; + } } else if (arg == "-h" || arg == "--help" || arg == "-?" || arg == "-help") { print_info(argv[0]); exit(0); @@ -1068,10 +1068,10 @@ static void parse_arguments (int argc, char *argv[]) { videosink.erase(); videosink.append(argv[++i]); std::size_t pos = videosink.find(" "); - if (pos != std::string::npos) { + if (pos != std::string::npos) { videosink_options.erase(); videosink_options = videosink.substr(pos); - videosink.erase(pos); + videosink.erase(pos); } } else if (arg == "-as") { if (!option_has_value(i, argc, arg, argv[i+1])) exit(1); @@ -1083,7 +1083,7 @@ static void parse_arguments (int argc, char *argv[]) { exit(1); } else if (arg == "-nc") { new_window_closing_behavior = false; - if (i < argc - 1) { + if (i < argc - 1) { if (strlen(argv[i+1]) == 2 && strncmp(argv[i+1], "no", 2) == 0) { new_window_closing_behavior = true; i++; @@ -1113,7 +1113,7 @@ static void parse_arguments (int argc, char *argv[]) { exit(1); } else if (arg == "-fs" ) { fullscreen = true; - } else if (arg == "-FPSdata") { + } else if (arg == "-FPSdata") { show_client_FPS_data = true; } else if (arg == "-reset") { /* now using feedback (every 1 sec ) instead of ntp timeouts (every 3 secs) to detect offline client and reset connections */ @@ -1214,7 +1214,7 @@ static void parse_arguments (int argc, char *argv[]) { int n; char *end; if (i < argc - 1 && *argv[i+1] != '-') { - n = (int) (strtof(argv[++i], &end) * SECOND_IN_USECS); + n = (int) (strtof(argv[++i], &end) * SECOND_IN_USECS); if (*end == '\0' && n >=0 && n <= 10 * SECOND_IN_USECS) { audiodelay = n; continue; @@ -1226,7 +1226,7 @@ static void parse_arguments (int argc, char *argv[]) { } else if (arg == "-pin") { setup_legacy_pairing = true; pin_pw = 1; - if (i < argc - 1 && *argv[i+1] != '-') { + if (i < argc - 1 && *argv[i+1] != '-') { unsigned int n = 9999; if (!get_value(argv[++i], &n)) { fprintf(stderr, "invalid \"-pin %s\"; -pin nnnn : max nnnn=9999, (4 digits)\n", argv[i]); @@ -1255,10 +1255,10 @@ static void parse_arguments (int argc, char *argv[]) { exit(1); } } else { - // fprintf(stderr, "option \"-key \" requires a path to a file for persistent key storage\n"); - // exit(1); - keyfile.erase(); - keyfile.append("0"); + // fprintf(stderr, "option \"-key \" requires a path to a file for persistent key storage\n"); + // exit(1); + keyfile.erase(); + keyfile.append("0"); } } else if (arg == "-pw") { setup_legacy_pairing = false; @@ -1282,15 +1282,15 @@ static void parse_arguments (int argc, char *argv[]) { fprintf(stderr, "%s cannot be written to:\noption \"-dacp \" must be to a file with write access\n", fn); exit(1); } - } else { + } else { dacpfile.append(get_homedir()); dacpfile.append("/.uxplay.dacp"); } - } else if (arg == "-taper") { + } else if (arg == "-taper") { taper_volume = true; } else if (arg == "-db") { bool db_bad = true; - double db1, db2; + double db1, db2; if ( i < argc -1) { char *end1, *end2; db1 = strtod(argv[i+1], &end1); @@ -1308,7 +1308,7 @@ static void parse_arguments (int argc, char *argv[]) { fprintf(stderr, "invalid \"-db %s\": db value must be \"low\" or \"low:high\", low < 0 and high > low are decibel gains\n", argv[i+1]); exit(1); } - i++; + i++; db_low = db1; db_high = db2; printf("db range %f:%f\n", db_low, db_high); @@ -1337,7 +1337,7 @@ static void parse_arguments (int argc, char *argv[]) { fprintf(stderr, "invalid \"-vol %s\", value must be between 0.0 (mute) and 1.0 (full volume)\n", argv[i+1]); exit(1); } - i++; + i++; } else if (arg == "-hls") { hls_support = true; if (i < argc - 1 && *argv[i+1] != '-') { @@ -1346,7 +1346,7 @@ static void parse_arguments (int argc, char *argv[]) { fprintf(stderr, "invalid \"-hls %s\"; -hls n only allows \"playbin\" video player versions 2 or 3\n", argv[i]); exit(1); } - playbin_version = (guint) n; + playbin_version = (guint) n; } } else if (arg == "-h265") { h265_support = true; @@ -1463,7 +1463,7 @@ static void process_metadata(int count, const char *dmap_tag, const unsigned cha char *str = (char *) calloc(datalen + 1, sizeof(char)); memcpy(str, metadata, datalen); metadata_text->append(str); - metadata_text->append("\n"); + metadata_text->append("\n"); free(str); } else if (debug_log) { std::string md = ""; @@ -1485,7 +1485,7 @@ static int parse_dmap_header(const unsigned char *metadata, char *tag, int *len) bool istag = true; for (int i = 0; i < 4; i++) { tag[i] = (char) *header; - if (!isalpha(tag[i])) { + if (!isalpha(tag[i])) { istag = false; } header++; @@ -1801,10 +1801,10 @@ extern "C" void report_client_request(void *cls, char *deviceid, char * model, c LOGI("connection request from %s (%s) with deviceID = %s\n", name, model, deviceid); if (restrict_clients) { *admit = check_client(deviceid); - if (*admit == false) { + if (*admit == false) { LOGI("client connections have been restricted to those with listed deviceID,\nuse \"-allow %s\" to allow this client to connect.\n", deviceid); - } + } } else { *admit = true; } @@ -1853,8 +1853,8 @@ extern "C" void video_process (void *cls, raop_ntp_t *ntp, video_decode_struct * remote_clock_offset = local_time - data->ntp_time_remote; } int count = 0; - uint64_t pts_mismatch = 0; - do { + uint64_t pts_mismatch = 0; + do { data->ntp_time_remote = data->ntp_time_remote + remote_clock_offset; pts_mismatch = video_renderer_render_buffer(data->data, &(data->data_len), &(data->nal_count), &(data->ntp_time_remote)); if (pts_mismatch) { @@ -1926,15 +1926,15 @@ extern "C" void audio_set_volume (void *cls, float volume) { /* flat rescaling of decibel range from {-30dB : 0dB} to {db_low : db_high} */ db_flat = db_low + (db_high-db_low) * frac; if (taper_volume) { - /* taper the volume reduction by the (rescaled) Airplay {-30:0} range so each reduction of - * the remaining slider length by 50% reduces the perceived volume by 50% (-10dB gain) - * (This is the "dasl-tapering" scheme offered by shairport-sync) */ + /* taper the volume reduction by the (rescaled) Airplay {-30:0} range so each reduction of + * the remaining slider length by 50% reduces the perceived volume by 50% (-10dB gain) + * (This is the "dasl-tapering" scheme offered by shairport-sync) */ db = db_high + 10.0 * (log10(frac) / log10(2.0)); db = (db > db_flat) ? db : db_flat; - } else { + } else { db = db_flat; } - /* conversion from (gain) decibels to GStreamer's linear volume scale */ + /* conversion from (gain) decibels to GStreamer's linear volume scale */ gst_volume = pow(10.0, 0.05*db); } audio_renderer_set_volume(gst_volume); @@ -2132,24 +2132,20 @@ extern "C" void on_video_acquire_playback_info (void *cls, playback_info_t *play extern "C" void log_callback (void *cls, int level, const char *msg) { switch (level) { - case LOGGER_DEBUG: { - LOGD("%s", msg); - break; - } - case LOGGER_WARNING: { - LOGW("%s", msg); - break; - } - case LOGGER_INFO: { - LOGI("%s", msg); - break; - } - case LOGGER_ERR: { - LOGE("%s", msg); - break; - } - default: - break; + case LOGGER_DEBUG: + LOGD("%s", msg); + break; + case LOGGER_WARNING: + LOGW("%s", msg); + break; + case LOGGER_INFO: + LOGI("%s", msg); + break; + case LOGGER_ERR: + LOGE("%s", msg); + break; + default: + break; } } @@ -2306,7 +2302,7 @@ static void read_config_file(const char * filename, const char * uxplay_name) { } else { options.push_back(token.c_str()); } - } + } } } file.close(); @@ -2365,7 +2361,7 @@ int main (int argc, char *argv[]) { exit(1); } rcfile = argv[i+1]; - if (stat(rcfile, &sb) == -1) { + if (stat(rcfile, &sb) == -1) { LOGE("startup file %s specified by option -rc was not found", rcfile); exit(0); } @@ -2404,7 +2400,7 @@ int main (int argc, char *argv[]) { if (dump_video) { if (video_dump_limit > 0) { LOGI("dump video using \"-vdmp %d %s\"", video_dump_limit, video_dumpfile_name.c_str()); - } else { + } else { LOGI("dump video using \"-vdmp %s\"", video_dumpfile_name.c_str()); } } @@ -2449,9 +2445,9 @@ int main (int argc, char *argv[]) { if (fullscreen && use_video) { if (videosink == "waylandsink" || videosink == "vaapisink") { videosink_options.append(" fullscreen=true"); - } else if (videosink == "kmssink") { + } else if (videosink == "kmssink") { videosink_options.append(" force_modesetting=true"); - } + } } if (videosink == "d3d11videosink" && videosink_options.empty() && use_video) { @@ -2487,8 +2483,8 @@ int main (int argc, char *argv[]) { if (pairing_register == "") { const char * homedir = get_homedir(); if (homedir) { - pairing_register = homedir; - pairing_register.append("/.uxplay.register"); + pairing_register = homedir; + pairing_register.append("/.uxplay.register"); } } } @@ -2498,13 +2494,13 @@ int main (int argc, char *argv[]) { size_t len = 0; std::string key; int clients = 0; - std::ifstream file(pairing_register); + std::ifstream file(pairing_register); if (file.is_open()) { std::string line; while (std::getline(file, line)) { /*32 bytes pk -> base64 -> strlen(pk64) = 44 chars = line[0:43]; add '\0' at line[44] */ line[44] = '\0'; - std::string pk = line.c_str(); + std::string pk = line.c_str(); registered_keys.push_back(key.assign(pk)); clients ++; } @@ -2544,7 +2540,7 @@ int main (int argc, char *argv[]) { logger_set_level(render_logger, log_level); if (use_audio) { - audio_renderer_init(render_logger, audiosink.c_str(), &audio_sync, &video_sync); + audio_renderer_init(render_logger, audiosink.c_str(), &audio_sync, &video_sync); } else { LOGI("audio_disabled"); } From e7d2901b7f07f0da11a3d97ce1ae54b659bd4431 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Fri, 8 Aug 2025 19:42:01 -0400 Subject: [PATCH 11/58] add video packet length to debug output (raop_rtp_mirror) --- lib/raop_rtp_mirror.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/raop_rtp_mirror.c b/lib/raop_rtp_mirror.c index 029c6d5..d4d7908 100644 --- a/lib/raop_rtp_mirror.c +++ b/lib/raop_rtp_mirror.c @@ -409,9 +409,9 @@ raop_rtp_mirror_thread(void *arg) uint64_t ntp_now = raop_ntp_get_local_time(); int64_t latency = (ntp_timestamp_local ? ((int64_t) ntp_now) - ((int64_t) ntp_timestamp_local) : 0); logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, - "raop_rtp video: now = %8.6f, ntp = %8.6f, latency = %9.6f, ts = %8.6f, %s %s", + "raop_rtp video: now = %8.6f, ntp = %8.6f, latency = %9.6f, ts = %8.6f, %s %s, size: %d", (double) ntp_now / SEC, (double) ntp_timestamp_local / SEC, (double) latency / SEC, - (double) ntp_timestamp_remote / SEC, packet_description, h265_video ? h265 : h264); + (double) ntp_timestamp_remote / SEC, packet_description, (h265_video ? h265 : h264), payload_size); } unsigned char* payload_out; @@ -452,7 +452,7 @@ raop_rtp_mirror_thread(void *arg) payload_out = (unsigned char*) malloc(payload_size); payload_decrypted = payload_out; } - // Decrypt data + // Decrypt data: AES-CTR encryption/decryption does not change the size of the data mirror_buffer_decrypt(raop_rtp_mirror->buffer, payload, payload_decrypted, payload_size); // It seems the AirPlay protocol prepends NALs with their size, which we're replacing with the 4-byte From ab9a9d20b800f694e3883012538cf349ff202537 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Sat, 9 Aug 2025 07:37:17 -0400 Subject: [PATCH 12/58] whitespace --- lib/raop_rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/raop_rtp.c b/lib/raop_rtp.c index 51c304e..85f7de7 100644 --- a/lib/raop_rtp.c +++ b/lib/raop_rtp.c @@ -473,7 +473,7 @@ raop_rtp_thread_udp(void *arg) raop_rtp->control_saddr_len = saddrlen; got_remote_control_saddr = true; } - } else { + } else { packetlen = recvfrom(raop_rtp->csock, (char *)packet, sizeof(packet), 0, NULL, NULL); } int type_c = packet[1] & ~0x80; From 59c3abe140535e3bbac4f01189740c8c944b3594 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Mon, 11 Aug 2025 11:36:03 -0400 Subject: [PATCH 13/58] add mirror video activity monitoring (forscreensaver inhibition) --- lib/raop.h | 3 ++- lib/raop_rtp_mirror.c | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/raop.h b/lib/raop.h index 6cbe3d6..87f486b 100644 --- a/lib/raop.h +++ b/lib/raop.h @@ -12,7 +12,7 @@ * Lesser General Public License for more details. * *=================================================================== - * modified by fduncanh 2021-23 + * modified by fduncanh 2021-25 */ #ifndef RAOP_H @@ -87,6 +87,7 @@ struct raop_callbacks_s { void (*audio_set_progress)(void *cls, unsigned int start, unsigned int curr, unsigned int 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); void (*report_client_request) (void *cls, char *deviceid, char *model, char *name, bool *admit); void (*display_pin) (void *cls, char * pin); void (*register_client) (void *cls, const char *device_id, const char *pk_str, const char *name); diff --git a/lib/raop_rtp_mirror.c b/lib/raop_rtp_mirror.c index d4d7908..e2a00f0 100644 --- a/lib/raop_rtp_mirror.c +++ b/lib/raop_rtp_mirror.c @@ -795,7 +795,7 @@ raop_rtp_mirror_thread(void *arg) * Sometimes (e.g, when the client has a locked screen), there is a 25kB trailer attached to the packet. * * This 25000 Byte trailer with unidentified content seems to be the same data each time it is sent. */ - if (payload_size && raop_rtp_mirror->show_client_FPS_data) { + if (payload_size) { //char *str = utils_data_to_string(packet, 128, 16); //logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "type 5 video packet header:\n%s", str); //free (str); @@ -815,9 +815,17 @@ raop_rtp_mirror_thread(void *arg) uint32_t plist_len; plist_t root_node = NULL; plist_from_bin((char *) payload, plist_size, &root_node); - plist_to_xml(root_node, &plist_xml, &plist_len); - logger_log(raop_rtp_mirror->logger, LOGGER_INFO, "%s", plist_xml); - free(plist_xml); + if (raop_rtp_mirror->callbacks.mirror_video_activity) { + double txusage = 0.0; + plist_t tx_usage_avg_node = plist_dict_get_item(root_node, "txUsageAvg"); + plist_get_real_val(tx_usage_avg_node, &txusage); + raop_rtp_mirror->callbacks.mirror_video_activity(raop_rtp_mirror->callbacks.cls, &txusage); + } + if (raop_rtp_mirror->show_client_FPS_data) { + plist_to_xml(root_node, &plist_xml, &plist_len); + logger_log(raop_rtp_mirror->logger, LOGGER_INFO, "%s", plist_xml); + free(plist_xml); + } } } break; From 9d28d2770216551abb30e785b5ffb2e8bfbfbe89 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Mon, 11 Aug 2025 14:23:06 -0400 Subject: [PATCH 14/58] added support for DBus-based screensaver inhibition --- CMakeLists.txt | 14 ++++ README.html | 28 ++++++- README.md | 26 ++++++- README.txt | 29 +++++++- uxplay.1 | 2 + uxplay.cpp | 193 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 286 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 61f6d5e..d797d79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,15 @@ if ( ( UNIX AND NOT APPLE ) OR USE_X11 ) endif() endif() +if( UNIX AND NOT APPLE ) + find_package(PkgConfig REQUIRED) + pkg_check_modules(DBUS dbus-1>=1.4.12) + if (DBUS_FOUND ) + add_definitions(-DDBUS ) + include_directories(${DBUS_INCLUDE_DIRS}) + endif() +endif() + if( UNIX AND NOT APPLE ) add_definitions( -DSUPPRESS_AVAHI_COMPAT_WARNING ) # convert AirPlay colormap 1:3:7:1 to sRGB (1:1:7:1), needed on Linux and BSD @@ -54,6 +63,11 @@ target_link_libraries( uxplay renderers airplay ) +if (DBUS_FOUND) +target_link_libraries( uxplay + ${DBUS_LIBRARIES} + ) +endif() install( TARGETS uxplay RUNTIME DESTINATION bin ) install( FILES uxplay.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 ) diff --git a/README.html b/README.html index 6aeef12..b98ce60 100644 --- a/README.html +++ b/README.html @@ -8,6 +8,15 @@ developed at the GitHub site https://github.com/FDH2/UxPlay (where ALL user issues should be posted, and latest versions can be found).