Re: [Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands
On Mon, 15 Feb 2021 17:13:12 +, Terry Coles wrote: > When the button is pressed, the Webserver generates a message > which it sends to the Music program. There is a cron job, triggerd > by apscheduler which parses the message and in this case calls the > next_playlist() function. Ah, I think that changes things. Triggering a cron job is going to have an effect similar to starting a new thread. (Indeed, that might be precisely why you are using a cron job.) In which case, my hypothesis could well be completely wrong. I have a feeling you did explain this arrangement before, so I probably should have remembered. -- Next meeting: Online, Jitsi, Tuesday, 2021-03-02 20:00 Check to whom you are replying Meetings, mailing list, IRC, ... http://dorset.lug.org.uk New thread, don't hijack: mailto:dorset@mailman.lug.org.uk
Re: [Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands
On Monday, 15 February 2021 17:06:07 GMT Patrick Wigmore wrote: > I'm left wondering: > "Where are you calling next_playlist()?" > "What do you mean by 'freezes'?" That is triggered by another button on the Webserver Control page. > If you are calling next_playlist from an interrupt handler and if, by > 'freezes', you mean 'seems to stop handling interrupts', then this > could just be another manifestation of the same issue. Indirectly yes. When the button is pressed, the Webserver generates a message which it sends to the Music program. There is a cron job, triggerd by apscheduler which parses the message and in this case calls the next_playlist() function. So yes. It could still be related. -- Terry Coles -- Next meeting: Online, Jitsi, Tuesday, 2021-03-02 20:00 Check to whom you are replying Meetings, mailing list, IRC, ... http://dorset.lug.org.uk New thread, don't hijack: mailto:dorset@mailman.lug.org.uk
Re: [Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands
On Mon, 15 Feb 2021 15:02:23 +, Terry Coles wrote: > I just realised that things aren't quite as I thought. If I start > the program with the Plylist Number set to zero, the Music Player > doesn't start, as is expected. If I then call next_playlist(): > > def next_playlist(): > global playlists, playlist_index > > playlist_index += 1 # Select > the next Playlist Number > if playlist_index > len(playlists): > playlist_index = 1 > > Status[9] = str(playlist_index) > > mp3_player_start() > > then the software behaves as if the player has already been run and > freezes. Sorry, I didn't see this before replying. My response did not take any of this into account. I'm left wondering: "Where are you calling next_playlist()?" "What do you mean by 'freezes'?" If you are calling next_playlist from an interrupt handler and if, by 'freezes', you mean 'seems to stop handling interrupts', then this could just be another manifestation of the same issue. Otherwise, I'm less sure. Patrick -- Next meeting: Online, Jitsi, Tuesday, 2021-03-02 20:00 Check to whom you are replying Meetings, mailing list, IRC, ... http://dorset.lug.org.uk New thread, don't hijack: mailto:dorset@mailman.lug.org.uk
Re: [Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands
On Monday, 15 February 2021 16:51:06 GMT Patrick Wigmore wrote: > mp3_player_start() contains a while loop, and it looks like that is > not supposed to terminate until playlist_index == 0. > > If your interrupt handler calls restartmp3(), and restartmp3() calls > mp3_player_start(), then the interrupt handler will not terminate > until playlist_index == 0 and both functions return. So, I think that > might be the problem. > > I don't think you've posted enough code to know for sure, but if this > is what's going on, then I think I would try having the interrupt > handler run mp3_player_start() in a new thread. That way, the > interrupt handler should terminate as soon as it has set the thread > going, leaving mp3_player_start() to carry on on its own. > > e.g. > > threading.Thread(target=mp3_player_start).start() Patrick, Thanks. I was beginning to realise (dimly) that it was something like this and have been trying to ensure that all functions exited cleanly. Ideally, I think that rather than having my program start the MP3 Player during startup it needs to always be started from an interrupt and that's what I was looking at. That way the program will sit in the almost infinitely long delay that was always the intention, except when an interrupt is being serviced. However, I can see that this isn't the whole story and I need to look into your suggestion in a bit more detail. I won't have time to do that this evening, so I'll have another go first thing in the morning. Thanks again. -- Terry Coles -- Next meeting: Online, Jitsi, Tuesday, 2021-03-02 20:00 Check to whom you are replying Meetings, mailing list, IRC, ... http://dorset.lug.org.uk New thread, don't hijack: mailto:dorset@mailman.lug.org.uk
Re: [Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands
On Mon, 15 Feb 2021 12:53:24 +, Terry Coles wrote: > To me it seems that the software suddenly starts ignoring interrupts This makes me think the code that handled the previous interrupt might still be running. Having the previous interrupt handler still running is likely to block further interrupts from being handled. Taking a look at the code: mp3_player_start() contains a while loop, and it looks like that is not supposed to terminate until playlist_index == 0. If your interrupt handler calls restartmp3(), and restartmp3() calls mp3_player_start(), then the interrupt handler will not terminate until playlist_index == 0 and both functions return. So, I think that might be the problem. I don't think you've posted enough code to know for sure, but if this is what's going on, then I think I would try having the interrupt handler run mp3_player_start() in a new thread. That way, the interrupt handler should terminate as soon as it has set the thread going, leaving mp3_player_start() to carry on on its own. e.g. threading.Thread(target=mp3_player_start).start() Patrick -- Next meeting: Online, Jitsi, Tuesday, 2021-03-02 20:00 Check to whom you are replying Meetings, mailing list, IRC, ... http://dorset.lug.org.uk New thread, don't hijack: mailto:dorset@mailman.lug.org.uk
Re: [Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands
On Monday, 15 February 2021 12:53:24 GMT Terry Coles wrote: > To me it seems that the software suddenly starts ignoring interrupts because > the command should be detected after no more than 1 second when apscheduler > calls the command checking function which works fine up to that point. I just realised that things aren't quite as I thought. If I start the program with the Plylist Number set to zero, the Music Player doesn't start, as is expected. If I then call next_playlist(): def next_playlist(): global playlists, playlist_index playlist_index += 1 # Select the next Playlist Number if playlist_index > len(playlists): playlist_index = 1 Status[9] = str(playlist_index) mp3_player_start() then the software behaves as if the player has already been run and freezes. Presumably therefore, there is something in the underlying environment within the running code which isn't there when the program is launched, but is by the time the code is ready to process commands. -- Terry Coles -- Next meeting: Online, Jitsi, Tuesday, 2021-03-02 20:00 Check to whom you are replying Meetings, mailing list, IRC, ... http://dorset.lug.org.uk New thread, don't hijack: mailto:dorset@mailman.lug.org.uk
[Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands
Hi (Again), I'm inching towards squashing the (known) bugs in my Music Player and Bells software. By and large the Flask code is doing exactly what it should do and displays the current status of the two programs and also sends the correct commands to them when the control buttons are pressed. I have a bug which I'm sure is something to do with the fact that I am calling the mpg123 player a second time having previously killed it. I have attached two files to this message (since I understand that the list now accepts attachments as long as they aren't executable). The file 'Minster_Music_Software_Fragment.txt' contains the three functions that are used in this scenario and the file 'Console_Output.txt' shows what is written to the terminal from the point where I launch it to the point where I hit Ctrl-C to get out of it. I have edited this to remove all the messaging between the Webserver and the Music program, so only the relevant data remains. Here is what is supposed to happen: 1. At program Startup the sockets code sets up all connections. From then until Step 5 below all messaging works fine. 2. The function mp3_player_start() starts the mpg123 player with a List containing the filenames in the current playlist. (Most of this code was written 3+ years ago and is launched at program startup.) 3. While the contents of List is being played the software waits for the mpg123 player to exit at the end of the Playlist, whereupon the Playlist Number is incremented and the next Playlist is passed to mpg123, and so on for ever. 4. When a "Stop Music" command is received from the Webserver, the function mp3_player_stop() is called and the old Playlist Number is stored to ensure that the music can start again at the same place. Then the Playlist Number is set to zero before the mpg123 player is killed. This means that the mp3_player.wait() in the function mp3_player_start() returns and because the Playlist Number is zero the program breaks out of the loop. This all appears to work fine. 5. When a "Start Music" command is received from the Webserver, the function restartmp3() is called, the old Playlist Number is restored and the function mp3_player_start() is called again. The music starts as it should, but this is the point where it all goes wrong, because the Music Player software then stops responding to commands from the Webserver. To me it seems that the software suddenly starts ignoring interrupts because the command should be detected after no more than 1 second when apscheduler calls the command checking function which works fine up to that point. Is there anything obviously wrong with what I've done (apart from my rather noddy coding techniques that is)? (If the list rejects these attachments, I'll put them up on my website.) -- Terry Colesdef mp3_player_start(): # Setup and run the MP3 Player global playlists, playlist_index, mp3_player, Status print("") print("Entry into mp3_player_start()") print("Playlist Number = " +str(playlist_index)) print("") while playlist_index != 0: print ("Playlist Number = " + str(playlist_index)) print ("Playlist Length = " + str(len(playlists))) Status[9] = str(playlist_index) # Current Playlist mp3_subdir = playlists[playlist_index - 1] # directory containing mp3 files for the current Playlist playlist = sorted(glob.glob(mp3_subdir + '/*.[Mm][Pp]3')) # Create a list of files to be played in the current directory Status[10] = playlist mpg_list = ['mpg123'] args = mpg_list + playlist print (args) mp3_player = subprocess.Popen(args) mp3_wait = mp3_player.wait() if not mp3_wait: print('MP3 Player: mpg123 failed:%#x\n' % mp3_wait) mp3_player = None if playlist_index == 0: print("Break from Playlist Loop") break next_playlist() def mp3_player_stop(): # Setup and run the MP3 Player global mp3_player, playlist_index, last_playlist_index, Status last_playlist_index = playlist_index playlist_index = 0 # Not Playing Flag. mp3_player.terminate() mp3_wait = mp3_player.wait() if not mp3_wait: print ('MP3 Player: mpg123 failed:%#x\n' % mp3_wait) mp3_player = None print("Music Stopped") Status[10] = "Not Playing" def restartmp3(): # Restart the MP3 Player if the Wedding Sequence is completed. global playlist_index, last_playlist_index playlist_index = last_playlist_index # Restore the Plylist Number to what it was last time the Player was stopped. mp3_player_start() # (mp3_player_start() increments the index.) pi@minster-music:~ $ python3 minstermusic.py 5 second