0

On the Raspberry Pi, I'm trying to play some sounds using pygame.mixer and am having a problem when playing them on any thread other than the main thread. For example, I have a keypad hooked up and when a key is pressed (for which the detection is threaded) it fires a callback and in that callback it tries to play the sound. But when it tries it, most of the time, fails with:

Fatal Python error: (pygame parachute) Segmentation Fault

If I run it on the main thread, it works fine. Is there a reason why separate threads doesn't work or a way to do it? See code below, the method being called on the thread is audio_handler.playTone()

import pygame.mixer as mixer
import glob

class audio_handler:
    def __init__(self):
        mixer.init(channels = 2)
        mixer.set_num_channels(3)
        self._chanTones = mixer.Channel(0)
        self._chanMusic = mixer.Channel(1)
        self._chanRinger = mixer.Channel(2)
        self._dtmfTones = {}
        self._songs = []
        self._musicDir = "/home/pi/music/"

        self.loadDTMF()
        #self.loadSongs()

    def cleanup(self):
        mixer.quit()

    def loadDTMF(self):
        self._dtmfTones["0"] = mixer.Sound("./DTMF/0.ogg")
        self._dtmfTones["1"] = mixer.Sound("./DTMF/1.ogg")
        self._dtmfTones["2"] = mixer.Sound("./DTMF/2.ogg")
        self._dtmfTones["3"] = mixer.Sound("./DTMF/3.ogg")
        self._dtmfTones["4"] = mixer.Sound("./DTMF/4.ogg")
        self._dtmfTones["5"] = mixer.Sound("./DTMF/5.ogg")
        self._dtmfTones["6"] = mixer.Sound("./DTMF/6.ogg")
        self._dtmfTones["7"] = mixer.Sound("./DTMF/7.ogg")
        self._dtmfTones["8"] = mixer.Sound("./DTMF/8.ogg")
        self._dtmfTones["9"] = mixer.Sound("./DTMF/9.ogg")
        self._dtmfTones["*"] = mixer.Sound("./DTMF/star.ogg")
        self._dtmfTones["#"] = mixer.Sound("./DTMF/pound.ogg")

    def loadSongs(self):
        for file in glob.glob(self._musicDir + "*.ogg"):
            self._songs.append(file)

        print str(len(self._songs)) + " songs loaded."

    def playTone(self, tone):
        if self._dtmfTones.has_key(str(tone)):
            self._dtmfTones[str(tone)].play()
            self._chanTones.set_volume(1.0, 0.0)
            self._chanTones.play(self._dtmfTones[str(tone)])
  • Does the callback work correctly for a print statement of the button press? – Fred Mar 27 '14 at 16:45
  • Yes, it works fine – Adam Haile Mar 27 '14 at 16:47
  • Does a dummy class without the pygame mixer elements work? – Fred Mar 27 '14 at 16:48
  • yeah... it's definitely pygame that is blowing up. – Adam Haile Mar 27 '14 at 16:50
  • Are you passing an instance of the class to the callback or literally the class itself? If the latter it may be trying to play the sound without the init having been run, causing it to explode. – Fred Mar 27 '14 at 16:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.