From 69620d806d444bf2ae7fe6167b61a06b1163b4f1 Mon Sep 17 00:00:00 2001 From: jr-k Date: Sun, 21 Jul 2024 21:32:11 +0200 Subject: [PATCH] working dyn video duration --- data/www/js/global.js | 7 +++++ data/www/js/slideshow/slides.js | 28 +++++++++++++++++--- lang/en.json | 1 + lang/es.json | 1 + lang/fr.json | 1 + lang/it.json | 1 + src/controller/PlayerController.py | 7 +++-- src/controller/PlaylistController.py | 3 ++- src/model/enum/ContentType.py | 2 ++ views/player/player.jinja.html | 17 ++++++++++-- views/playlist/list.jinja.html | 1 + views/slideshow/slides/modal/add.jinja.html | 18 +++++++++++++ views/slideshow/slides/modal/edit.jinja.html | 10 +++++++ 13 files changed, 87 insertions(+), 10 deletions(-) diff --git a/data/www/js/global.js b/data/www/js/global.js index 7ddad5b..195f89b 100644 --- a/data/www/js/global.js +++ b/data/www/js/global.js @@ -162,5 +162,12 @@ jQuery(document).ready(function ($) { showToast(l.js_common_copied); }); + + // Weird fix for toggle in modals + $(document).on('click', '.modal .toggle label', function (e) { + const $toggle = $(this).parents('.toggle:eq(0)'); + const $checkbox = $toggle.find('input[type=checkbox]'); + $checkbox.prop('checked', !$checkbox.prop('checked')); + }); }); diff --git a/data/www/js/slideshow/slides.js b/data/www/js/slideshow/slides.js index 3714eae..d692581 100644 --- a/data/www/js/slideshow/slides.js +++ b/data/www/js/slideshow/slides.js @@ -98,7 +98,7 @@ jQuery(document).ready(function ($) { $datetimepickerStart.toggleClass('hidden', !isDatetimeStart); $datetimepickerEnd.toggleClass('hidden', !isDatetimeEnd); - $durationGroup.toggleClass('hidden', isNotification && isDatetimeEnd); + $durationGroup.toggleClass('hidden', (isNotification && isDatetimeEnd) || parseInt($targetDuration.val()) === auto_duration_cheatcode); $scheduleEndGroup.toggleClass('hidden', isLoopStart); $durationGroup.find('.widget input').prop('required', $durationGroup.is(':visible')); @@ -125,6 +125,18 @@ jQuery(document).ready(function ($) { flushValues(); }; + const inputAutoDurationUpdate = function (enableAutoDuration) { + const $modal = $('.modal-slide:visible'); + const $input = $modal.find('.slide-auto-duration'); + const $durationGroup = $modal.find('.slide-duration-group'); + const $durationInput = $durationGroup.find('input'); + const $autoDurationGroup = $modal.find('.slide-auto-duration-group'); + const activeAutoDuration = $input.prop('checked'); + + $durationGroup.toggleClass('hidden', enableAutoDuration && activeAutoDuration); + $autoDurationGroup.toggleClass('hidden', !enableAutoDuration); + $durationInput.val(enableAutoDuration && activeAutoDuration ? auto_duration_cheatcode : 3); + }; const main = function () { $("ul.slides").sortable({ @@ -147,7 +159,7 @@ jQuery(document).ready(function ($) { $(document).on('click', '.content-explr-picker', function () { showPickers('modal-content-explr-picker', function (content) { - inputContentUpdate(content) + inputContentUpdate(content); }); }); @@ -157,8 +169,11 @@ jQuery(document).ready(function ($) { const $inputLabel = $group.find('.target-label'); const $inputId = $group.find('.target'); const $actionShow = $group.find('.slide-content-show'); + const invalidContent = content === undefined || !content.id; - if (content === undefined || !content.id) { + inputAutoDurationUpdate(!invalidContent && content.type === 'video'); + + if (invalidContent) { $inputLabel.val(''); $inputId.val(''); $actionShow.addClass('hidden'); @@ -170,6 +185,10 @@ jQuery(document).ready(function ($) { $actionShow.removeClass('hidden'); }; + $(document).on('change', '.slide-auto-duration', function () { + inputAutoDurationUpdate(true); + }); + $(document).on('click', '.slide-content-show', function () { window.open($(this).attr('data-route').replace('__id__', $(this).parents('.widget:eq(0)').find('.target').val())); }); @@ -186,6 +205,9 @@ jQuery(document).ready(function ($) { const hasDateTimeEnd = hasCronEnd && validateCronDateTime(slide.cron_schedule_end); const isNotification = slide.is_notification; + + $modal.find('#slide-edit-auto-duration').prop('checked', slide.duration === auto_duration_cheatcode); + inputContentUpdate(slide.content); $modal.find('input[type=text]:visible:eq(0)').focus().select(); diff --git a/lang/en.json b/lang/en.json index dfdd22c..8287322 100644 --- a/lang/en.json +++ b/lang/en.json @@ -33,6 +33,7 @@ "slideshow_slide_form_section_scheduling": "Scheduling", "slideshow_slide_form_label_name": "Name", "slideshow_slide_form_label_enabled": "Enable/Disable", + "slideshow_slide_form_label_auto_duration": "Use video's duration as timer", "slideshow_slide_form_label_add_content": "Upload to library", "slideshow_slide_form_label_from_library": "From library", "slideshow_slide_form_label_content_id": "Content", diff --git a/lang/es.json b/lang/es.json index f1b13e7..17591de 100644 --- a/lang/es.json +++ b/lang/es.json @@ -34,6 +34,7 @@ "slideshow_slide_form_label_name": "Nombre", "slideshow_slide_form_label_add_content": "Upload a la biblioteca", "slideshow_slide_form_label_enabled": "Activar/Desactivar", + "slideshow_slide_form_label_auto_duration": "Utilizar la duración del vídeo", "slideshow_slide_form_label_from_library": "Dalla biblioteca", "slideshow_slide_form_label_content_id": "Contenido", "slideshow_slide_form_label_location": "Ubicación", diff --git a/lang/fr.json b/lang/fr.json index 6411218..f18463d 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -33,6 +33,7 @@ "slideshow_slide_form_section_scheduling": "Programmation", "slideshow_slide_form_label_name": "Nom", "slideshow_slide_form_label_enabled": "Activer/Désactiver", + "slideshow_slide_form_label_auto_duration": "Utiliser la durée de la vidéo", "slideshow_slide_form_label_add_content": "Upload à la bibliothèque", "slideshow_slide_form_label_from_library": "Depuis la bibliothèque", "slideshow_slide_form_label_content_id": "Contenu", diff --git a/lang/it.json b/lang/it.json index 0eca744..497ca32 100644 --- a/lang/it.json +++ b/lang/it.json @@ -33,6 +33,7 @@ "slideshow_slide_form_section_scheduling": "Programmazione", "slideshow_slide_form_label_name": "Nome", "slideshow_slide_form_label_enabled": "Abilita/Disabilita", + "slideshow_slide_form_label_auto_duration": "Utilizza la durata del video", "slideshow_slide_form_label_add_content": "Upload alla biblioteca", "slideshow_slide_form_label_from_library": "Dalla biblioteca", "slideshow_slide_form_label_content_id": "Contenuti", diff --git a/src/controller/PlayerController.py b/src/controller/PlayerController.py index 863b2f6..53ada3c 100644 --- a/src/controller/PlayerController.py +++ b/src/controller/PlayerController.py @@ -8,7 +8,7 @@ from flask import Flask, render_template, redirect, request, url_for, send_from_ from pathlib import Path from src.model.entity.Slide import Slide -from src.model.enum.ContentType import ContentType +from src.model.enum.ContentType import ContentType, AUTO_DURATION_CHEATCODE from src.exceptions.NoFallbackPlaylistException import NoFallbackPlaylistException from src.service.ModelStore import ModelStore from src.interface.ObController import ObController @@ -60,7 +60,8 @@ class PlayerController(ObController): slide_animation_enabled=animation_enabled, slide_animation_entrance_effect=slide_animation_entrance_effect, slide_animation_speed=slide_animation_speed, - animation_speed_duration=animation_speed_duration + animation_speed_duration=animation_speed_duration, + auto_duration_cheatcode=AUTO_DURATION_CHEATCODE ) def player_default(self): @@ -167,8 +168,6 @@ class PlayerController(ObController): 'hard_refresh_request': self._model_store.variable().get_one_by_name("refresh_player_request").as_int() } - logging.info(playlists['loop']) - return playlists def _check_slide_enablement(self, loop: List, notifications: List, slide: Dict) -> None: diff --git a/src/controller/PlaylistController.py b/src/controller/PlaylistController.py index 4b9a8dc..9e8e832 100644 --- a/src/controller/PlaylistController.py +++ b/src/controller/PlaylistController.py @@ -4,7 +4,7 @@ from flask import Flask, render_template, redirect, request, url_for, jsonify, a from src.service.ModelStore import ModelStore from src.model.entity.Playlist import Playlist from src.model.enum.FolderEntity import FolderEntity -from src.model.enum.ContentType import ContentType +from src.model.enum.ContentType import ContentType, AUTO_DURATION_CHEATCODE from src.interface.ObController import ObController @@ -49,6 +49,7 @@ class PlaylistController(ObController): folders_tree=self._model_store.folder().get_folder_tree(FolderEntity.CONTENT), enum_content_type=ContentType, enum_folder_entity=FolderEntity, + auto_duration_cheatcode=AUTO_DURATION_CHEATCODE, ) def playlist_add(self): diff --git a/src/model/enum/ContentType.py b/src/model/enum/ContentType.py index 5276ea7..0b564bd 100644 --- a/src/model/enum/ContentType.py +++ b/src/model/enum/ContentType.py @@ -5,6 +5,8 @@ from typing import Union, List, Optional from src.util.utils import str_to_enum +AUTO_DURATION_CHEATCODE = 98769876 + class ContentInputType(Enum): diff --git a/views/player/player.jinja.html b/views/player/player.jinja.html index e94a99a..a1d3d8b 100755 --- a/views/player/player.jinja.html +++ b/views/player/player.jinja.html @@ -75,6 +75,7 @@ let clockValue = 0; let curItemIndex = -1; let secondsBeforeNext = 0; + const durationsOverride = {}; const introSlide = document.getElementById('IntroSlide'); const notificationSlide = document.getElementById('NotificationSlide'); const firstSlide = document.getElementById('FirstSlide'); @@ -157,6 +158,10 @@ pause(); }; + const isDurationAuto = function(duration) { + return duration === {{ auto_duration_cheatcode }}; + } ; + const lookupPreviousItem = function() { return (curItemIndex - 1 < 0) ? items.loop[items.loop.length - 1] : items.loop[curItemIndex - 1]; }; @@ -191,7 +196,14 @@ if (!item) { return tickRefreshResolutionMs/1000; } - return item.duration + Math.ceil(animation_speed_duration/1000); + + let duration = item.duration; + + if (durationsOverride[item.id]) { + duration = durationsOverride[item.id]; + } + + return duration + Math.ceil(animation_speed_duration/1000); }; const main = function() { @@ -363,7 +375,8 @@ delayNoisyContentJIT = lookupCurrentItem().id !== item.id ? delayNoisyContentJIT : 0; video.addEventListener('loadedmetadata', function() { - if (item.duration !== video.duration) { + if (item.duration !== video.duration && isDurationAuto(item.duration)) { + durationsOverride[item.id] = video.duration; console.warn('Given duration ' + item.duration + 's is different from video file ' + Math.ceil(video.duration) + 's'); } }); diff --git a/views/playlist/list.jinja.html b/views/playlist/list.jinja.html index 6bb4e19..9214fe5 100644 --- a/views/playlist/list.jinja.html +++ b/views/playlist/list.jinja.html @@ -13,6 +13,7 @@ {% block add_js %}