Commit e77e1686 authored by David Trattnig's avatar David Trattnig
Browse files

Upgrade to Liquidsoap 1.4.1.

parent f9483b59
......@@ -71,23 +71,28 @@ git clone https://gitlab.servus.at/autoradio/engine
### Install System Libraries
Aura Engine requires at least `Node 13` and `Python 3.7`.
Aura Engine requires at least `Node 13`, `Python 3.7`. Then install `Liquidsoap 1.4.1` using [OPAM](https://www.liquidsoap.info/doc-1.4.1/install.html).
Having these installed you need to
```bash
sudo apt install \
git \
supervisor \
nodejs \
python3.7 python3.7-pip python3.7-dev \
redis-server \
libsndfile1 ffmpeg \
liquidsoap liquidsoap-plugin-icecast \
mariadb-server libmariadbclient-dev \
quelcom \
liquidsoap-plugin-alsa liquidsoap-plugin-pulseaudio \
liquidsoap-plugin-all
```
And finally
```bash
opam depext fdkaac flac opus pulseaudio bjack alsa
opam install fdkaac flac opus pulseaudio bjack alsa
```
### Install Engine
Development Environment
......
......@@ -78,6 +78,6 @@ output_source = fallback(id="fallback", track_sensitive=false, [stripped_stream,
# start initialization #
########################
system('#{list.assoc("install_dir", ini)}/guru.py --init-player --quiet')
system('#{list.assoc(default="", "install_dir", ini)}/guru.py --init-player --quiet')
......@@ -22,77 +22,165 @@
# along with engine. If not, see <http://www.gnu.org/licenses/>.
#
# Custom crossfade to deal with jingles.
def smart_crossfade (~start_next=5.,~fade_in=3.,~fade_out=3.,
~default=(fun (a,b) -> sequence([a, b])),
~high=-15., ~medium=-32., ~margin=4.,
~width=2.,~conservative=false,s)
# Crossfade between tracks,
# taking the respective volume levels
# into account in the choice of the
# transition.
# @category Source / Track Processing
# @param ~start_next Crossing duration, if any.
# @param ~fade_in Fade-in duration, if any.
# @param ~fade_out Fade-out duration, if any.
# @param ~width Width of the volume analysis window.
# @param ~conservative Always prepare for
# a premature end-of-track.
# @param s The input source.
def crossfade (~start_next=5.,~fade_in=3.,
~fade_out=3., ~width=2.,
~conservative=false,s)
high = -20.
medium = -32.
margin = 4.
fade.out = fade.out(type="sin",duration=fade_out)
fade.in = fade.in(type="sin",duration=fade_in)
add = fun (a,b) -> add(normalize=false,[b, a])
log = log(label="smart_crossfade")
add = fun (a,b) -> add(normalize=false,[b,a])
log = log(label="crossfade")
def transition(a,b,ma,mb,sa,sb)
list.iter(fun(x)-> log(level=4,"Before: #{x}"),ma)
list.iter(fun(x)-> log(level=4,"After : #{x}"),mb)
if ma["type"] == "jingles" or mb["type"] == "jingles" then
log("Old or new file is a jingle: sequenced transition.")
sequence([sa, sb])
elsif
# If A and B are not too loud and close, fully cross-fade them.
a <= medium and b <= medium and abs(a - b) <= margin
list.iter(fun(x)->
log(level=4,"Before: #{x}"),ma)
list.iter(fun(x)->
log(level=4,"After : #{x}"),mb)
if
# If A and B and not too loud and close,
# fully cross-fade them.
a <= medium and
b <= medium and
abs(a - b) <= margin
then
log("Old <= medium, new <= medium and |old-new| <= margin.")
log("Old and new source are not too loud and close.")
log("Transition: crossed, fade-in, fade-out.")
add(fade.out(sa),fade.in(sb))
elsif
# If B is significantly louder than A, only fade-out A.
# We don't want to fade almost silent things, ask for >medium.
# If B is significantly louder than A,
# only fade-out A.
# We don't want to fade almost silent things,
# ask for >medium.
b >= a + margin and a >= medium and b <= high
then
log("new >= old + margin, old >= medium and new <= high.")
log("New source is significantly louder than old one.")
log("Transition: crossed, fade-out.")
add(fade.out(sa),sb)
elsif
# Do not fade if it's already very low.
b >= a + margin and a <= medium and b <= high
then
log("Transition: crossed, no fade-out.")
add(sa,sb)
elsif
# Opposite as the previous one.
a >= b + margin and b >= medium and a <= high
then
log("old >= new + margin, new >= medium and old <= high")
log("Old source is significantly louder than new one.")
log("Transition: crossed, fade-in.")
add(sa,fade.in(sb))
elsif
# Do not fade if it's already very low.
b >= a + margin and a <= medium and b <= high
then
log("new >= old + margin, old <= medium and new <= high.")
log("Do not fade if it's already very low.")
log("Transition: crossed, no fade.")
add(sa,sb)
# What to do with a loud end and a quiet beginning ?
# A good idea is to use a jingle to separate the two tracks,
# but that's another story.
# What to do with a loud end and
# a quiet beginning ?
# A good idea is to use a jingle to separate
# the two tracks, but that's another story.
else
# Otherwise, A and B are just too loud to overlap nicely,
# or the difference between them is too large and overlapping would
# completely mask one of them.
log("No transition: using default.")
default(sa, sb)
# Otherwise, A and B are just too loud
# to overlap nicely, or the difference
# between them is too large and
# overlapping would completely mask one
# of them.
log("No transition: just sequencing.")
sequence([sa, sb])
end
end
smart_cross(width=width, duration=start_next, conservative=conservative, transition, s)
cross(width=width, duration=start_next,
conservative=conservative,
transition,s)
end
# Custom crossfade to deal with jingles.
# def smarter_crossfade (~start_next=5.,~fade_in=3.,~fade_out=3.,
# ~default=(fun (a,b) -> sequence([a, b])),
# ~high=-15., ~medium=-32., ~margin=4.,
# ~width=2.,~conservative=false,s)
# fade.out = fade.out(type="sin",duration=fade_out)
# fade.in = fade.in(type="sin",duration=fade_in)
# add = fun (a,b) -> add(normalize=false,[b, a])
# log = log(label="smarter_crossfade")
# def transition(a,b,ma,mb,sa,sb)
# list.iter(fun(x)-> log(level=4,"Before: #{x}"),ma)
# list.iter(fun(x)-> log(level=4,"After : #{x}"),mb)
# if ma["type"] == "jingles" or mb["type"] == "jingles" then
# log("Old or new file is a jingle: sequenced transition.")
# sequence([sa, sb])
# elsif
# # If A and B are not too loud and close, fully cross-fade them.
# a <= medium and b <= medium and abs(a - b) <= margin
# then
# log("Old <= medium, new <= medium and |old-new| <= margin.")
# log("Old and new source are not too loud and close.")
# log("Transition: crossed, fade-in, fade-out.")
# add(fade.out(sa),fade.in(sb))
# elsif
# # If B is significantly louder than A, only fade-out A.
# # We don't want to fade almost silent things, ask for >medium.
# b >= a + margin and a >= medium and b <= high
# then
# log("new >= old + margin, old >= medium and new <= high.")
# log("New source is significantly louder than old one.")
# log("Transition: crossed, fade-out.")
# add(fade.out(sa),sb)
# elsif
# # Opposite as the previous one.
# a >= b + margin and b >= medium and a <= high
# then
# log("old >= new + margin, new >= medium and old <= high")
# log("Old source is significantly louder than new one.")
# log("Transition: crossed, fade-in.")
# add(sa,fade.in(sb))
# elsif
# # Do not fade if it's already very low.
# b >= a + margin and a <= medium and b <= high
# then
# log("new >= old + margin, old <= medium and new <= high.")
# log("Do not fade if it's already very low.")
# log("Transition: crossed, no fade.")
# add(sa,sb)
# # What to do with a loud end and a quiet beginning ?
# # A good idea is to use a jingle to separate the two tracks,
# # but that's another story.
# else
# # Otherwise, A and B are just too loud to overlap nicely,
# # or the difference between them is too large and overlapping would
# # completely mask one of them.
# log("No transition: using default.")
# default(sa, sb)
# end
# end
# #smart_cross(width=width, duration=start_next, conservative=conservative, transition, s)
# smart_crossfade(duration=start_next, fade_in=fade_in, fade_out=fade_out, width=width, conservative=conservative, transition, s)
# end
# create a pool
def fallback_create(~skip=true, name, requestor)
log("Creating channel #{name}")
......@@ -113,7 +201,6 @@ def fallback_create(~skip=true, name, requestor)
source
end
# Tell the system when a new track is played
def do_meta(meta) =
filename = meta["filename"]
......@@ -127,11 +214,12 @@ def fallback_create(~skip=true, name, requestor)
log("channel created")
# Finally apply a smart crossfading
smart_crossfade(source)
#smarter_crossfade(source)
crossfade(source)
end
def create_dynamic_playlist(next)
request.create(list.hd(next))
request.create(list.hd(default="", next))
end
def create_playlist() =
......
......@@ -56,7 +56,7 @@ input_fs = request.equeue(id="fs")
def clear_items(s) =
ret = server.execute("fs.primary_queue")
ret = list.hd(ret)
ret = list.hd(default="", ret)
if ret == "" then
log("Queue cleared.")
(-1.)
......
......@@ -50,19 +50,19 @@ def stream_to_icecast(id, encoding, bitrate, host, port, pass, mount_point, url,
output_icecast_mono = output.icecast(id = id, host = host, port = port, password = pass, mount = mount_point, fallible = true, url = url, description = description, name = name, genre = genre, user = !user_ref, on_error = on_error, on_connect = on_connect)
output_icecast_stereo = output.icecast(id = id, host = host, port = port, password = pass, mount = mount_point, fallible = true, url = url, description = description, name = name, genre = genre, user = !user_ref, on_error = on_error, on_connect = on_connect)
%ifencoder %aac
if encoding == "aac" then
log("ENABLING AAC to ICECAST")
%include "outgoing_streams/aac.liq"
end
%endif
%ifencoder %flac
if encoding == "flac" then
log("ENABLING FLAC to ICECAST")
%include "outgoing_streams/flac.liq"
end
%endif
# %ifencoder %aac
# if encoding == "aac" then
# log("ENABLING AAC to ICECAST")
# %include "outgoing_streams/aac.liq"
# end
# %endif
#
# %ifencoder %flac
# if encoding == "flac" then
# log("ENABLING FLAC to ICECAST")
# %include "outgoing_streams/flac.liq"
# end
# %endif
if encoding == "mp3" then
log("ENABLING Mp3 to ICECAST")
......@@ -74,12 +74,12 @@ def stream_to_icecast(id, encoding, bitrate, host, port, pass, mount_point, url,
%include "outgoing_streams/ogg.liq"
end
%ifencoder %opus
if encoding == "opus" then
log("ENABLING OPUS to ICECAST")
%include "outgoing_streams/opus.liq"
end
%endif
# %ifencoder %opus
# if encoding == "opus" then
# log("ENABLING OPUS to ICECAST")
# %include "outgoing_streams/opus.liq"
# end
# %endif
end
###########
......@@ -149,11 +149,11 @@ def start_recorder(folder, duration, encoding, bitrate, channels, filenamepatter
recfile = ref ''
def on_start()
is_recording := true
recfile := list.hd(get_process_lines("date +#{filenamepattern}"))
recfile := list.hd(default="", get_process_lines("date +#{filenamepattern}"))
end
def on_close(filename)
is_recording := false
recfile := list.hd(get_process_lines("date +#{filenamepattern}"))
recfile := list.hd(default="", get_process_lines("date +#{filenamepattern}"))
end
def on_stop()
is_recording := false
......@@ -166,45 +166,45 @@ def start_recorder(folder, duration, encoding, bitrate, channels, filenamepatter
output_filesystem_mono = output.file(id="recorder_"^recorder_number, perm = 0o664, on_start=on_start, on_close=on_close, on_stop=on_stop, reopen_when={ int_of_float(gettimeofday()/60.) mod duration == 0 })
output_filesystem_stereo = output.file(id="recorder_"^recorder_number, perm = 0o664, on_start=on_start, on_close=on_close, on_stop=on_stop, reopen_when={ int_of_float(gettimeofday()/60.) mod duration == 0 })
%ifencoder %aac
# %ifencoder %aac
if encoding == "aac" then
log("ENABLING aac recorder to filesystem")
%include "outgoing_recordings/aac.liq"
end
%endif
# %endif
%ifencoder %flac
# %ifencoder %flac
if encoding == "flac" then
log("ENABLING flac recorder to filesystem")
%include "outgoing_recordings/flac.liq"
end
%endif
# %endif
%ifencoder %mp3
# %ifencoder %mp3
if encoding == "mp3" then
log("ENABLING mp3 recorder to filesystem")
%include "outgoing_recordings/mp3.liq"
end
%endif
# %endif
%ifencoder %vorbis
# %ifencoder %vorbis
if encoding == "ogg" then
log("ENABLING ogg recorder to filesystem")
%include "outgoing_recordings/ogg.liq"
end
%endif
# %endif
%ifencoder %opus
# %ifencoder %opus
if encoding == "opus" then
log("ENABLING opus recorder to filesystem")
%include "outgoing_recordings/opus.liq"
end
%endif
# %endif
%ifencoder %wav
# %ifencoder %wav
if encoding == "wav" then
log("ENABLING wav recorder to filesystem")
%include "outgoing_recordings/wav.liq"
end
%endif
# %endif
end
......@@ -22,45 +22,45 @@
# along with engine. If not, see <http://www.gnu.org/licenses/>.
#
r0_enable = list.assoc("rec_0", ini) == "y"
r1_enable = list.assoc("rec_1", ini) == "y"
r2_enable = list.assoc("rec_2", ini) == "y"
r3_enable = list.assoc("rec_3", ini) == "y"
r4_enable = list.assoc("rec_4", ini) == "y"
r0_enable = list.assoc(default="", "rec_0", ini) == "y"
r1_enable = list.assoc(default="", "rec_1", ini) == "y"
r2_enable = list.assoc(default="", "rec_2", ini) == "y"
r3_enable = list.assoc(default="", "rec_3", ini) == "y"
r4_enable = list.assoc(default="", "rec_4", ini) == "y"
r0_folder = list.assoc("rec_0_folder", ini)
r0_duration = int_of_string(list.assoc("rec_0_duration", ini))
r0_encoding = list.assoc("rec_0_encoding", ini)
r0_bitrate = int_of_string(list.assoc("rec_0_bitrate", ini))
r0_channels = list.assoc("rec_0_channels", ini)
r0_folder = list.assoc(default="", "rec_0_folder", ini)
r0_duration = int_of_string(list.assoc(default="", "rec_0_duration", ini))
r0_encoding = list.assoc(default="", "rec_0_encoding", ini)
r0_bitrate = int_of_string(list.assoc(default="", "rec_0_bitrate", ini))
r0_channels = list.assoc(default="", "rec_0_channels", ini)
r0_filenamepattern = r0_folder^"/%Y-%m-%d/%Y-%m-%d-%H-%M."^r0_encoding
r1_folder = list.assoc("rec_1_folder", ini)
r1_duration = int_of_string(list.assoc("rec_1_duration", ini))
r1_encoding = list.assoc("rec_1_encoding", ini)
r1_bitrate = int_of_string(list.assoc("rec_1_bitrate", ini))
r1_channels = list.assoc("rec_1_channels", ini)
r1_folder = list.assoc(default="", "rec_1_folder", ini)
r1_duration = int_of_string(list.assoc(default="", "rec_1_duration", ini))
r1_encoding = list.assoc(default="", "rec_1_encoding", ini)
r1_bitrate = int_of_string(list.assoc(default="", "rec_1_bitrate", ini))
r1_channels = list.assoc(default="", "rec_1_channels", ini)
r1_filenamepattern = r1_folder^"/%Y-%m-%d/%Y-%m-%d-%H-%M."^r1_encoding
r2_folder = list.assoc("rec_2_folder", ini)
r2_duration = int_of_string(list.assoc("rec_2_duration", ini))
r2_encoding = list.assoc("rec_2_encoding", ini)
r2_bitrate = int_of_string(list.assoc("rec_2_bitrate", ini))
r2_channels = list.assoc("rec_2_channels", ini)
r2_folder = list.assoc(default="", "rec_2_folder", ini)
r2_duration = int_of_string(list.assoc(default="", "rec_2_duration", ini))
r2_encoding = list.assoc(default="", "rec_2_encoding", ini)
r2_bitrate = int_of_string(list.assoc(default="", "rec_2_bitrate", ini))
r2_channels = list.assoc(default="", "rec_2_channels", ini)
r2_filenamepattern = r2_folder^"/%Y-%m-%d/%Y-%m-%d-%H-%M."^r2_encoding
r3_folder = list.assoc("rec_3_folder", ini)
r3_duration = int_of_string(list.assoc("rec_3_duration", ini))
r3_encoding = list.assoc("rec_3_encoding", ini)
r3_bitrate = int_of_string(list.assoc("rec_3_bitrate", ini))
r3_channels = list.assoc("rec_3_channels", ini)
r3_folder = list.assoc(default="", "rec_3_folder", ini)
r3_duration = int_of_string(list.assoc(default="", "rec_3_duration", ini))
r3_encoding = list.assoc(default="", "rec_3_encoding", ini)
r3_bitrate = int_of_string(list.assoc(default="", "rec_3_bitrate", ini))
r3_channels = list.assoc(default="", "rec_3_channels", ini)
r3_filenamepattern = r3_folder^"/%Y-%m-%d/%Y-%m-%d-%H-%M."^r3_encoding
r4_folder = list.assoc("rec_4_folder", ini)
r4_duration = int_of_string(list.assoc("rec_4_duration", ini))
r4_encoding = list.assoc("rec_4_encoding", ini)
r4_bitrate = int_of_string(list.assoc("rec_4_bitrate", ini))
r4_channels = list.assoc("rec_4_channels", ini)
r4_folder = list.assoc(default="", "rec_4_folder", ini)
r4_duration = int_of_string(list.assoc(default="", "rec_4_duration", ini))
r4_encoding = list.assoc(default="", "rec_4_encoding", ini)
r4_bitrate = int_of_string(list.assoc(default="", "rec_4_bitrate", ini))
r4_channels = list.assoc(default="", "rec_4_channels", ini)
r4_filenamepattern = r4_folder^"/%Y-%m-%d/%Y-%m-%d-%H-%M."^r4_encoding
r0_is_recording = ref false
......
......@@ -24,76 +24,76 @@
# Output streaming settings
# What a mess...
s0_enable = list.assoc("stream_0", ini) == "y"
s1_enable = list.assoc("stream_1", ini) == "y"
s2_enable = list.assoc("stream_2", ini) == "y"
s3_enable = list.assoc("stream_3", ini) == "y"
s4_enable = list.assoc("stream_4", ini) == "y"
s0_enable = list.assoc(default="", "stream_0", ini) == "y"
s1_enable = list.assoc(default="", "stream_1", ini) == "y"
s2_enable = list.assoc(default="", "stream_2", ini) == "y"
s3_enable = list.assoc(default="", "stream_3", ini) == "y"
s4_enable = list.assoc(default="", "stream_4", ini) == "y"
s0_encoding = list.assoc("stream_0_encoding", ini)
s0_bitrate = int_of_string(list.assoc("stream_0_bitrate", ini))
s0_host = list.assoc("stream_0_host", ini)
s0_port = int_of_string(list.assoc("stream_0_port", ini))
s0_user = list.assoc("stream_0_user", ini)
s0_pass = list.assoc("stream_0_password", ini)
s0_mount = list.assoc("stream_0_mountpoint", ini)
s0_url = list.assoc("stream_0_displayurl", ini)
s0_desc = list.assoc("stream_0_description", ini)
s0_genre = list.assoc("stream_0_genre", ini)
s0_name = list.assoc("stream_0_name", ini)
s0_channels = list.assoc("stream_0_channels", ini)
s0_encoding = list.assoc(default="", "stream_0_encoding", ini)
s0_bitrate = int_of_string(list.assoc(default="", "stream_0_bitrate", ini))
s0_host = list.assoc(default="", "stream_0_host", ini)
s0_port = int_of_string(list.assoc(default="", "stream_0_port", ini))
s0_user = list.assoc(default="", "stream_0_user", ini)
s0_pass = list.assoc(default="", "stream_0_password", ini)
s0_mount = list.assoc(default="", "stream_0_mountpoint", ini)
s0_url = list.assoc(default="", "stream_0_displayurl", ini)
s0_desc = list.assoc(default="", "stream_0_description", ini)
s0_genre = list.assoc(default="", "stream_0_genre", ini)
s0_name = list.assoc(default="", "stream_0_name", ini)
s0_channels = list.assoc(default="", "stream_0_channels", ini)
s1_encoding = list.assoc("stream_1_encoding", ini)
s1_bitrate = int_of_string(list.assoc("stream_1_bitrate", ini))
s1_host = list.assoc("stream_1_host", ini)
s1_port = int_of_string(list.assoc("stream_1_port", ini))
s1_user = list.assoc("stream_1_user", ini)
s1_pass = list.assoc("stream_1_password", ini)
s1_mount = list.assoc("stream_1_mountpoint", ini)
s1_url = list.assoc("stream_1_displayurl", ini)
s1_desc = list.assoc("stream_1_description", ini)
s1_genre = list.assoc("stream_1_genre", ini)
s1_name = list.assoc("stream_1_name", ini)
s1_channels = list.assoc("stream_1_channels", ini)
s1_encoding = list.assoc(default="", "stream_1_encoding", ini)
s1_bitrate = int_of_string(list.assoc(default="", "stream_1_bitrate", ini))
s1_host = list.assoc(default="", "stream_1_host", ini)
s1_port = int_of_string(list.assoc(default="", "stream_1_port", ini))
s1_user = list.assoc(default="", "stream_1_user", ini)
s1_pass = list.assoc(default="", "stream_1_password", ini)
s1_mount = list.assoc(default="", "stream_1_mountpoint", ini)
s1_url = list.assoc(default="", "stream_1_displayurl", ini)
s1_desc = list.assoc(default="", "stream_1_description", ini)
s1_genre = list.assoc(default="", "stream_1_genre", ini)
s1_name = list.assoc(default="", "stream_1_name", ini)
s1_channels = list.assoc(default="", "stream_1_channels", ini)
s2_encoding = list.assoc("stream_2_encoding", ini)
s2_bitrate = int_of_string(list.assoc("stream_2_bitrate", ini))
s2_host = list.assoc("stream_2_host", ini)
s2_port = int_of_string(list.assoc("stream_2_port", ini))
s2_user = list.assoc("stream_2_user", ini)
s2_pass = list.assoc("stream_2_password", ini)
s2_mount = list.assoc("stream_2_mountpoint", ini)
s2_url = list.assoc("stream_2_displayurl", ini)
s2_desc = list.assoc("stream_2_description", ini)
s2_genre = list.assoc("stream_2_genre", ini)
s2_name = list.assoc("stream_2_name", ini)
s2_channels = list.assoc("stream_2_channels", ini)
s2_encoding = list.assoc(default="", "stream_2_encoding", ini)
s2_bitrate = int_of_string(list.assoc(default="", "stream_2_bitrate", ini))
s2_host = list.assoc(default="", "stream_2_host", ini)
s2_port = int_of_string(list.assoc(default="", "stream_2_port", ini))
s2_user = list.assoc(default="", "stream_2_user", ini)
s2_pass = list.assoc(default="", "stream_2_password", ini)
s2_mount = list.assoc(default="", "stream_2_mountpoint", ini)
s2_url = list.assoc(default="", "stream_2_displayurl", ini)
s2_desc = list.assoc(default="", "stream_2_description", ini)
s2_genre = list.assoc(default="", "stream_2_genre", ini)
s2_name = list.assoc(default="", "stream_2_name", ini)
s2_channels = list.assoc(default="", "stream_2_channels", ini)
s3_encoding = list.assoc("stream_3_encoding", ini)
s3_bitrate = int_of_string(list.assoc("stream_3_bitrate", ini))
s3_host = list.assoc("stream_3_host", ini)
s3_port = int_of_string(list.assoc("stream_3_port", ini))
s3_user = list.assoc("stream_3_user", ini)
s3_pass = list.assoc("stream_3_password", ini)
s3_mount = list.assoc("stream_3_mountpoint", ini)
s3_url = list.assoc("stream_3_displayurl", ini)
s3_desc = list.assoc("stream_3_description", ini)
s3_genre = list.assoc("stream_3_genre", ini)
s3_name = list.assoc("stream_3_name", ini)
s3_channels = list.assoc("stream_3_channels", ini)
s3_encoding = list.assoc(default="", "stream_3_encoding", ini)
s3_bitrate = int_of_string(list.assoc(default="", "stream_3_bitrate", ini))
s3_host = list.assoc(default="", "stream_3_host", ini)
s3_port = int_of_string(list.assoc(default="", "stream_3_port", ini))
s3_user = list.assoc(default="", "stream_3_user", ini)
s3_pass = list.assoc(default="", "stream_3_password", ini)
s3_mount = list.assoc(default="", "stream_3_mountpoint", ini)
s3_url = list.assoc(default="", "stream_3_displayurl", ini)
s3_desc = list.assoc(default="", "stream_3_description", ini)
s3_genre = list.assoc(default="", "stream_3_genre", ini)
s3_name = list.assoc(default="", "stream_3_name", ini)
s3_channels = list.assoc(default="", "stream_3_channels", ini)
s4_encoding = list.assoc("stream_4_encoding", ini)
s4_bitrate = int_of_string(list.assoc("stream_4_bitrate", ini))
s4_host = list.assoc("stream_4_host", ini)
s4_port = int_of_string(list.assoc("stream_4_port", ini))
s4_user = list.assoc("stream_4_user", ini)
s4_pass = list.assoc("stream_4_password", ini)
s4_mount = list.assoc("stream_4_mountpoint", ini)
s4_url = list.assoc("stream_4_displayurl", ini)
s4_desc = list.assoc("stream_4_description", ini)
s4_genre = list.assoc("stream_4_genre", ini)
s4_name = list.assoc("stream_4_name", ini)
s4_channels = list.assoc("stream_4_channels", ini)
s4_encoding = list.assoc(default="", "stream_4_encoding", ini)
s4_bitrate = int_of_string(list.assoc(default="", "stream_4_bitrate", ini))
s4_host = list.assoc(default="", "stream_4_host", ini)
s4_port = int_of_string(list.assoc(default="", "stream_4_port", ini))
s4_user = list.assoc(default="", "stream_4_user", ini)
s4_pass = list.assoc(default="", "stream_4_password", ini)
s4_mount = list.assoc(default="", "stream_4_mountpoint", ini)
s4_url = list.assoc(default="", "stream_4_displayurl", ini)
s4_desc = list.assoc(default="", "stream_4_description", ini)
s4_genre = list.assoc(default="", "stream_4_genre", ini)
s4_name = list.assoc(default="", "stream_4_name", ini)
s4_channels = list.assoc(default="", "stream_4_channels", ini)
s0_connected = ref ''
s1_connected = ref ''
......
if bitrate == 24 then
if stereo then
ignore(output_filesystem_stereo(%aac(bitrate = 24, channels = 2), filenamepattern, !source))
else
ignore(output_filesystem_mono(%aac(bitrate = 24, channels = 1), filenamepattern, mean(!source)))
end
# if stereo then
ignore(output_filesystem_stereo(%fdkaac(bitrate = 24, channels = 2), filenamepattern, !source))
# else
# ignore(output_filesystem_mono(%fdkaac(bitrate = 24, channels = 1), filenamepattern, mean(!source)))
# end
elsif bitrate == 32 then
if stereo then