liquidsoap: fix error in template, station.current_source on request's id

This commit is contained in:
bkfox 2016-07-12 22:26:36 +02:00
parent 0d75f65ed4
commit a5638f0071
6 changed files with 109 additions and 43 deletions

View File

@ -2,12 +2,25 @@ from django.contrib import admin
import aircox.controllers.models as models import aircox.controllers.models as models
class SourceInline(admin.StackedInline):
model = models.Source
extra = 0
class OutputInline(admin.StackedInline):
model = models.Output
extra = 0
@admin.register(models.Station)
class StationAdmin(admin.ModelAdmin):
inlines = [ SourceInline, OutputInline ]
#@admin.register(Log) #@admin.register(Log)
#class LogAdmin(admin.ModelAdmin): #class LogAdmin(admin.ModelAdmin):
# list_display = ['id', 'date', 'source', 'comment', 'related_object'] # list_display = ['id', 'date', 'source', 'comment', 'related_object']
# list_filter = ['date', 'source', 'related_type'] # list_filter = ['date', 'source', 'related_type']
admin.site.register(models.Station)
admin.site.register(models.Source) admin.site.register(models.Source)
admin.site.register(models.Output) admin.site.register(models.Output)
admin.site.register(models.Log) admin.site.register(models.Log)

View File

@ -51,6 +51,10 @@ class Station(programs.Nameable):
plugin.StationController plugin.StationController
""" """
@property
def id_(self):
return self.slug
def get_sources(self, type = None, prepare = True): def get_sources(self, type = None, prepare = True):
""" """
Return a list of active sources that can have their controllers Return a list of active sources that can have their controllers
@ -87,7 +91,8 @@ class Station(programs.Nameable):
""" """
List of active outputs List of active outputs
""" """
return [ output for output in self.output_set if output.active ] print(self.output_set)
return [ output for output in self.output_set.filter(active = True) ]
def prepare(self, fetch = True): def prepare(self, fetch = True):
""" """
@ -129,6 +134,32 @@ class Station(programs.Nameable):
if self.plugin_name: if self.plugin_name:
self.plugin = Plugins.registry.get(self.plugin_name) self.plugin = Plugins.registry.get(self.plugin_name)
def play_logs(self, include_diffusions = True,
include_sounds = True,
exclude_archives = True):
"""
Return a queryset with what is playing on air for this station.
Ordered by date ascending.
"""
models = []
if include_diffusions: models.append(programs.Diffusion)
if include_sounds: models.append(programs.Sound)
qs = Log.get_for(model = models) \
.filter(station = station, type = Log.Type.play)
if exclude_archives and self.dealer:
qs = qs.exclude(
source = self.dealer.id_,
related_type = ContentType.objects.get_for_model(
program.Sound
)
)
return qs.order_by('date')
def save(self, make_sources = True, *args, **kwargs): def save(self, make_sources = True, *args, **kwargs):
""" """
* make_sources: if the model has not been yet saved, generate * make_sources: if the model has not been yet saved, generate
@ -216,6 +247,10 @@ class Source(programs.Nameable):
implements plugin.SourceController; implements plugin.SourceController;
""" """
@property
def id_(self):
return self.slug
@property @property
def stream(self): def stream(self):
if self.type != self.Type.stream or not self.program: if self.type != self.Type.stream or not self.program:
@ -392,8 +427,14 @@ class Log(models.Model):
if not model and object: if not model and object:
model = type(object) model = type(object)
qs = cl.objects.filter(related_type__pk = if type(model) in (list, tuple):
ContentTYpe.objects.get_for_model(model).id) model = [ ContentType.objects.get_for_model(m).id
for m in model ]
qs = cl.objects.filter(related_type__pk__in = model)
else:
model = ContentType.objects.get_for_model(model)
qs = cl.objects.filter(related_type__pk = model.id)
if object: if object:
qs = qs.filter(related_id = object.pk) qs = qs.filter(related_id = object.pk)
return qs return qs
@ -408,7 +449,7 @@ class Log(models.Model):
def __str__(self): def __str__(self):
return '#{} ({}, {})'.format( return '#{} ({}, {})'.format(
self.id, self.date.strftime('%Y/%m/%d %H:%M'), self.source.name self.pk, self.date.strftime('%Y/%m/%d %H:%M'), self.source.name
) )

View File

@ -12,6 +12,18 @@ class Monitor:
do that. do that.
""" """
station = None station = None
controller = None
def run(self):
"""
Run all monitoring functions. Ensure that station has controllers
"""
if not self.controller:
self.station.prepare()
self.controller = self.station.controller
self.track()
self.handler()
@staticmethod @staticmethod
def log(**kwargs): def log(**kwargs):
@ -27,25 +39,23 @@ class Monitor:
Check the current_sound of the station and update logs if Check the current_sound of the station and update logs if
needed needed
""" """
station = self.station self.controller.fetch()
station.controller.fetch() current_sound = self.controller.current_sound
current_source = self.controller.current_source
current_sound = station.controller.current_sound
current_source = station.controller.current_source
if not current_sound: if not current_sound:
return return
log = Log.get_for(model = programs.Sound) \ log = Log.get_for(model = programs.Sound) \
.filter(station = station).order_by('date').last() .filter(station = self.station).order_by('date').last()
# TODO: expiration # TODO: expiration
if log and (log.source == current_source and \ if log and (log.source == current_source.id_ and \
log.related.path == current_sound): log.related.path == current_sound):
return return
sound = programs.Sound.object.filter(path = current_sound) sound = programs.Sound.object.filter(path = current_sound)
self.log( self.log(
type = Log.Type.play, type = Log.Type.play,
source = current_source, source = current_source.id_,
date = tz.make_aware(tz.datetime.now()), date = tz.make_aware(tz.datetime.now()),
related = sound[0] if sound else None, related = sound[0] if sound else None,
@ -60,17 +70,21 @@ class Monitor:
station = self.station station = self.station
now = tz.make_aware(tz.datetime.now()) now = tz.make_aware(tz.datetime.now())
sound_log = Log.get_for(model = programs.Sound) \
.filter(station = station).order_by('date').last()
diff_log = Log.get_for(model = programs.Diffusion) \ diff_log = Log.get_for(model = programs.Diffusion) \
.filter(station = station).order_by('date').last() .filter(station = station, type = Log.Type.play) \
.order_by('date').last()
if not sound_log or not diff_log or \ if not diff_log or \
sound_log.source != diff_log.source or \ not diff_log.related.is_date_in_my_range(now):
diff_log.related.is_date_in_my_range(now) :
return None, [] return None, []
# last registered diff is still playing: update the playlist # sound has switched? assume it has been (forced to) stopped
sound_log = Log.get_for(model = programs.Sound) \
.filter(station = station).order_by('date').last()
if sound_log and sound_log.source != diff_log.source:
return None, []
# last diff is still playing: get the remaining playlist
sounds = Log.get_for(model = programs.Sound) \ sounds = Log.get_for(model = programs.Sound) \
.filter(station = station, source = diff_log.source) \ .filter(station = station, source = diff_log.source) \
.filter(pk__gt = diff.log.pk) .filter(pk__gt = diff.log.pk)
@ -94,13 +108,13 @@ class Monitor:
diff = programs.Diffusion.get( diff = programs.Diffusion.get(
now, now = True, now, now = True,
type = programs.Diffusion.Type.normal, type = programs.Diffusion.Type.normal,
sound__type = programs.Sound.Type.archive, sound__type = programs.Sound.Type.archive,
sound__removed = False, sound__removed = False,
**args **args
).distinct().order_by('start').first() ).distinct().order_by('start').first()
return (diff, diff and diff.playlist or []) return (diff, diff and diff.playlist or [])
def handle(self): def handle(self):
""" """
Handle scheduled diffusion, trigger if needed, preload playlists Handle scheduled diffusion, trigger if needed, preload playlists
@ -116,7 +130,7 @@ class Monitor:
diff, playlist = self.__current_diff() diff, playlist = self.__current_diff()
dealer.on = bool(playlist) dealer.on = bool(playlist)
next_diff, next_playlist = self.__next_diff() next_diff, next_playlist = self.__next_diff(diff)
playlist += next_playlist playlist += next_playlist
# playlist update # playlist update
@ -125,7 +139,7 @@ class Monitor:
if next_diff: if next_diff:
self.log( self.log(
type = Log.Type.load, type = Log.Type.load,
source = dealer.id, source = dealer.id_,
date = now, date = now,
related_object = next_diff related_object = next_diff
) )
@ -137,7 +151,7 @@ class Monitor:
source.controller.skip() source.controller.skip()
cl.log( cl.log(
type = Log.Type.play, type = Log.Type.play,
source = dealer.id, source = dealer.id_,
date = now, date = now,
related_object = next_diff, related_object = next_diff,
) )

View File

@ -34,17 +34,20 @@ class StationController(plugins.StationController):
def fetch(self): def fetch(self):
super().fetch() super().fetch()
data = self._send('request.on_air') rid = self._send('request.on_air')
if not data: if not rid:
return return
data = self._send('request.metadata', data, parse = True) data = self._send('request.metadata', rid, parse = True)
if not data: if not data:
return return
self.current_sound = data.get('initial_uri') self.current_sound = data.get('initial_uri')
# FIXME: point to the Source object self.current_source = [
self.current_source = data.get('source') # we assume sound is always from a registered source
source for source in self.station.get_sources()
if source.rid = rid
][0]
class SourceController(plugins.SourceController): class SourceController(plugins.SourceController):
@ -77,10 +80,7 @@ class SourceController(plugins.SourceController):
if not data: if not data:
return return
# FIXME: still usefull? originally tested only if there ass self.program self.rid = data.get('rid')
source = data.get('source') or ''
if not source.startswith(self.id):
return
self.current_sound = data.get('initial_uri') self.current_sound = data.get('initial_uri')
def stream(self): def stream(self):

View File

@ -53,10 +53,10 @@ class StationController:
""" """
Current sound being played (retrieved by fetch) Current sound being played (retrieved by fetch)
""" """
current_source = None
@property """
def id(self): Current source object that is responsible of self.current_sound
return '{station.slug}_{station.pk}'.format(station = self.station) """
# TODO: add function to launch external program? # TODO: add function to launch external program?
@ -72,6 +72,7 @@ class StationController:
""" """
sources = self.station.get_sources() sources = self.station.get_sources()
for source in sources: for source in sources:
source.prepare()
if source.controller: if source.controller:
source.controller.fetch() source.controller.fetch()
@ -110,7 +111,6 @@ class StationController:
pass pass
class SourceController: class SourceController:
""" """
Controller of a Source. Value are usually updated directly on the Controller of a Source. Value are usually updated directly on the
@ -138,10 +138,6 @@ class SourceController:
Current source being responsible of the current sound Current source being responsible of the current sound
""" """
@property
def id(self):
return '{source.station.slug}_{source.slug}'.format(source = self.source)
__playlist = None __playlist = None
@property @property

View File

@ -39,7 +39,9 @@
- list of played diffusions and tracks when non-stop; - list of played diffusions and tracks when non-stop;
# Long term TODO # Long term TODO
- automatic cancel of passed diffusion based on logs - automatic cancel of passed diffusion based on logs?
- archives can be set afterwards for rerun, so check must be done
at the same time we monitor
- sounds monitor: max_size of path, take in account - sounds monitor: max_size of path, take in account
- logs: archive functionnality - logs: archive functionnality
- track stats for diffusions - track stats for diffusions