cfr #121 Co-authored-by: Christophe Siraut <d@tobald.eu.org> Co-authored-by: bkfox <thomas bkfox net> Co-authored-by: Thomas Kairos <thomas@bkfox.net> Reviewed-on: #131 Co-authored-by: Chris Tactic <ctactic@noreply.git.radiocampus.be> Co-committed-by: Chris Tactic <ctactic@noreply.git.radiocampus.be>
This commit is contained in:
		
							
								
								
									
										9
									
								
								aircox_streamer/templates/aircox/widgets/nav.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								aircox_streamer/templates/aircox/widgets/nav.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
{% extends "aircox/widgets/nav.html" %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block admin-menu %}
 | 
			
		||||
{{ block.super }}
 | 
			
		||||
<a class="dropdown-item" href="{% url "streamer:dashboard-streamer" %}">
 | 
			
		||||
    {% translate "Streamer" %}
 | 
			
		||||
</a>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@ -10,16 +10,16 @@ Base liquidsoap station configuration.
 | 
			
		||||
 | 
			
		||||
{% block functions %}
 | 
			
		||||
{# Seek function #}
 | 
			
		||||
def seek(source, t) =
 | 
			
		||||
def seek(s, t) =
 | 
			
		||||
  t = float_of_string(default=0.,t)
 | 
			
		||||
  ret = source.seek(source,t)
 | 
			
		||||
  ret = source.seek(s,t)
 | 
			
		||||
  log("seek #{ret} seconds.")
 | 
			
		||||
  "#{ret}"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
{# Transition to live sources #}
 | 
			
		||||
def to_live(stream, live)
 | 
			
		||||
  stream = fade.final(duration=2., type='log', stream)
 | 
			
		||||
  stream = fade.out(duration=2., type='log', stream)
 | 
			
		||||
  live = fade.initial(duration=2., type='log', live)
 | 
			
		||||
  add(normalize=false, [stream,live])
 | 
			
		||||
end
 | 
			
		||||
@ -30,6 +30,17 @@ def to_stream(live, stream)
 | 
			
		||||
  add(normalize=false, [live,stream])
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
{# Skip command #}
 | 
			
		||||
def add_skip_command(id, s) =
 | 
			
		||||
    def skip(_) =
 | 
			
		||||
        source.skip(s)
 | 
			
		||||
        "Done!"
 | 
			
		||||
    end
 | 
			
		||||
    server.register(namespace=id,
 | 
			
		||||
        usage="skip",
 | 
			
		||||
        description="Skip the current song.",
 | 
			
		||||
        "skip",skip)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
{% comment %}
 | 
			
		||||
An interactive source is a source that:
 | 
			
		||||
@ -45,10 +56,13 @@ def interactive (id, s) =
 | 
			
		||||
    server.register(namespace=id,
 | 
			
		||||
                    description="Get source's track remaining time",
 | 
			
		||||
                    usage="remaining",
 | 
			
		||||
                    "remaining", fun (_) ->  begin json_of(source.remaining(s)) end)
 | 
			
		||||
                    "remaining", fun (_) ->  begin json.stringify(source.remaining(s)) end)
 | 
			
		||||
 | 
			
		||||
    add_skip_command(id, s)
 | 
			
		||||
 | 
			
		||||
    s_meta = interactive.string("#{id}_meta", "")
 | 
			
		||||
    s = source.on_metadata(s, fun(meta) -> s_meta.set(json.stringify(meta)))
 | 
			
		||||
 | 
			
		||||
    s = store_metadata(id=id, size=1, s)
 | 
			
		||||
    add_skip_command(s)
 | 
			
		||||
    s
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -65,15 +79,9 @@ end
 | 
			
		||||
{% block config %}
 | 
			
		||||
set("server.socket", true)
 | 
			
		||||
set("server.socket.path", "{{ streamer.socket_path }}")
 | 
			
		||||
set("log.file.path", "{{ station.path }}/liquidsoap.log")
 | 
			
		||||
{% for key, value in settings.AIRCOX_LIQUIDSOAP_SET.items %}
 | 
			
		||||
set("{{ key|safe }}", {{ value|safe }})
 | 
			
		||||
{% endfor %}
 | 
			
		||||
set("log.file.path", "{{ log_file }}")
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block config_extras %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block config_extras %}{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block sources %}
 | 
			
		||||
{% with source=streamer.dealer %}
 | 
			
		||||
@ -82,7 +90,6 @@ live = audio_to_stereo(interactive('{{ source.id }}',
 | 
			
		||||
))
 | 
			
		||||
{% endwith %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
streams = rotate(id="streams", [
 | 
			
		||||
    {% for source in streamer.sources %}
 | 
			
		||||
    {% if source != streamer.dealer %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										111
									
								
								aircox_streamer/templates/aircox_streamer/source_item.html
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										111
									
								
								aircox_streamer/templates/aircox_streamer/source_item.html
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@ -1,8 +1,9 @@
 | 
			
		||||
{% comment %}List item for a source.{% endcomment %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
<section class="box"><div class="columns is-desktop">
 | 
			
		||||
    <div class="column">
 | 
			
		||||
<section class="box"><div class="flex-row gap-3">
 | 
			
		||||
 | 
			
		||||
    <div class="flex-grow-1">
 | 
			
		||||
        <h5 class='title is-5' :class="{'has-text-danger': source.isPlaying, 'has-text-warning': source.isPaused}">
 | 
			
		||||
            <span>
 | 
			
		||||
                <span v-if="source.isPlaying" class="fas fa-play"></span>
 | 
			
		||||
@ -13,36 +14,78 @@
 | 
			
		||||
            <small v-if="source.isPaused || source.isPlaying">([[ source.remainingString ]])</small>
 | 
			
		||||
 | 
			
		||||
            <a v-if="source.data.program !== undefined"
 | 
			
		||||
               :href="'{% url 'admin:aircox_program_change' "$$" %}'.replace('$$', source.data.program)"
 | 
			
		||||
               title="{% translate "Edit related program" %}">
 | 
			
		||||
               :href="'{% url 'aircox:program_edit' "$$" %}'.replace('$$', source.data.program)"
 | 
			
		||||
               title="{% translate "Edit program" %}">
 | 
			
		||||
                <span class="icon">
 | 
			
		||||
                    <span class="fas fa-edit"></span>
 | 
			
		||||
                </span>
 | 
			
		||||
            </a>
 | 
			
		||||
        </h5>
 | 
			
		||||
 | 
			
		||||
        <table class="table bg-transparent">
 | 
			
		||||
            <tbody>
 | 
			
		||||
                <tr><th class="has-text-right ws-nowrap">
 | 
			
		||||
                    {% translate "Status" %}
 | 
			
		||||
                    </th>
 | 
			
		||||
                    <td :class="{'has-text-danger': source.isPlaying, 'has-text-warning': source.isPaused}">
 | 
			
		||||
                        <span v-if="source.isPlaying" class="fas fa-play"></span>
 | 
			
		||||
                        <span v-else-if="source.data.status" class="fas fa-pause"></span>
 | 
			
		||||
                        [[ source.data.status_verbose || "—" ]]
 | 
			
		||||
                    </td>
 | 
			
		||||
                </tr>
 | 
			
		||||
                <tr v-if="source.data.air_time">
 | 
			
		||||
                    <th class="has-text-right ws-nowrap">
 | 
			
		||||
                        {% translate "Air time" %}
 | 
			
		||||
                    </th><td>
 | 
			
		||||
                        <span class="far fa-clock"></span>
 | 
			
		||||
                        <time :datetime="source.date">
 | 
			
		||||
                        [[ source.data.air_time.toLocaleDateString() ]],
 | 
			
		||||
                        [[ source.data.air_time.toLocaleTimeString() ]]
 | 
			
		||||
                        </time>
 | 
			
		||||
                    </td>
 | 
			
		||||
                <tr v-if="source.remaining">
 | 
			
		||||
                    <th class="has-text-right ws-nowrap">
 | 
			
		||||
                        {% translate "Time left" %}
 | 
			
		||||
                    </th><td>
 | 
			
		||||
                        <span class="far fa-hourglass"></span>
 | 
			
		||||
                        [[ source.remainingString ]]
 | 
			
		||||
                    </td>
 | 
			
		||||
                </tr>
 | 
			
		||||
                <tr v-if="source.data.uri">
 | 
			
		||||
                    <th class="has-text-right ws-nowrap">
 | 
			
		||||
                        {% translate "Source" %}
 | 
			
		||||
                    </th><td>
 | 
			
		||||
                        <span class="far fa-play-circle"></span>
 | 
			
		||||
                        <template v-if="source.data.uri.length > 64">...</template>[[ (source.data.uri && source.data.uri.slice(-64)) || '—' ]]
 | 
			
		||||
                    </td>
 | 
			
		||||
                </tr>
 | 
			
		||||
            </tbody>
 | 
			
		||||
        </table>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div>
 | 
			
		||||
        <div>
 | 
			
		||||
            <button class="button" @click="source.sync()"
 | 
			
		||||
                    title="{% translate "Synchronize source with Liquidsoap" %}">
 | 
			
		||||
                <span class="icon is-small">
 | 
			
		||||
                    <span class="fas fa-sync"></span>
 | 
			
		||||
                </span>
 | 
			
		||||
                <span>{% translate "Synchronise" %}</span>
 | 
			
		||||
            </button>
 | 
			
		||||
            <button class="button" @click="source.restart()"
 | 
			
		||||
            <button class="button smaller mr-2 mb-2" @click="source.restart()"
 | 
			
		||||
                    title="{% translate "Restart current track" %}">
 | 
			
		||||
                <span class="icon is-small">
 | 
			
		||||
                    <span class="fas fa-step-backward"></span>
 | 
			
		||||
                </span>
 | 
			
		||||
                <span>{% translate "Restart" %}</span>
 | 
			
		||||
            </button>
 | 
			
		||||
            <button class="button" @click="source.skip()"
 | 
			
		||||
            <button class="button smaller mr-2 mb-2" @click="source.skip()"
 | 
			
		||||
                    title="{% translate "Skip current file" %}">
 | 
			
		||||
                <span>{% translate "Skip" %}</span>
 | 
			
		||||
                <span class="icon is-small">
 | 
			
		||||
                    <span class="fas fa-step-forward"></span>
 | 
			
		||||
                </span>
 | 
			
		||||
            </button>
 | 
			
		||||
            <button class="button smaller mr-2 mb-2" @click="source.sync()"
 | 
			
		||||
                    title="{% translate "Synchronize source with Liquidsoap" %}">
 | 
			
		||||
                <span class="icon is-small">
 | 
			
		||||
                    <span class="fas fa-sync"></span>
 | 
			
		||||
                </span>
 | 
			
		||||
                <span>{% translate "Synchronise" %}</span>
 | 
			
		||||
            </button>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div v-if="source.isQueue">
 | 
			
		||||
@ -89,46 +132,4 @@
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="column is-two-fifths">
 | 
			
		||||
        <h6 class="subtitle is-6 is-marginless">Metadata</h6>
 | 
			
		||||
        <table class="table has-background-transparent">
 | 
			
		||||
            <tbody>
 | 
			
		||||
                <tr><th class="has-text-right has-text-nowrap">
 | 
			
		||||
                    {% translate "Status" %}
 | 
			
		||||
                    </th>
 | 
			
		||||
                    <td :class="{'has-text-danger': source.isPlaying, 'has-text-warning': source.isPaused}">
 | 
			
		||||
                        <span v-if="source.isPlaying" class="fas fa-play"></span>
 | 
			
		||||
                        <span v-else-if="source.data.status" class="fas fa-pause"></span>
 | 
			
		||||
                        [[ source.data.status_verbose || "—" ]]
 | 
			
		||||
                    </td>
 | 
			
		||||
                </tr>
 | 
			
		||||
                <tr v-if="source.data.air_time">
 | 
			
		||||
                    <th class="has-text-right has-text-nowrap">
 | 
			
		||||
                        {% translate "Air time" %}
 | 
			
		||||
                    </th><td>
 | 
			
		||||
                        <span class="far fa-clock"></span>
 | 
			
		||||
                        <time :datetime="source.date">
 | 
			
		||||
                        [[ source.data.air_time.toLocaleDateString() ]],
 | 
			
		||||
                        [[ source.data.air_time.toLocaleTimeString() ]]
 | 
			
		||||
                        </time>
 | 
			
		||||
                    </td>
 | 
			
		||||
                <tr v-if="source.remaining">
 | 
			
		||||
                    <th class="has-text-right has-text-nowrap">
 | 
			
		||||
                        {% translate "Time left" %}
 | 
			
		||||
                    </th><td>
 | 
			
		||||
                        <span class="far fa-hourglass"></span>
 | 
			
		||||
                        [[ source.remainingString ]]
 | 
			
		||||
                    </td>
 | 
			
		||||
                </tr>
 | 
			
		||||
                <tr v-if="source.data.uri">
 | 
			
		||||
                    <th class="has-text-right has-text-nowrap">
 | 
			
		||||
                        {% translate "Data source" %}
 | 
			
		||||
                    </th><td>
 | 
			
		||||
                        <span class="far fa-play-circle"></span>
 | 
			
		||||
                        <template v-if="source.data.uri.length > 64">...</template>[[ (source.data.uri && source.data.uri.slice(-64)) || '—' ]]
 | 
			
		||||
                    </td>
 | 
			
		||||
                </tr>
 | 
			
		||||
            </tbody>
 | 
			
		||||
        </table>
 | 
			
		||||
    </div>
 | 
			
		||||
</div></section>
 | 
			
		||||
 | 
			
		||||
@ -1,16 +1,13 @@
 | 
			
		||||
{% extends "admin/base_site.html" %}
 | 
			
		||||
{% comment %}Admin tools used to manage the streamer.{% endcomment %}
 | 
			
		||||
{% extends "aircox/dashboard/base.html" %}
 | 
			
		||||
{% load i18n static %}
 | 
			
		||||
 | 
			
		||||
{% block init-scripts %}
 | 
			
		||||
aircox.init({apiUrl: "{% url "admin:api:streamer-list" %}"},
 | 
			
		||||
            {config: window.StreamerApp})
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
{% block title %}{% translate "Streamer" %}{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block content-container %}
 | 
			
		||||
{{ block.super }}
 | 
			
		||||
<div id="app">
 | 
			
		||||
    <a-streamer api-url="{% url "admin:api:streamer-list" %}">
 | 
			
		||||
<div class="container">
 | 
			
		||||
    <a-streamer api-url="{% url "streamer:api:streamer-list" %}">
 | 
			
		||||
    <template v-slot="{streamer,streamers,sources,fetchStreamers,Sound}">
 | 
			
		||||
        <div class="navbar toolbar">
 | 
			
		||||
            <div class="navbar-start">
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user