2

I'm developing a music player in Python 2.7 and I have a problem I can not solve.

Sometimes it's necessary to unmount the SD card I'm playing from. Since pygame still keeps the last played file open after pygame.mixer.stop() and pygame.mixer.quit() commands, it was not possible to unmount the card.

So I modified my code to use the file open and close commands to be able to properly close the played file before the unmount. This way the unmount is working fine.

My issue is with this solution that python always hangs during the playback of the first music. There are no any exceptions or error messages, the playback just stops and the program doesn't respond any user input, even the Ctrl+C doesn't work to quit the execution from shell.

This hanging always happens at a random time, somewhere between 1 and 40 seconds after the playing has started. If I open the file directly with the pygame.mixer.music.load(myfile) command, not using the open/close solution, I never have any hanging, the program plays properly even for several hours long.

What solution shall I use to be able to properly close the played file (to be able to unmount the memory card) and also avoid hanging of the program?

Here is the relevant part of my code. It closes the previous playing session and starts playing a new file.

FailedMusicLoad = 0
pygame.mixer.music.stop()
pygame.mixer.stop()
pygame.mixer.quit()
try:
        PlayedMp3File.close()
except AttributeError:
        pass

try:                        # test if selected music file can be loaded
        PlayedMp3File = open(Selectedmp3)
except IOError:
        FailedMusicLoad = 1

if FailedMusicLoad <> 1:
    pygame.mixer.init(frequency=musicforlength.info.sample_rate)
    pygame.mixer.music.set_volume(MainVolume)
    pygame.mixer.music.load(PlayedMp3File)
    pygame.mixer.music.play()
Andralin
  • 21
  • 2

2 Answers2

0

You could try to load the entire file into memory first by using a memory-mapped file:

import mmap

...

with open(Selectedmp3) as f: 
    PlayedMp3File = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) 

pygame.mixer.music.load(PlayedMp3File) 
pygame.mixer.music.play()

This way, you only touch the file while loading it into the memory and using with ensures it gets properly closed.

sloth
  • 91,747
  • 17
  • 156
  • 204
  • Thanks, this solution seems to be working, but doesn't it use too much memory? Specially if I load sometimes extra long music files? – Andralin Nov 02 '18 at 08:07
  • If your file is e.g. 5mb, we're talking about 5mb of extra memory etc. If that's an issue is up to you to decide. – sloth Nov 02 '18 at 10:38
0

I found a simple workaround to be able to unmount the SD card.

Before unmounting it, I open a dummy mp3 file not from the SD card, but from the local filesystem using the pygame.mixer.music.load() command. I do not start playing this dummy file, just open it. After that there is no any issue, the SD card seems to be properly released by pygame and I'm able to unmount it.

Andralin
  • 21
  • 2
  • Honestly, pygame not releasing the file correctly in Windows sounds like a bug in pygame. – sloth Nov 02 '18 at 10:39