From 46cf75884d78cd4304bc9f3dcb3271a64d1dfabe Mon Sep 17 00:00:00 2001 From: martin Date: Wed, 15 Jun 2011 18:23:12 -0400 Subject: [PATCH] cc-2015: on reboot resume show -liquidsoap is having some problems with cue points right now need to check if this is my fault. --- .../pypo/liquidsoap_scripts/library/Makefile | 1 + .../liquidsoap_scripts/library/externals.liq | 154 +++++++++++------- .../library/liquidsoap.initd | 0 .../pypo/liquidsoap_scripts/library/test.liq | 33 ---- .../liquidsoap_scripts/library/typing.liq | 112 ------------- .../pypo/liquidsoap_scripts/library/utils.liq | 144 +++++++++++----- .../pypo/liquidsoap_scripts/ls_script.liq | 1 + python_apps/pypo/pypo-notify.py | 1 - python_apps/pypo/pypofetch.py | 66 ++++++-- python_apps/pypo/pypopush.py | 6 +- 10 files changed, 248 insertions(+), 270 deletions(-) mode change 100755 => 100644 python_apps/pypo/liquidsoap_scripts/library/liquidsoap.initd delete mode 100644 python_apps/pypo/liquidsoap_scripts/library/test.liq delete mode 100644 python_apps/pypo/liquidsoap_scripts/library/typing.liq diff --git a/python_apps/pypo/liquidsoap_scripts/library/Makefile b/python_apps/pypo/liquidsoap_scripts/library/Makefile index cc4c77cda..d10777180 100644 --- a/python_apps/pypo/liquidsoap_scripts/library/Makefile +++ b/python_apps/pypo/liquidsoap_scripts/library/Makefile @@ -1,4 +1,5 @@ +SUBDIRS = tests DISTFILES = $(wildcard *.in) Makefile ask-liquidsoap.rb ask-liquidsoap.pl \ $(wildcard *.liq) extract-replaygain diff --git a/python_apps/pypo/liquidsoap_scripts/library/externals.liq b/python_apps/pypo/liquidsoap_scripts/library/externals.liq index ede1d2e3d..1a50f4b95 100644 --- a/python_apps/pypo/liquidsoap_scripts/library/externals.liq +++ b/python_apps/pypo/liquidsoap_scripts/library/externals.liq @@ -9,37 +9,43 @@ my_get_mime = get_mime get_mime = my_get_mime %ifdef add_decoder -if test_process("which flac") then - log(level=3,"Found flac binary: enabling flac external decoder.") - flac_p = "flac -d -c - 2>/dev/null" - def test_flac(file) = - if test_process("which metaflac") then - channels = list.hd(get_process_lines("metaflac \ - --show-channels #{quote(file)} \ - 2>/dev/null")) - # If the value is not an int, this returns 0 and we are ok :) - int_of_string(channels) - else - # Try to detect using mime test.. - mime = get_mime(file) - if string.match(pattern="flac",file) then - # We do not know the number of audio channels - # so setting to -1 - (-1) +# Enable external FLAC decoders. Requires flac binary +# in the path for audio decoding and metaflac binary for +# metadata. Does not work on Win32. Default: disabled. +# Please note that built-in support for FLAC is available +# in liquidsoap if compiled and should be preferred over +# the external decoder. +# @category Liquidsoap +def enable_external_flac_decoder() = + if test_process("which flac") then + log(level=3,"Found flac binary: enabling flac external decoder.") + flac_p = "flac -d -c - 2>/dev/null" + def test_flac(file) = + if test_process("which metaflac") then + channels = list.hd(get_process_lines("metaflac \ + --show-channels #{quote(file)} \ + 2>/dev/null")) + # If the value is not an int, this returns 0 and we are ok :) + int_of_string(channels) else - # All tests failed: no audio decodable using flac.. - 0 + # Try to detect using mime test.. + mime = get_mime(file) + if string.match(pattern="flac",file) then + # We do not know the number of audio channels + # so setting to -1 + (-1) + else + # All tests failed: no audio decodable using flac.. + 0 + end end end + add_decoder(name="FLAC",description="Decode files using the flac \ + decoder binary.", test=test_flac,flac_p) + else + log(level=3,"Did not find flac binary: flac decoder disabled.") end - add_decoder(name="FLAC",description="Decode files using the flac \ - decoder binary.", test=test_flac,flac_p) -else - log(level=3,"Did not find flac binary: flac decoder disabled.") -end -%endif -if os.type != "Win32" then if test_process("which metaflac") then log(level=3,"Found metaflac binary: enabling flac external metadata \ resolver.") @@ -55,49 +61,59 @@ if os.type != "Win32" then if list.length(l) >= 1 then list.append([(list.hd(l),"")],l') else - l' - end + l' end end - list.fold(f,[],ret) + end + list.fold(f,[],ret) end add_metadata_resolver("FLAC",flac_meta) else - log(level=3,"Did not find metaflac binary: flac metadata resolver disabled.") + log(level=3,"Did not find metaflac binary: flac metadata resolver disabled.") end end +%endif -# 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_filexts = ["m4a", "m4b", "m4p", "m4v", - "m4r", "3gp", "mp4", "aac"] +%ifdef add_oblivious_decoder +# Enable or disable external FAAD (AAC/AAC+/M4A) decoders. +# Requires faad binary in the path for audio decoding and +# metaflac binary for metadata. Does not work on Win32. +# Please note that built-in support for faad is available +# in liquidsoap if compiled and should be preferred over +# the external decoder. +# @category Liquidsoap +def enable_external_faad_decoder() = -# Faad is not very selective so -# We are checking only file that -# end with a known extension or mime type -def faad_test(file) = - # Get the file's mime - mime = get_mime(file) - # Test mime - if list.mem(mime,aac_mimes) then - true - else - # Otherwise test file extension - ret = string.extract(pattern='\.(.+)$',file) + # 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_filexts = ["m4a", "m4b", "m4p", "m4v", + "m4r", "3gp", "mp4", "aac"] + + # Faad is not very selective so + # We are checking only file that + # end with a known extension or mime type + def faad_test(file) = + # Get the file's mime + mime = get_mime(file) + # Test mime + if list.mem(mime,aac_mimes) then + true + else + # Otherwise test file extension + ret = string.extract(pattern='\.(.+)$',file) if list.length(ret) != 0 then - ext = ret["1"] - list.mem(ext,aac_filexts) - else - false - end + ext = ret["1"] + list.mem(ext,aac_filexts) + else + false + end + end end -end -if os.type != "Win32" then if test_process("which faad") then log(level=3,"Found faad binary: enabling external faad decoder and \ metadata resolver.") @@ -120,15 +136,13 @@ if os.type != "Win32" then 0 end end -%ifdef add_oblivious_decoder add_oblivious_decoder(name="FAAD",description="Decode files using \ the faad binary.", test=test_faad, faad_p) -%endif def faad_meta(file) = if faad_test(file) then ret = get_process_lines("faad -i \ #{quote(file)} 2>&1") - # Yea, this is tuff programming (again) ! + # Yea, this is ugly programming (again) ! def get_meta(l,s)= ret = string.extract(pattern="^(\w+):\s(.+)$",s) if list.length(ret) > 0 then @@ -147,6 +161,7 @@ if os.type != "Win32" then log(level=3,"Did not find faad binary: faad decoder disabled.") end end +%endif # Standard function for displaying metadata. # Shows artist and title, using "Unknown" when a field is empty. @@ -189,3 +204,22 @@ def notify_metadata(~urgency="low",~icon="stock_smiley-22",~time=3000, ^ ' -t #{time} #{quote(title)} ' on_metadata(fun (m) -> system(send^quote(display(m))),s) end + +%ifdef input.external +# 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 +%endif diff --git a/python_apps/pypo/liquidsoap_scripts/library/liquidsoap.initd b/python_apps/pypo/liquidsoap_scripts/library/liquidsoap.initd old mode 100755 new mode 100644 diff --git a/python_apps/pypo/liquidsoap_scripts/library/test.liq b/python_apps/pypo/liquidsoap_scripts/library/test.liq deleted file mode 100644 index ac78f2037..000000000 --- a/python_apps/pypo/liquidsoap_scripts/library/test.liq +++ /dev/null @@ -1,33 +0,0 @@ -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)) diff --git a/python_apps/pypo/liquidsoap_scripts/library/typing.liq b/python_apps/pypo/liquidsoap_scripts/library/typing.liq deleted file mode 100644 index 2a4c7eaa7..000000000 --- a/python_apps/pypo/liquidsoap_scripts/library/typing.liq +++ /dev/null @@ -1,112 +0,0 @@ -# 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 diff --git a/python_apps/pypo/liquidsoap_scripts/library/utils.liq b/python_apps/pypo/liquidsoap_scripts/library/utils.liq index da4224dc0..fe1963100 100644 --- a/python_apps/pypo/liquidsoap_scripts/library/utils.liq +++ b/python_apps/pypo/liquidsoap_scripts/library/utils.liq @@ -300,6 +300,25 @@ def server.insert_metadata(~id="",s) = s end +# Register a command that outputs the RMS of the returned source. +# @category Source / Visualization +# @param ~id Force the value of the source ID. +def server.rms(~id="",s) = + x = rms(id=id,s) + rms = fst(x) + s = snd(x) + id = source.id(s) + def rms(_) = + rms = rms() + "#{rms}" + end + server.register(namespace="#{id}", + description="Return the current RMS of the source.", + usage="rms", + "rms",rms) + s +end + # Get the base name of a path. # Implemented using the corresponding shell command. # @category System @@ -479,59 +498,95 @@ def smart_crossfade (~start_next=5.,~fade_in=3.,~fade_out=3., end # Custom playlist source written using the script language. -# Will read directory or playlist, play all files and stop +# Will read directory or playlist, play all files and stop. +# Returns a pair @(reload,source)@ where @reload@ is a function +# of type @(?uri:string)->unit@ used to reload the source and @source@ +# is the actual source. The reload function can optionally be called +# with a new playlist URI. Otherwise, it reloads the previous URI. # @category Source / Input +# @param ~id Force the value of the source ID. # @param ~random Randomize playlist content # @param ~on_done Function to execute when the playlist is finished # @param uri Playlist URI -def playlist.once(~random=false,~on_done={()},uri) - x = ref 0 - def playlist.custom(files) - length = list.length(files) - if length == 0 then - log("Empty playlist..") - fail () - else - files = - if random then - list.sort(fun (x,y) -> int_of_float(random.float()), files) - else - files - end - def next () = - state = !x - file = - if state < length then - x := state + 1 - list.nth(files,state) - else - # Playlist finished +def playlist.reloadable(~id="",~random=false,~on_done={()},uri) + # A reference to the playlist + playlist = ref [] + # A reference to the uri + playlist_uri = ref uri + # A reference to know if the source + # has been stopped + has_stopped = ref false + # The next function + def next () = + file = + if list.length(!playlist) > 0 then + ret = list.hd(!playlist) + playlist := list.tl(!playlist) + ret + else + # Playlist finished + if not !has_stopped then on_done () - "" end - request.create(file) + has_stopped := true + "" end - request.dynamic(next) + request.create(file) + end + # Instanciate the source + source = request.dynamic(id=id,next) + # Get its id. + id = source.id(source) + # The load function + def load_playlist () = + files = + if test_process("test -d #{quote(!playlist_uri)}") then + log(label=id,"playlist is a directory.") + get_process_lines("find #{quote(!playlist_uri)} -type f | sort") + else + playlist = request.create.raw(!playlist_uri) + result = + if request.resolve(playlist) then + playlist = request.filename(playlist) + files = playlist.parse(playlist) + list.map(snd,files) + else + log(label=id,"Couldn't read playlist: request resolution failed.") + [] + end + request.destroy(playlist) + result + end + if random then + playlist := list.sort(fun (x,y) -> int_of_float(random.float()), files) + else + playlist := files end end - if test_process("test -d #{quote(uri)}") then - files = get_process_lines("find #{quote(uri)} -type f | sort") - playlist.custom(files) - else - playlist = request.create.raw(uri) - result = - if request.resolve(playlist) then - playlist = request.filename(playlist) - files = playlist.parse(playlist) - files = list.map(snd,files) - playlist.custom(files) - else - log("Couldn't read playlist: request resolution failed.") - fail () - end - request.destroy(playlist) - result + # The reload function + def reload(~uri="") = + if uri != "" then + playlist_uri := uri + end + log(label=id,"Reloading playlist with URI #{!playlist_uri}") + has_stopped := false + load_playlist() end + # Load the playlist + load_playlist() + # Return + (reload,source) +end + +# Custom playlist source written using the script language. +# Will read directory or playlist, play all files and stop +# @category Source / Input +# @param ~id Force the value of the source ID. +# @param ~random Randomize playlist content +# @param ~on_done Function to execute when the playlist is finished +# @param uri Playlist URI +def playlist.once(~id="",~random=false,~on_done={()},uri) + snd(playlist.reloadable(id=id,random=random,on_done=on_done,uri)) end # Mixes two streams, with faded transitions between the state when only the @@ -588,7 +643,8 @@ def exec_at(~freq=1.,~pred,f) add_timeout(freq,check) end -# Register the replaygain protocol +# Register the replaygain protocol. +# @category Liquidsoap def replaygain_protocol(arg,delay) # The extraction program extract_replaygain = "#{configure.libdir}/extract-replaygain" diff --git a/python_apps/pypo/liquidsoap_scripts/ls_script.liq b/python_apps/pypo/liquidsoap_scripts/ls_script.liq index 0689a309f..ab856d903 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_script.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_script.liq @@ -7,6 +7,7 @@ set("server.telnet", true) set("server.telnet.port", 1234) queue = request.queue(id="queue", length=0.5) +queue = cue_cut(queue) queue = audio_to_stereo(queue) pypo_data = ref '0' diff --git a/python_apps/pypo/pypo-notify.py b/python_apps/pypo/pypo-notify.py index d59932dcb..754305748 100755 --- a/python_apps/pypo/pypo-notify.py +++ b/python_apps/pypo/pypo-notify.py @@ -37,7 +37,6 @@ from configobj import ConfigObj # custom imports from util import * from api_clients import * -from dls import * # Set up command-line options parser = OptionParser() diff --git a/python_apps/pypo/pypofetch.py b/python_apps/pypo/pypofetch.py index f0910943b..7006780ce 100755 --- a/python_apps/pypo/pypofetch.py +++ b/python_apps/pypo/pypofetch.py @@ -12,6 +12,7 @@ import math from threading import Thread from subprocess import Popen, PIPE from datetime import datetime +from datetime import timedelta # For RabbitMQ from kombu.connection import BrokerConnection @@ -99,6 +100,7 @@ class PypoFetch(Thread): logger.error(" * See this page for more info (v1.7): http://wiki.sourcefabric.org/x/BQBF") logger.error(" * and also the 'FAQ and Support' page underneath it.") + """ def get_currently_scheduled(self, playlistsOrMedias, str_tnow_s): for key in playlistsOrMedias: start = playlistsOrMedias[key]['start'] @@ -114,9 +116,6 @@ class PypoFetch(Thread): dtnow = datetime.today() tnow = dtnow.timetuple() - - #timenow = time.time() - #tnow = time.localtime(timenow) #tnow is struct_time. localtime is non-utc str_tnow_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4], tnow[5]) current_pkey = self.get_currently_scheduled(playlists, str_tnow_s) @@ -135,6 +134,7 @@ class PypoFetch(Thread): delta = dtnow - media_start #we get a TimeDelta object from this operation logger.info("Starting media item at %d second point", delta.seconds) + """ """ Process the schedule @@ -148,9 +148,9 @@ class PypoFetch(Thread): logger = logging.getLogger('fetch') playlists = schedule_data["playlists"] - if bootstrapping: + #if bootstrapping: #TODO: possible allow prepare_playlists to handle this. - self.handle_shows_currently_scheduled(playlists) + #self.handle_shows_currently_scheduled(playlists) self.check_matching_timezones(schedule_data["server_timezone"]) @@ -170,7 +170,7 @@ class PypoFetch(Thread): # Download all the media and put playlists in liquidsoap "annotate" format try: - liquidsoap_playlists = self.prepare_playlists(playlists) + liquidsoap_playlists = self.prepare_playlists(playlists, bootstrapping) except Exception, e: logger.error("%s", e) # Send the data to pypo-push @@ -190,7 +190,7 @@ class PypoFetch(Thread): and stored in a playlist folder. file is e.g. 2010-06-23-15-00-00/17_cue_10.132-123.321.mp3 """ - def prepare_playlists(self, playlists): + def prepare_playlists(self, playlists, bootstrapping): logger = logging.getLogger('fetch') liquidsoap_playlists = dict() @@ -211,18 +211,18 @@ class PypoFetch(Thread): try: os.mkdir(self.cache_dir + str(pkey)) except Exception, e: - pass + logger.error(e) #June 13, 2011: Commented this block out since we are not currently setting this to '1' #on the server side. Currently using a different method to detect if already played - Martin #if int(playlist['played']) == 1: # logger.info("playlist %s already played / sent to liquidsoap, so will ignore it", pkey) - ls_playlist = self.handle_media_file(playlist, pkey) + ls_playlist = self.handle_media_file(playlist, pkey, bootstrapping) liquidsoap_playlists[pkey] = ls_playlist except Exception, e: - logger.info("%s", e) + logger.error("%s", e) return liquidsoap_playlists @@ -231,17 +231,43 @@ class PypoFetch(Thread): This handles both remote and local files. Returns an updated ls_playlist string. """ - def handle_media_file(self, playlist, pkey): - ls_playlist = [] - + def handle_media_file(self, playlist, pkey, bootstrapping): logger = logging.getLogger('fetch') - for key in playlist['medias']: + + ls_playlist = [] + + dtnow = datetime.today() + str_tnow_s = dtnow.strftime('%Y-%m-%d-%H-%M-%S') + + sortedKeys = sorted(playlist['medias'].iterkeys()) + + for key in sortedKeys: media = playlist['medias'][key] logger.debug("Processing track %s", media['uri']) + + if bootstrapping: + start = media['start'] + end = media['end'] + + if end <= str_tnow_s: + continue + elif start <= str_tnow_s and str_tnow_s < end: + #song is currently playing and we just started pypo. Maybe there + #was a power outage? Let's restart playback of this song. + start_split = map(int, start.split('-')) + media_start = datetime(start_split[0], start_split[1], start_split[2], start_split[3], start_split[4], start_split[5]) + logger.debug("Found media item that started at %s.", media_start) + + delta = dtnow - media_start #we get a TimeDelta object from this operation + logger.info("Starting media item at %d second point", delta.seconds) + media['cue_in'] = delta.seconds + 10 #TODO is cue_in in seconds? + td = timedelta(seconds=10) + playlist['start'] = (dtnow + td).strftime('%Y-%m-%d-%H-%M-%S') + logger.info("Crash detected, setting playlist to restart at %s", (dtnow + td).strftime('%Y-%m-%d-%H-%M-%S')) + fileExt = os.path.splitext(media['uri'])[1] try: - #logger.debug('No cue in/out detected for this file') dst = "%s%s/%s%s" % (self.cache_dir, str(pkey), str(media['id']), str(fileExt)) # download media file @@ -256,9 +282,13 @@ class PypoFetch(Thread): if fsize > 0: pl_entry = \ - 'annotate:export_source="%s",media_id="%s",liq_start_next="%s",liq_fade_in="%s",liq_fade_out="%s",liq_cue_in="%s",liq_cue_out="%s",schedule_table_id="%s":%s'\ - % (str(media['export_source']), media['id'], 0, str(float(media['fade_in']) / 1000), \ - str(float(media['fade_out']) / 1000), str(float(media['cue_in']) / 1000), str(float(media['cue_out']) / 1000), media['row_id'],dst) + 'annotate:export_source="%s",media_id="%s",liq_start_next="%s",liq_fade_in="%s",liq_fade_out="%s",liq_cue_in="%s",liq_cue_out="%s",schedule_table_id="%s":%s' \ + % (str(media['export_source']), media['id'], 0, \ + str(float(media['fade_in']) / 1000), \ + str(float(media['fade_out']) / 1000), \ + str(float(media['cue_in'])), \ + str(float(media['cue_out'])), \ + media['row_id'], dst) """ Tracks are only added to the playlist if they are accessible diff --git a/python_apps/pypo/pypopush.py b/python_apps/pypo/pypopush.py index ea92e6605..78f005da6 100755 --- a/python_apps/pypo/pypopush.py +++ b/python_apps/pypo/pypopush.py @@ -97,9 +97,11 @@ class PypoPush(Thread): str_tnow_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4], tnow[5]) for pkey in schedule: - plstart = pkey[0:19] + plstart = schedule[pkey]['start'][0:19] + #plstart = pkey[0:19] - playedFlag = (pkey in playedItems) and playedItems[pkey].get("played", 0) + #playedFlag = (pkey in playedItems) and playedItems[pkey].get("played", 0) + playedFlag = False if plstart == str_tcoming_s or (plstart < str_tcoming_s and plstart > str_tcoming2_s and not playedFlag): logger.debug('Preparing to push playlist scheduled at: %s', pkey)