Raspberry Pi musicbox after pressing next/previous button, when the track ends it fails to play next track

44 Views Asked by At

I have been building a little musicbox. It should play the mp3 files using mpg123. The music should start when one of the buttons (push button) is depressed (like sensor) it should start playing the tracks from the directory in the random order. There is one button for increasing, one for decreasing volume. Also there is next and previous buttons.

Everything is working properly, for example the song is playing when button is depressed, the volume increase and decrease, the track change after next and previous button is pressed. When the 'box is opened' and next and previous buttons not being pressed after one songs is over next starts to play.

The problem is: when next or previous buttons been pressed, after the track ends, the script fails to play next one. I think it waits for press of another button. It should play next track. The code is:

import RPi.GPIO as GPIO
import subprocess
import random
import os
import time

# Set up GPIO pins
PLAY_BUTTON_PIN = 17
NEXT_BUTTON_PIN = 5
PREV_BUTTON_PIN = 6
BUTTON_INCREASE_PIN = 26
BUTTON_DECREASE_PIN = 25
GPIO.setmode(GPIO.BCM)
GPIO.setup(PLAY_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(NEXT_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PREV_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(BUTTON_INCREASE_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(BUTTON_DECREASE_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# Set up variables
app_running = False
button_state = GPIO.input(PLAY_BUTTON_PIN)
music_dir = "/home/pi/Downloads/"
music_files = []
music_paths = []
current_song_index = 0

MAX_VOLUME = 70
MIN_VOLUME = 0

command_set = ["amixer", "sset", "Master", "0%"]
command_get = ["amixer", "get", "Master"]

# Define function to start/stop app and play next/previous songs
def toggle_app(channel):
    global app_running
    global button_state
    global current_song_index
    global music_files
    global music_paths
    if channel == PLAY_BUTTON_PIN:
        if GPIO.input(PLAY_BUTTON_PIN) != button_state:
            button_state = GPIO.input(PLAY_BUTTON_PIN)
            if button_state == GPIO.HIGH:
                if not app_running:
                    music_files = os.listdir(music_dir)
                    if len(music_files) == 0:
                        print("No music files found in directory")
                        return
                    random.shuffle(music_files)
                    music_paths = [os.path.join(music_dir, file) for file in music_files]
                    subprocess.Popen(["mpg123", "-Z", *music_paths])
                    app_running = True
                    print(f"mpg123 started with files in directory: {music_dir}")
            else:
                if app_running:
                    subprocess.run(["killall", "mpg123"])
                    app_running = False
                    music_files = []
                    music_paths = []
                    print("mpg123 stopped")
    elif channel == NEXT_BUTTON_PIN:
        if GPIO.input(NEXT_BUTTON_PIN) == GPIO.LOW and app_running:
            subprocess.run(["killall", "mpg123"])
            current_song_index = (current_song_index + 1) % len(music_files)
            subprocess.Popen(["mpg123", music_paths[current_song_index]])
            print(f"Playing next song: {music_files[current_song_index]}")
    elif channel == PREV_BUTTON_PIN:
        if GPIO.input(PREV_BUTTON_PIN) == GPIO.LOW and app_running:
            subprocess.run(["killall", "mpg123"])
            current_song_index = (current_song_index - 1) % len(music_files)
            subprocess.Popen(["mpg123", music_paths[current_song_index]])
            print(f"Playing previous song: {music_files[current_song_index]}")

# Set up interrupts
GPIO.add_event_detect(PLAY_BUTTON_PIN, GPIO.BOTH, callback=toggle_app, bouncetime=200)
GPIO.add_event_detect(NEXT_BUTTON_PIN, GPIO.FALLING, callback=lambda x: toggle_app(NEXT_BUTTON_PIN), bouncetime=200)
GPIO.add_event_detect(PREV_BUTTON_PIN, GPIO.FALLING, callback=lambda x: toggle_app(PREV_BUTTON_PIN), bouncetime=200)

while True:
    if not GPIO.input(BUTTON_INCREASE_PIN):
        # Increase volume by 3%
        result = subprocess.run(command_get, capture_output=True, text=True)
        current_volume = int(result.stdout[result.stdout.find('[')+1:result.stdout.find('%')])
        print("Current volume:", current_volume, "%")
        new_volume = current_volume + 3
        if new_volume > MAX_VOLUME:
            new_volume = MAX_VOLUME
        command_set[3] = str(new_volume) + "%"
        subprocess.run(command_set)
        print("Volume set to:", new_volume, "%")

    if not GPIO.input(BUTTON_DECREASE_PIN):
        # Decrease volume by 3%
        result = subprocess.run(command_get, capture_output=True, text=True)
        current_volume = int(result.stdout[result.stdout.find('[')+1:result.stdout.find('%')])
        print("Current volume:", current_volume, "%")
        new_volume = current_volume - 3
        if new_volume < MIN_VOLUME:
            new_volume = MIN_VOLUME
        command_set[3] = str(new_volume) + "%"
        subprocess.run(command_set)
        print("Volume set to:", new_volume, "%")

    time.sleep(0.1)

Could anyone help me with this issue. I am very inexperienced with programming.

Many thanks

I also tried to send -SIGUSR2 to play next song but don`t know how to play previous one as -SIGUSR1 pause the track.

elif channel == NEXT_BUTTON_PIN:
        if GPIO.input(NEXT_BUTTON_PIN) == GPIO.LOW and app_running:
            subprocess.run(["killall", "-SIGUSR2", "mpg123"])
            time.sleep(0.5)  # Give some time to load the next song
    elif channel == PREV_BUTTON_PIN:
        if GPIO.input(PREV_BUTTON_PIN) == GPIO.LOW and app_running:
            if GPIO.input(PREV_BUTTON_PIN) == GPIO.LOW and app_running:
            subprocess.run(["killall", "-SIGUSR1", "mpg123"])
            time.sleep(0.1)  # Give some time to load the previous song

0

There are 0 best solutions below