Sean
Sean

Reputation: 43

Python Pygame Music While Loop

I have a Rpi 3 with:

Magnetic Reed switch (pin 18) Oil Diffuser Ch1 relay hat Disco Ball Ch2 relay hat

I am trying to trigger the diffuser, and disco ball with the reed switch to start diffusing good smells while the disco ball spins and lights up.

The diffuser and ball are working perfectly, however when I play the mp3 with pygame it seems to loop the song in sync with sleep. I want the song to play uninterrupted until the reed switch is TRUE and play from beginning when it's false.

import RPi.GPIO as GPIO
import pygame
from time import sleep

pygame.mixer.init()
pygame.mixer.music.load("/home/sean/Downloads/song.mp3")
pygame.mixer.music.play()

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

GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(26, GPIO.OUT)
GPIO.setup(20, GPIO.OUT)

try:
    
    while (True):
        
        if GPIO.input(18):
            pygame.mixer.music.stop()
            GPIO.output(26, 1)
            GPIO.output(20, 1)
            
        elif GPIO.input(18) == False:
            pygame.mixer.music.play()
            GPIO.output(26, 0)
            GPIO.output(20, 0)
            sleep(1)
    
except KeyboardInterrupt:
    pygame.mixer.music.stop()
    GPIO.cleanup()


Upvotes: 1

Views: 158

Answers (1)

Kingsley
Kingsley

Reputation: 14924

pygame.mixer.music.play() instructs the mixer to begin playing the audio. So what you're experiencing seems to match exactly what one would expect. Everytime .play() is called, it starts again.

A nice way to do this is to use a threaded function to monitor the GPIO I/Os, and then send messages to the PyGame event loop. You do need to service the event loop, otherwise your program will be considered to be "not responding".

import pygame
import threading
import RPi.GPIO as GPIO

# Window size
WINDOW_WIDTH      = 400
WINDOW_HEIGHT     = 400

BLACK    = (  0,   0,   0)
GREEN    = (  0, 255,   0)

# custom event-loop events
MUSIC_ON_EVENT  = pygame.USEREVENT + 1
MUSIC_OFF_EVENT = pygame.USEREVENT + 2


def GPIOHandlerThread():
    global running

    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(26, GPIO.OUT)
    GPIO.setup(20, GPIO.OUT)
    
    while ( running ):
        gpio_18 = GPIO.input(18)
        if ( gpio_18 ):
            pygame.event.post( pygame.event.Event( MUSIC_OFF_EVENT ) )
            GPIO.output(26, 1)
            GPIO.output(20, 1)
        else:
            pygame.event.post( pygame.event.Event( MUSIC_ON_EVENT ) )
            GPIO.output(26, 0)
            GPIO.output(20, 0)
        time.sleep( 0.5 )  # save some electricity
            


###
### MAIN
###

pygame.init()
window  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), pygame.HWSURFACE )
pygame.display.set_caption("GPIO Events")

# Load some music
pygame.mixer.init()
pygame.mixer.music.load("/home/sean/Downloads/song.mp3")

# start a thread to handle GPIO events
gpio_thread = threading.Thread( target=GPIOHandlerThread, args=())
gpio_thread.start()


# Main loop
music_playing = False
clock = pygame.time.Clock()
running = True

while running:
    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            running = False

        elif ( event.type == MUSIC_ON_EVENT ):
            # Start the music, if necessary
            if ( not music_playing ):
                pygame.mixer.music.play(-1)  # start playback, but loop continuously
                music_playing = True

        elif ( event.type == MUSIC_OFF_EVENT ):
            # Stop the music, if playing already
            if ( music_playing ):
                pygame.mixer.music.stop()
                music_playing = False

    # Paint the screen in a gradient centred about the mouse
    if ( music_playing ):
        window.fill( GREEN )
    else:
        window.fill( BLACK )

    # TODO: Maybe draw kind of GUI, status etc.

    pygame.display.flip()

    # Clamp FPS
    clock.tick(3)   # slow update

pygame.quit()

This code has not been tested, errors should be expected.

Upvotes: 1

Related Questions