mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-15 00:34:05 +09:00
added support for display of ALAC audio metadata on the terminal
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
<p>UxPlay is tested on a number of systems, including (among others) Debian 10.11 “Buster” and 11.2 “Bullseye”, Ubuntu 20.04 and 21.10, Linux Mint 20.2, Pop!_OS 21.10 (NVIDIA edition), Rocky Linux 8.5 (a CentOS successor), OpenSUSE 15.3, Arch Linux 5.16.8, macOS 12.3 (Intel and M1), FreeBSD 13.0.</p>
|
||||
<p>Its main use is to act like an AppleTV for screen-mirroring (with audio) of iOS/iPadOS/macOS clients (iPhones, iPads, MacBooks) in a window on the server display (with the possibility of sharing that window on screen-sharing applications such as Zoom) on a host running Linux, macOS, or other unix. UxPlay supports a “legacy” form of Apple’s AirPlay Mirror protocol introduced in iOS 12; client devices running iOS/iPadOS 9.3.5 or later are supported, as is a (non-free) Windows-based AirPlay-client software emulator, AirMyPC. (Details of what is publically known about Apple’s AirPlay2 protocol can be found <a href="https://github.com/SteeBono/airplayreceiver/wiki/AirPlay2-Protocol">here</a> and <a href="https://emanuelecozzi.net/docs/airplay2">here</a>).</p>
|
||||
<p>The UxPlay server and its client must be on the same local area network, on which a <strong>Bonjour/Zeroconf mDNS/DNS-SD server</strong> is also running (only DNS-SD “Service Discovery” service is strictly necessary, it is not necessary that the local network also be of the “.local” mDNS-based type). On Linux and BSD Unix servers, this is usually provided by <a href="https://www.avahi.org">Avahi</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).</p>
|
||||
<p>Connections to the UxPlay server by iOS/MacOS clients can be initiated both in AirPlay Mirror mode (which streams lossily-compressed AAC audio while mirroring the client screen, or in the alternative AirPlay Audio mode which streams Apple Lossless (ALAC) audio without screen mirroring (the accompanying metadata and cover art in this mode is not displayed). <em>Switching between these two modes during an active connection is possible: in Mirror mode, close the mirror window and start an Audio mode connection, switch back by initiating a Mirror mode connection.</em> <strong>Note that Apple DRM (as in Apple TV app content on the client) cannot be decrypted by UxPlay, and (unlike with a true AppleTV), the client cannot run a http connection on the server instead of streaming content from one on the client.</strong></p>
|
||||
<p>Connections to the UxPlay server by iOS/MacOS clients can be initiated both in AirPlay Mirror mode (which streams lossily-compressed AAC audio while mirroring the client screen, or in the alternative AirPlay Audio mode which streams Apple Lossless (ALAC) audio without screen mirroring (the accompanying cover art in this mode is not displayed, but metadata is displayed in the terminal). <em>Switching between these two modes during an active connection is possible: in Mirror mode, close the mirror window and start an Audio mode connection, switch back by initiating a Mirror mode connection.</em> <strong>Note that Apple DRM (as in Apple TV app content on the client) cannot be decrypted by UxPlay, and (unlike with a true AppleTV), the client cannot run a http connection on the server instead of streaming content from one on the client.</strong></p>
|
||||
<h3 id="possibility-for-using-hardware-accelerated-h264-video-decoding-if-available.">Possibility for using hardware-accelerated h264 video-decoding, if available.</h3>
|
||||
<p>UxPlay uses <a href="https://gstreamer.freedesktop.org">GStreamer</a> Plugins for rendering audio and video, This means that video and audio are supported “out of the box”, using a choice of plugins. AirPlay streams video in h264 format: gstreamer decoding is plugin agnostic, and uses accelerated GPU hardware h264 decoders if available; if not, software decoding is used.</p>
|
||||
<p>For systems with Intel or AMD integrated graphics, hardware GPU decoding with the gstreamer VAAPI plugin is preferable. VAAPI is open-source, and in addition to Intel and AMD graphics, the open-source “Nouveau” drivers for NVIDIA graphics are also in principle supported: see <a href="https://nouveau.freedesktop.org/VideoAcceleration.html">here</a>, which requires VAAPI to be supplemented with firmware extracted from the proprietary NVIDIA drivers.</p>
|
||||
@@ -137,7 +137,7 @@
|
||||
<p>This can happen if the TCP video stream from the client stops arriving at the server, probably because of network problems (the UDP audio stream may continue to arrive). At 3-second intervals, UxPlay checks that the client is still connected by sending it a request for a NTP time signal. If a reply is not received from the client within a 0.3 sec time-window, an “ntp timeout” is registered. If a certain number (currently 5) of consecutive ntp timeouts occur, UxPlay assumes that the client is “dead”, and resets the connection, becoming available for connection to a new client, or reconnection to the previous one. Sometimes the connection may recover before the timeout limit is reached, and if the default limit is not right for your network, it can be modified using the option “-reset <em>n</em>”, where <em>n</em> is the desired timeout-limit value (<em>n</em> = 0 means “no limit”). If the connection starts to recover after ntp timeouts, a corrupt video packet from before the timeout may trigger a “connection reset by peer” error, which also causes UxPlay to reset the connection. When the connection is reset, the “frozen” mirror screen of the previous connection is left in place, and will be taken over by a new client connection when it is made.</p>
|
||||
<h3 id="failure-to-decrypt-all-video-and-audio-streams-from-old-or-non-apple-clients">6. Failure to decrypt ALL video and audio streams from old or non-Apple clients:</h3>
|
||||
<p>This triggers an unending stream of error messages, and means that the audio decryption key (also used in video decryption) was not correctly extracted from data sent by the client. This should not happen for iOS 9.3 or later clients. However, if a client uses the same older version of the protocol that is used by the Windows-based AirPlay client emulator <em>AirMyPC</em>, the protocol can be switched to the older version by the setting <code>OLD_PROTOCOL_CLIENT_USER_AGENT_LIST</code> in lib/global.h. UxPlay reports the client’s “User Agent” string when it connects. If some other client also fails to decrypt all audio and video, try adding its “User Agent” string in place of “xxx” in the entry “AirMyPC/2.0;xxx” in global.h and rebuild uxplay.</p>
|
||||
<p>Note that Uxplay declares itself to be an AppleTV3,2 with a sourceVersion 220.68; this can also be changed in global.h. It had been thought that it was necessary for UxPlay to claim to be an older 32 bit AppleTV model that cannot run modern 64bit tvOS, in order for the client to use a “legacy” protocol for pairing with the server (see the <em>“Notes on AirPlay protocol versions”</em> at the end of this README). However, UxPlay still works if it declares itself as an AppleTV6,2 with sourceVersion 380.20.1 (an AppleTV 4K 1st gen, introduced 2017, running tvOS 12.2.1), so it is unclear what setting prompts the client to use the “legacy” protocol needed by UxPlay.</p>
|
||||
<p>Note that Uxplay declares itself to be an AppleTV3,2 with a sourceVersion 220.68; this can also be changed in global.h. It had been thought that it was necessary for UxPlay to claim to be an older 32 bit AppleTV model that cannot run modern 64bit tvOS, in order for the client to use a “legacy” protocol for pairing with the server (see the <em>“Notes on AirPlay protocol versions”</em> at the end of this README). However, UxPlay still works if it declares itself as an AppleTV6,2 with sourceVersion 380.20.1 (an AppleTV 4K 1st gen, introduced 2017, running tvOS 12.2.1); it seems that the use of “legacy” protocol just requires bit 27 (listed as “SupportsLegacyPairing”) of the “features” plist code (reported to the client by the AirPlay server) to be set.</p>
|
||||
<h1 id="changelog">ChangeLog</h1>
|
||||
<p>1.52 2022-05-05 Cleaned up initial audio sync code, and reformatted streaming debug output (readable aligned timestamps with decimal points in seconds). Eliminate memory leaks (found by valgrind).</p>
|
||||
<p>1.51 2022-04-24 Reworked options forVideo4Linux2 support (new option -v4l2) and short options -rpi, -rpifb, -rpiwl as synonyms for -v4l2, -v4l2 -vs kmssink, and -v4l2 -vs waylandsink. Reverted a change from 1.48 that broke reconnection after “Stop Mirroring” is sent by client.</p>
|
||||
|
||||
37
README.md
37
README.md
@@ -45,7 +45,8 @@ AirPlay-client software emulator, AirMyPC.
|
||||
|
||||
The UxPlay server and its client must be on the same local area network,
|
||||
on which a **Bonjour/Zeroconf mDNS/DNS-SD server** is also running
|
||||
(only DNS-SD "Service Discovery" service is strictly necessary, it is not necessary that the local network also be of the ".local" mDNS-based type).
|
||||
(only DNS-SD "Service Discovery" service is strictly necessary, it is not necessary
|
||||
that the local network also be of the ".local" mDNS-based type).
|
||||
On Linux and BSD Unix servers, this is usually provided by [Avahi](https://www.avahi.org),
|
||||
through the avahi-daemon service, and is included in most Linux distributions (this
|
||||
service can also be provided by macOS, iOS or Windows servers).
|
||||
@@ -54,8 +55,9 @@ Connections to the UxPlay server by
|
||||
iOS/MacOS clients can be initiated both in AirPlay Mirror mode (which streams
|
||||
lossily-compressed AAC audio while mirroring the client screen,
|
||||
or in the alternative AirPlay Audio mode which streams
|
||||
Apple Lossless (ALAC) audio without screen mirroring (the accompanying metadata and cover art in
|
||||
this mode is not displayed). _Switching between these two modes during an active connection is
|
||||
Apple Lossless (ALAC) audio without screen mirroring (the accompanying cover art in
|
||||
this mode is not displayed, but metadata is displayed in the terminal).
|
||||
_Switching between these two modes during an active connection is
|
||||
possible: in Mirror mode, close the mirror window and start an Audio mode connection,
|
||||
switch back by initiating a Mirror mode connection._ **Note that Apple DRM
|
||||
(as in Apple TV app content on the client) cannot be decrypted by UxPlay,
|
||||
@@ -81,7 +83,8 @@ NVIDIA's CUDA driver `libcuda.so` is installed.
|
||||
This plugin should be used with options
|
||||
`uxplay -vd nvh264dec -vs glimagesink`. For GStreamer-1.16.3
|
||||
or earlier, the
|
||||
plugin is called `nvdec`, and must be built by the user: see [these instructions](https://github.com/FDH2/UxPlay/wiki/NVIDIA-nvdec-and-nvenc-plugins).
|
||||
plugin is called `nvdec`, and must be built by the user:
|
||||
see [these instructions](https://github.com/FDH2/UxPlay/wiki/NVIDIA-nvdec-and-nvenc-plugins).
|
||||
This older form of the plugin should be used with the `-vd nvdec -vs glimagesink` uxplay options.
|
||||
|
||||
* **GPU Support for Raspberry Pi**
|
||||
@@ -141,7 +144,8 @@ Make sure that your distribution provides OpenSSL 1.1.1 or later, and libplist 2
|
||||
need to build and install these from source (see below).
|
||||
|
||||
In a terminal window, change directories to the source directory of the
|
||||
downloaded source code ("UxPlay-\*", "\*" = "master" or the release tag for zipfile downloads, "UxPlay" for "git clone" downloads), then follow the instructions below:
|
||||
downloaded source code ("UxPlay-\*", "\*" = "master" or the release tag for zipfile downloads, "UxPlay"
|
||||
for "git clone" downloads), then follow the instructions below:
|
||||
|
||||
**Note:** By default UxPlay will be built with optimization for the computer it is built on; when this is
|
||||
not the case, as when you are packaging for a distribution, use the cmake option `-DNO_MARCH_NATIVE=ON`.
|
||||
@@ -162,17 +166,21 @@ for GStreamer-1.18.x or earlier**.
|
||||
is needed for hardware-accelerated h264 video decoding by Intel or AMD graphics (but not for use with NVIDIA using proprietary drivers).
|
||||
Also install "**tools**" to get the utility gst-inspect-1.0 for examining the GStreamer installation.
|
||||
|
||||
_If you intend to modify the code, use a separate "build" directory: replace_ "```cmake [ ] . ```" _by_ "```mkdir build ; cd build ; cmake [ ] ..```"; _you can then clean
|
||||
the build directory with_ "```rm -rf build/* ```" _(run from within the UxPlay source directory) without affecting the source directories which contain your modifications_.
|
||||
_If you intend to modify the code, use a separate "build" directory:
|
||||
replace_ "`cmake [ ] .`" _by_ "``mkdir build ; cd build ; cmake [ ] ..``"; _you can then clean
|
||||
the build directory with_ "`rm -rf build/* `" _(run from within the UxPlay source directory) without affecting
|
||||
the source directories which contain your modifications_.
|
||||
|
||||
The above script installs the executable file "`uxplay`" to `/usr/local/bin`, (and installs a manpage to somewhere like `/usr/local/share/man/man1` and README
|
||||
The above script installs the executable file "`uxplay`" to `/usr/local/bin`, (and installs a manpage to
|
||||
somewhere like `/usr/local/share/man/man1` and README
|
||||
files to somewhere like `/usr/local/share/doc/uxplay`).
|
||||
It can also be found in the build directory after the build
|
||||
processs.
|
||||
|
||||
**Finally, run uxplay in a terminal window**. If it is not seen by the iOS client's drop-down "Screen Mirroring" panel,
|
||||
check that your DNS-SD server (usually avahi-daemon) is running: do this in a terminal window with ```systemctl status avahi-daemon```.
|
||||
If this shows the avahi-daemon is not running, control it with ```sudo systemctl [start,stop,enable,disable] avahi-daemon``` (or avahi-daemon.service).
|
||||
If this shows the avahi-daemon is not running, control it with ```sudo systemctl [start,stop,enable,disable] avahi-daemon```
|
||||
(or avahi-daemon.service).
|
||||
If UxPlay is seen, but the client fails to connect when it is selected, there may be a firewall on the server that prevents
|
||||
UxPlay from receiving client connection requests unless some network ports are opened. See [Troubleshooting](#troubleshooting) below for
|
||||
help with this or other problems. See [Usage](#usage) for run-time options.
|
||||
@@ -189,7 +197,8 @@ GStreamer packages (you may need to use versions from [Packman](https://ftp.gwd
|
||||
gstreamer-devel gstreamer-plugins-base-devel gstreamer-plugins-libav gstreamer-plugins-bad (+ gstreamer-plugins-vaapi for Intel graphics).
|
||||
|
||||
* **Arch Linux**
|
||||
(sudo pacman -Syu) openssl libplist avahi gst-plugins-base gst-plugins-good gst-plugins-bad gst-libav (+ gstreamer-vaapi for Intel graphics). (**Also available as a package in AUR**).
|
||||
(sudo pacman -Syu) openssl libplist avahi gst-plugins-base gst-plugins-good gst-plugins-bad gst-libav (+ gstreamer-vaapi
|
||||
for Intel graphics). (**Also available as a package in AUR**).
|
||||
|
||||
* **FreeBSD:** (sudo pkg install) libplist gstreamer1, gstreamer1-libav, gstreamer1-plugins, gstreamer1-plugins-*
|
||||
(\* = core, good, bad, x, gtk, gl, vulkan, pulse ...), (+ gstreamer1-vaapi for Intel graphics).
|
||||
@@ -235,7 +244,8 @@ and then run "sudo ldconfig".
|
||||
_Note: A native AirPlay Server feature is included in macOS 12 Monterey, but is restricted to recent hardware.
|
||||
UxPlay can run on older macOS systems that will not be able to run Monterey, or can run Monterey but not AirPlay._
|
||||
|
||||
These instructions for macOS asssume that the Xcode command-line developer tools are installed (if Xcode is installed, open the Terminal, type "sudo xcode-select --install" and accept the conditions).
|
||||
These instructions for macOS asssume that the Xcode command-line developer tools are installed (if Xcode is
|
||||
installed, open the Terminal, type "sudo xcode-select --install" and accept the conditions).
|
||||
|
||||
It is also assumed that CMake >= 3.13 is installed:
|
||||
this can be done with package managers [MacPorts](http://www.macports.org),
|
||||
@@ -591,8 +601,9 @@ to use a "legacy" protocol for pairing with the server (see
|
||||
the _"Notes on AirPlay protocol versions"_ at the end of this README).
|
||||
However, UxPlay still works if it declares itself as an AppleTV6,2 with
|
||||
sourceVersion 380.20.1 (an AppleTV 4K 1st gen, introduced 2017, running
|
||||
tvOS 12.2.1), so it is unclear what setting prompts the client
|
||||
to use the "legacy" protocol needed by UxPlay.
|
||||
tvOS 12.2.1); it seems that the use of "legacy" protocol just requires bit 27 (listed as
|
||||
"SupportsLegacyPairing") of the
|
||||
"features" plist code (reported to the client by the AirPlay server) to be set.
|
||||
|
||||
# ChangeLog
|
||||
1.52 2022-05-05 Cleaned up initial audio sync code, and reformatted streaming debug output (readable aligned timestamps with
|
||||
|
||||
21
README.txt
21
README.txt
@@ -68,14 +68,14 @@ Connections to the UxPlay server by iOS/MacOS clients can be initiated
|
||||
both in AirPlay Mirror mode (which streams lossily-compressed AAC audio
|
||||
while mirroring the client screen, or in the alternative AirPlay Audio
|
||||
mode which streams Apple Lossless (ALAC) audio without screen mirroring
|
||||
(the accompanying metadata and cover art in this mode is not displayed).
|
||||
*Switching between these two modes during an active connection is
|
||||
possible: in Mirror mode, close the mirror window and start an Audio
|
||||
mode connection, switch back by initiating a Mirror mode connection.*
|
||||
**Note that Apple DRM (as in Apple TV app content on the client) cannot
|
||||
be decrypted by UxPlay, and (unlike with a true AppleTV), the client
|
||||
cannot run a http connection on the server instead of streaming content
|
||||
from one on the client.**
|
||||
(the accompanying cover art in this mode is not displayed, but metadata
|
||||
is displayed in the terminal). *Switching between these two modes during
|
||||
an active connection is possible: in Mirror mode, close the mirror
|
||||
window and start an Audio mode connection, switch back by initiating a
|
||||
Mirror mode connection.* **Note that Apple DRM (as in Apple TV app
|
||||
content on the client) cannot be decrypted by UxPlay, and (unlike with a
|
||||
true AppleTV), the client cannot run a http connection on the server
|
||||
instead of streaming content from one on the client.**
|
||||
|
||||
### Possibility for using hardware-accelerated h264 video-decoding, if available.
|
||||
|
||||
@@ -775,8 +775,9 @@ to use a "legacy" protocol for pairing with the server (see the *"Notes
|
||||
on AirPlay protocol versions"* at the end of this README). However,
|
||||
UxPlay still works if it declares itself as an AppleTV6,2 with
|
||||
sourceVersion 380.20.1 (an AppleTV 4K 1st gen, introduced 2017, running
|
||||
tvOS 12.2.1), so it is unclear what setting prompts the client to use
|
||||
the "legacy" protocol needed by UxPlay.
|
||||
tvOS 12.2.1); it seems that the use of "legacy" protocol just requires
|
||||
bit 27 (listed as "SupportsLegacyPairing") of the "features" plist code
|
||||
(reported to the client by the AirPlay server) to be set.
|
||||
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
42
uxplay.cpp
42
uxplay.cpp
@@ -873,6 +873,45 @@ extern "C" void video_report_size(void *cls, float *width_source, float *height_
|
||||
video_renderer_size(width_source, height_source, width, height);
|
||||
}
|
||||
|
||||
extern "C" void audio_set_metadata(void *cls, const void *buffer, int buflen) {
|
||||
unsigned char mark[]={ 0x00, 0x00, 0x00 }; /*daap seperator mark */
|
||||
if (buflen > 4) {
|
||||
printf("==============Audio Metadata=============\n");
|
||||
const unsigned char *metadata = (const unsigned char *) buffer;
|
||||
const char *tag = (const char *) buffer;
|
||||
int len;
|
||||
metadata += 4;
|
||||
for (int i = 4; i < buflen ; i++) {
|
||||
if (memcmp (metadata, mark, 3) == 0 && (len = (int) *(metadata +3))) {
|
||||
bool found_text = true;
|
||||
if (strcmp (tag, "asal") == 0) {
|
||||
printf("Album: ");
|
||||
} else if (strcmp (tag, "asar") == 0) {
|
||||
printf("Artist: ");
|
||||
} else if (strcmp (tag, "ascp") == 0) {
|
||||
printf("Composer: ");
|
||||
} else if (strcmp (tag, "asgn") == 0) {
|
||||
printf("Genre: ");
|
||||
} else if (strcmp (tag, "minm") == 0) {
|
||||
printf("Title: ");
|
||||
} else {
|
||||
found_text = false;
|
||||
}
|
||||
if (found_text) {
|
||||
const unsigned char *text = metadata + 4;
|
||||
for (int j = 0; j < len ; j++) {
|
||||
printf("%c", *text);
|
||||
text++;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
metadata++;
|
||||
tag++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void log_callback (void *cls, int level, const char *msg) {
|
||||
switch (level) {
|
||||
case LOGGER_DEBUG: {
|
||||
@@ -912,7 +951,8 @@ int start_raop_server (std::vector<char> hw_addr, std::string name, unsigned sho
|
||||
raop_cbs.audio_set_volume = audio_set_volume;
|
||||
raop_cbs.audio_get_format = audio_get_format;
|
||||
raop_cbs.video_report_size = video_report_size;
|
||||
|
||||
raop_cbs.audio_set_metadata = audio_set_metadata;
|
||||
|
||||
/* set max number of connections = 2 */
|
||||
raop = raop_init(2, &raop_cbs);
|
||||
if (raop == NULL) {
|
||||
|
||||
Reference in New Issue
Block a user