mopidy icon indicating copy to clipboard operation
mopidy copied to clipboard

Save (playlist) state on each playlist change

Open maystar opened this issue 4 years ago • 8 comments

I use mopidy on a Raspberry Pi with a (mostly) read-only root fs as music player. I turn the power supply on and off for starting and stopping the music. With mopidy 2 I used the qsaver plugin to make sure the playback resumes my playlist. Mopidy 3 persists the state when I stop mopidy and shutdown the OS, but it does not persist any state in the background. So if I hard kill the machine mopidy always start with an empty state.

Would it be possible to trigger the state persistence on each playlist change? I wouldn't expect that the state contains the position inside a track, but it would be great if the playlist and the last played track could be recovered after a boot. I think from this feature desktop users could benefit, too. Even nowadays processes crash and stop unexpected.

maystar avatar Mar 09 '20 19:03 maystar

I have managed to do this by making some changes in mopidy/core/actor.py.

Firstly, move the lines try: state_file_unlink() + error handler from near the end of _load_state(), and put into _save_state() after save_state has got the filename. With this change, the state file is only ever missing for a fraction of a second.

And the second thing is to make calls to self.teardown() in each of the functions: volume_changed, position_changed, state_changed, stream_changed and mute_changed. (A teardown comment specifically says do-not-use; but all it does is check that the save state option is configured, and then saves-the-state if so.)

The one thing I'm missing is a pause_changed() function, so the state file does not get updated when the audio is paused.

I'm not a python programmer, so I may not have done things properly, but it works for me. actor.py.txt actor.py-diffs.txt

mjkeehan avatar Mar 16 '20 17:03 mjkeehan

_save_state does not look at all thread-safe to me. I would guess that is the main reason we suggest you don't call it yourself from random places.

kingosticks avatar Mar 16 '20 17:03 kingosticks

Ahh, yeah, my programming expertise was developed long before threads unfortunately. Guess I'll have to try to understand them now. Thanks for information!!

mjkeehan avatar Mar 16 '20 19:03 mjkeehan

If you have time, could you please say what sort of things in _save_state look unsafe for threads. The only thing I can see is that the state file might get deleted by a thread which clashes with writing by another.

mjkeehan avatar Mar 19 '20 16:03 mjkeehan

Yes, exactly that. Do you not think that could give you some problems?

kingosticks avatar Mar 19 '20 16:03 kingosticks

OK thanks. I think I've got around that, so I'll post again with what I've done. Probably tomorrow, cheers, Mike.

mjkeehan avatar Mar 19 '20 17:03 mjkeehan

I have changed the way the saved state file is handled in as much that if the save_state option is true, then there will always be an up to date state_file on disk. And if the save_state option is false then any state_file on disk is deleted whenever Mopidy starts up. I think the code is thread safe now. As I said previously, I have no experience with Python, so my code may not be up-to-scratch. actor.py.diff.txt actor.py.txt

mjkeehan avatar Mar 20 '20 14:03 mjkeehan

Thanks for providing your changes, perhaps anyone else interested can make use of them. However, this use-case is outside of what we had in mind for the state restoration functionality. It would require more work to support this properly and it's not something we are looking at doing right now.

kingosticks avatar Mar 20 '20 17:03 kingosticks