RPi-Jukebox-RFID
RPi-Jukebox-RFID copied to clipboard
🐛 | Resume issue - Playlist starts from beginning after unexpected interruption (reboot, play via iris, ...)
Bug
The resume funcion is great. My son uses it for playlist with more than 100 songs. In regular situations there is no problem with it, the resume position is saved correctly and the playout restarts fine all the time.
But when there is an unexpected interuption of the playout, e. g. by a sudden reboot (loss of power), or even when I want to start another song via iris, or something different than the normal playout functions (longer loss of WiFi connectivity), the resume function for the last playlist doesnt work anymore. The playlist starts from the beginning.
What happened
See above.
I expected this to happen
The resume function should work as in normal situations.
Software
2.2 master, Spotify edition
I think that for handling loss of power there is no easy solution.
Could you explain the other two situations a little more in detail?
A look to the resume_playout.sh gives me a hint to the problem:
the resume command works in this situation:
# Check if we got a "savepos" command after the last "resume". Otherwise we assume that the playlist was played until the end.
# In this case, start the playlist from beginning
if [ $PLAYSTATUS == "Stopped" ]
then
# Get the playlist position of the file from mpd
# Alternative approach: "mpc searchplay xx && mpc seek yy"
PLAYLISTPOS=$(echo -e playlistfind filename \"$CURRENTFILENAME\"\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=Pos: ).*')
# If the file is found, it is played from ELAPSED, otherwise start playlist from beginning. If we got a playlist position
# play from that position, not the saved one.
if [ ! -z $PLAYLISTPOS ] && [ -z $VALUE ] ;
So the Playstatus has to be "stopped" and the song / positions has to be found. By an unexpected interruption of the playout the status seems to stay "Playing", as there was no command which set the status to "Stopped". So the resume funcions cant work in this case.
The reason why you chose this behaviour is explained in the resume_playout.sh, too:
# If the playlist ends without any stop/shutdown/new swipe (you've listened to all of the tracks), # there's no savepos event and we would resume at the last position anywhere in the playlist. # To catch these, we signal it to the next "resume" call via writing it to folder.conf that # we still assume that the audio is playing. # be anything here, as we won't use the information if "Playing" is found by "resume".
A possible solution would be the implementation of a third playstatus like "Finished", which can be set when reaching the end of a playlist. But I might know the problem here. There obviously is no easy possibility to set the status because there is no event to catch when the playlist has reached the end, right?
hey. I found a possibility to cath the end of playlist by injecting some code to the mopidy core. This is obviously no permanent solution, but on my system this works great. What I did:
I edited the file "/usr/local/lib/python3.7/dist-packages/mopidy/core/actor.py"
search: import logging after add: import subprocess
search: CoreListener.send("reached_end_of_stream") after add: subprocess.run(["bash", "/home/pi/RPi-Jukebox-RFID/scripts/resume_play.sh", "-c=finished"])
In the resume_play.sh I added a new command:
finished)
# Get folder name of currently played audio
FOLDER=$(cat $PATHDATA/../settings/Latest_Folder_Played)
# Read the current config file (include will execute == read)
. "$AUDIOFOLDERSPATH/$FOLDER/folder.conf"
if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo "VAR FOLDER from settings/Latest_Folder_Played: $FOLDER" >> $PATHDATA/../logs/debug.log; fi
if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " finished FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi
# Check if "folder.conf" exists
if [ $RESUME == "ON" ] || [ $SINGLE == "ON" ];
then
# "Stopped" for signaling -c=resume that there was a stopping event
# (this is done to get a proper resume on the first track if the playlist has ended before)
# set the vars we need to change
CURRENTFILENAME="filename"
ELAPSED="0"
PLAYSTATUS="Finished"
# now calling a script which will only replace these new vars in folder.conf
# (see script for details)
. $PATHDATA/inc.writeFolderConfig.sh
if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " finished ... fertig geschrieben" >> $PATHDATA/../logs/debug.log; fi
fi
if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then cat "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" >> $PATHDATA/../logs/debug.log; fi
;;
In the resume command I disabled
PLAYSTATUS="Playing"
Finally mopidy needs the rights execute the resume_play.sh. You can do it by adding the priviledges in the sudoers, or by setfacl.
What all this does: mopidy has an internal listening event for reaching the end of streams. If this happens, resume_play.sh will be executed with the new command "finished". The new finisehd command sets the playstatus "finished" for the playlist / folder. The Playlist command "Playing" is not needed anymore. The Playlist will now be resumed until the end of the list is reached and the command finished is set. Only then it starts from the beginning.
In case of an unexpected shutdown the playlist now starts from the last saved position again. Works fine!
I know, that changing the core of mopidy is no permanent solution, but you could do it (and as I already suggested in another thread) by using an own mopidy extension.