add script to import playlists to sounds or to diffusions

This commit is contained in:
bkfox
2016-07-15 18:23:08 +02:00
parent f458583f68
commit 161af3fb1a
12 changed files with 393 additions and 122 deletions

View File

@ -39,6 +39,11 @@ class Station(programs.Nameable):
max_length = 32,
choices = [ (name, name) for name in Plugins.registry.keys() ],
)
active = models.BooleanField(
_('active'),
default = True,
help_text = _('this station is active')
)
plugin = None
"""
@ -127,24 +132,22 @@ class Station(programs.Nameable):
if self.plugin_name:
self.plugin = Plugins.registry.get(self.plugin_name)
def play_logs(self, include_diffusions = True,
include_sounds = True,
exclude_archives = True):
def get_played(self, models, archives = True):
"""
Return a queryset with log of played elements on this station.
Ordered by date ascending.
"""
models = []
if include_diffusions: models.append(programs.Diffusion)
if include_sounds: models.append(programs.Sound)
Return a queryset with log of played elements on this station,
of the given models, ordered by date ascending.
* model: a model or a list of models
* archive: if false, exclude log of diffusion's archives from
the queryset;
"""
qs = Log.get_for(model = models) \
.filter(station = station, type = Log.Type.play)
if exclude_archives and self.dealer:
if not archives and self.dealer:
qs = qs.exclude(
source = self.dealer.id_,
related_type = ContentType.objects.get_for_model(
program.Sound
programs.Sound
)
)
return qs.order_by('date')
@ -294,7 +297,6 @@ class Source(programs.Nameable):
raise ValueError('can not save a dealer source')
super().save(*args, **kwargs)
# TODO update controls
class Output (models.Model):
@ -326,7 +328,7 @@ class Output (models.Model):
)
class Log(models.Model):
class Log(programs.Related):
"""
Log sounds and diffusions that are played on the station.
@ -376,16 +378,6 @@ class Log(models.Model):
max_length = 512,
blank = True, null = True,
)
related_type = models.ForeignKey(
ContentType,
blank = True, null = True,
)
related_id = models.PositiveIntegerField(
blank = True, null = True,
)
related = GenericForeignKey(
'related_type', 'related_id',
)
@property
def end(self):
@ -407,29 +399,6 @@ class Log(models.Model):
date = programs.date_or_default(date)
return self.end < date
@classmethod
def get_for(cl, object = None, model = None):
"""
Return a queryset that filter on the related object. If object is
given, filter using it, otherwise only using model.
If model is not given, uses object's type.
"""
if not model and object:
model = type(object)
if type(model) in (list, tuple):
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:
qs = qs.filter(related_id = object.pk)
return qs
def print(self):
logger.info('log #%s: %s%s',
str(self),

View File

@ -10,6 +10,11 @@ class Monitor:
Monitor should be able to be used after a crash a go back
where it was playing, so we heavily use logs to be able to
do that.
We keep trace of played items on the generated stream:
- sounds played on this stream;
- scheduled diffusions
- tracks for sounds of streamed programs
"""
station = None
controller = None
@ -22,11 +27,10 @@ class Monitor:
self.station.prepare()
self.controller = self.station.controller
self.track()
self.trace()
self.handler()
@staticmethod
def log(**kwargs):
def log(self, **kwargs):
"""
Create a log using **kwargs, and print info
"""
@ -34,10 +38,10 @@ class Monitor:
log.save()
log.print()
def track(self):
def trace(self):
"""
Check the current_sound of the station and update logs if
needed
needed.
"""
self.controller.fetch()
current_sound = self.controller.current_sound
@ -47,6 +51,11 @@ class Monitor:
log = Log.get_for(model = programs.Sound) \
.filter(station = self.station).order_by('date').last()
# only streamed
if log and not log.related.diffusion:
self.trace_sound_tracks(log)
# TODO: expiration
if log and (log.source == current_source.id_ and \
log.related.path == current_sound):
@ -56,12 +65,37 @@ class Monitor:
self.log(
type = Log.Type.play,
source = current_source.id_,
date = tz.make_aware(tz.datetime.now()),
date = tz.now(),
related = sound[0] if sound else None,
comment = None if sound else current_sound,
)
def trace_sound_tracks(self, log):
"""
Log tracks for the given sound (for streamed programs); Called by
self.trace
"""
logs = Log.get_for(model = programs.Track) \
.filter(pk__gt = log.pk)
logs = [ log.pk for log in logs ]
tracks = programs.Track.get_for(object = log.related)
.filter(pos_in_sec = True)
if len(tracks) == len(logs):
return
tracks = tracks.exclude(pk__in = logs).order_by('pos')
now = tz.now()
for track in tracks:
pos = log.date + tz.timedelta(seconds = track.pos)
if pos < now:
self.log(
type = Log.Type.play,
source = log.source,
date = pos,
related = track
)
def __current_diff(self):
"""
Return a tuple with the currently running diffusion and the items
@ -70,24 +104,23 @@ class Monitor:
station = self.station
now = tz.make_aware(tz.datetime.now())
diff_log = Log.get_for(model = programs.Diffusion) \
.filter(station = station, type = Log.Type.play) \
.order_by('date').last()
diff_log = station.get_played(models = programs.Diffusion) \
.order_by('date').last()
if not diff_log or \
not diff_log.related.is_date_in_my_range(now):
return None, []
# 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:
sounds = station.get_played(models = programs.Sound)
last_sound = sounds.order_by('date').last()
if last_sound and last_sound.source != diff_log.source:
return None, []
# last diff is still playing: get the remaining playlist
sounds = Log.get_for(model = programs.Sound) \
.filter(station = station, source = diff_log.source) \
.filter(pk__gt = diff.log.pk)
sounds = sounds.filter(
source = diff_log.source, pk__gt = diff_log.pk
)
sounds = [ sound.path for sound in sounds if not sound.removed ]
return (