Re: [Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands

2021-02-15 Thread Patrick Wigmore
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


[Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands

2021-02-15 Thread Terry Coles
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 

Re: [Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands

2021-02-15 Thread Terry Coles
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


Re: [Dorset] On Second Entry to MP3 Player Function Program Stops Responding to External Commands

2021-02-15 Thread Terry Coles
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

2021-02-15 Thread Patrick Wigmore
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

2021-02-15 Thread Terry Coles
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

2021-02-15 Thread Patrick Wigmore
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