From d61d2124fbfa63750ab7ac580f14639a11bc1177 Mon Sep 17 00:00:00 2001 From: Jonathan Baecker Date: Mon, 21 Oct 2024 15:08:32 +0200 Subject: [PATCH 1/8] add info about relative paths --- frontend/components/ConfigPlayout.vue | 5 +++++ frontend/i18n/locales/de-DE.js | 3 ++- frontend/i18n/locales/en-US.js | 3 ++- frontend/i18n/locales/pt-BR.js | 3 ++- frontend/i18n/locales/ru-RU.js | 3 ++- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/frontend/components/ConfigPlayout.vue b/frontend/components/ConfigPlayout.vue index c55ed05d..cf003283 100644 --- a/frontend/components/ConfigPlayout.vue +++ b/frontend/components/ConfigPlayout.vue @@ -705,6 +705,11 @@ class="textarea textarea-bordered" rows="6" /> +
+ + {{ t('config.outputParam') }} + +
diff --git a/frontend/i18n/locales/de-DE.js b/frontend/i18n/locales/de-DE.js index 0db7d93e..f599c170 100644 --- a/frontend/i18n/locales/de-DE.js +++ b/frontend/i18n/locales/de-DE.js @@ -206,7 +206,7 @@ export default { playlistLength: 'Ziel-Länge der Playlist; wenn es leer ist, wird die reale Länge nicht berücksichtigt.', playlistInfinit: 'Eine einzelne Playlist-Datei endlos wiederholen.', storageHelp: 'Speichereinstellungen, die Standorte sind relativ zum Kanal-Speicher.', - storageFiller: 'Verwende Füllmaterial, um anstelle einer fehlenden Datei abzuspielen oder um die verbleibende Zeit zu füllen, um eine Gesamtdauer von 24 Stunden zu erreichen. Es kann eine Datei oder ein Ordner sein und wird bei Bedarf wiederholt.', + storageFiller: 'Verwenden Sie einen Platzhalter, um eine fehlende Datei abzuspielen oder um die verbleibende Zeit auf insgesamt 24 Stunden zu füllen. Es kann sich um eine Datei oder einen Ordner mit relativem Pfad handeln, der bei Bedarf wiederholt wird.', storageExtension: 'Gib an, welche Dateien gesucht und verwendet werden sollen.', storageShuffle: 'Wähle Dateien zufällig aus (im Ordner-Modus und bei der Playlist-Erstellung).', textHelp: 'Texteinblendung in Kombination mit libzmq für die Fernmanipulation von Text.', @@ -217,6 +217,7 @@ export default { taskHelp: 'Führe ein externes Programm mit einem gegebenen Medienobjekt aus. Das Medienobjekt ist im JSON-Format und enthält alle Informationen über den aktuellen Clip. Das externe Programm kann ein Skript oder eine Binärdatei sein, sollte aber nur für kurze Zeit laufen.', taskPath: 'Pfad zur ausführbaren Datei.', outputHelp: `Die endgültige Playout-Codierung, passe die Einstellungen nach deinen Bedürfnissen an. Verwende den 'stream'-Modus und passe den 'Ausgabe-Parameter' an, wenn du zu einem RTMP/RTSP/SRT/...-Server streamen möchtest. Im Produktionsbetrieb verwende kein HLS mit ffplayout; nutze Nginx oder einen anderen Webserver!`, + outputParam: 'HLS-Segment- und Playlist-Pfade sind relativ.', restartTile: 'Playout neustarten', restartText: 'ffplayout neustarten um Einstellungen anzuwenden?', updatePlayoutSuccess: 'Update der Playout-Konfiguration erfolgreich!', diff --git a/frontend/i18n/locales/en-US.js b/frontend/i18n/locales/en-US.js index 7c5fb291..8b5cfcfa 100644 --- a/frontend/i18n/locales/en-US.js +++ b/frontend/i18n/locales/en-US.js @@ -206,7 +206,7 @@ export default { playlistLength: 'Target length of the playlist; when it is blank, the real length will not be considered.', playlistInfinit: 'Loop a single playlist file infinitely.', storageHelp: 'Storage settings, locations are relative to channel storage.', - storageFiller: 'Use filler to play in place of a missing file or to fill the remaining time to reach a total of 24 hours. It can be a file or folder and will loop when necessary.', + storageFiller: 'Use filler to play in place of a missing file or to fill the remaining time to reach a total of 24 hours. It can be a file or folder, with relative path, and will loop when necessary.', storageExtension: 'Specify which files to search and use.', storageShuffle: 'Pick files randomly (in folder mode and playlist generation).', textHelp: 'Overlay text in combination with libzmq for remote text manipulation.', @@ -218,6 +218,7 @@ export default { taskPath: 'Path to executable.', outputHelp: `The final playout encoding, set the settings according to your needs. Use 'stream' mode and adjust the 'Output Parameter' when you want to stream to an RTMP/RTSP/SRT/... server. In production, don't serve HLS playlists with ffplayout; use Nginx or another web server!`, + outputParam: 'HLS segment and playlist paths are relative.', restartTile: 'Restart Playout', restartText: 'Restart ffplayout to apply changes?', updatePlayoutSuccess: 'Update playout config success!', diff --git a/frontend/i18n/locales/pt-BR.js b/frontend/i18n/locales/pt-BR.js index 4914e6dc..d370c280 100644 --- a/frontend/i18n/locales/pt-BR.js +++ b/frontend/i18n/locales/pt-BR.js @@ -206,7 +206,7 @@ export default { playlistLength: 'Duração alvo da playlist; quando estiver em branco, o comprimento real não será considerado.', playlistInfinit: 'Reproduza infinitamente um único arquivo de playlist.', storageHelp: 'Configurações de armazenamento, os locais são relativos ao armazenamento do canal.', - storageFiller: 'Use preenchimento para tocar no lugar de um arquivo ausente ou para preencher o tempo restante para atingir um total de 24 horas. Pode ser um arquivo ou pasta e será repetido quando necessário.', + storageFiller: 'Use um preenchimento para reproduzir no lugar de um arquivo ausente ou preencher o tempo restante para alcançar um total de 24 horas. Pode ser um arquivo ou uma pasta com caminho relativo, e será repetido quando necessário.', storageExtension: 'Especifique quais arquivos procurar e usar.', storageShuffle: 'Escolha arquivos aleatoriamente (no modo de pasta e geração de playlist).', textHelp: 'Sobrepor texto em combinação com libzmq para manipulação remota de texto.', @@ -217,6 +217,7 @@ export default { taskHelp: 'Execute um programa externo com um objeto de mídia fornecido. O objeto de mídia está em formato JSON e contém todas as informações sobre o clipe atual. O programa externo pode ser um script ou binário, mas deve ser executado apenas por um curto período de tempo.', taskPath: 'Caminho para o executável.', outputHelp: `A codificação final do playout, ajuste as configurações de acordo com suas necessidades. Use o modo 'stream' e ajuste o 'Parâmetro de Saída' quando quiser fazer streaming para um servidor RTMP/RTSP/SRT/... No ambiente de produção, não sirva playlists HLS com ffplayout; use Nginx ou outro servidor web!`, + outputParam: 'Os caminhos dos segmentos e playlists HLS são relativos.', restartTile: 'Reiniciar Playout', restartText: 'Reiniciar o ffplayout para aplicar as alterações?', updatePlayoutSuccess: 'Sucesso na atualização da configuração do playout!', diff --git a/frontend/i18n/locales/ru-RU.js b/frontend/i18n/locales/ru-RU.js index 489cb2eb..f8f50d48 100644 --- a/frontend/i18n/locales/ru-RU.js +++ b/frontend/i18n/locales/ru-RU.js @@ -206,7 +206,7 @@ export default { playlistLength: 'Target length of the playlist; when it is blank, the real length will not be considered.', playlistInfinit: 'Loop a single playlist file infinitely.', storageHelp: 'Storage settings, locations are relative to channel storage.', - storageFiller: 'Use filler to play in place of a missing file or to fill the remaining time to reach a total of 24 hours. It can be a file or folder and will loop when necessary.', + storageFiller: 'Use filler to play in place of a missing file or to fill the remaining time to reach a total of 24 hours. It can be a file or folder, with relative path, and will loop when necessary.', storageExtension: 'Specify which files to search and use.', storageShuffle: 'Pick files randomly (in folder mode and playlist generation).', textHelp: 'Overlay text in combination with libzmq for remote text manipulation.', @@ -218,6 +218,7 @@ export default { taskPath: 'Path to executable.', outputHelp: `The final playout encoding, set the settings according to your needs. Use 'stream' mode and adjust the 'Output Parameter' when you want to stream to an RTMP/RTSP/SRT/... server. In production, don't serve HLS playlists with ffplayout; use Nginx or another web server!`, + outputParam: 'HLS segment and playlist paths are relative.', restartTile: 'Перезапуск Playout', restartText: 'Перезапустить ffplayout для применения изменений?', updatePlayoutSuccess: 'Обновление конфигурации воспроизведения прошло успешно!', From 627f02d5f2c68a42568f31e981c7729ced3dad2e Mon Sep 17 00:00:00 2001 From: Jonathan Baecker Date: Wed, 23 Oct 2024 12:28:28 +0200 Subject: [PATCH 2/8] add doc string --- engine/src/player/controller.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/src/player/controller.rs b/engine/src/player/controller.rs index 146ccb48..40acca75 100644 --- a/engine/src/player/controller.rs +++ b/engine/src/player/controller.rs @@ -400,6 +400,7 @@ fn find_m3u8_files(path: &Path) -> io::Result> { Ok(m3u8_files) } +/// Check if segment is in playlist, if not, delete it. fn delete_old_segments + Clone + std::fmt::Debug>( path: P, pl_segments: &[String], From 144799e7224388789a808e7fc2daa1b05da19a4b Mon Sep 17 00:00:00 2001 From: Jonathan Baecker Date: Wed, 23 Oct 2024 15:09:46 +0200 Subject: [PATCH 3/8] remove signal term, scroll down on logs, scroll to item on playlist generation --- Cargo.lock | 49 +++++++++-------------- engine/Cargo.toml | 6 +-- engine/src/api/routes.rs | 4 +- engine/src/player/controller.rs | 19 ++++----- frontend/components/PlaylistGenerator.vue | 1 + frontend/components/PlaylistTable.vue | 14 ++++--- frontend/pages/logging.vue | 22 +++++++--- frontend/pages/media.vue | 16 ++++---- frontend/stores/playlist.ts | 1 + 9 files changed, 67 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10433b92..42e76d1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,9 +341,9 @@ dependencies = [ [[package]] name = "actix-web-lab" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a965e3e826aa4737af33666aa09ed949aa1837706fda2adee07039347be50d6" +checksum = "ee75923689132fc5fb57ccc5bb98d25bb214796a29cd505844eb3b42daf11df0" dependencies = [ "actix-http", "actix-router", @@ -366,7 +366,6 @@ dependencies = [ "local-channel", "mediatype", "mime", - "once_cell", "pin-project-lite", "regex", "serde", @@ -380,9 +379,9 @@ dependencies = [ [[package]] name = "actix-web-lab-derive" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008f98f5a68eeacf5e6d44ed74ce03c1b906baa53eabfb41faf0f5f40bd685f8" +checksum = "4c221da13534b9352f3f79fcbbd6095f6d8aee63bdf1da8a73d36f9eeea17d5a" dependencies = [ "proc-macro2", "quote", @@ -720,9 +719,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "bytestring" @@ -1233,7 +1232,6 @@ dependencies = [ "ffprobe", "flexi_logger", "futures-util", - "home", "jsonwebtoken", "lazy_static", "lettre", @@ -1259,7 +1257,6 @@ dependencies = [ "serde_json", "serde_with", "shlex", - "signal-child", "sqlx", "static-files", "sysinfo", @@ -1326,9 +1323,9 @@ dependencies = [ [[package]] name = "flexi_logger" -version = "0.29.3" +version = "0.29.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719236bdbcf6033a3395165f797076b31056018e6723ccff616eb25fc9c99de1" +checksum = "0bc6a1594377eb9de4205e15e33e222c996de8dc047f7c998cc477030bfac48a" dependencies = [ "chrono", "log", @@ -2592,9 +2589,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -3011,18 +3008,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" dependencies = [ "proc-macro2", "quote", @@ -3186,12 +3183,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-child" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3184fa464a0128cbcc353100ae752a848bc0067dd5715a50550f31570051150" - [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -3715,18 +3706,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", @@ -3791,9 +3782,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", diff --git a/engine/Cargo.toml b/engine/Cargo.toml index c00355e4..d43362e2 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -18,7 +18,7 @@ actix-multipart = "0.7" actix-web = "4" actix-web-grants = "4" actix-web-httpauth = "0.8" -actix-web-lab = "0.22" +actix-web-lab = "0.23" actix-web-static-files = "4.0" argon2 = "0.5" chrono = { version = "0.4", default-features = false, features = ["clock", "std", "serde"] } @@ -29,7 +29,6 @@ faccess = "0.2" ffprobe = "0.4" flexi_logger = { version = "0.29", features = ["kv", "colors"] } futures-util = { version = "0.3", default-features = false, features = ["std"] } -home = "0.5" jsonwebtoken = "9" lazy_static = "1.4" lettre = { version = "0.11", features = ["builder", "rustls-tls", "smtp-transport", "tokio1", "tokio1-rustls-tls"], default-features = false } @@ -70,9 +69,6 @@ zeromq = { version = "0.4", default-features = false, features = [ "tcp-transport", ] } -[target.'cfg(not(target_arch = "windows"))'.dependencies] -signal-child = "1" - [build-dependencies] static-files = "0.2" diff --git a/engine/src/api/routes.rs b/engine/src/api/routes.rs index 978f87eb..6dc31898 100644 --- a/engine/src/api/routes.rs +++ b/engine/src/api/routes.rs @@ -984,10 +984,10 @@ pub async fn process_control( } ProcessCtl::Stop => { manager.channel.lock().unwrap().active = false; - manager.async_stop().await; + manager.async_stop().await?; } ProcessCtl::Restart => { - manager.async_stop().await; + manager.async_stop().await?; tokio::time::sleep(tokio::time::Duration::from_millis(1500)).await; if !manager.is_alive.load(Ordering::SeqCst) { diff --git a/engine/src/player/controller.rs b/engine/src/player/controller.rs index 40acca75..e1c42883 100644 --- a/engine/src/player/controller.rs +++ b/engine/src/player/controller.rs @@ -11,9 +11,7 @@ use std::{ time::Duration, }; -#[cfg(not(windows))] -use signal_child::Signalable; - +use actix_web::web; use log::*; use m3u8_rs::Playlist; use serde::{Deserialize, Serialize}; @@ -26,7 +24,7 @@ use crate::player::{ }; use crate::utils::{ config::{OutputMode::*, PlayoutConfig}, - errors::ProcessError, + errors::{ProcessError, ServiceError}, }; use crate::ARGS; use crate::{ @@ -203,11 +201,6 @@ impl ChannelManager { match unit { Decoder => { if let Some(proc) = self.decoder.lock()?.as_mut() { - #[cfg(not(windows))] - proc.term() - .map_err(|e| ProcessError::Custom(format!("Decoder: {e}")))?; - - #[cfg(windows)] proc.kill() .map_err(|e| ProcessError::Custom(format!("Decoder: {e}")))?; } @@ -258,7 +251,7 @@ impl ChannelManager { Ok(()) } - pub async fn async_stop(&self) { + pub async fn async_stop(&self) -> Result<(), ServiceError> { self.is_terminated.store(true, Ordering::SeqCst); self.is_alive.store(false, Ordering::SeqCst); self.ingest_is_running.store(false, Ordering::SeqCst); @@ -272,12 +265,16 @@ impl ChannelManager { }; for unit in [Decoder, Encoder, Ingest] { - if let Err(e) = self.stop(unit) { + let self_clone = self.clone(); + + if let Err(e) = web::block(move || self_clone.stop(unit)).await? { if !e.to_string().contains("exited process") { error!(target: Target::all(), channel = channel_id; "{e}") } } } + + Ok(()) } /// No matter what is running, terminate them all. diff --git a/frontend/components/PlaylistGenerator.vue b/frontend/components/PlaylistGenerator.vue index 847df9f2..a0b0c774 100644 --- a/frontend/components/PlaylistGenerator.vue +++ b/frontend/components/PlaylistGenerator.vue @@ -420,6 +420,7 @@ async function generatePlaylist() { resetCheckboxes() resetTemplate() + playlistStore.scrollToItem = true playlistStore.isLoading = false } diff --git a/frontend/components/PlaylistTable.vue b/frontend/components/PlaylistTable.vue index d47823d1..21e2047d 100644 --- a/frontend/components/PlaylistTable.vue +++ b/frontend/components/PlaylistTable.vue @@ -140,7 +140,7 @@ const playlistContainer = ref() const sortContainer = ref() const todayDate = ref($dayjs().utcOffset(configStore.utcOffset).format('YYYY-MM-DD')) const { i } = storeToRefs(useConfig()) -const { currentIndex, listDate, playoutIsRunning } = storeToRefs(usePlaylist()) +const { currentIndex, listDate, playoutIsRunning, scrollToItem } = storeToRefs(usePlaylist()) const playlistSortOptions = { group: 'playlist', @@ -175,10 +175,14 @@ watch([listDate, i], () => { }, 800) }) -watch([playoutIsRunning], () => { - setTimeout(() => { - scrollTo(currentIndex.value) - }, 400) +watch([playoutIsRunning, scrollToItem], () => { + if (playoutIsRunning.value || scrollToItem.value) { + setTimeout(() => { + scrollTo(currentIndex.value) + + scrollToItem.value = false + }, 400) + } }) defineExpose({ diff --git a/frontend/pages/logging.vue b/frontend/pages/logging.vue index 00c8342e..4f074a8d 100644 --- a/frontend/pages/logging.vue +++ b/frontend/pages/logging.vue @@ -34,10 +34,9 @@
-
+
+
+
@@ -88,7 +87,16 @@ watch([listDate, i], () => { }) const calendarFormat = (date: Date) => { - return $dayjs(date).locale(locale.value).format('ddd L') + return $dayjs(date).locale(locale.value).format('ddd L') +} + +function scrollTo() { + const parent = document.getElementById('log-container') + const child = document.getElementById('log-content') + + if (child && parent) { + parent.scrollTop = child.scrollHeight + } } function filterLogsBySeverity(logString: string, minSeverity: string): string { @@ -121,6 +129,10 @@ async function getLog() { .then((response) => response.text()) .then((data) => { currentLog.value = data + + nextTick(() => { + scrollTo() + }) }) .catch(() => { currentLog.value = '' diff --git a/frontend/pages/media.vue b/frontend/pages/media.vue index be8022a9..dc93e634 100644 --- a/frontend/pages/media.vue +++ b/frontend/pages/media.vue @@ -330,14 +330,6 @@ useHead({ title: `${t('button.media')} | ffplayout`, }) -watch([width], () => { - if (width.value < 640) { - horizontal.value = true - } else { - horizontal.value = false - } -}) - const horizontal = ref(false) const deleteName = ref('') const recursive = ref(false) @@ -384,6 +376,14 @@ onMounted(async () => { } }) +watch([width], () => { + if (width.value < 640) { + horizontal.value = true + } else { + horizontal.value = false + } +}) + watch([i], () => { mediaStore.getTree('') }) diff --git a/frontend/stores/playlist.ts b/frontend/stores/playlist.ts index 5c530341..c7c8286b 100644 --- a/frontend/stores/playlist.ts +++ b/frontend/stores/playlist.ts @@ -24,6 +24,7 @@ export const usePlaylist = defineStore('playlist', { playoutIsRunning: false, last_channel: 0, firstLoad: true, + scrollToItem: false, }), getters: {}, From f99f28384700c9f9dd22ec4f2ed1b4eece1d2e0f Mon Sep 17 00:00:00 2001 From: Jonathan Baecker Date: Wed, 23 Oct 2024 15:18:44 +0200 Subject: [PATCH 4/8] log only when is alive --- engine/src/player/controller.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/engine/src/player/controller.rs b/engine/src/player/controller.rs index e1c42883..04d5ad06 100644 --- a/engine/src/player/controller.rs +++ b/engine/src/player/controller.rs @@ -252,13 +252,17 @@ impl ChannelManager { } pub async fn async_stop(&self) -> Result<(), ServiceError> { + let channel_id = self.channel.lock().unwrap().id; + + if self.is_alive.load(Ordering::SeqCst) { + debug!(target: Target::all(), channel = channel_id; "Deactivate playout and stop all child processes from channel: {channel_id}"); + } + self.is_terminated.store(true, Ordering::SeqCst); self.is_alive.store(false, Ordering::SeqCst); self.ingest_is_running.store(false, Ordering::SeqCst); self.run_count.fetch_sub(1, Ordering::SeqCst); let pool = self.db_pool.clone().unwrap(); - let channel_id = self.channel.lock().unwrap().id; - debug!(target: Target::all(), channel = channel_id; "Deactivate playout and stop all child processes from channel: {channel_id}"); if let Err(e) = handles::update_player(&pool, channel_id, false).await { error!(target: Target::all(), channel = channel_id; "Unable write to player status: {e}"); @@ -279,12 +283,16 @@ impl ChannelManager { /// No matter what is running, terminate them all. pub fn stop_all(&self) { + let channel_id = self.channel.lock().unwrap().id; + + if self.is_alive.load(Ordering::SeqCst) { + debug!(target: Target::all(), channel = channel_id; "Stop all child processes from channel: {channel_id}"); + } + self.is_terminated.store(true, Ordering::SeqCst); self.is_alive.store(false, Ordering::SeqCst); self.ingest_is_running.store(false, Ordering::SeqCst); self.run_count.fetch_sub(1, Ordering::SeqCst); - let channel_id = self.channel.lock().unwrap().id; - debug!(target: Target::all(), channel = channel_id; "Stop all child processes from channel: {channel_id}"); for unit in [Decoder, Encoder, Ingest] { if let Err(e) = self.stop(unit) { From 3cf0d12200c731e886a3d8ac06a57fe5c75aac53 Mon Sep 17 00:00:00 2001 From: Jonathan Baecker Date: Wed, 23 Oct 2024 15:51:20 +0200 Subject: [PATCH 5/8] rename message to prevent confusion --- frontend/i18n/locales/de-DE.js | 4 ++-- frontend/i18n/locales/en-US.js | 4 ++-- frontend/i18n/locales/ru-RU.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/i18n/locales/de-DE.js b/frontend/i18n/locales/de-DE.js index f599c170..bf0fc960 100644 --- a/frontend/i18n/locales/de-DE.js +++ b/frontend/i18n/locales/de-DE.js @@ -1,8 +1,8 @@ export default { ok: 'Ok', cancel: 'Abbrechen', - socketConnected: 'Event Stream verbunden', - socketDisconnected: 'Event Stream nicht verbunden', + socketConnected: 'Message-Stream verbunden', + socketDisconnected: 'Message-Stream nicht verbunden', alert: { wrongLogin: 'Falsche Anmeldedaten!', }, diff --git a/frontend/i18n/locales/en-US.js b/frontend/i18n/locales/en-US.js index 8b5cfcfa..41145a46 100644 --- a/frontend/i18n/locales/en-US.js +++ b/frontend/i18n/locales/en-US.js @@ -1,8 +1,8 @@ export default { ok: 'Ok', cancel: 'Cancel', - socketConnected: 'Event stream connected', - socketDisconnected: 'Event stream disconnected', + socketConnected: 'Message stream connected', + socketDisconnected: 'Message stream disconnected', alert: { wrongLogin: 'Incorrect login data!', }, diff --git a/frontend/i18n/locales/ru-RU.js b/frontend/i18n/locales/ru-RU.js index f8f50d48..58908efa 100644 --- a/frontend/i18n/locales/ru-RU.js +++ b/frontend/i18n/locales/ru-RU.js @@ -1,8 +1,8 @@ export default { ok: 'ОК', cancel: 'Отмена', - socketConnected: 'Event stream connected', - socketDisconnected: 'Event stream disconnected', + socketConnected: 'Message stream connected', + socketDisconnected: 'Message stream disconnected', alert: { wrongLogin: 'Неверные данные для входа!', }, From 532c4b4615593ed7dd0c5e92ff7b169a84ef4c41 Mon Sep 17 00:00:00 2001 From: Jonathan Baecker Date: Thu, 24 Oct 2024 13:12:56 +0200 Subject: [PATCH 6/8] fix user permissions --- engine/src/api/routes.rs | 3 +-- frontend/components/ConfigChannel.vue | 12 ++++++++---- frontend/components/ConfigUser.vue | 4 +++- frontend/pages/configure.vue | 1 + frontend/pages/index.vue | 1 - 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/engine/src/api/routes.rs b/engine/src/api/routes.rs index 6dc31898..0f70b115 100644 --- a/engine/src/api/routes.rs +++ b/engine/src/api/routes.rs @@ -467,8 +467,7 @@ async fn get_all_channels( /// ``` #[patch("/channel/{id}")] #[protect( - "Role::GlobalAdmin", - "Role::ChannelAdmin", + any("Role::GlobalAdmin", "Role::ChannelAdmin"), ty = "Role", expr = "user.channels.contains(&*id) || role.has_authority(&Role::GlobalAdmin)" )] diff --git a/frontend/components/ConfigChannel.vue b/frontend/components/ConfigChannel.vue index ef806ae1..c8f9a93f 100644 --- a/frontend/components/ConfigChannel.vue +++ b/frontend/components/ConfigChannel.vue @@ -15,8 +15,9 @@ v-model="channel.name" type="text" placeholder="Type here" - class="input input-bordered w-full" + class="input input-bordered w-full !bg-base-100" @keyup="isChanged" + :disabled="authStore.role === 'User'" /> @@ -27,8 +28,9 @@ @@ -39,8 +41,10 @@ @@ -88,7 +92,7 @@ -
+
diff --git a/frontend/components/ConfigUser.vue b/frontend/components/ConfigUser.vue index dbbce716..8d902830 100644 --- a/frontend/components/ConfigUser.vue +++ b/frontend/components/ConfigUser.vue @@ -149,7 +149,9 @@ const user = ref({ } as User) onMounted(() => { - getUsers() + if (authStore.role === 'GlobalAdmin') { + getUsers() + } }) async function getUsers() { diff --git a/frontend/pages/configure.vue b/frontend/pages/configure.vue index 5c8f0c6c..09ede593 100644 --- a/frontend/pages/configure.vue +++ b/frontend/pages/configure.vue @@ -17,6 +17,7 @@ Advanced