Merge branch 'devel' of dev.sourcefabric.org:airtime into devel

This commit is contained in:
Rudi Grinberg 2012-08-20 16:23:15 -04:00
commit a993691c6a
18 changed files with 195 additions and 149 deletions

View File

@ -27,6 +27,7 @@ class WebstreamController extends Zend_Controller_Action
$webstream->setDbName("Untitled Webstream"); $webstream->setDbName("Untitled Webstream");
$this->view->ws = new Application_Model_Webstream($webstream); $this->view->ws = new Application_Model_Webstream($webstream);
$this->view->action = "new";
$this->view->html = $this->view->render('webstream/webstream.phtml'); $this->view->html = $this->view->render('webstream/webstream.phtml');
} }
@ -41,6 +42,7 @@ class WebstreamController extends Zend_Controller_Action
$webstream = CcWebstreamQuery::create()->findPK($id); $webstream = CcWebstreamQuery::create()->findPK($id);
$this->view->ws = new Application_Model_Webstream($webstream); $this->view->ws = new Application_Model_Webstream($webstream);
$this->view->action = "edit";
$this->view->html = $this->view->render('webstream/webstream.phtml'); $this->view->html = $this->view->render('webstream/webstream.phtml');
} }

View File

@ -893,7 +893,7 @@ class Application_Model_StoredFile
#something went wrong likely there wasn't enough space in the audio_stor to move the file too. #something went wrong likely there wasn't enough space in the audio_stor to move the file too.
#warn the user that the file wasn't uploaded and they should check if there is enough disk space. #warn the user that the file wasn't uploaded and they should check if there is enough disk space.
unlink($audio_file);//remove the file after failed rename unlink($audio_file);//remove the file after failed rename
$result = array("code" => 108, "message" => "The file was not uploaded, this error can occur if the computer hard drive does not have enough disk space."); $result = array("code" => 108, "message" => "The file was not uploaded, this error can occur if the computer hard drive does not have enough disk space or the stor directory does not have correct write permissions.");
} }
} else { } else {
$result = array("code" => 110, "message" => "This file appears to be corrupted and will not be added to media library."); $result = array("code" => 110, "message" => "This file appears to be corrupted and will not be added to media library.");

View File

@ -1,6 +1,6 @@
<button id="ws_new" class="ui-button ui-widget ui-state-default" role="button" aria-disabled="false">New</button> <button id="ws_new" class="ui-button ui-widget ui-state-default" role="button" aria-disabled="false">New</button>
<?php if (isset($this->ws)) : ?> <?php if (isset($this->ws)) : ?>
<button id="ws_delete" class="ui-button ui-widget ui-state-default" role="button" aria-disabled="false">Delete</button> <button id="ws_delete" class="ui-button ui-widget ui-state-default" <?php if ($this->action == "new"): ?>style="display:none;"<?php endif; ?> role="button" aria-disabled="false">Delete</button>
<?php endif; ?> <?php endif; ?>
<?php if (isset($this->ws)) : ?> <?php if (isset($this->ws)) : ?>

View File

@ -0,0 +1,11 @@
/var/log/airtime/zendphp.log {
compress
rotate 10
size 1000k
missingok
notifempty
sharedscripts
postrotate
chown www-data:www-data /var/log/airtime/
endscript
}

View File

@ -360,7 +360,6 @@ var AIRTIME = (function(AIRTIME){
appendAddButton(); appendAddButton();
appendModAddButton(); appendModAddButton();
removeButtonCheck(); removeButtonCheck();
} }
//sets events dynamically for playlist entries (each row in the playlist) //sets events dynamically for playlist entries (each row in the playlist)
@ -600,6 +599,9 @@ var AIRTIME = (function(AIRTIME){
var $ws_id = $("#ws_id"); var $ws_id = $("#ws_id");
$ws_id.attr("value", json.streamId); $ws_id.attr("value", json.streamId);
var $ws_id = $("#ws_delete");
$ws_id.show();
//redraw the library to show the new webstream //redraw the library to show the new webstream
redrawLib(); redrawLib();
} }

View File

@ -178,6 +178,9 @@ fi
if [ -e /etc/init.d/airtime-playout ]; then if [ -e /etc/init.d/airtime-playout ]; then
invoke-rc.d airtime-playout stop > /dev/null 2>&1 invoke-rc.d airtime-playout stop > /dev/null 2>&1
fi fi
if [ -e /etc/init.d/airtime-playout ]; then
invoke-rc.d airtime-liquidsoap stop > /dev/null 2>&1
fi
#export these variables to make them available in sub bash scripts #export these variables to make them available in sub bash scripts
export DO_UPGRADE export DO_UPGRADE

View File

@ -88,15 +88,16 @@ ln -sf /usr/lib/airtime/utils/airtime-test-stream /usr/bin/airtime-test-stream
echo "* Creating /var/log/airtime" echo "* Creating /var/log/airtime"
mkdir -p /var/log/airtime mkdir -p /var/log/airtime
chmod a+x /var/log/airtime chmod a+x /var/log/airtime
touch /var/log/airtime/zendphp.log chown www-data:www-data /var/log/airtime/
chown www-data:www-data /var/log/airtime/zendphp.log
chmod 644 /var/log/airtime/zendphp.log
if [ "$web" = "t" ]; then if [ "$web" = "t" ]; then
echo "* Creating /usr/share/airtime" echo "* Creating /usr/share/airtime"
rm -rf "/usr/share/airtime" rm -rf "/usr/share/airtime"
mkdir -p /usr/share/airtime mkdir -p /usr/share/airtime
cp -R $AIRTIMEROOT/airtime_mvc/* /usr/share/airtime/ cp -R $AIRTIMEROOT/airtime_mvc/* /usr/share/airtime/
rm -f /etc/logrotate.d/airtime-php
cp $AIRTIMEROOT/airtime_mvc/build/airtime-php.logrotate /etc/logrotate.d/airtime-php
fi fi
echo "* Creating /var/log/airtime" echo "* Creating /var/log/airtime"

View File

@ -0,0 +1,70 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: airtime-playout
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Liquidsoap daemon
### END INIT INFO
USERID=pypo
GROUPID=pypo
NAME="Liquidsoap Playout Engine"
DAEMON=/usr/lib/airtime/pypo/bin/airtime-liquidsoap
PIDFILE=/var/run/airtime-liquidsoap.pid
start () {
start-stop-daemon --start --background --quiet --chuid $USERID:$GROUPID \
--nicelevel -15 --make-pidfile --pidfile $PIDFILE --startas $DAEMON
monit monitor airtime-liquidsoap >/dev/null 2>&1
}
stop () {
monit unmonitor airtime-liquidsoap >/dev/null 2>&1
/usr/lib/airtime/airtime_virtualenv/bin/python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_prepare_terminate.py
# Send TERM after 5 seconds, wait at most 30 seconds.
start-stop-daemon --stop --oknodo --retry 5 --quiet --pidfile $PIDFILE
rm -f $PIDFILE
}
start_no_monit() {
start-stop-daemon --start --background --quiet --chuid $USERID:$USERID --make-pidfile --pidfile $PIDFILE --startas $DAEMON
}
case "${1:-''}" in
'stop')
echo -n "Stopping Liquidsoap: "
stop
echo "Done."
;;
'start')
echo -n "Starting Liquidsoap: "
start
echo "Done."
;;
'restart')
# restart commands here
echo -n "Restarting Liquidsoap: "
stop
start
echo "Done."
;;
'start-no-monit')
# restart commands here
echo -n "Starting $NAME: "
start_no_monit
echo "Done."
;;
*) # no parameter specified
echo "Usage: $SELF start|stop|restart"
exit 1
;;
esac

View File

@ -9,80 +9,30 @@
# Short-Description: Manage airtime-playout daemon # Short-Description: Manage airtime-playout daemon
### END INIT INFO ### END INIT INFO
USERID=pypo USERID=root
ROOTUSERID=root NAME="Airtime Scheduler Engine"
GROUPID=pypo
NAME=Airtime\ Playout
DAEMON0=/usr/lib/airtime/pypo/bin/airtime-playout DAEMON=/usr/lib/airtime/pypo/bin/airtime-playout
PIDFILE0=/var/run/airtime-playout.pid PIDFILE=/var/run/airtime-playout.pid
DAEMON1=/usr/lib/airtime/pypo/bin/airtime-liquidsoap
PIDFILE1=/var/run/airtime-liquidsoap.pid
liquidsoap_start () {
start-stop-daemon --start --background --quiet --chuid $USERID:$GROUPID \
--nicelevel -15 --make-pidfile --pidfile $PIDFILE1 --startas $DAEMON1
monit monitor airtime-liquidsoap >/dev/null 2>&1
}
liquidsoap_stop () {
monit unmonitor airtime-liquidsoap >/dev/null 2>&1
/usr/lib/airtime/airtime_virtualenv/bin/python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_prepare_terminate.py
# Send TERM after 5 seconds, wait at most 30 seconds.
start-stop-daemon --stop --oknodo --retry TERM/5/0/30 --quiet --pidfile $PIDFILE1
rm -f $PIDFILE1
}
stop_pypo () {
monit unmonitor airtime-playout >/dev/null 2>&1
# Send TERM after 5 seconds, wait at most 30 seconds.
start-stop-daemon --stop --oknodo --retry TERM/5/0/30 --quiet --pidfile $PIDFILE0
rm -f $PIDFILE0
}
start () { start () {
chown pypo:pypo /etc/airtime chown pypo:pypo /etc/airtime
chown pypo:pypo /etc/airtime/liquidsoap.cfg chown pypo:pypo /etc/airtime/liquidsoap.cfg
start-stop-daemon --start --background --quiet --chuid $ROOTUSERID:$ROOTUSERID --make-pidfile --pidfile $PIDFILE0 --startas $DAEMON0 start-stop-daemon --start --background --quiet --chuid $USERID:$USERID --make-pidfile --pidfile $PIDFILE --startas $DAEMON
monit monitor airtime-playout >/dev/null 2>&1 monit monitor airtime-playout >/dev/null 2>&1
liquidsoap_start
} }
stop () { stop () {
# Send TERM after 5 seconds, wait at most 30 seconds. # Send TERM after 5 seconds, wait at most 30 seconds.
monit unmonitor airtime-playout >/dev/null 2>&1 monit unmonitor airtime-playout >/dev/null 2>&1
start-stop-daemon --stop --oknodo --retry TERM/5/0/30 --quiet --pidfile $PIDFILE0 start-stop-daemon --stop --oknodo --retry TERM/5/0/30 --quiet --pidfile $PIDFILE
rm -f $PIDFILE0 rm -f $PIDFILE
liquidsoap_stop
}
monit_restart() {
start-stop-daemon --stop --oknodo --retry TERM/5/0/30 --quiet --pidfile $PIDFILE0
rm -f $PIDFILE0
/usr/lib/airtime/airtime_virtualenv/bin/python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_prepare_terminate.py
start-stop-daemon --stop --oknodo --retry TERM/5/0/30 --quiet --pidfile $PIDFILE1
rm -f $PIDFILE1
start-stop-daemon --start --background --quiet --chuid $ROOTUSERID:$ROOTUSERID --make-pidfile --pidfile $PIDFILE0 --startas $DAEMON0
start-stop-daemon --start --background --quiet --chuid $USERID:$GROUPID \
--nicelevel -15 --make-pidfile --pidfile $PIDFILE1 --startas $DAEMON1
} }
start_no_monit() { start_no_monit() {
start-stop-daemon --start --background --quiet --chuid $ROOTUSERID:$ROOTUSERID --make-pidfile --pidfile $PIDFILE0 --startas $DAEMON0 start-stop-daemon --start --background --quiet --chuid $USERID:$USERID --make-pidfile --pidfile $PIDFILE --startas $DAEMON
liquidsoap_start
} }
case "${1:-''}" in case "${1:-''}" in
@ -111,41 +61,13 @@ case "${1:-''}" in
start_no_monit start_no_monit
echo "Done." echo "Done."
;; ;;
'monit-restart')
# restart commands here
echo -n "Monit Restarting $NAME: "
monit_restart
echo "Done."
;;
'status') 'status')
# status commands here # status commands here
/usr/bin/airtime-check-system /usr/bin/airtime-check-system
;; ;;
'stop-liquidsoap')
echo -n "Stopping Liquidsoap: "
liquidsoap_stop
echo "Done."
;;
'start-liquidsoap')
echo -n "Starting Liquidsoap: "
liquidsoap_start
echo "Done."
;;
'restart-liquidsoap')
# restart commands here
echo -n "Restarting Liquidsoap: "
liquidsoap_stop
liquidsoap_start
echo "Done."
;;
'pypo-stop')
# restart commands here
echo -n "Restarting Pypo: "
stop_pypo
echo "Done."
;;
*) # no parameter specified *) # no parameter specified
echo "Usage: $SELF start|stop|restart|status" echo "Usage: $SELF start|stop|restart|status"
exit 1 exit 1
;; ;;
esac esac

View File

@ -98,6 +98,7 @@ try:
#copy init.d script #copy init.d script
shutil.copy(config["bin_dir"]+"/bin/airtime-playout-init-d", "/etc/init.d/airtime-playout") shutil.copy(config["bin_dir"]+"/bin/airtime-playout-init-d", "/etc/init.d/airtime-playout")
shutil.copy(config["bin_dir"]+"/bin/airtime-liquidsoap-init-d", "/etc/init.d/airtime-liquidsoap")
#copy log rotate script #copy log rotate script
shutil.copy(config["bin_dir"]+"/bin/liquidsoap_scripts/airtime-liquidsoap.logrotate", "/etc/logrotate.d/airtime-liquidsoap") shutil.copy(config["bin_dir"]+"/bin/liquidsoap_scripts/airtime-liquidsoap.logrotate", "/etc/logrotate.d/airtime-liquidsoap")

View File

@ -109,6 +109,7 @@ try:
if "airtime_service_start" in os.environ and os.environ["airtime_service_start"] == "t": if "airtime_service_start" in os.environ and os.environ["airtime_service_start"] == "t":
print "* Waiting for pypo processes to start..." print "* Waiting for pypo processes to start..."
subprocess.call("invoke-rc.d airtime-liquidsoap start-no-monit > /dev/null 2>&1", shell=True)
subprocess.call("invoke-rc.d airtime-playout start-no-monit > /dev/null 2>&1", shell=True) subprocess.call("invoke-rc.d airtime-playout start-no-monit > /dev/null 2>&1", shell=True)
except Exception, e: except Exception, e:

View File

@ -13,6 +13,6 @@ if dj_type == '--master':
elif dj_type == '--dj': elif dj_type == '--dj':
source_type = 'dj' source_type = 'dj'
response = api_clients.check_live_stream_auth(username, password, type) response = api_clients.check_live_stream_auth(username, password, source_type)
print response['msg'] print response['msg']

View File

@ -237,7 +237,7 @@ def add_skip_command(s)
server.register(namespace="source", server.register(namespace="source",
usage="skip", usage="skip",
description="Skip the current song.", description="Skip the current song.",
"skip",skip) "skip",fun(s) -> begin log("source.skip") skip(s) end)
end end
dyn_out = output.icecast(%wav, dyn_out = output.icecast(%wav,

View File

@ -57,55 +57,55 @@ ignore(output.dummy(stream_queue, fallible=true))
server.register(namespace="vars", server.register(namespace="vars",
"pypo_data", "pypo_data",
fun (s) -> begin pypo_data := s "Done" end) fun (s) -> begin log("vars.pypo_data") pypo_data := s "Done" end)
server.register(namespace="vars", server.register(namespace="vars",
"stream_metadata_type", "stream_metadata_type",
fun (s) -> begin stream_metadata_type := int_of_string(s) s end) fun (s) -> begin log("vars.stream_metadata_type") stream_metadata_type := int_of_string(s) s end)
server.register(namespace="vars", server.register(namespace="vars",
"show_name", "show_name",
fun (s) -> begin show_name := s s end) fun (s) -> begin log("vars.show_name") show_name := s s end)
server.register(namespace="vars", server.register(namespace="vars",
"station_name", "station_name",
fun (s) -> begin station_name := s s end) fun (s) -> begin log("vars.station_name") station_name := s s end)
server.register(namespace="vars", server.register(namespace="vars",
"bootup_time", "bootup_time",
fun (s) -> begin time := s s end) fun (s) -> begin log("vars.bootup_time") time := s s end)
server.register(namespace="streams", server.register(namespace="streams",
"connection_status", "connection_status",
fun (s) -> begin "1:#{!s1_connected},2:#{!s2_connected},3:#{!s3_connected}" end) fun (s) -> begin log("streams.connection_status") "1:#{!s1_connected},2:#{!s2_connected},3:#{!s3_connected}" end)
server.register(namespace="vars", server.register(namespace="vars",
"default_dj_fade", "default_dj_fade",
fun (s) -> begin default_dj_fade := float_of_string(s) s end) fun (s) -> begin log("vars.default_dj_fade") default_dj_fade := float_of_string(s) s end)
server.register(namespace="dynamic_source", server.register(namespace="dynamic_source",
description="Enable webstream output", description="Enable webstream output",
usage='start', usage='start',
"output_start", "output_start",
fun (s) -> begin webstream_enabled := true "enabled" end) fun (s) -> begin log("dynamic_source.output_start") webstream_enabled := true "enabled" end)
server.register(namespace="dynamic_source", server.register(namespace="dynamic_source",
description="Enable webstream output", description="Enable webstream output",
usage='stop', usage='stop',
"output_stop", "output_stop",
fun (s) -> begin webstream_enabled := false "disabled" end) fun (s) -> begin log("dynamic_source.output_stop") webstream_enabled := false "disabled" end)
server.register(namespace="dynamic_source", server.register(namespace="dynamic_source",
description="Set the cc_schedule row id", description="Set the cc_schedule row id",
usage="id <id>", usage="id <id>",
"id", "id",
set_dynamic_source_id) fun (s) -> begin log("dynamic_source.id") set_dynamic_source_id(s) end)
server.register(namespace="dynamic_source", server.register(namespace="dynamic_source",
description="Start a new dynamic source.", description="Start a new dynamic source.",
usage="start <uri>", usage="start <uri>",
"read_start", "read_start",
create_dynamic_source) fun (s) -> begin log("dynamic_source.read_start") create_dynamic_source(s) end)
server.register(namespace="dynamic_source", server.register(namespace="dynamic_source",
description="Stop a dynamic source.", description="Stop a dynamic source.",
usage="stop <uri>", usage="stop <uri>",
"read_stop", "read_stop",
destroy_dynamic_source) fun (s) -> begin log("dynamic_source.read_stop") destroy_dynamic_source(s) end)
default = amplify(id="silence_src", 0.00001, noise()) default = amplify(id="silence_src", 0.00001, noise())
default = rewrite_metadata([("artist","Airtime"), ("title", "offline")],default) default = rewrite_metadata([("artist","Airtime"), ("title", "offline")], default)
ignore(output.dummy(default, fallible=true)) ignore(output.dummy(default, fallible=true))
master_dj_enabled = ref false master_dj_enabled = ref false
@ -160,19 +160,18 @@ end
#auth function for live stream #auth function for live stream
def check_master_dj_client(user,password) = def check_master_dj_client(user,password) =
log("master connected")
#get the output of the php script #get the output of the php script
ret = get_process_lines("python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_auth.py --master #{user} #{password}") ret = get_process_lines("python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_auth.py --master #{user} #{password}")
#ret has now the value of the live client (dj1,dj2, or djx), or "ERROR"/"unknown" ... #ret has now the value of the live client (dj1,dj2, or djx), or "ERROR"/"unknown" ...
ret = list.hd(ret) ret = list.hd(ret)
#return true to let the client transmit data, or false to tell harbor to decline #return true to let the client transmit data, or false to tell harbor to decline
if (ret == "True") then ret == "True"
true
else
false
end
end end
def check_dj_client(user,password) = def check_dj_client(user,password) =
log("live dj connected")
#get the output of the php script #get the output of the php script
ret = get_process_lines("python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_auth.py --dj #{user} #{password}") ret = get_process_lines("python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_auth.py --dj #{user} #{password}")
#ret has now the value of the live client (dj1,dj2, or djx), or "ERROR"/"unknown" ... #ret has now the value of the live client (dj1,dj2, or djx), or "ERROR"/"unknown" ...
@ -223,32 +222,32 @@ server.register(namespace="streams",
description="Stop Master DJ source.", description="Stop Master DJ source.",
usage="master_dj_stop", usage="master_dj_stop",
"master_dj_stop", "master_dj_stop",
fun (s) -> begin make_master_dj_unavailable() "Done." end) fun (s) -> begin log("streams.master_dj_stop") make_master_dj_unavailable() "Done." end)
server.register(namespace="streams", server.register(namespace="streams",
description="Start Master DJ source.", description="Start Master DJ source.",
usage="master_dj_start", usage="master_dj_start",
"master_dj_start", "master_dj_start",
fun (s) -> begin make_master_dj_available() "Done." end) fun (s) -> begin log("streams.master_dj_start") make_master_dj_available() "Done." end)
server.register(namespace="streams", server.register(namespace="streams",
description="Stop Live DJ source.", description="Stop Live DJ source.",
usage="live_dj_stop", usage="live_dj_stop",
"live_dj_stop", "live_dj_stop",
fun (s) -> begin make_live_dj_unavailable() "Done." end) fun (s) -> begin log("streams.live_dj_stop") make_live_dj_unavailable() "Done." end)
server.register(namespace="streams", server.register(namespace="streams",
description="Start Live DJ source.", description="Start Live DJ source.",
usage="live_dj_start", usage="live_dj_start",
"live_dj_start", "live_dj_start",
fun (s) -> begin make_live_dj_available() "Done." end) fun (s) -> begin log("streams.live_dj_start") make_live_dj_available() "Done." end)
server.register(namespace="streams", server.register(namespace="streams",
description="Stop Scheduled Play source.", description="Stop Scheduled Play source.",
usage="scheduled_play_stop", usage="scheduled_play_stop",
"scheduled_play_stop", "scheduled_play_stop",
fun (s) -> begin make_scheduled_play_unavailable() "Done." end) fun (s) -> begin log("streams.scheduled_play_stop") make_scheduled_play_unavailable() "Done." end)
server.register(namespace="streams", server.register(namespace="streams",
description="Start Scheduled Play source.", description="Start Scheduled Play source.",
usage="scheduled_play_start", usage="scheduled_play_start",
"scheduled_play_start", "scheduled_play_start",
fun (s) -> begin make_scheduled_play_available() "Done." end) fun (s) -> begin log("streams.scheduled_play_start") make_scheduled_play_available() "Done." end)
if output_sound_device then if output_sound_device then
@ -303,7 +302,7 @@ if s1_enable == true then
else else
s1_namespace := s1_mount s1_namespace := s1_mount
end end
server.register(namespace=!s1_namespace, "connected", fun (s) -> begin !s1_connected end) server.register(namespace=!s1_namespace, "connected", fun (s) -> begin log("#{!s1_namespace}.connected") !s1_connected end)
output_to(s1_output, s1_type, s1_bitrate, s1_host, s1_port, s1_pass, s1_mount, s1_url, s1_description, s1_genre, s1_user, s, "1", s1_connected, s1_description) output_to(s1_output, s1_type, s1_bitrate, s1_host, s1_port, s1_pass, s1_mount, s1_url, s1_description, s1_genre, s1_user, s, "1", s1_connected, s1_description)
end end
@ -313,7 +312,7 @@ if s2_enable == true then
else else
s2_namespace := s2_mount s2_namespace := s2_mount
end end
server.register(namespace=!s2_namespace, "connected", fun (s) -> begin !s2_connected end) server.register(namespace=!s2_namespace, "connected", fun (s) -> begin log("#{!s2_namespace}.connected") !s2_connected end)
output_to(s2_output, s2_type, s2_bitrate, s2_host, s2_port, s2_pass, s2_mount, s2_url, s2_description, s2_genre, s2_user, s, "2", s2_connected, s2_description) output_to(s2_output, s2_type, s2_bitrate, s2_host, s2_port, s2_pass, s2_mount, s2_url, s2_description, s2_genre, s2_user, s, "2", s2_connected, s2_description)
end end
@ -324,7 +323,7 @@ if s3_enable == true then
else else
s3_namespace := s3_mount s3_namespace := s3_mount
end end
server.register(namespace=!s3_namespace, "connected", fun (s) -> begin !s3_connected end) server.register(namespace=!s3_namespace, "connected", fun (s) -> begin log("#{!s3_namespace}.connected") !s3_connected end)
output_to(s3_output, s3_type, s3_bitrate, s3_host, s3_port, s3_pass, s3_mount, s3_url, s3_description, s3_genre, s3_user, s, "3", s3_connected, s3_description) output_to(s3_output, s3_type, s3_bitrate, s3_host, s3_port, s3_pass, s3_mount, s3_url, s3_description, s3_genre, s3_user, s, "3", s3_connected, s3_description)
end end

View File

@ -5,5 +5,5 @@
check process airtime-liquidsoap check process airtime-liquidsoap
with pidfile "/var/run/airtime-liquidsoap.pid" with pidfile "/var/run/airtime-liquidsoap.pid"
start program = "/etc/init.d/airtime-playout monit-restart" with timeout 5 seconds start program = "/etc/init.d/airtime-liquidsoap start" with timeout 5 seconds
stop program = "/etc/init.d/airtime-playout stop" stop program = "/etc/init.d/airtime-playout stop"

View File

@ -130,7 +130,7 @@ def liquidsoap_running_test(telnet_lock, host, port, logger):
msg = "version\n" msg = "version\n"
tn.write(msg) tn.write(msg)
tn.write("exit\n") tn.write("exit\n")
logger.info("Liquidsoap version %s", tn.read_all()) logger.info("Found: %s", tn.read_all())
except Exception, e: except Exception, e:
logger.error(str(e)) logger.error(str(e))
success = False success = False
@ -210,7 +210,7 @@ if __name__ == '__main__':
recorder.start() recorder.start()
# all join() are commented out because we want to exit entire pypo # all join() are commented out because we want to exit entire pypo
# if pypofetch is exiting # if pypofetch is exiting
#pmh.join() #pmh.join()
#recorder.join() #recorder.join()
#pp.join() #pp.join()

View File

@ -8,6 +8,7 @@ import json
import telnetlib import telnetlib
import copy import copy
from threading import Thread from threading import Thread
import subprocess
from Queue import Empty from Queue import Empty
@ -86,7 +87,7 @@ class PypoFetch(Thread):
self.process_schedule(self.schedule_data) self.process_schedule(self.schedule_data)
elif command == 'update_stream_setting': elif command == 'update_stream_setting':
self.logger.info("Updating stream setting...") self.logger.info("Updating stream setting...")
self.regenerateLiquidsoapConf(m['setting']) self.regenerate_liquidsoap_conf(m['setting'])
elif command == 'update_stream_format': elif command == 'update_stream_format':
self.logger.info("Updating stream format...") self.logger.info("Updating stream format...")
self.update_liquidsoap_stream_format(m['stream_format']) self.update_liquidsoap_stream_format(m['stream_format'])
@ -142,14 +143,14 @@ class PypoFetch(Thread):
def switch_source(logger, lock, sourcename, status): def switch_source(logger, lock, sourcename, status):
logger.debug('Switching source: %s to "%s" status', sourcename, status) logger.debug('Switching source: %s to "%s" status', sourcename, status)
command = "streams." command = "streams."
if(sourcename == "master_dj"): if sourcename == "master_dj":
command += "master_dj_" command += "master_dj_"
elif(sourcename == "live_dj"): elif sourcename == "live_dj":
command += "live_dj_" command += "live_dj_"
elif(sourcename == "scheduled_play"): elif sourcename == "scheduled_play":
command += "scheduled_play_" command += "scheduled_play_"
if(status == "on"): if status == "on":
command += "start\n" command += "start\n"
else: else:
command += "stop\n" command += "stop\n"
@ -204,12 +205,41 @@ class PypoFetch(Thread):
fh.write(api_client.encode_to(buffer_str)) fh.write(api_client.encode_to(buffer_str))
fh.write("log_file = \"/var/log/airtime/pypo-liquidsoap/<script>.log\"\n"); fh.write("log_file = \"/var/log/airtime/pypo-liquidsoap/<script>.log\"\n");
fh.close() fh.close()
# restarting pypo.
# we could just restart liquidsoap but it take more time somehow.
self.logger.info("Restarting pypo...")
sys.exit(0)
def regenerateLiquidsoapConf(self, setting): def restart_liquidsoap(self):
self.telnet_lock.acquire()
try:
self.logger.info("Restarting Liquidsoap")
subprocess.call('/etc/init.d/airtime-liquidsoap restart', shell=True)
#Wait here and poll Liquidsoap until it has started up
self.logger.info("Waiting for Liquidsoap to start")
while True:
try:
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
tn.write("exit\n")
tn.read_all()
self.logger.info("Liquidsoap is up and running")
break
except Exception, e:
#sleep 0.5 seconds and try again
time.sleep(0.5)
except Exception, e:
self.logger.error(e)
finally:
self.telnet_lock.release()
try:
self.set_bootstrap_variables()
#get the most up to date schedule, which will #initiate the process
#of making sure Liquidsoap is playing the schedule
self.manual_schedule_fetch()
except Exception, e:
self.logger.error(str(e))
def regenerate_liquidsoap_conf(self, setting):
existing = {} existing = {}
# create a temp file # create a temp file
@ -218,7 +248,8 @@ class PypoFetch(Thread):
fh = open('/etc/airtime/liquidsoap.cfg', 'r') fh = open('/etc/airtime/liquidsoap.cfg', 'r')
except IOError, e: except IOError, e:
#file does not exist #file does not exist
self.write_liquidsoap_config(setting) self.restart_liquidsoap()
return
self.logger.info("Reading existing config...") self.logger.info("Reading existing config...")
# read existing conf file and build dict # read existing conf file and build dict
@ -246,10 +277,10 @@ class PypoFetch(Thread):
existing[key] = value existing[key] = value
fh.close() fh.close()
# dict flag for any change in cofig # dict flag for any change in config
change = {} change = {}
# this flag is to detect disable -> disable change # this flag is to detect disable -> disable change
# in that case, we don't want to restart even if there are chnges. # in that case, we don't want to restart even if there are changes.
state_change_restart = {} state_change_restart = {}
#restart flag #restart flag
restart = False restart = False
@ -284,7 +315,7 @@ class PypoFetch(Thread):
if stream not in change: if stream not in change:
change[stream] = False change[stream] = False
if not (s[u'value'] == existing[s[u'keyname']]): if not (s[u'value'] == existing[s[u'keyname']]):
self.logger.info("Keyname: %s, Curent value: %s, New Value: %s", s[u'keyname'], existing[s[u'keyname']], s[u'value']) self.logger.info("Keyname: %s, Current value: %s, New Value: %s", s[u'keyname'], existing[s[u'keyname']], s[u'value'])
change[stream] = True change[stream] = True
# set flag change for sound_device alway True # set flag change for sound_device alway True
@ -298,21 +329,21 @@ class PypoFetch(Thread):
restart = True restart = True
# rewrite # rewrite
if restart: if restart:
self.write_liquidsoap_config(setting) self.restart_liquidsoap()
else: else:
self.logger.info("No change detected in setting...") self.logger.info("No change detected in setting...")
self.update_liquidsoap_connection_status() self.update_liquidsoap_connection_status()
def update_liquidsoap_connection_status(self): def update_liquidsoap_connection_status(self):
""" """
updates the status of liquidsoap connection to the streaming server updates the status of Liquidsoap connection to the streaming server
This fucntion updates the bootup time variable in liquidsoap script This function updates the bootup time variable in Liquidsoap script
""" """
self.telnet_lock.acquire() self.telnet_lock.acquire()
try: try:
tn = telnetlib.Telnet(LS_HOST, LS_PORT) tn = telnetlib.Telnet(LS_HOST, LS_PORT)
# update the boot up time of liquidsoap. Since liquidsoap is not restarting, # update the boot up time of Liquidsoap. Since Liquidsoap is not restarting,
# we are manually adjusting the bootup time variable so the status msg will get # we are manually adjusting the bootup time variable so the status msg will get
# updated. # updated.
current_time = time.time() current_time = time.time()
@ -474,13 +505,18 @@ class PypoFetch(Thread):
except Exception, e: except Exception, e:
self.logger.error(e) self.logger.error(e)
def manual_schedule_fetch(self):
success, self.schedule_data = self.api_client.get_schedule()
if success:
self.process_schedule(self.schedule_data)
return success
def main(self): def main(self):
# Bootstrap: since we are just starting up, we need to grab the # Bootstrap: since we are just starting up, we need to grab the
# most recent schedule. After that we can just wait for updates. # most recent schedule. After that we can just wait for updates.
success, self.schedule_data = self.api_client.get_schedule() success = self.manual_schedule_fetch()
if success: if success:
self.logger.info("Bootstrap schedule received: %s", self.schedule_data) self.logger.info("Bootstrap schedule received: %s", self.schedule_data)
self.process_schedule(self.schedule_data)
self.set_bootstrap_variables() self.set_bootstrap_variables()
loops = 1 loops = 1
@ -506,9 +542,7 @@ class PypoFetch(Thread):
self.handle_message(message) self.handle_message(message)
except Empty, e: except Empty, e:
self.logger.info("Queue timeout. Fetching schedule manually") self.logger.info("Queue timeout. Fetching schedule manually")
success, self.schedule_data = self.api_client.get_schedule() self.manual_schedule_fetch()
if success:
self.process_schedule(self.schedule_data)
except Exception, e: except Exception, e:
import traceback import traceback
top = traceback.format_exc() top = traceback.format_exc()

View File

@ -390,7 +390,7 @@ class PypoPush(Thread):
elif media_item['type'] == 'stream_buffer_start': elif media_item['type'] == 'stream_buffer_start':
self.start_web_stream_buffer(media_item) self.start_web_stream_buffer(media_item)
elif media_item['type'] == "stream": elif media_item['type'] == "stream":
if media_item['row_id'] != self.current_prebuffering_stream_id if media_item['row_id'] != self.current_prebuffering_stream_id:
#this is called if the stream wasn't scheduled sufficiently ahead of time #this is called if the stream wasn't scheduled sufficiently ahead of time
#so that the prebuffering stage could take effect. Let's do the prebuffering now. #so that the prebuffering stage could take effect. Let's do the prebuffering now.
self.start_web_stream_buffer(media_item) self.start_web_stream_buffer(media_item)