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>
676 lines
17 KiB
Bash
676 lines
17 KiB
Bash
#!/bin/sh
|
|
# WebRadio Controller - SecuBox Backend CLI
|
|
# Manages Icecast, Ezstream, DarkIce streaming services
|
|
|
|
set -e
|
|
|
|
CONF_DIR="/srv/webradio/config"
|
|
MUSIC_DIR="/srv/webradio/music"
|
|
JINGLE_DIR="/srv/webradio/jingles"
|
|
PLAYLIST_FILE="/tmp/webradio_playlist.m3u"
|
|
ICECAST_XML="$CONF_DIR/icecast.xml"
|
|
EZSTREAM_XML="$CONF_DIR/ezstream.xml"
|
|
DARKICE_CFG="$CONF_DIR/darkice.cfg"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
log() { echo -e "${GREEN}[WebRadio]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[WebRadio]${NC} $1"; }
|
|
error() { echo -e "${RED}[WebRadio]${NC} $1" >&2; }
|
|
|
|
uci_get() { uci -q get "webradio.$1" 2>/dev/null || echo "$2"; }
|
|
|
|
#--- Status ---
|
|
cmd_status() {
|
|
echo -e "${CYAN}=== WebRadio Status ===${NC}"
|
|
|
|
local enabled=$(uci_get main.enabled 0)
|
|
local name=$(uci_get main.name "SecuBox Radio")
|
|
local port=$(uci_get main.port 8000)
|
|
|
|
echo "Station: $name"
|
|
echo "Enabled: $([ "$enabled" = "1" ] && echo "Yes" || echo "No")"
|
|
echo ""
|
|
|
|
# Icecast status
|
|
if pgrep -f "icecast" >/dev/null 2>&1; then
|
|
echo -e "Icecast: ${GREEN}Running${NC} (port $port)"
|
|
# Get listener count
|
|
local listeners=$(curl -s "http://127.0.0.1:$port/status-json.xsl" 2>/dev/null | jsonfilter -e '@.icestats.source.listeners' 2>/dev/null || echo "0")
|
|
echo "Listeners: $listeners"
|
|
else
|
|
echo -e "Icecast: ${RED}Stopped${NC}"
|
|
fi
|
|
|
|
# Ezstream status
|
|
if pgrep -f "ezstream" >/dev/null 2>&1; then
|
|
echo -e "Ezstream: ${GREEN}Running${NC} (playlist mode)"
|
|
else
|
|
echo -e "Ezstream: ${YELLOW}Stopped${NC}"
|
|
fi
|
|
|
|
# DarkIce status
|
|
if pgrep -f "darkice" >/dev/null 2>&1; then
|
|
echo -e "DarkIce: ${GREEN}Running${NC} (live mode)"
|
|
else
|
|
echo -e "DarkIce: ${YELLOW}Stopped${NC}"
|
|
fi
|
|
|
|
# Exposure status
|
|
local domain=$(uci_get exposure.domain "")
|
|
if [ -n "$domain" ]; then
|
|
echo ""
|
|
echo "Exposed at: https://$domain/"
|
|
fi
|
|
}
|
|
|
|
#--- Generate Configs ---
|
|
cmd_genconfig() {
|
|
log "Generating configuration files..."
|
|
mkdir -p "$CONF_DIR"
|
|
|
|
# Generate Icecast config
|
|
generate_icecast_config
|
|
|
|
# Generate Ezstream config
|
|
generate_ezstream_config
|
|
|
|
# Generate DarkIce config
|
|
generate_darkice_config
|
|
|
|
log "Configuration files generated in $CONF_DIR"
|
|
}
|
|
|
|
generate_icecast_config() {
|
|
local name=$(uci_get main.name "SecuBox Radio")
|
|
local port=$(uci_get main.port 8000)
|
|
local max_listeners=$(uci_get main.max_listeners 100)
|
|
local source_pass=$(uci_get main.source_password "hackme")
|
|
local admin_pass=$(uci_get main.admin_password "admin123")
|
|
local relay_pass=$(uci_get main.relay_password "relay123")
|
|
|
|
cat > "$ICECAST_XML" <<EOF
|
|
<icecast>
|
|
<location>SecuBox</location>
|
|
<admin>admin@secubox.local</admin>
|
|
<limits>
|
|
<clients>$max_listeners</clients>
|
|
<sources>5</sources>
|
|
<queue-size>524288</queue-size>
|
|
<client-timeout>30</client-timeout>
|
|
<header-timeout>15</header-timeout>
|
|
<source-timeout>10</source-timeout>
|
|
<burst-on-connect>1</burst-on-connect>
|
|
<burst-size>65535</burst-size>
|
|
</limits>
|
|
<authentication>
|
|
<source-password>$source_pass</source-password>
|
|
<relay-password>$relay_pass</relay-password>
|
|
<admin-user>admin</admin-user>
|
|
<admin-password>$admin_pass</admin-password>
|
|
</authentication>
|
|
<hostname>localhost</hostname>
|
|
<listen-socket>
|
|
<port>$port</port>
|
|
<bind-address>0.0.0.0</bind-address>
|
|
</listen-socket>
|
|
<mount>
|
|
<mount-name>/stream</mount-name>
|
|
<fallback-mount>/silence.mp3</fallback-mount>
|
|
<fallback-override>1</fallback-override>
|
|
<stream-name>$name</stream-name>
|
|
<stream-description>SecuBox Community Radio</stream-description>
|
|
<genre>Various</genre>
|
|
<public>0</public>
|
|
</mount>
|
|
<mount>
|
|
<mount-name>/live</mount-name>
|
|
<stream-name>$name - Live</stream-name>
|
|
<public>0</public>
|
|
</mount>
|
|
<fileserve>1</fileserve>
|
|
<paths>
|
|
<basedir>/usr/share/icecast</basedir>
|
|
<logdir>/var/log/webradio</logdir>
|
|
<webroot>/usr/share/icecast/web</webroot>
|
|
<adminroot>/usr/share/icecast/admin</adminroot>
|
|
<pidfile>/var/run/icecast.pid</pidfile>
|
|
</paths>
|
|
<logging>
|
|
<accesslog>access.log</accesslog>
|
|
<errorlog>error.log</errorlog>
|
|
<loglevel>3</loglevel>
|
|
</logging>
|
|
<security>
|
|
<chroot>0</chroot>
|
|
<changeowner>
|
|
<user>icecast</user>
|
|
<group>icecast</group>
|
|
</changeowner>
|
|
</security>
|
|
</icecast>
|
|
EOF
|
|
}
|
|
|
|
generate_ezstream_config() {
|
|
local port=$(uci_get main.port 8000)
|
|
local source_pass=$(uci_get main.source_password "hackme")
|
|
local format=$(uci_get stream.format "mp3")
|
|
local bitrate=$(uci_get stream.bitrate 128)
|
|
local samplerate=$(uci_get stream.samplerate 44100)
|
|
local channels=$(uci_get stream.channels 2)
|
|
local shuffle=$(uci_get playlist.shuffle 1)
|
|
|
|
cat > "$EZSTREAM_XML" <<EOF
|
|
<ezstream>
|
|
<url>http://localhost:$port/stream</url>
|
|
<sourcepassword>$source_pass</sourcepassword>
|
|
<format>MP3</format>
|
|
<filename>$PLAYLIST_FILE</filename>
|
|
<playlist_program>0</playlist_program>
|
|
<shuffle>$shuffle</shuffle>
|
|
<stream_once>0</stream_once>
|
|
<reconnect_attempts>-1</reconnect_attempts>
|
|
<svrinfoname>SecuBox Radio</svrinfoname>
|
|
<svrinfourl>https://secubox.in</svrinfourl>
|
|
<svrinfogenre>Various</svrinfogenre>
|
|
<svrinfodescription>SecuBox Community Radio</svrinfodescription>
|
|
<svrinfobitrate>$bitrate</svrinfobitrate>
|
|
<svrinfochannels>$channels</svrinfochannels>
|
|
<svrinfosamplerate>$samplerate</svrinfosamplerate>
|
|
<svrinfopublic>0</svrinfopublic>
|
|
</ezstream>
|
|
EOF
|
|
}
|
|
|
|
generate_darkice_config() {
|
|
local port=$(uci_get main.port 8000)
|
|
local source_pass=$(uci_get main.source_password "hackme")
|
|
local device=$(uci_get live.device "default")
|
|
local bitrate=$(uci_get live.bitrate 192)
|
|
local samplerate=$(uci_get stream.samplerate 44100)
|
|
local channels=$(uci_get stream.channels 2)
|
|
|
|
cat > "$DARKICE_CFG" <<EOF
|
|
[general]
|
|
duration = 0
|
|
bufferSecs = 5
|
|
reconnect = yes
|
|
|
|
[input]
|
|
device = $device
|
|
sampleRate = $samplerate
|
|
bitsPerSample = 16
|
|
channel = $channels
|
|
|
|
[icecast2-0]
|
|
bitrateMode = cbr
|
|
format = mp3
|
|
bitrate = $bitrate
|
|
server = localhost
|
|
port = $port
|
|
password = $source_pass
|
|
mountPoint = live
|
|
name = SecuBox Radio - Live
|
|
description = Live broadcast
|
|
genre = Live
|
|
public = no
|
|
EOF
|
|
}
|
|
|
|
#--- Playlist Management ---
|
|
cmd_playlist() {
|
|
case "$1" in
|
|
generate)
|
|
cmd_playlist_generate
|
|
;;
|
|
list)
|
|
cmd_playlist_list
|
|
;;
|
|
add)
|
|
shift
|
|
cmd_playlist_add "$@"
|
|
;;
|
|
*)
|
|
cmd_playlist_list
|
|
;;
|
|
esac
|
|
}
|
|
|
|
cmd_playlist_generate() {
|
|
log "Generating playlist..."
|
|
mkdir -p "$MUSIC_DIR"
|
|
|
|
local shuffle=$(uci_get playlist.shuffle 1)
|
|
local jingle_interval=$(uci_get playlist.jingle_interval 4)
|
|
local jingle_dir=$(uci_get playlist.jingle_directory "$JINGLE_DIR")
|
|
|
|
# Find all audio files
|
|
find "$MUSIC_DIR" -type f \( -name "*.mp3" -o -name "*.ogg" -o -name "*.flac" \) > /tmp/music_files.txt
|
|
|
|
# Shuffle if enabled (using awk for BusyBox compatibility)
|
|
if [ "$shuffle" = "1" ]; then
|
|
awk 'BEGIN{srand()} {print rand()"\t"$0}' /tmp/music_files.txt | sort -n | cut -f2- > /tmp/music_shuffled.txt
|
|
mv /tmp/music_shuffled.txt /tmp/music_files.txt
|
|
fi
|
|
|
|
# Generate playlist with jingles
|
|
rm -f "$PLAYLIST_FILE"
|
|
local count=0
|
|
while read -r file; do
|
|
echo "$file" >> "$PLAYLIST_FILE"
|
|
count=$((count + 1))
|
|
|
|
# Insert jingle every N tracks
|
|
if [ "$jingle_interval" -gt 0 ] && [ $((count % jingle_interval)) -eq 0 ]; then
|
|
local jingle=$(find "$jingle_dir" -type f -name "*.mp3" 2>/dev/null | sort -R | head -1)
|
|
[ -n "$jingle" ] && echo "$jingle" >> "$PLAYLIST_FILE"
|
|
fi
|
|
done < /tmp/music_files.txt
|
|
|
|
rm -f /tmp/music_files.txt
|
|
|
|
local total=$(wc -l < "$PLAYLIST_FILE" 2>/dev/null || echo 0)
|
|
log "Playlist generated: $total tracks"
|
|
}
|
|
|
|
cmd_playlist_list() {
|
|
echo -e "${CYAN}=== Playlist ===${NC}"
|
|
if [ -f "$PLAYLIST_FILE" ]; then
|
|
awk '{print NR": "$0}' "$PLAYLIST_FILE" | head -20
|
|
local total=$(wc -l < "$PLAYLIST_FILE")
|
|
echo "..."
|
|
echo "Total: $total tracks"
|
|
else
|
|
warn "No playlist generated. Run: webradioctl playlist generate"
|
|
fi
|
|
}
|
|
|
|
cmd_playlist_add() {
|
|
local file="$1"
|
|
if [ -f "$file" ]; then
|
|
cp "$file" "$MUSIC_DIR/"
|
|
log "Added: $(basename "$file")"
|
|
else
|
|
error "File not found: $file"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
#--- Stream Mode (FFmpeg) ---
|
|
cmd_stream() {
|
|
case "$1" in
|
|
start)
|
|
cmd_stream_start
|
|
;;
|
|
stop)
|
|
cmd_stream_stop
|
|
;;
|
|
*)
|
|
cmd_stream_status
|
|
;;
|
|
esac
|
|
}
|
|
|
|
cmd_stream_start() {
|
|
if pgrep -f "ffmpeg.*icecast" >/dev/null 2>&1; then
|
|
warn "Stream already running"
|
|
return 0
|
|
fi
|
|
|
|
# Ensure playlist exists
|
|
if [ ! -f "$PLAYLIST_FILE" ] || [ ! -s "$PLAYLIST_FILE" ]; then
|
|
cmd_playlist_generate
|
|
fi
|
|
|
|
if [ ! -s "$PLAYLIST_FILE" ]; then
|
|
error "No music files found in $MUSIC_DIR"
|
|
return 1
|
|
fi
|
|
|
|
local port=$(uci_get main.port 8000)
|
|
local source_pass=$(uci_get main.source_password "hackme")
|
|
local bitrate=$(uci_get stream.bitrate 128)
|
|
local name=$(uci_get main.name "SecuBox Radio")
|
|
|
|
log "Starting stream to icecast..."
|
|
|
|
# Create a loop script for continuous streaming
|
|
cat > /tmp/webradio_stream.sh << 'STREAMEOF'
|
|
#!/bin/sh
|
|
PLAYLIST="$1"
|
|
PORT="$2"
|
|
PASS="$3"
|
|
BITRATE="$4"
|
|
NAME="$5"
|
|
|
|
while true; do
|
|
while read -r file; do
|
|
[ -f "$file" ] || continue
|
|
ffmpeg -re -i "$file" \
|
|
-vn -acodec libmp3lame -ab ${BITRATE}k -ar 44100 -ac 2 \
|
|
-content_type audio/mpeg \
|
|
-f mp3 "icecast://source:${PASS}@127.0.0.1:${PORT}/stream" \
|
|
2>/var/log/webradio/ffmpeg.log
|
|
done < "$PLAYLIST"
|
|
# Re-shuffle for next loop (BusyBox compatible)
|
|
awk 'BEGIN{srand()} {print rand()"\t"$0}' "$PLAYLIST" | sort -n | cut -f2- > "${PLAYLIST}.tmp" && mv "${PLAYLIST}.tmp" "$PLAYLIST"
|
|
done
|
|
STREAMEOF
|
|
chmod +x /tmp/webradio_stream.sh
|
|
|
|
nohup /tmp/webradio_stream.sh "$PLAYLIST_FILE" "$port" "$source_pass" "$bitrate" "$name" \
|
|
>/dev/null 2>&1 &
|
|
|
|
sleep 3
|
|
if pgrep -f "webradio_stream.sh" >/dev/null 2>&1 || pgrep -f "ffmpeg" >/dev/null 2>&1; then
|
|
log "Stream started on http://127.0.0.1:$port/stream"
|
|
else
|
|
error "Failed to start stream - check /var/log/webradio/ffmpeg.log"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
cmd_stream_status() {
|
|
local port=$(uci_get main.port 8000)
|
|
if pgrep -f "webradio_stream.sh" >/dev/null 2>&1 || pgrep -f "ffmpeg" >/dev/null 2>&1; then
|
|
echo -e "FFmpeg Stream: ${GREEN}Running${NC}"
|
|
echo "URL: http://127.0.0.1:$port/stream"
|
|
# Get current listener count
|
|
local listeners=$(curl -s "http://127.0.0.1:$port/status-json.xsl" 2>/dev/null | jsonfilter -e '@.icestats.source.listeners' 2>/dev/null || echo "0")
|
|
echo "Listeners: $listeners"
|
|
else
|
|
echo -e "FFmpeg Stream: ${YELLOW}Stopped${NC}"
|
|
fi
|
|
}
|
|
|
|
cmd_stream_stop() {
|
|
log "Stopping stream..."
|
|
pkill -f "webradio_stream.sh" 2>/dev/null || true
|
|
pkill -f "ffmpeg.*icecast" 2>/dev/null || true
|
|
log "Stream stopped"
|
|
}
|
|
|
|
#--- Live Mode ---
|
|
cmd_live() {
|
|
case "$1" in
|
|
start)
|
|
cmd_live_start
|
|
;;
|
|
stop)
|
|
cmd_live_stop
|
|
;;
|
|
status)
|
|
cmd_live_status
|
|
;;
|
|
devices)
|
|
cmd_live_devices
|
|
;;
|
|
*)
|
|
cmd_live_status
|
|
;;
|
|
esac
|
|
}
|
|
|
|
cmd_live_start() {
|
|
if pgrep -f "darkice" >/dev/null 2>&1; then
|
|
warn "DarkIce already running"
|
|
return 0
|
|
fi
|
|
|
|
if [ ! -f "$DARKICE_CFG" ]; then
|
|
cmd_genconfig
|
|
fi
|
|
|
|
log "Starting live broadcast..."
|
|
darkice -c "$DARKICE_CFG" &
|
|
sleep 1
|
|
|
|
if pgrep -f "darkice" >/dev/null 2>&1; then
|
|
log "Live broadcast started on /live"
|
|
else
|
|
error "Failed to start DarkIce"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
cmd_live_stop() {
|
|
log "Stopping live broadcast..."
|
|
pkill -f "darkice" 2>/dev/null || true
|
|
log "Live broadcast stopped"
|
|
}
|
|
|
|
cmd_live_status() {
|
|
if pgrep -f "darkice" >/dev/null 2>&1; then
|
|
echo -e "DarkIce: ${GREEN}Running${NC}"
|
|
local device=$(uci_get live.device "default")
|
|
echo "Device: $device"
|
|
else
|
|
echo -e "DarkIce: ${YELLOW}Stopped${NC}"
|
|
fi
|
|
}
|
|
|
|
cmd_live_devices() {
|
|
echo -e "${CYAN}=== Audio Devices ===${NC}"
|
|
if command -v arecord >/dev/null 2>&1; then
|
|
arecord -l 2>/dev/null || echo "No capture devices found"
|
|
else
|
|
echo "alsa-utils not installed"
|
|
fi
|
|
}
|
|
|
|
#--- Exposure (Punk Model) ---
|
|
cmd_expose() {
|
|
local domain="$1"
|
|
local channel="${2:-dns}" # dns, tor, mesh, all
|
|
|
|
if [ -z "$domain" ]; then
|
|
error "Usage: webradioctl expose <domain> [dns|tor|mesh|all]"
|
|
return 1
|
|
fi
|
|
|
|
local port=$(uci_get main.port 8000)
|
|
|
|
log "Exposing WebRadio on $domain (channel: $channel)..."
|
|
|
|
case "$channel" in
|
|
dns|all)
|
|
# Create HAProxy vhost
|
|
if command -v haproxyctl >/dev/null 2>&1; then
|
|
# Create backend
|
|
haproxyctl backend add webradio_stream 127.0.0.1 "$port" 2>/dev/null || true
|
|
# Create vhost
|
|
haproxyctl vhost add "$domain" webradio_stream
|
|
haproxyctl reload
|
|
log "DNS exposure: https://$domain/"
|
|
else
|
|
error "haproxyctl not available"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
case "$channel" in
|
|
tor|all)
|
|
# Add Tor hidden service
|
|
if command -v torctl >/dev/null 2>&1; then
|
|
torctl hidden-service add webradio "$port"
|
|
local onion=$(torctl hidden-service get webradio 2>/dev/null)
|
|
[ -n "$onion" ] && log "Tor exposure: http://$onion/"
|
|
else
|
|
warn "torctl not available - skipping Tor"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
case "$channel" in
|
|
mesh|all)
|
|
# Publish to mesh
|
|
if command -v vortexctl >/dev/null 2>&1; then
|
|
vortexctl mesh publish webradio "$domain" "$port"
|
|
log "Mesh exposure: Published to P2P network"
|
|
else
|
|
warn "vortexctl not available - skipping Mesh"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# Save exposure config
|
|
uci set webradio.exposure.domain="$domain"
|
|
[ "$channel" = "tor" ] || [ "$channel" = "all" ] && uci set webradio.exposure.tor='1'
|
|
[ "$channel" = "mesh" ] || [ "$channel" = "all" ] && uci set webradio.exposure.mesh='1'
|
|
uci commit webradio
|
|
|
|
log "Exposure complete!"
|
|
}
|
|
|
|
cmd_unexpose() {
|
|
local domain=$(uci_get exposure.domain "")
|
|
|
|
if [ -z "$domain" ]; then
|
|
warn "No exposure configured"
|
|
return 0
|
|
fi
|
|
|
|
log "Removing exposure for $domain..."
|
|
|
|
# Remove HAProxy vhost
|
|
if command -v haproxyctl >/dev/null 2>&1; then
|
|
haproxyctl vhost del "$domain" 2>/dev/null || true
|
|
haproxyctl reload
|
|
fi
|
|
|
|
# Remove Tor hidden service
|
|
if command -v torctl >/dev/null 2>&1; then
|
|
torctl hidden-service del webradio 2>/dev/null || true
|
|
fi
|
|
|
|
# Remove from mesh
|
|
if command -v vortexctl >/dev/null 2>&1; then
|
|
vortexctl mesh unpublish webradio 2>/dev/null || true
|
|
fi
|
|
|
|
# Clear config
|
|
uci set webradio.exposure.domain=''
|
|
uci set webradio.exposure.tor='0'
|
|
uci set webradio.exposure.mesh='0'
|
|
uci commit webradio
|
|
|
|
log "Exposure removed"
|
|
}
|
|
|
|
#--- Service Control ---
|
|
cmd_start() {
|
|
/etc/init.d/webradio start
|
|
}
|
|
|
|
cmd_stop() {
|
|
/etc/init.d/webradio stop
|
|
}
|
|
|
|
cmd_restart() {
|
|
/etc/init.d/webradio restart
|
|
}
|
|
|
|
cmd_enable() {
|
|
uci set webradio.main.enabled='1'
|
|
uci commit webradio
|
|
/etc/init.d/webradio enable
|
|
log "WebRadio enabled"
|
|
}
|
|
|
|
cmd_disable() {
|
|
uci set webradio.main.enabled='0'
|
|
uci commit webradio
|
|
/etc/init.d/webradio disable
|
|
log "WebRadio disabled"
|
|
}
|
|
|
|
#--- Skip Track ---
|
|
cmd_skip() {
|
|
if pgrep -f "ezstream" >/dev/null 2>&1; then
|
|
pkill -USR1 -f "ezstream"
|
|
log "Skipped to next track"
|
|
else
|
|
warn "Ezstream not running"
|
|
fi
|
|
}
|
|
|
|
#--- Help ---
|
|
cmd_help() {
|
|
cat <<EOF
|
|
${CYAN}WebRadio Controller - SecuBox Backend CLI${NC}
|
|
|
|
Usage: webradioctl <command> [options]
|
|
|
|
${GREEN}Service Commands:${NC}
|
|
status Show service status
|
|
start Start WebRadio services
|
|
stop Stop WebRadio services
|
|
restart Restart services
|
|
enable Enable autostart
|
|
disable Disable autostart
|
|
|
|
${GREEN}Configuration:${NC}
|
|
genconfig Generate Icecast/Ezstream/DarkIce configs
|
|
|
|
${GREEN}Playlist:${NC}
|
|
playlist List current playlist
|
|
playlist generate Regenerate playlist from music directory
|
|
playlist add <file> Add file to music directory
|
|
|
|
${GREEN}Streaming:${NC}
|
|
stream Show stream status
|
|
stream start Start FFmpeg stream to Icecast
|
|
stream stop Stop streaming
|
|
skip Skip to next track
|
|
|
|
${GREEN}Live Broadcast:${NC}
|
|
live Show live status
|
|
live start Start DarkIce live input
|
|
live stop Stop live broadcast
|
|
live devices List audio capture devices
|
|
|
|
${GREEN}Exposure (Punk Model):${NC}
|
|
expose <domain> [channel] Expose radio (dns|tor|mesh|all)
|
|
unexpose Remove all exposure
|
|
|
|
${GREEN}Examples:${NC}
|
|
webradioctl enable
|
|
webradioctl playlist generate
|
|
webradioctl stream start
|
|
webradioctl expose radio.secubox.in dns
|
|
webradioctl expose radio.secubox.in all
|
|
|
|
EOF
|
|
}
|
|
|
|
#--- Main ---
|
|
case "$1" in
|
|
status) cmd_status ;;
|
|
start) cmd_start ;;
|
|
stop) cmd_stop ;;
|
|
restart) cmd_restart ;;
|
|
enable) cmd_enable ;;
|
|
disable) cmd_disable ;;
|
|
genconfig) cmd_genconfig ;;
|
|
playlist) shift; cmd_playlist "$@" ;;
|
|
stream) shift; cmd_stream "$@" ;;
|
|
skip) cmd_skip ;;
|
|
live) shift; cmd_live "$@" ;;
|
|
expose) shift; cmd_expose "$@" ;;
|
|
unexpose) cmd_unexpose ;;
|
|
help|--help|-h|"")
|
|
cmd_help
|
|
;;
|
|
*)
|
|
error "Unknown command: $1"
|
|
cmd_help
|
|
exit 1
|
|
;;
|
|
esac
|