I'm writing a C# wrapper around libspotfiy, and have a problem with the track playing. From what I can tell, when I want to start streaming a track for the first time in a session, I should call
sp_session_player_load(sessionHandle, trackHandle)
sp_session_player_play(sessionHandle, true);
This is what I'm doing, and it works fine. The problem start when I want to play something else. With a track still playing, what am I meant to do to play a new one? Should I call
sp_session_player_play(sessionHandle, false);
sp_session_player_unload(sessionHandle);
Before then calling a new round of load/play? I ask because when I do this, I often see my program hang when I call the unload, or call play with an argument of false. I'm using the get_audio_buffer_stats callback. I've got appropriate thread syncronisation in place, so I'm wondering if I'mu sing the api incorrectly?
My code reacts to a notify_main_thread callback by simply signalling to another thread, so it's totally non blocking.
I seem to have resolved things, but I'm still left a little puzzled. I did indeed remove the get_audio_buffer_stats callback. However, the thing that seemed to help was to stop doing anything in the music_delivery callbacks before calling sp_session_player_unload.
I had a lock around evrything I did in the music_delivery callback, and the same lock protecting the sp_session_player_unload. So it seems that while performing the sp_session_player_unload, another thread inside libspotify would trigger the music_delivery callback, which would naturally have to wait for the sp_session_player_unload to complete. It seems this could cause deadlock.
I thought I was doing the right thing by ensuring that the music_delivery callback and other libspotify functions (ie sp_session_player_unload) should be protected by the same mutex? Perhaps the right thing to do inside the music_delivery is to return immediately, reporting no samples taken if the attempt to get the lock fails? (and would this then be the case for all the callbacks made outside of the process_events thread?)
This is exactly what the official Mac and iOS library does, and it works fine:
When playing for the first time:
When playing again:
There are a couple of things you can check, though:
The most common hang I've seen is due to how the program implements the
notify_main_thread
callback. When you get this, you must schedule a call sosp_session_process_events
on the main thread in a non-blocking way. I.e., yournotify_main_thread
implementation should return beforesp_session_process_events
is called on the other thread.Try taking out your
get_audio_buffer_stats
implementation. This Mac/iOS library doesn't implement this at all - it isn't required.If this isn't enough, please try to get a stack trace of the hang. If you catch it in the debugger, hitting pause is often good enough.