change strategy on liquidsoap logging
This commit is contained in:
		@ -70,7 +70,7 @@ class PostListView (PostBaseView, ListView):
 | 
			
		||||
                return
 | 
			
		||||
            self.__dict__.update(query)
 | 
			
		||||
 | 
			
		||||
    template_name = 'aircox_cms/list.html'
 | 
			
		||||
    template_name = 'aircox/cms/list.html'
 | 
			
		||||
    allow_empty = True
 | 
			
		||||
    paginate_by = 50
 | 
			
		||||
    model = None
 | 
			
		||||
@ -143,7 +143,7 @@ class PostDetailView (DetailView, PostBaseView):
 | 
			
		||||
    """
 | 
			
		||||
    Detail view for posts and children
 | 
			
		||||
    """
 | 
			
		||||
    template_name = 'aircox_cms/detail.html'
 | 
			
		||||
    template_name = 'aircox/cms/detail.html'
 | 
			
		||||
 | 
			
		||||
    sections = []
 | 
			
		||||
 | 
			
		||||
@ -179,7 +179,7 @@ class PostDetailView (DetailView, PostBaseView):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Menu (View):
 | 
			
		||||
    template_name = 'aircox_cms/menu.html'
 | 
			
		||||
    template_name = 'aircox/cms/menu.html'
 | 
			
		||||
 | 
			
		||||
    name = ''
 | 
			
		||||
    tag = 'nav'
 | 
			
		||||
@ -218,7 +218,7 @@ class BaseSection (View):
 | 
			
		||||
    Base class for sections. Sections are view that can be used in detail view
 | 
			
		||||
    in order to have extra content about a post, or in menus.
 | 
			
		||||
    """
 | 
			
		||||
    template_name = 'aircox_cms/base_section.html'
 | 
			
		||||
    template_name = 'aircox/cms/base_section.html'
 | 
			
		||||
    kwargs = None   # kwargs argument passed to get
 | 
			
		||||
    tag = 'div'     # container tags
 | 
			
		||||
    classes = ''    # container classes
 | 
			
		||||
@ -253,7 +253,7 @@ class Section (BaseSection):
 | 
			
		||||
    """
 | 
			
		||||
    A Section that can be related to an object.
 | 
			
		||||
    """
 | 
			
		||||
    template_name = 'aircox_cms/section.html'
 | 
			
		||||
    template_name = 'aircox/cms/section.html'
 | 
			
		||||
    object = None
 | 
			
		||||
    object_required = False
 | 
			
		||||
    title = ''
 | 
			
		||||
@ -331,7 +331,7 @@ class Sections:
 | 
			
		||||
        use_icons = True        # print icons
 | 
			
		||||
        paginate_by = 0         # number of items
 | 
			
		||||
        icon_size = '32x32'     # icons size
 | 
			
		||||
        template_name = 'aircox_cms/section_list.html'
 | 
			
		||||
        template_name = 'aircox/cms/section_list.html'
 | 
			
		||||
 | 
			
		||||
        def get_object_list (self):
 | 
			
		||||
            return []
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,7 @@ import time
 | 
			
		||||
import re
 | 
			
		||||
from argparse import RawTextHelpFormatter
 | 
			
		||||
 | 
			
		||||
from django.conf import settings as main_settings
 | 
			
		||||
from django.core.management.base import BaseCommand, CommandError
 | 
			
		||||
from django.template.loader import render_to_string
 | 
			
		||||
from django.utils import timezone as tz
 | 
			
		||||
@ -36,12 +37,20 @@ class StationConfig:
 | 
			
		||||
            self.make_playlists()
 | 
			
		||||
 | 
			
		||||
    def make_config (self):
 | 
			
		||||
        log_script = main_settings.BASE_DIR \
 | 
			
		||||
                     if hasattr(main_settings, 'BASE_DIR') else \
 | 
			
		||||
                     main_settings.PROJECT_ROOT
 | 
			
		||||
        log_script = os.path.join(log_script, 'manage.py') + \
 | 
			
		||||
                        ' liquidsoap_log'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        context = {
 | 
			
		||||
            'controller': self.controller,
 | 
			
		||||
            'settings': settings,
 | 
			
		||||
            'log_script': log_script,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        data = render_to_string('aircox_liquidsoap/station.liq', context)
 | 
			
		||||
        data = render_to_string('aircox/liquidsoap/station.liq', context)
 | 
			
		||||
        data = re.sub(r'\s*\\\n', r'#\\n#', data)
 | 
			
		||||
        data = data.replace('\n', '')
 | 
			
		||||
        data = re.sub(r'#\\n#', '\n', data)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										62
									
								
								aircox/liquidsoap/management/commands/liquidsoap_log.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								aircox/liquidsoap/management/commands/liquidsoap_log.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
"""
 | 
			
		||||
This script is used by liquidsoap in order to log a file change. It should not
 | 
			
		||||
be used for other purposes.
 | 
			
		||||
"""
 | 
			
		||||
import os
 | 
			
		||||
from argparse import RawTextHelpFormatter
 | 
			
		||||
 | 
			
		||||
from django.utils import timezone as tz
 | 
			
		||||
from django.core.management.base import BaseCommand, CommandError
 | 
			
		||||
 | 
			
		||||
import aircox.programs.models as programs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Command (BaseCommand):
 | 
			
		||||
    help= __doc__
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def date(s):
 | 
			
		||||
        try:
 | 
			
		||||
            return tz.make_aware(tz.datetime.strptime(s, '%Y/%m/%d %H:%M:%S'))
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            raise argparse.ArgumentTypeError('Invalid date format')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def add_arguments (self, parser):
 | 
			
		||||
        parser.formatter_class=RawTextHelpFormatter
 | 
			
		||||
        parser.add_argument(
 | 
			
		||||
            '-c', '--comment', type=str,
 | 
			
		||||
            help='log comment'
 | 
			
		||||
        )
 | 
			
		||||
        parser.add_argument(
 | 
			
		||||
            '-s', '--source', type=str,
 | 
			
		||||
            required=True,
 | 
			
		||||
            help='source path'
 | 
			
		||||
        )
 | 
			
		||||
        parser.add_argument(
 | 
			
		||||
            '-p', '--path', type=str,
 | 
			
		||||
            required=True,
 | 
			
		||||
            help='sound path to log'
 | 
			
		||||
        )
 | 
			
		||||
        parser.add_argument(
 | 
			
		||||
            '-d', '--date', type=Command.date,
 | 
			
		||||
            help='set date instead of now (using format "%Y/%m/%d %H:%M:%S")'
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def handle (self, *args, **options):
 | 
			
		||||
        comment = options.get('comment') or ''
 | 
			
		||||
        path = os.path.realpath(options.get('path'))
 | 
			
		||||
 | 
			
		||||
        sound = programs.Sound.objects.filter(path = path)
 | 
			
		||||
        if sound:
 | 
			
		||||
            sound = sound[0]
 | 
			
		||||
        else:
 | 
			
		||||
            sound = None
 | 
			
		||||
            comment += '\nunregistered sound: {}'.format(path)
 | 
			
		||||
 | 
			
		||||
        programs.Log(source = options.get('source'),
 | 
			
		||||
                     comment = comment,
 | 
			
		||||
                     related_object = sound).save()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -106,15 +106,15 @@
 | 
			
		||||
                </header>
 | 
			
		||||
                <div class="sources">
 | 
			
		||||
                    {% with source=controller.master %}
 | 
			
		||||
                    {% include 'aircox_liquidsoap/base_source.html' %}
 | 
			
		||||
                    {% include 'aircox_liquidsoap/source.html' %}
 | 
			
		||||
                    {% endwith %}
 | 
			
		||||
 | 
			
		||||
                    {% with source=controller.dealer %}
 | 
			
		||||
                    {% include 'aircox_liquidsoap/base_source.html' %}
 | 
			
		||||
                    {% include 'aircox_liquidsoap/source.html' %}
 | 
			
		||||
                    {% endwith %}
 | 
			
		||||
 | 
			
		||||
                    {% for source in controller.streams.values %}
 | 
			
		||||
                    {% include 'aircox_liquidsoap/base_source.html' %}
 | 
			
		||||
                    {% include 'aircox_liquidsoap/source.html' %}
 | 
			
		||||
                    {% endfor %}
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="next">
 | 
			
		||||
@ -1,9 +1,14 @@
 | 
			
		||||
{# Context: #}
 | 
			
		||||
{# - controller: controller used to generate the current file #}
 | 
			
		||||
{# - settings: global settings #}
 | 
			
		||||
 | 
			
		||||
def interactive_source (id, s) = \
 | 
			
		||||
    s = store_metadata(id=id, size=1, s) \
 | 
			
		||||
    def handler(m) = \
 | 
			
		||||
        file = string.escape(m['filename']) \
 | 
			
		||||
        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) \
 | 
			
		||||
    add_skip_command(s) \
 | 
			
		||||
    s \
 | 
			
		||||
end \
 | 
			
		||||
@ -16,7 +21,7 @@ end \
 | 
			
		||||
\
 | 
			
		||||
{# Config #}
 | 
			
		||||
set("server.socket", true) \
 | 
			
		||||
set("server.socket.path", {{ controller.socket_path }}) \
 | 
			
		||||
set("server.socket.path", "{{ controller.socket_path }}") \
 | 
			
		||||
{% for key, value in settings.AIRCOX_LIQUIDSOAP_SET.items %}
 | 
			
		||||
set("{{ key|safe }}", {{ value|safe }}) \
 | 
			
		||||
{% endfor %}
 | 
			
		||||
@ -279,39 +279,6 @@ class Dealer (Source):
 | 
			
		||||
            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:
 | 
			
		||||
            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:
 | 
			
		||||
    """
 | 
			
		||||
@ -412,27 +379,6 @@ class Controller:
 | 
			
		||||
        for source in self.streams.values():
 | 
			
		||||
            source.update()
 | 
			
		||||
 | 
			
		||||
    def __change_log (self, source):
 | 
			
		||||
        last_log = programs.Log.objects.filter(
 | 
			
		||||
            source = source.id,
 | 
			
		||||
        ).prefetch_related('sound').order_by('-date')
 | 
			
		||||
 | 
			
		||||
        on_air = source.current_sound
 | 
			
		||||
        if not on_air:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if last_log:
 | 
			
		||||
            last_log = last_log[0]
 | 
			
		||||
            if last_log.sound and on_air == last_log.sound.path:
 | 
			
		||||
                return
 | 
			
		||||
 | 
			
		||||
        self.log(
 | 
			
		||||
            source = source.id,
 | 
			
		||||
            date = tz.make_aware(tz.datetime.now()),
 | 
			
		||||
            comment = 'sound has changed',
 | 
			
		||||
            related_object = programs.Sound.objects.get(path = on_air),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def monitor (self):
 | 
			
		||||
        """
 | 
			
		||||
        Log changes in the streams, and call dealer.monitor.
 | 
			
		||||
@ -441,9 +387,6 @@ class Controller:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        self.dealer.monitor()
 | 
			
		||||
        self.__change_log(self.dealer)
 | 
			
		||||
        for source in self.streams.values():
 | 
			
		||||
            self.__change_log(source)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Monitor:
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ class Actions:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LiquidControl (View):
 | 
			
		||||
    template_name = 'aircox_liquidsoap/controller.html'
 | 
			
		||||
    template_name = 'aircox/liquidsoap/controller.html'
 | 
			
		||||
 | 
			
		||||
    def get_context_data (self, **kwargs):
 | 
			
		||||
        get_monitor().update()
 | 
			
		||||
 | 
			
		||||
@ -100,7 +100,7 @@ class DiffusionAdmin (admin.ModelAdmin):
 | 
			
		||||
        else:
 | 
			
		||||
            self.readonly_fields = ['program', 'date', 'duration']
 | 
			
		||||
 | 
			
		||||
        if obj.initial:
 | 
			
		||||
        if obj and obj.initial:
 | 
			
		||||
            self.readonly_fields += ['program', 'sounds']
 | 
			
		||||
        return super().get_form(request, obj, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -639,13 +639,9 @@ class Log (models.Model):
 | 
			
		||||
        help_text = 'source information',
 | 
			
		||||
        blank = True, null = True,
 | 
			
		||||
    )
 | 
			
		||||
    sound = models.ForeignKey(
 | 
			
		||||
        'Sound',
 | 
			
		||||
        help_text = _('played sound'),
 | 
			
		||||
        blank = True, null = True,
 | 
			
		||||
    )
 | 
			
		||||
    date = models.DateTimeField(
 | 
			
		||||
        'date',
 | 
			
		||||
        auto_now_add=True,
 | 
			
		||||
    )
 | 
			
		||||
    comment = models.CharField(
 | 
			
		||||
        max_length = 512,
 | 
			
		||||
@ -662,12 +658,20 @@ class Log (models.Model):
 | 
			
		||||
        'related_type', 'related_id',
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_for_related_model (cl, model):
 | 
			
		||||
        """
 | 
			
		||||
        Return a queryset that filter related_type to the given one.
 | 
			
		||||
        """
 | 
			
		||||
        return cl.objects.filter(related_type__pk =
 | 
			
		||||
                                    ContentType.objects.get_for_model(model).id)
 | 
			
		||||
 | 
			
		||||
    def print (self):
 | 
			
		||||
        print(str(self), ':', self.comment or '')
 | 
			
		||||
        if self.diffusion:
 | 
			
		||||
            print(' - diffusion #' + str(self.diffusion.id))
 | 
			
		||||
        if self.sound:
 | 
			
		||||
            print(' - sound #' + str(self.sound.id), self.sound.path)
 | 
			
		||||
        if self.related_object:
 | 
			
		||||
            print(' - {}: #{}'.format(self.related_type,
 | 
			
		||||
                                      self.related_id))
 | 
			
		||||
 | 
			
		||||
    def __str__ (self):
 | 
			
		||||
        return self.date.strftime('%Y-%m-%d %H:%M') + ', ' + self.source
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user