kholbrook1303 / RPI5-Bookworm-ProjectM-Audio-Receiver

GNU General Public License v3.0
9 stars 1 forks source link

Add AirPlay implementation to the README as an optional component #17

Open kholbrook1303 opened 7 months ago

kholbrook1303 commented 7 months ago

Feature request through Reddit post. Need to investigate RPI AirPlay implementations and perform testing with an Apple device.

I should be able to start this Week 15 (April 8, 2024 - April 14, 2024).

aerogeek217 commented 7 months ago

I've started looking into this but haven't gotten it working yet. Steps that may help:

  1. When building shairport-sync, configured with the '--with-pa' flag to enable the pulseaudio backend.
  2. Set output_backend = "pa" in /etc/shairport-sync.conf
  3. Start shairport-sync after pulseaudio (I think), otherwise it will select the default alsa output.
kholbrook1303 commented 7 months ago

Thanks for the info! I'm out of town till Sunday but I plan on looking more into this when I get back.

PulseAudio does seems to add complexity and is not widely preferred among the community. I have it on my todo list to start looking into configurable alternatives.

aerogeek217 commented 7 months ago

No worries, I'll keep poking away at it. I think it's just down to selecting the correct source, but I haven't gotten shairport to show up in the list of pa sources yet.

kholbrook1303 commented 7 months ago

I have gone through the motions for shairport-sync and in my testing everything is working. That said I still dont have a means of handling the audio independently compared to say a physical connection. I will investigate further. Let me know how it goes!

aerogeek217 commented 7 months ago

Still no luck. I previously went through the same steps, except for the wayfire.ini entry (I'm not running desktop). Does shairport-sync show up as a source when you run pactl?

kholbrook1303 commented 7 months ago

Still no luck. I previously went through the same steps, except for the wayfire.ini entry (I'm not running desktop). Does shairport-sync show up as a source when you run pactl?

Nope. I still need to get more details around managing devices with AirPlay. I hear sound but there is nothing in PA. To further complicate things a fresh install of Bookworm now has Pulseaudio over Pipewire so there is some additional support that I need to write up to accommodate various versions. Was already on my todo list but now more urgent as there is a wider audience to support.

I have not tried any of this headless.... what is the exact build you ran? I can replicate your deployment as closely as possible and hopefully get some alternatives. The reason for wayfire was it would not launch under user with systemd. In the Shairport docs they mentioned if you have to use PA, to run it as a daemon.

In your scenario, it may be beneficial to spin up an ssh session and run 'shairport-sync -v' and attempt a device connection to see if perhaps something is having issues.

aerogeek217 commented 7 months ago

I'm on bookworm 64-bit (Debian 12.5). I've tried running both pulseaudio and shairport-sync in every conceivable combination - daemon started from CLI, system service, user command in a different session, and within projectMAR.py. In most cases I can connect a device and play audio, but I see no response in the visualizer. Sounds like I should try this from a desktop install (will have to wait until later in the week).

kholbrook1303 commented 7 months ago

Let me check it out first before spending too much effort. I prefer this to be headless anyway!

Thanks for your patience, and continued effort! I want this to be multi-suited and dropping the GUI may actually allow all visualizations I've hand picked to run 1080p (which really they can minus a few).

aerogeek217 commented 7 months ago

And thanks for your work putting this together. Happy to contribute to testing. I happen to be using the same Pi to run RetroPie, which I've found performs much better on the non-desktop bookworm distribution. No idea why, maybe a function of the default system services.

kholbrook1303 commented 7 months ago

And thanks for your work putting this together. Happy to contribute to testing. I happen to be using the same Pi to run RetroPie, which I've found performs much better on the non-desktop bookworm distribution. No idea why, maybe a function of the default system services.

Can you direct me to the instructions you used to get retropie up and running on RP5? Perhaps if I can reproduce your scenario I can see if there is some kind of missing dependency.

Yesterday for testing I imaged a new card with the latest Raspberry Pi OS Lite (64-bit). I felt somewhat disappointed as I expected to see much better performance but for some reason some of the visualizations are choppy. Not sure the reason. I confirmed the device is using the correct res as you can enforce res at boot (/boot/firmware/cmdline.txt) by appending the following entries:

  1. video=HDMI-A-1:1280x720M@60
  2. video=HDMI-A-2:1280x720M@60

I confirmed res enforcement by making HDMI-2 1080p and HDMI-1 as 720p and verifying the monitor output.

Shairport-Sync so far is working and presets (that do react to frequencies) were responsive for a prolonged period (I just let it play through an album to make sure there were no disconnects).

Hopefully we can determine where the problem is. I dont mind having a look at some debug log outputs. I have recently added much more to debugging so I can see all of the PA sinks/sources/modules which may or may not give us some more insight. If you do I would advise using the latest version. Just ensure the projectMAR.conf logging level is set to DEBUG (10).

aerogeek217 commented 7 months ago

I installed RetroPie earlier this week, after all of the testing with shairport-sync - so it shouldn't be a factor. That said, here is the process I used: https://retropie.org.uk/docs/Manual-Installation/

I will try a fresh install using the desktop image, just to confirm I can reproduce your setup. From there I'll try the same using the Lite version.

I also have an Elgato HD60X connected (for video capture to HyperHDR). It's possible pa is using it as the default source, which is why I was trying to get shairport-sync to show up in the list of pa sources. In any case, I'll be sure to disconnect the video capture device when testing with a new card.

kholbrook1303 commented 7 months ago

Sounds good... let me know! I was looking at potential options to control it and found shairport-metadatareader-python. This may work to if not control at least get data surrounding connected devices and whatnot.

aerogeek217 commented 7 months ago

Progress: ProjectM is now responding to shairport-sync audio, but I'm not sure what was broken originally. It seems to be related to my capture device, which is a corner case from your perspective. Things are still working even after I reconnected the capture device (maybe it's now the second source instead of the first?) Still trying to find the shairport-sync source name so I can specify it in the projectMSDL config file.

I have two remaining issues, with workarounds for each:

  1. Figure out how to pipe the audio to the hdmi output (currently getting no audio). For now I can just select my audio receiver as a second AirPlay device.
  2. Figure out how to start shairport-sync as a user service. Using the updated instructions, I'm getting an error when calling sudo systemctl --user enable shairport: "Failed to connect to bus: No medium found". For now, I'm starting it manually via a separate ssh window.

Also, I tried installing a fresh desktop image but ran into a missing dependency: lib.common. I installed lib with pip3 but ran into a new missing dependency: lib.config. I reran each of the python setup steps just to be sure I didn't miss a step, but didn't spend any additional time troubleshooting.

kholbrook1303 commented 7 months ago

Thank you very much, this is partly an oversight on my part.

I recently broke out common functions to a lib/common.py. I missed adding it to the commit. All of these libs are in the latest main branch now: https://github.com/kholbrook1303/RPI5-Bookworm-ProjectM-Audio-Receiver/tree/main/lib

Also, the user service, you cannot use sudo and that is my mistake from documentation (Too much going on right now). I updated the documentation and that should clear the "Failed to connect to bus: No medium found" error.

The no audio through hdmi part is interesting though as that is how I am testing it. Will need to investigate that further.

ratsark commented 3 months ago

Hi all! I ran into the same problem -- shairport audio wasn't getting routed correctly. I also have a USB capture card (for screen capture in Hyperion) which was being used as the default source.

So here's what worked for me to get shairport-sync's audio routed into ProjectM without interrupting playback:

I did this through code changes, but it could probably be done with the config file as well (I'm planning to add some other sources and sinks, and want fine-grained control of the prioritization between them).

I also ran into an issue with shairport-sync where it would give an error along the lines of "default audio device busy" when run via systemctl, but if I stopped it and ran it from the command line it would work fine. This turned out to be a problem with Pulse Audio not accepting connections from other users (the shairport-sync service runs under the shairport-sync user, not the logged-in user), and I was able to resolve it by following these instructions.

I also experimented with building and configuring shairport-sync to use PA instead of ALSA, but I think this is a red herring -- in either case shairport-sync will show up as a "sink-input", never as a "source". As I understand it sources are the abstraction for physical connections, while sink-inputs are the abstraction for software that's playing sound that should be routed to a sink.

So now I'm able to connect to shairport-sync from my phone and get sound output, and I can run ProjectMAR for correct visualizations without interrupting the sound output.

@kholbrook1303 Thank you so much for putting this project together! I was looking at ways to get a music visualizer going on a Pi 5, and I'm so glad you did all the hard work both to solve the problem AND to document and share your solution with the world. I really appreciate it!

One thing I'm still trying to understand is how ProjectMAR deals with sink-inputs. It doesn't seem like the code deals with them at all, and the supported devices in projectMAR.py exclude the loopback devices by default, so it's unclear to me how these would end up routed to ProjectM. But both of you were able to do it, so I must be missing something.

kholbrook1303 commented 1 month ago

@ratsark Thanks for providing the details for the audio routing issue! I would really like to reproduce this ... could you at a high level walk me through the intial device setup? The way I have performed the setup since Raspberry Pi Imager is to specify a user in a custom config so that is all taken care of by the imager.

You mentioned is adding fine grained control using prioritization. I am working on a build (currently in the dev branch), so that the system is not necessarilly bound to a single input/output device and supports multiple. For sinks I am loading 'module-combine-sink' if enabled for multiple sink playback. Then for any auxillary inputs I am loading 'module-loopback' to route the device to the active sink. When using manual mode the devices are validated/controled in the order they are specfied which is somewhat of a prioritization method but it may not fullfil your need. If you have a specific use case or requirements I would be more than happy to see how we can accomodate your request.

Now then sink-inputs. Current implementation in the main branch does not look at these. I am not sure what kind of control I would have over it but I have not encounted any issues with shairplay or plexamp routing to the default sink which is set by ProjectMAR. Now then that said I did not have a way to know if Plexamp or Shairplay were connected, so I am now on execute enumerating a list of processes and pids, then in the device discovery logic using that to determine if the application.process.id exists. If it does, the cl arguments are analyzed to determine which type of device it is and assign that device profile as a "source" device. So really this is only now used to identify what is running, but not necessarily control it.