Merge branch '2.4.x'

Conflicts:
	airtime_mvc/public/js/airtime/showbuilder/builder.js
	python_apps/pypo/liquidsoap_scripts/fdkaac.liq
	python_apps/pypo/schedule/pypofetch.py
	python_apps/pypo/schedule/telnetliquidsoap.py
This commit is contained in:
Martin Konecny 2013-06-14 16:45:52 -04:00
commit 2a0c9769aa
40 changed files with 3341 additions and 3801 deletions

View file

@ -1,5 +1,6 @@
import pyinotify
import time
import os
from pydispatch import dispatcher
from os.path import normpath
@ -186,13 +187,12 @@ class Manager(Loggable):
try: mmp.create_dir(path)
except mmp.FailedToCreateDir as e: self.unexpected_exception(e)
os.chmod(store_paths['organize'], 0775)
self.set_problem_files_path(store_paths['problem_files'])
self.set_imported_path(store_paths['imported'])
self.set_recorded_path(store_paths['recorded'])
self.set_organize_path(store_paths['organize'])
mmp.create_dir(store)
for p in store_paths.values():
mmp.create_dir(p)
def has_watch(self, path):
""" returns true if the path is being watched or not. Any kind

View file

@ -4,6 +4,5 @@
set httpd port 2812
check process airtime-liquidsoap with pidfile "/var/run/airtime-liquidsoap.pid"
if does not exist for 3 cycles then restart
start program = "/etc/init.d/airtime-liquidsoap start" with timeout 5 seconds
stop program = "/etc/init.d/airtime-liquidsoap stop"

View file

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

View file

@ -1,24 +1,24 @@
if bitrate == 24 then
ignore(output_stereo(%fdkaac(bitrate = 24), !source))
ignore(output_stereo(%fdkaac(bitrate = 24, aot="mpeg4_he_aac_v2"), !source))
elsif bitrate == 32 then
ignore(output_stereo(%fdkaac(bitrate = 32), !source))
ignore(output_stereo(%fdkaac(bitrate = 32, aot="mpeg4_he_aac_v2"), !source))
elsif bitrate == 48 then
ignore(output_stereo(%fdkaac(bitrate = 48), !source))
ignore(output_stereo(%fdkaac(bitrate = 48, aot="mpeg4_he_aac_v2"), !source))
elsif bitrate == 64 then
ignore(output_stereo(%fdkaac(bitrate = 64), !source))
ignore(output_stereo(%fdkaac(bitrate = 64, aot="mpeg4_he_aac_v2"), !source))
elsif bitrate == 96 then
ignore(output_stereo(%fdkaac(bitrate = 96), !source))
ignore(output_stereo(%fdkaac(bitrate = 96, aot="mpeg4_he_aac_v2"), !source))
elsif bitrate == 128 then
ignore(output_stereo(%fdkaac(bitrate = 128), !source))
ignore(output_stereo(%fdkaac(bitrate = 128, aot="mpeg4_he_aac_v2"), !source))
elsif bitrate == 160 then
ignore(output_stereo(%fdkaac(bitrate = 160), !source))
ignore(output_stereo(%fdkaac(bitrate = 160, aot="mpeg4_he_aac_v2"), !source))
elsif bitrate == 192 then
ignore(output_stereo(%fdkaac(bitrate = 192), !source))
ignore(output_stereo(%fdkaac(bitrate = 192, aot="mpeg4_he_aac_v2"), !source))
elsif bitrate == 224 then
ignore(output_stereo(%fdkaac(bitrate = 224), !source))
ignore(output_stereo(%fdkaac(bitrate = 224, aot="mpeg4_he_aac_v2"), !source))
elsif bitrate == 256 then
ignore(output_stereo(%fdkaac(bitrate = 256), !source))
ignore(output_stereo(%fdkaac(bitrate = 256, aot="mpeg4_he_aac_v2"), !source))
elsif bitrate == 320 then
ignore(output_stereo(%fdkaac(bitrate = 320), !source))
ignore(output_stereo(%fdkaac(bitrate = 320, aot="mpeg4_he_aac_v2"), !source))
end

View file

@ -1,10 +1,15 @@
def notify(m)
#current_media_id := string_of(m['schedule_table_id'])
command = "/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --media-id=#{m['schedule_table_id']} &"
log(command)
system(command)
end
def notify_queue(m)
f = !dynamic_metadata_callback
ignore(f(m))
notify(m)
end
def notify_stream(m)
json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m))
#if a string has a single apostrophe in it, let's comment it out by ending the string before right before it
@ -18,12 +23,19 @@ end
# A function applied to each metadata chunk
def append_title(m) =
log("Using stream_format #{!stream_metadata_type}")
if !stream_metadata_type == 1 then
[("title", "#{!show_name} - #{m['artist']} - #{m['title']}")]
elsif !stream_metadata_type == 2 then
[("title", "#{!station_name} - #{!show_name}")]
if list.mem_assoc("mapped", m) then
#protection against applying this function twice. It shouldn't be happening
#and bug file with Liquidsoap.
m
else
[("title", "#{m['artist']} - #{m['title']}")]
if !stream_metadata_type == 1 then
[("title", "#{!show_name} - #{m['artist']} - #{m['title']}"), ("mapped", "true")]
elsif !stream_metadata_type == 2 then
[("title", "#{!station_name} - #{!show_name}"), ("mapped", "true")]
else
[("title", "#{m['artist']} - #{m['title']}"), ("mapped", "true")]
end
end
end

View file

@ -24,6 +24,8 @@ default_dj_fade = ref 0.
station_name = ref ''
show_name = ref ''
dynamic_metadata_callback = ref fun (s) -> begin () end
s1_connected = ref ''
s2_connected = ref ''
s3_connected = ref ''
@ -47,7 +49,7 @@ def create_source()
# the crossfade function controls fade in/out
l = crossfade_airtime(l)
l = on_metadata(notify, l)
l = on_metadata(notify_queue, l)
sources := list.append([l], !sources)
server.register(namespace="queues",
"s#{!source_id}_skip",
@ -70,6 +72,10 @@ create_source()
queue = add(!sources, normalize=false)
pair = insert_metadata(queue)
dynamic_metadata_callback := fst(pair)
queue = snd(pair)
output.dummy(fallible=true, queue)
http = input.http_restart(id="http")

View file

@ -25,6 +25,7 @@ from recorder import Recorder
from listenerstat import ListenerStat
from pypomessagehandler import PypoMessageHandler
from pypoliquidsoap import PypoLiquidsoap
from timeout import ls_timeout
from media.update.replaygainupdater import ReplayGainUpdater
from media.update.silananalyzer import SilanAnalyzer
@ -156,6 +157,7 @@ def keyboardInterruptHandler(signum, frame):
logger.info('\nKeyboard Interrupt\n')
sys.exit(0)
@ls_timeout
def liquidsoap_get_info(telnet_lock, host, port, logger):
logger.debug("Checking to see if Liquidsoap is running")
try:

View file

@ -2,6 +2,7 @@
from datetime import datetime
from datetime import timedelta
from configobj import ConfigObj
import sys
import time
@ -21,7 +22,7 @@ from threading import Thread
from api_clients import api_client
from std_err_override import LogWriter
from configobj import ConfigObj
from timeout import ls_timeout
# configure logging
@ -114,44 +115,6 @@ class PypoPush(Thread):
return present, future
def get_current_stream_id_from_liquidsoap(self):
response = "-1"
try:
self.telnet_lock.acquire()
tn = telnetlib.Telnet(self.config['ls_host'], self.config['ls_port'])
msg = 'dynamic_source.get_id\n'
tn.write(msg)
response = tn.read_until("\r\n").strip(" \r\n")
tn.write('exit\n')
tn.read_all()
except Exception, e:
self.logger.error("Error connecting to Liquidsoap: %s", e)
response = []
finally:
self.telnet_lock.release()
return response
#def is_correct_current_item(self, media_item, liquidsoap_queue_approx, liquidsoap_stream_id):
#correct = False
#if media_item is None:
#correct = (len(liquidsoap_queue_approx) == 0 and liquidsoap_stream_id == "-1")
#else:
#if is_file(media_item):
#if len(liquidsoap_queue_approx) == 0:
#correct = False
#else:
#correct = liquidsoap_queue_approx[0]['start'] == media_item['start'] and \
#liquidsoap_queue_approx[0]['row_id'] == media_item['row_id'] and \
#liquidsoap_queue_approx[0]['end'] == media_item['end'] and \
#liquidsoap_queue_approx[0]['replay_gain'] == media_item['replay_gain']
#elif is_stream(media_item):
#correct = liquidsoap_stream_id == str(media_item['row_id'])
#self.logger.debug("Is current item correct?: %s", str(correct))
#return correct
def date_interval_to_seconds(self, interval):
"""
Convert timedelta object into int representing the number of seconds. If
@ -162,6 +125,7 @@ class PypoPush(Thread):
return seconds
@ls_timeout
def stop_web_stream_all(self):
try:
self.telnet_lock.acquire()

View file

@ -34,6 +34,7 @@ from subprocess import Popen, PIPE
from api_clients import api_client
from std_err_override import LogWriter
from timeout import ls_timeout
import pure
@ -55,6 +56,8 @@ class PypoFetch(Thread):
def __init__(self, pypoFetch_q, pypoPush_q, media_q, pypo_liquidsoap,
config):
Thread.__init__(self)
#Hacky...
PypoFetch.ref = self
self.api_client = api_client.AirtimeApiClient()
self.fetch_queue = pypoFetch_q
@ -198,15 +201,23 @@ class PypoFetch(Thread):
commands.append(('vars.default_dj_fade %s\n' % fade).encode('utf-8'))
self.pypo_liquidsoap.get_telnet_dispatcher().telnet_send(commands)
self.pypo_liquidsoap.clear_all_queues()
self.pypo_liquidsoap.clear_queue_tracker()
def restart_liquidsoap(self):
self.logger.info("Restarting Liquidsoap")
subprocess.call(['/etc/init.d/airtime-liquidsoap', 'restart'])
self.telnet_lock.acquire(False)
#Wait here and poll Liquidsoap until it has started up
self.logger.info("Waiting for Liquidsoap to start")
self.pypo_liquidsoap.liquidsoap_startup_test()
try:
self.logger.info("Restarting Liquidsoap")
subprocess.call(['/etc/init.d/airtime-liquidsoap', 'restart'])
#Wait here and poll Liquidsoap until it has started up
self.logger.info("Waiting for Liquidsoap to start")
self.pypo_liquidsoap.liquidsoap_startup_test()
except Exception, e:
self.logger.error(e)
finally:
self.telnet_lock.release()
"""
TODO: This function needs to be way shorter, and refactored :/ - MK
@ -306,6 +317,7 @@ class PypoFetch(Thread):
self.logger.info("No change detected in setting...")
self.update_liquidsoap_connection_status()
@ls_timeout
def update_liquidsoap_connection_status(self):
"""
updates the status of Liquidsoap connection to the streaming server
@ -333,6 +345,7 @@ class PypoFetch(Thread):
self.api_client.notify_liquidsoap_status("OK", stream_id,
str(fake_time))
"""
Process the schedule
- Reads the scheduled entries of a given range (actual time +/-

View file

@ -9,6 +9,7 @@
"""
import telnetlib
from threading import Lock
from timeout import ls_timeout
def create_liquidsoap_annotation(media):
# We need liq_start_next value in the annotate. That is the value that
@ -48,6 +49,7 @@ class TelnetLiquidsoap:
else:
raise Exception("Unexpected list length returned: %s" % output)
@ls_timeout
def queue_clear_all(self):
with self.telnet_lock:
tn = self.__connect()
@ -60,6 +62,7 @@ class TelnetLiquidsoap:
tn.write("exit\n")
self.logger.debug(tn.read_all())
@ls_timeout
def queue_remove(self, queue_id):
with self.telnet_lock:
tn = self.__connect()
@ -71,6 +74,7 @@ class TelnetLiquidsoap:
tn.write("exit\n")
self.logger.debug(tn.read_all())
@ls_timeout
def queue_push(self, queue_id, media_item):
with self.telnet_lock:
if not self.__is_empty(queue_id):
@ -90,6 +94,7 @@ class TelnetLiquidsoap:
tn.write("exit\n")
self.logger.debug(tn.read_all())
@ls_timeout
def stop_web_stream_buffer(self):
with self.telnet_lock:
tn = self.__connect()
@ -105,6 +110,7 @@ class TelnetLiquidsoap:
tn.write("exit\n")
self.logger.debug(tn.read_all())
@ls_timeout
def stop_web_stream_output(self):
with self.telnet_lock:
tn = self.__connect()
@ -116,6 +122,8 @@ class TelnetLiquidsoap:
tn.write("exit\n")
self.logger.debug(tn.read_all())
@ls_timeout
def start_web_stream(self, media_item):
with self.telnet_lock:
tn = self.__connect()
@ -133,6 +141,7 @@ class TelnetLiquidsoap:
self.current_prebuffering_stream_id = None
@ls_timeout
def start_web_stream_buffer(self, media_item):
with self.telnet_lock:
tn = self.__connect()
@ -150,6 +159,7 @@ class TelnetLiquidsoap:
self.current_prebuffering_stream_id = media_item['row_id']
@ls_timeout
def get_current_stream_id(self):
with self.telnet_lock:
tn = self.__connect()
@ -164,6 +174,7 @@ class TelnetLiquidsoap:
return stream_id
@ls_timeout
def disconnect_source(self, sourcename):
self.logger.debug('Disconnecting source: %s', sourcename)
command = ""
@ -179,6 +190,7 @@ class TelnetLiquidsoap:
tn.write('exit\n')
tn.read_all()
@ls_timeout
def telnet_send(self, commands):
with self.telnet_lock:
tn = self.__connect()
@ -189,6 +201,7 @@ class TelnetLiquidsoap:
tn.write('exit\n')
tn.read_all()
@ls_timeout
def switch_source(self, sourcename, status):
self.logger.debug('Switching source: %s to "%s" status', sourcename,
status)
@ -207,6 +220,7 @@ class TelnetLiquidsoap:
self.telnet_send([command])
@ls_timeout
def liquidsoap_get_info(self):
self.logger.debug("Checking to see if Liquidsoap is running")
response = ""
@ -219,6 +233,7 @@ class TelnetLiquidsoap:
return response
@ls_timeout
def update_liquidsoap_station_name(self, station_name):
with self.telnet_lock:
tn = self.__connect()
@ -229,6 +244,7 @@ class TelnetLiquidsoap:
tn.write('exit\n')
tn.read_all()
@ls_timeout
def get_liquidsoap_connection_status(self, current_time):
output = None
with self.telnet_lock:
@ -249,6 +265,7 @@ class TelnetLiquidsoap:
return output
@ls_timeout
def update_liquidsoap_stream_format(self, stream_format):
with self.telnet_lock:
tn = self.__connect()
@ -259,6 +276,7 @@ class TelnetLiquidsoap:
tn.write('exit\n')
tn.read_all()
@ls_timeout
def update_liquidsoap_transition_fade(self, fade):
with self.telnet_lock:
tn = self.__connect()
@ -278,6 +296,7 @@ class DummyTelnetLiquidsoap:
for i in range(4):
self.liquidsoap_mock_queues["s"+str(i)] = []
@ls_timeout
def queue_push(self, queue_id, media_item):
try:
self.telnet_lock.acquire()
@ -293,6 +312,7 @@ class DummyTelnetLiquidsoap:
finally:
self.telnet_lock.release()
@ls_timeout
def queue_remove(self, queue_id):
try:
self.telnet_lock.acquire()

View file

@ -0,0 +1,36 @@
import threading
import pypofetch
def __timeout(func, timeout_duration, default, args, kwargs):
class InterruptableThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.result = default
def run(self):
self.result = func(*args, **kwargs)
first_attempt = True
while True:
it = InterruptableThread()
it.start()
it.join(timeout_duration)
if it.isAlive():
"""Restart Liquidsoap and try the command one more time. If it
fails again then there is something critically wrong..."""
if first_attempt:
#restart liquidsoap
pypofetch.PypoFetch.ref.restart_liquidsoap()
else:
raise Exception("Thread did not terminate")
else:
return it.result
first_attempt = False
def ls_timeout(f, timeout=4, default=None):
def new_f(*args, **kwargs):
return __timeout(f, timeout, default, args, kwargs)
return new_f