diff --git a/README.md b/README.md index 78647cd..f7abc70 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# UxPlay 1.35 +# UxPlay 1.35.1 This project is a GPLv3 unix AirPlay server which now also works on macOS. Its main use is to act like an AppleTV for screen-mirroring (with audio) of iOS/macOS clients @@ -12,7 +12,11 @@ On Linux and BSD Unix servers, this is usually provided by [Avahi](https://www.a through the avahi-daemon service, and is included in most Linux distributions (this service can also be provided by macOS, iOS or Windows servers). -UxPlay 1.35 is based on https://github.com/FD-/RPiPlay, with GStreamer integration from +_Note: UxPlay currently only uses the AirPlay screen-mirroring protocol +(not the AirPlay audio-only streaming protocol) +but the **-vs 0** option streams audio without displaying the client's screen._ + +UxPlay 1.35.1 is based on https://github.com/FD-/RPiPlay, with GStreamer integration from https://github.com/antimof/UxPlay. (UxPlay only uses GStreamer, and does not contain the alternative Raspberry-Pi-specific audio and video renderers also found in RPiPlay.) @@ -252,18 +256,23 @@ Also: image transforms that had been added to RPiPlay have been ported to UxPlay "..." might allow some parameters to be included with the videosink name. (Some choices of videosink might not work on your system.) +**-vs 0** suppresses display of streamed video, but plays streamed audio. (The client's screen + is still mirrored at a reduced rate of 1 frame per second, but is not rendered or displayed.) + **-t _timeout_** will cause the server to relaunch (without stopping uxplay) if no connections -have been present during the previous _timeout_ seconds. (You may wish to use this because the Server may not be -visible to new Clients that were inactive when the Server was launched, and an idle Bonjour -registration also eventually becomes unavailable for new connections.) The timer only starts once a -Client has first made a mirror connection and then has disconnected with "Stop Mirrroring". -_This option should **not** be -used if the display window is an OpenGL window on macOS, as such an OpenGL window created -by GStreamer does not terminate correctly (it causes a segfault) -if it is still open when the GStreamer pipeline is closed._ + have been present during the previous _timeout_ seconds. (You may wish to use this because the Server may not be + visible to new Clients that were inactive when the Server was launched, and an idle Bonjour + registration also eventually becomes unavailable for new connections.) The timer only starts once a + Client has first made a mirror connection and then has disconnected with "Stop Mirrroring". + _This option should **not** be + used if the display window is an OpenGL window on macOS, as such an OpenGL window created + by GStreamer does not terminate correctly (it causes a segfault) + if it is still open when the GStreamer pipeline is closed._ # ChangeLog +1.35.1 2021-09-28 Added the -vs 0 option for streaming audio, but not displaying video. + 1.35 2021-09-10 now uses a GLib MainLoop, and builds on macOS (tested on Intel Mac, 10.15 ). New option -t _timeout_ for relaunching server if no connections were active in previous _timeout_ seconds (to renew Bonjour registration). diff --git a/renderers/video_renderer_gstreamer.c b/renderers/video_renderer_gstreamer.c index 5c60ea8..02bfae8 100644 --- a/renderers/video_renderer_gstreamer.c +++ b/renderers/video_renderer_gstreamer.c @@ -188,9 +188,9 @@ void video_renderer_flush(video_renderer_t *renderer) { void video_renderer_destroy(video_renderer_t *renderer) { gst_app_src_end_of_stream (GST_APP_SRC(renderer->appsrc)); - gst_object_unref(renderer->bus); + if(renderer->bus) gst_object_unref(renderer->bus); gst_element_set_state (renderer->pipeline, GST_STATE_NULL); - gst_object_unref (renderer->pipeline); + if(renderer->pipeline) gst_object_unref (renderer->pipeline); #ifdef X_DISPLAY_FIX free(renderer->gst_window); #endif diff --git a/uxplay.cpp b/uxplay.cpp index 7161b62..f76f147 100755 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -34,7 +34,7 @@ #include "renderers/video_renderer.h" #include "renderers/audio_renderer.h" -#define VERSION "1.35" +#define VERSION "1.35.1" #define DEFAULT_NAME "UxPlay" #define DEFAULT_DEBUG_LOG false @@ -58,6 +58,7 @@ static uint open_connections = 0; static bool connections_stopped = false; static unsigned int server_timeout = 0; static unsigned int counter; +static bool use_video = true; gboolean connection_callback (gpointer loop){ if (!connections_stopped) { @@ -85,11 +86,12 @@ static gboolean sigterm_callback(gpointer loop) { static void main_loop() { guint connection_watch_id = 0; + guint gst_bus_watch_id = 0; GMainLoop *loop = g_main_loop_new(NULL,FALSE); if (server_timeout) { connection_watch_id = g_timeout_add_seconds(1, (GSourceFunc) connection_callback, (gpointer) loop); } - guint gst_bus_watch_id = (guint) video_renderer_listen((void *)loop, video_renderer); + if (use_video) gst_bus_watch_id = (guint) video_renderer_listen((void *)loop, video_renderer); guint sigterm_watch_id = g_unix_signal_add(SIGTERM, (GSourceFunc) sigterm_callback, (gpointer) loop); guint sigint_watch_id = g_unix_signal_add(SIGINT, (GSourceFunc) sigint_callback, (gpointer) loop); relaunch_server = true; @@ -160,6 +162,7 @@ static void print_info (char *name) { printf("-t n Relaunch server if no connection existed in last n seconds\n"); printf("-vs Choose the GStreamer videosink; default \"autovideosink\"\n"); printf(" choices: ximagesink,xvimagesink,vaapisink,fpsdisplaysink, etc.\n"); + printf("-vs 0 Streamed audio only, with no video display window\n"); printf("-d Enable debug logging\n"); printf("-v/-h Displays this help and version information\n"); } @@ -485,6 +488,11 @@ int start_server (std::vector hw_addr, std::string name, unsigned short di /* write desired display pixel width, pixel height, refresh_rate, max_fps, overscanned. */ /* use 0 for default values 1920,1080,60,30,0; these are sent to the Airplay client */ + + if(videosink == "0") { + use_video = false; + display[3] = 1; /* set fps to 1 frame per sec when no video will be shown */ + } raop_set_display(raop, display[0], display[1], display[2], display[3], display[4]); /* network port selection (ports listed as "0" will be dynamically assigned) */ @@ -518,7 +526,7 @@ int start_server (std::vector hw_addr, std::string name, unsigned short di return -1; } - if (video_renderer) video_renderer_start(video_renderer); + if (use_video && video_renderer) video_renderer_start(video_renderer); if (audio_renderer) audio_renderer_start(audio_renderer); unsigned short port = raop_get_port(raop);