cc-2015: on reboot resume show

-liquidsoap is having some problems with cue points right now
 need to check if this is my fault.
This commit is contained in:
martin 2011-06-15 18:23:12 -04:00
parent e5ed11ee51
commit e90e6d7c12
10 changed files with 248 additions and 270 deletions

View File

@ -1,4 +1,5 @@
SUBDIRS = tests
DISTFILES = $(wildcard *.in) Makefile ask-liquidsoap.rb ask-liquidsoap.pl \ DISTFILES = $(wildcard *.in) Makefile ask-liquidsoap.rb ask-liquidsoap.pl \
$(wildcard *.liq) extract-replaygain $(wildcard *.liq) extract-replaygain

View File

@ -9,37 +9,43 @@ my_get_mime = get_mime
get_mime = my_get_mime get_mime = my_get_mime
%ifdef add_decoder %ifdef add_decoder
if test_process("which flac") then # Enable external FLAC decoders. Requires flac binary
log(level=3,"Found flac binary: enabling flac external decoder.") # in the path for audio decoding and metaflac binary for
flac_p = "flac -d -c - 2>/dev/null" # metadata. Does not work on Win32. Default: disabled.
def test_flac(file) = # Please note that built-in support for FLAC is available
if test_process("which metaflac") then # in liquidsoap if compiled and should be preferred over
channels = list.hd(get_process_lines("metaflac \ # the external decoder.
--show-channels #{quote(file)} \ # @category Liquidsoap
2>/dev/null")) def enable_external_flac_decoder() =
# If the value is not an int, this returns 0 and we are ok :) if test_process("which flac") then
int_of_string(channels) log(level=3,"Found flac binary: enabling flac external decoder.")
else flac_p = "flac -d -c - 2>/dev/null"
# Try to detect using mime test.. def test_flac(file) =
mime = get_mime(file) if test_process("which metaflac") then
if string.match(pattern="flac",file) then channels = list.hd(get_process_lines("metaflac \
# We do not know the number of audio channels --show-channels #{quote(file)} \
# so setting to -1 2>/dev/null"))
(-1) # If the value is not an int, this returns 0 and we are ok :)
int_of_string(channels)
else else
# All tests failed: no audio decodable using flac.. # Try to detect using mime test..
0 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
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 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 if test_process("which metaflac") then
log(level=3,"Found metaflac binary: enabling flac external metadata \ log(level=3,"Found metaflac binary: enabling flac external metadata \
resolver.") resolver.")
@ -55,49 +61,59 @@ if os.type != "Win32" then
if list.length(l) >= 1 then if list.length(l) >= 1 then
list.append([(list.hd(l),"")],l') list.append([(list.hd(l),"")],l')
else else
l' l'
end
end end
end end
list.fold(f,[],ret) end
list.fold(f,[],ret)
end end
add_metadata_resolver("FLAC",flac_meta) add_metadata_resolver("FLAC",flac_meta)
else 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
end end
%endif
# A list of know extensions and content-type for AAC. %ifdef add_oblivious_decoder
# Values from http://en.wikipedia.org/wiki/Advanced_Audio_Coding # Enable or disable external FAAD (AAC/AAC+/M4A) decoders.
# TODO: can we register a setting for that ?? # Requires faad binary in the path for audio decoding and
aac_mimes = # metaflac binary for metadata. Does not work on Win32.
["audio/aac", "audio/aacp", "audio/3gpp", "audio/3gpp2", "audio/mp4", # Please note that built-in support for faad is available
"audio/MP4A-LATM", "audio/mpeg4-generic", "audio/x-hx-aac-adts"] # in liquidsoap if compiled and should be preferred over
aac_filexts = ["m4a", "m4b", "m4p", "m4v", # the external decoder.
"m4r", "3gp", "mp4", "aac"] # @category Liquidsoap
def enable_external_faad_decoder() =
# Faad is not very selective so # A list of know extensions and content-type for AAC.
# We are checking only file that # Values from http://en.wikipedia.org/wiki/Advanced_Audio_Coding
# end with a known extension or mime type # TODO: can we register a setting for that ??
def faad_test(file) = aac_mimes =
# Get the file's mime ["audio/aac", "audio/aacp", "audio/3gpp", "audio/3gpp2", "audio/mp4",
mime = get_mime(file) "audio/MP4A-LATM", "audio/mpeg4-generic", "audio/x-hx-aac-adts"]
# Test mime aac_filexts = ["m4a", "m4b", "m4p", "m4v",
if list.mem(mime,aac_mimes) then "m4r", "3gp", "mp4", "aac"]
true
else # Faad is not very selective so
# Otherwise test file extension # We are checking only file that
ret = string.extract(pattern='\.(.+)$',file) # 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 if list.length(ret) != 0 then
ext = ret["1"] ext = ret["1"]
list.mem(ext,aac_filexts) list.mem(ext,aac_filexts)
else else
false false
end end
end
end end
end
if os.type != "Win32" then
if test_process("which faad") then if test_process("which faad") then
log(level=3,"Found faad binary: enabling external faad decoder and \ log(level=3,"Found faad binary: enabling external faad decoder and \
metadata resolver.") metadata resolver.")
@ -120,15 +136,13 @@ if os.type != "Win32" then
0 0
end end
end end
%ifdef add_oblivious_decoder
add_oblivious_decoder(name="FAAD",description="Decode files using \ add_oblivious_decoder(name="FAAD",description="Decode files using \
the faad binary.", test=test_faad, faad_p) the faad binary.", test=test_faad, faad_p)
%endif
def faad_meta(file) = def faad_meta(file) =
if faad_test(file) then if faad_test(file) then
ret = get_process_lines("faad -i \ ret = get_process_lines("faad -i \
#{quote(file)} 2>&1") #{quote(file)} 2>&1")
# Yea, this is tuff programming (again) ! # Yea, this is ugly programming (again) !
def get_meta(l,s)= def get_meta(l,s)=
ret = string.extract(pattern="^(\w+):\s(.+)$",s) ret = string.extract(pattern="^(\w+):\s(.+)$",s)
if list.length(ret) > 0 then 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.") log(level=3,"Did not find faad binary: faad decoder disabled.")
end end
end end
%endif
# Standard function for displaying metadata. # Standard function for displaying metadata.
# Shows artist and title, using "Unknown" when a field is empty. # 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)} ' ^ ' -t #{time} #{quote(title)} '
on_metadata(fun (m) -> system(send^quote(display(m))),s) on_metadata(fun (m) -> system(send^quote(display(m))),s)
end 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

View File

View File

@ -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))

View File

@ -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

View File

@ -300,6 +300,25 @@ def server.insert_metadata(~id="",s) =
s s
end 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. # Get the base name of a path.
# Implemented using the corresponding shell command. # Implemented using the corresponding shell command.
# @category System # @category System
@ -479,59 +498,95 @@ def smart_crossfade (~start_next=5.,~fade_in=3.,~fade_out=3.,
end end
# Custom playlist source written using the script language. # 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 # @category Source / Input
# @param ~id Force the value of the source ID.
# @param ~random Randomize playlist content # @param ~random Randomize playlist content
# @param ~on_done Function to execute when the playlist is finished # @param ~on_done Function to execute when the playlist is finished
# @param uri Playlist URI # @param uri Playlist URI
def playlist.once(~random=false,~on_done={()},uri) def playlist.reloadable(~id="",~random=false,~on_done={()},uri)
x = ref 0 # A reference to the playlist
def playlist.custom(files) playlist = ref []
length = list.length(files) # A reference to the uri
if length == 0 then playlist_uri = ref uri
log("Empty playlist..") # A reference to know if the source
fail () # has been stopped
else has_stopped = ref false
files = # The next function
if random then def next () =
list.sort(fun (x,y) -> int_of_float(random.float()), files) file =
else if list.length(!playlist) > 0 then
files ret = list.hd(!playlist)
end playlist := list.tl(!playlist)
def next () = ret
state = !x else
file = # Playlist finished
if state < length then if not !has_stopped then
x := state + 1
list.nth(files,state)
else
# Playlist finished
on_done () on_done ()
""
end end
request.create(file) has_stopped := true
""
end 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
end end
if test_process("test -d #{quote(uri)}") then # The reload function
files = get_process_lines("find #{quote(uri)} -type f | sort") def reload(~uri="") =
playlist.custom(files) if uri != "" then
else playlist_uri := uri
playlist = request.create.raw(uri) end
result = log(label=id,"Reloading playlist with URI #{!playlist_uri}")
if request.resolve(playlist) then has_stopped := false
playlist = request.filename(playlist) load_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
end 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 end
# Mixes two streams, with faded transitions between the state when only the # 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) add_timeout(freq,check)
end end
# Register the replaygain protocol # Register the replaygain protocol.
# @category Liquidsoap
def replaygain_protocol(arg,delay) def replaygain_protocol(arg,delay)
# The extraction program # The extraction program
extract_replaygain = "#{configure.libdir}/extract-replaygain" extract_replaygain = "#{configure.libdir}/extract-replaygain"

View File

@ -7,6 +7,7 @@ set("server.telnet", true)
set("server.telnet.port", 1234) set("server.telnet.port", 1234)
queue = request.queue(id="queue", length=0.5) queue = request.queue(id="queue", length=0.5)
queue = cue_cut(queue)
queue = audio_to_stereo(queue) queue = audio_to_stereo(queue)
pypo_data = ref '0' pypo_data = ref '0'

View File

@ -37,7 +37,6 @@ from configobj import ConfigObj
# custom imports # custom imports
from util import * from util import *
from api_clients import * from api_clients import *
from dls import *
# Set up command-line options # Set up command-line options
parser = OptionParser() parser = OptionParser()

View File

@ -12,6 +12,7 @@ import math
from threading import Thread from threading import Thread
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
from datetime import datetime from datetime import datetime
from datetime import timedelta
# For RabbitMQ # For RabbitMQ
from kombu.connection import BrokerConnection 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(" * 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.") logger.error(" * and also the 'FAQ and Support' page underneath it.")
"""
def get_currently_scheduled(self, playlistsOrMedias, str_tnow_s): def get_currently_scheduled(self, playlistsOrMedias, str_tnow_s):
for key in playlistsOrMedias: for key in playlistsOrMedias:
start = playlistsOrMedias[key]['start'] start = playlistsOrMedias[key]['start']
@ -114,9 +116,6 @@ class PypoFetch(Thread):
dtnow = datetime.today() dtnow = datetime.today()
tnow = dtnow.timetuple() 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]) 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) 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 delta = dtnow - media_start #we get a TimeDelta object from this operation
logger.info("Starting media item at %d second point", delta.seconds) logger.info("Starting media item at %d second point", delta.seconds)
"""
""" """
Process the schedule Process the schedule
@ -148,9 +148,9 @@ class PypoFetch(Thread):
logger = logging.getLogger('fetch') logger = logging.getLogger('fetch')
playlists = schedule_data["playlists"] playlists = schedule_data["playlists"]
if bootstrapping: #if bootstrapping:
#TODO: possible allow prepare_playlists to handle this. #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"]) 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 # Download all the media and put playlists in liquidsoap "annotate" format
try: try:
liquidsoap_playlists = self.prepare_playlists(playlists) liquidsoap_playlists = self.prepare_playlists(playlists, bootstrapping)
except Exception, e: logger.error("%s", e) except Exception, e: logger.error("%s", e)
# Send the data to pypo-push # Send the data to pypo-push
@ -190,7 +190,7 @@ class PypoFetch(Thread):
and stored in a playlist folder. and stored in a playlist folder.
file is e.g. 2010-06-23-15-00-00/17_cue_10.132-123.321.mp3 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') logger = logging.getLogger('fetch')
liquidsoap_playlists = dict() liquidsoap_playlists = dict()
@ -211,18 +211,18 @@ class PypoFetch(Thread):
try: try:
os.mkdir(self.cache_dir + str(pkey)) os.mkdir(self.cache_dir + str(pkey))
except Exception, e: except Exception, e:
pass logger.error(e)
#June 13, 2011: Commented this block out since we are not currently setting this to '1' #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 #on the server side. Currently using a different method to detect if already played - Martin
#if int(playlist['played']) == 1: #if int(playlist['played']) == 1:
# logger.info("playlist %s already played / sent to liquidsoap, so will ignore it", pkey) # 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 liquidsoap_playlists[pkey] = ls_playlist
except Exception, e: except Exception, e:
logger.info("%s", e) logger.error("%s", e)
return liquidsoap_playlists return liquidsoap_playlists
@ -231,17 +231,43 @@ class PypoFetch(Thread):
This handles both remote and local files. This handles both remote and local files.
Returns an updated ls_playlist string. Returns an updated ls_playlist string.
""" """
def handle_media_file(self, playlist, pkey): def handle_media_file(self, playlist, pkey, bootstrapping):
ls_playlist = []
logger = logging.getLogger('fetch') 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] media = playlist['medias'][key]
logger.debug("Processing track %s", media['uri']) 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] fileExt = os.path.splitext(media['uri'])[1]
try: 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)) dst = "%s%s/%s%s" % (self.cache_dir, str(pkey), str(media['id']), str(fileExt))
# download media file # download media file
@ -256,9 +282,13 @@ class PypoFetch(Thread):
if fsize > 0: if fsize > 0:
pl_entry = \ 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'\ '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(media['export_source']), media['id'], 0, \
str(float(media['fade_out']) / 1000), str(float(media['cue_in']) / 1000), str(float(media['cue_out']) / 1000), media['row_id'],dst) 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 Tracks are only added to the playlist if they are accessible

View File

@ -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]) 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: 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): 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) logger.debug('Preparing to push playlist scheduled at: %s', pkey)