work on liquidsoap script (fix & fade) + fix errors in monitor
This commit is contained in:
		@ -530,9 +530,10 @@ class SectionItemMeta(models.base.ModelBase):
 | 
			
		||||
 | 
			
		||||
        cl = super().__new__(cls, name, bases, attrs)
 | 
			
		||||
        if not 'template' in attrs:
 | 
			
		||||
            cl.snake_name = camelcase_to_underscore(name)
 | 
			
		||||
            cl.template = '{}/sections/{}.html'.format(
 | 
			
		||||
                cl._meta.app_label,
 | 
			
		||||
                camelcase_to_underscore(name),
 | 
			
		||||
                cl.snake_name,
 | 
			
		||||
            )
 | 
			
		||||
            if name != 'SectionItem':
 | 
			
		||||
                try:
 | 
			
		||||
 | 
			
		||||
@ -76,6 +76,11 @@ nav.menu {
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .menu.top a {
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
        margin: 0.2em 1em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
.page_left > section,
 | 
			
		||||
.page_right > section {
 | 
			
		||||
    margin-bottom: 1em;
 | 
			
		||||
@ -328,4 +333,3 @@ main .body ~ section:not(.comments) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -87,7 +87,8 @@ main {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    main .content img.cover {
 | 
			
		||||
       width: 100%;
 | 
			
		||||
       width: calc(100% + 2em);
 | 
			
		||||
       margin-left: -1em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
<section class="section_item {{ self.css_class }}">
 | 
			
		||||
<section class="section_item {{ self.css_class }} {{ self.snake_name }}">
 | 
			
		||||
    {% block title %}
 | 
			
		||||
    {% if self.show_title %}<h2>{{ self.title }}</h2>{% endif %}
 | 
			
		||||
    {% endblock %}
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,6 @@ class Monitor:
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, station, **kwargs):
 | 
			
		||||
        Log.objects.all().delete()
 | 
			
		||||
        self.station = station
 | 
			
		||||
        self.__dict__.update(kwargs)
 | 
			
		||||
 | 
			
		||||
@ -169,7 +168,7 @@ class Monitor:
 | 
			
		||||
        )
 | 
			
		||||
        sounds = [
 | 
			
		||||
            sound.related.path for sound in sounds
 | 
			
		||||
            if not sound.related.removed
 | 
			
		||||
            if sound.related.type != programs.Sound.Type.removed
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        return (
 | 
			
		||||
@ -229,8 +228,6 @@ class Monitor:
 | 
			
		||||
        if next_diff and not dealer.controller.active and \
 | 
			
		||||
                next_diff.start <= now:
 | 
			
		||||
            dealer.controller.active = True
 | 
			
		||||
            for source in station.get_sources():
 | 
			
		||||
                source.controller.skip()
 | 
			
		||||
            self.log(
 | 
			
		||||
                type = Log.Type.play,
 | 
			
		||||
                source = dealer.id_,
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,8 @@ position in order to do it. Keep in mind that you might want to avoid to
 | 
			
		||||
put station specific configuration in the template itself.
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block functions %}
 | 
			
		||||
{% comment %}
 | 
			
		||||
An interactive source is a source that:
 | 
			
		||||
- is skippable through the given id on external interfaces
 | 
			
		||||
@ -36,7 +38,7 @@ def interactive_source (id, s, ~active=true, ~disable_switch=false) =
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
{% comment %}
 | 
			
		||||
a stream is a source that:
 | 
			
		||||
A stream is a source that:
 | 
			
		||||
- is a playlist on random mode (playlist object accessible at {id}_playlist
 | 
			
		||||
- is interactive
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
@ -44,70 +46,104 @@ def stream (id, file) =
 | 
			
		||||
    s = playlist(id = '#{id}_playlist', mode = "random", file)
 | 
			
		||||
    interactive_source(id, s)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
{% block post_funcs %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{# config #}
 | 
			
		||||
{% block functions_extras %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block config %}
 | 
			
		||||
set("server.socket", true)
 | 
			
		||||
set("server.socket.path", "{{ station.controller.socket_path }}")
 | 
			
		||||
set("log.file.path", "{{ station.controller.station.path }}/liquidsoap.log")
 | 
			
		||||
{% for key, value in settings.AIRCOX_LIQUIDSOAP_SET.items %}
 | 
			
		||||
set("{{ key|safe }}", {{ value|safe }})
 | 
			
		||||
{% endfor %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block post_config %}
 | 
			
		||||
{% block config_extras %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{# station #}
 | 
			
		||||
{% block sources %}
 | 
			
		||||
live = fallback([
 | 
			
		||||
    {% for source in station.file_sources %}
 | 
			
		||||
    {% with controller=source.controller %}
 | 
			
		||||
    interactive_source(
 | 
			
		||||
        '{{ source.id_ }}', single("{{ source.url }}"), active=false
 | 
			
		||||
    ),
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
 | 
			
		||||
    {% with source=station.dealer controller=station.dealer.controller %}
 | 
			
		||||
    interactive_source('{{ source.id_ }}',
 | 
			
		||||
        playlist.once(reload_mode='watch', "{{ controller.path }}"),
 | 
			
		||||
        active=false
 | 
			
		||||
    ),
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stream = fallback([
 | 
			
		||||
    rotate([
 | 
			
		||||
        {% for source in station.stream_sources %}
 | 
			
		||||
        {% with controller=source.controller stream=source.controller.stream %}
 | 
			
		||||
            {% if stream.delay %}
 | 
			
		||||
            delay({{ stream.delay }}.,
 | 
			
		||||
                  stream("{{ source.id_ }}", "{{ controller.path }}")),
 | 
			
		||||
            {% elif stream.begin and stream.end %}
 | 
			
		||||
            at({ {{stream.begin}}-{{stream.end}} },
 | 
			
		||||
               stream("{{ source.id_ }}", "{{ controller.path }}")),
 | 
			
		||||
            {% elif not stream %}
 | 
			
		||||
            stream("{{ source.id_ }}", "{{ controller.path }}"),
 | 
			
		||||
            {% endif %}
 | 
			
		||||
        {% endwith %}
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
    ]),
 | 
			
		||||
 | 
			
		||||
    {% for source in station.fallback_sources %}
 | 
			
		||||
    {% with controller=source.controller %}
 | 
			
		||||
    single("{{ source.value }}"),
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
 | 
			
		||||
    blank(id="blank_fallback", duration=0.1),
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block sources_extras %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_live(stream,live)
 | 
			
		||||
  stream = fade.final(duration=2., type='log', stream)
 | 
			
		||||
  live = fade.initial(duration=2., type='log', live)
 | 
			
		||||
  add(normalize=false, [stream,live])
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def to_stream(live,stream)
 | 
			
		||||
  source.skip(stream)
 | 
			
		||||
  add(normalize=false, [live,stream])
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block station %}
 | 
			
		||||
{{ station.id_ }} = interactive_source (
 | 
			
		||||
    "{{ station.id_ }}",
 | 
			
		||||
    fallback(track_sensitive = false, [
 | 
			
		||||
        {% for source in station.file_sources %}
 | 
			
		||||
        {% with controller=source.controller %}
 | 
			
		||||
        interactive_source(
 | 
			
		||||
            '{{ source.id_ }}', single("{{ source.url }}"),
 | 
			
		||||
            active=false
 | 
			
		||||
        ),
 | 
			
		||||
        {% endwith %}
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
 | 
			
		||||
        {% with source=station.dealer %}
 | 
			
		||||
        {% with controller=source.controller %}
 | 
			
		||||
        interactive_source('{{ source.id_ }}',
 | 
			
		||||
            playlist.once(reload_mode='watch', "{{ controller.path }}"),
 | 
			
		||||
            active=false
 | 
			
		||||
        ),
 | 
			
		||||
        {% endwith %}
 | 
			
		||||
        {% endwith %}
 | 
			
		||||
 | 
			
		||||
        rotate([
 | 
			
		||||
            {% for source in station.stream_sources %}
 | 
			
		||||
            {% with controller=source.controller stream=source.controller.stream %}
 | 
			
		||||
                {% if stream.delay %}
 | 
			
		||||
                delay({{ stream.delay }}.,
 | 
			
		||||
                      stream("{{ source.id_ }}", "{{ controller.path }}")),
 | 
			
		||||
                {% elif stream.begin and stream.end %}
 | 
			
		||||
                at({ {{stream.begin}}-{{stream.end}} },
 | 
			
		||||
                   stream("{{ source.id_ }}", "{{ controller.path }}")),
 | 
			
		||||
                {% elif not stream %}
 | 
			
		||||
                stream("{{ source.id_ }}", "{{ controller.path }}"),
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            {% endwith %}
 | 
			
		||||
            {% endfor %}
 | 
			
		||||
        ]),
 | 
			
		||||
 | 
			
		||||
        {% for source in station.fallback_sources %}
 | 
			
		||||
        {% with controller=source.controller %}
 | 
			
		||||
        single("{{ source.value }}"),
 | 
			
		||||
        {% endwith %}
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
 | 
			
		||||
        blank(id="blank_fallback", duration=0.1),
 | 
			
		||||
    ]),
 | 
			
		||||
    fallback(
 | 
			
		||||
        track_sensitive=false,
 | 
			
		||||
        transitions=[to_live,to_stream],
 | 
			
		||||
        [ live, stream ]
 | 
			
		||||
    ),
 | 
			
		||||
    disable_switch=true
 | 
			
		||||
)
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block station_extras %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block outputs %}
 | 
			
		||||
{% for output in station.outputs %}
 | 
			
		||||
@ -120,6 +156,6 @@ output.{{ output.get_type_display }}(
 | 
			
		||||
{% endfor %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block post_output %}
 | 
			
		||||
{% block output_extras %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -54,8 +54,11 @@ var Monitor = {
 | 
			
		||||
        return document.cookie.replace(/.*csrftoken=([^;]+)(;.*|$)/, '$1');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    post: function(station, action) {
 | 
			
		||||
    post: function(station, source, action) {
 | 
			
		||||
        var params = 'station=' + station + '&&action=' + action;
 | 
			
		||||
        if(source)
 | 
			
		||||
            params += '&&source=' + source;
 | 
			
		||||
 | 
			
		||||
        var req = new XMLHttpRequest()
 | 
			
		||||
        req.open('POST', '{% url 'controllers.monitor' %}', false);
 | 
			
		||||
        req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
 | 
			
		||||
@ -66,8 +69,8 @@ var Monitor = {
 | 
			
		||||
        this.update();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    skip: function(station) {
 | 
			
		||||
        this.post(station, 'skip');
 | 
			
		||||
    skip: function(station, source) {
 | 
			
		||||
        this.post(station, source, 'skip');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    update: function(timeout) {
 | 
			
		||||
@ -110,6 +113,8 @@ Monitor.update(1000);
 | 
			
		||||
            <div class="source{% if source == station.controller.current_source %} current{% endif %}">
 | 
			
		||||
                <span class="name">{{ source.name }}</span>
 | 
			
		||||
                <span class="file">{{ source.controller.current_sound }}</span>
 | 
			
		||||
                <button onclick="Monitor.skip('{{ station.name }}','{{ source.name }}');">
 | 
			
		||||
                    {% trans "skip" %}</button>
 | 
			
		||||
            </div>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
            {% endfor %}
 | 
			
		||||
 | 
			
		||||
@ -94,7 +94,7 @@ class Monitor(View,TemplateResponseMixin,LoginRequiredMixin):
 | 
			
		||||
        if not request.user.is_active:
 | 
			
		||||
            return Http404()
 | 
			
		||||
 | 
			
		||||
        if not 'action' in request.POST:
 | 
			
		||||
        if not ('action' or 'station') in request.POST:
 | 
			
		||||
            return HttpResponse('')
 | 
			
		||||
 | 
			
		||||
        POST = request.POST
 | 
			
		||||
@ -107,8 +107,22 @@ class Monitor(View,TemplateResponseMixin,LoginRequiredMixin):
 | 
			
		||||
            return HttpResponse('')
 | 
			
		||||
        station.prepare(fetch=True)
 | 
			
		||||
 | 
			
		||||
        source = None
 | 
			
		||||
        if 'source' in POST:
 | 
			
		||||
            source = station.source_set.filter(name = POST['source']) \
 | 
			
		||||
                            .first()
 | 
			
		||||
            if not source and POST['source'] == station.dealer.name:
 | 
			
		||||
                source = station.dealer
 | 
			
		||||
 | 
			
		||||
            if source:
 | 
			
		||||
                source.prepare()
 | 
			
		||||
 | 
			
		||||
        if station and action == 'skip':
 | 
			
		||||
            station.controller.skip()
 | 
			
		||||
            if source:
 | 
			
		||||
                print('skip ', source)
 | 
			
		||||
                source.controller.skip()
 | 
			
		||||
            else:
 | 
			
		||||
                station.controller.skip()
 | 
			
		||||
 | 
			
		||||
        return HttpResponse('')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -591,7 +591,7 @@ class Program(Nameable):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DiffusionManager(models.Manager):
 | 
			
		||||
    def get_at(self, date = None):
 | 
			
		||||
    def get_at(self, date = None, next = False):
 | 
			
		||||
        """
 | 
			
		||||
        Return a queryset of diffusions that have the given date
 | 
			
		||||
        in their range.
 | 
			
		||||
@ -606,9 +606,12 @@ class DiffusionManager(models.Manager):
 | 
			
		||||
                models.Q(end__contains = date)
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        if not next:
 | 
			
		||||
            return self.filter(start__lte = date, end__gte = date) \
 | 
			
		||||
                       .order_by('start')
 | 
			
		||||
 | 
			
		||||
        return self.filter(
 | 
			
		||||
            models.Q(start__lte = date, end__gte = date) |
 | 
			
		||||
            # FIXME: should not be here?
 | 
			
		||||
            models.Q(start__gte = date),
 | 
			
		||||
        ).order_by('start')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user