Skip to content
Snippets Groups Projects
Commit b110f22d authored by Gottfried Gaisbauer's avatar Gottfried Gaisbauer
Browse files

recording is now part of engine.liq. a redefinition of the recorded source is...

recording is now part of engine.liq. a redefinition of the recorded source is needed if those two should be separated.
parent b91073e6
No related branches found
No related tags found
No related merge requests found
Pipeline #
...@@ -26,7 +26,8 @@ sudo apt install \ ...@@ -26,7 +26,8 @@ sudo apt install \
redis-server redis-tools \ redis-server redis-tools \
liquidsoap liquidsoap-plugin-alsa liquidsoap-plugin-flac liquidsoap-plugin-icecast liquidsoap-plugin-pulseaudio \ liquidsoap liquidsoap-plugin-alsa liquidsoap-plugin-flac liquidsoap-plugin-icecast liquidsoap-plugin-pulseaudio \
libev4 libev-dev \ libev4 libev-dev \
mariadb-server libmariadbclient-dev mariadb-server libmariadbclient-dev \
quelcom
``` ```
......
...@@ -24,25 +24,23 @@ alsa_buffer_length="7" ...@@ -24,25 +24,23 @@ alsa_buffer_length="7"
# alsa_periods => int # alsa_periods => int
alsa_periods="0" alsa_periods="0"
# frame_duration => double # frame_duration => double
frame_duration="0.60" frame_duration="0.65"
# frame_size => int # frame_size => int
frame_size="" frame_size=""
[recording] [recording]
# duration in minutes # duration in minutes
rec_duration=1 rec_duration="30"
# flac settings # flac settings
rec_filetype="flac" rec_filetype="flac"
#rec_samplerate=44100 #rec_samplerate=44100
#rec_channels=2 #rec_channels="2"
#rec_compression=5 #rec_compression="5"
#rec_bits_per_sample=16 #rec_bits_per_sample="16"
# wav settings # wav settings
# rec_filetype="wav" # rec_filetype="wav"
rec_channels=2 rec_channels="2"
rec_samplesize=16 rec_samplesize="16"
[database] [database]
db_user="engine" db_user="engine"
...@@ -63,6 +61,7 @@ loglevel="info" ...@@ -63,6 +61,7 @@ loglevel="info"
http_channels="http,http2" http_channels="http,http2"
line_in_channels="live,live2" line_in_channels="live,live2"
filesystem_channels="filesystem" filesystem_channels="filesystem"
# track_sensitive => fallback_folder track sensitivity # track_sensitive => fallback_folder track sensitivity
# max_blank => maximum time of blank from source # max_blank => maximum time of blank from source
# min_noise => minimum duration of noise on source to switch back over # min_noise => minimum duration of noise on source to switch back over
......
...@@ -39,14 +39,17 @@ class LiquidSoapInitThread(threading.Thread): ...@@ -39,14 +39,17 @@ class LiquidSoapInitThread(threading.Thread):
for c in channels: for c in channels:
self.liquidsoapcommunicator.channel_activate(c, True) self.liquidsoapcommunicator.channel_activate(c, True)
time.sleep(2) time.sleep(1)
self.logger.info("LiquidSoapInitThread sets activechannel: "+str(self.active_entry)) if self.active_entry is not None:
self.logger.info("LiquidSoapInitThread sets activechannel: "+str(self.active_entry))
channel = self.active_entry.type channel = self.active_entry.type
if channel != "" and channel is not None: if channel != "" and channel is not None:
self.liquidsoapcommunicator.http_start_stop(channel == ScheduleEntryType.STREAM) self.liquidsoapcommunicator.http_start_stop(channel == ScheduleEntryType.STREAM)
self.liquidsoapcommunicator.channel_volume(channel.value, self.active_entry.volume) self.liquidsoapcommunicator.channel_volume(channel.value, self.active_entry.volume)
else:
self.logger.warning("No active entry in the scheduler! Is a programme loaded?")
self.liquidsoapcommunicator.disable_transaction() self.liquidsoapcommunicator.disable_transaction()
except Exception as e: except Exception as e:
......
#!/usr/bin/liquidsoap #!/usr/bin/liquidsoap
%include "readini.liq" # TELNET SETTINGS
set("server.telnet", true)
ini = read_ini("/etc/aura/engine.ini") set("server.telnet.bind_addr", "0.0.0.0")
set("server.telnet.port", 1234)
%include "settings.liq" %include "settings.liq"
%include "fallback.liq" %include "fallback.liq"
...@@ -14,11 +15,6 @@ input_fs = request.queue(id="fs") ...@@ -14,11 +15,6 @@ input_fs = request.queue(id="fs")
input_http = input.http(id="http", "http://stream.fro.at/fro-128.ogg") input_http = input.http(id="http", "http://stream.fro.at/fro-128.ogg")
input_alsa = input.alsa(id="live", device="hw:0", bufferize = false) input_alsa = input.alsa(id="live", device="hw:0", bufferize = false)
# create fallbacks
timeslot_fallback = fallback_create(skip=true, "timeslot_fallback", create_timeslot_fallback)
station_fallback = fallback_create(skip=true, "station_fallback", create_station_fallback)
show_fallback = fallback_create(skip=true, "show_fallback", create_show_fallback)
# fill the mixer # fill the mixer
mixer = mix(id="mixer", [input_fs, input_http, input_alsa]) mixer = mix(id="mixer", [input_fs, input_http, input_alsa])
...@@ -30,4 +26,9 @@ clock.unify([output_source, mixer, show_fallback, timeslot_fallback, station_fal ...@@ -30,4 +26,9 @@ clock.unify([output_source, mixer, show_fallback, timeslot_fallback, station_fal
# create output # create output
output.alsa(id="lineout", device="hw:0", bufferize = false, output_source) output.alsa(id="lineout", device="hw:0", bufferize = false, output_source)
system('#{list.assoc("install_dir", ini)}/guru.py --init-player') %include "recorder.liq"
recorder = get_recorder_output()
system('#{list.assoc("install_dir", ini)}/guru.py --init-player -q')
...@@ -95,6 +95,8 @@ def fallback_create(~skip=true, name, requestor) ...@@ -95,6 +95,8 @@ def fallback_create(~skip=true, name, requestor)
source = on_metadata(fun (meta) -> source = on_metadata(fun (meta) ->
system('#{list.assoc("install_dir", ini)}/guru.py -c aura -t liquid_startup'), source) system('#{list.assoc("install_dir", ini)}/guru.py -c aura -t liquid_startup'), source)
log("channel created")
# Finally apply a smart crossfading # Finally apply a smart crossfading
smart_crossfade(source) smart_crossfade(source)
end end
...@@ -126,4 +128,9 @@ def create_timeslot_fallback() = ...@@ -126,4 +128,9 @@ def create_timeslot_fallback() =
log("requesting next song for TIMESLOT fallback") log("requesting next song for TIMESLOT fallback")
result = get_process_lines('#{list.assoc("install_dir", ini)}/guru.py --get-next-file-for "timeslot-fallback" --quiet') result = get_process_lines('#{list.assoc("install_dir", ini)}/guru.py --get-next-file-for "timeslot-fallback" --quiet')
create_dynamic_playlist(result) create_dynamic_playlist(result)
end end
\ No newline at end of file
# create fallbacks
timeslot_fallback = fallback_create(skip=true, "timeslot_fallback", create_timeslot_fallback)
station_fallback = fallback_create(skip=true, "station_fallback", create_station_fallback)
show_fallback = fallback_create(skip=true, "show_fallback", create_show_fallback)
\ No newline at end of file
# LOG FILE SETTINGS
set("log.file.path", "./<script>.log")
# TELNET SETTINGS # %include "readini.liq"
set("server.telnet", true) # ini = read_ini("/etc/aura/engine.ini")
set("server.telnet.bind_addr", "0.0.0.0")
set("server.telnet.port", 2345) # %include "settings.liq"
# SOCKET SETTINGS # TELNET SETTINGS
set("server.socket", true) # set("server.telnet", true)
set("server.socket.path", "./<script>.sock") # set("server.telnet.bind_addr", "0.0.0.0")
# set("server.telnet.port", 2345)
inst = if argv(1) != "" then string_of(argv(1)) else 'record' end inst = if argv(1) != "" then string_of(argv(1)) else 'record' end
instance = ref inst instance = ref inst
%include "readini.liq"
ini = read_ini("/etc/aura/engine.ini")
audiobase = if !instance == 'record' then list.assoc("audiobase", ini) else list.assoc("altaudiobase", ini) end audiobase = if !instance == 'record' then list.assoc("audiobase", ini) else list.assoc("altaudiobase", ini) end
rec_filetype = list.assoc("rec_filetype", ini) rec_filetype = list.assoc("rec_filetype", ini)
...@@ -70,7 +66,7 @@ def get_output() ...@@ -70,7 +66,7 @@ def get_output()
on_start=on_start, on_start=on_start,
!filenamepattern, !filenamepattern,
on_close=on_close, on_close=on_close,
reopen_when={ if !instance == 'record' then int_of_float(gettimeofday()/60.) mod d == 0 else false end }, reopen_when={ if !instance == 'record' then int_of_float(gettimeofday()/60.) mod 30 == 0 else false end },
input input
) )
elsif rec_filetype == 'wav' then elsif rec_filetype == 'wav' then
...@@ -86,7 +82,7 @@ def get_output() ...@@ -86,7 +82,7 @@ def get_output()
input input
) )
else else
log("dummy out as rec out") log("DUMMY out as rec out")
output.dummy(blank()) output.dummy(blank())
end end
end end
...@@ -112,14 +108,7 @@ def start_dump() = ...@@ -112,14 +108,7 @@ def start_dump() =
log('starting to record') log('starting to record')
record = get_output() record = get_output()
log('record defined') log('record defined')
# Die Stopfunkton zeigt nun auf die Shutdown-Funktion der aktuellen Source # Die Stopfunkton zeigt nun auf die Shutdown-Funktion der aktuellen Source
......
audiobase = list.assoc("audiobase", ini)
rec_filetype = list.assoc("rec_filetype", ini)
print(list.assoc("rec_duration", ini))
print(rec_filetype)
rec_duration = int_of_string(list.assoc("rec_duration", ini))
# define file name pattern
filenamepattern = ref audiobase^"/%Y-%m-%d/%Y-%m-%d-%H-%M.flac"
# Der aktuelle Dateiname für die Aufnahme
recordingfile = ref ""
# bewahre uns davor, dass zweimal gleichzeitig die gleiche Date aufgenommen wird
is_record_active = ref false
#wir definieren eine Referenz für die Stop-Funktion, die aber bisher noch nichts tun kann
stop_f = ref (fun () -> ())
# Der input wie oben definiert
def get_input()
input.alsa()
end
def on_start()
recordingfile := list.hd(get_process_lines("date +#{!filenamepattern}"))
end
# Wav header fixen und ggf. die Aufzeichnung beenden
def on_close(filename)
# es darf wieder aufgenommen werden
is_record_active := false
if list.assoc("rec_filetype", ini) == 'wav' then
# Korrekten WAV-Header schreiben
system("qwavheaderdump -F #{filename}")
end
# Naechsten Dateinamen vormerken
recordingfile := list.hd(get_process_lines("date +#{!filenamepattern}"))
end
def start_flac_output()
print(gettimeofday())
print(gettimeofday()/60.)
print(int_of_float(gettimeofday()/60.))
print(int_of_float(gettimeofday()/60.) mod rec_duration)
# output def
output.file(
id="recorder",
%flac(samplerate=44100, channels=2, compression=5, bits_per_sample=16),
perm = 0o664,
on_start=on_start,
!filenamepattern,
on_close=on_close,
reopen_when={ int_of_float(gettimeofday()/60.) mod rec_duration == 0 },
output_source
)
end
def start_wav_output()
output.file(
id="recorder",
%wav(stereo=true, channels=2, samplesize=16, header=true),
perm = 0o664,
on_start=on_start,
!filenamepattern,
on_close=on_close,
reopen_when={ int_of_float(gettimeofday()/60.) mod rec_duration == 0 },
output_source
)
end
def enable_stop_function(record)
# Die Stopfunkton zeigt nun auf die Shutdown-Funktion der aktuellen Source
stop_f := fun () -> begin
log('stop recording')
# Aufnahme sauber beenden
ignore(server.execute('recorder.stop'))
# Source zerstören
source.shutdown(record)
# Variable zurücksetzen
recordingfile := ""
end
end
def get_recorder_output()
# flac output
if rec_filetype == 'flac' then
log("output file type is FLAC")
record = start_flac_output()
enable_stop_function(record)
# WAV output
elsif rec_filetype == 'wav' then
log("output file type is WAV")
record = start_wav_output()
enable_stop_function(record)
# DUMMY output
else
log("DUMMY out as rec out")
record = output.dummy(blank())
end
end
def currecording()
curfile = !recordingfile
if curfile != "" then
bytes_written = list.hd(get_process_lines("echo $(($(stat -c%s "^curfile^")))"))
"#{curfile}, #{bytes_written}B"
else
""
end
end
server.register(namespace="record",
description="Show current file.",
usage="curfile",
"curfile",
fun (s) -> currecording() )
\ No newline at end of file
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
# description="shutdown server", # description="shutdown server",
# usage="stop", # usage="stop",
# "stop", # "stop",
# fun(x,y) -> stop_server ) # fun(x,y) -> shutdown )
\ No newline at end of file \ No newline at end of file
# READ INI FILE
%include "readini.liq"
ini = read_ini("/etc/aura/engine.ini")
# LOG FILE SETTINGS # LOG FILE SETTINGS
set("log.file.path", "./<script>.log") set("log.file.path", "./<script>.log")
# TELNET SETTINGS
set("server.telnet", true)
set("server.telnet.bind_addr", "0.0.0.0")
set("server.telnet.port", 1234)
# SOCKET SETTINGS # SOCKET SETTINGS
set("server.socket", true) set("server.socket", true)
set("server.socket.path", "./<script>.sock") set("server.socket.path", "./<script>.sock")
# SOUND CARD SETTINGS # SOUND CARD SETTINGS
input_device_0 = list.assoc("input_device[0]", ini) #input_device_0 = list.assoc("input_device[0]", ini)
#input_device_1 = list.assoc("input_device[1]", ini) #input_device_1 = list.assoc("input_device[1]", ini)
#input_device_2 = list.assoc("input_device[2]", ini) #input_device_2 = list.assoc("input_device[2]", ini)
output_device_0 = list.assoc("output_device[0]", ini) #output_device_0 = list.assoc("output_device[0]", ini)
ignore(input_device_0) #ignore(input_device_0)
ignore(output_device_0) #ignore(output_device_0)
# ALSA / pulse settings # ALSA / pulse settings
use_alsa = list.assoc("use_alsa", ini) == "y" use_alsa = list.assoc("use_alsa", ini) == "y"
...@@ -29,12 +28,12 @@ alsa_periods = int_of_string(list.assoc("alsa_periods", ini)) ...@@ -29,12 +28,12 @@ alsa_periods = int_of_string(list.assoc("alsa_periods", ini))
if use_alsa then if use_alsa then
if frame_duration > 0.0 then if frame_duration > 0.0 then
print("setting frame.duration to #{frame_duration}") print("setting frame.duration to #{frame_duration}s")
set("frame.duration", frame_duration) set("frame.duration", frame_duration)
end end
if frame_size > 0 then if frame_size > 0 then
print("setting frame.size to #{frame_size}") print("setting frame.size to #{frame_size}")
set("frame.size", frame_size) set("frame.audio.size", frame_size)
end end
if alsa_buffer > 0 then if alsa_buffer > 0 then
print("setting alsa.buffer to #{alsa_buffer}") print("setting alsa.buffer to #{alsa_buffer}")
......
...@@ -387,9 +387,9 @@ class AuraScheduler(ExceptionLogger, threading.Thread): ...@@ -387,9 +387,9 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
self.logger.critical(str(self.get_active_entry())) self.logger.critical(str(self.get_active_entry()))
self.logger.critical(playlistname) self.logger.critical(playlistname)
self.redismessenger.set_next_file_for(playlistname, "/var/audio/blank.flac") self.redismessenger.set_next_file_for(playlistname, "/var/audio/blank.flac")
print('return self.config.get("install_dir") + "/configuration/blank.flac"') #print('return self.config.get("install_dir") + "/configuration/blank.flac"')
import sys #import sys
sys.exit(0) #sys.exit(0)
# ------------------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------------------ #
def start_recording(self, data): def start_recording(self, data):
......
[Unit]
Description=Aura Engine Playout Server
After=network.target aura-engine.service
Wants=aura-engine.service
[Service]
Type=simple
User=gg
WorkingDirectory=/home/gg/PycharmProjects/engine/modules/liquidsoap
ExecStart=/usr/bin/liquidsoap /home/gg/PycharmProjects/engine/modules/liquidsoap/engine.liq
Restart=always
[Install]
WantedBy=multi-user.target
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment