-
-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Metadata pipe enhancement to send volume #317
Comments
Implement the new volume "event" shouldn't be a problem since we already have the event internally. Can you ointime to the documentation where I can see the codes to send? I guess I could also implement the control pipe, can you create a separate issue for that? |
Here are the events for volume control from https://github.com/mikebrady/shairport-sync-metadata-reader
I believe that you ignore the volume, lowest_volume and highest_values as you will send the audio stream to forked-daapd at 100% volume. Then forked-daapd will parse the airplay_volume from 0.00 to -30.00 as it already has this capability when working with shairport-sync and the volume will be controlled at the speakers natively by forked-daapd. I have created another feature request for the DACP control interface here. https://github.com/librespot-org/librespot-java/issues/318 Thank you for your excellent work. |
Wait, we are already sending that: librespot-java/player/src/main/java/xyz/gianlu/librespot/player/Player.java Lines 1033 to 1039 in 5c9c9be
|
Ah that's interesting. It doesn't seem to work for me and I know that it works with other sources to forked-daapd. I'll take a look at the logs in debug mode and see if I can find out why it is not working. I'll report back any findings. Thanks for taking a look at this. |
It was implemented back in #174 |
Are you aware of anyone who has this working?I have looked at the forked-daapd log in debug mode and it is not recording any events being received and the volume is not changing. The track metadata is coming through so the pipe seems to be working? I am doing some investigations using shairport-sync and I will get this back to you as soon as possible. So I have captured the log from forked-daapd when using shairport-sync with the metadata pipe and changing the volume. Forked-daapd logs the event and changes the volume in the UI. This does not happen when using spocon. Forked-daapd does not register the event. In my experience with this in the past, this can happen if the message is malformed or forked-daapd can't make sense of it. I am doing more investigations with the shairport-sync-metadata-reader and will report my findings here aswell. |
@uvjustin Was the one who requested it in the first place. |
So I've done a comparison between shairport-sync and spocon metadata feeds using shairport-sync-metadata-reader. There is quite a difference and it seems that there is some corruption using spocon. I have not managed to record any pvol events from spocon which is why I think forked-daapd is not responding. I have observed this when testing this before (I was constructing some very crude bash scripts to write metadata to the pipe) I'm willing to help out here wherever possible however my java skills are very limited. shairport-sync-metadata-capture.log If I was guessing, I would say the issue relates to the PICT event. It's possible that the length argument sent for the base64 encoded picture may be incorrect and this causes the receiving end to over or under read the buffer which truncates or corrupts the next event. |
@aleszczynskig Not sure why your metadata is corrupted. Seems to work fine for me. Note that the
|
I can add a null terminator, should it be at the end of the base64 string or after |
Great. Thank you for the feedback guys. That does make sense as forked-daapd was getting the correct metadata, only the volume control is broken. Maybe the changes proposed will bring it to life for me. In testing I noticed though that when changing the volume in the Spotify client, the volume is changed in the audio stream. Ideally when using the pipe and volume control with forked-daapd, the volume in the stream should be maxed out and only the metadata for volume changes should be sent with volume changes. It doesn't seem to do this currently. Is it possible to fix this too? Otherwise you get a a double amplification effect, first in the stream and then from the speaker itself. Thanks for looking into this. |
The null terminator is not an issue with forked-daapd. forked-daapd already adds a null terminator after |
@aleszczynskig In your forked-daapd logs, are you seeing any of the volume debug messages from here? |
No. Not when using librespot-java. I see these messages when using shairport-sync however and the volume changes as you would expect. |
Just compiled 5143348 and retested. The null terminator has worked in shairport-sync-metadata-reader however the output is still garbage, is this because it is UTF-8 formatted, perhaps ssmr is expecting US_ASCII? I still do not see any PVOL events though. More importantly, this change seems to have broken the metadata working in forked-daapd. |
I don't think the volume events that you send from a Spotify client ever enter the librespot-java event space. Librespot-java has its own volume in player that you can adjust via the API like this: |
@uvjustin yes you are correct, issuing the volume commands via curl does indeed send the pvol event to forked-daapd, it then works as expected. My use case is that I am using spocon as a Spotify connect destination, this is then piped to forked-daapd and out to a number of speakers around the house using airplay. I want to be able to control the volume using forked-daapd to control the speaker volumes. To do this it would require that a Spotify client (I use the Mac OS client, but also IOS and Apple Watch) can trigger the pvol events when the volume is changed. Is there a way to do this? |
I think librespot has something similar after librespot-org/librespot#447 |
I got a bit lost in the conversation. Is there something I need to change in the metadata pipe? I do not have a setup to test this stuff so I depend entirely on your feedback. I fixed the issue with the volume events not being dispatched correctly even if I believe it was beneficial for you (?). So, do I have to implement something like librespot-org/librespot#447? |
@devgianlu. Thank you. I will test your new commit tomorrow and see if it works. It would be great if you could implement the fixed volume output available in librespot-org/librespot#447 as well. |
@devgianlu - I have tested the latest commit and the volume control is working as expected. However this was after I removed the null character you included in 5143348. I noted in #317 (comment) that this entirely broke the metadata in forked-daapd. I think you may need to revert this change but once done this works correctly. Volume changes in the Spotify client are reflected in forked-daapd and the volume is changed. I am unsure whether the output audio stream is fixed now though, I suspect that it is not, being both amplified by librespot-java and then again by forked-daapd. If you are able to implement the FIXED output as per #317 (comment) then that would entirely implement this feature as per my original enhancement request and that would be awesome. |
I reverted that change. To have the fixed behavior you can just set |
My apologies, the null character won't work as it's not valid XML and the mini-xml library that forked-daapd uses to parse the XML probably won't process it. I think just taking it out makes the most sense, as the original way works and the only "issue" is ssmr writing a warning message. |
Thanks @devgianlu and @uvjustin for your work on this. I will try now with volumeSteps = 0 and feedback. Presuming this works as expected, this enhancement will be complete and you should be able to close the ticket. |
@devgianlu I have changed the volumeSteps to 0. Unfortunately this means that the Spotify client loses the ability to change the volume entirely which is not the desired effect. The aim is to always the output audio data sent to the pipe at 100% volume. When the spotify client sends a signal to change volume, this does not change the audio stream but simply sends the relevant pvol event to the metadata pipe for forked-daapd to process and implement the volume change. In effect the volume handling is offloaded to forked-daapd and librespot-java simply parsing the request from the user and forwards it on. Is this possible? Thanks |
Should be good now, you can change the |
OK - I have tested this by setting byPassSinkVolume = true and volumeSteps = 64 and it doesn't seem to work as expected. There is a double step in volume change, the first from forked-daapd as this change is almost instant and the second a few seconds later. I presume the later change is because the pipe audio stream has a different volume setting indicating that librespot-java is still changing the volume. I do not know how to test if librespot-java is changing the output volume into the pipe, so I cannot verify this, but it is very evident when listening. Is there something I should be looking for in the logs? They are very verbose so it's hard to analyse. If not, are you certain that the byPassSinkVollume setting, when set to true, sets the pipe output volume to 100% and never changes it? With volumeSteps = 0, there is no option in the Spotify client to change the volume. It is just fixed at the initialVolume setting (which for me is ~20%). One final observation and I don't know if this can be fixed. When you first connect, the output volume in Spotify is not synced to forked-daapd. Is it possible to send a pvol event with the initialVolume on connection? This prevents unexpected behaviour after the first volume change in spotify if there is a delta between the spotify volume and the forked-daapd volume settings. Thank you for your continued work on this. |
@aleszczynskig I made a dump mistake on the volume thing so I fixed that and now it's also sending a volume event right at the beginning. |
Excellent. I'll test it right away. |
Great. It all seems to be working. There is no longer a double change in volume and the initial volume seems to work as well. I think this is now working as per my initial enhancement request so I will close it. Thank you @devgianlu and @uvjustin for all of your hard work and patience on this. I'm hoping you might be able to get #318 implemented now ;) though I don't know how simple that will be. Thank you for a great project and sharing your time and skills for a great community. I'm always willing to help out in my own little way if there is anything I can do to contribute. |
I didn't do anything here.. Thanks @devgianlu =) |
Is it possible that the feature no longer works in the current dev branch? I built and tested it, but I get this result:
|
There haven't been no significant modifications since. Could you try piping to a file instead to analyze the content? |
I am not sure if I got it right after all. Is that what you mean?
|
Can you upload |
Clear. I have now "written" the metadata to a file. |
Looks fine to me, maybe someone can try parsing it and see if it works for them. |
Is your feature request related to a problem? Please describe.
You have implemented sending metadata to forked-daapd using the shairport style metadata pipe. It works very well. Thank you. It is also possible to send the current volume and any volume changes to forked-daapd via the metadata pipe so that volume changes are implemented at the speaker and not in software. This works via well with Shairport-sync and forked-daapd. Can you implement this in librespot-java? I know that the changes made using the speakers will not be communicated back to librespot as the pipe is one-way however this would provide some useful functionality.
Describe the solution you'd like
Enable an option to output the audio stream to a pipe fixed at 100% and pass the current volume and volume changes in the metadata pipe to enable forked-daapd to process volume changes using hardware controls of connected devices.
Describe alternatives you've considered
None at this time
Additional context
Because shairport-sync and forked-daapd work in the airplay world, forked-daapd can control the source volume as the source details are provided to forked-daapd via the metadata pipe so that it can establish a control channel back to the source, this enables changes on the device (playback controls, volume changes to be reflected in the source). Would it also be possible to implement an airplay control interface that forked-daapd could communicate with to enable this functionality as well?
The text was updated successfully, but these errors were encountered: