From Segfault
Jump to navigation Jump to search


raop-play (Apple Airport Express Client Player) tends to crash under Debian GNU/Linux for PowerPC but seems to work under i386. Example setup:

sudo apt-get install gcc g++ libid3tag0-dev  libfltk1.3-dev  fluid libsamplerate0-dev  libssl-dev libglib2.0-dev   # Debian
sudo yum install gcc gcc-c++ libid3tag-devel fltk-devel fltk-fluid libsamplerate-devel openssl-devel glib2-devel   # Fedora
git clone git:// raop-play-git
cd raop-play-git/raop_play

For configure to work, we have to include the -lcrypto flag - otherwise the SSL library would be used for certain tests and configure would fail with:

configure:3774: checking for RSA_new in -lssl
configure:3809: gcc -o conftest -g -O2   conftest.c -lssl  -lsamplerate -lfltk -lid3tag  >&5
/usr/bin/ld: /tmp/ccNFQBB5.o: undefined reference to symbol ''
/usr/bin/ld: note: '' is defined in DSO /lib/ so try adding it to the linker command line
/lib/ could not read symbols: Invalid operation
collect2: error: ld returned 1 exit status

Additionally, for some reason the LIBS variable is configured but not used in raop_play/Makefile and we have to fix that:

diff --git a/raop_play/raop_play/ b/raop_play/raop_play/
index 4fa69fc..6c12677 100644
--- a/raop_play/raop_play/
+++ b/raop_play/raop_play/
@@ -20,7 +20,7 @@ pcm_stream.o flac_stream.o
 all: $(TARGET)
 raop_play: $(OBJS)
-       $(CC) -o $@  -lssl -lsamplerate -lid3tag $^
+       $(CC) -o $@ @LIBS@ $^
        $(mkinstalldirs) $(DESTDIR)$(bindir)/

With that in place, we can finally run configure:

LIBS="-lcrypto" ./configure --prefix=/opt/raop-play
make -C raop_play                                      #   Build only raop_play
sudo make -C raop_play install                         # Install only raop_play, not the kernel modules

raop_play needs external programs to actually play music files:

sudo apt-get install vorbis-tools flac mpg123          # Debian, use mpg321 if mpg123 is not available
sudo yum install vorbis-tools flac                     # Fedora


In combination with mpg123, we can also play streams:

mkfifo foo
mpg123 -s > foo &
/opt/raop-play/bin/raop_play airportexpress foo


Fedora does not ship MP3 decoders[1], let's install mpg123 then:

svn co svn:// mpg123-svn
cd mpg123-svn
autoreconf --install --verbose
./configure --prefix=/opt/mpg123
sudo make install

Because raop_play expects mpg321 in the executable PATH, let's add a symlink:

sudo ln -s /opt/mpg123/bin/mpg123 /usr/local/bin/mpg321


SNI once wrote webmp3, a web frontend to play MP3 files on the server. This may be useful here because with raop_play we don't even need an audio device on the server:

svn co webmp3-svn
cd webmp3-svn
sudo svn export www /var/www/webmp3
sudo cp -p /var/www/webmp3/config.php{.sample,}
sudo chown apache:apache /var/www/webmp3/var/                        # php-fpm needs to write here!

Tune config.php for raop_play:

$config["logfile"]      = "./var/webmp3.log";
$config["searchPath"]   = "/mnt/data/music";
$config["ext"][".mp3"]["binary"] = "/opt/raop-play/bin/raop_play";
$config["ext"][".mp3"]["option"] = array("");              # AirPort Express address

$config["ext"][".ogg"]["binary"] = "/opt/raop-play/bin/raop_play";
$config["ext"][".ogg"]["option"] = array("");

$config["volumeBin"]   = "./";                      # executable to change volume

Note: since we're streaming via raop_play, we don't really need a volumeBin. But when it's undefined or when it's unable to return the volume, the user interface prints an error. As a workaround we create a dummy script:

$ cat | sudo tee /var/www/webmp3/ > /dev/null
echo 100
$ sudo chmod 0755 /var/www/webmp3/

OK, so webmp3 is installed, but we still need a webserver with PHP support. We're still on the same Fedora box, Nginx should be able to handle this.

NOTE: running webmp3 like this will probably spam the var/webmp3.log logfile above with the output of mpg321 and ogg123. Instead of disabling the logfile (use /dev/null) we could also install wrapper scripts. However, for this to work we have to make sure that raop_play uses them. Since we have no way to provide the executables as arguments to raop_play, we will make sure these wrapper scripts are used anyway. To explain this a bit more in detail, this is the call trace:

/usr/bin/php play.php
 \_ /opt/raop-play/bin/raop_play '' '/mnt/data/music/file.mp3' >> ./var/webmp3.log 2>&1
   \_ /opt/mpg123/bin/mpg123 -s /mnt/data/music/file.mp3

→ Somehow we have to make run mpg123 with -q (quiet):

$ grep PATH /etc/php-fpm.d/www.conf 
env[PATH] = /usr/local/bin:/usr/bin:/bin
$ sudo systemctl restart php-fpm

$ cat /usr/local/bin/ogg123
/usr/bin/ogg123 -q "$@"

$ cat /usr/local/bin/mpg321
/opt/mpg123/bin/mpg123 -q "$@"

$ sudo chmod 0755 /usr/local/bin/ogg123 /usr/local/bin/mpg321

With all that in place, our call trace should look like this:

/usr/bin/php play.php
 \_ /opt/raop-play/bin/raop_play '' '/mnt/data/music/file.mp3' >> ./var/webmp3.log 2>&1
  \_ /bin/sh /usr/local/bin/mpg321 -q -s /mnt/data/music/file.mp3
   \_ /opt/mpg123/bin/mpg123 -q -s /mnt/data/music/file.mp3