Schlaubischlump / RAOP-Player-bindings

This library provides python bindings for the RAOP library.
GNU Lesser General Public License v3.0
1 stars 1 forks source link

Running on RPI4 / ARM #1

Open nadigo opened 2 years ago

nadigo commented 2 years ago

Hey,

I managed to compile your RAOP-Player on Rasberry PI 4 by using cmake as the pip / setup.py didn't work on the PI. I got the library compiled under libraop.cpython-39-arm-linux-gnueabihf.so, it was moved to the player folder under the name ibraop.so

When I try to run the raop_play.py I get the below error:

root@phono:~/raop_play.py# ./raop_player.py Traceback (most recent call last): File "/root/raop_play.py/./raop_player.py", line 31, in from libraop import RaopClient, RAOP_ALAC, RAOP_PCM, MAX_SAMPLES_PER_CHUNK, RAOP_CLEAR, MS2TS, TS2MS, MS2NTP, SECNTP, \ ImportError: /root/raop_play.py/libraop.so: undefined symbol: plist_json_init

Any idea why?

btw - you need to update the .gitmodules have a look https://github.com/nadigo/RAOP-Player-bindings/blob/master/.gitmodules

Schlaubischlump commented 2 years ago

Looks like you made an error while compiling / statically linking the project.

plist_json_init is a function defined in libplist. You can see it here: https://github.com/libimobiledevice/libplist/blob/master/src/plist.c. This error is telling you the function can not be found. Either you used a version of libplist, which is outdated or more likely you forgot to link the libraries using the -l flag, while compiling.

What didn't work when using the pip install method ?

Edit: Just saw that you used cmake. That means you do not need to link anything, since I compile the sources directly. It is working fine on my macOS machine using the pip install version (which executes cmake internally). Either this error has something to do with the ARM architecture or you are missing some necessary cmake flags. I do not have a Raspberry Pi 4, so I can sadly not test this. Would be good to know if libplist is working on a raspberry pi.

nadigo commented 2 years ago

you need to update .gitmodules (see my commit request that was also merged to philippe44/RAOP-Player repo). Once I fixed this and run the pip install I get the below error (missing CMAKE arg. for ARM?)

Have in mind that to get philippe44/RAOP-Player to compile on the PI, I needed to add the -pthread flag to CMakeCache.txt and re-run make (adding it to the Makefile didn't work)

CMakeCache.txt //Flags used by the CXX compiler during all build types. CMAKE_CXX_FLAGS:STRING=-pthread

Happy to help as I'm trying to build AirVinyl - always-on RPI line-in to AirPlay for my record player :-)

Here is the error:

pip install git+https://github.com/nadigo/RAOP-Player-bindings
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting git+https://github.com/nadigo/RAOP-Player-bindings
  Cloning https://github.com/nadigo/RAOP-Player-bindings to /tmp/pip-req-build-fzfq4p0_
  Running command git clone -q https://github.com/nadigo/RAOP-Player-bindings /tmp/pip-req-build-fzfq4p0_
  Running command git submodule update --init --recursive -q
Building wheels for collected packages: libraop
  Building wheel for libraop (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /usr/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-fzfq4p0_/setup.py'"'"'; __file__='"'"'/tmp/pip-req-build-fzfq4p0_/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-3swnj4wf
       cwd: /tmp/pip-req-build-fzfq4p0_/
  Complete output (45 lines):
  running bdist_wheel
  running build
  running build_ext
  CMake Error: CMake was unable to find a build program corresponding to "Ninja".  CMAKE_MAKE_PROGRAM is not set.  You probably need to select a different build tool.
  CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
  CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
  -- Configuring incomplete, errors occurred!
  See also "/tmp/pip-req-build-fzfq4p0_/build/temp.linux-armv7l-3.9/CMakeFiles/CMakeOutput.log".
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/tmp/pip-req-build-fzfq4p0_/setup.py", line 117, in <module>
      setup(
    File "/usr/lib/python3/dist-packages/setuptools/__init__.py", line 153, in setup
      return distutils.core.setup(**attrs)
    File "/usr/lib/python3.9/distutils/core.py", line 148, in setup
      dist.run_commands()
    File "/usr/lib/python3.9/distutils/dist.py", line 966, in run_commands
      self.run_command(cmd)
    File "/usr/lib/python3.9/distutils/dist.py", line 985, in run_command
      cmd_obj.run()
    File "/usr/lib/python3/dist-packages/wheel/bdist_wheel.py", line 223, in run
      self.run_command('build')
    File "/usr/lib/python3.9/distutils/cmd.py", line 313, in run_command
      self.distribution.run_command(command)
    File "/usr/lib/python3.9/distutils/dist.py", line 985, in run_command
      cmd_obj.run()
    File "/usr/lib/python3.9/distutils/command/build.py", line 135, in run
      self.run_command(cmd_name)
    File "/usr/lib/python3.9/distutils/cmd.py", line 313, in run_command
      self.distribution.run_command(command)
    File "/usr/lib/python3.9/distutils/dist.py", line 985, in run_command
      cmd_obj.run()
    File "/usr/lib/python3/dist-packages/setuptools/command/build_ext.py", line 79, in run
      _build_ext.run(self)
    File "/usr/lib/python3.9/distutils/command/build_ext.py", line 340, in run
      self.build_extensions()
    File "/usr/lib/python3.9/distutils/command/build_ext.py", line 449, in build_extensions
      self._build_extensions_serial()
    File "/usr/lib/python3.9/distutils/command/build_ext.py", line 474, in _build_extensions_serial
      self.build_extension(ext)
    File "/tmp/pip-req-build-fzfq4p0_/setup.py", line 109, in build_extension
      subprocess.check_call(
    File "/usr/lib/python3.9/subprocess.py", line 373, in check_call
      raise CalledProcessError(retcode, cmd)
  subprocess.CalledProcessError: Command '['cmake', '/tmp/pip-req-build-fzfq4p0_', '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/tmp/pip-req-build-fzfq4p0_/build/lib.linux-armv7l-3.9/', '-DPYTHON_EXECUTABLE=/usr/bin/python3', '-DLIBRAOP_VERSION_INFO=0.0.1', '-DCMAKE_BUILD_TYPE=Release', '-GNinja']' returned non-zero exit status 1.
  ----------------------------------------
  ERROR: Failed building wheel for libraop
  Running setup.py clean for libraop
Failed to build libraop
Installing collected packages: libraop
    Running setup.py install for libraop ... error
    ERROR: Command errored out with exit status 1:
     command: /usr/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-fzfq4p0_/setup.py'"'"'; __file__='"'"'/tmp/pip-req-build-fzfq4p0_/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-f95k_1ai/install-record.txt --single-version-externally-managed --compile --install-headers /usr/local/include/python3.9/libraop
         cwd: /tmp/pip-req-build-fzfq4p0_/
    Complete output (47 lines):
    running install
    running build
    running build_ext
    CMake Error: CMake was unable to find a build program corresponding to "Ninja".  CMAKE_MAKE_PROGRAM is not set.  You probably need to select a different build tool.
    CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
    CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
    -- Configuring incomplete, errors occurred!
    See also "/tmp/pip-req-build-fzfq4p0_/build/temp.linux-armv7l-3.9/CMakeFiles/CMakeOutput.log".
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-req-build-fzfq4p0_/setup.py", line 117, in <module>
        setup(
      File "/usr/lib/python3/dist-packages/setuptools/__init__.py", line 153, in setup
        return distutils.core.setup(**attrs)
      File "/usr/lib/python3.9/distutils/core.py", line 148, in setup
        dist.run_commands()
      File "/usr/lib/python3.9/distutils/dist.py", line 966, in run_commands
        self.run_command(cmd)
      File "/usr/lib/python3.9/distutils/dist.py", line 985, in run_command
        cmd_obj.run()
      File "/usr/lib/python3/dist-packages/setuptools/command/install.py", line 61, in run
        return orig.install.run(self)
      File "/usr/lib/python3.9/distutils/command/install.py", line 590, in run
        self.run_command('build')
      File "/usr/lib/python3.9/distutils/cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "/usr/lib/python3.9/distutils/dist.py", line 985, in run_command
        cmd_obj.run()
      File "/usr/lib/python3.9/distutils/command/build.py", line 135, in run
        self.run_command(cmd_name)
      File "/usr/lib/python3.9/distutils/cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "/usr/lib/python3.9/distutils/dist.py", line 985, in run_command
        cmd_obj.run()
      File "/usr/lib/python3/dist-packages/setuptools/command/build_ext.py", line 79, in run
        _build_ext.run(self)
      File "/usr/lib/python3.9/distutils/command/build_ext.py", line 340, in run
        self.build_extensions()
      File "/usr/lib/python3.9/distutils/command/build_ext.py", line 449, in build_extensions
        self._build_extensions_serial()
      File "/usr/lib/python3.9/distutils/command/build_ext.py", line 474, in _build_extensions_serial
        self.build_extension(ext)
      File "/tmp/pip-req-build-fzfq4p0_/setup.py", line 109, in build_extension
        subprocess.check_call(
      File "/usr/lib/python3.9/subprocess.py", line 373, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command '['cmake', '/tmp/pip-req-build-fzfq4p0_', '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/tmp/pip-req-build-fzfq4p0_/build/lib.linux-armv7l-3.9/', '-DPYTHON_EXECUTABLE=/usr/bin/python3', '-DLIBRAOP_VERSION_INFO=0.0.1', '-DCMAKE_BUILD_TYPE=Release', '-GNinja']' returned non-zero exit status 1.
    ----------------------------------------
ERROR: Command errored out with exit status 1: /usr/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-fzfq4p0_/setup.py'"'"'; __file__='"'"'/tmp/pip-req-build-fzfq4p0_/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-f95k_1ai/install-record.txt --single-version-externally-managed --compile --install-headers /usr/local/include/python3.9/libraop Check the logs for full command output.
Schlaubischlump commented 2 years ago

You can see the error here:

CMake Error: CMake was unable to find a build program corresponding to "Ninja"

You can fix this by installing Ninja. Use:

sudo apt update
sudo apt install -y ninja-build

After you have Ninja installed try installing again with pip.

nadigo commented 2 years ago

you were right, I can confirm it complied on RPI 4 with the pip install

nadigo commented 2 years ago

to pair do you need to pass the -pin arg? it's asking for a file

Schlaubischlump commented 2 years ago

It is no asking for a file. It is asking for a pin code. Which Apple TV are you trying to pair ? This is only necessary for Apple TV 4 and up running TV OS 10 or greater.

If you pass the pin flag and no other flags your Apple TV should display a four digit pin code. If you type that pin code in the terminal window and press enter you will get a secret. Store that secret somewhere. Now each time you try to stream something to the apple tv you can just use the secret (-s) . Requesting the pin code is a one time operation. You can generate this pin code with the perl scripts in the original RAOP-Player repo as well, in case that my implementation should be broken for some reason.

nadigo commented 2 years ago

it's not for an AppleTV it's for a speaker - what is the way to get the secret back from a speaker ?

Schlaubischlump commented 2 years ago

Which speaker? There are two possibilities:

  1. Raop-Player (and my fork) do not support the speaker
  2. You do not need a secret
nadigo commented 2 years ago

Raop-Player did work on 2 speakers in my house and stopped yesterday, maybe it's something apple added? The only thing I did was to add it to the 'Home' app on my phone but the issue continues after I deleted them from it.

speakers are:Wiim Mini Airplay Streamer and Devialet Phantom

nadigo commented 2 years ago

root@phono:~# ./raop_player.py -v 20 -p 7000 192.168.4.13 file_example_WAV_10MG.wav [09:55:03.546575] Pairing with AirPlay device 192.168.4.13 failed.

nadigo commented 2 years ago

this is from raop_play

root@phono:~# raop_play -p 7000 -v 20 192.168.4.12 file_example_WAV_10MG.wav [10:14:28.921539] exec_request:643 [0x1d1db28]: <------ : request failed, error RTSP/1.0 [10:14:29.883728] exec_request:643 [0x1d1db28]: <------ : request failed, error Content-Length: [10:14:29.884120] exec_request:643 [0x1d1db28]: <------ : request failed, error Server: double free or corruption (!prev) Aborted root@phono

nadigo commented 2 years ago

confirmed - it will work only when adding to the home app. raop_play works while yours doesn't

root@phono:~# raop_play -p 7000 -v 20 192.168.4.13 file_example_WAV_10MG.wav [10:21:28.656852] main:374 connected to 192.168.4.13 on port 7000, player latency is 1250 ms [10:21:30.657089] main:404 at 3850903290.2822171470 (2000 ms after start), played 745 ms [10:21:31.657091] main:404 at 3850903291.2822180060 (3000 ms after start), played 1743 ms ^C

root@phono:~# ./raop_player.py -v 40 -p 7000 192.168.4.13 file_example_WAV_10MG.wav [10:21:36.602463] Connected to 192.168.4.13 on port 7000, player latency is 1250 ms. ^CTraceback (most recent call last): File "/root/./raop_player.py", line 267, in if status == PLAYING and client.accept_frames() and (data := infile.read(MAX_SAMPLES_PER_CHUNK*4)): KeyboardInterrupt

Schlaubischlump commented 2 years ago

This is strange, since this is just a wrapper around RAOP-Player. I'm calling exactly the same code to stream the file. Could you wait a little bit longer before interrupting the process ? The output only shows me, that my fork is connecting just fine and then it is killed by the user.

nadigo commented 2 years ago

root@phono:~# ./raop_player.py -v 40 -p 7000 192.168.4.13 file_example_WAV_10MG.wav [10:45:22.575415] Connected to 192.168.4.13 on port 7000, player latency is 1250 ms. [10:46:22.827741] End at : 3554858531.

it timed out, also it does connect to the other speaker (once it's added to the home app) but the sound is jittered (while with the raop_player it works well)

Schlaubischlump commented 2 years ago

It might very well be the case that the Raspberry Pi is the problem. The latency between sending the chunks must be small. If your processor is too slow, then the communication overhead between the Python and the underlying C-Code is too big, meaning that the data is send too slowly. The only option to prevent this, is to optimise the for-loop which is sending the chunks. This is very hard to optimize in Python. It is much easier to just write the loop in C-Code. There is nothing I will do about this, since this is not a problem with the library, but instead a problem with the example program I wrote. The example program is just a showcase and not intended to be used as a ready to go solution for all platforms.

You got three options here:

  1. Optimise the python performance (use pypy or compile it down to C or something else)
  2. Fork my project and add another C-function to send the chunks
  3. The easiest solution: Use the original RAOP-Player binary and call it using subprocess.run or something similar. Since you only want to stream a file and not really use all features of the python bindings I provide here, this is much easier for you.