New features

This commit is contained in:
nemunaire 2023-11-13 18:50:42 +01:00
commit a9c6cdcd0f
16 changed files with 584 additions and 19 deletions

View file

@ -0,0 +1,66 @@
<script>
import { activeInputs, inputsList } from '$lib/stores/inputs';
import { activeSources } from '$lib/stores/sources';
export let showInactives = false;
</script>
<ul class="list-group list-group-flush">
{#if $activeSources.length === 0 && ((showInactives && $inputsList.length === 0) || (!showInactives && $activeInputs.length === 0))}
<li class="list-group-item py-3">
<span class="text-muted">
Aucune source active.
</span>
</li>
{/if}
{#each $activeSources as source}
<li class="list-group-item py-3 d-flex justify-content-between">
<div>
<strong>{source.name}</strong>
{#await source.currently()}
<div class="spinner-border spinner-border-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
{:then title}
<span class="text-muted">{title}</span>
{/await}
</div>
{#if source.controlable}
<div>
<button
class="btn btn-sm btn-primary"
on:click={() => source.playpause()}
>
<i class="bi bi-pause"></i>
</button>
</div>
{/if}
</li>
{/each}
{#each $inputsList as input}
{#if showInactives || input.active}
<li class="list-group-item py-3 d-flex justify-content-between">
<div>
<strong>{input.name}</strong>
{#await input.currently()}
<div class="spinner-border spinner-border-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
{:then title}
<span class="text-muted">{title}</span>
{/await}
</div>
{#if input.controlable}
<div>
<button
class="btn btn-sm btn-primary"
on:click={() => input.playpause()}
>
<i class="bi bi-pause"></i>
</button>
</div>
{/if}
</li>
{/if}
{/each}
</ul>

56
ui/src/lib/input.js Normal file
View file

@ -0,0 +1,56 @@
export class Input {
constructor(id, res) {
this.id = id;
if (res) {
this.update(res);
}
}
update({ name, active, controlable }) {
this.name = name;
this.active = active;
this.controlable = controlable;
}
async currently() {
const data = await fetch(`api/inputs/${this.id}/currently`, {headers: {'Accept': 'application/json'}});
if (data.status == 200) {
return await data.json();
} else {
throw new Error((await res.json()).errmsg);
}
}
async playpause() {
const data = await fetch(`api/inputs/${this.id}/pause`, {headers: {'Accept': 'application/json'}, method: 'POST'});
if (data.status != 200) {
throw new Error((await res.json()).errmsg);
}
}
}
export async function getInputs() {
const res = await fetch(`api/inputs`, {headers: {'Accept': 'application/json'}})
if (res.status == 200) {
const data = await res.json();
if (data == null) {
return {}
} else {
Object.keys(data).forEach((k) => {
data[k] = new Input(k, data[k]);
});
return data;
}
} else {
throw new Error((await res.json()).errmsg);
}
}
export async function getInput(sid) {
const res = await fetch(`api/inputs/${sid}`, {headers: {'Accept': 'application/json'}})
if (res.status == 200) {
return new Input(sid, await res.json());
} else {
throw new Error((await res.json()).errmsg);
}
}

View file

@ -6,10 +6,11 @@ export class Source {
}
}
update({ name, enabled, active }) {
update({ name, enabled, active, controlable }) {
this.name = name;
this.enabled = enabled;
this.active = active;
this.controlable = controlable;
}
async activate() {
@ -28,6 +29,13 @@ export class Source {
throw new Error((await res.json()).errmsg);
}
}
async playpause() {
const data = await fetch(`api/sources/${this.id}/pause`, {headers: {'Accept': 'application/json'}, method: 'POST'});
if (data.status != 200) {
throw new Error((await res.json()).errmsg);
}
}
}
export async function getSources() {

View file

@ -0,0 +1,41 @@
import { derived, writable } from 'svelte/store';
import { getInputs } from '$lib/input'
function createInputsStore() {
const { subscribe, set, update } = writable(null);
return {
subscribe,
set: (v) => {
update((m) => v);
},
refresh: async () => {
const list = await getInputs();
update((m) => list);
return list;
},
};
}
export const inputs = createInputsStore();
export const inputsList = derived(
inputs,
($inputs) => {
if (!$inputs) {
return [];
}
return Object.keys($inputs).map((k) => $inputs[k]);
},
);
export const activeInputs = derived(
inputsList,
($inputsList) => {
return $inputsList.filter((s) => s.active);
},
);

View file

@ -6,6 +6,10 @@
sources.refresh();
setInterval(sources.refresh, 5000);
import { inputs } from '$lib/stores/inputs';
inputs.refresh();
setInterval(inputs.refresh, 4500);
const version = fetch('api/version', {headers: {'Accept': 'application/json'}}).then((res) => res.json())
</script>

View file

@ -1,7 +1,9 @@
<script>
import Inputs from '$lib/components/Inputs.svelte';
import Mixer from '$lib/components/Mixer.svelte';
import SourceSelection from '$lib/components/SourceSelection.svelte';
import { activeSources } from '$lib/stores/sources';
import { activeInputs } from '$lib/stores/inputs';
let mixerAdvanced = false;
</script>
@ -11,7 +13,7 @@
</div>
<div class="container">
{#if $activeSources.length === 0}
{#if $activeSources.length === 0 && $activeInputs.length === 0}
<div class="text-muted text-center mt-1 mb-1">
Aucune source active pour l'instant.
</div>
@ -21,15 +23,31 @@
<div class="d-inline-block me-3">
<div class="d-flex justify-content-between align-items-center">
<div>
<strong>{source.name}&nbsp;:</strong>
{#await source.currently()}
<div class="spinner-border spinner-border-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div> <span class="text-muted">@ {source.name}</span>
{:then title}
{title}
<strong>{title}</strong> <span class="text-muted">@ {source.name}</span>
{:catch error}
activée
{source.name} activée
{/await}
</div>
</div>
</div>
{/each}
{#each $activeInputs as input}
<div class="d-inline-block me-3">
<div class="d-flex justify-content-between align-items-center">
<div>
{#await input.currently()}
<div class="spinner-border spinner-border-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div> <span class="text-muted">@ {input.name}</span>
{:then title}
<strong>{title}</strong> <span class="text-muted">@ {input.name}</span>
{:catch error}
{input.name} activée
{/await}
</div>
</div>
@ -39,7 +57,7 @@
{/if}
<div class="row">
<div class="col">
<div class="col-md">
<div class="card my-2">
<h4 class="card-header">
<div class="d-flex justify-content-between">
@ -61,14 +79,13 @@
</div>
</div>
<div class="col">
<div class="col-md">
<div class="card my-2">
<h4 class="card-header">
<i class="bi bi-speaker"></i>
Sources
</h4>
<div class="card-body">
</div>
<Inputs />
</div>
</div>
</div>