1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
log.stdout.set(true)
# use yt-dlp
settings.protocol.youtube_dl.path.set("yt-dlp")
## functions
def stringify_attrs(attrs) =
let json.stringify out = (attrs : [(string * string)] as json.object)
out
end
def filter_graveyard(req) =
filename = request.filename(req)
if string.match(pattern = '.*/\\.graveyard/.*', filename) then
false
else
true
end
end
def queue_contents(q) =
list.map(fun (req) -> request.uri(req), q)
end
## main
env = environment()
port = string.to_int(env["RADIO_PORT"], default = 8000)
all_music = playlist(env["MUSIC"], check_next = filter_graveyard)
wishlist = request.queue()
tracks = fallback(track_sensitive = true, [wishlist, all_music])
last_metadata = ref([])
def on_metadata(m) =
last_metadata := m
print("changing tracks")
out = process.read(env["HOOK_TRACK_CHANGE"], env = m)
print(out)
end
tracks.on_metadata(on_metadata)
# some nice effects
music = crossfade(tracks)
music = mksafe(music)
music = normalize(music)
news = request.queue()
radio = smooth_add(normal = music, special = amplify(1.5, news))
if string.length(env["ICECAST_HOST"]) > 0 then
output.icecast(host = env["ICECAST_HOST"], mount = '/music.ogg', password = 'hackme', %vorbis(quality = 1), music)
output.icecast(host = env["ICECAST_HOST"], mount = '/music.mp3', password = 'hackme', %mp3.vbr(), music)
output.icecast(host = env["ICECAST_HOST"], mount = '/music.opus', password = 'hackme', %opus(bitrate = 128), music)
output.icecast(host = env["ICECAST_HOST"], mount = '/radio.ogg', password = 'hackme', %vorbis(quality = 1), radio)
output.icecast(host = env["ICECAST_HOST"], mount = '/radio.mp3', password = 'hackme', %mp3.vbr(), radio)
output.icecast(host = env["ICECAST_HOST"], mount = '/radio.opus', password = 'hackme', %opus(bitrate = 128), radio)
else
output(fallible = true, buffer(radio))
end
interactive.harbor(port = port)
def current(~protocol, ~headers, ~data, uri) =
http.response(content_type = "application/json", data = stringify_attrs(
!last_metadata
))
end
harbor.http.register("/current", port = port, current)
def skip(~protocol, ~headers, ~data, uri) =
tracks.skip()
http.response(content_type = "application/json", data = stringify_attrs(
!last_metadata
))
end
harbor.http.register("/skip", method = "POST", port = port, skip)
def all_tracks(~protocol, ~headers, ~data, uri) =
http.response(content_type = "application/json", data = json.stringify(
all_music.remaining_files()
))
end
harbor.http.register("/all_tracks", port = port, all_tracks)
def wish_track(~protocol, ~headers, ~data, uri) =
# disallow process:
if string.match(pattern = '^process:', data) then
http.response(code = 400)
else
# TODO report errors back
wish = request.create(data)
wishlist.push(wish)
http.response(content_type = "application/json", data = "ok")
end
end
harbor.http.register("/wish", method = "POST", port = port, wish_track)
def wish_tracklist(~protocol, ~headers, ~data, uri) =
http.response(content_type = "application/json", data = json.stringify(
queue_contents(wishlist.queue())
))
end
harbor.http.register("/wish", port = port, wish_tracklist)
def newsshow(~protocol, ~headers, ~data, uri) =
news.push(request.create("http://c.r/news.ogg"))
http.response(content_type = "application/json", data = "ok")
end
harbor.http.register("/newsshow", method = "POST", port = port, newsshow)
|