Python callback issue with GPIO on raspberry
Question: I'm an absolute python newbie and this is my first raspberry project. I try to
build a simple music player in which every input button loads a different
album (8 albums) and 3 buttons to control playback (next, pause, last).

To load the music I use a USB drive which, as soon as it is connected
automatically triggers the copy process.

The buttons are debounced with a callback function. Everything works great,
except that after new music is loaded with the USB drive the buttons don't
work anymore.

Most likely it is a simple programming issue which I - as a beginner - just
don't see.

This is the code to work with two buttons:

    
    
    #!/usr/bin/env python 
    
    import RPi.GPIO as GPIO 
    import os 
    import pyudev 
    from time import sleep 
    from mpd import MPDClient 
    from socket import error as SocketError 
    
    # Configure MPD connection settings 
    HOST = 'localhost' 
    PORT = '6600' 
    CON_ID = {'host':HOST, 'port':PORT} 
    
    #Configure Buttons 
    Button1 = 25 
    Button2 = 24 
    
    
    GPIO.setmode(GPIO.BCM) 
    GPIO.setup(Button1, GPIO.IN) 
    GPIO.setup(Button2, GPIO.IN) 
    
    
    client = MPDClient() 
    
    #Function to check if USB is connected 
    def checkForUSBDevice(name): 
            res = "" 
            context = pyudev.Context() 
            for device in context.list_devices(subsystem='block', DEVTYPE='partition'): 
                    if device.get('ID_FS_LABEL') == name: 
                            res = device.device_node 
            return res 
    
    #Function to load music from USB         
    def loadMusic(client, con_id, device): 
            os.system("mount "+device+" /music/usb") 
            os.system("/etc/init.d/mpd stop") 
            os.system("rm -r /music/mp3/*") 
            os.system("cp -r /music/usb/* /music/mp3/") 
            os.system("umount /music/usb") 
            os.system("rm /music/mpd/tag_cache") 
            os.system("/etc/init.d/mpd start") 
            os.system("mpc clear") 
            os.system("mpc ls | mpc add") 
            os.system("/etc/init.d/mpd restart") 
    
    #Function to connect to MPD 
    def mpdConnect(client, con_id): 
            try: 
                    client.connect(**con_id) 
            except SocketError: 
                    return False 
            return True 
    
    #Function to load an Album 
    def loadAlbum(number): 
        mpdConnect(client, CON_ID)   
        if client.status()["state"] == "play" or client.status()["state"] == "pause": client.stop()  
        os.system("mpc clear") 
        os.system("mpc ls "+str(number)+" | mpc add") 
        client.play() 
        client.disconnect() 
    
    
    
    #Callback Function 
    def buttonPressed(channel): 
        if channel == Button1: 
            print('Button 1 HIT') 
            loadAlbum(1) 
        elif channel == Button2: 
            print('Button 2 HIT') 
            loadAlbum(2) 
    
    
    def main(): 
        GPIO.add_event_detect(Button1, GPIO.RISING, callback=buttonPressed, bouncetime=200) 
        GPIO.add_event_detect(Button2, GPIO.RISING, callback=buttonPressed, bouncetime=200) 
    
        # This function just creates an endless loop which does 
        # nothing, in order for the button detection to work  
        try: 
            flag = 0 
            while flag == 0: 
                device = checkForUSBDevice("MUSIC") # MUSIC is the name of my thumb drive  
                if flag == 1: 
                    flag = 0 
                else: 
                    flag = 0 
    
                if device != "":  
                # USB thumb drive has been inserted, new music will be copied  
                    print('USB erkannt, Musik wird kopiert.', device) 
                    loadMusic(client, CON_ID, device)   
                    print('Musik wurde kopiert, USB kann entfernt werden!', device) 
                    while checkForUSBDevice("MUSIC") == device: 
                        sleep(1.0) 
                    print('USB wurde entfernt.') 
                    loadAlbum(1) 
    
        except KeyboardInterrupt: 
            GPIO.cleanup()  
    
    
    
    if __name__ == "__main__": 
        main() 
    

Hope anyone can help me on this?

Matthias


Answer: Here is what did the trick for me. Probably it's not the best solution but it
seams to do the trick. Only the main function was changed. Changes are
highlighted at the beginning of the line with a comment.

    
    
    def main():  
        GPIO.add_event_detect(Button1, GPIO.RISING, callback=buttonPressed, bouncetime=200)  
        GPIO.add_event_detect(Button2, GPIO.RISING, callback=buttonPressed, bouncetime=200)  
    
        # This function just creates an endless loop which does  
        # nothing, in order for the button detection to work   
        try:  
            flag = 0  
            while flag == 0:  
                device = checkForUSBDevice("MUSIC") # MUSIC is the name of my thumb drive   
                if flag == 1:  
                    flag = 0  
                else:  
                    flag = 0  
    
                if device != "":   
                # USB thumb drive has been inserted, new music will be copied   
                    print('USB erkannt, Musik wird kopiert.', device) 
    
    # Stop the callback before loading the files from the USB:  
                    GPIO.remove_event_detect(Button1) 
                    GPIO.remove_event_detect(Button2) 
    
                    loadMusic(client, CON_ID, device)    
                    print('Musik wurde kopiert, USB kann entfernt werden!', device)  
                    while checkForUSBDevice("MUSIC") == device:  
                        sleep(1.0)  
                    print('USB wurde entfernt.')  
                    loadAlbum(1)  
    
    # Recall the main function 
                    main() 
    
        except KeyboardInterrupt:  
            GPIO.cleanup() 
    

