-greatly simplified ls_script. Much easier to add live-streaming support.
-begin adding configurability for ogg/mp3/audio_out
This commit is contained in:
parent
2cbddf0f82
commit
a4b5a1d618
|
@ -663,29 +663,12 @@ class Playout:
|
||||||
logger.debug('OK - Can read playlist file')
|
logger.debug('OK - Can read playlist file')
|
||||||
|
|
||||||
pl_file = open(src, "r")
|
pl_file = open(src, "r")
|
||||||
|
|
||||||
"""
|
|
||||||
i know this could be wrapped, maybe later..
|
|
||||||
"""
|
|
||||||
tn = telnetlib.Telnet(LS_HOST, 1234)
|
|
||||||
|
|
||||||
for line in pl_file.readlines():
|
|
||||||
line = line.strip()
|
|
||||||
logger.debug(line)
|
|
||||||
tn.write(self.export_source + '.push %s' % (line))
|
|
||||||
tn.write("\n")
|
|
||||||
|
|
||||||
tn.write("exit\n")
|
|
||||||
logger.debug(tn.read_all())
|
|
||||||
|
|
||||||
pattern = '%Y-%m-%d-%H-%M-%S'
|
|
||||||
|
|
||||||
#strptime returns struct_time in local time
|
#strptime returns struct_time in local time
|
||||||
#mktime takes a time_struct and returns a floating point
|
#mktime takes a time_struct and returns a floating point
|
||||||
#gmtime Convert a time expressed in seconds since the epoch to a struct_time in UTC
|
#gmtime Convert a time expressed in seconds since the epoch to a struct_time in UTC
|
||||||
|
|
||||||
#mktime: expresses the time in local time, not UTC. It returns a floating point number, for compatibility with time().
|
#mktime: expresses the time in local time, not UTC. It returns a floating point number, for compatibility with time().
|
||||||
epoch_start = calendar.timegm(time.gmtime(time.mktime(time.strptime(pkey, pattern))))
|
epoch_start = calendar.timegm(time.gmtime(time.mktime(time.strptime(pkey, '%Y-%m-%d-%H-%M-%S'))))
|
||||||
|
|
||||||
#Return the time as a floating point number expressed in seconds since the epoch, in UTC.
|
#Return the time as a floating point number expressed in seconds since the epoch, in UTC.
|
||||||
epoch_now = time.time()
|
epoch_now = time.time()
|
||||||
|
@ -701,8 +684,19 @@ class Playout:
|
||||||
|
|
||||||
logger.debug('sleeping for %s s' % (sleep_time))
|
logger.debug('sleeping for %s s' % (sleep_time))
|
||||||
time.sleep(sleep_time)
|
time.sleep(sleep_time)
|
||||||
|
|
||||||
|
tn = telnetlib.Telnet(LS_HOST, 1234)
|
||||||
|
|
||||||
|
for line in pl_file.readlines():
|
||||||
|
line = line.strip()
|
||||||
|
logger.debug(line)
|
||||||
|
tn.write('queue.push %s' % (line))
|
||||||
|
tn.write("\n")
|
||||||
|
|
||||||
|
tn.write("exit\n")
|
||||||
|
logger.debug(tn.read_all())
|
||||||
|
|
||||||
logger.debug('sending "flip"')
|
"""
|
||||||
tn = telnetlib.Telnet(LS_HOST, 1234)
|
tn = telnetlib.Telnet(LS_HOST, 1234)
|
||||||
|
|
||||||
# Get any extra information for liquidsoap (which will be sent back to us)
|
# Get any extra information for liquidsoap (which will be sent back to us)
|
||||||
|
@ -717,6 +711,7 @@ class Playout:
|
||||||
tn.write("exit\n")
|
tn.write("exit\n")
|
||||||
|
|
||||||
tn.read_all()
|
tn.read_all()
|
||||||
|
"""
|
||||||
status = 1
|
status = 1
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.error('%s', e)
|
logger.error('%s', e)
|
||||||
|
|
|
@ -51,13 +51,7 @@ parser = OptionParser(usage=usage)
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
parser.add_option("-d", "--data", help="Pass JSON data from liquidsoap into this script.", metavar="data")
|
parser.add_option("-d", "--data", help="Pass JSON data from liquidsoap into this script.", metavar="data")
|
||||||
#parser.add_option("-p", "--playing", help="Tell server what is playing right now.", default=False, action="store_true", dest="playing")
|
|
||||||
#parser.add_option("-t", "--playlist-type", help="", metavar="playlist_type")
|
|
||||||
parser.add_option("-m", "--media-id", help="ID of the file that is currently playing.", metavar="media_id")
|
parser.add_option("-m", "--media-id", help="ID of the file that is currently playing.", metavar="media_id")
|
||||||
#parser.add_option("-U", "--user-id", help="", metavar="user_id")
|
|
||||||
#parser.add_option("-P", "--playlist-id", help="", metavar="playlist_id")
|
|
||||||
#parser.add_option("-T", "--transmission-id", help="", metavar="transmission_id")
|
|
||||||
#parser.add_option("-E", "--export-source", help="", metavar="export_source")
|
|
||||||
|
|
||||||
# parse options
|
# parse options
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
|
@ -73,135 +67,21 @@ except Exception, e:
|
||||||
print 'error: ', e
|
print 'error: ', e
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
class Global:
|
|
||||||
def __init__(self):
|
|
||||||
print
|
|
||||||
|
|
||||||
def selfcheck(self):
|
|
||||||
pass
|
|
||||||
#self.api_client = api_client.api_client_factory(config)
|
|
||||||
#self.api_client.check_version()
|
|
||||||
|
|
||||||
class Notify:
|
class Notify:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.api_client = api_client.api_client_factory(config)
|
self.api_client = api_client.api_client_factory(config)
|
||||||
#self.dls_client = DlsClient('127.0.0.128', 50008, 'myusername', 'mypass')
|
|
||||||
|
|
||||||
|
|
||||||
def notify_media_start_playing(self, data, media_id):
|
def notify_media_start_playing(self, data, media_id):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
#tnow = time.localtime(time.time())
|
|
||||||
|
|
||||||
logger.debug('#################################################')
|
logger.debug('#################################################')
|
||||||
logger.debug('# Calling server to update about what\'s playing #')
|
logger.debug('# Calling server to update about what\'s playing #')
|
||||||
logger.debug('#################################################')
|
logger.debug('#################################################')
|
||||||
logger.debug('data = '+ str(data))
|
logger.debug('data = '+ str(data))
|
||||||
#print 'options.data = '+ options.data
|
|
||||||
#data = json.loads(options.data)
|
|
||||||
response = self.api_client.notify_media_item_start_playing(data, media_id)
|
response = self.api_client.notify_media_item_start_playing(data, media_id)
|
||||||
logger.debug("Response: "+str(response))
|
logger.debug("Response: "+str(response))
|
||||||
|
|
||||||
#def start_playing(self, options):
|
|
||||||
# logger = logging.getLogger("start_playing")
|
|
||||||
# tnow = time.localtime(time.time())
|
|
||||||
#
|
|
||||||
# #print options
|
|
||||||
#
|
|
||||||
# logger.debug('#################################################')
|
|
||||||
# logger.debug('# Calling server to update about what\'s playing #')
|
|
||||||
# logger.debug('#################################################')
|
|
||||||
#
|
|
||||||
# if int(options.playlist_type) < 5:
|
|
||||||
# logger.debug('seems to be a playlist')
|
|
||||||
#
|
|
||||||
# try:
|
|
||||||
# media_id = int(options.media_id)
|
|
||||||
# except Exception, e:
|
|
||||||
# media_id = 0
|
|
||||||
#
|
|
||||||
# response = self.api_client.update_start_playing(options.playlist_type, options.export_source, media_id, options.playlist_id, options.transmission_id)
|
|
||||||
#
|
|
||||||
# logger.debug(response)
|
|
||||||
#
|
|
||||||
# if int(options.playlist_type) == 6:
|
|
||||||
# logger.debug('seems to be a couchcast')
|
|
||||||
#
|
|
||||||
# try:
|
|
||||||
# media_id = int(options.media_id)
|
|
||||||
# except Exception, e:
|
|
||||||
# media_id = 0
|
|
||||||
#
|
|
||||||
# response = self.api_client.update_start_playing(options.playlist_type, options.export_source, media_id, options.playlist_id, options.transmission_id)
|
|
||||||
#
|
|
||||||
# logger.debug(response)
|
|
||||||
#
|
|
||||||
# sys.exit()
|
|
||||||
|
|
||||||
#def start_playing_legacy(self, options):
|
|
||||||
# logger = logging.getLogger("start_playing")
|
|
||||||
# tnow = time.localtime(time.time())
|
|
||||||
#
|
|
||||||
# print '#################################################'
|
|
||||||
# print '# Calling server to update about what\'s playing #'
|
|
||||||
# print '#################################################'
|
|
||||||
#
|
|
||||||
# path = options
|
|
||||||
#
|
|
||||||
# print
|
|
||||||
# print path
|
|
||||||
# print
|
|
||||||
#
|
|
||||||
# if 'pl_id' in path:
|
|
||||||
# print 'seems to be a playlist'
|
|
||||||
# type = 'playlist'
|
|
||||||
# id = path[5:]
|
|
||||||
#
|
|
||||||
# elif 'text' in path:
|
|
||||||
# print 'seems to be a playlist'
|
|
||||||
# type = 'text'
|
|
||||||
# id = path[4:]
|
|
||||||
# print id
|
|
||||||
#
|
|
||||||
# else:
|
|
||||||
# print 'seems to be a single track (media)'
|
|
||||||
# type = 'media'
|
|
||||||
# try:
|
|
||||||
# file = path.split("/")[-1:][0]
|
|
||||||
# if file.find('_cue_') > 0:
|
|
||||||
# id = file.split("_cue_")[0]
|
|
||||||
# else:
|
|
||||||
# id = file.split(".")[-2:][0]
|
|
||||||
#
|
|
||||||
# except Exception, e:
|
|
||||||
# #print e
|
|
||||||
# id = False
|
|
||||||
#
|
|
||||||
# try:
|
|
||||||
# id = id
|
|
||||||
# except Exception, e:
|
|
||||||
# #print e
|
|
||||||
# id = False
|
|
||||||
#
|
|
||||||
# print
|
|
||||||
# print type + " id: ",
|
|
||||||
# print id
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# response = self.api_client.update_start_playing(type, id, self.export_source, path)
|
|
||||||
#
|
|
||||||
# print 'DONE'
|
|
||||||
#
|
|
||||||
# try:
|
|
||||||
# txt = response['txt']
|
|
||||||
# print '#######################################'
|
|
||||||
# print txt
|
|
||||||
# print '#######################################'
|
|
||||||
# #self.dls_client.set_txt(txt)
|
|
||||||
#
|
|
||||||
# except Exception, e:
|
|
||||||
# print e
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print
|
print
|
||||||
|
@ -211,13 +91,8 @@ if __name__ == '__main__':
|
||||||
print '#########################################'
|
print '#########################################'
|
||||||
|
|
||||||
# initialize
|
# initialize
|
||||||
g = Global()
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
#if options.playing:
|
|
||||||
# try: n.start_playing(options)
|
|
||||||
# except Exception, e:
|
|
||||||
# print e
|
|
||||||
# sys.exit()
|
|
||||||
if not options.data:
|
if not options.data:
|
||||||
print "NOTICE: 'data' command-line argument not given."
|
print "NOTICE: 'data' command-line argument not given."
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
@ -227,7 +102,6 @@ if __name__ == '__main__':
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
g.selfcheck()
|
|
||||||
n = Notify()
|
n = Notify()
|
||||||
n.notify_media_start_playing(options.data, options.media_id)
|
n.notify_media_start_playing(options.data, options.media_id)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
|
|
@ -28,7 +28,8 @@ icecast_port = 8000
|
||||||
icecast_pass = "hackme"
|
icecast_pass = "hackme"
|
||||||
|
|
||||||
# mountpoints
|
# mountpoints
|
||||||
mount_scheduler = "airtime.mp3"
|
mount_point_mp3 = "airtime.mp3"
|
||||||
|
mount_point_vorbis = "airtime.ogg"
|
||||||
|
|
||||||
# mount intra is used for scheduler >>> fallback stream
|
# mount intra is used for scheduler >>> fallback stream
|
||||||
mount_intra = "pypo_intra"
|
mount_intra = "pypo_intra"
|
||||||
|
@ -38,3 +39,10 @@ intra_host = "127.0.0.1"
|
||||||
intra_port = 9000
|
intra_port = 9000
|
||||||
intra_pass = "hackme"
|
intra_pass = "hackme"
|
||||||
|
|
||||||
|
icecast_url = "http://airtime.sourcefabric.org"
|
||||||
|
icecast_description = "Airtime Radio!"
|
||||||
|
icecast_genre = "genre"
|
||||||
|
|
||||||
|
output_sound_device = true
|
||||||
|
output_icecast_vorbis = true
|
||||||
|
output_icecast_mp3 = true
|
||||||
|
|
|
@ -5,42 +5,14 @@ set("log.file.path", log_file)
|
||||||
set("log.stdout", true)
|
set("log.stdout", true)
|
||||||
set("server.telnet", true)
|
set("server.telnet", true)
|
||||||
|
|
||||||
active_queue = ref 0
|
queue = request.queue(conservative=true,length=600.,id="queue")
|
||||||
|
queue = audio_to_stereo(queue)
|
||||||
scheduler_q0 = request.queue(conservative=true,length=600.,id="scheduler_q0")
|
|
||||||
scheduler_q1 = request.queue(conservative=true,length=600.,id="scheduler_q1")
|
|
||||||
|
|
||||||
scheduler_q0 = audio_to_stereo(scheduler_q0)
|
|
||||||
scheduler_q1 = audio_to_stereo(scheduler_q1)
|
|
||||||
|
|
||||||
pypo_data = ref '0'
|
pypo_data = ref '0'
|
||||||
|
|
||||||
# push function, enqueues file in inactive queue (does not start automatically)
|
#def notify(m)
|
||||||
def scheduler_push(s)
|
# print("./notify.sh --data='#{!pypo_data}' --media-id=#{m['media_id']}")
|
||||||
ignore(server.execute("scheduler_q#{!active_queue}.push #{s}"))
|
#end
|
||||||
print('push to #{!active_queue} - #{s}')
|
|
||||||
"Done"
|
|
||||||
end
|
|
||||||
|
|
||||||
# flips the queues
|
|
||||||
def scheduler_flip()
|
|
||||||
# get playing (active) queue and flush it
|
|
||||||
l = list.hd(server.execute("scheduler_q#{!active_queue}.queue"))
|
|
||||||
l = string.split(separator=" ",l)
|
|
||||||
list.iter(fun (rid) -> ignore(server.execute("scheduler_q#{!active_queue}.ignore #{rid}")), l)
|
|
||||||
|
|
||||||
# skip the playing item
|
|
||||||
source.skip(if !active_queue==0 then scheduler_q0 else scheduler_q1 end)
|
|
||||||
|
|
||||||
# flip variables
|
|
||||||
active_queue := 1-!active_queue
|
|
||||||
print('switch to active queue: #{!active_queue}')
|
|
||||||
"Done"
|
|
||||||
end
|
|
||||||
|
|
||||||
def notify(m)
|
|
||||||
print("./notify.sh --data='#{!pypo_data}' --media-id=#{m['media_id']}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def crossfade(s)
|
def crossfade(s)
|
||||||
s = fade.in(type="log", s)
|
s = fade.in(type="log", s)
|
||||||
|
@ -49,23 +21,42 @@ def crossfade(s)
|
||||||
cross(fader,s)
|
cross(fader,s)
|
||||||
end
|
end
|
||||||
|
|
||||||
server.register(namespace="scheduler","push", scheduler_push)
|
|
||||||
server.register(namespace="scheduler","flip", fun (s) -> begin scheduler_flip() end)
|
|
||||||
server.register(namespace="vars", "pypo_data", fun (s) -> begin pypo_data := s "Done" end)
|
server.register(namespace="vars", "pypo_data", fun (s) -> begin pypo_data := s "Done" end)
|
||||||
|
|
||||||
default = single("/opt/pypo/files/basic/silence.mp3")
|
default = single("/opt/pypo/files/basic/silence.mp3")
|
||||||
radio = fallback(track_sensitive=false, [switch(track_sensitive=false, [(fun () -> !active_queue==1, scheduler_q0), (fun () -> !active_queue==0, scheduler_q1)]), default])
|
default = rewrite_metadata([("artist","Airtime"), ("title", "offline")],default)
|
||||||
|
|
||||||
#radio = on_metadata(notify, radio)
|
s = fallback(track_sensitive=false, [queue, default])
|
||||||
|
|
||||||
radio = crossfade(radio)
|
#s = on_metadata(notify, s)
|
||||||
|
s = crossfade(s)
|
||||||
|
|
||||||
out(radio)
|
if output_sound_device then
|
||||||
clock(id="clock_icecast",
|
out_device = out(s)
|
||||||
output.icecast(%mp3,
|
end
|
||||||
host = icecast_host, port = icecast_port,
|
|
||||||
password = icecast_pass, mount = mount_scheduler,
|
if output_icecast_mp3 then
|
||||||
fallible = true,
|
out_mp3 = output.icecast(%mp3,
|
||||||
restart = true,
|
host = icecast_host, port = icecast_port,
|
||||||
restart_delay = 5,
|
password = icecast_pass, mount = mount_point_mp3,
|
||||||
buffer(radio)))
|
fallible = true,
|
||||||
|
restart = true,
|
||||||
|
restart_delay = 5,
|
||||||
|
url = icecast_url,
|
||||||
|
description = icecast_description,
|
||||||
|
genre = icecast_genre,
|
||||||
|
s)
|
||||||
|
end
|
||||||
|
|
||||||
|
if output_icecast_vorbis then
|
||||||
|
out_vorbis = output.icecast(%vorbis,
|
||||||
|
host = icecast_host, port = icecast_port,
|
||||||
|
password = icecast_pass, mount = mount_point_vorbis,
|
||||||
|
fallible = true,
|
||||||
|
restart = true,
|
||||||
|
restart_delay = 5,
|
||||||
|
url = icecast_url,
|
||||||
|
description = icecast_description,
|
||||||
|
genre = icecast_genre,
|
||||||
|
s)
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue