-fixed liquidsoap not working when the liquidsoap global libraries were not installed
This commit is contained in:
parent
277095a538
commit
692ba3513b
|
@ -54,14 +54,11 @@ def copy_dir(src_dir, dest_dir):
|
|||
try:
|
||||
# Create users
|
||||
create_user("pypo")
|
||||
#create_user("pypo-logger")
|
||||
|
||||
print "Creating log directories"
|
||||
create_path("/var/log/pypo")
|
||||
os.system("chmod -R 755 /var/log/pypo")
|
||||
os.system("chown -R pypo:pypo /var/log/pypo")
|
||||
#os.mkdirs("/var/log/liquidsoap")
|
||||
#os.system("chown -R liquidsoap:liquidsoap /var/log/liquidsoap")
|
||||
|
||||
create_path(BASE_PATH)
|
||||
create_path(BASE_PATH+"bin")
|
||||
|
@ -87,17 +84,7 @@ try:
|
|||
print "Unknown system architecture."
|
||||
sys.exit(1)
|
||||
|
||||
#shutil.copy("../pypo-cli.py", BASE_PATH+"bin")
|
||||
#shutil.copy("../pypo-notify.py", BASE_PATH+"bin")
|
||||
#shutil.copy("../logging.cfg", BASE_PATH+"bin")
|
||||
#shutil.copy("../config.cfg", BASE_PATH+"bin")
|
||||
#shutil.copy("../pypo-log.sh", BASE_PATH+"bin")
|
||||
copy_dir("..", BASE_PATH+"bin/")
|
||||
#copy_dir("../util", BASE_PATH+"bin/")
|
||||
#copy_dir("../api_clients", BASE_PATH+"bin/api_clients")
|
||||
#copy_dir("../scripts", BASE_PATH+"bin/scripts")
|
||||
#copy_dir("../dls", BASE_PATH+"bin/dls")
|
||||
#copy_dir("../dls", BASE_PATH+"bin/dls")
|
||||
|
||||
print "Setting permissions"
|
||||
os.system("chmod -R 755 "+BASE_PATH)
|
||||
|
@ -120,8 +107,7 @@ try:
|
|||
os.system("chown -R pypo:pypo /etc/service/pypo-push")
|
||||
|
||||
print "Installing daemontool script pypo-liquidsoap"
|
||||
os.system("svc -dk /etc/service/pypo-liquidsoap > /dev/null 2>&1")
|
||||
os.system("killall liquidsoap")
|
||||
os.system("svc -dx /etc/service/pypo-liquidsoap 1>/dev/null 2>&1")
|
||||
create_path("/etc/service/pypo-liquidsoap")
|
||||
create_path("/etc/service/pypo-liquidsoap/log")
|
||||
shutil.copy("pypo-daemontools-liquidsoap.sh", "/etc/service/pypo-liquidsoap/run")
|
||||
|
@ -131,6 +117,7 @@ try:
|
|||
|
||||
print "Waiting for processes to start..."
|
||||
time.sleep(5)
|
||||
os.system("killall liquidsoap")
|
||||
os.system("python ./pypo-start.py")
|
||||
time.sleep(2)
|
||||
|
||||
|
@ -148,9 +135,7 @@ try:
|
|||
p = Popen('svstat /etc/service/pypo-liquidsoap', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
|
||||
output = p.stdout.read()
|
||||
print output
|
||||
|
||||
#os.symlink(BASE_PATH+"bin/pypo-log.sh", "/usr/local/bin/")
|
||||
|
||||
|
||||
print "Install complete."
|
||||
except Exception, e:
|
||||
print "exception:" + str(e)
|
||||
|
|
|
@ -19,4 +19,4 @@ try:
|
|||
os.system("svc -t /etc/service/pypo-liquidsoap")
|
||||
|
||||
except Exception, e:
|
||||
print "exception:" + str(e)
|
||||
print "exception:" + str(e)
|
||||
|
|
|
@ -21,7 +21,7 @@ def remove_user(username):
|
|||
print "Waiting for processes to close..."
|
||||
time.sleep(5)
|
||||
|
||||
os.system("deluser --remove-home " + username + " > /dev/null")
|
||||
os.system("deluser --remove-home " + username + " 1>/dev/null")
|
||||
|
||||
try:
|
||||
os.system("python ./pypo-stop.py")
|
||||
|
@ -44,4 +44,4 @@ try:
|
|||
remove_user("pypo")
|
||||
print "Uninstall complete."
|
||||
except Exception, e:
|
||||
print "exception:" + str(e)
|
||||
print "exception:" + str(e)
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
|
||||
DISTFILES = $(wildcard *.in) Makefile ask-liquidsoap.rb ask-liquidsoap.pl \
|
||||
$(wildcard *.liq) extract-replaygain
|
||||
|
||||
top_srcdir = ..
|
||||
include $(top_srcdir)/Makefile.rules
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict ;
|
||||
use Net::Telnet ;
|
||||
|
||||
my $telnet = new Net::Telnet ( Timeout=>10, Errmode=>'die', Port=>1234) ;
|
||||
$telnet->open('localhost') ;
|
||||
|
||||
die "Usage: $0 <command>\n" unless @ARGV ;
|
||||
$telnet->print($ARGV[0]) ;
|
||||
my ($output,$end) = $telnet->waitfor('/END$/') ;
|
||||
print $output;
|
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/ruby
|
||||
|
||||
require 'net/telnet'
|
||||
|
||||
liq_host = "localhost"
|
||||
liq_port = 1234
|
||||
|
||||
conn = Net::Telnet::new("Host" => liq_host, "Port" => liq_port)
|
||||
|
||||
conn.puts(ARGV[0])
|
||||
conn.waitfor("Match" => /^END$/) do |data|
|
||||
puts data.sub(/\nEND\n/,"")
|
||||
end
|
|
@ -0,0 +1,314 @@
|
|||
# These operators need to be updated..
|
||||
|
||||
|
||||
# Stream data from mplayer
|
||||
# @category Source / Input
|
||||
# @param s data URI.
|
||||
# @param ~restart restart on exit.
|
||||
# @param ~restart_on_error restart on exit with error.
|
||||
# @param ~buffer Duration of the pre-buffered data.
|
||||
# @param ~max Maximum duration of the buffered data.
|
||||
def input.mplayer(~id="input.mplayer",
|
||||
~restart=true,~restart_on_error=false,
|
||||
~buffer=0.2,~max=10.,s) =
|
||||
input.external(id=id,restart=restart,
|
||||
restart_on_error=restart_on_error,
|
||||
buffer=buffer,max=max,
|
||||
"mplayer -really-quiet -ao pcm:file=/dev/stdout \
|
||||
-vc null -vo null #{quote(s)} 2>/dev/null")
|
||||
end
|
||||
|
||||
|
||||
# Output the stream using aplay.
|
||||
# Using this turns "root.sync" to false
|
||||
# since aplay will do the synchronisation
|
||||
# @category Source / Output
|
||||
# @param ~id Output's ID
|
||||
# @param ~device Alsa pcm device name
|
||||
# @param ~restart_on_crash Restart external process on crash. If false, liquidsoap will stop.
|
||||
# @param ~fallible Allow the child source to fail, in which case the output will be (temporarily) stopped.
|
||||
# @param ~on_start Callback executed when outputting starts.
|
||||
# @param ~on_stop Callback executed when outputting stops.
|
||||
# @param s Source to play
|
||||
def output.aplay(~id="output.aplay",~device="default",
|
||||
~fallible=false,~on_start={()},~on_stop={()},
|
||||
~restart_on_crash=false,s)
|
||||
def aplay_p(m) =
|
||||
"aplay -D #{device}"
|
||||
end
|
||||
log(label=id,level=3,"Setting root.sync to false")
|
||||
set("root.sync",false)
|
||||
output.pipe.external(id=id,
|
||||
fallible=fallible,on_start=on_start,on_stop=on_stop,
|
||||
restart_on_crash=restart_on_crash,
|
||||
restart_on_new_track=false,
|
||||
process=aplay_p,s)
|
||||
end
|
||||
|
||||
%ifdef output.icecast.external
|
||||
# Output to icecast using the lame command line encoder.
|
||||
# @category Source / Output
|
||||
# @param ~id Output's ID
|
||||
# @param ~start Start output threads on operator initialization.
|
||||
# @param ~restart Restart output after a failure. By default, liquidsoap will stop if the output failed.
|
||||
# @param ~restart_delay Delay, in seconds, before attempting new connection, if restart is enabled.
|
||||
# @param ~restart_on_crash Restart external process on crash. If false, liquidsoap will stop.
|
||||
# @param ~restart_on_new_track Restart encoder upon new track.
|
||||
# @param ~restart_encoder_delay Restart the encoder after this delay, in seconds.
|
||||
# @param ~user User for shout source connection. Useful only in special cases, like with per-mountpoint users.
|
||||
# @param ~lame The lame binary
|
||||
# @param ~bitrate Encoder bitrate
|
||||
# @param ~swap Swap audio samples. Depends on local machine's endianess and lame's version. Test this parameter if you experience garbaged mp3 audio data. On intel 32 and 64 architectures, the parameter should be "true" for lame version >= 3.98.
|
||||
# @param ~dumpfile Dump stream to file, for debugging purpose. Disabled if empty.
|
||||
# @param ~protocol Protocol of the streaming server: 'http' for Icecast, 'icy' for Shoutcast.
|
||||
# @param ~fallible Allow the child source to fail, in which case the output will be (temporarily) stopped.
|
||||
# @param ~on_start Callback executed when outputting starts.
|
||||
# @param ~on_stop Callback executed when outputting stops.
|
||||
# @param s The source to output
|
||||
def output.icecast.lame(
|
||||
~id="output.icecast.lame",~start=true,
|
||||
~restart=false,~restart_delay=3,
|
||||
~host="localhost",~port=8000,
|
||||
~user="source",~password="hackme",
|
||||
~genre="Misc",~url="http://savonet.sf.net/",
|
||||
~description="OCaml Radio!",~public=true,
|
||||
~dumpfile="",~mount="Use [name]",
|
||||
~name="Use [mount]",~protocol="http",
|
||||
~lame="lame",~bitrate=128,~swap=false,
|
||||
~fallible=false,~on_start={()},~on_stop={()},
|
||||
~restart_on_crash=false,~restart_on_new_track=false,
|
||||
~restart_encoder_delay=3600,~headers=[],s)
|
||||
samplerate = get(default=44100,"frame.samplerate")
|
||||
samplerate = float_of_int(samplerate) / 1000.
|
||||
channels = get(default=2,"frame.channels")
|
||||
swap = if swap then "-x" else "" end
|
||||
mode =
|
||||
if channels == 2 then
|
||||
"j" # Encoding in joint stereo..
|
||||
else
|
||||
"m"
|
||||
end
|
||||
# Metadata update is set by ICY with icecast
|
||||
def lame_p(m)
|
||||
"#{lame} -b #{bitrate} -r --bitwidth 16 -s #{samplerate} \
|
||||
--signed -m #{mode} --nores #{swap} -t - -"
|
||||
end
|
||||
output.icecast.external(id=id,
|
||||
process=lame_p,bitrate=bitrate,start=start,
|
||||
restart=restart,restart_delay=restart_delay,
|
||||
host=host,port=port,user=user,password=password,
|
||||
genre=genre,url=url,description=description,
|
||||
public=public,dumpfile=dumpfile,restart_encoder_delay=restart_encoder_delay,
|
||||
name=name,mount=mount,protocol=protocol,
|
||||
header=false,restart_on_crash=restart_on_crash,
|
||||
restart_on_new_track=restart_on_new_track,headers=headers,
|
||||
fallible=fallible,on_start=on_start,on_stop=on_stop,
|
||||
s)
|
||||
end
|
||||
|
||||
# Output to shoutcast using the lame encoder.
|
||||
# @category Source / Output
|
||||
# @param ~id Output's ID
|
||||
# @param ~start Start output threads on operator initialization.
|
||||
# @param ~restart Restart output after a failure. By default, liquidsoap will stop if the output failed.
|
||||
# @param ~restart_delay Delay, in seconds, before attempting new connection, if restart is enabled.
|
||||
# @param ~restart_on_crash Restart external process on crash. If false, liquidsoap will stop.
|
||||
# @param ~restart_on_new_track Restart encoder upon new track.
|
||||
# @param ~restart_encoder_delay Restart the encoder after this delay, in seconds.
|
||||
# @param ~user User for shout source connection. Useful only in special cases, like with per-mountpoint users.
|
||||
# @param ~lame The lame binary
|
||||
# @param ~bitrate Encoder bitrate
|
||||
# @param ~icy_reset Reset shoutcast source buffer upon connecting (necessary for NSV).
|
||||
# @param ~dumpfile Dump stream to file, for debugging purpose. Disabled if empty.
|
||||
# @param ~fallible Allow the child source to fail, in which case the output will be (temporarily) stopped.
|
||||
# @param ~on_start Callback executed when outputting starts.
|
||||
# @param ~on_stop Callback executed when outputting stops.
|
||||
# @param s The source to output
|
||||
def output.shoutcast.lame(
|
||||
~id="output.shoutcast.mp3",~start=true,
|
||||
~restart=false,~restart_delay=3,
|
||||
~host="localhost",~port=8000,
|
||||
~user="source",~password="hackme",
|
||||
~genre="Misc",~url="http://savonet.sf.net/",
|
||||
~description="OCaml Radio!",~public=true,
|
||||
~dumpfile="",~name="Use [mount]",~icy_reset=true,
|
||||
~lame="lame",~aim="",~icq="",~irc="",
|
||||
~fallible=false,~on_start={()},~on_stop={()},
|
||||
~restart_on_crash=false,~restart_on_new_track=false,
|
||||
~restart_encoder_delay=3600,~bitrate=128,s) =
|
||||
icy_reset = if icy_reset then "1" else "0" end
|
||||
headers = [("icy-aim",aim),("icy-irc",irc),
|
||||
("icy-icq",icq),("icy-reset",icy_reset)]
|
||||
output.icecast.lame(
|
||||
id=id, headers=headers, lame=lame,
|
||||
bitrate=bitrate, start=start,
|
||||
restart=restart, restart_encoder_delay=restart_encoder_delay,
|
||||
host=host, port=port, user=user, password=password,
|
||||
genre=genre, url=url, description=description,
|
||||
public=public, dumpfile=dumpfile,
|
||||
restart_on_crash=restart_on_crash,
|
||||
restart_on_new_track=restart_on_new_track,
|
||||
name=name, mount="/", protocol="icy",
|
||||
fallible=fallible,on_start=on_start,on_stop=on_stop,
|
||||
s)
|
||||
end
|
||||
|
||||
# Output to icecast using the flac command line encoder.
|
||||
# @category Source / Output
|
||||
# @param ~id Output's ID
|
||||
# @param ~start Start output threads on operator initialization.
|
||||
# @param ~restart Restart output after a failure. By default, liquidsoap will stop if the output failed.
|
||||
# @param ~restart_delay Delay, in seconds, before attempting new connection, if restart is enabled.
|
||||
# @param ~restart_on_crash Restart external process on crash. If false, liquidsoap will stop.
|
||||
# @param ~restart_on_new_track Restart encoder upon new track. If false, the resulting stream will have a single track.
|
||||
# @param ~restart_encoder_delay Restart the encoder after this delay, in seconds.
|
||||
# @param ~user User for shout source connection. Useful only in special cases, like with per-mountpoint users.
|
||||
# @param ~flac The flac binary
|
||||
# @param ~quality Encoder quality (0..8)
|
||||
# @param ~dumpfile Dump stream to file, for debugging purpose. Disabled if empty.
|
||||
# @param ~protocol Protocol of the streaming server: 'http' for Icecast, 'icy' for Shoutcast.
|
||||
# @param ~fallible Allow the child source to fail, in which case the output will be (temporarily) stopped.
|
||||
# @param ~on_start Callback executed when outputting starts.
|
||||
# @param ~on_stop Callback executed when outputting stops.
|
||||
# @param s The source to output
|
||||
def output.icecast.flac(
|
||||
~id="output.icecast.flac",~start=true,
|
||||
~restart=false,~restart_delay=3,
|
||||
~host="localhost",~port=8000,
|
||||
~user="source",~password="hackme",
|
||||
~genre="Misc",~url="http://savonet.sf.net/",
|
||||
~description="OCaml Radio!",~public=true,
|
||||
~dumpfile="",~mount="Use [name]",
|
||||
~name="Use [mount]",~protocol="http",
|
||||
~flac="flac",~quality=6,
|
||||
~restart_on_crash=false,
|
||||
~restart_on_new_track=true,
|
||||
~restart_encoder_delay=(-1),
|
||||
~fallible=false,~on_start={()},~on_stop={()},
|
||||
s)
|
||||
# We will use raw format, to
|
||||
# bypass input length value in WAV
|
||||
# header (input length is not known)
|
||||
channels = get(default=2,"frame.channels")
|
||||
samplerate = get(default=44100,"frame.samplerate")
|
||||
def flac_p(m)=
|
||||
def option(x) =
|
||||
"-T #{quote(fst(x))}=#{quote(snd(x))}"
|
||||
end
|
||||
m = list.map(option,m)
|
||||
m = string.concat(separator=" ",m)
|
||||
"#{flac} --force-raw-format --endian=little --channels=#{channels} \
|
||||
--bps=16 --sample-rate=#{samplerate} --sign=signed #{m} \
|
||||
-#{quality} --ogg -c -"
|
||||
end
|
||||
output.icecast.external(id=id,
|
||||
process=flac_p,bitrate=(-1),start=start,
|
||||
restart=restart,restart_delay=restart_delay,
|
||||
host=host,port=port,user=user,password=password,
|
||||
genre=genre,url=url,description=description,
|
||||
public=public,dumpfile=dumpfile,
|
||||
name=name,mount=mount,protocol=protocol,
|
||||
fallible=fallible,on_start=on_start,on_stop=on_stop,
|
||||
restart_on_new_track=restart_on_new_track,
|
||||
format="ogg",header=false,icy_metadata=false,
|
||||
restart_on_crash=restart_on_crash,
|
||||
restart_encoder_delay=restart_encoder_delay,
|
||||
s)
|
||||
end
|
||||
|
||||
# Output to icecast using the aacplusenc command line encoder.
|
||||
# @category Source / Output
|
||||
# @param ~id Output's ID
|
||||
# @param ~start Start output threads on operator initialization.
|
||||
# @param ~restart Restart output after a failure. By default, liquidsoap will stop if the output failed.
|
||||
# @param ~restart_delay Delay, in seconds, before attempting new connection, if restart is enabled.
|
||||
# @param ~restart_on_crash Restart external process on crash. If false, liquidsoap will stop.
|
||||
# @param ~restart_on_new_track Restart encoder upon new track.
|
||||
# @param ~restart_encoder_delay Restart the encoder after this delay, in seconds.
|
||||
# @param ~user User for shout source connection. Useful only in special cases, like with per-mountpoint users.
|
||||
# @param ~aacplusenc The aacplusenc binary
|
||||
# @param ~bitrate Encoder bitrate
|
||||
# @param ~dumpfile Dump stream to file, for debugging purpose. Disabled if empty.
|
||||
# @param ~protocol Protocol of the streaming server: 'http' for Icecast, 'icy' for Shoutcast.
|
||||
# @param ~fallible Allow the child source to fail, in which case the output will be (temporarily) stopped.
|
||||
# @param ~on_start Callback executed when outputting starts.
|
||||
# @param ~on_stop Callback executed when outputting stops.
|
||||
# @param s The source to output
|
||||
def output.icecast.aacplusenc(
|
||||
~id="output.icecast.aacplusenc",~start=true,
|
||||
~restart=false,~restart_delay=3,
|
||||
~host="localhost",~port=8000,
|
||||
~user="source",~password="hackme",
|
||||
~genre="Misc",~url="http://savonet.sf.net/",
|
||||
~description="OCaml Radio!",~public=true,
|
||||
~dumpfile="",~mount="Use [name]",
|
||||
~name="Use [mount]",~protocol="http",
|
||||
~aacplusenc="aacplusenc",~bitrate=64,
|
||||
~fallible=false,~on_start={()},~on_stop={()},
|
||||
~restart_on_crash=false,~restart_on_new_track=false,
|
||||
~restart_encoder_delay=3600,~headers=[],s)
|
||||
# Metadata update is set by ICY with icecast
|
||||
def aacplusenc_p(m)
|
||||
"#{aacplusenc} - - #{bitrate}"
|
||||
end
|
||||
output.icecast.external(id=id,
|
||||
process=aacplusenc_p,bitrate=bitrate,start=start,
|
||||
restart=restart,restart_delay=restart_delay,
|
||||
host=host,port=port,user=user,password=password,
|
||||
genre=genre,url=url,description=description,
|
||||
public=public,dumpfile=dumpfile,
|
||||
name=name,mount=mount,protocol=protocol,
|
||||
fallible=fallible,on_start=on_start,on_stop=on_stop,
|
||||
header=true,restart_on_crash=restart_on_crash,
|
||||
restart_on_new_track=restart_on_new_track,headers=headers,
|
||||
restart_encoder_delay=restart_encoder_delay,format="audio/aacp",s)
|
||||
end
|
||||
|
||||
# Output to shoutcast using the aacplusenc encoder.
|
||||
# @category Source / Output
|
||||
# @param ~id Output's ID
|
||||
# @param ~start Start output threads on operator initialization.
|
||||
# @param ~restart Restart output after a failure. By default, liquidsoap will stop if the output failed.
|
||||
# @param ~restart_delay Delay, in seconds, before attempting new connection, if restart is enabled.
|
||||
# @param ~restart_on_crash Restart external process on crash. If false, liquidsoap will stop.
|
||||
# @param ~restart_on_new_track Restart encoder upon new track.
|
||||
# @param ~restart_encoder_delay Restart the encoder after this delay, in seconds.
|
||||
# @param ~user User for shout source connection. Useful only in special cases, like with per-mountpoint users.
|
||||
# @param ~aacplusenc The aacplusenc binary
|
||||
# @param ~bitrate Encoder bitrate
|
||||
# @param ~icy_reset Reset shoutcast source buffer upon connecting (necessary for NSV).
|
||||
# @param ~dumpfile Dump stream to file, for debugging purpose. Disabled if empty.
|
||||
# @param ~fallible Allow the child source to fail, in which case the output will be (temporarily) stopped.
|
||||
# @param ~on_start Callback executed when outputting starts.
|
||||
# @param ~on_stop Callback executed when outputting stops.
|
||||
# @param s The source to output
|
||||
def output.shoutcast.aacplusenc(
|
||||
~id="output.shoutcast.aacplusenc",~start=true,
|
||||
~restart=false,~restart_delay=3,
|
||||
~host="localhost",~port=8000,
|
||||
~user="source",~password="hackme",
|
||||
~genre="Misc",~url="http://savonet.sf.net/",
|
||||
~description="OCaml Radio!",~public=true,
|
||||
~fallible=false,~on_start={()},~on_stop={()},
|
||||
~dumpfile="",~name="Use [mount]",~icy_reset=true,
|
||||
~aim="",~icq="",~irc="",~aacplusenc="aacplusenc",
|
||||
~restart_on_crash=false,~restart_on_new_track=false,
|
||||
~restart_encoder_delay=3600,~bitrate=64,s) =
|
||||
icy_reset = if icy_reset then "1" else "0" end
|
||||
headers = [("icy-aim",aim),("icy-irc",irc),
|
||||
("icy-icq",icq),("icy-reset",icy_reset)]
|
||||
output.icecast.aacplusenc(
|
||||
id=id, headers=headers, aacplusenc=aacplusenc,
|
||||
bitrate=bitrate, start=start,
|
||||
restart=restart, restart_delay=restart_delay,
|
||||
host=host, port=port, user=user, password=password,
|
||||
genre=genre, url=url, description=description,
|
||||
public=public, dumpfile=dumpfile,
|
||||
fallible=fallible,on_start=on_start,on_stop=on_stop,
|
||||
restart_on_crash=restart_on_crash, restart_encoder_delay=restart_encoder_delay,
|
||||
restart_on_new_track=restart_on_new_track,
|
||||
name=name, mount="/", protocol="icy",
|
||||
s)
|
||||
end
|
||||
%endif
|
||||
|
|
@ -35,7 +35,7 @@ if test_process("which flac") then
|
|||
add_decoder(name="FLAC",description="Decode files using the flac \
|
||||
decoder binary.", test=test_flac,flac_p)
|
||||
else
|
||||
log(level=3,"flac binary not found: flac decoder disabled.")
|
||||
log(level=3,"Did not find flac binary: flac decoder disabled.")
|
||||
end
|
||||
%endif
|
||||
|
||||
|
@ -63,15 +63,16 @@ if os.type != "Win32" then
|
|||
end
|
||||
add_metadata_resolver("FLAC",flac_meta)
|
||||
else
|
||||
log(level=3,"metaflac binary not found: flac metadata resolver disabled.")
|
||||
log(level=3,"Did not find metaflac binary: flac metadata resolver disabled.")
|
||||
end
|
||||
end
|
||||
|
||||
# A list of know extensions and content-type for AAC.
|
||||
# Values from http://en.wikipedia.org/wiki/Advanced_Audio_Coding
|
||||
# TODO: can we register a setting for that ??
|
||||
aac_mimes = ["audio/aac", "audio/aacp", "audio/3gpp", "audio/3gpp2", "audio/mp4",
|
||||
"audio/MP4A-LATM", "audio/mpeg4-generic", "audio/x-hx-aac-adts"]
|
||||
aac_mimes =
|
||||
["audio/aac", "audio/aacp", "audio/3gpp", "audio/3gpp2", "audio/mp4",
|
||||
"audio/MP4A-LATM", "audio/mpeg4-generic", "audio/x-hx-aac-adts"]
|
||||
aac_filexts = ["m4a", "m4b", "m4p", "m4v",
|
||||
"m4r", "3gp", "mp4", "aac"]
|
||||
|
||||
|
@ -143,7 +144,48 @@ if os.type != "Win32" then
|
|||
end
|
||||
add_metadata_resolver("FAAD",faad_meta)
|
||||
else
|
||||
log(level=3,"faad binary not found: faad decoder disabled.")
|
||||
log(level=3,"Did not find faad binary: faad decoder disabled.")
|
||||
end
|
||||
end
|
||||
|
||||
# Standard function for displaying metadata.
|
||||
# Shows artist and title, using "Unknown" when a field is empty.
|
||||
# @param m Metadata packet to be displayed.
|
||||
def string_of_metadata(m)
|
||||
artist = m["artist"]
|
||||
title = m["title"]
|
||||
artist = if ""==artist then "Unknown" else artist end
|
||||
title = if ""==title then "Unknown" else title end
|
||||
"#{artist} -- #{title}"
|
||||
end
|
||||
|
||||
# Use X On Screen Display to display metadata info.
|
||||
# @param ~color Color of the text.
|
||||
# @param ~position Position of the text (top|middle|bottom).
|
||||
# @param ~font Font used (xfontsel is your friend...)
|
||||
# @param ~display Function used to display a metadata packet.
|
||||
def osd_metadata(~color="green",~position="top",
|
||||
~font="-*-courier-*-r-*-*-*-240-*-*-*-*-*-*",
|
||||
~display=string_of_metadata,
|
||||
s)
|
||||
osd = 'osd_cat -p #{position} --font #{quote(font)}'
|
||||
^ ' --color #{color}'
|
||||
def feedback(m)
|
||||
system("echo #{quote(display(m))} | #{osd} &")
|
||||
end
|
||||
on_metadata(feedback,s)
|
||||
end
|
||||
|
||||
# Use notify to display metadata info.
|
||||
# @param ~urgency Urgency (low|normal|critical).
|
||||
# @param ~icon Icon filename or stock icon to display.
|
||||
# @param ~time Timeout in milliseconds.
|
||||
# @param ~display Function used to display a metadata packet.
|
||||
# @param ~title Title of the notification message.
|
||||
def notify_metadata(~urgency="low",~icon="stock_smiley-22",~time=3000,
|
||||
~display=string_of_metadata,
|
||||
~title="Liquidsoap: new track",s)
|
||||
send = 'notify-send -i #{icon} -u #{urgency}'
|
||||
^ ' -t #{time} #{quote(title)} '
|
||||
on_metadata(fun (m) -> system(send^quote(display(m))),s)
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@ if (($file =~ /\.mp3$/i) || (test_mime($file) =~ /audio\/mpeg/)) {
|
|||
|
||||
if (`which mp3gain`) {
|
||||
|
||||
my $out = `nice -n 20 mp3gain -q "$file" 2> /dev/null` ;
|
||||
my $out = `mp3gain -q "$file" 2> /dev/null` ;
|
||||
$out =~ /Recommended "Track" dB change: (.*)$/m || die ;
|
||||
print "$1 dB\n" ;
|
||||
|
||||
|
@ -29,7 +29,7 @@ if (($file =~ /\.mp3$/i) || (test_mime($file) =~ /audio\/mpeg/)) {
|
|||
|
||||
if ((`which vorbisgain`) && (`which ogginfo`)) {
|
||||
|
||||
system("nice -n 20 vorbisgain -q -f \"$file\" 2>/dev/null >/dev/null") ;
|
||||
system("vorbisgain -q -f \"$file\" 2>/dev/null >/dev/null") ;
|
||||
my $info = `ogginfo "$file"` ;
|
||||
$info =~ /REPLAYGAIN_TRACK_GAIN=(.*) dB/ || die ;
|
||||
print "$1 dB\n" ;
|
||||
|
@ -52,7 +52,7 @@ if (($file =~ /\.mp3$/i) || (test_mime($file) =~ /audio\/mpeg/)) {
|
|||
|
||||
} else {
|
||||
|
||||
system("nice -n 20 metaflac --add-replay-gain \"$file\" \
|
||||
system("metaflac --add-replay-gain \"$file\" \
|
||||
2>/dev/null >/dev/null") ;
|
||||
$info = `metaflac --show-tag=REPLAYGAIN_TRACK_GAIN "$file"` ;
|
||||
$info =~ /REPLAYGAIN_TRACK_GAIN=(.*) dB/ || die "Error in $file" ;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# Launch with: screen -c interactive.screen
|
||||
screen -t Liquidsoap liquidsoap --interactive 'set("log.file.path","/tmp/interactive.log") system("echo \"setenv PID #{getpid()}\" > /tmp/interactive.env")'
|
||||
verbose
|
||||
# Yeah, this is a trick
|
||||
# to wait for interactive.env
|
||||
# to be created
|
||||
logfile /dev/null
|
||||
log
|
||||
source /tmp/interactive.env
|
||||
screen -t Log tail --pid=$PID -f /tmp/interactive.log
|
||||
split -v
|
||||
select 0
|
||||
focus
|
||||
select 1
|
||||
focus
|
|
@ -0,0 +1,43 @@
|
|||
#!/sbin/runscript
|
||||
|
||||
user=liquidsoap
|
||||
group=liquidsoap
|
||||
prefix=/usr/local
|
||||
exec_prefix=${prefix}
|
||||
confdir=${prefix}/etc/liquidsoap
|
||||
liquidsoap=${exec_prefix}/bin/liquidsoap
|
||||
rundir=${prefix}/var/run/liquidsoap
|
||||
|
||||
depend() {
|
||||
after net icecast
|
||||
}
|
||||
|
||||
start() {
|
||||
cd $confdir
|
||||
for liq in *.liq ; do
|
||||
if test $liq != '*.liq' ; then
|
||||
ebegin "Starting $liq"
|
||||
start-stop-daemon --start --quiet --pidfile $rundir/${liq%.liq}.pid \
|
||||
--chuid $user:$group --exec $liquidsoap -- -d $confdir/$liq
|
||||
eend $?
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
stop() {
|
||||
cd $rundir
|
||||
for liq in *.pid ; do
|
||||
if test $liq != '*.pid' ; then
|
||||
ebegin "Stopping $liq"
|
||||
start-stop-daemon --stop --quiet --pidfile $liq
|
||||
eend $?
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
restart() {
|
||||
svc_stop
|
||||
einfo "Sleeping 4 seconds ..."
|
||||
sleep 4
|
||||
svc_start
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#!/sbin/runscript
|
||||
|
||||
user=@install_user@
|
||||
group=@install_group@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
confdir=@sysconfdir@/liquidsoap
|
||||
liquidsoap=@bindir@/liquidsoap
|
||||
rundir=@localstatedir@/run/liquidsoap
|
||||
|
||||
depend() {
|
||||
after net icecast
|
||||
}
|
||||
|
||||
start() {
|
||||
cd $confdir
|
||||
for liq in *.liq ; do
|
||||
if test $liq != '*.liq' ; then
|
||||
ebegin "Starting $liq"
|
||||
start-stop-daemon --start --quiet --pidfile $rundir/${liq%.liq}.pid \
|
||||
--chuid $user:$group --exec $liquidsoap -- -d $confdir/$liq
|
||||
eend $?
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
stop() {
|
||||
cd $rundir
|
||||
for liq in *.pid ; do
|
||||
if test $liq != '*.pid' ; then
|
||||
ebegin "Stopping $liq"
|
||||
start-stop-daemon --stop --quiet --pidfile $liq
|
||||
eend $?
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
restart() {
|
||||
svc_stop
|
||||
einfo "Sleeping 4 seconds ..."
|
||||
sleep 4
|
||||
svc_start
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: liquidsoap
|
||||
# Required-Start: $remote_fs $network $time
|
||||
# Required-Stop: $remote_fs $network $time
|
||||
# Should-Start:
|
||||
# Should-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Starts the liquidsoap daemon
|
||||
# Description:
|
||||
### END INIT INFO
|
||||
|
||||
user=liquidsoap
|
||||
group=liquidsoap
|
||||
prefix=/usr/local
|
||||
exec_prefix=${prefix}
|
||||
confdir=${prefix}/etc/liquidsoap
|
||||
liquidsoap=${exec_prefix}/bin/liquidsoap
|
||||
rundir=${prefix}/var/run/liquidsoap
|
||||
|
||||
# Test if $rundir exists
|
||||
if [ ! -d $rundir ]; then
|
||||
mkdir -p $rundir;
|
||||
chown $user:$group $rundir
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
stop)
|
||||
echo -n "Stopping channels: "
|
||||
cd $rundir
|
||||
for liq in *.pid ; do
|
||||
if test $liq != '*.pid' ; then
|
||||
echo -n "$liq "
|
||||
start-stop-daemon --stop --quiet --pidfile $liq --retry 4
|
||||
fi
|
||||
done
|
||||
echo "OK"
|
||||
;;
|
||||
|
||||
start)
|
||||
echo -n "Starting channels: "
|
||||
cd $confdir
|
||||
for liq in *.liq ; do
|
||||
if test $liq != '*.liq' ; then
|
||||
echo -n "$liq "
|
||||
start-stop-daemon --start --quiet --pidfile $rundir/${liq%.liq}.pid \
|
||||
--chuid $user:$group --exec $liquidsoap -- -d $confdir/$liq
|
||||
fi
|
||||
done
|
||||
echo "OK"
|
||||
;;
|
||||
|
||||
restart|force-reload)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|force-reload}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,63 @@
|
|||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: liquidsoap
|
||||
# Required-Start: $remote_fs $network $time
|
||||
# Required-Stop: $remote_fs $network $time
|
||||
# Should-Start:
|
||||
# Should-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Starts the liquidsoap daemon
|
||||
# Description:
|
||||
### END INIT INFO
|
||||
|
||||
user=@install_user@
|
||||
group=@install_group@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
confdir=@sysconfdir@/liquidsoap
|
||||
liquidsoap=@bindir@/liquidsoap
|
||||
rundir=@localstatedir@/run/liquidsoap
|
||||
|
||||
# Test if $rundir exists
|
||||
if [ ! -d $rundir ]; then
|
||||
mkdir -p $rundir;
|
||||
chown $user:$group $rundir
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
stop)
|
||||
echo -n "Stopping channels: "
|
||||
cd $rundir
|
||||
for liq in *.pid ; do
|
||||
if test $liq != '*.pid' ; then
|
||||
echo -n "$liq "
|
||||
start-stop-daemon --stop --quiet --pidfile $liq --retry 4
|
||||
fi
|
||||
done
|
||||
echo "OK"
|
||||
;;
|
||||
|
||||
start)
|
||||
echo -n "Starting channels: "
|
||||
cd $confdir
|
||||
for liq in *.liq ; do
|
||||
if test $liq != '*.liq' ; then
|
||||
echo -n "$liq "
|
||||
start-stop-daemon --start --quiet --pidfile $rundir/${liq%.liq}.pid \
|
||||
--chuid $user:$group --exec $liquidsoap -- -d $confdir/$liq
|
||||
fi
|
||||
done
|
||||
echo "OK"
|
||||
;;
|
||||
|
||||
restart|force-reload)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|force-reload}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,15 @@
|
|||
/usr/local/var/log/liquidsoap/*.log {
|
||||
compress
|
||||
rotate 5
|
||||
size 300k
|
||||
missingok
|
||||
notifempty
|
||||
sharedscripts
|
||||
postrotate
|
||||
for liq in /usr/local/var/run/liquidsoap/*.pid ; do
|
||||
if test $liq != '/usr/local/var/run/liquidsoap/*.pid' ; then
|
||||
start-stop-daemon --stop --signal USR1 --quiet --pidfile $liq
|
||||
fi
|
||||
done
|
||||
endscript
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
@localstatedir@/log/liquidsoap/*.log {
|
||||
compress
|
||||
rotate 5
|
||||
size 300k
|
||||
missingok
|
||||
notifempty
|
||||
sharedscripts
|
||||
postrotate
|
||||
for liq in @localstatedir@/run/liquidsoap/*.pid ; do
|
||||
if test $liq != '@localstatedir@/run/liquidsoap/*.pid' ; then
|
||||
start-stop-daemon --stop --signal USR1 --quiet --pidfile $liq
|
||||
fi
|
||||
done
|
||||
endscript
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This script is called from liquidsoap for generating a file
|
||||
# for "say:voice/text" URIs.
|
||||
# Usage: liquidtts text output_file voice
|
||||
|
||||
echo $1 | @TEXT2WAVE@ -f 44100 > $2.tmp.wav && @SOX@ 2> /dev/null > /dev/null
|
||||
return=$?
|
||||
@RM@ $2.tmp.wav
|
||||
@NORMALIZE@ $2 2> /dev/null > /dev/null
|
||||
exit $return
|
|
@ -41,7 +41,7 @@ def output.shoutcast(
|
|||
restart=restart, restart_delay=restart_delay,
|
||||
host=host, port=port, user=user, password=password,
|
||||
genre=genre, url=url, description="UNUSED",
|
||||
public=public, dumpfile=dumpfile,
|
||||
public=public, dumpfile=dumpfile,encoding="ISO-8859-1",
|
||||
name=name, mount="/", protocol="icy",
|
||||
fallible=fallible,on_start=on_start,on_stop=on_stop,
|
||||
s)
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
set("log.file",false)
|
||||
|
||||
echo = fun (x) -> system("echo "^quote(x))
|
||||
|
||||
def test(lbl,f)
|
||||
if f() then echo(lbl) else system("echo fail "^lbl) end
|
||||
end
|
||||
|
||||
test("1",{ 1==1 })
|
||||
test("2",{ 1+1==2 })
|
||||
test("3",{ (-1)+2==1 })
|
||||
test("4",{ (-1)+2 <= 3*2 })
|
||||
test("5",{ true })
|
||||
test("6",{ true and true })
|
||||
test("7",{ 1==1 and 1==1 })
|
||||
test("8",{ (1==1) and (1==1) })
|
||||
test("9",{ true and (-1)+2 <= 3*2 })
|
||||
|
||||
l = [ ("bla",""), ("bli","x"), ("blo","xx"), ("blu","xxx"), ("dix","10") ]
|
||||
echo(l["dix"])
|
||||
test("11",{ 2 == list.length(string.split(separator="",l["blo"])) })
|
||||
|
||||
%ifdef foobarbaz
|
||||
if = if is not a well-formed expression, and we do not care...
|
||||
%endif
|
||||
|
||||
echo("1#{1+1}")
|
||||
echo(string_of(int_of_float(float_of_string(default=13.,"blah"))))
|
||||
|
||||
f=fun(x)->x
|
||||
# Checking that the following is not recursive:
|
||||
f=fun(x)->f(x)
|
||||
print(f(14))
|
|
@ -0,0 +1,112 @@
|
|||
# Check these examples with: liquidsoap --no-libs -i -c typing.liq
|
||||
|
||||
# TODO Throughout this file, parsing locations displayed in error messages
|
||||
# are often much too inaccurate.
|
||||
|
||||
set("log.file",false)
|
||||
|
||||
# Check that some polymorphism is allowed.
|
||||
# id :: (string,'a)->'a
|
||||
def id(a,b)
|
||||
log(a)
|
||||
b
|
||||
end
|
||||
ignore("bla"==id("bla","bla"))
|
||||
ignore(0==id("zero",0))
|
||||
|
||||
# Reporting locations for the next error is non-trivial, because it is about
|
||||
# an instantiation of the type of id. The deep error doesn't have relevant
|
||||
# information about why the int should be a string, the outer one has.
|
||||
# id(0,0)
|
||||
|
||||
# Polymorphism is limited to outer generalizations, this is not system F.
|
||||
# apply :: ((string)->'a)->'a
|
||||
def apply(f)
|
||||
f("bla")
|
||||
# f is not polymorphic, the following is forbidden:
|
||||
# f(0)
|
||||
# f(f)
|
||||
end
|
||||
|
||||
# The level checks forbid abusive generalization.
|
||||
# id' :: ('a)->'a
|
||||
def id'(x)
|
||||
# If one isn't careful about levels/scoping, f2 gets the type ('a)->'b
|
||||
# and so does twisted_id.
|
||||
def f2(y)
|
||||
x
|
||||
end
|
||||
f2(x)
|
||||
end
|
||||
|
||||
# More errors...
|
||||
# 0=="0"
|
||||
# [3,""]
|
||||
|
||||
# Subtyping, functions and lists.
|
||||
f1 = fun () -> 3
|
||||
f2 = fun (a=1) -> a
|
||||
|
||||
# This is OK, l1 is a list of elements of type f1.
|
||||
l1 = [f1,f2]
|
||||
list.iter(fun (f) -> log(string_of(f())), l1)
|
||||
# Forbidden. Indeed, f1 doesn't accept any argument -- although f2 does.
|
||||
# Here the error message may even be too detailed since it goes back to the
|
||||
# definition of l1 and requires that f1 has type (int)->int.
|
||||
# list.iter(fun (f) -> log(string_of(f(42))), l1)
|
||||
|
||||
# Actually, this is forbidden too, but the reason is more complex...
|
||||
# The infered type for the function is ((int)->int)->unit,
|
||||
# and (int)->int is not a subtype of (?int)->int.
|
||||
# There's no most general answer here since (?int)->int is not a
|
||||
# subtype of (int)->int either.
|
||||
# list.iter(fun (f) -> log(string_of(f(42))), [f2])
|
||||
|
||||
# Unlike l1, this is not OK, since we don't leave open subtyping constraints
|
||||
# while infering types.
|
||||
# I hope we can make the inference smarter in the future, without obfuscating
|
||||
# the error messages too much.
|
||||
# The type error here shows the use of all the displayed positions:
|
||||
# f1 has type t1, f2 has type t2, t1 should be <: t2
|
||||
# l2 = [ f2, f1 ]
|
||||
|
||||
# An error where contravariance flips the roles of both sides..
|
||||
# [fun (x) -> x+1, fun (y) -> y^"."]
|
||||
|
||||
# An error without much locations..
|
||||
# TODO An explaination about the missing label would help a lot here.
|
||||
# def f(f)
|
||||
# f(output.icecast.vorbis)
|
||||
# f(output.icecast.mp3)
|
||||
# end
|
||||
|
||||
# This causes an occur-check error.
|
||||
# TODO The printing of the types breaks the sharing of one EVAR
|
||||
# across two types. Here the sharing is actually the origin of the occur-check
|
||||
# error. And it's not easy to understand..
|
||||
# omega = fun (x) -> x(x)
|
||||
|
||||
# Now let's test ad-hoc polymorphism.
|
||||
|
||||
echo = fun(x) -> system("echo #{quote(string_of(x))}")
|
||||
|
||||
echo("bla")
|
||||
echo((1,3.12))
|
||||
echo(1 + 1)
|
||||
echo(1. + 2.14)
|
||||
|
||||
# string is not a Num
|
||||
# echo("bl"+"a")
|
||||
|
||||
echo(1 <= 2)
|
||||
echo((1,2) == (1,3))
|
||||
|
||||
# float <> int
|
||||
# echo(1 == 2.)
|
||||
|
||||
# source is not an Ord
|
||||
# echo(blank()==blank())
|
||||
|
||||
def sum_eq(a,b)
|
||||
a+b == a
|
||||
end
|
|
@ -2,7 +2,7 @@
|
|||
# Turn a source into an infaillible source.
|
||||
# by adding blank when the source is not available.
|
||||
# @param s the source to turn infaillible
|
||||
# @category Source / Input
|
||||
# @category Source / Track Processing
|
||||
def mksafe(s)
|
||||
fallback(id="mksafe",track_sensitive=false,[s,blank(id="safe_blank")])
|
||||
end
|
||||
|
@ -87,11 +87,14 @@ end
|
|||
|
||||
# Removes all metadata coming from a source
|
||||
# @category Source / Track Processing
|
||||
def clear_metadata(s)
|
||||
def map(m)
|
||||
[]
|
||||
end
|
||||
map_metadata(map,update=false,strip=true,s)
|
||||
def drop_metadata(s)
|
||||
map_metadata(fun(_)->[],update=false,strip=true,insert_missing=false,s)
|
||||
end
|
||||
|
||||
# Merge all tracks from a source, provided that it does not fail
|
||||
# @category Source / Track Processing
|
||||
def merge_tracks(s)
|
||||
sequence(merge=true,[s])
|
||||
end
|
||||
|
||||
output.prefered=output.dummy
|
||||
|
@ -125,7 +128,7 @@ in = fun () -> blank()
|
|||
in = fun () -> input.portaudio(id="pa_mic")
|
||||
%endif
|
||||
# Create a source from the first available input driver in this list:
|
||||
# portaudio, alsa, oss, blank
|
||||
# portaudio, alsa, oss, blank.
|
||||
# @category Source / Input
|
||||
def in()
|
||||
in()
|
||||
|
@ -208,12 +211,6 @@ def say_metadata
|
|||
interactive=false))
|
||||
end
|
||||
|
||||
# Relay the audio stream of Dolebraï, a libre music netradio running liquidsoap.
|
||||
# @category Source / Input
|
||||
def dolebrai ()
|
||||
input.http(id="dolebrai","http://dolebrai.net:8000/dolebrai.ogg")
|
||||
end
|
||||
|
||||
%ifdef soundtouch
|
||||
# Increases the pitch, making voices sound like on helium.
|
||||
# @category Source / Sound Processing
|
||||
|
@ -237,6 +234,72 @@ def test_process(command)
|
|||
end
|
||||
end
|
||||
|
||||
# Split an url of the form foo?arg=bar&arg2=bar2
|
||||
# into ("foo",[("arg","bar"),("arg2","bar2")]
|
||||
# @category String
|
||||
# @param uri Url to split
|
||||
def url.split(uri) =
|
||||
ret = string.extract(pattern="([^\?]*)\?(.*)",uri)
|
||||
args = ret["2"]
|
||||
if args != "" then
|
||||
l = string.split(separator="&",args)
|
||||
def f(x) =
|
||||
ret = string.split(separator="=",x)
|
||||
(url.decode(list.nth(ret,0)),
|
||||
url.decode(list.nth(ret,1)))
|
||||
end
|
||||
l = list.map(f,l)
|
||||
(ret["1"],l)
|
||||
else
|
||||
(uri,[])
|
||||
end
|
||||
end
|
||||
|
||||
# Register a server/telnet command to
|
||||
# update a source's metadata. Returns
|
||||
# a new source, which will receive the
|
||||
# updated metadata. Semantics is the
|
||||
# same as pre 1.0 insert_metadata operator,
|
||||
# i.e. @insert key1="val1",key2="val2",..@
|
||||
# @category Source / Track Processing
|
||||
# @param ~id Force the value of the source ID.
|
||||
def server.insert_metadata(~id="",s) =
|
||||
x = insert_metadata(id=id,s)
|
||||
insert = fst(x)
|
||||
s = snd(x)
|
||||
def insert(s) =
|
||||
l = string.split(separator='([^=]+\s*=\s*"(\\"|[^"])*")\s*,\s*',s)
|
||||
def f(l,x) =
|
||||
sub = fun (s) -> string.replace(pattern='\\"',fun (_) -> '"',s)
|
||||
if x != "" then
|
||||
ret = string.extract(pattern='([^=]+)\s*=\s*"((?:\\"|[^"])*)"',x)
|
||||
if ret["1"] != "" then
|
||||
list.append(l,[(ret["1"],
|
||||
sub(ret["2"]))])
|
||||
else
|
||||
l
|
||||
end
|
||||
else
|
||||
l
|
||||
end
|
||||
end
|
||||
meta = list.fold(f,[],l)
|
||||
if meta != [] then
|
||||
insert(meta)
|
||||
"Done"
|
||||
else
|
||||
"Syntax error or no metadata given. \
|
||||
Use key1=\"val1\",key2=\"val2\",.."
|
||||
end
|
||||
end
|
||||
id = source.id(s)
|
||||
server.register(namespace="#{id}",
|
||||
description="Insert a metadata chunk.",
|
||||
usage="insert key1=\"val1\",key2=\"val2\",..",
|
||||
"insert",insert)
|
||||
s
|
||||
end
|
||||
|
||||
# Get the base name of a path.
|
||||
# Implemented using the corresponding shell command.
|
||||
# @category System
|
||||
|
@ -559,14 +622,18 @@ def enable_replaygain_metadata(
|
|||
end
|
||||
|
||||
# Create a log of clock times for all the clocks initially present.
|
||||
# The log is in simple format, which you can notably directly use with gnuplot.
|
||||
# The log is in a simple format which you can directly use with gnuplot.
|
||||
# @category Liquidsoap
|
||||
# @param ~interval Polling interval.
|
||||
def log_clocks(~interval=1.,logfile)
|
||||
# @param ~delay Delay before setting up the clock logger. This should \
|
||||
# be used to ensure that the logger starts only after \
|
||||
# the clocks are created.
|
||||
# @param unlabeled Path of the log file.
|
||||
def log_clocks(~delay=0.,~interval=1.,logfile)
|
||||
# Get the current clocks
|
||||
clocks = list.map(fst,get_clock_status())
|
||||
# Column headers
|
||||
system("echo \# #{string.concat(separator=' ',clocks)} > #{logfile}")
|
||||
system("echo \# #{string.concat(separator=' ',clocks)} > #{(logfile:string)}")
|
||||
def report()
|
||||
status = get_clock_status()
|
||||
status = list.map(fun (x) -> (fst(x),string_of(snd(x))), status)
|
||||
|
@ -574,5 +641,9 @@ def log_clocks(~interval=1.,logfile)
|
|||
system("echo #{string.concat(separator=' ',status)} >> #{logfile}")
|
||||
interval
|
||||
end
|
||||
add_timeout(interval,report)
|
||||
if delay<=0. then
|
||||
add_timeout(interval,report)
|
||||
else
|
||||
add_timeout(delay,{add_timeout(interval,report) (-1.)})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
# include configuration #
|
||||
########################################
|
||||
|
||||
%include "library/pervasives.liq"
|
||||
%include "ls_config.liq"
|
||||
%include "library.liq"
|
||||
%include "include_dynamic_vars.liq"
|
||||
|
@ -49,8 +50,9 @@ end
|
|||
#######################################################################
|
||||
silence = single("/opt/pypo/files/basic/silence.mp3")
|
||||
jingles_cc = playlist("/opt/pypo/files/jingles/jcc")
|
||||
fallback_couchcaster = playlist("/opt/pypo/files/fallback_couchcaster")
|
||||
fallback_couchcaster = audio_to_stereo(fallback_couchcaster)
|
||||
fallback_airtime = playlist("/opt/pypo/files/basic/silence-playlist.lsp")
|
||||
fallback_airtime = audio_to_stereo(fallback_airtime)
|
||||
|
||||
|
||||
# default
|
||||
default = silence
|
||||
|
@ -69,7 +71,7 @@ source = fallback(track_sensitive=false,transitions=[dp_to_scheduler],[strip_bla
|
|||
|
||||
%include "include_live_in.liq"
|
||||
|
||||
live = fallback(track_sensitive=false,[strip_blank(threshold=silence_threshold,length=silence_time,live),fallback_couchcaster])
|
||||
live = fallback(track_sensitive=false,[strip_blank(threshold=silence_threshold,length=silence_time,live),fallback_airtime])
|
||||
live = switch(track_sensitive=false, [({!live_active},live)])
|
||||
|
||||
source = fallback(track_sensitive=false,transitions=[to_live_s, to_scheduler_s],[live, source])
|
||||
|
|
Loading…
Reference in New Issue