Merge pull request #12 from Spengreb/bugfix/show-force-start-issue

Fix bug where force start did not force starting the show
This commit is contained in:
Spengreb 2026-05-21 14:15:21 +02:00 committed by GitHub
commit b4e93cc63c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 103 additions and 21 deletions

View file

@ -2,6 +2,7 @@ const LOGGER = require('@calzoneman/jsli')('shows');
const util = require('./utilities'); const util = require('./utilities');
const showDB = require('./database/shows'); const showDB = require('./database/shows');
const Server = require('./server'); const Server = require('./server');
const InfoGetter = require('./get-info');
function makeSystemProxy(name) { function makeSystemProxy(name) {
const rank = 5; const rank = 5;
@ -43,7 +44,90 @@ function normalizePlaylist(rawPlaylist) {
.filter(item => item.id && item.type); .filter(item => item.id && item.type);
} }
function applyShowToChannel(chan, show) { function queueShowEntry(plmod, proxy, entry, idx) {
return new Promise((resolve, reject) => {
let data = {
id: entry.id,
type: entry.type,
pos: idx === 0 && entry.pos === 'next' ? 'next' : 'end',
title: false,
link: util.formatLink(entry.id, entry.type, null),
temp: false,
shouldAddToLibrary: true,
queueby: proxy.getName(),
duration: undefined,
maxlength: 0
};
InfoGetter.getMedia(entry.id, entry.type, (err, media) => {
if (err) {
reject(new Error(String(err)));
return;
}
if (Array.isArray(media)) {
let list = media.slice();
if (data.pos === 'next') {
list = list.reverse();
if (plmod.items.length === 0 && list.length > 0) {
list.unshift(list.pop());
}
}
if (list.length === 0) {
reject(new Error(`Show item resolved to an empty playlist: ${entry.type}:${entry.id}`));
return;
}
let firstUid = null;
let pending = list.length;
let failed = false;
list.forEach((video) => {
const beforeUid = plmod._nextuid;
const itemData = Object.assign({}, data, {
id: video.id,
type: video.type,
link: util.formatLink(video.id, video.type, video.meta || null)
});
plmod._addItem(video, itemData, proxy, () => {
if (failed) {
return;
}
if (plmod._nextuid === beforeUid) {
failed = true;
reject(new Error(`Failed to add show list item: ${entry.type}:${entry.id}`));
return;
}
if (firstUid === null) {
firstUid = beforeUid;
}
pending -= 1;
if (pending === 0) {
resolve(firstUid);
}
});
});
return;
}
const beforeUid = plmod._nextuid;
plmod._addItem(media, data, proxy, () => {
if (plmod._nextuid === beforeUid) {
reject(new Error(`Failed to add show item: ${entry.type}:${entry.id}`));
return;
}
resolve(beforeUid);
});
});
});
}
async function applyShowToChannel(chan, show) {
const playlist = normalizePlaylist(show.playlist); const playlist = normalizePlaylist(show.playlist);
if (playlist.length === 0) { if (playlist.length === 0) {
throw new Error('Show playlist is empty'); throw new Error('Show playlist is empty');
@ -62,18 +146,16 @@ function applyShowToChannel(chan, show) {
plmod.handleClear(proxy); plmod.handleClear(proxy);
} }
playlist.forEach((entry, idx) => { const addedUids = [];
plmod.handleQueue(proxy, { for (let i = 0; i < playlist.length; i++) {
id: entry.id, const uid = await queueShowEntry(plmod, proxy, playlist[i], i);
type: entry.type, addedUids.push(uid);
pos: idx === 0 && entry.pos === 'next' ? 'next' : 'end' }
});
});
if (show.start_playback) { if (show.start_playback) {
const first = plmod.items.first; const firstShowUid = addedUids[0];
if (first) { if (typeof firstShowUid === 'number') {
plmod.handleJumpTo(proxy, first.uid); plmod.handleJumpTo(proxy, firstShowUid);
} }
} }
} }
@ -85,7 +167,7 @@ async function runShow(show) {
} }
const chan = server.getChannel(show.channel_name); const chan = server.getChannel(show.channel_name);
applyShowToChannel(chan, show); await applyShowToChannel(chan, show);
} }
async function pollAndRunDueShows() { async function pollAndRunDueShows() {

View file

@ -284,17 +284,17 @@ mixin shows
option(value="append") Append to queue option(value="append") Append to queue
option(value="replace") Replace queue option(value="replace") Replace queue
.form-group .form-group
label.control-label.col-sm-3(for="cs-shows-conflict-mode") Conflict Mode .col-sm-9.col-sm-offset-3
.col-sm-9 .checkbox
select#cs-shows-conflict-mode.form-control label(for="cs-shows-conflict-skip")
option(value="force") Force run input#cs-shows-conflict-skip(type="checkbox")
option(value="skip") Skip if queue not empty | Skip show if queue is not empty
.form-group .form-group
.col-sm-9.col-sm-offset-3 .col-sm-9.col-sm-offset-3
.checkbox .checkbox
label(for="cs-shows-start-playback") label(for="cs-shows-start-playback")
input#cs-shows-start-playback(type="checkbox") input#cs-shows-start-playback(type="checkbox")
| Start playback immediately | Skip current playback and start this show's first item immediately
.form-group .form-group
label.control-label.col-sm-3(for="cs-shows-mediaurl") Show Playlist label.control-label.col-sm-3(for="cs-shows-mediaurl") Show Playlist
.col-sm-9 .col-sm-9

View file

@ -1472,7 +1472,7 @@ var CSTShows = (function () {
timezone: timezone, timezone: timezone,
recurrence: $('#cs-shows-recurrence').val(), recurrence: $('#cs-shows-recurrence').val(),
fill_mode: $('#cs-shows-fill-mode').val(), fill_mode: $('#cs-shows-fill-mode').val(),
conflict_mode: $('#cs-shows-conflict-mode').val(), conflict_mode: $('#cs-shows-conflict-skip').prop('checked') ? 'skip' : 'force',
start_playback: $('#cs-shows-start-playback').prop('checked'), start_playback: $('#cs-shows-start-playback').prop('checked'),
playlist: draftPlaylist.map(function (item) { playlist: draftPlaylist.map(function (item) {
return { id: item.id, type: item.type, pos: item.pos || 'end' }; return { id: item.id, type: item.type, pos: item.pos || 'end' };
@ -1496,7 +1496,7 @@ var CSTShows = (function () {
$('#cs-shows-timezone').val(detectedTz); $('#cs-shows-timezone').val(detectedTz);
$('#cs-shows-recurrence').val('none'); $('#cs-shows-recurrence').val('none');
$('#cs-shows-fill-mode').val('append'); $('#cs-shows-fill-mode').val('append');
$('#cs-shows-conflict-mode').val('force'); $('#cs-shows-conflict-skip').prop('checked', false);
$('#cs-shows-start-playback').prop('checked', false); $('#cs-shows-start-playback').prop('checked', false);
$('#cs-shows-mediaurl').val(''); $('#cs-shows-mediaurl').val('');
draftPlaylist = []; draftPlaylist = [];
@ -1515,7 +1515,7 @@ var CSTShows = (function () {
$('#cs-shows-timezone').val(showTz); $('#cs-shows-timezone').val(showTz);
$('#cs-shows-recurrence').val(show.recurrence || 'none'); $('#cs-shows-recurrence').val(show.recurrence || 'none');
$('#cs-shows-fill-mode').val(show.fill_mode || 'append'); $('#cs-shows-fill-mode').val(show.fill_mode || 'append');
$('#cs-shows-conflict-mode').val(show.conflict_mode || 'force'); $('#cs-shows-conflict-skip').prop('checked', (show.conflict_mode || 'force') === 'skip');
$('#cs-shows-start-playback').prop('checked', !!show.start_playback); $('#cs-shows-start-playback').prop('checked', !!show.start_playback);
draftPlaylist = (show.playlist || []).map(function (item) { draftPlaylist = (show.playlist || []).map(function (item) {
return { return {