roll back to older logging method (we don't wan't to run logging on liquidsoap's main thread. Move monitoring in appropriate file

This commit is contained in:
bkfox 2015-12-23 12:40:57 +01:00
parent 3e038c4c16
commit 2445690da3
3 changed files with 145 additions and 99 deletions

View File

@ -13,8 +13,9 @@ from django.core.management.base import BaseCommand, CommandError
from django.template.loader import render_to_string
from django.utils import timezone as tz
import aircox.programs.models as models
import aircox.programs.models as programs
import aircox.programs.settings as programs_settings
from aircox.programs.utils import to_timedelta
import aircox.liquidsoap.settings as settings
import aircox.liquidsoap.utils as utils
@ -61,9 +62,9 @@ class StationConfig:
for stream in self.controller.streams.values():
program = stream.program
sounds = models.Sound.objects.filter(
sounds = programs.Sound.objects.filter(
# good_quality = True,
type = models.Sound.Type['archive'],
type = programs.Sound.Type['archive'],
path__startswith = os.path.join(
programs_settings.AIRCOX_SOUND_ARCHIVES_SUBDIR,
program.path
@ -73,6 +74,120 @@ class StationConfig:
file.write('\n'.join(sound.path for sound in sounds))
class Monitor:
@classmethod
def run (cl, controller):
"""
Run once the monitor on the controller
"""
if not controller.connector.available and controller.connector.open():
return
cl.run_source(controller.master)
cl.run_dealer(controller)
for stream in controller.streams.values():
cl.run_source(stream)
@staticmethod
def log (**kwargs):
"""
Create a log using **kwargs, and print info
"""
log = programs.Log(**kwargs)
log.save()
log.print()
@staticmethod
def expected_diffusion (station, date, on_air):
"""
Return which diffusion should be played now and is not playing
on the given station
"""
r = [ programs.Diffusion.get_prev(station, date),
programs.Diffusion.get_next(station, date) ]
r = [ diffusion.prefetch_related('sounds')[0]
for diffusion in r if diffusion.count() ]
for diffusion in r:
duration = to_timedelta(diffusion.archives_duration())
end_at = diffusion.date + duration
if end_at < date:
continue
diffusion.playlist = [ sound.path
for sound in diffusion.get_archives() ]
if diffusion.playlist and on_air not in diffusion.playlist:
return diffusion
@classmethod
def run_dealer (cl, controller):
"""
Monitor dealer playlist (if it is time to load) and whether it is time
to trigger the button to start a diffusion.
"""
dealer = controller.dealer
playlist = dealer.playlist
on_air = dealer.current_sound
now = tz.make_aware(tz.datetime.now())
diff = cl.expected_diffusion(controller.station, now, on_air)
if not diff:
return # there is nothing we can do
# playlist reload
if dealer.playlist != diff.playlist:
if not playlist or on_air == playlist[-1] or \
on_air not in playlist:
dealer.on = False
dealer.playlist = diff.playlist
# run the diff
if dealer.playlist == diff.playlist and diff.date <= now and not dealer.on:
dealer.on = True
for source in controller.streams.values():
source.skip()
cl.log(
source = dealer.id,
date = now,
comment = 'trigger the scheduled diffusion to liquidsoap; '
'skip all other streams',
related_object = diff,
)
@classmethod
def run_source (cl, source):
"""
Keep trace of played sounds on the given source. For the moment we only
keep track of known sounds.
"""
last_log = programs.Log.objects.filter(
source = source.id,
).prefetch_related('related_object').order_by('-date')
on_air = source.current_sound
if not on_air:
return
if last_log:
last_log = last_log[0]
if type(last_log.related_object) == programs.Sound and \
on_air == last_log.related_object.path:
return
sound = programs.Sound.objects.filter(path = on_air)
if not sound:
return
sound = sound[0]
cl.log(
source = source.id,
date = tz.make_aware(tz.datetime.now()),
comment = 'sound has changed',
related_object = sound or None,
)
class Command (BaseCommand):
help= __doc__
output_dir = settings.AIRCOX_LIQUIDSOAP_MEDIA
@ -117,33 +232,37 @@ class Command (BaseCommand):
def handle (self, *args, **options):
if options.get('station'):
station = models.Station.objects.get(id = options.get('station'))
station = programs.Station.objects.get(id = options.get('station'))
StationConfig(station).handle(options)
elif options.get('all') or options.get('config') or \
options.get('streams'):
for station in models.Station.objects.filter(active = True):
for station in programs.Station.objects.filter(active = True):
StationConfig(station).handle(options)
if options.get('on_air') or options.get('monitor'):
self.handle_monitor(options)
def handle_monitor (self, options):
self.monitor = utils.Monitor()
self.monitor.update()
controllers = [
utils.Controller(station)
for station in programs.Station.objects.filter(active = True)
]
for controller in controllers:
controller.update()
if options.get('on_air'):
for id, controller in self.monitor.controller.items():
print(id, controller.on_air)
for controller in controllers:
print(controller.id, controller.on_air)
return
if options.get('monitor'):
delay = options.get('delay') / 1000
while True:
for controller in self.monitor.controllers.values():
try:
controller.monitor()
except Exception as err:
print(err)
for controller in controllers:
#try:
Monitor.run(controller)
#except Exception as err:
# print(err)
time.sleep(delay)
return

View File

@ -2,21 +2,15 @@
{# - controller: controller used to generate the current file #}
{# - settings: global settings #}
def interactive_source (id, s) = \
def handler(m) = \
file = string.escape(m['filename']) \
system('echo {{ log_script }} -s "#{id}" -p \"#{file}\" -c "liquidsoap: play" &') \
system('{{ log_script }} -s "#{id}" -p \"#{file}\" -c "liquidsoap: play" &') \
end \
\
s = on_track(id=id, handler, s)
# s = store_metadata(id=id, size=1, s) \
s = store_metadata(id=id, size=1, s) \
add_skip_command(s) \
s \
end \
\
def stream (id, file) = \
s = playlist(id = '#{id}_playlist', mode = "random", \
reload_mode='watch', file) \
#s = playlist(id = '#{id}_playlist', mode = "random", \
# file) \
s = playlist(id = '#{id}_playlist', mode = "random", file)
interactive_source(id, s) \
end \
\
@ -66,7 +60,7 @@ set("{{ key|safe }}", {{ value|safe }}) \
{% if controller.station.fallback %}
single("{{ controller.station.fallback }}"), \
{% else %}
blank(duration=0.1), \
blank(id="scheize_blank", duration=0.1), \
{% endif %}
]) \
) \

View File

@ -6,9 +6,7 @@ import json
from django.utils.translation import ugettext as _, ugettext_lazy
from django.utils import timezone as tz
from aircox.programs.utils import to_timedelta
import aircox.programs.models as programs
import aircox.liquidsoap.models as models
import aircox.liquidsoap.settings as settings
@ -57,7 +55,7 @@ class Connector:
self.__socket.sendall(data)
data = ''
while not reg.search(data):
data += self.__socket.recv(1024).decode('unicode_escape')
data += self.__socket.recv(1024).decode('utf-8')
if data:
data = reg.sub(r'\1', data)
@ -259,59 +257,6 @@ class Dealer (Source):
return self.connector.send('var.set ', self.id, '_on',
'=', 'true' if value else 'false')
def __get_next (self, date, on_air):
"""
Return which diffusion should be played now and is not playing
"""
r = [ programs.Diffusion.get_prev(self.station, date),
programs.Diffusion.get_next(self.station, date) ]
r = [ diffusion.prefetch_related('sounds')[0]
for diffusion in r if diffusion.count() ]
for diffusion in r:
duration = to_timedelta(diffusion.archives_duration())
end_at = diffusion.date + duration
if end_at < date:
continue
diffusion.playlist = [ sound.path
for sound in diffusion.get_archives() ]
if diffusion.playlist and on_air not in diffusion.playlist:
return diffusion
def monitor (self):
"""
Monitor playlist (if it is time to load) and if it time to trigger
the button to start a diffusion.
"""
playlist = self.playlist
on_air = self.current_sound
now = tz.make_aware(tz.datetime.now())
diff = self.__get_next(now, on_air)
if not diff:
return # there is nothing we can do
# playlist reload
if self.playlist != diff.playlist:
if not playlist or on_air == playlist[-1] or \
on_air not in playlist:
self.on = False
self.playlist = diff.playlist
# run the diff
if self.playlist == diff.playlist and diff.date <= now and not self.on:
self.on = True
for source in self.controller.streams.values():
source.skip()
self.controller.log(
source = self.id,
date = now,
comment = 'trigger the scheduled diffusion to liquidsoap; '
'skip all other streams',
related_object = diff,
)
class Controller:
"""
Main class controller for station and sources (streams and dealer)
@ -356,7 +301,7 @@ class Controller:
"""
return os.path.join(self.path, 'station.liq')
def __init__ (self, station, connector = True):
def __init__ (self, station, connector = True, update = False):
"""
Params:
- station: managed station
@ -384,6 +329,9 @@ class Controller:
]
}
if update:
self.update()
def get (self, source_id):
"""
Get a source by its id
@ -394,15 +342,8 @@ class Controller:
return self.dealer
return self.streams.get(source_id)
def log (self, **kwargs):
"""
Create a log using **kwargs, and print info
"""
log = programs.Log(**kwargs)
log.save()
log.print()
def update_all (self):
def update (self):
"""
Fetch and update all streams metadata.
"""
@ -411,14 +352,6 @@ class Controller:
for source in self.streams.values():
source.update()
def monitor (self):
"""
Log changes in the streams, and call dealer.monitor.
"""
if not self.connector.available and self.connector.open():
return
self.dealer.monitor()
class Monitor:
"""
@ -437,6 +370,6 @@ class Monitor:
def update (self):
for controller in self.controllers.values():
controller.update_all()
controller.update()