add 'live' log type, and handle it in streamer

This commit is contained in:
bkfox 2017-06-27 20:58:29 +02:00
parent 086eb7ba2f
commit 8a129da46a
2 changed files with 91 additions and 67 deletions

View File

@ -18,6 +18,13 @@ from django.utils import timezone as tz
from aircox.models import Station, Diffusion, Track, Sound, Log from aircox.models import Station, Diffusion, Track, Sound, Log
class Tracer:
"""
Keep trace of played item and update logs in adequation to it
"""
pass
class Monitor: class Monitor:
""" """
Log and launch diffusions for the given station. Log and launch diffusions for the given station.
@ -65,11 +72,12 @@ class Monitor:
self.sync_playlists() self.sync_playlists()
self.handle() self.handle()
def log(self, **kwargs): def log(self, date = None, **kwargs):
""" """
Create a log using **kwargs, and print info Create a log using **kwargs, and print info
""" """
log = Log(station = self.station, **kwargs) log = Log(station = self.station, date = date or tz.now(),
**kwargs)
log.save() log.save()
log.print() log.print()
@ -147,8 +155,8 @@ class Monitor:
for source in self.station.sources: for source in self.station.sources:
if source == self.station.dealer: if source == self.station.dealer:
continue continue
playlist = [ sound.path for sound in playlist = source.program.sound_set.all() \
source.program.sound_set.all() ] .values_list('path', flat = True)
source.playlist = playlist source.playlist = playlist
def trace_canceled(self): def trace_canceled(self):
@ -187,52 +195,78 @@ class Monitor:
station = self.station station = self.station
now = tz.now() now = tz.now()
diff_log = station.played(models = Diffusion) \ log = station.played(models = Diffusion).order_by('date').last()
.order_by('date').last() if not log or not log.related.is_date_in_range(now):
if not diff_log or \ # not running anymore
not diff_log.related.is_date_in_range(now):
return None, [] return None, []
# sound has switched? assume it has been (forced to) stopped # sound has switched? assume it has been (forced to) stopped
sounds = station.played(models = Sound) \ sounds = station.played(models = Sound) \
.filter(date__gte = diff_log.date) \ .filter(date__gte = log.date) \
.order_by('date') .order_by('date')
if sounds.last() and sounds.last().source != diff_log.source: # last sound source change: end of file reached
return diff_log, [] if sounds.count() and sounds.last().source != log.source:
# diffusion is finished: end of sound file reached
return None, []
# last diff is still playing: get the remaining playlist # last diff is still playing: get remaining playlist
sounds = sounds.filter( sounds = sounds \
source = diff_log.source, pk__gt = diff_log.pk .filter(source = log.source, pk__gt = diff_log.pk) \
) .exclude(related__type = Sound.Type.removed)
sounds = [ .values_list('related__path', flat = True)
sound.related.path for sound in sounds remaining = log.related.get_archives().exclude(path__in = sounds)
if sound.related.type != Sound.Type.removed
]
return ( return log.related, remaining
diff_log.related,
[ path for path in diff_log.related.playlist
if path not in sounds ]
)
def __next_diff(self, diff): def __next_diff(self, diff):
""" """
Return the tuple with the next diff that should be played and Return the next diffusion to be played as tuple of (diff, playlist).
the playlist If diff is given, it is the one to be played right after it.
Note: diff is a log
""" """
station = self.station station = self.station
now = tz.now() now = tz.now()
args = {'start__gt': diff.date } if diff else {} kwargs = {'start__gte': diff.end } if diff else {}
diff = Diffusion.objects.at(station, now).filter( diff = Diffusion.objects \
type = Diffusion.Type.normal, .at(station, now) \
sound__type = Sound.Type.archive, .filter(type = Diffusion.Type.normal,
**args sound_type = Sound.Type.archive, **kwargs) \
).distinct().order_by('start').first() .distinct().order_by('start').first()
return (diff, diff and diff.playlist or []) return diff
def handle_pl_sync(self, source, playlist, diff = None, date = None):
"""
Update playlist of a source if required, and handle logging when
it is needed.
"""
dealer = self.station.dealer
if dealer.playlist != playlist:
dealer.playlist = playlist
if diff and not diff.is_live():
self.log(type = Log.Type.load, source = source.id,
related = diff, date = date)
def handle_diff_start(self, source, diff, date):
"""
Enable dealer in order to play a given diffusion if required,
handle start of diffusion
"""
if not diff or not diff.start <= now:
return
# live: just log it
if diff.is_live():
if not Log.get_for(object = diff).count():
self.log(type = Log.Type.live, source = source.id,
related = diff, date = date)
return
# enable dealer
if not dealer.active:
dealer.active = True
self.log(type = Log.Type.play, source = source.id,
related = diff, date = date)
def handle(self): def handle(self):
""" """
@ -246,33 +280,15 @@ class Monitor:
now = tz.now() now = tz.now()
# current and next diffs # current and next diffs
diff, playlist = self.__current_diff() current_diff, current_pl = self.__current_diff()
dealer.active = bool(playlist) next_diff, next_pl = self.__next_diff(diff)
next_diff, next_playlist = self.__next_diff(diff) # playlist
playlist += next_playlist dealer.active = bool(current_pl)
playlist = current_pl + next_pl
# playlist update self.handle_pl_sync(dealer, playlist, next_diff, now)
if dealer.playlist != playlist: self.handle_diff_start(dealer, next_diff)
dealer.playlist = playlist
if next_diff:
self.log(
type = Log.Type.load,
source = dealer.id,
date = now,
related = next_diff
)
# dealer.on when next_diff start <= now
if next_diff and not dealer.active and \
next_diff.start <= now:
dealer.active = True
self.log(
type = Log.Type.play,
source = dealer.id,
date = now,
related = next_diff,
)
class Command (BaseCommand): class Command (BaseCommand):

View File

@ -231,11 +231,11 @@ class Station(Nameable):
self.__prepare() self.__prepare()
return self.__streamer return self.__streamer
def played(self, models, archives = True): def played(self, models, archives = True, include_live = True):
""" """
Call Log.objects.played for this station Call Log.objects.played for this station
""" """
return Log.objects.played(self, models, archives) return Log.objects.played(self, models, archives, include_live)
@staticmethod @staticmethod
def __mix_logs_and_diff(diffs, logs, count = 0): def __mix_logs_and_diff(diffs, logs, count = 0):
@ -867,7 +867,7 @@ class Diffusion(models.Model):
""" """
List of archives' path; uses get_archives List of archives' path; uses get_archives
""" """
return [ sound.path for sound in self.get_archives() ] return self.get_archives().values_list('path', flat = True)
def get_archives(self): def get_archives(self):
""" """
@ -1260,7 +1260,7 @@ class LogManager(RelatedManager):
qs = self.get_for(station, object, model, qs) qs = self.get_for(station, object, model, qs)
return self._at(date, qs) return self._at(date, qs)
def played(self, station, models, archives = True): def played(self, station, models, archives = True, include_live = True):
""" """
Return a queryset of the played elements' log for the given Return a queryset of the played elements' log for the given
station and model. This queryset is ordered by date ascending station and model. This queryset is ordered by date ascending
@ -1270,8 +1270,12 @@ class LogManager(RelatedManager):
* archives: if false, exclude log of diffusion's archives from * archives: if false, exclude log of diffusion's archives from
the queryset; the queryset;
""" """
qs = self.get_for(station, model = models) \ if include_live:
.filter(type = Log.Type.play) qs = self.get_for(station, model = models) \
.filter(type__in = (Log.Type.play, Log.Type.live))
else:
qs = self.get_for(station, model = models) \
.filter(type = Log.Type.play)
if not archives and station.dealer: if not archives and station.dealer:
qs = qs.exclude( qs = qs.exclude(
@ -1303,7 +1307,11 @@ class Log(Related):
""" """
Source starts to be preload related_object Source starts to be preload related_object
""" """
other = 0x03 live = 0x03
"""
A diffusion occured, but in live (no sound played by Aircox)
"""
other = 0x04
""" """
Other log Other log
""" """