New packages: - luci-app-webradio: Web radio management with Lyrion bridge tab - luci-app-turn: TURN/STUN server UI for WebRTC (Jitsi integration) - secubox-app-lyrion-bridge: Lyrion → Squeezelite → FFmpeg → Icecast pipeline - secubox-app-squeezelite: Squeezelite audio player with FIFO output - secubox-app-turn: TURN server with ACME SSL and Jitsi setup - secubox-app-webradio: Icecast/ezstream web radio server Features: - HTTPS streaming via HAProxy (stream.gk2.secubox.in) - Lyrion Music Server bridge for streaming playlists to Icecast - TURN server with time-limited credential generation - CrowdSec integration for WebRadio security - Schedule-based radio programming with jingles Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
282 lines
6.6 KiB
Bash
282 lines
6.6 KiB
Bash
#!/bin/sh
|
|
# Squeezelite Controller - SecuBox Virtual Player CLI
|
|
|
|
set -e
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
log() { echo -e "${GREEN}[Squeezelite]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[Squeezelite]${NC} $1"; }
|
|
error() { echo -e "${RED}[Squeezelite]${NC} $1" >&2; }
|
|
|
|
uci_get() { uci -q get "squeezelite.$1" 2>/dev/null || echo "$2"; }
|
|
|
|
#--- Status ---
|
|
cmd_status() {
|
|
echo -e "${CYAN}=== Squeezelite Player Status ===${NC}"
|
|
|
|
local enabled=$(uci_get main.enabled 0)
|
|
local name=$(uci_get main.name "SecuBox-Player")
|
|
local server=$(uci_get main.server "")
|
|
local auto_discover=$(uci_get main.auto_discover 1)
|
|
|
|
echo "Player Name: $name"
|
|
echo "Enabled: $([ "$enabled" = "1" ] && echo "Yes" || echo "No")"
|
|
|
|
if pgrep -f "squeezelite" >/dev/null 2>&1; then
|
|
echo -e "Process: ${GREEN}Running${NC}"
|
|
local pid=$(pgrep -f "squeezelite" | head -1)
|
|
echo "PID: $pid"
|
|
else
|
|
echo -e "Process: ${RED}Stopped${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
if [ -n "$server" ]; then
|
|
echo "Server: $server"
|
|
elif [ "$auto_discover" = "1" ]; then
|
|
echo "Server: Auto-discover (Lyrion on network)"
|
|
else
|
|
echo "Server: Not configured"
|
|
fi
|
|
|
|
# Check Lyrion availability
|
|
local lyrion_host=$(uci_get main.server "127.0.0.1")
|
|
if curl -s "http://${lyrion_host}:9000/status.html" >/dev/null 2>&1; then
|
|
echo -e "Lyrion Server: ${GREEN}Available${NC}"
|
|
else
|
|
echo -e "Lyrion Server: ${YELLOW}Not detected${NC}"
|
|
fi
|
|
}
|
|
|
|
#--- Discover Lyrion ---
|
|
cmd_discover() {
|
|
log "Searching for Lyrion Music Server..."
|
|
|
|
# Check localhost first
|
|
if curl -s "http://127.0.0.1:9000/status.html" >/dev/null 2>&1; then
|
|
log "Found Lyrion at 127.0.0.1:9000"
|
|
echo "127.0.0.1"
|
|
return 0
|
|
fi
|
|
|
|
# Check LXC container
|
|
local lxc_ip=$(lxc-info -n lyrion 2>/dev/null | grep "IP:" | awk '{print $2}' | head -1)
|
|
if [ -n "$lxc_ip" ] && curl -s "http://${lxc_ip}:9000/status.html" >/dev/null 2>&1; then
|
|
log "Found Lyrion in LXC at $lxc_ip:9000"
|
|
echo "$lxc_ip"
|
|
return 0
|
|
fi
|
|
|
|
# Network scan for Slim Protocol (port 3483)
|
|
for ip in $(ip route | grep -oE "192\.168\.[0-9]+\.[0-9]+" | head -1 | sed 's/\.[0-9]*$/.1/'); do
|
|
local subnet=$(echo $ip | sed 's/\.[0-9]*$//')
|
|
for host in $(seq 1 254); do
|
|
local target="${subnet}.${host}"
|
|
if nc -z -w 1 "$target" 3483 2>/dev/null; then
|
|
log "Found Lyrion at $target"
|
|
echo "$target"
|
|
return 0
|
|
fi
|
|
done &
|
|
done
|
|
wait
|
|
|
|
error "No Lyrion server found"
|
|
return 1
|
|
}
|
|
|
|
#--- Connect to Server ---
|
|
cmd_connect() {
|
|
local server="$1"
|
|
|
|
if [ -z "$server" ]; then
|
|
# Auto-discover
|
|
server=$(cmd_discover 2>/dev/null)
|
|
if [ -z "$server" ]; then
|
|
error "No server specified and auto-discover failed"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
log "Connecting to Lyrion at $server..."
|
|
|
|
uci set squeezelite.main.server="$server"
|
|
uci set squeezelite.main.enabled='1'
|
|
uci commit squeezelite
|
|
|
|
/etc/init.d/squeezelite restart
|
|
|
|
sleep 2
|
|
if pgrep -f "squeezelite" >/dev/null 2>&1; then
|
|
log "Connected to $server"
|
|
else
|
|
error "Failed to connect"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
#--- Disconnect ---
|
|
cmd_disconnect() {
|
|
log "Disconnecting..."
|
|
/etc/init.d/squeezelite stop
|
|
uci set squeezelite.main.enabled='0'
|
|
uci commit squeezelite
|
|
log "Disconnected"
|
|
}
|
|
|
|
#--- Enable FIFO Output (for streaming) ---
|
|
cmd_fifo() {
|
|
case "$1" in
|
|
enable)
|
|
local path="${2:-/tmp/squeezelite.pcm}"
|
|
log "Enabling FIFO output to $path..."
|
|
uci set squeezelite.streaming.fifo_output='1'
|
|
uci set squeezelite.streaming.fifo_path="$path"
|
|
uci commit squeezelite
|
|
|
|
# Create FIFO
|
|
[ -p "$path" ] || mkfifo "$path"
|
|
|
|
log "FIFO enabled. Restart player to apply."
|
|
;;
|
|
disable)
|
|
log "Disabling FIFO output..."
|
|
uci set squeezelite.streaming.fifo_output='0'
|
|
uci commit squeezelite
|
|
log "FIFO disabled. Restart player to apply."
|
|
;;
|
|
status)
|
|
local enabled=$(uci_get streaming.fifo_output 0)
|
|
local path=$(uci_get streaming.fifo_path "/tmp/squeezelite.pcm")
|
|
echo "FIFO Output: $([ "$enabled" = "1" ] && echo "Enabled" || echo "Disabled")"
|
|
echo "FIFO Path: $path"
|
|
[ -p "$path" ] && echo "FIFO exists: Yes" || echo "FIFO exists: No"
|
|
;;
|
|
*)
|
|
echo "Usage: squeezelitectl fifo {enable|disable|status} [path]"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#--- List Audio Devices ---
|
|
cmd_devices() {
|
|
echo -e "${CYAN}=== Audio Output Devices ===${NC}"
|
|
if command -v aplay >/dev/null 2>&1; then
|
|
aplay -L 2>/dev/null | grep -E "^(default|hw:|plughw:|sysdefault)" | head -20
|
|
else
|
|
echo "alsa-utils not installed"
|
|
fi
|
|
}
|
|
|
|
#--- Set Output Device ---
|
|
cmd_output() {
|
|
local device="$1"
|
|
|
|
if [ -z "$device" ]; then
|
|
echo "Current output: $(uci_get main.output 'default')"
|
|
echo ""
|
|
echo "Available devices:"
|
|
cmd_devices
|
|
return
|
|
fi
|
|
|
|
log "Setting output to: $device"
|
|
uci set squeezelite.main.output="$device"
|
|
uci commit squeezelite
|
|
log "Output set. Restart player to apply."
|
|
}
|
|
|
|
#--- Service Control ---
|
|
cmd_start() {
|
|
/etc/init.d/squeezelite start
|
|
}
|
|
|
|
cmd_stop() {
|
|
/etc/init.d/squeezelite stop
|
|
}
|
|
|
|
cmd_restart() {
|
|
/etc/init.d/squeezelite restart
|
|
}
|
|
|
|
cmd_enable() {
|
|
uci set squeezelite.main.enabled='1'
|
|
uci commit squeezelite
|
|
/etc/init.d/squeezelite enable
|
|
log "Squeezelite enabled"
|
|
}
|
|
|
|
cmd_disable() {
|
|
uci set squeezelite.main.enabled='0'
|
|
uci commit squeezelite
|
|
/etc/init.d/squeezelite disable
|
|
log "Squeezelite disabled"
|
|
}
|
|
|
|
#--- Help ---
|
|
cmd_help() {
|
|
cat <<EOF
|
|
${CYAN}Squeezelite Controller - SecuBox Virtual Player CLI${NC}
|
|
|
|
Usage: squeezelitectl <command> [options]
|
|
|
|
${GREEN}Service Commands:${NC}
|
|
status Show player status
|
|
start Start player
|
|
stop Stop player
|
|
restart Restart player
|
|
enable Enable autostart
|
|
disable Disable autostart
|
|
|
|
${GREEN}Connection:${NC}
|
|
discover Find Lyrion servers on network
|
|
connect [server] Connect to Lyrion (auto-discover if no server)
|
|
disconnect Disconnect from server
|
|
|
|
${GREEN}Audio:${NC}
|
|
devices List audio output devices
|
|
output [device] Set/show output device
|
|
|
|
${GREEN}Streaming:${NC}
|
|
fifo enable [path] Enable FIFO output for streaming bridge
|
|
fifo disable Disable FIFO output
|
|
fifo status Show FIFO status
|
|
|
|
${GREEN}Examples:${NC}
|
|
squeezelitectl connect 192.168.1.100
|
|
squeezelitectl fifo enable /tmp/lyrion.pcm
|
|
squeezelitectl output hw:0,0
|
|
|
|
EOF
|
|
}
|
|
|
|
#--- Main ---
|
|
case "$1" in
|
|
status) cmd_status ;;
|
|
start) cmd_start ;;
|
|
stop) cmd_stop ;;
|
|
restart) cmd_restart ;;
|
|
enable) cmd_enable ;;
|
|
disable) cmd_disable ;;
|
|
discover) cmd_discover ;;
|
|
connect) shift; cmd_connect "$@" ;;
|
|
disconnect) cmd_disconnect ;;
|
|
devices) cmd_devices ;;
|
|
output) shift; cmd_output "$@" ;;
|
|
fifo) shift; cmd_fifo "$@" ;;
|
|
help|--help|-h|"")
|
|
cmd_help
|
|
;;
|
|
*)
|
|
error "Unknown command: $1"
|
|
cmd_help
|
|
exit 1
|
|
;;
|
|
esac
|