diff --git a/server.ls b/server.ls new file mode 100644 index 0000000..bdb098d --- /dev/null +++ b/server.ls @@ -0,0 +1,324 @@ +#!/usr/bin/liquidsoap +set("log.file.path", "/tmp/lsl.txt") +set("log.stdout", true) +set("harbor.bind_addrs", ["127.0.0.1"]) + + +# Get next track dynamically [Each station] + +def get_next_main() = + uri = list.hd(default="", process.read.lines("uv run get_next_track.py main")) + [request.create(uri)] +end + +def get_next_rock() = + uri = list.hd(default="", process.read.lines("uv run get_next_track.py rock")) + [request.create(uri)] +end + +def get_next_electronic() = + uri = list.hd(default="", process.read.lines("uv run get_next_track.py electronic")) + [request.create(uri)] +end + +def get_next_rap() = + uri = list.hd(default="", process.read.lines("uv run get_next_track.py rap")) + [request.create(uri)] +end + +def get_next_classical() = + uri = list.hd(default="", process.read.lines("uv run get_next_track.py classical")) + [request.create(uri)] +end + +def get_next_pop() = + uri = list.hd(default="", process.read.lines("uv run get_next_track.py pop")) + [request.create(uri)] +end + + +# Set up queues [Each station] + +main_list = request.dynamic.list( + id="requests", + get_next_main, + prefetch=0 +) + + +rock_list = request.dynamic.list( + id="rock_requests", + get_next_rock, + prefetch=0 +) + +electronic_list = request.dynamic.list( + id="electronic_requests", + get_next_electronic, + prefetch=0 +) + +rap_list = request.dynamic.list( + id="rap_requests", + get_next_rap, + prefetch=0 +) + +classical_list = request.dynamic.list( + id="classical_requests", + get_next_classical, + prefetch=0 +) + +pop_list = request.dynamic.list( + id="pop_requests", + get_next_pop, + prefetch=0 +) + + +# Standard + +silence = single("/home/kyle/ls/silence.ogg") + +# Queue [Each station] + +def main_queue(remaining, _) = + log("MAIN: Queueing with #{remaining} seconds remaining") + if not main_list.fetch() then + log("Fetching next query failed") + end +end + +def rock_queue(remaining, _) = + log("ROCK: Queueing with #{remaining} seconds remaining") + if not rock_list.fetch() then + log("Fetching next query failed") + end +end + +def electronic_queue(remaining, _) = + log("ELECTRONIC: Queueing with #{remaining} seconds remaining") + if not electronic_list.fetch() then + log("Fetching next query failed") + end +end + +def rap_queue(remaining, _) = + log("RAP: Queueing with #{remaining} seconds remaining") + if not rap_list.fetch() then + log("Fetching next query failed") + end +end + +def classical_queue(remaining, _) = + log("CLASSICAL: Queueing with #{remaining} seconds remaining") + if not classical_list.fetch() then + log("Fetching next query failed") + end +end + +def pop_queue(remaining, _) = + log("POP: Queueing with #{remaining} seconds remaining") + if not pop_list.fetch() then + log("Fetching next query failed") + end +end + + + +# Initial fetch [Each station] + +main_list.fetch() +rock_list.fetch() +electronic_list.fetch() +rap_list.fetch() +classical_list.fetch() +pop_list.fetch() + +# Source setup [Each station] + +main_source = source.on_end(delay=1.0, main_list, main_queue) +rock_source = source.on_end(delay=1.0, rock_list, rock_queue) +electronic_source = source.on_end(delay=1.0, electronic_list, electronic_queue) +rap_source = source.on_end(delay=1.0, rap_list, rap_queue) +classical_source = source.on_end(delay=1.0, classical_list, classical_queue) +pop_source = source.on_end(delay=1.0, pop_list, pop_queue) + +all_tracks_main = fallback(track_sensitive=false, [main_source, silence]) +all_tracks_rock = fallback(track_sensitive=false, [rock_source, silence]) +all_tracks_electronic = fallback(track_sensitive=false, [electronic_source, silence]) +all_tracks_rap = fallback(track_sensitive=false, [rap_source, silence]) +all_tracks_classical = fallback(track_sensitive=false, [classical_source, silence]) +all_tracks_pop = fallback(track_sensitive=false, [pop_source, silence]) + +# HLS Setup [Standard] + +aac_lofi = + %ffmpeg(format = "mpegts", %audio(codec = "aac", channels = 2, ar = 44100)) + +aac_midfi = + %ffmpeg( + format = "mpegts", + %audio(codec = "aac", channels = 2, ar = 44100, b = "96k") + ) + +aac_hifi = + %ffmpeg( + format = "mpegts", + %audio(codec = "aac", channels = 2, ar = 44100, b = "192k") + ) + +streams = + [("aac_lofi", aac_lofi), ("aac_midfi", aac_midfi), ("aac_hifi", aac_hifi)] + + +# HLS Outputs [Each station] + +output.file.hls( + playlist="main.m3u8", + segment_duration=1.0, + segments=3, + segments_overhead=4, + persist_at="/tmp/hls/state.config", + "/tmp/hls/main", + streams, + mksafe(main_source) +) + +output.file.hls( + playlist="rock.m3u8", + segment_duration=1.0, + segments=3, + segments_overhead=4, + persist_at="/tmp/hls/rock/state.config", + "/tmp/hls/rock", + streams, + mksafe(rock_source) +) + +output.file.hls( + playlist="electronic.m3u8", + segment_duration=1.0, + segments=3, + segments_overhead=4, + persist_at="/tmp/hls/electronic/state.config", + "/tmp/hls/electronic", + streams, + mksafe(electronic_source) +) + +output.file.hls( + playlist="rap.m3u8", + segment_duration=1.0, + segments=3, + segments_overhead=4, + persist_at="/tmp/hls/rap_state.config", + "/tmp/hls/rap", + streams, + mksafe(rap_source) +) + +output.file.hls( + playlist="classical.m3u8", + segment_duration=1.0, + segments=3, + segments_overhead=4, + persist_at="/tmp/hls/classical_state.config", + "/tmp/hls/classical", + streams, + mksafe(classical_source) +) + +output.file.hls( + playlist="pop.m3u8", + segment_duration=1.0, + segments=3, + segments_overhead=4, + persist_at="/tmp/hls/pop_state.config", + "/tmp/hls/pop", + streams, + mksafe(pop_source) +) + + +def get_next_http(~protocol,~data,~headers,uri) = + log("Station from POST Data: #{data}") + if data == "main" then + _req = source.skip(all_tracks_main) + elsif data == "rock" then + _req = source.skip(all_tracks_rock) + elsif data == "electronic" then + _req = source.skip(all_tracks_electronic) + elsif data == "rap" then + _req = source.skip(all_tracks_rap) + elsif data == "classical" then + _req = source.skip(all_tracks_classical) + elsif data == "pop" then + _req = source.skip(all_tracks_pop) + end + http.response( + protocol=protocol, + code=200, + data="OK #{data}" + ) +end + +harbor.http.register(port=29000, method="POST", "/next", get_next_http) + +# Icecast Outputs [Each station] + +output.icecast( + %ogg(%vorbis(quality=1.0, samplerate=44100)), + host="localhost", port=9992, + user="redacted", password="redacted", + mount="sfm.ogg", + fallible=false, + all_tracks_main +) + +output.icecast( + %ogg(%vorbis(quality=1.0, samplerate=44100)), + host="localhost", port=9992, + user="redacted", password="redacted", + mount="rock.ogg", + fallible=false, + all_tracks_rock +) + +output.icecast( + %ogg(%vorbis(quality=1.0, samplerate=44100)), + host="localhost", port=9992, + user="redacted", password="redacted", + mount="electronic.ogg", + fallible=false, + all_tracks_electronic +) + + +output.icecast( + %ogg(%vorbis(quality=1.0, samplerate=44100)), + host="localhost", port=9992, + user="redacted", password="redacted", + mount="rap.ogg", + fallible=false, + all_tracks_rap +) + +output.icecast( + %ogg(%vorbis(quality=1.0, samplerate=44100)), + host="localhost", port=9992, + user="redacted", password="redacted", + mount="classical.ogg", + fallible=false, + all_tracks_classical +) + +output.icecast( + %ogg(%vorbis(quality=1.0, samplerate=44100)), + host="localhost", port=9992, + user="redacted", password="redacted", + mount="pop.ogg", + fallible=false, + all_tracks_pop +)