Raspberry Pi4B soundbox

Hello everyone,
I’d like to build a standalone, disconnected sound box with a Raspberry Pi (for example, to present elements of a work of art or a model). The idea is to play a file (.wav, .mp3, etc.) on the SD card when buttons connected to the GPIOs are pressed. Has anyone else done this before?

Hi @Olivier2704

You need to be a bit more specific.

  • You want to play/stop/pause by a button press? Look at plugin GPIO-Buttons.
  • You want to play a track, depending on which button you press?

Hello @Wheaten ,
Thank you for this quick response.
I’d like to read a file based on the button pressed. Perhaps there’s a script (Python) to run in the background ?

This is just a scribble, successfully tested. It might give you a start: I don’t teach Python.

import gpiod
import requests
import time

# Define GPIO chip and line
CHIP_NAME = "/dev/gpiochip0"  # Default chip on Raspberry Pi 4 and 5
BUTTON_LINE = 5  # Change to your actual GPIO pin number

# Volumio API URL
VOLUMIO_URL = "http://127.0.0.1:3000/api/v1/replaceAndPlay"

# Track URL or playlist
TRACK_URI = "NAS/QNAP/AC-DC/(1983) - Flick Of The Switch/0103 - AC-DC - Flick of the switch.flac" # Change this to the actual track URI


def play_track():
    """Sends command to Volumio to play a track"""
    payload = {
        "uri": TRACK_URI
    }
    try:
        response = requests.post(VOLUMIO_URL, json=payload)
        print(f"Track play command sent, response: {response.status_code}")
    except requests.exceptions.RequestException as e:
        print(f"Error sending request: {e}")

# Setup GPIO
chip = gpiod.Chip(CHIP_NAME)
button = chip.get_line(BUTTON_LINE)
button.request(consumer="volumio_button", type=gpiod.LINE_REQ_DIR_IN)

print("Listening for button press...")

try:
    while True:
        if button.get_value() == 0:  # Button pressed (falling edge)
            play_track()
            time.sleep(0.3)  # Debounce delay
        time.sleep(0.1)  # Polling interval
except KeyboardInterrupt:
    print("Exiting...")
finally:
    button.release()
May 19 08:31:09 rpi4-ws800 volumio[1377]: info: Preload queue cleared
May 19 08:31:09 rpi4-ws800 volumio[1377]: info: Adding Item to queue: mnt/NAS/QNAP/AC-DC/(1983) - Flick Of The Switch/0103 - AC-DC - Flick of the switch.flac
May 19 08:31:09 rpi4-ws800 volumio[1377]: info: Exploding uri mnt/NAS/QNAP/AC-DC/(1983) - Flick Of The Switch/0103 - AC-DC - Flick of the switch.flac in service mpd

Same script in bash:

#!/bin/bash

# Define GPIO chip and line
CHIP_NAME="/dev/gpiochip0"  # Default chip on Raspberry Pi 4 and 5
BUTTON_LINE=5  # Change to your actual GPIO pin number

# Volumio API URL
VOLUMIO_URL="http://127.0.0.1:3000/api/v1/replaceAndPlay"

# Track URL or playlist
TRACK_URI="NAS/QNAP/AC-DC/(1983) - Flick Of The Switch/0103 - AC-DC - Flick of the switch.flac"

# Function to send command to Volumio to play a track
play_track() {
    curl -X POST -H "Content-Type: application/json" -d "{\"uri\":\"$TRACK_URI\"}" "$VOLUMIO_URL"
    echo "Track play command sent"
}

echo "Listening for button press..."

while true; do
    BUTTON_STATE=$(gpioget $CHIP_NAME $BUTTON_LINE)
    
    if [ "$BUTTON_STATE" -eq 0 ]; then
        play_track
        sleep 0.3  # Debounce delay
    fi

    sleep 0.1  # Polling interval
done

Hello, @Wheaten
Thank you very much for your valuable help, I will test this as soon as I can.
Have a nice day!

final contribution for multiple buttons (GPIO needs a default High):

sudo apt-get install gpiod

#!/bin/bash

# Define GPIO chip and button lines
CHIP_NAME="/dev/gpiochip0"  # Default chip on Raspberry Pi 4 and 5
BUTTON_LINES=(2 5 6 7 8)  # GPIO pins for buttons

# Volumio API URL
VOLUMIO_URL="http://127.0.0.1:3000/api/v1/replaceAndPlay"

# Track URIs corresponding to each button
TRACK_URIS=(
    "track_01.flac"
    "track_02.flac"
    "track_03.flac"
    "track_04.flac"
    "track_05.flac"
)

# Function to send command to Volumio to play a track
play_track() {
    local track_uri=$1
    curl -X POST -H "Content-Type: application/json" -d "{\"uri\":\"$track_uri\"}" "$VOLUMIO_URL"
    echo "Track play command sent: $track_uri"
}

# Initialize all GPIO buttons to `1`
echo "Initializing GPIO pins..."
for gpio in "${BUTTON_LINES[@]}"; do
    gpioset $CHIP_NAME $gpio=1
done

echo "Listening for button presses..."

while true; do
    for i in "${!BUTTON_LINES[@]}"; do
        BUTTON_STATE=$(gpioget $CHIP_NAME "${BUTTON_LINES[$i]}")

        if [ "$BUTTON_STATE" -eq 0 ]; then
            play_track "${TRACK_URIS[$i]}"
            sleep 0.3  # Debounce delay
        fi
    done

    sleep 0.1  # Polling interval
done

Service:
sudo nano /lib/systemd/system/play_track.service

Copy/paste:

[Unit]
Description=Play Track By Button

[Service]
ExecStart=/bin/bash /home/volumio/scripts/play_track02.sh

[Install]
WantedBy=multi-user.target

ctrl+o => Enter => ctrl+x

sudo chmod 644 /lib/systemd/system/play_track.service
sudo systemctl daemon-reload && sudo systemctl enable play_track.service && sudo systemctl start play_track.service

Wow !
Thank you so much @Wheaten for this final, detailed contribution !

1 Like