docker: add audio passthrough for containerized FM receiver

New files for running the FM receiver in Docker with audio output:

- Dockerfile.gnuradio-audio: GNU Radio image with ALSA→PulseAudio bridge
  - libasound2-plugins for ALSA PulseAudio plugin
  - /etc/asound.conf configures ALSA to route to PulseAudio

- docker-compose.fm-receiver.yml: Full FM receiver setup
  - PulseAudio socket mount for audio
  - USB passthrough for RTL-SDR (requires privileged mode)
  - XML-RPC port 8090 exposed for tuning control
  - Environment vars: FREQ_MHZ, GAIN

- entrypoint-fm.sh: Builds and runs flowgraph at specified frequency
- run-fm-receiver.sh: Helper script with usage instructions

Usage:
  HOST_UID=$(id -u) FREQ_MHZ=107.2 docker compose -f docker/docker-compose.fm-receiver.yml up
This commit is contained in:
Ryan Malloy 2026-01-29 04:12:07 -07:00
parent f6c9e465c5
commit 6c642f4a7e
4 changed files with 113 additions and 0 deletions

View File

@ -0,0 +1,35 @@
FROM librespace/gnuradio:latest
# PulseAudio client + ALSA-PulseAudio plugin for audio output
# GNU Radio uses ALSA backend, so we bridge ALSA → PulseAudio
RUN apt-get update && apt-get install -y --no-install-recommends \
pulseaudio-utils \
libpulse0 \
libasound2-plugins \
alsa-utils \
&& rm -rf /var/lib/apt/lists/*
# Configure ALSA to use PulseAudio as default output
# This makes any ALSA app (including GNU Radio) output to PulseAudio
RUN echo 'pcm.!default { type pulse }' > /etc/asound.conf && \
echo 'ctl.!default { type pulse }' >> /etc/asound.conf
# Create non-root user for PulseAudio (matches typical host UID)
ARG USER_ID=1000
ARG GROUP_ID=1000
RUN groupadd -g ${GROUP_ID} gnuradio || true \
&& useradd -m -u ${USER_ID} -g ${GROUP_ID} gnuradio || true
WORKDIR /flowgraphs
# PulseAudio socket location
ENV PULSE_SERVER=unix:/run/pulse/native
# XML-RPC port for runtime control
ENV XMLRPC_PORT=8090
EXPOSE 8090
USER gnuradio
# Default: run a flowgraph passed as argument
ENTRYPOINT ["python3"]

View File

@ -0,0 +1,32 @@
services:
fm-receiver:
build:
context: .
dockerfile: Dockerfile.gnuradio-audio
# Root required for USB device access (RTL-SDR)
user: root
privileged: true
volumes:
# PulseAudio socket for audio output (ALSA → PulseAudio bridge)
- /run/user/${HOST_UID:-1000}/pulse/native:/run/pulse/native
# Flowgraph source files
- ../examples:/flowgraphs:ro
- ../src:/src:ro
# Entrypoint script
- ./entrypoint-fm.sh:/entrypoint-fm.sh:ro
environment:
- PULSE_SERVER=unix:/run/pulse/native
- FREQ_MHZ=${FREQ_MHZ:-101.1}
- GAIN=${GAIN:-10}
# XML-RPC port for tuning control from host
ports:
- "8090:8090"
entrypoint: ["/bin/bash", "/entrypoint-fm.sh"]
stdin_open: true
tty: true

22
docker/entrypoint-fm.sh Normal file
View File

@ -0,0 +1,22 @@
#!/bin/bash
# Entrypoint for containerized FM receiver
set -e
FREQ_MHZ=${FREQ_MHZ:-101.1}
GAIN=${GAIN:-10}
python3 -c "
import sys, subprocess, os
sys.path.insert(0, '/flowgraphs')
sys.path.insert(0, '/src')
from fm_scanner import build_fm_receiver
freq = float(os.environ.get('FREQ_MHZ', '101.1'))
gain = int(os.environ.get('GAIN', '10'))
print(f'Building FM receiver for {freq} MHz (gain {gain} dB)...')
py_path = build_fm_receiver(freq, gain=gain)
print(f'Launching {py_path.name} — Ctrl+C to stop')
print(f'XML-RPC control at http://localhost:8090')
subprocess.run([sys.executable, str(py_path)])
"

24
docker/run-fm-receiver.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
# Run containerized FM receiver with audio output to host
#
# Usage: ./run-fm-receiver.sh [FREQ_MHZ] [GAIN]
# FREQ_MHZ: FM frequency (default: 101.1)
# GAIN: RF gain in dB (default: 10)
#
# Once running, use XML-RPC from host to retune:
# python -c "import xmlrpc.client; p=xmlrpc.client.ServerProxy('http://localhost:8090'); p.set_freq(107.2e6)"
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export HOST_UID=$(id -u)
export FREQ_MHZ=${1:-101.1}
export GAIN=${2:-10}
echo "Starting FM receiver at $FREQ_MHZ MHz (gain: $GAIN dB)"
echo "XML-RPC control available at http://localhost:8090"
echo "Press Ctrl+C to stop"
echo
docker compose -f "$SCRIPT_DIR/docker-compose.fm-receiver.yml" up --build