Search code examples
pythonpython-3.xraspberry-pipygameraspbian

Pygame music switch (ON/OFF multiple songs)


I'm really new to python so I don't have much experience. I'm creating a RPi program to play and stop 7 different songs using toggle switches (https://ktechnics.com/wp-content/uploads/2015/12/mini-6a-125vac-spdt-mts-102-3-pin-2-position-on-on-toggle-switch.jpg).

I'm using the PullUP/DOWN resistors of the GPIO pins for the switches and the pygame.mixer.music module to play the songs. It works as expected with one song:

import RPi.GPIO as GPIO
import pygame

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)

pygame.init()
pygame.mixer.init()

cancion_1 = '/media/pi/PIERRE/0001.mp3'

while True:
    switch_1 = GPIO.input(18)

    if switch_1 == False:
        if pygame.mixer.music.get_busy() == False:
            print("Cancion 1 Sonando")
            pygame.mixer.music.load(cancion_1)
            pygame.mixer.music.play()

    else:
        if pygame.mixer.music.get_busy() == True:
            print("Cancion 1 Callada")
            pygame.mixer.music.stop()

But when I try to add more songs the program only plays the first song:

import RPi.GPIO as GPIO
import pygame

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_UP)

pygame.init()
pygame.mixer.init()

cancion_1 = '/media/pi/PIERRE/0001.mp3'
cancion_2 = '/media/pi/PIERRE/0002.mp3'

while True:
    switch_1 = GPIO.input(18)
    switch_2 = GPIO.input(19)

    if switch_1 == False:
        if pygame.mixer.music.get_busy() == False:
            print("Cancion 1 Sonando")
            pygame.mixer.music.load(cancion_1)
            pygame.mixer.music.play()

    elif switch_1 == True:
        if pygame.mixer.music.get_busy() == True:
            print("Cancion 1 Callada")
            pygame.mixer.music.stop()

    elif switch_2 == False:
        if pygame.mixer.music.get_busy() == False:
            print("Cancion 2 Sonando")
            pygame.mixer.music.load(cancion_2)
            pygame.mixer.music.play()

    elif switch_2 == True:
        if pygame.mixer.music.get_busy() == True:
            print("Cancion 2 Callada")
            pygame.mixer.music.stop()

I tried creating a function for each song and calling it later but it doesn't work either. Any idea??


Solution

  • As I mentioned in the comments, your logic only allows the first song to be played. Because one of either the first condition (if switch_1 == False:) or the second (elif switch_1 == True:) will be true. Because of this, conditions 3 and 4 never get reached.

    Here's one way to reconfigure:

    import RPi.GPIO as GPIO
    import pygame
    
    # Create a list of tuples. First index is gpio pin, 2nd is song
    # This marries the pin data with the song data
    # It also allows you to easily add more pins/songs
    song_data = [(18, "/media/pi/PIERRE/0001.mp3"),
                 (19, "/media/pi/PIERRE/0002.mp3")]
    
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    
    # Use a loop to setup pins
    for pin,_ in song_data:
       GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    
    pygame.init()
    pygame.mixer.init()
    
    # A function to check a pin and react
    def check_toggle(pin, song):
        # Looks like you want to play when switch == False
        # I'm adding these variables to clarify
        button_is_pressed = not GPIO.input(pin)
        music_is_playing = pygame.mixer.music.get_busy()
        if button_is_pressed and not music_is_playing:
            pygame.mixer.music.load(song)
            pygame.mixer.music.play()
        elif not button_is_pressed and music_is_playing:
            pygame.mixer.music.stop()
    
    while True:
        for pin,song in song_data:
            check_toggle(pin, song)
        # You might want to add a sleep here to keep from hogging the CPU
    

    Note: In this example, if you have both switches on, only the first song gets played. Pygame can only play one song at a time. Which makes toggle switches seem like a bad choice here. It is not clear what should happen when 2 toggles are both switched on. Consider using momentary switches or a rotary switch.