forked from rc/aircox
		
	add 'live' log type, and handle it in streamer
This commit is contained in:
		@ -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):
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user