Merge pull request #135 from FDH2/master

minor README update (building libplist from source)
This commit is contained in:
antimof
2023-06-03 22:34:46 +03:00
committed by GitHub
16 changed files with 355 additions and 145 deletions

View File

@@ -1,6 +1,6 @@
<h1
id="uxplay-1.64-airplay-mirror-and-airplay-audio-server-for-linux-macos-and-unix-now-also-runs-on-windows.">UxPlay
1.64: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix
id="uxplay-1.65-airplay-mirror-and-airplay-audio-server-for-linux-macos-and-unix-now-also-runs-on-windows.">UxPlay
1.65: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix
(now also runs on Windows).</h1>
<h3
id="now-developed-at-the-github-site-httpsgithub.comfdh2uxplay-where-all-user-issues-should-be-posted.">Now
@@ -82,27 +82,29 @@ antimof site is no longer involved in development, but periodically
posts updates pulled from the new main <a
href="https://github.com/FDH2/UxPlay">UxPlay site</a>).</p>
<p>UxPlay is tested on a number of systems, including (among others)
Debian 10.11 “Buster” and 11.2 “Bullseye”, Ubuntu 20.04 LTS and 22.04.1
LTS, (also Ubuntu derivatives Linux Mint 20.3, Pop!_OS 22.04 (NVIDIA
edition)), Rocky Linux 9.1 (a CentOS successor), Fedora 36, OpenSUSE
15.4, Arch Linux 22.10, macOS 13.3 (Intel and M2), FreeBSD 13.2, Windows
10 and 11 (64 bit).</p>
Debian (10 “Buster”, 11 “Bullseye”, 12 “Bookworm”), Ubuntu (20.04 LTS,
22.04 LTS, 23.04; also Ubuntu derivatives Linux Mint 20.3, Pop!_OS 22.04
(NVIDIA edition)), Red Hat and clones (Fedora 38, Rocky Linux 9.2),
OpenSUSE 15.4, Arch Linux 23.05, macOS 13.3 (Intel and M2), FreeBSD
13.2, Windows 10 and 11 (64 bit).</p>
<p>On Raspberry Pi 4 model B, it is tested on Raspberry Pi OS (Bullseye)
(32- and 64-bit), Ubuntu 22.04 and 22.10, Manjaro RPi4 23.02, and
(32- and 64-bit), Ubuntu 22.04 LTS and 23.04, Manjaro RPi4 23.02, and
(without hardware video decoding) on OpenSUSE 15.4. Also tested on
Raspberry Pi 3 model B+.</p>
<p>Its main use is to act like an AppleTV for screen-mirroring (with
audio) of iOS/iPadOS/macOS clients (iPhone, iPod Touch, iPad, Mac
computers) on the server display of a host running Linux, macOS, or
other unix (and now also Microsoft Windows). UxPlay supports Apples
AirPlay2 protocol using “Legacy Pairing”, but some features are missing.
(Details of what is publicly known about Apples AirPlay 2 protocol can
be found <a href="https://openairplay.github.io/airplay-spec/">here</a>,
<a
AirPlay2 protocol using “Legacy Protocol”, but some features are
missing. (Details of what is publicly known about Apples AirPlay 2
protocol can be found <a
href="https://openairplay.github.io/airplay-spec/">here</a>, <a
href="https://github.com/SteeBono/airplayreceiver/wiki/AirPlay2-Protocol">here</a>
and <a href="https://emanuelecozzi.net/docs/airplay2">here</a>). While
there is no guarantee that future iOS releases will keep supporting
“Legacy Pairing”, the recent iOS 16 release continues support.</p>
and <a href="https://emanuelecozzi.net/docs/airplay2">here</a>; see also
<a href="https://pyatv.dev/documentation/protocols">pyatv</a> which
could be a resource for adding modern protocols.) While there is no
guarantee that future iOS releases will keep supporting “Legacy
Protocol”, the recent iOS 16 release continues support.</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
@@ -286,7 +288,8 @@ gstreamer1-devel gstreamer1-plugins-base-devel (+libX11-devel for
fullscreen X11) <em>(some of these may be in the “CodeReady” add-on
repository, called “PowerTools” by clones)</em></p></li>
<li><p><strong>OpenSUSE:</strong> (sudo zypper install) libopenssl-devel
libplist-devel avahi-compat-mDNSResponder-devel gstreamer-devel
libplist-2_0-devel (formerly libplist-devel)
avahi-compat-mDNSResponder-devel gstreamer-devel
gstreamer-plugins-base-devel (+ libX11-devel for fullscreen
X11).</p></li>
<li><p><strong>Arch Linux</strong> (<em>Also available as a package in
@@ -1127,6 +1130,15 @@ when the client sends the “Stop Mirroring” signal, try the no-close
option “-nc” that leaves the video window open.</p>
<h3 id="gstreamer-issues-missing-plugins-etc.">4. GStreamer issues
(missing plugins, etc.):</h3>
<ul>
<li>clearing the users GStreamer cache with
<code>rm -rf ~/.cache/gstreamer-1.0/*</code> may be the solution to
problems where gst-inspect-1.0 does not show a plugin that you believe
is installed. The cache will be regenerated next time GStreamer is
started. <strong>This is the solution to puzzling problems that turn out
to come from corruption of the cache, and should be tried
first.</strong></li>
</ul>
<p>If UxPlay fails to start, with a message that a required GStreamer
plugin (such as “libav”) was not found, first check with the GStreamer
tool gst-inspect-1.0 to see what GStreamer knows is available. (You may
@@ -1138,13 +1150,6 @@ installed (as one user found), try entirely removing and reinstalling
the package. That user found that a solution to a “<strong>Required
gstreamer plugin libav not found</strong>” message that kept recurring
was to clear the users gstreamer cache.</p>
<ul>
<li>clearing the users GStreamer cache with
<code>rm -rf ~/.cache/gstreamer-1.0/*</code> may be the solution to
problems where gst-inspect-1.0 does not show a plugin that you believe
is installed. The cache will be regenerated next time GStreamer is
started.</li>
</ul>
<p>If it fails to start with an error like
<code>no element "avdec_aac"</code> this is because even though
gstreamer-libav is installed. it is incomplete because some plugins are
@@ -1211,6 +1216,21 @@ when it is made.</li>
id="protocol-issues-such-as-failure-to-decrypt-all-video-and-audio-streams-from-old-or-non-apple-clients">6.
Protocol issues, such as failure to decrypt ALL video and audio streams
from old or non-Apple clients:</h3>
<ul>
<li><strong>NEW</strong> As UxPlay only connects to one client at any
time, it can work without the client pairing setup, allowing faster
connections.</li>
</ul>
<p>This is allowed by disabling “Supports Legacy Pairing” (bit 27) in
the “features” code UxPlay advertises on DNS-SD Service Discovery. Most
clients will then not attempt to setup the “shared secret key” for
pairing.</p>
<ul>
<li><strong>This new behavior (since UxPlay-1.65) can be reverted to the
previous behavior by uncommenting the previous “FEATURES_1” setting (and
commenting out the new one) in lib/dnssdint.h, and then rebuilding
UxPlay.</strong></li>
</ul>
<p>A protocol failure may trigger 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
@@ -1230,13 +1250,23 @@ 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. 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>
380.20.1 (an AppleTV 4K 1st gen, introduced 2017, running tvOS 12.2.1).
It was previously thought that use of “legacy” protocol requires bit 27
(“SupportsLegacyPairing”) of the “features” plist code (reported to the
client by the AirPlay server) to be set, but it was recently discovered
that it was possible to switch that off (after a small protocol
modification) to eliminate a 5 second delay by the client in making
connections to the server.</p>
<p>The “features” code and other settings are set in
<code>UxPlay/lib/dnssdint.h</code>.</p>
<h1 id="changelog">Changelog</h1>
<p>1.65 2023-05-31 Eliminate pair_setup part of connection protocol to
allow faster connections with clients (thanks to <span class="citation"
data-cites="shuax">@shuax</span> #176 for this discovery); to revert,
uncomment a line in lib/dnssdint.h. Disconnect from audio device when
connection closes, to not block its use by other apps if uxplay is
running but not connected. Fix for AirMyPC client (broken since 1.60),
so its older non-NTP timestamp protocol works with -vsync.</p>
<p>1.64 2023-04-23 Timestamp-based synchronization of audio and video is
now the default in Mirror mode. (Use “-vsync no” to restore previous
behavior.) A configuration file can now be used for startup options.
@@ -1390,13 +1420,17 @@ then run “sudo ldconfig”.</p>
can avoid this step by installing libplist-dev and libplist3 from Debian
10 or Ubuntu 18.04.)</em> As well as the usual build tools (autoconf,
automake, libtool), you may need to also install some libpython*-dev
package. Download the latest source from <a
href="https://github.com/libimobiledevice/libplist">https://github.com/libimobiledevice/libplist</a>:
get <a
href="https://github.com/libimobiledevice/libplist/archive/refs/heads/master.zip">libplist-master.zip</a>,
then (“unzip libplist-master.zip ; cd libplist-master”), build/install
(“./autogen.sh ; make ; sudo make install”). This will probably install
libplist-2.0.* in /usr/local/lib.</p>
package. Download the latest source with git from <a
href="https://github.com/libimobiledevice/libplist">https://github.com/libimobiledevice/libplist</a>,
or get the source from the Releases section (use the *.tar.bz2 release,
<strong>not</strong> the *.zip or *.tar.gz versions): download <a
href="https://github.com/libimobiledevice/libplist/releases/download/2.3.0/libplist-2.3.0.tar.bz2">libplist-2.3.0</a>,
then unpack it (“tar -xvjf libplist-2.3.0.tar.bz2 ; cd libplist-2.3.0”),
and build/install it: (“./configure ; make ; sudo make install”). This
will probably install libplist-2.0.* in /usr/local/lib. The new
libplist-2.3.0 release should be compatible with UxPlay; <a
href="https://github.com/libimobiledevice/libplist/releases/download/2.2.0/libplist-2.2.0.tar.bz2">libplist-2.2.0</a>
is also available if there are any issues.</p>
<p><em>(Ignore the following for builds on MacOS:)</em> On some systems
like Debian or Ubuntu, you may also need to add a missing entry
<code>/usr/local/lib</code> in /etc/ld.so.conf (or place a file

View File

@@ -1,4 +1,4 @@
# UxPlay 1.64: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix (now also runs on Windows).
# UxPlay 1.65: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix (now also runs on Windows).
### Now developed at the GitHub site [https://github.com/FDH2/UxPlay](https://github.com/FDH2/UxPlay) (where all user issues should be posted).
@@ -59,23 +59,24 @@ from OpenMAX-based [RPiPlay](https://github.com/FD-/RPiPlay), which in turn deri
development, but periodically posts updates pulled from the new
main [UxPlay site](https://github.com/FDH2/UxPlay)).
UxPlay is tested on a number of systems, including (among others) Debian 10.11 "Buster" and 11.2 "Bullseye",
Ubuntu 20.04 LTS and 22.04.1 LTS, (also Ubuntu derivatives Linux Mint 20.3, Pop!\_OS 22.04 (NVIDIA edition)),
Rocky Linux 9.1 (a CentOS successor), Fedora 36, OpenSUSE 15.4, Arch Linux 22.10, macOS 13.3 (Intel and M2),
UxPlay is tested on a number of systems, including (among others) Debian (10 "Buster", 11 "Bullseye", 12 "Bookworm"),
Ubuntu (20.04 LTS, 22.04 LTS, 23.04; also Ubuntu derivatives Linux Mint 20.3, Pop!\_OS 22.04 (NVIDIA edition)), Red Hat and clones (Fedora 38,
Rocky Linux 9.2), OpenSUSE 15.4, Arch Linux 23.05, macOS 13.3 (Intel and M2),
FreeBSD 13.2, Windows 10 and 11 (64 bit).
On Raspberry Pi 4 model B, it is tested on Raspberry Pi OS (Bullseye) (32- and 64-bit), Ubuntu 22.04 and 22.10, Manjaro RPi4 23.02,
On Raspberry Pi 4 model B, it is tested on Raspberry Pi OS (Bullseye) (32- and 64-bit), Ubuntu 22.04 LTS and 23.04, Manjaro RPi4 23.02,
and (without hardware video decoding) on OpenSUSE 15.4. Also tested on Raspberry Pi 3 model B+.
Its main use is to act like an AppleTV for screen-mirroring (with audio) of iOS/iPadOS/macOS clients
(iPhone, iPod Touch, iPad, Mac computers) on the server display
of a host running Linux, macOS, or other unix (and now also Microsoft Windows). UxPlay supports
Apple's AirPlay2 protocol using "Legacy Pairing", but some features are missing.
Apple's AirPlay2 protocol using "Legacy Protocol", but some features are missing.
(Details of what is publicly known about Apple's AirPlay 2 protocol can be found
[here](https://openairplay.github.io/airplay-spec/),
[here](https://github.com/SteeBono/airplayreceiver/wiki/AirPlay2-Protocol) and
[here](https://emanuelecozzi.net/docs/airplay2)). While there is no guarantee that future
iOS releases will keep supporting "Legacy Pairing", the recent iOS 16 release continues support.
[here](https://emanuelecozzi.net/docs/airplay2); see also [pyatv](https://pyatv.dev/documentation/protocols) which could be
a resource for adding modern protocols.) While there is no guarantee that future
iOS releases will keep supporting "Legacy Protocol", the recent iOS 16 release continues support.
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
@@ -241,7 +242,7 @@ may be in the "CodeReady" add-on repository, called "PowerTools" by clones)_
* **OpenSUSE:**
(sudo zypper install) libopenssl-devel libplist-devel
(sudo zypper install) libopenssl-devel libplist-2_0-devel (formerly libplist-devel)
avahi-compat-mDNSResponder-devel gstreamer-devel
gstreamer-plugins-base-devel (+ libX11-devel for fullscreen X11).
@@ -922,6 +923,9 @@ the client sends the "Stop Mirroring" signal, try the no-close option "-nc" that
### 4. GStreamer issues (missing plugins, etc.):
* clearing the user's GStreamer cache with `rm -rf ~/.cache/gstreamer-1.0/*` may be the solution to problems
where gst-inspect-1.0 does not show a plugin that you believe is installed. The cache will be regenerated next time
GStreamer is started. **This is the solution to puzzling problems that turn out to come from corruption of the cache, and should be tried first.**
If UxPlay fails to start, with a message that a required GStreamer plugin (such as "libav") was not found, first check with the GStreamer tool
gst-inspect-1.0 to see what GStreamer knows is available. (You may need to install some additional GStreamer "tools" package to get gst-inspect-1.0).
@@ -929,11 +933,6 @@ For, _e.g._ a libav problem, check with "`gst-inspect-1.0 libav`". If it is no
shows the relevant package as installed (as one user found), try entirely removing and reinstalling the package.
That user found that a solution to a "**Required gstreamer plugin 'libav' not found**" message that kept recurring was to clear the user's gstreamer
cache.
* clearing the user's GStreamer cache with `rm -rf ~/.cache/gstreamer-1.0/*` may be the solution to problems
where gst-inspect-1.0 does not show a plugin that you believe is installed. The cache will be regenerated next time
GStreamer is started.
If it fails to start with an error like '`no element "avdec_aac"`' this is
because even though gstreamer-libav is installed. it is incomplete because some plugins are missing: "`gst-inspect-1.0 | grep avdec_aac`" will
@@ -984,6 +983,14 @@ new connections, and will be taken over by a new client connection when it is ma
### 6. Protocol issues, such as failure to decrypt ALL video and audio streams from old or non-Apple clients:
* **NEW** As UxPlay only connects to one client at any time, it can work without the client pairing setup, allowing faster connections.
This is allowed by disabling "Supports Legacy Pairing" (bit 27) in the "features" code UxPlay advertises
on DNS-SD Service Discovery. Most clients will then not attempt to setup the "shared secret key" for pairing.
* **This new behavior (since UxPlay-1.65) can be reverted to the previous behavior by uncommenting the previous "FEATURES_1" setting
(and commenting out the new one) in lib/dnssdint.h, and then rebuilding UxPlay.**
A protocol failure may trigger 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.
@@ -1004,13 +1011,21 @@ AppleTV model that cannot run modern 64bit tvOS, in order for the client
to use a "legacy" protocol for pairing with the server.
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.
tvOS 12.2.1). It was previously thought that
use of "legacy" protocol requires bit 27 ("SupportsLegacyPairing") of the
"features" plist code (reported to the client by the AirPlay server) to be set,
but it was recently discovered that it was possible to switch that off (after a small protocol
modification) to eliminate a 5 second delay by the client in making connections to the server.
The "features" code and other settings are set in `UxPlay/lib/dnssdint.h`.
# Changelog
1.65 2023-05-31 Eliminate pair_setup part of connection protocol to allow faster connections with clients
(thanks to @shuax #176 for this discovery); to revert, uncomment a line in lib/dnssdint.h.
Disconnect from audio device when connection closes, to not block its use by other apps if
uxplay is running but not connected. Fix for AirMyPC client (broken since 1.60), so its
older non-NTP timestamp protocol works with -vsync.
1.64 2023-04-23 Timestamp-based synchronization of audio and video is now the default in Mirror mode.
(Use "-vsync no" to restore previous behavior.) A configuration file can now be used
for startup options. Also some internal cleanups and a minor bugfix that fixes #192.
@@ -1159,10 +1174,14 @@ _(Note: on Debian 9 "Stretch" or Ubuntu 16.04 LTS editions, you can avoid this s
and libplist3 from Debian 10 or Ubuntu 18.04.)_
As well as the usual build tools (autoconf, automake, libtool), you
may need to also install some libpython\*-dev package. Download the latest source
from [https://github.com/libimobiledevice/libplist](https://github.com/libimobiledevice/libplist): get
[libplist-master.zip](https://github.com/libimobiledevice/libplist/archive/refs/heads/master.zip), then
("unzip libplist-master.zip ; cd libplist-master"), build/install
("./autogen.sh ; make ; sudo make install"). This will probably install libplist-2.0.* in /usr/local/lib.
with git from [https://github.com/libimobiledevice/libplist](https://github.com/libimobiledevice/libplist), or
get the source from the Releases section (use the \*.tar.bz2 release, **not** the \*.zip or \*.tar.gz versions):
download [libplist-2.3.0](https://github.com/libimobiledevice/libplist/releases/download/2.3.0/libplist-2.3.0.tar.bz2),
then unpack it ("tar -xvjf libplist-2.3.0.tar.bz2 ; cd libplist-2.3.0"), and build/install it:
("./configure ; make ; sudo make install"). This will probably install libplist-2.0.\* in /usr/local/lib.
The new libplist-2.3.0 release should be compatible with
UxPlay; [libplist-2.2.0](https://github.com/libimobiledevice/libplist/releases/download/2.2.0/libplist-2.2.0.tar.bz2) is
also available if there are any issues.
_(Ignore the following for builds on MacOS:)_ On some systems like
Debian or Ubuntu, you may also need to add a missing entry ```/usr/local/lib```

View File

@@ -1,4 +1,4 @@
# UxPlay 1.64: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix (now also runs on Windows).
# UxPlay 1.65: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix (now also runs on Windows).
### Now developed at the GitHub site <https://github.com/FDH2/UxPlay> (where all user issues should be posted).
@@ -77,14 +77,14 @@ is no longer involved in development, but periodically posts updates
pulled from the new main [UxPlay site](https://github.com/FDH2/UxPlay)).
UxPlay is tested on a number of systems, including (among others) Debian
10.11 "Buster" and 11.2 "Bullseye", Ubuntu 20.04 LTS and 22.04.1 LTS,
(also Ubuntu derivatives Linux Mint 20.3, Pop!\_OS 22.04 (NVIDIA
edition)), Rocky Linux 9.1 (a CentOS successor), Fedora 36, OpenSUSE
15.4, Arch Linux 22.10, macOS 13.3 (Intel and M2), FreeBSD 13.2, Windows
10 and 11 (64 bit).
(10 "Buster", 11 "Bullseye", 12 "Bookworm"), Ubuntu (20.04 LTS, 22.04
LTS, 23.04; also Ubuntu derivatives Linux Mint 20.3, Pop!\_OS 22.04
(NVIDIA edition)), Red Hat and clones (Fedora 38, Rocky Linux 9.2),
OpenSUSE 15.4, Arch Linux 23.05, macOS 13.3 (Intel and M2), FreeBSD
13.2, Windows 10 and 11 (64 bit).
On Raspberry Pi 4 model B, it is tested on Raspberry Pi OS (Bullseye)
(32- and 64-bit), Ubuntu 22.04 and 22.10, Manjaro RPi4 23.02, and
(32- and 64-bit), Ubuntu 22.04 LTS and 23.04, Manjaro RPi4 23.02, and
(without hardware video decoding) on OpenSUSE 15.4. Also tested on
Raspberry Pi 3 model B+.
@@ -92,13 +92,15 @@ Its main use is to act like an AppleTV for screen-mirroring (with audio)
of iOS/iPadOS/macOS clients (iPhone, iPod Touch, iPad, Mac computers) on
the server display of a host running Linux, macOS, or other unix (and
now also Microsoft Windows). UxPlay supports Apple's AirPlay2 protocol
using "Legacy Pairing", but some features are missing. (Details of what
using "Legacy Protocol", but some features are missing. (Details of what
is publicly known about Apple's AirPlay 2 protocol can be found
[here](https://openairplay.github.io/airplay-spec/),
[here](https://github.com/SteeBono/airplayreceiver/wiki/AirPlay2-Protocol)
and [here](https://emanuelecozzi.net/docs/airplay2)). While there is no
guarantee that future iOS releases will keep supporting "Legacy
Pairing", the recent iOS 16 release continues support.
and [here](https://emanuelecozzi.net/docs/airplay2); see also
[pyatv](https://pyatv.dev/documentation/protocols) which could be a
resource for adding modern protocols.) While there is no guarantee that
future iOS releases will keep supporting "Legacy Protocol", the recent
iOS 16 release continues support.
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
@@ -284,7 +286,8 @@ installed)
*(some of these may be in the "CodeReady" add-on repository, called
"PowerTools" by clones)*
- **OpenSUSE:** (sudo zypper install) libopenssl-devel libplist-devel
- **OpenSUSE:** (sudo zypper install) libopenssl-devel
libplist-2_0-devel (formerly libplist-devel)
avahi-compat-mDNSResponder-devel gstreamer-devel
gstreamer-plugins-base-devel (+ libX11-devel for fullscreen X11).
@@ -1158,6 +1161,13 @@ option "-nc" that leaves the video window open.
### 4. GStreamer issues (missing plugins, etc.):
- clearing the user's GStreamer cache with
`rm -rf ~/.cache/gstreamer-1.0/*` may be the solution to problems
where gst-inspect-1.0 does not show a plugin that you believe is
installed. The cache will be regenerated next time GStreamer is
started. **This is the solution to puzzling problems that turn out
to come from corruption of the cache, and should be tried first.**
If UxPlay fails to start, with a message that a required GStreamer
plugin (such as "libav") was not found, first check with the GStreamer
tool gst-inspect-1.0 to see what GStreamer knows is available. (You may
@@ -1170,12 +1180,6 @@ user found that a solution to a "**Required gstreamer plugin 'libav' not
found**" message that kept recurring was to clear the user's gstreamer
cache.
- clearing the user's GStreamer cache with
`rm -rf ~/.cache/gstreamer-1.0/*` may be the solution to problems
where gst-inspect-1.0 does not show a plugin that you believe is
installed. The cache will be regenerated next time GStreamer is
started.
If it fails to start with an error like '`no element "avdec_aac"`' this
is because even though gstreamer-libav is installed. it is incomplete
because some plugins are missing: "`gst-inspect-1.0 | grep avdec_aac`"
@@ -1247,6 +1251,19 @@ causes UxPlay to reset the connection.
### 6. Protocol issues, such as failure to decrypt ALL video and audio streams from old or non-Apple clients:
- **NEW** As UxPlay only connects to one client at any time, it can
work without the client pairing setup, allowing faster connections.
This is allowed by disabling "Supports Legacy Pairing" (bit 27) in the
"features" code UxPlay advertises on DNS-SD Service Discovery. Most
clients will then not attempt to setup the "shared secret key" for
pairing.
- **This new behavior (since UxPlay-1.65) can be reverted to the
previous behavior by uncommenting the previous "FEATURES_1" setting
(and commenting out the new one) in lib/dnssdint.h, and then
rebuilding UxPlay.**
A protocol failure may trigger 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
@@ -1265,16 +1282,27 @@ 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. 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.
380.20.1 (an AppleTV 4K 1st gen, introduced 2017, running tvOS 12.2.1).
It was previously thought that use of "legacy" protocol requires bit 27
("SupportsLegacyPairing") of the "features" plist code (reported to the
client by the AirPlay server) to be set, but it was recently discovered
that it was possible to switch that off (after a small protocol
modification) to eliminate a 5 second delay by the client in making
connections to the server.
The "features" code and other settings are set in
`UxPlay/lib/dnssdint.h`.
# Changelog
1.65 2023-05-31 Eliminate pair_setup part of connection protocol to
allow faster connections with clients (thanks to @shuax #176 for this
discovery); to revert, uncomment a line in lib/dnssdint.h. Disconnect
from audio device when connection closes, to not block its use by other
apps if uxplay is running but not connected. Fix for AirMyPC client
(broken since 1.60), so its older non-NTP timestamp protocol works with
-vsync.
1.64 2023-04-23 Timestamp-based synchronization of audio and video is
now the default in Mirror mode. (Use "-vsync no" to restore previous
behavior.) A configuration file can now be used for startup options.
@@ -1454,12 +1482,17 @@ ldconfig".
avoid this step by installing libplist-dev and libplist3 from Debian 10
or Ubuntu 18.04.)* As well as the usual build tools (autoconf, automake,
libtool), you may need to also install some libpython\*-dev package.
Download the latest source from
<https://github.com/libimobiledevice/libplist>: get
[libplist-master.zip](https://github.com/libimobiledevice/libplist/archive/refs/heads/master.zip),
then ("unzip libplist-master.zip ; cd libplist-master"), build/install
("./autogen.sh ; make ; sudo make install"). This will probably install
libplist-2.0.\* in /usr/local/lib.
Download the latest source with git from
<https://github.com/libimobiledevice/libplist>, or get the source from
the Releases section (use the \*.tar.bz2 release, **not** the \*.zip or
\*.tar.gz versions): download
[libplist-2.3.0](https://github.com/libimobiledevice/libplist/releases/download/2.3.0/libplist-2.3.0.tar.bz2),
then unpack it ("tar -xvjf libplist-2.3.0.tar.bz2 ; cd libplist-2.3.0"),
and build/install it: ("./configure ; make ; sudo make install"). This
will probably install libplist-2.0.\* in /usr/local/lib. The new
libplist-2.3.0 release should be compatible with UxPlay;
[libplist-2.2.0](https://github.com/libimobiledevice/libplist/releases/download/2.2.0/libplist-2.2.0.tar.bz2)
is also available if there are any issues.
*(Ignore the following for builds on MacOS:)* On some systems like
Debian or Ubuntu, you may also need to add a missing entry

View File

@@ -42,7 +42,7 @@ endif()
if( APPLE )
set( ENV{PKG_CONFIG_PATH} "/usr/local/lib/pkgconfig" ) # standard location, and Brew
set( ENV{PKG_CONFIG_PATH} "/opt/homebrew/lib/pkgconfig" ) # Brew for M1 macs
set( ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/opt/homebrew/lib/pkgconfig" ) # Brew for M1 macs
set( ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/opt/local/lib/pkgconfig/" ) # MacPorts
set( ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/opt/openssl@3/lib/pkgconfig" ) # Brew openssl
set( ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/opt/homebrew/opt/openssl@3/lib/pkgconfig" ) # Brew M1 openssl

View File

@@ -24,7 +24,8 @@
#define RAOP_CN "0,1,2,3" /* Audio codec: PCM, ALAC, AAC, AAC ELD */
#define RAOP_ET "0,3,5" /* Encryption type: None, FairPlay, FairPlay SAPv2.5 */
#define RAOP_VV "2"
#define FEATURES_1 "0x5A7FFEE6" /* first 32 bits of features */
//#define FEATURES_1 "0x5A7FFEE6" /* first 32 bits of features, with bit 27 ("supports legacy pairing") ON */
#define FEATURES_1 "0x527FFEE6" /* first 32 bits of features, with bit 27 ("supports legacy pairing") OFF */
#define FEATURES_2 "0x0" /* second 32 bits of features */
#define RAOP_FT FEATURES_1 "," FEATURES_2
#define RAOP_RHD "5.6.0.0"

View File

@@ -90,14 +90,19 @@ pairing_get_public_key(pairing_t *pairing, unsigned char public_key[ED25519_KEY_
ed25519_key_get_raw(public_key, pairing->ed);
}
void
int
pairing_get_ecdh_secret_key(pairing_session_t *session, unsigned char ecdh_secret[X25519_KEY_SIZE])
{
assert(session);
memcpy(ecdh_secret, session->ecdh_secret, X25519_KEY_SIZE);
switch (session->status) {
case STATUS_INITIAL:
return 0;
default:
memcpy(ecdh_secret, session->ecdh_secret, X25519_KEY_SIZE);
return 1;
}
}
pairing_session_t *
pairing_session_init(pairing_t *pairing)
{

View File

@@ -38,6 +38,6 @@ void pairing_session_destroy(pairing_session_t *session);
void pairing_destroy(pairing_t *pairing);
void pairing_get_ecdh_secret_key(pairing_session_t *session, unsigned char ecdh_secret[X25519_KEY_SIZE]);
int pairing_get_ecdh_secret_key(pairing_session_t *session, unsigned char ecdh_secret[X25519_KEY_SIZE]);
#endif

View File

@@ -70,8 +70,9 @@ struct raop_callbacks_s {
void (*video_report_size)(void *cls, float *width_source, float *height_source, float *width, float *height);
};
typedef struct raop_callbacks_s raop_callbacks_t;
raop_ntp_t *raop_ntp_init(logger_t *logger, raop_callbacks_t *callbacks, const unsigned char *remote_addr, int remote_addr_len, unsigned short timing_rport);
raop_ntp_t *raop_ntp_init(logger_t *logger, raop_callbacks_t *callbacks, const unsigned char *remote_addr, int remote_addr_len,
unsigned short timing_rport, timing_protocol_t *time_protocol);
RAOP_API raop_t *raop_init(int max_clients, raop_callbacks_t *callbacks);
RAOP_API void raop_set_log_level(raop_t *raop, int level);
RAOP_API void raop_set_log_callback(raop_t *raop, raop_log_callback_t callback, void *cls);

View File

@@ -395,14 +395,6 @@ raop_handler_setup(raop_conn_t *conn,
free(str);
}
unsigned char ecdh_secret[X25519_KEY_SIZE];
pairing_get_ecdh_secret_key(conn->pairing, ecdh_secret);
if (logger_debug) {
char *str = utils_data_to_string(ecdh_secret, X25519_KEY_SIZE, 16);
logger_log(conn->raop->logger, LOGGER_DEBUG, "32 byte shared ecdh_secret:\n%s", str);
free(str);
}
const char *user_agent = http_request_get_header(request, "User-Agent");
logger_log(conn->raop->logger, LOGGER_INFO, "Client identified as User-Agent: %s", user_agent);
@@ -413,17 +405,33 @@ raop_handler_setup(raop_conn_t *conn,
if (old_protocol) { /* some windows AirPlay-client emulators use old AirPlay 1 protocol with unhashed AES key */
logger_log(conn->raop->logger, LOGGER_INFO, "Client identifed as using old protocol (unhashed) AES audio key)");
} else {
memcpy(eaeskey, aeskey, 16);
sha_ctx_t *ctx = sha_init();
sha_update(ctx, eaeskey, 16);
sha_update(ctx, ecdh_secret, 32);
sha_final(ctx, eaeskey, NULL);
sha_destroy(ctx);
memcpy(aeskey, eaeskey, 16);
if (logger_debug) {
char *str = utils_data_to_string(aeskey, 16, 16);
logger_log(conn->raop->logger, LOGGER_DEBUG, "16 byte aeskey after sha-256 hash with ecdh_secret:\n%s", str);
free(str);
unsigned char ecdh_secret[X25519_KEY_SIZE];
if (pairing_get_ecdh_secret_key(conn->pairing, ecdh_secret)) {
/* In this case (legacy) pairing with client was successfully set up and created the shared ecdh_secret:
* aeskey must be hashed with it
*
* If byte 27 of features ("supports legacy pairing") is turned off, the client does not request pairsetup
* and does NOT set up pairing (this eliminates a 5 second delay in connecting with no apparent bad effects).
* This may be because uxplay currently does not support connections with more than one client at a time
* while AppleTV supports up to 12 clients, and uses pairing to give each a distinct SessionID .*/
if (logger_debug) {
char *str = utils_data_to_string(ecdh_secret, X25519_KEY_SIZE, 16);
logger_log(conn->raop->logger, LOGGER_DEBUG, "32 byte shared ecdh_secret:\n%s", str);
free(str);
}
memcpy(eaeskey, aeskey, 16);
sha_ctx_t *ctx = sha_init();
sha_update(ctx, eaeskey, 16);
sha_update(ctx, ecdh_secret, 32);
sha_final(ctx, eaeskey, NULL);
sha_destroy(ctx);
memcpy(aeskey, eaeskey, 16);
if (logger_debug) {
char *str = utils_data_to_string(aeskey, 16, 16);
logger_log(conn->raop->logger, LOGGER_DEBUG, "16 byte aeskey after sha-256 hash with ecdh_secret:\n%s", str);
free(str);
}
}
}
@@ -437,13 +445,28 @@ raop_handler_setup(raop_conn_t *conn,
" Only AirPlay v1 protocol (using NTP and timing port) is supported");
}
}
uint64_t string_len;
uint64_t string_len = 0;
const char *timing_protocol;
timing_protocol_t time_protocol;
plist_t req_timing_protocol_node = plist_dict_get_item(req_root_node, "timingProtocol");
timing_protocol = plist_get_string_ptr(req_timing_protocol_node, &string_len);
if (strcmp(timing_protocol, "NTP")) {
logger_log(conn->raop->logger, LOGGER_ERR, "Client specified timingProtocol=%s, but timingProtocol= NTP is required here", timing_protocol);
}
if (string_len) {
if (strncmp(timing_protocol, "NTP", string_len) == 0) {
time_protocol = NTP;
} else if (strncmp(timing_protocol, "None", string_len) == 0) {
time_protocol = TP_NONE;
} else {
time_protocol = TP_OTHER;
}
if (time_protocol != NTP) {
logger_log(conn->raop->logger, LOGGER_ERR, "Client specified timingProtocol=%s,"
" but timingProtocol= NTP is required here", timing_protocol);
}
} else {
logger_log(conn->raop->logger, LOGGER_DEBUG, "Client did not specify timingProtocol,"
" old protocol without offset will be used");
time_protocol = TP_UNSPECIFIED;
}
timing_protocol = NULL;
uint64_t timing_rport = 0;
plist_t req_timing_port_node = plist_dict_get_item(req_root_node, "timingPort");
@@ -453,14 +476,18 @@ raop_handler_setup(raop_conn_t *conn,
if (timing_rport) {
logger_log(conn->raop->logger, LOGGER_DEBUG, "timing_rport = %llu", timing_rport);
} else {
logger_log(conn->raop->logger, LOGGER_ERR, "Client did not supply timing_rport, may be using unsupported AirPlay2 \"Remote Control\" protocol");
logger_log(conn->raop->logger, LOGGER_ERR, "Client did not supply timing_rport,"
" may be using unsupported AirPlay2 \"Remote Control\" protocol");
}
unsigned short timing_lport = conn->raop->timing_lport;
conn->raop_ntp = raop_ntp_init(conn->raop->logger, &conn->raop->callbacks, conn->remote, conn->remotelen, timing_rport);
conn->raop_ntp = raop_ntp_init(conn->raop->logger, &conn->raop->callbacks, conn->remote,
conn->remotelen, (unsigned short) timing_rport, &time_protocol);
raop_ntp_start(conn->raop_ntp, &timing_lport, conn->raop->max_ntp_timeouts);
conn->raop_rtp = raop_rtp_init(conn->raop->logger, &conn->raop->callbacks, conn->raop_ntp, conn->remote, conn->remotelen, aeskey, aesiv);
conn->raop_rtp_mirror = raop_rtp_mirror_init(conn->raop->logger, &conn->raop->callbacks, conn->raop_ntp, conn->remote, conn->remotelen, aeskey);
conn->raop_rtp = raop_rtp_init(conn->raop->logger, &conn->raop->callbacks, conn->raop_ntp,
conn->remote, conn->remotelen, aeskey, aesiv);
conn->raop_rtp_mirror = raop_rtp_mirror_init(conn->raop->logger, &conn->raop->callbacks,
conn->raop_ntp, conn->remote, conn->remotelen, aeskey);
plist_t res_event_port_node = plist_new_uint(conn->raop->port);
plist_t res_timing_port_node = plist_new_uint(timing_lport);
@@ -490,7 +517,8 @@ raop_handler_setup(raop_conn_t *conn,
plist_t stream_id_node = plist_dict_get_item(req_stream_node, "streamConnectionID");
uint64_t stream_connection_id;
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);
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_init_mirror_aes(conn->raop_rtp_mirror, &stream_connection_id);

View File

@@ -91,6 +91,8 @@ struct raop_ntp_s {
// UDP socket
int tsock;
timing_protocol_t time_protocol;
};
@@ -140,7 +142,7 @@ raop_ntp_parse_remote_address(raop_ntp_t *raop_ntp, const unsigned char *remote_
}
raop_ntp_t *raop_ntp_init(logger_t *logger, raop_callbacks_t *callbacks, const unsigned char *remote_addr,
int remote_addr_len, unsigned short timing_rport) {
int remote_addr_len, unsigned short timing_rport, timing_protocol_t *time_protocol) {
raop_ntp_t *raop_ntp;
assert(logger);
@@ -150,6 +152,7 @@ raop_ntp_t *raop_ntp_init(logger_t *logger, raop_callbacks_t *callbacks, const u
if (!raop_ntp) {
return NULL;
}
raop_ntp->time_protocol = *time_protocol;
raop_ntp->logger = logger;
memcpy(&raop_ntp->callbacks, callbacks, sizeof(raop_callbacks_t));
raop_ntp->timing_rport = timing_rport;
@@ -322,10 +325,10 @@ raop_ntp_thread(void *arg)
int64_t t0 = (int64_t) byteutils_get_ntp_timestamp(response, 8);
// Local time of the client when the NTP request packet arrives at the client
int64_t t1 = (int64_t) byteutils_get_ntp_timestamp(response, 16);
int64_t t1 = (int64_t) raop_remote_timestamp_to_nano_seconds(raop_ntp, byteutils_get_long_be(response, 16));
// Local time of the client when the response message leaves the client
int64_t t2 = (int64_t) byteutils_get_ntp_timestamp(response, 24);
int64_t t2 = (int64_t) raop_remote_timestamp_to_nano_seconds(raop_ntp, byteutils_get_long_be(response, 24));
if (logger_debug) {
char *str = utils_data_to_string(response, response_len, 16);
@@ -480,6 +483,12 @@ uint64_t raop_ntp_timestamp_to_nano_seconds(uint64_t ntp_timestamp, bool account
return (seconds * SECOND_IN_NSECS) + ((fraction * SECOND_IN_NSECS) >> 32);
}
uint64_t raop_remote_timestamp_to_nano_seconds(raop_ntp_t *raop_ntp, uint64_t timestamp) {
uint64_t seconds = ((timestamp >> 32) & 0xffffffff);
if (raop_ntp->time_protocol == NTP) seconds -= SECONDS_FROM_1900_TO_1970;
uint64_t fraction = (timestamp & 0xffffffff);
return (seconds * SECOND_IN_NSECS) + ((fraction * SECOND_IN_NSECS) >> 32);
}
/**
* Returns the current time in nano seconds according to the local wall clock.
* The system Unix time is used as the local wall clock.

View File

@@ -25,6 +25,7 @@
typedef struct raop_ntp_s raop_ntp_t;
typedef enum timing_protocol_e { NTP, TP_NONE, TP_OTHER, TP_UNSPECIFIED } timing_protocol_t;
void raop_ntp_start(raop_ntp_t *raop_ntp, unsigned short *timing_lport, int max_ntp_timeouts);
@@ -35,6 +36,7 @@ unsigned short raop_ntp_get_port(raop_ntp_t *raop_ntp);
void raop_ntp_destroy(raop_ntp_t *raop_rtp);
uint64_t raop_ntp_timestamp_to_nano_seconds(uint64_t ntp_timestamp, bool account_for_epoch_diff);
uint64_t raop_remote_timestamp_to_nano_seconds(raop_ntp_t *raop_ntp, uint64_t timestamp);
uint64_t raop_ntp_get_local_time(raop_ntp_t *raop_ntp);
uint64_t raop_ntp_get_remote_time(raop_ntp_t *raop_ntp);

View File

@@ -557,7 +557,7 @@ raop_rtp_thread_udp(void *arg)
have_synced = true;
}
uint64_t sync_ntp_raw = byteutils_get_long_be(packet, 8);
uint64_t sync_ntp_remote = raop_ntp_timestamp_to_nano_seconds(sync_ntp_raw, true);
uint64_t sync_ntp_remote = raop_remote_timestamp_to_nano_seconds(raop_rtp->ntp, sync_ntp_raw);
if (logger_debug) {
uint64_t sync_ntp_local = raop_ntp_convert_remote_time(raop_rtp->ntp, sync_ntp_remote);
char *str = utils_data_to_string(packet, packetlen, 20);

View File

@@ -321,11 +321,13 @@ raop_rtp_mirror_thread(void *arg)
/* 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 *
* 0x01 0x00: unencrypted packet containing a type 7 SPS NAL + a type 8 PPS NAL unit *
* 0x02 0x00: unencryted 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: *
* 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 SPS+PPS packets *
* 0x56 0x01 : occasionally seen in unencrypted SPS+PPS packets (why different?) */
@@ -400,15 +402,19 @@ raop_rtp_mirror_thread(void *arg)
* that has not yet been sent. This will trigger prepending it to the current NAL, and the prepend_sps_pps
* flag will be set to false after it has been prepended. */
if (prepend_sps_pps & (ntp_timestamp_raw != ntp_timestamp_nal)) {
logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG,
"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;
prepend_sps_pps = false;
}
if (prepend_sps_pps) {
assert(sps_pps);
payload_out = (unsigned char*) malloc(payload_size + sps_pps_len);
payload_decrypted = payload_out + sps_pps_len;
if (ntp_timestamp_raw != ntp_timestamp_nal) {
logger_log(raop_rtp_mirror->logger, LOGGER_WARNING,
"raop_rtp_mirror: prepended sps_pps timestamp does not match timestamp of "
"video payload\n%llu\n%llu", ntp_timestamp_raw, ntp_timestamp_nal);
}
memcpy(payload_out, sps_pps, sps_pps_len);
free (sps_pps);
sps_pps = NULL;
@@ -441,6 +447,7 @@ raop_rtp_mirror_thread(void *arg)
int nalu_type = payload_decrypted[nalu_size] & 0x1f;
int ref_idc = (payload_decrypted[nalu_size] >> 5);
switch (nalu_type) {
case 14: /* Prefix NALu , seen before all VCL Nalu's in AirMyPc */
case 5: /*IDR, slice_layer_without_partitioning */
case 1: /*non-IDR, slice_layer_without_partitioning */
break;
@@ -461,6 +468,24 @@ raop_rtp_mirror_thread(void *arg)
free(str);
}
break;
case 7:
if (logger_debug) {
char *str = utils_data_to_string(payload_decrypted + nalu_size, nc_len, 16);
logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror SPS NAL size = %d", nc_len);
logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG,
"raop_rtp_mirror h264 Sequence Parameter Set:\n%s", str);
free(str);
}
break;
case 8:
if (logger_debug) {
char *str = utils_data_to_string(payload_decrypted + nalu_size, nc_len, 16);
logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror PPS NAL size = %d", nc_len);
logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG,
"raop_rtp_mirror h264 Picture Parameter Set :\n%s", str);
free(str);
}
break;
default:
logger_log(raop_rtp_mirror->logger, LOGGER_INFO,
"unexpected non-VCL NAL unit: nalu_type = %d, ref_idc = %d, nalu_size = %d,"
@@ -580,6 +605,10 @@ raop_rtp_mirror_thread(void *arg)
// memcpy(h264.picture_parameter_set, picture_parameter_set, pps_size);
break;
case 0x02:
logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "\nReceived old-protocol once-per-second packet from client:"
" payload_size %d header %s ts_raw = %llu", payload_size, packet_description, ntp_timestamp_raw);
/* "old protocol" (used by AirMyPC), rest of 128-byte packet is empty */
case 0x05:
logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "\nReceived video streaming performance info packet from client:"
" payload_size %d header %s ts_raw = %llu", payload_size, packet_description, ntp_timestamp_raw);
@@ -615,7 +644,7 @@ raop_rtp_mirror_thread(void *arg)
break;
default:
logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "\nReceived unexpected TCP packet from client, "
"size %d, %s ts_raw = raw%llu", payload_size, packet_description, ntp_timestamp_raw);
"size %d, %s ts_raw = %llu", payload_size, packet_description, ntp_timestamp_raw);
break;
}

View File

@@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.4.1)
if (APPLE )
set( ENV{PKG_CONFIG_PATH} "/Library/FrameWorks/GStreamer.framework/Libraries/pkgconfig" ) # GStreamer.framework, preferred
set( ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig" ) # Brew or self-installed gstreamer
set( ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig" ) # Brew or self-installed gstreamer
set( ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/opt/homebrew/lib/pkgconfig" ) # Brew, M1/M2 macs
set( ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/opt/local/lib/pkgconfig/" ) # MacPorts
message( "PKG_CONFIG_PATH (Apple, renderers) = " $ENV{PKG_CONFIG_PATH} )
find_program( PKG_CONFIG_EXECUTABLE pkg-config PATHS /Library/FrameWorks/GStreamer.framework/Commands )

View File

@@ -1,11 +1,11 @@
.TH UXPLAY "1" "April 2023" "1.64" "User Commands"
.TH UXPLAY "1" "June 2023" "1.65" "User Commands"
.SH NAME
uxplay \- start AirPlay server
.SH SYNOPSIS
.B uxplay
[\fI\,-n name\/\fR] [\fI\,-s wxh\/\fR] [\fI\,-p \/\fR[\fI\,n\/\fR]] [more \fI OPTIONS \/\fR ...]
.SH DESCRIPTION
UxPlay 1.64: An open\-source AirPlay mirroring (+ audio streaming) server:
UxPlay 1.65: An open\-source AirPlay mirroring (+ audio streaming) server:
.SH OPTIONS
.TP
.B
@@ -142,7 +142,7 @@ COPYRIGHT
.TP
Various, see website or distribution. License: GPL v3+: GNU GPL version 3 or later.
.TP
(some parts LGPL v.2.1 and MIT).
(some parts LGPL v.2.1+ or MIT).
.SH
SEE ALSO
.TP

View File

@@ -59,7 +59,7 @@
#include "renderers/video_renderer.h"
#include "renderers/audio_renderer.h"
#define VERSION "1.64"
#define VERSION "1.65"
#define SECOND_IN_USECS 1000000
#define SECOND_IN_NSECS 1000000000UL
@@ -1055,6 +1055,9 @@ extern "C" void conn_destroy (void *cls) {
//LOGD("Open connections: %i", open_connections);
if (open_connections == 0) {
remote_clock_offset = 0;
if (use_audio) {
audio_renderer_stop();
}
}
}
@@ -1315,17 +1318,62 @@ static void read_config_file(const char * filename, const char * uxplay_name) {
std::string line;
while (std::getline(file, line)) {
if (line[0] == '#') continue;
std::stringstream ss(line);
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;
std::vector<std::string> tokens(begin,end);
if (tokens.size() > 0) {
options.push_back(option_char + tokens[0]);
for (int i = 1; i < tokens.size(); i++) {
options.push_back(tokens[i].c_str());
}
// first process line into separate option items with '\0' as delimiter
bool is_part_of_item, in_quotes;
char endchar;
is_part_of_item = false;
for (int i = 0; i < line.size(); i++) {
switch (is_part_of_item) {
case false:
if (line[i] == ' ') {
line[i] = '\0';
} else {
// start of new item
is_part_of_item = true;
switch (line[i]) {
case '\'':
case '\"':
endchar = line[i];
line[i] = '\0';
in_quotes = true;
break;
default:
in_quotes = false;
endchar = ' ';
break;
}
}
break;
case true:
/* previous character was inside this item */
if (line[i] == endchar) {
if (in_quotes) {
/* cases where endchar is inside quoted item */
if (i > 0 && line[i - 1] == '\\') continue;
if (i + 1 < line.size() && line[i + 1] != ' ') continue;
}
line[i] = '\0';
is_part_of_item = false;
}
break;
}
}
}
// now tokenize the processed line
std::istringstream iss(line);
std::string token;
bool first = true;
while (std::getline(iss, token, '\0')) {
if (token.size() > 0) {
if (first) {
options.push_back(option_char + token.c_str());
first = false;
} else {
options.push_back(token.c_str());
}
}
}
}
file.close();
} else {
fprintf(stderr,"UxPlay: failed to open configuration file at %s\n", config_file.c_str());