Skip to content
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

Spotify Connect #295

Open
snizzleorg opened this issue Oct 18, 2016 · 84 comments
Open

Spotify Connect #295

snizzleorg opened this issue Oct 18, 2016 · 84 comments

Comments

@snizzleorg
Copy link

Would be awesome if spotify-connect could be supported so that one could stream from spotify to forked-daapd and then to all the speakers in the house:

https://github.com/plietar/librespot

It's probably possible to do this even now via pipe (the same was as mentioned here: #278)

See also this discussion:
plietar/librespot#88

@ejurgensen
Copy link
Member

Certainly would be an interesting feature.

It would mean that a user like me, which has both local music (+ radio) and Spotify, would need to use two clients. Personally, I prefer having all my music controllable from one client per device (mostly Remote on my phone). So what I am going for (and hoping for) is still proper integration. This is hard to do right now because of the lack of replacement for libspotify. So right now, Spotify support in forked-daapd is lackluster. The plan on my part (and @chme, I believe) is to see if Spotify delivers on their promise to make a replacement for libspotify. The announcement says before the end of this year.

Anyone who feels like writing them to encourage this should probably do so!

@snizzleorg
Copy link
Author

Yeah one would have to use two clients. (My use case is identical to yours).
Not ideal But much better than only having the playlists as we have now.
I kinda don't really expect the spotify API to be released anytime soon...

@ejurgensen
Copy link
Member

Yes, they may well disappoint. I actually have begun working on a little something that will give you all your Spotify music in forked-daapd. Basically by mixing libspotify with the web api. So I hope they will at least not cripple libspotify any more.

@snizzleorg
Copy link
Author

Cool. Let me know if I can help testing. However still think that forked-daapd besides iTunes being the only piece of software able to stream to multiple airplay speakers synchronised would be good to accept input from spotify directly via spotify-connect. also forked-daapd as a airplay target would be nice to distribute audio from e.g. an iPhone to multiple speakers.

@snizzleorg
Copy link
Author

Sounds interesting. Let me know if you need someone to test it out...

Sent from my phone.

On 26 Oct 2016, at 20:43, ejurgensen [email protected] wrote:

Yes, they may well disappoint. I actually have begun working on a little something that will give you all your Spotify music in forked-daapd. Basically by mixing libspotify with the web api. So I hope they will at least not cripple libspotify any more.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.

@ejurgensen
Copy link
Member

I agree, it’s just that adding direct support for librespot and libshairport/libshairplay in forked-daapd (and maintaining the support) is a bit more work than I can take on.

I hope that the pipe (+ metadata pipe) can serve the purpose for now. Maybe a good thing to add to the current pipe implementation would be to make forked-daapd automatically start playing a watched pipe, if there is audio being written to it. That would mean you could start playback without interacting with forked-daapd.

@snizzleorg
Copy link
Author

So for the interested:
I got https://github.com/plietar/librespot to work on the same raspberrypi that runs forked-daapd.

I created a named pipe:

mkfifo ~/music/spotify

and then run librespot like this:

/home/pi/librespot --backend pipe --device /home/pi/music/spotify -n spotifyConnect --cache /tmp > /dev/null 2>&1

then I can "play" Spotify in forked-daapd and select SpotifyConnect in the Spotify App - The output then goes to which-ever speakers selected in forked-daapd.

Not exactly elegant but it works nicely to stream Spotify from the app to all airplay speakers.

@1liminal1
Copy link

This is very cool.

https://bbs.nextthing.co/t/howto-chip-or-chip-pro-as-spotify-connect-radio/17621

I found this guide, is this what you did or?

Thanks

@snizzleorg
Copy link
Author

snizzleorg commented Sep 4, 2017

I went for step 2B from your link. I downloaded the binary.

the point however is starting it so that it outputs the audio to a named pipe, which is then read by forked-daapd

This is done as I wrote above.

@1liminal1
Copy link

Ive found a place with the install, but no idea how to install this to a headless Pi Zero

https://github.com/herrernst/librespot/releases

Any guides, im Googling, but im struggling.

@1liminal1
Copy link

1liminal1 commented Sep 5, 2017

Right, hope this helps someone in the future :)

Create the directory first, cd into that and then;

wget` https://github.com/herrernst/librespot/releases/download/v20170717-910974e/librespot-linux-armhf-raspberry_pi.zip
unzip librespot-linux-armhf-raspberry_pi.zip

@1liminal1
Copy link

1liminal1 commented Sep 5, 2017

So if I run it this way, it works, but obviously goes no where; (I have set up the pipe, same as above)

./librespot --name "AirPlay" --username "Username" --password "Password"

If I try running it like this;

./librespot --name "AirPlay" --username "Username" --password "Password" --backend pipe --device /home/pi/music/spotify -n spotifyConnect --cache /tmp > /dev/null 2>&1

It seems to just crash, any ideas?

@1liminal1
Copy link

1liminal1 commented Sep 5, 2017

Ok, so its running now, but the pipe doesnt work;

I can see a device called "AirPlay" I can play to it.

I cant see it in the remote and I can see this in the logs

laudio: Error initializing Pulseaudio: Connection refused

Im also using the native spotify "client" the one that just shows you the playlists in the remote. But I would assume if it was picking up the pipe correctly, it would show both?

@snizzleorg
Copy link
Author

Did you create the pipe?

mkfifo /home/pi/music/spotify

and of course this needs to be inside the library folder of forked-daapd

so the above assumes that /home/pi/music/ is the library folder of forked-daapd.

@snizzleorg
Copy link
Author

snizzleorg commented Sep 5, 2017

This option in /etc/forked-daapd.conf is also helpful

...
	# Watch named pipes in the library for data and autostart playback when
	# there is data to be read. To exclude specific pipes from watching,
	# consider using the above _ignore options.
	pipe_autostart = true
...

This makes forked-daapd automatically start if it detects data in the pipe. So you do not have to select the pipe file, forked-daapd will automatically do that if it detects that librespot is putting data into it.

@1liminal1
Copy link

1liminal1 commented Sep 6, 2017

so the above assumes that /home/pi/music/ is the library folder of forked-daapd.

Thats what it was, I had the default in the conf file. Thanks so much, would never have got that.

But its all working, and working well, crashes a bit though :( How are you finding stability?
Also is there a way to make this run on start up?

Thanks again for your help with this :)

@snizzleorg
Copy link
Author

snizzleorg commented Sep 7, 2017

stability is so-so. It is crashing on me always. mostly I suppose it's forked-daapd crashing. not sure why though and I haven't had time to go into debugging.

For running it as a service I use systemd

/etc/systemd/system/spotify-connect.service

pretty crude but it works.

[Unit]
Description=Spotify Connect
After=network-online.target
[Service]
Type=idle
User=pi
ExecStart=/home/pi/librespot --backend pipe --device /home/pi/music/spotify -n spotifyConnect --cache /tmp > /dev/null 2>&1
Restart=always
RestartSec=10
StartLimitInterval=30
StartLimitBurst=20
[Install]
WantedBy=multi-user.target

I can then use sudo service spotify-connect start

@ejurgensen
Copy link
Member

Don't like to hear about forked-daapd instability, so now I have also setup librespot with a pipe to test it the next few days...

Would be nice if librespot would support metadata pipes like shairport does. That could also help remove some of the volume control lag.

@1liminal1
Copy link

@snizzleorg sorry, been away, thanks for that.

Have you guys seen this?

dtcooper/raspotify#15 (comment)

Its a client that's easy to install and has a conf file for settings, like piping as you can see from this issue.

@chimpy
Copy link

chimpy commented Sep 12, 2017

@1liminal1 @snizzleorg is the one that explained it to me :P

@chimpy
Copy link

chimpy commented Sep 12, 2017

@ejurgensen Just wanted to say thanks for an awesome piece of software. The setup detailed in this thread took me about an hour, which was a lot quicker than I expected. Mostly thanks to your slick software.
Getting rid of volume control lag would be brilliant!

@1liminal1
Copy link

@chimpy Nice! and thanks for your help on that other thread :)

I also second how awesome forked-daapd is and just a general thanks for how helpful everyone is in getting stuff setup.

@ejurgensen
Copy link
Member

ejurgensen commented Sep 13, 2017

Yes, I'm hoping librespot will implement metadata pipe or file, so forked-daapd can pickup volume changes instantly. However, so far there has been no response in the thread, so might require that someone steps up and makes a PR.

I've been running the setup a few days, and so far no crashes. If there are specific circumstances that produce a crash I hope you will share.

@snizzleorg
Copy link
Author

thanks for testing. I have not had time to dig to the root of this. Not sure what the crashes are and who is to blame. It's not so easy to debug and doesn't follow a pattern so that I can recognise so far.

However if I find a little more time I will do some more thorough testing. Maybe I can find some specific circumstances.

@1liminal1
Copy link

I have mine working now as well so ill test over the next few days and let you guys know about stability.

So the meta-pipe causes the slow response, is there any workaround for that, or nothing we can do?

@Condorello
Copy link

Take a look here, seems to be more Active mantained than librespot for now:

https://github.com/Spotifyd/spotifyd

@ejurgensen
Copy link
Member

Thanks for the hint. But isn't it built on top of librespot? Or am I not understanding it properly?

It also looks like it only can output to alsa and Pulseaudio, which won't do for forked-daapd. It will need to provide raw audio so that forked-daapd can send to any output (Airplay, Chromecast, alsa etc.).

@aleszczynskig
Copy link

I use echo "<item><type>73736e63</type><code>70666C73</code><length>0</length></item>" > /media/usb-disk2/Media/Music/aux.metadata

@ejurgensen
Copy link
Member

Here is another attempt. I tested with the command you shared, and it seems to work with that. I haven't made any further tests than that, so hope you can check if it does what you are looking for.

@aleszczynskig
Copy link

aleszczynskig commented Mar 10, 2021

Thank you. I'll give it ago.

Update. Yes - it seems to work exactly as I would expect it too. Thank you for implementing this.

@aleszczynskig
Copy link

FYI - I have asked the developer of librespot-java to implement a pfls event for playback commands. He has done this via librespot-org/librespot-java@6a2679d. I have tested in combination with the deb here by @ejurgensen and the controls are now super slick and very responsive. It works better than I had hoped.

The only small caveat to this is you get approximate 0.2 seconds of the previous track play at the beginning of the next track. You can mitigate this with a sleep command or similar if scripting.

@floodwayprintco
Copy link

floodwayprintco commented Mar 11, 2021 via email

@aleszczynskig
Copy link

aleszczynskig commented Mar 12, 2021

@floodwayprintco - sure. I can put together a little write-up to cover it. I can only provide instructions for use on a raspberry pi though, if you are using other distributions you will need to alter as necessary.

FYI - at present the capabilities are not in the formal releases so you will need to install either a test deb for forked-daapd or compile from source. For librespot-Java you will need to compile from source and make a small modification to the spocon systemd configuration. Depending on your technical capabilities you may want to wait until these changes are rolled into a full release for everything involved.

@floodwayprintco
Copy link

floodwayprintco commented Mar 12, 2021 via email

@st0nec0ld
Copy link

st0nec0ld commented Mar 19, 2021

Hi,
I use forked-daapd the same way @floodwayprintco does.
Until today using the pipe capability of raspotify was my approach too. Now I encountered a Java based connector called spocon.
Additionally to the functionalities of raspotify it supports a metadata pipe that works fine with forked-daapd!

After following the installation instructions of spocon I created two files (spotify and spotify.metadata) and changed the configuration in the [player]-Section:

# Audio output device (MIXER, PIPE, STDOUT)
output = "PIPE"
# Output raw (signed) PCM to this file (`player.output` must be PIPE)
pipe = "/home/pi/music/spotify" 
# Output metadata in Shairport Sync format (https://github.com/mikebrady/shairport-sync-metadata-reader)
metadataPipe = "/home/pi/music/spotify.metadata"

After restarting spocon and forked-daapd I finally have metadata with artwork in my UI.
I hope this helps everyone who is using forked-daapd with Spotify this way. Thank you for your great work on this topic!

Hi, how you create the two files? I made it with "touch".

touch spotify
touch spotify.metadata

Then i edit spocon config.toml

metadataPipe = "/home/pi/spotify.metadata"
output = "PIPE"
pipe = "/home/pi/spotify

After Restart i cannot connect to spocon. What i doing wrong?
`

@floodwayprintco
Copy link

floodwayprintco commented Mar 19, 2021 via email

@aleszczynskig
Copy link

aleszczynskig commented Mar 20, 2021

Hello, apologies I have not found the time to respond to this. @floodwayprintco is correct, you must use mkfifo for both the audio and metadata pipes.

A brief description of what is required is listed here. I am sorry I do not have time to do a more complete write-up at this time.

  1. Install the latest release of forked-daapd to get all of the features. Follow the INSTALL.md instructions. Note the minimum version for full metadata support is 27.3. I don't think there is a deb available for this yet (it may be) but it will be soon. I compiled from source which is not hard. Just follow the instructions provided by @ejurgensen.
  2. Install spocon. Follow instructions.
  3. Download the latest version of master from librespot-java and compile.
  4. Copy the compiled librespot-api-xxx-SNAPSHOT.jar to /opt/spocon where xxx is the latest version number. It should be in the api/target directory after compilation. Note if you are compiling this on a raspberry pi you will need to compile the protobuf library manually and then call the man command mvn clean package -DprotocExecutable=/usr/local/bin/protoc assuming that /usr/local/bin is where protoc is installed to compile librespot-java otherwise you will get an error.
  5. Update /lib/systemd/system/spocon.service to point to the new jar file you copied to /opt/spocon
  6. run sudo systemctl daemon-reload
  7. update your /opt/spocon/config.toml file player section with the following settings. Updating the paths to your pipes as necessary
[player]
        # Whether to apply the Spotify loudness normalisation
        enableNormalisation = true
        # Initial volume (0-65536)
        initialVolume = 5243
        # Release mixer line after set delay (in seconds)
        releaseLineDelay = 20
        # Normalisation pregain in decibels (loud at +6, normal at +3, quiet at -5)
        normalisationPregain = 3.0
        # Output metadata in Shairport Sync format (https://github.com/mikebrady/shairport-sync-metadata-reader)
        metadataPipe = "/media/usb-disk2/Media/Music/spotify.metadata"
        # Autoplay similar songs when your music ends
        autoplayEnabled = true
        # Preferred audio quality (NORMAL, HIGH, VERY_HIGH)
        preferredAudioQuality = "VERY_HIGH"
        # Audio output device (MIXER, PIPE, STDOUT)
        output = "PIPE"
        # Crossfade overlap time (in milliseconds)
        crossfadeDuration = 0
        # Whether the player should retry fetching a chuck if it fails
        retryOnChunkError = true
        # Mixer/backend search keywords (semicolon separated)
        mixerSearchKeywords = ""
        # Output raw (signed) PCM to this file (`player.output` must be PIPE)
        pipe = "/media/usb-disk2/Media/Music/spotify"
        # Log available mixers
        logAvailableMixers = true
        # Number of volume notches
        volumeSteps = 64
        #Bypass spotify volume control (for use with forked-daapd metadata pipe or similar)
        bypassSinkVolume = true
  1. run sudo systemctl restart spocon
  2. Open your spotify client and connect to the spocon device once it is available.
  3. When you play you should now have the outputs coming from whichever devices you have selected in forked-daapd. Changing the volume in the spotify client should reflect immediately in forked-daapd. Current item metadata should also be available. You should find that the controls are very responsive. The only small lag is when you resume playback. I believe this is because of various buffers in the playback stack. It's not a big deal (a second or two).

Note I have recently asked the librespot-java developers to implement configurable scripts to run on a variety of events. These are available in the latest master build.

You will need to add this section to your config.toml if you want this to work. I have for example setup forked-daapd to connect to selected speakers when spocon resumes playback. I am sure there are many uses for these.

[shell]
        # Shell events enabled
        enabled = true
        onContextChanged = ""
        onTrackChanged = ""
        onPlaybackEnded = ""
        onPlaybackPaused = ""
        onPlaybackResumed = "/bin/bash -c /usr/local/sbin/speaker-connect.sh"
        onTrackSeeked = ""
        onMetadataAvailable = ""
        onVolumeChanged = ""
        onInactiveSession = ""
        onPanicState = ""
        onConnectionDropped = ""
        onConnectionEstablished = ""

and speaker-connect.sh looks like this

#!/bin/sh
/usr/bin/curl -s -X PUT "http://localhost:3689/api/outputs/set" --data "{\"outputs\":[\"233717573016223\",\"233797576358078\"]}"

You will need to update the ids for your devices accordingly.

I hope this helps. I am sorry it is brief. I would like to author a proper HOWTO for this and add to the wiki pages if @ejurgensen is willing for me to do that.

Finally none of this would be possible without the wonderful work of all the developers who give their free time to create these excellent examples of open-source software. Thanks to all of those involved.

@snoopbird
Copy link

Hello, first of all many thanks for this great project and to all contributors!

I have been able to successfully implement the instructions from aleszczynskig so far. However, the changes in volume are not adopted.

This notice comes in the log. What am I doing wrong?

forked-daapd[1512]: [2021-03-26 08:02:07] [DEBUG]   player: Read Shairport metadata (type=73736e63, code=70766f6c, len=21)
forked-daapd[1512]: [2021-03-26 08:02:07] [DEBUG]   player: Not applying Shairport airplay volume while software volume control is enabled (-18,07,0.00,0.00,0.00)
java[1428]: 2021-03-26 08:02:07,923 INFO  DeviceStateHandler:250 - Put state. {ts: 1616742127767, connId: ODYwY...xMTU4, reason: VOLUME_CHANGED}
forked-daapd[1512]: [2021-03-26 08:02:08] [DEBUG]   player: Read Shairport metadata (type=73736e63, code=70766f6c, len=21)
forked-daapd[1512]: [2021-03-26 08:02:08] [DEBUG]   player: Not applying Shairport airplay volume while software volume control is enabled (-19,68,0.00,0.00,0.00)
forked-daapd[1512]: [2021-03-26 08:02:08] [DEBUG]   player: Read Shairport metadata (type=73736e63, code=70766f6c, len=21)
forked-daapd[1512]: [2021-03-26 08:02:08] [DEBUG]   player: Not applying Shairport airplay volume while software volume control is enabled (-20,00,0.00,0.00,0.00)
java[1428]: 2021-03-26 08:02:08,556 INFO  DeviceStateHandler:250 - Put state. {ts: 1616742128052, connId: ODYwY...xMTU4, reason: VOLUME_CHANGED}
java[1428]: 2021-03-26 08:02:08,683 INFO  DeviceStateHandler:250 - Put state. {ts: 1616742128318, connId: ODYwY...xMTU4, reason: VOLUME_CHANGED}

@ejurgensen
Copy link
Member

@snoopbird
Copy link

I don't use shairport-sync because I use PIPE to transfer the data from Spocon (librespot-java) to forked-daapd. I don't use shairport-sync because I think it is not needed?

@ejurgensen
Copy link
Member

Sorry, misunderstood. It looks like the similar setting for Spocon might be: "bypassSinkVolume = true" (see the above)

@snoopbird
Copy link

No Problem :) I have set the value "bypassSinkVolume = true" in the configuration and it appears in the log.

Mar 26 11:35:35 raspotify java[32699]: 2021-03-26 11:35:35,795 INFO  DeviceStateHandler:247 - Put state. {ts: 1616754935499, connId: NmZkN...5QkU5, reason: VOLUME_CHANGED, request: device { device_info { can_play: true volume: 35938 name: "SpoCon-Spotify" capabilities { can_be_player: true gaia_eq_connect_id: true supports_logout: true is_observable: true volume_steps: 64 supported_types: "audio/episode" supported_types: "audio/track" command_acks: true supports_playlist_v2: true is_controllable: true supports_transfer_command: true supports_command_request: true supports_gzip_pushes: true } device_software_version: "librespot-java 1.5.6-SNAPSHOT" device_type: SPEAKER spirc_version: "3.2.6" device_id: "6fd7d2d1bb1745e86ce1c2ff05d5a0ff609c5122" } player_state { timestamp: 1616754894111 context_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" context_url: "context://spotify:artist:79xxUllDTqG8bugjRRdmIe" context_restrictions { } play_origin { feature_identifier: "desktop-client-x" feature_version: "1.1.54.592" device_identifier: "c5125b41e3cdd0eb337b02b259234108a1edd8f1" } index { track: 1 } track { uri: "spotify:track:5PLgj89ZyK6kM8z2vl0idE" uid: "toptrack5PLgj89ZyK6kM8z2vl0idE" metadata { key: "album_artist_name" value: "Witchseeker" } metadata { key: "album_artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } metadata { key: "album_disc_number" value: "1" } metadata { key: "album_title" value: "Break Away" } metadata { key: "album_uri" value: "spotify:album:2SckEHxbc2j0GidHxkhJwQ" } metadata { key: "artist_name" value: "Witchseeker" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } metadata { key: "available_file_formats" value: "[\"OGG_VORBIS_320\",\"OGG_VORBIS_160\",\"OGG_VORBIS_96\",\"AAC_24\"]" } metadata { key: "duration" value: "199467" } metadata { key: "image_large_url" value: "spotify:image:ab67616d0000b2730bcb0cc23a5fa72daecad0b0" } metadata { key: "image_small_url" value: "spotify:image:ab67616d000048510bcb0cc23a5fa72daecad0b0" } metadata { key: "image_url" value: "spotify:image:ab67616d00001e020bcb0cc23a5fa72daecad0b0" } metadata { key: "popularity" value: "5" } metadata { key: "title" value: "Break Away" } provider: "context" album_uri: "spotify:album:2SckEHxbc2j0GidHxkhJwQ" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } playback_id: "011833a8ada63c88e404514669719f30" playback_speed: 1.0 position_as_of_timestamp: 0 duration: 199467 is_playing: true options { shuffling_context: false repeating_context: false repeating_track: false } restrictions { } suppressions { } prev_tracks { uri: "spotify:track:1j8DYZpqHzHTpEkkGiNmx4" uid: "toptrack1j8DYZpqHzHTpEkkGiNmx4" metadata { key: "album_uri" value: "spotify:album:0THmDcPTOEaipA41ubPF7B" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } metadata { key: "duration" value: "149250" } provider: "context" album_uri: "spotify:album:0THmDcPTOEaipA41ubPF7B" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:52sCOP1GtDHh9CEGr2mUKk" uid: "toptrack52sCOP1GtDHh9CEGr2mUKk" metadata { key: "album_uri" value: "spotify:album:7KoBPFtaNjPyUKCdDnMRFS" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:7KoBPFtaNjPyUKCdDnMRFS" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:509DytGOFKTDG8nCHXiRuU" uid: "toptrack509DytGOFKTDG8nCHXiRuU" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:1Vf556Am126zRcg40XvHZ2" uid: "toptrack1Vf556Am126zRcg40XvHZ2" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:2BgiZvgRLvvXPsa6pcfJWX" uid: "toptrack2BgiZvgRLvvXPsa6pcfJWX" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:2Jef30hUAx4srflWlB249b" uid: "toptrack2Jef30hUAx4srflWlB249b" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:2RMWXXujopOt8irGOEtB8O" uid: "toptrack2RMWXXujopOt8irGOEtB8O" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:23JXRZsfkXfrCouMEFNijD" uid: "toptrack23JXRZsfkXfrCouMEFNijD" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:0q9zUVaY0S3GMAWmTPVKw2" uid: "toptrack0q9zUVaY0S3GMAWmTPVKw2" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } session_id: "p/hs1hgfULYyoaQ/SNa7CA" } } member_type: CONNECT_STATE is_active: true put_state_reason: VOLUME_CHANGED last_command_message_id: 1847233023 started_playing_at: 1616754685775 has_been_playing_for_ms: 43212 client_side_timestamp: 1616754935696}
Mar 26 11:35:36 raspotify java[32699]: 2021-03-26 11:35:36,072 INFO  DeviceStateHandler:247 - Put state. {ts: 1616754935696, connId: NmZkN...5QkU5, reason: VOLUME_CHANGED, request: device { device_info { can_play: true volume: 35938 name: "SpoCon-Spotify" capabilities { can_be_player: true gaia_eq_connect_id: true supports_logout: true is_observable: true volume_steps: 64 supported_types: "audio/episode" supported_types: "audio/track" command_acks: true supports_playlist_v2: true is_controllable: true supports_transfer_command: true supports_command_request: true supports_gzip_pushes: true } device_software_version: "librespot-java 1.5.6-SNAPSHOT" device_type: SPEAKER spirc_version: "3.2.6" device_id: "6fd7d2d1bb1745e86ce1c2ff05d5a0ff609c5122" } player_state { timestamp: 1616754894111 context_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" context_url: "context://spotify:artist:79xxUllDTqG8bugjRRdmIe" context_restrictions { } play_origin { feature_identifier: "desktop-client-x" feature_version: "1.1.54.592" device_identifier: "c5125b41e3cdd0eb337b02b259234108a1edd8f1" } index { track: 1 } track { uri: "spotify:track:5PLgj89ZyK6kM8z2vl0idE" uid: "toptrack5PLgj89ZyK6kM8z2vl0idE" metadata { key: "album_artist_name" value: "Witchseeker" } metadata { key: "album_artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } metadata { key: "album_disc_number" value: "1" } metadata { key: "album_title" value: "Break Away" } metadata { key: "album_uri" value: "spotify:album:2SckEHxbc2j0GidHxkhJwQ" } metadata { key: "artist_name" value: "Witchseeker" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } metadata { key: "available_file_formats" value: "[\"OGG_VORBIS_320\",\"OGG_VORBIS_160\",\"OGG_VORBIS_96\",\"AAC_24\"]" } metadata { key: "duration" value: "199467" } metadata { key: "image_large_url" value: "spotify:image:ab67616d0000b2730bcb0cc23a5fa72daecad0b0" } metadata { key: "image_small_url" value: "spotify:image:ab67616d000048510bcb0cc23a5fa72daecad0b0" } metadata { key: "image_url" value: "spotify:image:ab67616d00001e020bcb0cc23a5fa72daecad0b0" } metadata { key: "popularity" value: "5" } metadata { key: "title" value: "Break Away" } provider: "context" album_uri: "spotify:album:2SckEHxbc2j0GidHxkhJwQ" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } playback_id: "011833a8ada63c88e404514669719f30" playback_speed: 1.0 position_as_of_timestamp: 0 duration: 199467 is_playing: true options { shuffling_context: false repeating_context: false repeating_track: false } restrictions { } suppressions { } prev_tracks { uri: "spotify:track:1j8DYZpqHzHTpEkkGiNmx4" uid: "toptrack1j8DYZpqHzHTpEkkGiNmx4" metadata { key: "album_uri" value: "spotify:album:0THmDcPTOEaipA41ubPF7B" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } metadata { key: "duration" value: "149250" } provider: "context" album_uri: "spotify:album:0THmDcPTOEaipA41ubPF7B" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:52sCOP1GtDHh9CEGr2mUKk" uid: "toptrack52sCOP1GtDHh9CEGr2mUKk" metadata { key: "album_uri" value: "spotify:album:7KoBPFtaNjPyUKCdDnMRFS" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:7KoBPFtaNjPyUKCdDnMRFS" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:509DytGOFKTDG8nCHXiRuU" uid: "toptrack509DytGOFKTDG8nCHXiRuU" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:1Vf556Am126zRcg40XvHZ2" uid: "toptrack1Vf556Am126zRcg40XvHZ2" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:2BgiZvgRLvvXPsa6pcfJWX" uid: "toptrack2BgiZvgRLvvXPsa6pcfJWX" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:2Jef30hUAx4srflWlB249b" uid: "toptrack2Jef30hUAx4srflWlB249b" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:2RMWXXujopOt8irGOEtB8O" uid: "toptrack2RMWXXujopOt8irGOEtB8O" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:23JXRZsfkXfrCouMEFNijD" uid: "toptrack23JXRZsfkXfrCouMEFNijD" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } next_tracks { uri: "spotify:track:0q9zUVaY0S3GMAWmTPVKw2" uid: "toptrack0q9zUVaY0S3GMAWmTPVKw2" metadata { key: "album_uri" value: "spotify:album:2DXwYTR5YLSM0tUYe68hja" } metadata { key: "artist_uri" value: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } provider: "context" album_uri: "spotify:album:2DXwYTR5YLSM0tUYe68hja" artist_uri: "spotify:artist:79xxUllDTqG8bugjRRdmIe" } session_id: "p/hs1hgfULYyoaQ/SNa7CA" } } member_type: CONNECT_STATE is_active: true put_state_reason: VOLUME_CHANGED last_command_message_id: 1847233023 started_playing_at: 1616754685775 has_been_playing_for_ms: 43212 client_side_timestamp: 1616754935696}

@aleszczynskig
Copy link

aleszczynskig commented Mar 26, 2021

Yes - this setting is required in config.toml for spocon. I can't tell from your post; has enabling this setting worked for you?

@snoopbird
Copy link

I think it's set correctly right? Thank you! :)

### Player ###
[player]
	# Whether to apply the Spotify loudness normalisation
	enableNormalisation = false
	# Initial volume (0-65536)
	initialVolume = 5243
	# Whether librespot-java should ignore volume events, sink volume is set to the max
	bypassSinkVolume = true
	# Release mixer line after set delay (in seconds)
	releaseLineDelay = 20
	# Normalisation pregain in decibels (loud at +6, normal at +3, quiet at -5)
	normalisationPregain = 0.0
	# Output metadata in Shairport Sync format (https://github.com/mikebrady/shairport-sync-metadata-reader)
	metadataPipe = "/srv/music/spotify.metadata"
	# Autoplay similar songs when your music ends
	autoplayEnabled = true
	# Preferred audio quality (NORMAL, HIGH, VERY_HIGH)
	preferredAudioQuality = "VERY_HIGH"
	# Audio output device (MIXER, PIPE, STDOUT)
	output = "PIPE"
	# Crossfade overlap time (in milliseconds)
	crossfadeDuration = 0
	# Whether the player should retry fetching a chuck if it fails
	retryOnChunkError = true
	# Mixer/backend search keywords (semicolon separated)
	mixerSearchKeywords = ""
	# Output raw (signed) PCM to this file (`player.output` must be PIPE)
	pipe = "/srv/music/spotify"
	# Log available mixers
	logAvailableMixers = true
	# Number of volume notches
	volumeSteps = 64

@aleszczynskig
Copy link

Yes that looks correct.

FYI. You may want to change settings like the number of volume steps, pre-gain and initial volume to suit your needs. The values here are what works best for me.

@snoopbird
Copy link

OK thanks! I just pulled and built the current dev branch again. Bug is still there.
So then it seems to be 1) error from me when building librespot-java or 2) a bug in the dev branch of librespot-java.
Many thanks to your support!

@aleszczynskig
Copy link

You can use the librespot-Java master branch. Is there a reason you are using the dev branch?

@snoopbird
Copy link

As far as I understand, only this branch (git branch) currently exists there. I probably just don't know my way around git well enough.
In a pinch, I'll just wait until there is a release with the changes.

@aleszczynskig
Copy link

You are right. That is the correct branch.

@jshep321
Copy link

jshep321 commented Apr 7, 2021

Hey guys,
I installed from the "regular" branch and installed and works great on my rpi4. I used raspotify before and ran out of steam before I ever got metadata working. This works nearly out of the box, so thanks!

@snoopbird you don't need shairport-sync for spotify, but it can be configured to use this device as an airplay endpoint, in case you want to use your iOS device as a source. iphone (airplay audio sender)->shairport-sync(pipeout)->pipefile (file with mkfifo)->forked-daapd -> airplay speakers.

If you enable pipe_autostart in forked_daapd and then play from iOS to the shairport-sync device, it will take over the stream from spocon and pause the spotify session.

@snoopbird
Copy link

My goal is to transfer the music above PIPE to the owntone server above SpoCon (librespot-java). This all works wonderfully, except for the quick control of the volume with the new option bypassSinkVolume = true.

Unfortunately I don't know why.

I have again created a current build of librespot-java ("regular" branch / dev branch).

If I set the switch bypassSinkVolume = true, then I can change the volume in Spotify without this having any effect.

@jshep321
Copy link

jshep321 commented Apr 9, 2021

@snoopbird I have played around with this and after setting my config.toml file to include the bypassSinkVolume line, I get an error (log level is TRACE):

Apr  9 12:31:11 pi4-1 java[19521]: 2021-04-09 12:31:11,545 TRACE FileConfiguration:109 - Removed entry from configuration file: player.bypassSinkVolume

I have the standard install of spocon. Unclear if this option is supported?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests