mirror of
https://github.com/mistergibson/radio.git
synced 2026-09-08 22:09:51 -07:00
testing
This commit is contained in:
parent
57aa2aa1c9
commit
11e1292a75
3 changed files with 55 additions and 52 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,6 +1,6 @@
|
|||
# Secrets and local configuration
|
||||
config.json
|
||||
|
||||
dirs.txt
|
||||
# Runtime data (should live under the storage path, not here)
|
||||
.venv/
|
||||
state/
|
||||
|
|
|
|||
12
check_dirs.sh
Executable file
12
check_dirs.sh
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
STORAGE="/mnt/storage/radio"
|
||||
JINGLES="no"
|
||||
ANNOUNCEMENTS="no"
|
||||
if find "$STORAGE/jingles" -type f \( -name "*.mp3" -o -name "*.m4a" \) 2>/dev/null | grep -q .; then
|
||||
JINGLES="yes"
|
||||
fi
|
||||
if find "$STORAGE/announcements" -type f \( -name "*.mp3" -o -name "*.m4a" \) 2>/dev/null | grep -q .; then
|
||||
ANNOUNCEMENTS="yes"
|
||||
fi
|
||||
echo "jingles=$JINGLES" > /srv/radio/dirs.txt
|
||||
echo "announcements=$ANNOUNCEMENTS" >> /srv/radio/dirs.txt
|
||||
93
station.liq
93
station.liq
|
|
@ -2,18 +2,20 @@
|
|||
|
||||
# ---------------------------------------------------------------
|
||||
# station.liq - Liquidsoap configuration for radio automation
|
||||
# Auto-detects its own location so all paths are relative.
|
||||
# Music/jingles/announcements live under the storage path from
|
||||
# config.json; code stays in the install dir.
|
||||
# Written for Liquidsoap 2.2.x. Run from /srv/radio so that the
|
||||
# relative config.json path resolves correctly; media lives under
|
||||
# the storage path read from that file. Directory playlists scan
|
||||
# recursively for audio files automatically.
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
configure.bindir()
|
||||
|
||||
set("log.stdout", true)
|
||||
set("log.level", 3)
|
||||
|
||||
# --- Load Icecast credentials + storage path from config.json ---
|
||||
let cfg : {
|
||||
# --- Step 1: path to config.json (relative to working directory) ---
|
||||
let config_path = "config.json"
|
||||
|
||||
# --- Step 2: read and parse the whole file with explicit types --
|
||||
let json.parse (cfg : {
|
||||
storage: string,
|
||||
icecast: {
|
||||
host: string,
|
||||
|
|
@ -21,82 +23,71 @@ let cfg : {
|
|||
mount: string,
|
||||
username: string,
|
||||
password: string
|
||||
},
|
||||
gpodder: {
|
||||
enable: bool,
|
||||
host: string,
|
||||
username: string,
|
||||
password: string
|
||||
}
|
||||
} = json.parse(file.contents("#{bindir()}/config.json"))
|
||||
}) = file.contents(config_path)
|
||||
|
||||
# --- Step 3: pull out the values we need ------------------------
|
||||
let storage = cfg.storage
|
||||
let ic_host = cfg.icecast.host
|
||||
let ic_port = cfg.icecast.port
|
||||
let ic_mount = cfg.icecast.mount
|
||||
let ic_username = cfg.icecast.username
|
||||
let ic_password = cfg.icecast.password
|
||||
let storage = cfg.storage
|
||||
|
||||
set("log.file.path", "#{storage}/logs/liquidsoap.log")
|
||||
|
||||
# --- Background music library (recursive scan for mp3/m4a) ---
|
||||
# --- Background music library (directory scanned recursively) --
|
||||
music_playlist =
|
||||
request.cue(
|
||||
playlist(
|
||||
recurse=true,
|
||||
pattern="\\.(mp3|m4a)$",
|
||||
"#{storage}/music"
|
||||
)
|
||||
)
|
||||
playlist("#{storage}/music")
|
||||
|
||||
# --- Scheduled content: request queue fed by schedule.txt ---
|
||||
# --- Scheduled content: request queue fed by schedule.txt ------
|
||||
sched_queue = request.queue(id="scheduler")
|
||||
|
||||
# --- Jingles / announcements (optional) ---
|
||||
jingle_dir = "#{storage}/jingles"
|
||||
announce_dir = "#{storage}/announcements"
|
||||
|
||||
# --- Helper: check if a directory contains any audio files -----
|
||||
def has_audio(dir) =
|
||||
try
|
||||
let l = list.filter(fun(f) -> regexp("\\.(mp3|m4a)$").test(f), ls.dir(dir))
|
||||
list.length(l) > 0
|
||||
let entries = file.ls(dir)
|
||||
let audio_count = list.length(
|
||||
list.filter(fun(f) -> regexp("\\.(mp3|m4a)$").test(f), entries)
|
||||
)
|
||||
audio_count > 0
|
||||
catch _ do
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
jingles_src =
|
||||
if has_audio(jingle_dir) then
|
||||
mksafe(request.cue(playlist(recurse=true, pattern="\\.(mp3|m4a)$", jingle_dir)))
|
||||
else
|
||||
null()
|
||||
end
|
||||
# --- Jingles / announcements (only active if they have content) ---
|
||||
jingles_active = has_audio("#{storage}/jingles")
|
||||
announcements_active = has_audio("#{storage}/announcements")
|
||||
|
||||
announcements_src =
|
||||
if has_audio(announce_dir) then
|
||||
mksafe(request.cue(playlist(recurse=true, pattern="\\.(mp3|m4a)$", announce_dir)))
|
||||
else
|
||||
null()
|
||||
end
|
||||
log("#[info] Jingles directory has audio: #{string(jingles_active)}")
|
||||
log("#[info] Announcements directory has audio: #{string(announcements_active)}")
|
||||
|
||||
# --- Assemble the stream ---
|
||||
# --- Assemble the stream ---------------------------------------
|
||||
primary = fallback(track_sensitive=false, [sched_queue, music_playlist])
|
||||
|
||||
content =
|
||||
match jingles_src with
|
||||
| null() => primary
|
||||
| src => random(weights=[1, 8], [src, primary])
|
||||
if jingles_active then
|
||||
random(weights=[1, 8], [
|
||||
mksafe(playlist("#{storage}/jingles")),
|
||||
primary
|
||||
])
|
||||
else
|
||||
primary
|
||||
end
|
||||
|
||||
final_content =
|
||||
match announcements_src with
|
||||
| null() => content
|
||||
| src => fallback(track_sensitive=false, [src, content])
|
||||
if announcements_active then
|
||||
fallback(track_sensitive=false, [
|
||||
mksafe(playlist("#{storage}/announcements")),
|
||||
content
|
||||
])
|
||||
else
|
||||
content
|
||||
end
|
||||
|
||||
radio = normalize(final_content)
|
||||
|
||||
# --- Output to Icecast ---
|
||||
# --- Output to Icecast -----------------------------------------
|
||||
output.icecast(
|
||||
%mp3(bitrate=128, samplerate=44100, stereo=true),
|
||||
host=ic_host,
|
||||
|
|
|
|||
Loading…
Reference in a new issue