New upstream version 21.0.2+dfsg1
This commit is contained in:
parent
1f1bbb3518
commit
baafb6325b
706 changed files with 49633 additions and 5044 deletions
|
|
@ -5,12 +5,14 @@ if(APPLE)
|
|||
include_directories(${COCOA})
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(X11 REQUIRED)
|
||||
link_libraries(${X11_LIBRARIES})
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/deps/obs-scripting")
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/frontend-tools-config.h.in"
|
||||
"${CMAKE_BINARY_DIR}/config/frontend-tools-config.h")
|
||||
|
|
@ -21,12 +23,19 @@ set(frontend-tools_HEADERS
|
|||
auto-scene-switcher.hpp
|
||||
output-timer.hpp
|
||||
tool-helpers.hpp
|
||||
../../properties-view.hpp
|
||||
../../properties-view.moc.hpp
|
||||
../../vertical-scroll-area.hpp
|
||||
../../double-slider.hpp
|
||||
)
|
||||
set(frontend-tools_SOURCES
|
||||
${frontend-tools_SOURCES}
|
||||
auto-scene-switcher.cpp
|
||||
frontend-tools.c
|
||||
output-timer.cpp
|
||||
../../properties-view.cpp
|
||||
../../vertical-scroll-area.cpp
|
||||
../../double-slider.cpp
|
||||
)
|
||||
set(frontend-tools_UI
|
||||
${frontend-tools_UI}
|
||||
|
|
@ -34,6 +43,25 @@ set(frontend-tools_UI
|
|||
forms/output-timer.ui
|
||||
)
|
||||
|
||||
if(SCRIPTING_ENABLED)
|
||||
set(frontend-tools_HEADERS
|
||||
${frontend-tools_HEADERS}
|
||||
scripts.hpp
|
||||
)
|
||||
set(frontend-tools_SOURCES
|
||||
${frontend-tools_SOURCES}
|
||||
scripts.cpp
|
||||
)
|
||||
set(frontend-tools_UI
|
||||
${frontend-tools_UI}
|
||||
forms/scripts.ui
|
||||
)
|
||||
set(EXTRA_LIBS
|
||||
${EXTRA_LIBS}
|
||||
obs-scripting
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(frontend-tools_PLATFORM_SOURCES
|
||||
auto-scene-switcher-win.cpp)
|
||||
|
|
@ -79,6 +107,7 @@ add_library(frontend-tools MODULE
|
|||
)
|
||||
target_link_libraries(frontend-tools
|
||||
${frontend-tools_PLATFORM_LIBS}
|
||||
${EXTRA_LIBS}
|
||||
obs-frontend-api
|
||||
Qt5::Widgets
|
||||
libobs)
|
||||
|
|
|
|||
|
|
@ -8,8 +8,18 @@
|
|||
#include <util/windows/CoTaskMemPtr.hpp>
|
||||
#include <util/threading.h>
|
||||
#include <util/platform.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
#include <sphelper.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <obs.hpp>
|
||||
|
||||
#include <thread>
|
||||
|
|
|
|||
|
|
@ -10,8 +10,18 @@
|
|||
#include <util/windows/WinHandle.hpp>
|
||||
#include <util/windows/ComPtr.hpp>
|
||||
#include <obs-module.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
#include <sphelper.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
|
|
|||
|
|
@ -11,3 +11,5 @@ Captions.CurrentSystemLanguage="বর্তমান সিস্টেমে
|
|||
OutputTimer="আউটপুট টাইমার"
|
||||
OutputTimer.Stream="এর পরে বন্ধ।:"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="La gravació s'aturarà en:"
|
|||
OutputTimer.Stream.EnableEverytime="Activa el temporitzador en cada transmissió"
|
||||
OutputTimer.Record.EnableEverytime="Activa el temporitzador en cada enregistrament"
|
||||
|
||||
Scripts="Scripts"
|
||||
LoadedScripts="Scripts carregats"
|
||||
AddScripts="Afegeix scripts"
|
||||
RemoveScripts="Suprimeix scripts"
|
||||
ReloadScripts="Torna a carregar els scripts"
|
||||
PythonSettings="Configuració del Python"
|
||||
PythonSettings.PythonInstallPath32bit="Camí d'instal·lació del Python (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Camí d'instal·lació del Python (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Camí del Python"
|
||||
ScriptLogWindow="Informe script"
|
||||
Description="Descripció"
|
||||
|
||||
FileFilter.ScriptFiles="Fitxers script"
|
||||
FileFilter.AllFiles="Tots els fitxers"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Nahrávání se zastaví za:"
|
|||
OutputTimer.Stream.EnableEverytime="Pokaždé povolit časovač vysílání"
|
||||
OutputTimer.Record.EnableEverytime="Pokaždé povolit časovač nahrávání"
|
||||
|
||||
Scripts="Skripty"
|
||||
LoadedScripts="Načtené skripty"
|
||||
AddScripts="Přidat skripty"
|
||||
RemoveScripts="Odebrat skripty"
|
||||
ReloadScripts="Restartovat skripty"
|
||||
PythonSettings="Python nastavení"
|
||||
PythonSettings.PythonInstallPath32bit="Cesta k instalaci Pythonu (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Cesta k instalaci Pythonu (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Najít cestu k Pythonu"
|
||||
ScriptLogWindow="Log skriptu"
|
||||
Description="Popis"
|
||||
|
||||
FileFilter.ScriptFiles="Soubory skriptů"
|
||||
FileFilter.AllFiles="Všechny soubory"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Streaming standser om:"
|
|||
OutputTimer.Stream.EnableEverytime="Aktivér streaming-timer hver gang"
|
||||
OutputTimer.Record.EnableEverytime="Aktivér optage-timer hver gang"
|
||||
|
||||
Scripts="Scripts"
|
||||
LoadedScripts="Indlæste scripts"
|
||||
AddScripts="Tilføj scripts"
|
||||
RemoveScripts="Fjern scripts"
|
||||
ReloadScripts="Genindlæs scripts"
|
||||
PythonSettings="Python-indstillinger"
|
||||
PythonSettings.PythonInstallPath32bit="Python-installationssti (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Python-installationssti (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Gennemse Python-sti"
|
||||
ScriptLogWindow="Scriptlog"
|
||||
Description="Beskrivelse"
|
||||
|
||||
FileFilter.ScriptFiles="Scriptfiler"
|
||||
FileFilter.AllFiles="Alle filer"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Aufnahme stoppt in:"
|
|||
OutputTimer.Stream.EnableEverytime="Streaming-Timer jedes Mal aktivieren"
|
||||
OutputTimer.Record.EnableEverytime="Aufnahme-Timer jedes Mal aktivieren"
|
||||
|
||||
Scripts="Skripte"
|
||||
LoadedScripts="Geladene Skripte"
|
||||
AddScripts="Skripte hinzufügen"
|
||||
RemoveScripts="Skripte entfernen"
|
||||
ReloadScripts="Skripte neu laden"
|
||||
PythonSettings="Python-Einstellungen"
|
||||
PythonSettings.PythonInstallPath32bit="Python Installationspfad (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Python Installationspfad (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Python-Pfad öffnen"
|
||||
ScriptLogWindow="Skriptprotokoll"
|
||||
Description="Beschreibung"
|
||||
|
||||
FileFilter.ScriptFiles="Skriptdateien"
|
||||
FileFilter.AllFiles="Alle Dateien"
|
||||
|
||||
|
|
|
|||
29
UI/frontend-plugins/frontend-tools/data/locale/el-GR.ini
Normal file
29
UI/frontend-plugins/frontend-tools/data/locale/el-GR.ini
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
SceneSwitcher="Αυτόματος Εναλλαγέας Σκηνών"
|
||||
SceneSwitcher.OnNoMatch="Όταν δεν ταιριάζει με κανένα παράθυρο:"
|
||||
SceneSwitcher.OnNoMatch.DontSwitch="Καμία Μετάβαση"
|
||||
SceneSwitcher.OnNoMatch.SwitchTo="Μετάβαση σε:"
|
||||
SceneSwitcher.CheckInterval="Έλεγχος τίτλου ενεργού παραθύρου κάθε:"
|
||||
SceneSwitcher.ActiveOrNotActive="Ο Εναλλαγέας Σκηνών είναι:"
|
||||
InvalidRegex.Title="Μη έγκυρη τυπική έκφραση"
|
||||
InvalidRegex.Text="Η τυπική έκφραση που εισαγάγατε δεν είναι έγκυρη."
|
||||
Active="Ενεργός"
|
||||
Inactive="Ανενεργός"
|
||||
Start="Eκκίνηση"
|
||||
Stop="Διακοπή"
|
||||
|
||||
Captions="Υπότιτλοι (Πειραματικό)"
|
||||
Captions.AudioSource="Πηγή ήχου"
|
||||
Captions.CurrentSystemLanguage="Τρέχουσα γλώσσα του συστήματος (%1)"
|
||||
Captions.Provider="Πάροχος"
|
||||
Captions.Error.GenericFail="Αποτυχία εκκίνησης των υποτίτλων"
|
||||
|
||||
OutputTimer="Χρονόμετρο εξόδου"
|
||||
OutputTimer.Stream="Διακοπή streaming μετά από:"
|
||||
OutputTimer.Record="Διακοπή εγγραφής βίντεο μετά από:"
|
||||
OutputTimer.Stream.StoppingIn="Διακοπή streaming σε:"
|
||||
OutputTimer.Record.StoppingIn="Διακοπή εγγραφής σε:"
|
||||
OutputTimer.Stream.EnableEverytime="Ενεργοποίηση χρονόμετρου streaming κάθε φορά"
|
||||
OutputTimer.Record.EnableEverytime="Ενεργοποίηση χρονόμετρου εγγραφής κάθε φορά"
|
||||
|
||||
|
||||
|
||||
|
|
@ -24,3 +24,19 @@ OutputTimer.Stream.StoppingIn="Streaming stopping in:"
|
|||
OutputTimer.Record.StoppingIn="Recording stopping in:"
|
||||
OutputTimer.Stream.EnableEverytime="Enable streaming timer every time"
|
||||
OutputTimer.Record.EnableEverytime="Enable recording timer every time"
|
||||
|
||||
Scripts="Scripts"
|
||||
LoadedScripts="Loaded Scripts"
|
||||
AddScripts="Add Scripts"
|
||||
RemoveScripts="Remove Scripts"
|
||||
ReloadScripts="Reload Scripts"
|
||||
LoadedScripts="Loaded Scripts"
|
||||
PythonSettings="Python Settings"
|
||||
PythonSettings.PythonInstallPath32bit="Python Install Path (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Python Install Path (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Browse Python Path"
|
||||
ScriptLogWindow="Script Log"
|
||||
Description="Description"
|
||||
|
||||
FileFilter.ScriptFiles="Script Files"
|
||||
FileFilter.AllFiles="All Files"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
SceneSwitcher="Cambiador de escena automática"
|
||||
SceneSwitcher="Selector de escena automático"
|
||||
SceneSwitcher.OnNoMatch="Cuando no coincida con ninguna ventana:"
|
||||
SceneSwitcher.OnNoMatch.DontSwitch="No cambiar"
|
||||
SceneSwitcher.OnNoMatch.SwitchTo="Cambiar a:"
|
||||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Finalizando grabación en:"
|
|||
OutputTimer.Stream.EnableEverytime="Activar temporizador en cada transmisión"
|
||||
OutputTimer.Record.EnableEverytime="Activar temporizador en cada grabación"
|
||||
|
||||
Scripts="Guion"
|
||||
LoadedScripts="Guiones cargados"
|
||||
AddScripts="Agregar Guiones"
|
||||
RemoveScripts="Quitar Guiones"
|
||||
ReloadScripts="Recargar Guiones"
|
||||
PythonSettings="Configuración de Python"
|
||||
PythonSettings.PythonInstallPath32bit="Dirección de la instalación de Python (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Dirección de la instalación de Python (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Buscar Ruta de Phyton"
|
||||
ScriptLogWindow="Registro de secuencia de comandos"
|
||||
Description="Descripción"
|
||||
|
||||
FileFilter.ScriptFiles="Archivos de Guiones"
|
||||
FileFilter.AllFiles="Todos los archivos"
|
||||
|
||||
|
|
|
|||
|
|
@ -23,3 +23,5 @@ OutputTimer.Record.StoppingIn="Salvestamine lõppeb:"
|
|||
OutputTimer.Stream.EnableEverytime="Lülita voogedastuse taimer alati sisse"
|
||||
OutputTimer.Record.EnableEverytime="Lülita salvestus taimer alati sisse"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Grabazioa geldituko da hau barru:"
|
|||
OutputTimer.Stream.EnableEverytime="Gaitu transmisio tenporizadorea aldiro"
|
||||
OutputTimer.Record.EnableEverytime="Gaitu grabazio tenporizadorea aldiro"
|
||||
|
||||
Scripts="Script-ak"
|
||||
LoadedScripts="Kargatutako script-ak"
|
||||
AddScripts="Gehitu script-ak"
|
||||
RemoveScripts="Kendu script-ak"
|
||||
ReloadScripts="Birkargatu script-ak"
|
||||
PythonSettings="Python ezarpenak"
|
||||
PythonSettings.PythonInstallPath32bit="Python instalazioaren bide-izena (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Python instalazioaren bide-izena (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Arakatu Python-en bide-izena"
|
||||
ScriptLogWindow="Script-aren erregistroa"
|
||||
Description="Deskribapena"
|
||||
|
||||
FileFilter.ScriptFiles="Script-aren fitxategiak"
|
||||
FileFilter.AllFiles="Fitxategi guztiak"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Tallennus pysäytetään:"
|
|||
OutputTimer.Stream.EnableEverytime="Ota lähetysajastin käyttöön aina"
|
||||
OutputTimer.Record.EnableEverytime="Ota tallennusajastin käyttöön aina"
|
||||
|
||||
Scripts="Skriptit"
|
||||
LoadedScripts="Ladatut skriptit"
|
||||
AddScripts="Lisää skriptejä"
|
||||
RemoveScripts="Poista skriptejä"
|
||||
ReloadScripts="Lataa skriptit uudelleen"
|
||||
PythonSettings="Python-asetukset"
|
||||
PythonSettings.PythonInstallPath32bit="Python-asennuspolku (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Python-asennuspolku (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Selaa Python-polku"
|
||||
ScriptLogWindow="Skripti-lokit"
|
||||
Description="Kuvaus"
|
||||
|
||||
FileFilter.ScriptFiles="Skripti-tiedostot"
|
||||
FileFilter.AllFiles="Kaikki tiedostot"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Arrêt de l'enregistrement dans :"
|
|||
OutputTimer.Stream.EnableEverytime="Activer le minuteur automatiquement à chaque stream"
|
||||
OutputTimer.Record.EnableEverytime="Activer le minuteur automatiquement à chaque enregistrement"
|
||||
|
||||
Scripts="Scripts"
|
||||
LoadedScripts="Scripts chargés"
|
||||
AddScripts="Ajouter des Scripts"
|
||||
RemoveScripts="Retirer des Scripts"
|
||||
ReloadScripts="Recharger les Scripts"
|
||||
PythonSettings="Paramètres Python"
|
||||
PythonSettings.PythonInstallPath32bit="Chemin d’installation Python (32 bits)"
|
||||
PythonSettings.PythonInstallPath64bit="Chemin d’installation Python (64 bits)"
|
||||
PythonSettings.BrowsePythonPath="Parcourir le chemin de Python"
|
||||
ScriptLogWindow="Journal de script"
|
||||
Description="Description"
|
||||
|
||||
FileFilter.ScriptFiles="Fichiers de script"
|
||||
FileFilter.AllFiles="Tous les fichiers"
|
||||
|
||||
|
|
|
|||
|
|
@ -23,3 +23,9 @@ OutputTimer.Record.StoppingIn="הקלטה עוצרת ב:"
|
|||
OutputTimer.Stream.EnableEverytime="הפעל טיימר הזרמה כל פעם"
|
||||
OutputTimer.Record.EnableEverytime="הפעל טיימר הקלטה כל פעם"
|
||||
|
||||
ScriptLogWindow="סקריפט לוג"
|
||||
Description="תיאור"
|
||||
|
||||
FileFilter.ScriptFiles="קובץ סקריפט"
|
||||
FileFilter.AllFiles="כל הקבצים"
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ Inactive="Neaktivan"
|
|||
Start="Pokreni"
|
||||
Stop="Zaustavi"
|
||||
|
||||
Captions="Opisi (experimentalno)"
|
||||
|
||||
OutputTimer="Tempomat snimanja i emitovanja"
|
||||
OutputTimer.Stream="Zaustavi emitovanje nakon:"
|
||||
|
|
@ -20,3 +21,5 @@ OutputTimer.Record.StoppingIn="Prekidanje snimanja za:"
|
|||
OutputTimer.Stream.EnableEverytime="Omogući štopovanje emitovanja svaki put"
|
||||
OutputTimer.Record.EnableEverytime="Omogući štopovanje snimanja svaki put"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Felvétel leáll:"
|
|||
OutputTimer.Stream.EnableEverytime="Stream időzítő indítása minden alkalommal"
|
||||
OutputTimer.Record.EnableEverytime="Felvétel időzítő indítása minden alkalommal"
|
||||
|
||||
Scripts="Szkriptek"
|
||||
LoadedScripts="Betöltött szkriptek"
|
||||
AddScripts="Szkriptek hozzáadása"
|
||||
RemoveScripts="Szkriptek eltávolítása"
|
||||
ReloadScripts="Szkriptek újraindítása"
|
||||
PythonSettings="Python beállítások"
|
||||
PythonSettings.PythonInstallPath32bit="Python telepítési útvonal (32 bites)"
|
||||
PythonSettings.PythonInstallPath64bit="Python telepítési útvonal (64 bites)"
|
||||
PythonSettings.BrowsePythonPath="Python elérési útjának tallózása"
|
||||
ScriptLogWindow="Szkript napló"
|
||||
Description="Leírás"
|
||||
|
||||
FileFilter.ScriptFiles="Szkriptfájl"
|
||||
FileFilter.AllFiles="Minden fájl"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
SceneSwitcher="Cambia scena automatico"
|
||||
SceneSwitcher.OnNoMatch="Quando nessuna scena coincide a:"
|
||||
SceneSwitcher.OnNoMatch="Quando nessuna finestra coincide:"
|
||||
SceneSwitcher.OnNoMatch.DontSwitch="Non passare"
|
||||
SceneSwitcher.OnNoMatch.SwitchTo="Passa a:"
|
||||
SceneSwitcher.CheckInterval="Controlla il titolo della finestra attiva ogni:"
|
||||
SceneSwitcher.ActiveOrNotActive="Lo scene switcher è:"
|
||||
SceneSwitcher.ActiveOrNotActive="Il cambio scena è:"
|
||||
InvalidRegex.Title="Espressione regolare non valida"
|
||||
InvalidRegex.Text="L'espressione regolare che hai inserito non è valido."
|
||||
InvalidRegex.Text="L'espressione regolare che hai inserito non è valida."
|
||||
Active="Attivo"
|
||||
Inactive="Inattivo"
|
||||
Start="Inizio"
|
||||
Stop="Stop"
|
||||
Start="Avvia"
|
||||
Stop="Ferma"
|
||||
|
||||
Captions="Sottotitoli (Sperimentale)"
|
||||
Captions="Sottotitoli (sperimentale)"
|
||||
Captions.AudioSource="Fonte audio"
|
||||
Captions.CurrentSystemLanguage="Lingua del sistema in uso (%1)"
|
||||
Captions.CurrentSystemLanguage="Lingua del sistema (%1)"
|
||||
Captions.Provider="Sintetizzatore"
|
||||
Captions.Error.GenericFail="Impossibile avviare i sottititoli"
|
||||
|
||||
OutputTimer="Timer Output"
|
||||
OutputTimer="Timer di uscita"
|
||||
OutputTimer.Stream="Termina diretta dopo:"
|
||||
OutputTimer.Record="Termina registrazione dopo:"
|
||||
OutputTimer.Stream.StoppingIn="La diretta terminerà in:"
|
||||
|
|
@ -23,3 +25,18 @@ OutputTimer.Record.StoppingIn="La registrazione terminerà in:"
|
|||
OutputTimer.Stream.EnableEverytime="Abilita il timer per lo streaming ogni volta"
|
||||
OutputTimer.Record.EnableEverytime="Abilita il timer per la registrazione ogni volta"
|
||||
|
||||
Scripts="Script"
|
||||
LoadedScripts="Script caricati"
|
||||
AddScripts="Aggiungi script"
|
||||
RemoveScripts="Rimuovi script"
|
||||
ReloadScripts="Ricarica script"
|
||||
PythonSettings="Impostazioni di Python"
|
||||
PythonSettings.PythonInstallPath32bit="Percorso d'installazione di Python (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Percorso d'installazione di Python (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Sfoglia Percorso Python"
|
||||
ScriptLogWindow="Log degli script"
|
||||
Description="Descrizione"
|
||||
|
||||
FileFilter.ScriptFiles="Lista degli script"
|
||||
FileFilter.AllFiles="Tutti i file"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="録画停止まで:"
|
|||
OutputTimer.Stream.EnableEverytime="毎回配信タイマーを有効にする"
|
||||
OutputTimer.Record.EnableEverytime="毎回録画タイマーを有効にする"
|
||||
|
||||
Scripts="スクリプト"
|
||||
LoadedScripts="ロードしたスクリプト"
|
||||
AddScripts="スクリプトを追加"
|
||||
RemoveScripts="スクリプトを削除"
|
||||
ReloadScripts="スクリプトの再読み込み"
|
||||
PythonSettings="Python の設定"
|
||||
PythonSettings.PythonInstallPath32bit="Python インストールパス (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Python インストールパス (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Python パスを参照"
|
||||
ScriptLogWindow="スクリプトログ"
|
||||
Description="説明"
|
||||
|
||||
FileFilter.ScriptFiles="スクリプトファイル"
|
||||
FileFilter.AllFiles="すべてのファイル"
|
||||
|
||||
|
|
|
|||
11
UI/frontend-plugins/frontend-tools/data/locale/ka-GE.ini
Normal file
11
UI/frontend-plugins/frontend-tools/data/locale/ka-GE.ini
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
Active="ჩართული"
|
||||
Inactive="გამორთული"
|
||||
Start="დაწყება"
|
||||
Stop="შეწყვეტა"
|
||||
|
||||
Captions.AudioSource="აუდიოს წყარო"
|
||||
|
||||
OutputTimer.Record.StoppingIn="ჩაწერის შეწყვეტის დრო:"
|
||||
|
||||
|
||||
|
||||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="녹화 중지까지 남은 시간:"
|
|||
OutputTimer.Stream.EnableEverytime="매번 방송 시간 기록기 활성화"
|
||||
OutputTimer.Record.EnableEverytime="매번 녹화 시간 기록기 활성화"
|
||||
|
||||
Scripts="스크립트"
|
||||
LoadedScripts="입력한 스크립트"
|
||||
AddScripts="스크립트 추가"
|
||||
RemoveScripts="스크립트 제거"
|
||||
ReloadScripts="스크립트 다시 읽기"
|
||||
PythonSettings="Python 설정"
|
||||
PythonSettings.PythonInstallPath32bit="Python 설치 경로 (32비트)"
|
||||
PythonSettings.PythonInstallPath64bit="Python 설치 경로 (64비트)"
|
||||
PythonSettings.BrowsePythonPath="Python 경로 찾기"
|
||||
ScriptLogWindow="스크립트 기록"
|
||||
Description="설명"
|
||||
|
||||
FileFilter.ScriptFiles="스크립트 파일"
|
||||
FileFilter.AllFiles="모든 파일"
|
||||
|
||||
|
|
|
|||
29
UI/frontend-plugins/frontend-tools/data/locale/lt-LT.ini
Normal file
29
UI/frontend-plugins/frontend-tools/data/locale/lt-LT.ini
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
SceneSwitcher="Automatinis scenų keitiklis"
|
||||
SceneSwitcher.OnNoMatch="Kai langai nesutampa:"
|
||||
SceneSwitcher.OnNoMatch.DontSwitch="Neperjungti"
|
||||
SceneSwitcher.OnNoMatch.SwitchTo="Perjungti į:"
|
||||
SceneSwitcher.CheckInterval="Tikrinti aktyvaus lango antraštę kas:"
|
||||
SceneSwitcher.ActiveOrNotActive="Scenų keitimas yra:"
|
||||
InvalidRegex.Title="Neteisinga Reguliarioji Išraiška"
|
||||
InvalidRegex.Text="Reguliarioji išraiška, kurią įvedėte - neteisinga."
|
||||
Active="Aktyvus"
|
||||
Inactive="Neaktyvus"
|
||||
Start="Įjungti"
|
||||
Stop="Išjungti"
|
||||
|
||||
Captions="Titrai (Eksperimentinis)"
|
||||
Captions.AudioSource="Garso šaltinis"
|
||||
Captions.CurrentSystemLanguage="Dabartinė sistemos kalba (%1)"
|
||||
Captions.Provider="Iš"
|
||||
Captions.Error.GenericFail="Nepavyko įjungti titrų"
|
||||
|
||||
OutputTimer="Išvesties automatinis laikmatis"
|
||||
OutputTimer.Stream="Sustabdyti transliaciją po:"
|
||||
OutputTimer.Record="Stabdyti įrašymą po:"
|
||||
OutputTimer.Stream.StoppingIn="Transliacija sustos po:"
|
||||
OutputTimer.Record.StoppingIn="Įrašymas sustos po:"
|
||||
OutputTimer.Stream.EnableEverytime="Įgalinti transliacijos laikmatį kiekvieną kartą"
|
||||
OutputTimer.Record.EnableEverytime="Įgalinti įrašymo laikmatį kiekvieną kartą"
|
||||
|
||||
|
||||
|
||||
|
|
@ -9,3 +9,5 @@ OutputTimer.Record="Berhenti merakam selepas:"
|
|||
OutputTimer.Stream.StoppingIn="'Streaming' dihentikan dalam:"
|
||||
OutputTimer.Record.StoppingIn="Rakaman dihentikan dalam:"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ Stop="Stopp"
|
|||
Captions="Bildetekster (eksperimentell)"
|
||||
Captions.AudioSource="Lyd kilde"
|
||||
Captions.CurrentSystemLanguage="Någjeldende System Språk"
|
||||
Captions.Provider="Leverandør"
|
||||
Captions.Error.GenericFail="Feilet å starte undertekst"
|
||||
|
||||
OutputTimer="Stoppeklokke"
|
||||
OutputTimer.Stream="Stopp streaming etter:"
|
||||
|
|
@ -23,3 +25,18 @@ OutputTimer.Record.StoppingIn="Opptak stopper om:"
|
|||
OutputTimer.Stream.EnableEverytime="Aktiver streaming timer hver gang"
|
||||
OutputTimer.Record.EnableEverytime="Aktiver opptaks timer hver gang"
|
||||
|
||||
Scripts="Skripter"
|
||||
LoadedScripts="Innlastede skripter"
|
||||
AddScripts="Legg til skripter"
|
||||
RemoveScripts="Fjern skripter"
|
||||
ReloadScripts="Last inn skripter på nytt"
|
||||
PythonSettings="Python-innstillinger"
|
||||
PythonSettings.PythonInstallPath32bit="Python-installasjonsfilbane (32-bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Python-installasjonsfilbane (64-bit)"
|
||||
PythonSettings.BrowsePythonPath="Finn Python-filbanen"
|
||||
ScriptLogWindow="Skripthistorikk"
|
||||
Description="Beskrivelse"
|
||||
|
||||
FileFilter.ScriptFiles="Skriptfiler"
|
||||
FileFilter.AllFiles="Alle filer"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Opname stopt over:"
|
|||
OutputTimer.Stream.EnableEverytime="Schakel streaming timer elke keer in"
|
||||
OutputTimer.Record.EnableEverytime="Schakel opnametimer elke keer in"
|
||||
|
||||
Scripts="Scripts"
|
||||
LoadedScripts="Geladen Scripts"
|
||||
AddScripts="Voeg Scripts Toe"
|
||||
RemoveScripts="Verwijder Scripts"
|
||||
ReloadScripts="Herlaad Scripts"
|
||||
PythonSettings="Python-instellingen"
|
||||
PythonSettings.PythonInstallPath32bit="Python Installatiepad (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Python Installatiepad (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Blader Naar Python Pad"
|
||||
ScriptLogWindow="Script Log"
|
||||
Description="Beschrijving"
|
||||
|
||||
FileFilter.ScriptFiles="Scriptbestanden"
|
||||
FileFilter.AllFiles="Alle Bestanden"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Zatrzymanie nagrywania za:"
|
|||
OutputTimer.Stream.EnableEverytime="Włącz timer streamu za każdym razem"
|
||||
OutputTimer.Record.EnableEverytime="Włącz timer nagrywania za każdym razem"
|
||||
|
||||
Scripts="Skrypty"
|
||||
LoadedScripts="Wczytane skrypty"
|
||||
AddScripts="Dodaj skrypty"
|
||||
RemoveScripts="Usuń skrypty"
|
||||
ReloadScripts="Przeładuj skrypty"
|
||||
PythonSettings="Ustawienia Pythona"
|
||||
PythonSettings.PythonInstallPath32bit="Ścieżka instalacji Pythona (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Ścieżka instalacji Pythona (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Wybierz ścieżkę instalacji Pythona"
|
||||
ScriptLogWindow="Dziennik skryptów"
|
||||
Description="Opis"
|
||||
|
||||
FileFilter.ScriptFiles="Pliki skryptów"
|
||||
FileFilter.AllFiles="Wszystkie Pliki"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
SceneSwitcher="Alternador automático de cena"
|
||||
SceneSwitcher.OnNoMatch="Quando nenhuma janela corresponde:"
|
||||
SceneSwitcher.OnNoMatch="Quando nenhuma janela corresponder:"
|
||||
SceneSwitcher.OnNoMatch.DontSwitch="Não alternar"
|
||||
SceneSwitcher.OnNoMatch.SwitchTo="Alternar para:"
|
||||
SceneSwitcher.CheckInterval="Checar o título da janela ativa a cada:"
|
||||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="A gravação irá parar em:"
|
|||
OutputTimer.Stream.EnableEverytime="Ativar o timer streaming o tempo todo"
|
||||
OutputTimer.Record.EnableEverytime="Ativar o timer de gravação o tempo todo"
|
||||
|
||||
Scripts="Scripts"
|
||||
LoadedScripts="Scripts Carregados"
|
||||
AddScripts="Adicionar Scripts"
|
||||
RemoveScripts="Remover Scripts"
|
||||
ReloadScripts="Recarregar Scripts"
|
||||
PythonSettings="Configurações Python"
|
||||
PythonSettings.PythonInstallPath32bit="Caminho de Instalação Python (32 bits)"
|
||||
PythonSettings.PythonInstallPath64bit="Caminho de Instalação Python (64 bits)"
|
||||
PythonSettings.BrowsePythonPath="Procurar Caminho do Python"
|
||||
ScriptLogWindow="Log dos Scripts"
|
||||
Description="Descrição"
|
||||
|
||||
FileFilter.ScriptFiles="Arquivos de Scripts"
|
||||
FileFilter.AllFiles="Todos os Arquivos"
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,18 @@ Inactive="Inativa"
|
|||
Start="Iniciar"
|
||||
Stop="Parar"
|
||||
|
||||
Captions="Legendas (Experimental)"
|
||||
Captions.AudioSource="Fonte de audio"
|
||||
Captions.CurrentSystemLanguage="Linguagem de Sistema Atual (%1)"
|
||||
Captions.Error.GenericFail="Ocorreu um erro a iniciar legendas"
|
||||
|
||||
OutputTimer="Temporizador de saída"
|
||||
OutputTimer.Stream="Para a transmissão após:"
|
||||
OutputTimer.Record="Parar a gravação após:"
|
||||
OutputTimer.Stream.StoppingIn="A transmissão irá parar em:"
|
||||
OutputTimer.Record.StoppingIn="A gravação irá parar em:"
|
||||
OutputTimer.Stream.EnableEverytime="Ativar temporizador de transmissão sempre"
|
||||
OutputTimer.Record.EnableEverytime="Ativar temporizador de gravação sempre"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
SceneSwitcher="Schimbator automat de scenă"
|
||||
SceneSwitcher.OnNoMatch="Cand nici o fereastra nu se potriveste:"
|
||||
SceneSwitcher.OnNoMatch="Când nicio fereastră nu se potrivește:"
|
||||
SceneSwitcher.OnNoMatch.SwitchTo="Schimbă la:"
|
||||
Active="Activ"
|
||||
Inactive="Inactiv"
|
||||
Start="Pornire"
|
||||
Stop="Oprire"
|
||||
|
||||
Captions="Subtitrări (experimentale)"
|
||||
Captions.AudioSource="Sursa audio"
|
||||
Captions.CurrentSystemLanguage="Limba curentă a sistemului (%1)"
|
||||
Captions.Provider="Furnizor"
|
||||
|
||||
OutputTimer.Record="Opriți inregistrarea dupa:"
|
||||
OutputTimer.Record.StoppingIn="Oprire înregistrare în:"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Запись будет завершена чер
|
|||
OutputTimer.Stream.EnableEverytime="Включать таймер стрима каждый раз"
|
||||
OutputTimer.Record.EnableEverytime="Включать таймер записи каждый раз"
|
||||
|
||||
Scripts="Скрипты"
|
||||
LoadedScripts="Загруженные скрипты"
|
||||
AddScripts="Добавить скрипты"
|
||||
RemoveScripts="Удалить скрипты"
|
||||
ReloadScripts="Перезагрузить скрипты"
|
||||
PythonSettings="Параметры Python"
|
||||
PythonSettings.PythonInstallPath32bit="Путь установки Python (32 бита)"
|
||||
PythonSettings.PythonInstallPath64bit="Путь установки Python (64 бита)"
|
||||
PythonSettings.BrowsePythonPath="Обзор пути Python"
|
||||
ScriptLogWindow="Лог скрипта"
|
||||
Description="Описание"
|
||||
|
||||
FileFilter.ScriptFiles="Файлы скриптов"
|
||||
FileFilter.AllFiles="Все файлы"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,29 @@
|
|||
SceneSwitcher="Automatický prepínač scén"
|
||||
SceneSwitcher.OnNoMatch="Ak sa žiadne okno nezhoduje:"
|
||||
SceneSwitcher.OnNoMatch.DontSwitch="Neprepínať"
|
||||
SceneSwitcher.OnNoMatch.SwitchTo="Prepnúť na:"
|
||||
SceneSwitcher.CheckInterval="Kontrolovať aktívne okno každých:"
|
||||
SceneSwitcher.ActiveOrNotActive="Prepínač scén je:"
|
||||
InvalidRegex.Title="Neplatný regulárny výraz"
|
||||
InvalidRegex.Text="Zadaný regulárny výraz je chybný."
|
||||
Active="Aktívny"
|
||||
Inactive="Neaktivní"
|
||||
Start="Spustiť"
|
||||
Stop="Zastaviť"
|
||||
|
||||
Captions="Titulky (experiment.)"
|
||||
Captions.AudioSource="Zdroj zvuku"
|
||||
Captions.CurrentSystemLanguage="Aktuálny systémový jazyk (%1)"
|
||||
Captions.Provider="Poskytovateľ"
|
||||
Captions.Error.GenericFail="Nepodarilo sa spustiť titulky"
|
||||
|
||||
OutputTimer="Časovač"
|
||||
OutputTimer.Stream="Zastaviť stream po:"
|
||||
OutputTimer.Record="Zastaviť nahrávanie po:"
|
||||
OutputTimer.Stream.StoppingIn="Streamovanie za zastaví za:"
|
||||
OutputTimer.Record.StoppingIn="Nahrávanie za zastaví za:"
|
||||
OutputTimer.Stream.EnableEverytime="Povoliť časovač streamovania zakaždým"
|
||||
OutputTimer.Record.EnableEverytime="Zapnúť časovač nahrávania zakaždým"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,3 +20,5 @@ OutputTimer.Record.StoppingIn="Prekidanje snimanja za:"
|
|||
OutputTimer.Stream.EnableEverytime="Omogući štopovanje emitovanja svaki put"
|
||||
OutputTimer.Record.EnableEverytime="Omogući štopovanje snimanja svaki put"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,3 +20,5 @@ OutputTimer.Record.StoppingIn="Прекидање снимања за:"
|
|||
OutputTimer.Stream.EnableEverytime="Омогући штоповање емитовање сваки пут"
|
||||
OutputTimer.Record.EnableEverytime="Омогући штоповање снимања сваки пут"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Inspelningen stoppas om:"
|
|||
OutputTimer.Stream.EnableEverytime="Aktivera strömtimer varje gång"
|
||||
OutputTimer.Record.EnableEverytime="Aktivera inspelningstimer varje gång"
|
||||
|
||||
Scripts="Skript"
|
||||
LoadedScripts="Inlästa skript"
|
||||
AddScripts="Lägg till skript"
|
||||
RemoveScripts="Ta bort skript"
|
||||
ReloadScripts="Ladda om skript"
|
||||
PythonSettings="Python-inställningar"
|
||||
PythonSettings.PythonInstallPath32bit="Installationssökväg för Python (32 bitar)"
|
||||
PythonSettings.PythonInstallPath64bit="Installationssökväg för Python (64 bitar)"
|
||||
PythonSettings.BrowsePythonPath="Bläddra Python-sökväg"
|
||||
ScriptLogWindow="Skriptlogg"
|
||||
Description="Beskrivning"
|
||||
|
||||
FileFilter.ScriptFiles="Skriptfiler"
|
||||
FileFilter.AllFiles="Alla filer"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Kayıt durduruluyor:"
|
|||
OutputTimer.Stream.EnableEverytime="Her zaman yayın zamanlayıcıyı etkinleştir"
|
||||
OutputTimer.Record.EnableEverytime="Her zaman kayıt zamanlayıcıyı etkinleştir"
|
||||
|
||||
Scripts="Betikler"
|
||||
LoadedScripts="Yüklü Betikler"
|
||||
AddScripts="Betik Ekle"
|
||||
RemoveScripts="Betikleri Sil"
|
||||
ReloadScripts="Betikleri Yeniden Yükle"
|
||||
PythonSettings="Python Ayarları"
|
||||
PythonSettings.PythonInstallPath32bit="Python Kurulum Yolu (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Python Kurulum Yolu (64bit)"
|
||||
PythonSettings.BrowsePythonPath="Python Yoluna Göz At"
|
||||
ScriptLogWindow="Betik Kütüğü"
|
||||
Description="Açıklama"
|
||||
|
||||
FileFilter.ScriptFiles="Betik Dosyaları"
|
||||
FileFilter.AllFiles="Tüm Dosyalar"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="Запис зупиниться за:"
|
|||
OutputTimer.Stream.EnableEverytime="Щоразу запускається трансляція - вмикати Таймер для Виводу"
|
||||
OutputTimer.Record.EnableEverytime="Щоразу починається запис - вмикати Таймер для Виводу"
|
||||
|
||||
Scripts="Скрипти"
|
||||
LoadedScripts="Завантажені скрипти"
|
||||
AddScripts="Додати скрипти"
|
||||
RemoveScripts="Видалити скрипти"
|
||||
ReloadScripts="Перезавантажити скрипти"
|
||||
PythonSettings="Python налаштування"
|
||||
PythonSettings.PythonInstallPath32bit="Шлях до програми Python (32 біти)"
|
||||
PythonSettings.PythonInstallPath64bit="Шлях до програми Python (64 біти)"
|
||||
PythonSettings.BrowsePythonPath="Огляд шляху до програми Python"
|
||||
ScriptLogWindow="Журнал роботи скрипта"
|
||||
Description="Опис"
|
||||
|
||||
FileFilter.ScriptFiles="Файли скриптів"
|
||||
FileFilter.AllFiles="Всі файли"
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,20 @@ Inactive="Không hoạt động"
|
|||
Start="Bắt đầu"
|
||||
Stop="Dừng"
|
||||
|
||||
Captions="Phụ đề (Thử nghiệm)"
|
||||
Captions.AudioSource="Nguồn âm thanh"
|
||||
Captions.CurrentSystemLanguage="Ngôn ngữ hiện tại của máy tính (%1)"
|
||||
Captions.Provider="Nhà cung cấp"
|
||||
Captions.Error.GenericFail="Thất bại trong việc bắt đầu phụ đề"
|
||||
|
||||
OutputTimer.Stream="Dừng stream sau:"
|
||||
OutputTimer.Record="Dừng ghi video sau:"
|
||||
OutputTimer.Stream.StoppingIn="Stream sẽ dừng trong:"
|
||||
OutputTimer.Record.StoppingIn="Quay video sẽ dừng trong:"
|
||||
|
||||
AddScripts="Thêm script"
|
||||
Description="Mô tả"
|
||||
|
||||
FileFilter.ScriptFiles="Tập tin script"
|
||||
FileFilter.AllFiles="Tất cả tập tin"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="录制停止在:"
|
|||
OutputTimer.Stream.EnableEverytime="每次启用流计时器"
|
||||
OutputTimer.Record.EnableEverytime="每次启用录制计时器"
|
||||
|
||||
Scripts="脚本"
|
||||
LoadedScripts="已载入脚本"
|
||||
AddScripts="添加脚本"
|
||||
RemoveScripts="移除脚本"
|
||||
ReloadScripts="重新载入脚本"
|
||||
PythonSettings="Python 设置"
|
||||
PythonSettings.PythonInstallPath32bit="Python 安装路径 (32位)"
|
||||
PythonSettings.PythonInstallPath64bit="Python 安装路径 (64位)"
|
||||
PythonSettings.BrowsePythonPath="浏览 Python 路径"
|
||||
ScriptLogWindow="脚本日志"
|
||||
Description="说明"
|
||||
|
||||
FileFilter.ScriptFiles="脚本文件"
|
||||
FileFilter.AllFiles="所有文件"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,18 @@ OutputTimer.Record.StoppingIn="錄影將在下面時間內停止"
|
|||
OutputTimer.Stream.EnableEverytime="每次都啟動串流計時器"
|
||||
OutputTimer.Record.EnableEverytime="每次都啟動錄影計時器"
|
||||
|
||||
Scripts="腳本"
|
||||
LoadedScripts="已載入腳本"
|
||||
AddScripts="增加腳本"
|
||||
RemoveScripts="移除腳本"
|
||||
ReloadScripts="重新載入腳本"
|
||||
PythonSettings="Python 設置"
|
||||
PythonSettings.PythonInstallPath32bit="Python 安裝路徑 (32bit)"
|
||||
PythonSettings.PythonInstallPath64bit="Python 安裝路徑 (64bit)"
|
||||
PythonSettings.BrowsePythonPath="瀏覽 Python 路徑"
|
||||
ScriptLogWindow="腳本記錄"
|
||||
Description="描述"
|
||||
|
||||
FileFilter.ScriptFiles="脚本文件"
|
||||
FileFilter.AllFiles="所有檔案"
|
||||
|
||||
|
|
|
|||
119
UI/frontend-plugins/frontend-tools/data/scripts/clock-source.lua
Normal file
119
UI/frontend-plugins/frontend-tools/data/scripts/clock-source.lua
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
obs = obslua
|
||||
bit = require("bit")
|
||||
|
||||
source_def = {}
|
||||
source_def.id = "lua_clock_source"
|
||||
source_def.output_flags = bit.bor(obs.OBS_SOURCE_VIDEO, obs.OBS_SOURCE_CUSTOM_DRAW)
|
||||
|
||||
function image_source_load(image, file)
|
||||
obs.obs_enter_graphics();
|
||||
obs.gs_image_file_free(image);
|
||||
obs.obs_leave_graphics();
|
||||
|
||||
obs.gs_image_file_init(image, file);
|
||||
|
||||
obs.obs_enter_graphics();
|
||||
obs.gs_image_file_init_texture(image);
|
||||
obs.obs_leave_graphics();
|
||||
|
||||
if not image.loaded then
|
||||
print("failed to load texture " .. file);
|
||||
end
|
||||
end
|
||||
|
||||
source_def.get_name = function()
|
||||
return "Lua Clock"
|
||||
end
|
||||
|
||||
source_def.create = function(source, settings)
|
||||
local data = {}
|
||||
data.image = obs.gs_image_file()
|
||||
data.hour_image = obs.gs_image_file()
|
||||
data.minute_image = obs.gs_image_file()
|
||||
data.second_image = obs.gs_image_file()
|
||||
|
||||
image_source_load(data.image, script_path() .. "clock-source/dial.png")
|
||||
image_source_load(data.hour_image, script_path() .. "clock-source/hour.png")
|
||||
image_source_load(data.minute_image, script_path() .. "clock-source/minute.png")
|
||||
image_source_load(data.second_image, script_path() .. "clock-source/second.png")
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
source_def.destroy = function(data)
|
||||
obs.obs_enter_graphics();
|
||||
obs.gs_image_file_free(data.image);
|
||||
obs.gs_image_file_free(data.hour_image);
|
||||
obs.gs_image_file_free(data.minute_image);
|
||||
obs.gs_image_file_free(data.second_image);
|
||||
obs.obs_leave_graphics();
|
||||
end
|
||||
|
||||
source_def.video_render = function(data, effect)
|
||||
if not data.image.texture then
|
||||
return;
|
||||
end
|
||||
|
||||
local time = os.date("*t")
|
||||
local seconds = time.sec
|
||||
local mins = time.min + seconds / 60.0;
|
||||
local hours = time.hour + (mins * 60.0) / 3600.0;
|
||||
|
||||
effect = obs.obs_get_base_effect(obs.OBS_EFFECT_DEFAULT)
|
||||
|
||||
obs.gs_blend_state_push()
|
||||
obs.gs_reset_blend_state()
|
||||
|
||||
while obs.gs_effect_loop(effect, "Draw") do
|
||||
obs.obs_source_draw(data.image.texture, 0, 0, data.image.cx, data.image.cy, false);
|
||||
end
|
||||
|
||||
obs.gs_matrix_push()
|
||||
obs.gs_matrix_translate3f(250, 250, 0)
|
||||
obs.gs_matrix_rotaa4f(0.0, 0.0, 1.0, 2 * math.pi / 60 * mins);
|
||||
obs.gs_matrix_translate3f(-250, -250, 0)
|
||||
|
||||
while obs.gs_effect_loop(effect, "Draw") do
|
||||
obs.obs_source_draw(data.minute_image.texture, 0, 0, data.image.cx, data.image.cy, false);
|
||||
end
|
||||
|
||||
obs.gs_matrix_pop()
|
||||
|
||||
obs.gs_matrix_push()
|
||||
obs.gs_matrix_translate3f(250, 250, 0)
|
||||
obs.gs_matrix_rotaa4f(0.0, 0.0, 1.0, 2.0 * math.pi / 12 * hours);
|
||||
obs.gs_matrix_translate3f(-250, -250, 0)
|
||||
|
||||
while obs.gs_effect_loop(effect, "Draw") do
|
||||
obs.obs_source_draw(data.hour_image.texture, 0, 0, data.image.cx, data.image.cy, false);
|
||||
end
|
||||
|
||||
obs.gs_matrix_pop()
|
||||
|
||||
obs.gs_matrix_push()
|
||||
obs.gs_matrix_translate3f(250, 250, 0)
|
||||
obs.gs_matrix_rotaa4f(0.0, 0.0, 1.0, 2 * math.pi / 60 * seconds);
|
||||
obs.gs_matrix_translate3f(-250, -250, 0)
|
||||
|
||||
while obs.gs_effect_loop(effect, "Draw") do
|
||||
obs.obs_source_draw(data.second_image.texture, 0, 0, data.image.cx, data.image.cy, false);
|
||||
end
|
||||
|
||||
obs.gs_matrix_pop()
|
||||
|
||||
obs.gs_blend_state_pop()
|
||||
end
|
||||
|
||||
source_def.get_width = function(data)
|
||||
return 500
|
||||
end
|
||||
|
||||
source_def.get_height = function(data)
|
||||
return 500
|
||||
end
|
||||
|
||||
function script_description()
|
||||
return "Adds a \"Lua Clock\" source which draws an animated analog clock."
|
||||
end
|
||||
|
||||
obs.obs_register_source(source_def)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2 KiB |
180
UI/frontend-plugins/frontend-tools/data/scripts/countdown.lua
Normal file
180
UI/frontend-plugins/frontend-tools/data/scripts/countdown.lua
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
obs = obslua
|
||||
source_name = ""
|
||||
total_seconds = 0
|
||||
|
||||
cur_seconds = 0
|
||||
last_text = ""
|
||||
stop_text = ""
|
||||
activated = false
|
||||
|
||||
hotkey_id = obs.OBS_INVALID_HOTKEY_ID
|
||||
|
||||
-- Function to set the time text
|
||||
function set_time_text()
|
||||
local seconds = math.floor(cur_seconds % 60)
|
||||
local total_minutes = math.floor(cur_seconds / 60)
|
||||
local minutes = math.floor(total_minutes % 60)
|
||||
local hours = math.floor(total_minutes / 60)
|
||||
local text = string.format("%02d:%02d:%02d", hours, minutes, seconds)
|
||||
|
||||
if cur_seconds < 1 then
|
||||
text = stop_text
|
||||
end
|
||||
|
||||
if text ~= last_text then
|
||||
local source = obs.obs_get_source_by_name(source_name)
|
||||
if source ~= nil then
|
||||
local settings = obs.obs_data_create()
|
||||
obs.obs_data_set_string(settings, "text", text)
|
||||
obs.obs_source_update(source, settings)
|
||||
obs.obs_data_release(settings)
|
||||
obs.obs_source_release(source)
|
||||
end
|
||||
end
|
||||
|
||||
last_text = text
|
||||
end
|
||||
|
||||
function timer_callback()
|
||||
cur_seconds = cur_seconds - 1
|
||||
if cur_seconds < 0 then
|
||||
obs.remove_current_callback()
|
||||
cur_seconds = 0
|
||||
end
|
||||
|
||||
set_time_text()
|
||||
end
|
||||
|
||||
function activate(activating)
|
||||
if activated == activating then
|
||||
return
|
||||
end
|
||||
|
||||
activated = activating
|
||||
|
||||
if activating then
|
||||
cur_seconds = total_seconds
|
||||
set_time_text()
|
||||
obs.timer_add(timer_callback, 1000)
|
||||
else
|
||||
obs.timer_remove(timer_callback)
|
||||
end
|
||||
end
|
||||
|
||||
-- Called when a source is activated/deactivated
|
||||
function activate_signal(cd, activating)
|
||||
local source = obs.calldata_source(cd, "source")
|
||||
if source ~= nil then
|
||||
local name = obs.obs_source_get_name(source)
|
||||
if (name == source_name) then
|
||||
activate(activating)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function source_activated(cd)
|
||||
activate_signal(cd, true)
|
||||
end
|
||||
|
||||
function source_deactivated(cd)
|
||||
activate_signal(cd, false)
|
||||
end
|
||||
|
||||
function reset(pressed)
|
||||
if not pressed then
|
||||
return
|
||||
end
|
||||
|
||||
activate(false)
|
||||
local source = obs.obs_get_source_by_name(source_name)
|
||||
if source ~= nil then
|
||||
local active = obs.obs_source_active(source)
|
||||
obs.obs_source_release(source)
|
||||
activate(active)
|
||||
end
|
||||
end
|
||||
|
||||
function reset_button_clicked(props, p)
|
||||
reset(true)
|
||||
return false
|
||||
end
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
-- A function named script_properties defines the properties that the user
|
||||
-- can change for the entire script module itself
|
||||
function script_properties()
|
||||
local props = obs.obs_properties_create()
|
||||
obs.obs_properties_add_int(props, "duration", "Duration (minutes)", 1, 100000, 1)
|
||||
|
||||
local p = obs.obs_properties_add_list(props, "source", "Text Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
|
||||
local sources = obs.obs_enum_sources()
|
||||
if sources ~= nil then
|
||||
for _, source in ipairs(sources) do
|
||||
source_id = obs.obs_source_get_id(source)
|
||||
if source_id == "text_gdiplus" or source_id == "text_ft2_source" then
|
||||
local name = obs.obs_source_get_name(source)
|
||||
obs.obs_property_list_add_string(p, name, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
obs.source_list_release(sources)
|
||||
|
||||
obs.obs_properties_add_text(props, "stop_text", "Final Text", obs.OBS_TEXT_DEFAULT)
|
||||
obs.obs_properties_add_button(props, "reset_button", "Reset Timer", reset_button_clicked)
|
||||
|
||||
return props
|
||||
end
|
||||
|
||||
-- A function named script_description returns the description shown to
|
||||
-- the user
|
||||
function script_description()
|
||||
return "Sets a text source to act as a countdown timer when the source is active.\n\nMade by Jim"
|
||||
end
|
||||
|
||||
-- A function named script_update will be called when settings are changed
|
||||
function script_update(settings)
|
||||
activate(false)
|
||||
|
||||
total_seconds = obs.obs_data_get_int(settings, "duration") * 60
|
||||
source_name = obs.obs_data_get_string(settings, "source")
|
||||
stop_text = obs.obs_data_get_string(settings, "stop_text")
|
||||
|
||||
reset(true)
|
||||
end
|
||||
|
||||
-- A function named script_defaults will be called to set the default settings
|
||||
function script_defaults(settings)
|
||||
obs.obs_data_set_default_int(settings, "duration", 5)
|
||||
obs.obs_data_set_default_string(settings, "stop_text", "Starting soon (tm)")
|
||||
end
|
||||
|
||||
-- A function named script_save will be called when the script is saved
|
||||
--
|
||||
-- NOTE: This function is usually used for saving extra data (such as in this
|
||||
-- case, a hotkey's save data). Settings set via the properties are saved
|
||||
-- automatically.
|
||||
function script_save(settings)
|
||||
local hotkey_save_array = obs.obs_hotkey_save(hotkey_id)
|
||||
obs.obs_data_set_array(settings, "reset_hotkey", hotkey_save_array)
|
||||
obs.obs_data_array_release(hotkey_save_array)
|
||||
end
|
||||
|
||||
-- a function named script_load will be called on startup
|
||||
function script_load(settings)
|
||||
-- Connect hotkey and activation/deactivation signal callbacks
|
||||
--
|
||||
-- NOTE: These particular script callbacks do not necessarily have to
|
||||
-- be disconnected, as callbacks will automatically destroy themselves
|
||||
-- if the script is unloaded. So there's no real need to manually
|
||||
-- disconnect callbacks that are intended to last until the script is
|
||||
-- unloaded.
|
||||
local sh = obs.obs_get_signal_handler()
|
||||
obs.signal_handler_connect(sh, "source_activate", source_activated)
|
||||
obs.signal_handler_connect(sh, "source_deactivate", source_deactivated)
|
||||
|
||||
hotkey_id = obs.obs_hotkey_register_frontend("reset_timer_thingy", "Reset Timer", reset)
|
||||
local hotkey_save_array = obs.obs_data_get_array(settings, "reset_hotkey")
|
||||
obs.obs_hotkey_load(hotkey_id, hotkey_save_array)
|
||||
obs.obs_data_array_release(hotkey_save_array)
|
||||
end
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
obs = obslua
|
||||
source_name = ""
|
||||
hotkey_id = obs.OBS_INVALID_HOTKEY_ID
|
||||
attempts = 0
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
function try_play()
|
||||
local replay_buffer = obs.obs_frontend_get_replay_buffer_output()
|
||||
if replay_buffer == nil then
|
||||
obs.remove_current_callback()
|
||||
return
|
||||
end
|
||||
|
||||
-- Call the procedure of the replay buffer named "get_last_replay" to
|
||||
-- get the last replay created by the replay buffer
|
||||
local cd = obs.calldata_create()
|
||||
local ph = obs.obs_output_get_proc_handler(replay_buffer)
|
||||
obs.proc_handler_call(ph, "get_last_replay", cd)
|
||||
local path = obs.calldata_string(cd, "path")
|
||||
obs.calldata_destroy(cd)
|
||||
|
||||
obs.obs_output_release(replay_buffer)
|
||||
|
||||
-- If the path is valid and the source exists, update it with the
|
||||
-- replay file to play back the replay. Otherwise, stop attempting to
|
||||
-- replay after 10 seconds
|
||||
if path == nil then
|
||||
attempts = attempts + 1
|
||||
if attempts >= 10 then
|
||||
obs.remove_current_callback()
|
||||
end
|
||||
else
|
||||
local source = obs.obs_get_source_by_name(source_name)
|
||||
if source ~= nil then
|
||||
local settings = obs.obs_data_create()
|
||||
obs.obs_data_set_string(settings, "local_file", path)
|
||||
obs.obs_data_set_bool(settings, "is_local_file", true)
|
||||
obs.obs_data_set_bool(settings, "close_when_inactive", true)
|
||||
obs.obs_data_set_bool(settings, "restart_on_activate", true)
|
||||
|
||||
-- updating will automatically cause the source to
|
||||
-- refresh if the source is currently active, otherwise
|
||||
-- the source will play whenever its scene is activated
|
||||
obs.obs_source_update(source, settings)
|
||||
|
||||
obs.obs_data_release(settings)
|
||||
obs.obs_source_release(source)
|
||||
end
|
||||
|
||||
obs.remove_current_callback()
|
||||
end
|
||||
end
|
||||
|
||||
-- The "Instant Replay" hotkey callback
|
||||
function instant_replay(pressed)
|
||||
if not pressed then
|
||||
return
|
||||
end
|
||||
|
||||
local replay_buffer = obs.obs_frontend_get_replay_buffer_output()
|
||||
if replay_buffer ~= nil then
|
||||
-- Call the procedure of the replay buffer named "get_last_replay" to
|
||||
-- get the last replay created by the replay buffer
|
||||
local ph = obs.obs_output_get_proc_handler(replay_buffer)
|
||||
obs.proc_handler_call(ph, "save", nil)
|
||||
|
||||
-- Set a 1-second timer to attempt playback every 1 second
|
||||
-- until the replay is available
|
||||
if obs.obs_output_active(replay_buffer) then
|
||||
attempts = 0
|
||||
obs.timer_add(try_play, 1000)
|
||||
else
|
||||
obs.script_log(obs.LOG_WARNING, "Tried to save an instant replay, but the replay buffer is not active!")
|
||||
end
|
||||
|
||||
obs.obs_output_release(replay_buffer)
|
||||
else
|
||||
obs.script_log(obs.LOG_WARNING, "Tried to save an instant replay, but found no active replay buffer!")
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
-- A function named script_update will be called when settings are changed
|
||||
function script_update(settings)
|
||||
source_name = obs.obs_data_get_string(settings, "source")
|
||||
end
|
||||
|
||||
-- A function named script_description returns the description shown to
|
||||
-- the user
|
||||
function script_description()
|
||||
return "When the \"Instant Replay\" hotkey is triggered, saves a replay with the replay buffer, and then plays it in a media source as soon as the replay is ready. Requires an active replay buffer.\n\nMade by Jim"
|
||||
end
|
||||
|
||||
-- A function named script_properties defines the properties that the user
|
||||
-- can change for the entire script module itself
|
||||
function script_properties()
|
||||
props = obs.obs_properties_create()
|
||||
|
||||
local p = obs.obs_properties_add_list(props, "source", "Media Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
|
||||
local sources = obs.obs_enum_sources()
|
||||
if sources ~= nil then
|
||||
for _, source in ipairs(sources) do
|
||||
source_id = obs.obs_source_get_id(source)
|
||||
if source_id == "ffmpeg_source" then
|
||||
local name = obs.obs_source_get_name(source)
|
||||
obs.obs_property_list_add_string(p, name, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
obs.source_list_release(sources)
|
||||
|
||||
return props
|
||||
end
|
||||
|
||||
-- A function named script_load will be called on startup
|
||||
function script_load(settings)
|
||||
hotkey_id = obs.obs_hotkey_register_frontend("instant_replay.trigger", "Instant Replay", instant_replay)
|
||||
local hotkey_save_array = obs.obs_data_get_array(settings, "instant_replay.trigger")
|
||||
obs.obs_hotkey_load(hotkey_id, hotkey_save_array)
|
||||
obs.obs_data_array_release(hotkey_save_array)
|
||||
end
|
||||
|
||||
-- A function named script_save will be called when the script is saved
|
||||
--
|
||||
-- NOTE: This function is usually used for saving extra data (such as in this
|
||||
-- case, a hotkey's save data). Settings set via the properties are saved
|
||||
-- automatically.
|
||||
function script_save(settings)
|
||||
local hotkey_save_array = obs.obs_hotkey_save(hotkey_id)
|
||||
obs.obs_data_set_array(settings, "instant_replay.trigger", hotkey_save_array)
|
||||
obs.obs_data_array_release(hotkey_save_array)
|
||||
end
|
||||
77
UI/frontend-plugins/frontend-tools/data/scripts/url-text.py
Normal file
77
UI/frontend-plugins/frontend-tools/data/scripts/url-text.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import obspython as obs
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
url = ""
|
||||
interval = 30
|
||||
source_name = ""
|
||||
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def update_text():
|
||||
global url
|
||||
global interval
|
||||
global source_name
|
||||
|
||||
source = obs.obs_get_source_by_name(source_name)
|
||||
if source is not None:
|
||||
try:
|
||||
with urllib.request.urlopen(url) as response:
|
||||
data = response.read()
|
||||
text = data.decode('utf-8')
|
||||
|
||||
settings = obs.obs_data_create()
|
||||
obs.obs_data_set_string(settings, "text", text)
|
||||
obs.obs_source_update(source, settings)
|
||||
obs.obs_data_release(settings)
|
||||
|
||||
except urllib.error.URLError as err:
|
||||
obs.script_log(obs.LOG_WARNING, "Error opening URL '" + url + "': " + err.reason)
|
||||
obs.remove_current_callback()
|
||||
|
||||
obs.obs_source_release(source)
|
||||
|
||||
def refresh_pressed(props, prop):
|
||||
update_text()
|
||||
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def script_description():
|
||||
return "Updates a text source to the text retrieved from a URL at every specified interval.\n\nBy Jim"
|
||||
|
||||
def script_update(settings):
|
||||
global url
|
||||
global interval
|
||||
global source_name
|
||||
|
||||
url = obs.obs_data_get_string(settings, "url")
|
||||
interval = obs.obs_data_get_int(settings, "interval")
|
||||
source_name = obs.obs_data_get_string(settings, "source")
|
||||
|
||||
obs.timer_remove(update_text)
|
||||
|
||||
if url != "" and source_name != "":
|
||||
obs.timer_add(update_text, interval * 1000)
|
||||
|
||||
def script_defaults(settings):
|
||||
obs.obs_data_set_default_int(settings, "interval", 30)
|
||||
|
||||
def script_properties():
|
||||
props = obs.obs_properties_create()
|
||||
|
||||
obs.obs_properties_add_text(props, "url", "URL", obs.OBS_TEXT_DEFAULT)
|
||||
obs.obs_properties_add_int(props, "interval", "Update Interval (seconds)", 5, 3600, 1)
|
||||
|
||||
p = obs.obs_properties_add_list(props, "source", "Text Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
|
||||
sources = obs.obs_enum_sources()
|
||||
if sources is not None:
|
||||
for source in sources:
|
||||
source_id = obs.obs_source_get_id(source)
|
||||
if source_id == "text_gdiplus" or source_id == "text_ft2_source":
|
||||
name = obs.obs_source_get_name(source)
|
||||
obs.obs_property_list_add_string(p, name, name)
|
||||
|
||||
obs.source_list_release(sources)
|
||||
|
||||
obs.obs_properties_add_button(props, "button", "Refresh", refresh_pressed)
|
||||
return props
|
||||
266
UI/frontend-plugins/frontend-tools/forms/scripts.ui
Normal file
266
UI/frontend-plugins/frontend-tools/forms/scripts.ui
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ScriptsTool</class>
|
||||
<widget class="QWidget" name="ScriptsTool">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>775</width>
|
||||
<height>492</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Scripts</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="scriptsTab">
|
||||
<attribute name="title">
|
||||
<string>Scripts</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>LoadedScripts</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>scripts</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="scripts">
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="addScripts">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>AddScripts</string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>AddScripts</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">addIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeScripts">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>RemoveScripts</string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>RemoveScripts</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">removeIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="reloadScripts">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>ReloadScripts</string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>ReloadScripts</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">refreshIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="scriptLog">
|
||||
<property name="text">
|
||||
<string>ScriptLogWindow</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="propertiesLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="description">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>12</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pythonSettingsTab">
|
||||
<attribute name="title">
|
||||
<string>PythonSettings</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="pythonPathLabel">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pythonPath</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="pythonPath">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pythonPathBrowse">
|
||||
<property name="accessibleName">
|
||||
<string>PythonSettings.BrowsePythonPath</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>510</width>
|
||||
<height>306</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="close">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>close</tabstop>
|
||||
<tabstop>pythonPath</tabstop>
|
||||
<tabstop>pythonPathBrowse</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -1,3 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef ON
|
||||
#define ON 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef OFF
|
||||
#define OFF 0
|
||||
#endif
|
||||
|
||||
#define BUILD_CAPTIONS @BUILD_CAPTIONS@
|
||||
#define ENABLE_SCRIPTING @SCRIPTING_ENABLED@
|
||||
#define COMPILE_LUA @COMPILE_LUA@
|
||||
#define COMPILE_PYTHON @COMPILE_PYTHON@
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ void FreeCaptions();
|
|||
void InitOutputTimer();
|
||||
void FreeOutputTimer();
|
||||
|
||||
#if ENABLE_SCRIPTING
|
||||
void InitScripts();
|
||||
void FreeScripts();
|
||||
#endif
|
||||
|
||||
bool obs_module_load(void)
|
||||
{
|
||||
#if defined(_WIN32) && BUILD_CAPTIONS
|
||||
|
|
@ -22,6 +27,9 @@ bool obs_module_load(void)
|
|||
#endif
|
||||
InitSceneSwitcher();
|
||||
InitOutputTimer();
|
||||
#if ENABLE_SCRIPTING
|
||||
InitScripts();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -32,4 +40,7 @@ void obs_module_unload(void)
|
|||
#endif
|
||||
FreeSceneSwitcher();
|
||||
FreeOutputTimer();
|
||||
#if ENABLE_SCRIPTING
|
||||
FreeScripts();
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,11 +40,13 @@ void OutputTimer::closeEvent(QCloseEvent*)
|
|||
void OutputTimer::StreamingTimerButton()
|
||||
{
|
||||
if (!obs_frontend_streaming_active()) {
|
||||
blog(LOG_INFO, "Starting stream due to OutputTimer");
|
||||
obs_frontend_streaming_start();
|
||||
} else if (streamingAlreadyActive) {
|
||||
StreamTimerStart();
|
||||
streamingAlreadyActive = false;
|
||||
} else if (obs_frontend_streaming_active()) {
|
||||
blog(LOG_INFO, "Stopping stream due to OutputTimer");
|
||||
obs_frontend_streaming_stop();
|
||||
}
|
||||
}
|
||||
|
|
@ -52,11 +54,13 @@ void OutputTimer::StreamingTimerButton()
|
|||
void OutputTimer::RecordingTimerButton()
|
||||
{
|
||||
if (!obs_frontend_recording_active()) {
|
||||
blog(LOG_INFO, "Starting recording due to OutputTimer");
|
||||
obs_frontend_recording_start();
|
||||
} else if (recordingAlreadyActive) {
|
||||
RecordTimerStart();
|
||||
recordingAlreadyActive = false;
|
||||
} else if (obs_frontend_recording_active()) {
|
||||
blog(LOG_INFO, "Stopping recording due to OutputTimer");
|
||||
obs_frontend_recording_stop();
|
||||
}
|
||||
}
|
||||
|
|
@ -204,11 +208,13 @@ void OutputTimer::ShowHideDialog()
|
|||
|
||||
void OutputTimer::EventStopStreaming()
|
||||
{
|
||||
blog(LOG_INFO, "Stopping stream due to OutputTimer timeout");
|
||||
obs_frontend_streaming_stop();
|
||||
}
|
||||
|
||||
void OutputTimer::EventStopRecording()
|
||||
{
|
||||
blog(LOG_INFO, "Stopping recording due to OutputTimer timeout");
|
||||
obs_frontend_recording_stop();
|
||||
}
|
||||
|
||||
|
|
|
|||
552
UI/frontend-plugins/frontend-tools/scripts.cpp
Normal file
552
UI/frontend-plugins/frontend-tools/scripts.cpp
Normal file
|
|
@ -0,0 +1,552 @@
|
|||
#include "scripts.hpp"
|
||||
#include "frontend-tools-config.h"
|
||||
#include "../../properties-view.hpp"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QScrollBar>
|
||||
#include <QPushButton>
|
||||
#include <QFontDatabase>
|
||||
#include <QFont>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QResizeEvent>
|
||||
|
||||
#include <obs.hpp>
|
||||
#include <obs-module.h>
|
||||
#include <obs-frontend-api.h>
|
||||
#include <obs-scripting.h>
|
||||
|
||||
#include <util/config-file.h>
|
||||
#include <util/platform.h>
|
||||
#include <util/util.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ui_scripts.h"
|
||||
|
||||
#if COMPILE_PYTHON && (defined(_WIN32) || defined(__APPLE__))
|
||||
#define PYTHON_UI 1
|
||||
#else
|
||||
#define PYTHON_UI 0
|
||||
#endif
|
||||
|
||||
#if ARCH_BITS == 64
|
||||
#define ARCH_NAME "64bit"
|
||||
#else
|
||||
#define ARCH_NAME "32bit"
|
||||
#endif
|
||||
|
||||
#define PYTHONPATH_LABEL_TEXT "PythonSettings.PythonInstallPath" ARCH_NAME
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
using OBSScript = OBSObj<obs_script_t*, obs_script_destroy>;
|
||||
|
||||
struct ScriptData {
|
||||
std::vector<OBSScript> scripts;
|
||||
|
||||
inline obs_script_t *FindScript(const char *path)
|
||||
{
|
||||
for (OBSScript &script : scripts) {
|
||||
const char *script_path = obs_script_get_path(script);
|
||||
if (strcmp(script_path, path) == 0) {
|
||||
return script;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ScriptOpened(const char *path)
|
||||
{
|
||||
for (OBSScript &script : scripts) {
|
||||
const char *script_path = obs_script_get_path(script);
|
||||
if (strcmp(script_path, path) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static ScriptData *scriptData = nullptr;
|
||||
static ScriptsTool *scriptsWindow = nullptr;
|
||||
static ScriptLogWindow *scriptLogWindow = nullptr;
|
||||
static QPlainTextEdit *scriptLogWidget = nullptr;
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
ScriptLogWindow::ScriptLogWindow() : QWidget(nullptr)
|
||||
{
|
||||
const QFont fixedFont =
|
||||
QFontDatabase::systemFont(QFontDatabase::FixedFont);
|
||||
|
||||
QPlainTextEdit *edit = new QPlainTextEdit();
|
||||
edit->setReadOnly(true);
|
||||
edit->setFont(fixedFont);
|
||||
edit->setWordWrapMode(QTextOption::NoWrap);
|
||||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout();
|
||||
QPushButton *clearButton = new QPushButton(tr("Clear"));
|
||||
connect(clearButton, &QPushButton::clicked,
|
||||
this, &ScriptLogWindow::ClearWindow);
|
||||
QPushButton *closeButton = new QPushButton(tr("Close"));
|
||||
connect(closeButton, &QPushButton::clicked,
|
||||
this, &QDialog::hide);
|
||||
|
||||
buttonLayout->addStretch();
|
||||
buttonLayout->addWidget(clearButton);
|
||||
buttonLayout->addWidget(closeButton);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout();
|
||||
layout->addWidget(edit);
|
||||
layout->addLayout(buttonLayout);
|
||||
|
||||
setLayout(layout);
|
||||
scriptLogWidget = edit;
|
||||
|
||||
resize(600, 400);
|
||||
|
||||
config_t *global_config = obs_frontend_get_global_config();
|
||||
const char *geom = config_get_string(global_config,
|
||||
"ScriptLogWindow", "geometry");
|
||||
if (geom != nullptr) {
|
||||
QByteArray ba = QByteArray::fromBase64(QByteArray(geom));
|
||||
restoreGeometry(ba);
|
||||
}
|
||||
|
||||
setWindowTitle(obs_module_text("ScriptLogWindow"));
|
||||
|
||||
connect(edit->verticalScrollBar(), &QAbstractSlider::sliderMoved,
|
||||
this, &ScriptLogWindow::ScrollChanged);
|
||||
}
|
||||
|
||||
ScriptLogWindow::~ScriptLogWindow()
|
||||
{
|
||||
config_t *global_config = obs_frontend_get_global_config();
|
||||
config_set_string(global_config,
|
||||
"ScriptLogWindow", "geometry",
|
||||
saveGeometry().toBase64().constData());
|
||||
}
|
||||
|
||||
void ScriptLogWindow::ScrollChanged(int val)
|
||||
{
|
||||
QScrollBar *scroll = scriptLogWidget->verticalScrollBar();
|
||||
bottomScrolled = (val == scroll->maximum());
|
||||
}
|
||||
|
||||
void ScriptLogWindow::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
|
||||
if (bottomScrolled) {
|
||||
QScrollBar *scroll = scriptLogWidget->verticalScrollBar();
|
||||
scroll->setValue(scroll->maximum());
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptLogWindow::AddLogMsg(int log_level, QString msg)
|
||||
{
|
||||
QScrollBar *scroll = scriptLogWidget->verticalScrollBar();
|
||||
bottomScrolled = scroll->value() == scroll->maximum();
|
||||
|
||||
lines += QStringLiteral("\n");
|
||||
lines += msg;
|
||||
scriptLogWidget->setPlainText(lines);
|
||||
|
||||
if (bottomScrolled)
|
||||
scroll->setValue(scroll->maximum());
|
||||
|
||||
if (log_level <= LOG_WARNING) {
|
||||
show();
|
||||
raise();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptLogWindow::ClearWindow()
|
||||
{
|
||||
Clear();
|
||||
scriptLogWidget->setPlainText(QString());
|
||||
}
|
||||
|
||||
void ScriptLogWindow::Clear()
|
||||
{
|
||||
lines.clear();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
ScriptsTool::ScriptsTool()
|
||||
: QWidget (nullptr),
|
||||
ui (new Ui_ScriptsTool)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
RefreshLists();
|
||||
|
||||
#if PYTHON_UI
|
||||
config_t *config = obs_frontend_get_global_config();
|
||||
const char *path = config_get_string(config, "Python",
|
||||
"Path" ARCH_NAME);
|
||||
ui->pythonPath->setText(path);
|
||||
ui->pythonPathLabel->setText(obs_module_text(PYTHONPATH_LABEL_TEXT));
|
||||
#else
|
||||
delete ui->pythonSettingsTab;
|
||||
ui->pythonSettingsTab = nullptr;
|
||||
#endif
|
||||
|
||||
delete propertiesView;
|
||||
propertiesView = new QWidget();
|
||||
propertiesView->setSizePolicy(QSizePolicy::Expanding,
|
||||
QSizePolicy::Expanding);
|
||||
ui->propertiesLayout->addWidget(propertiesView);
|
||||
}
|
||||
|
||||
ScriptsTool::~ScriptsTool()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ScriptsTool::RemoveScript(const char *path)
|
||||
{
|
||||
for (size_t i = 0; i < scriptData->scripts.size(); i++) {
|
||||
OBSScript &script = scriptData->scripts[i];
|
||||
|
||||
const char *script_path = obs_script_get_path(script);
|
||||
if (strcmp(script_path, path) == 0) {
|
||||
scriptData->scripts.erase(
|
||||
scriptData->scripts.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptsTool::ReloadScript(const char *path)
|
||||
{
|
||||
for (OBSScript &script : scriptData->scripts) {
|
||||
const char *script_path = obs_script_get_path(script);
|
||||
if (strcmp(script_path, path) == 0) {
|
||||
obs_script_reload(script);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptsTool::RefreshLists()
|
||||
{
|
||||
ui->scripts->clear();
|
||||
|
||||
for (OBSScript &script : scriptData->scripts) {
|
||||
const char *script_file = obs_script_get_file(script);
|
||||
const char *script_path = obs_script_get_path(script);
|
||||
|
||||
QListWidgetItem *item = new QListWidgetItem(script_file);
|
||||
item->setData(Qt::UserRole, QString(script_path));
|
||||
ui->scripts->addItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptsTool::on_close_clicked()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void ScriptsTool::on_addScripts_clicked()
|
||||
{
|
||||
const char **formats = obs_scripting_supported_formats();
|
||||
const char **cur_format = formats;
|
||||
QString extensions;
|
||||
QString filter;
|
||||
|
||||
while (*cur_format) {
|
||||
if (!extensions.isEmpty())
|
||||
extensions += QStringLiteral(" ");
|
||||
|
||||
extensions += QStringLiteral("*.");
|
||||
extensions += *cur_format;
|
||||
|
||||
cur_format++;
|
||||
}
|
||||
|
||||
if (!extensions.isEmpty()) {
|
||||
filter += obs_module_text("FileFilter.ScriptFiles");
|
||||
filter += QStringLiteral(" (");
|
||||
filter += extensions;
|
||||
filter += QStringLiteral(")");
|
||||
}
|
||||
|
||||
if (filter.isEmpty())
|
||||
return;
|
||||
|
||||
static std::string lastBrowsedDir;
|
||||
|
||||
if (lastBrowsedDir.empty()) {
|
||||
BPtr<char> baseScriptPath = obs_module_file("scripts");
|
||||
lastBrowsedDir = baseScriptPath;
|
||||
}
|
||||
|
||||
QFileDialog dlg(this, obs_module_text("AddScripts"));
|
||||
dlg.setFileMode(QFileDialog::ExistingFiles);
|
||||
dlg.setDirectory(QDir(lastBrowsedDir.c_str()));
|
||||
dlg.setNameFilter(filter);
|
||||
dlg.exec();
|
||||
|
||||
QStringList files = dlg.selectedFiles();
|
||||
if (!files.count())
|
||||
return;
|
||||
|
||||
lastBrowsedDir = dlg.directory().path().toUtf8().constData();
|
||||
|
||||
for (const QString &file : files) {
|
||||
QByteArray pathBytes = file.toUtf8();
|
||||
const char *path = pathBytes.constData();
|
||||
|
||||
if (scriptData->ScriptOpened(path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
obs_script_t *script = obs_script_create(path, NULL);
|
||||
if (script) {
|
||||
const char *script_file = obs_script_get_file(script);
|
||||
|
||||
scriptData->scripts.emplace_back(script);
|
||||
|
||||
QListWidgetItem *item = new QListWidgetItem(script_file);
|
||||
item->setData(Qt::UserRole, QString(file));
|
||||
ui->scripts->addItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptsTool::on_removeScripts_clicked()
|
||||
{
|
||||
QList<QListWidgetItem *> items = ui->scripts->selectedItems();
|
||||
|
||||
for (QListWidgetItem *item : items)
|
||||
RemoveScript(item->data(Qt::UserRole).toString()
|
||||
.toUtf8().constData());
|
||||
RefreshLists();
|
||||
}
|
||||
|
||||
void ScriptsTool::on_reloadScripts_clicked()
|
||||
{
|
||||
QList<QListWidgetItem *> items = ui->scripts->selectedItems();
|
||||
for (QListWidgetItem *item : items)
|
||||
ReloadScript(item->data(Qt::UserRole).toString()
|
||||
.toUtf8().constData());
|
||||
|
||||
on_scripts_currentRowChanged(ui->scripts->currentRow());
|
||||
}
|
||||
|
||||
void ScriptsTool::on_scriptLog_clicked()
|
||||
{
|
||||
scriptLogWindow->show();
|
||||
scriptLogWindow->raise();
|
||||
}
|
||||
|
||||
void ScriptsTool::on_pythonPathBrowse_clicked()
|
||||
{
|
||||
QString curPath = ui->pythonPath->text();
|
||||
QString newPath = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
ui->pythonPathLabel->text(),
|
||||
curPath);
|
||||
|
||||
if (newPath.isEmpty())
|
||||
return;
|
||||
|
||||
QByteArray array = newPath.toUtf8();
|
||||
const char *path = array.constData();
|
||||
|
||||
config_t *config = obs_frontend_get_global_config();
|
||||
config_set_string(config, "Python", "Path" ARCH_NAME, path);
|
||||
|
||||
ui->pythonPath->setText(newPath);
|
||||
|
||||
if (obs_scripting_python_loaded())
|
||||
return;
|
||||
if (!obs_scripting_load_python(path))
|
||||
return;
|
||||
|
||||
for (OBSScript &script : scriptData->scripts) {
|
||||
enum obs_script_lang lang = obs_script_get_lang(script);
|
||||
if (lang == OBS_SCRIPT_LANG_PYTHON) {
|
||||
obs_script_reload(script);
|
||||
}
|
||||
}
|
||||
|
||||
on_scripts_currentRowChanged(ui->scripts->currentRow());
|
||||
}
|
||||
|
||||
void ScriptsTool::on_scripts_currentRowChanged(int row)
|
||||
{
|
||||
ui->propertiesLayout->removeWidget(propertiesView);
|
||||
delete propertiesView;
|
||||
|
||||
if (row == -1) {
|
||||
propertiesView = new QWidget();
|
||||
propertiesView->setSizePolicy(QSizePolicy::Expanding,
|
||||
QSizePolicy::Expanding);
|
||||
ui->propertiesLayout->addWidget(propertiesView);
|
||||
ui->description->setText(QString());
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray array = ui->scripts->item(row)->data(Qt::UserRole)
|
||||
.toString().toUtf8();
|
||||
const char *path = array.constData();
|
||||
|
||||
obs_script_t *script = scriptData->FindScript(path);
|
||||
if (!script) {
|
||||
propertiesView = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
OBSData settings = obs_script_get_settings(script);
|
||||
obs_data_release(settings);
|
||||
|
||||
propertiesView = new OBSPropertiesView(settings, script,
|
||||
(PropertiesReloadCallback)obs_script_get_properties,
|
||||
(PropertiesUpdateCallback)obs_script_update);
|
||||
ui->propertiesLayout->addWidget(propertiesView);
|
||||
ui->description->setText(obs_script_get_description(script));
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
extern "C" void FreeScripts()
|
||||
{
|
||||
obs_scripting_unload();
|
||||
}
|
||||
|
||||
static void obs_event(enum obs_frontend_event event, void *)
|
||||
{
|
||||
if (event == OBS_FRONTEND_EVENT_EXIT) {
|
||||
delete scriptData;
|
||||
delete scriptsWindow;
|
||||
delete scriptLogWindow;
|
||||
|
||||
} else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP) {
|
||||
scriptLogWindow->hide();
|
||||
scriptLogWindow->Clear();
|
||||
|
||||
delete scriptData;
|
||||
scriptData = new ScriptData;
|
||||
}
|
||||
}
|
||||
|
||||
static void load_script_data(obs_data_t *load_data, bool, void *)
|
||||
{
|
||||
obs_data_array_t *array = obs_data_get_array(load_data,
|
||||
"scripts-tool");
|
||||
|
||||
delete scriptData;
|
||||
scriptData = new ScriptData;
|
||||
|
||||
size_t size = obs_data_array_count(array);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
obs_data_t *obj = obs_data_array_item(array, i);
|
||||
const char *path = obs_data_get_string(obj, "path");
|
||||
obs_data_t *settings = obs_data_get_obj(obj, "settings");
|
||||
|
||||
obs_script_t *script = obs_script_create(path, settings);
|
||||
if (script) {
|
||||
scriptData->scripts.emplace_back(script);
|
||||
}
|
||||
|
||||
obs_data_release(settings);
|
||||
obs_data_release(obj);
|
||||
}
|
||||
|
||||
if (scriptsWindow)
|
||||
scriptsWindow->RefreshLists();
|
||||
|
||||
obs_data_array_release(array);
|
||||
}
|
||||
|
||||
static void save_script_data(obs_data_t *save_data, bool saving, void *)
|
||||
{
|
||||
if (!saving)
|
||||
return;
|
||||
|
||||
obs_data_array_t *array = obs_data_array_create();
|
||||
|
||||
for (OBSScript &script : scriptData->scripts) {
|
||||
const char *script_path = obs_script_get_path(script);
|
||||
obs_data_t *settings = obs_script_save(script);
|
||||
|
||||
obs_data_t *obj = obs_data_create();
|
||||
obs_data_set_string(obj, "path", script_path);
|
||||
obs_data_set_obj(obj, "settings", settings);
|
||||
obs_data_array_push_back(array, obj);
|
||||
obs_data_release(obj);
|
||||
|
||||
obs_data_release(settings);
|
||||
}
|
||||
|
||||
obs_data_set_array(save_data, "scripts-tool", array);
|
||||
obs_data_array_release(array);
|
||||
}
|
||||
|
||||
static void script_log(void *, obs_script_t *script, int log_level,
|
||||
const char *message)
|
||||
{
|
||||
QString qmsg;
|
||||
|
||||
if (script) {
|
||||
qmsg = QStringLiteral("[%1] %2").arg(
|
||||
obs_script_get_file(script),
|
||||
message);
|
||||
} else {
|
||||
qmsg = QStringLiteral("[Unknown Script] %1").arg(message);
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(scriptLogWindow, "AddLogMsg",
|
||||
Q_ARG(int, log_level),
|
||||
Q_ARG(QString, qmsg));
|
||||
}
|
||||
|
||||
extern "C" void InitScripts()
|
||||
{
|
||||
scriptLogWindow = new ScriptLogWindow();
|
||||
|
||||
obs_scripting_load();
|
||||
obs_scripting_set_log_callback(script_log, nullptr);
|
||||
|
||||
QAction *action = (QAction*)obs_frontend_add_tools_menu_qaction(
|
||||
obs_module_text("Scripts"));
|
||||
|
||||
#if PYTHON_UI
|
||||
config_t *config = obs_frontend_get_global_config();
|
||||
const char *python_path = config_get_string(config, "Python",
|
||||
"Path" ARCH_NAME);
|
||||
|
||||
if (!obs_scripting_python_loaded() && python_path && *python_path)
|
||||
obs_scripting_load_python(python_path);
|
||||
#endif
|
||||
|
||||
scriptData = new ScriptData;
|
||||
|
||||
auto cb = [] ()
|
||||
{
|
||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||
|
||||
if (!scriptsWindow) {
|
||||
scriptsWindow = new ScriptsTool();
|
||||
scriptsWindow->show();
|
||||
} else {
|
||||
scriptsWindow->show();
|
||||
scriptsWindow->raise();
|
||||
}
|
||||
|
||||
obs_frontend_pop_ui_translation();
|
||||
};
|
||||
|
||||
obs_frontend_add_save_callback(save_script_data, nullptr);
|
||||
obs_frontend_add_preload_callback(load_script_data, nullptr);
|
||||
obs_frontend_add_event_callback(obs_event, nullptr);
|
||||
|
||||
action->connect(action, &QAction::triggered, cb);
|
||||
}
|
||||
50
UI/frontend-plugins/frontend-tools/scripts.hpp
Normal file
50
UI/frontend-plugins/frontend-tools/scripts.hpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include <QWidget>
|
||||
#include <QString>
|
||||
|
||||
class Ui_ScriptsTool;
|
||||
|
||||
class ScriptLogWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
QString lines;
|
||||
bool bottomScrolled = true;
|
||||
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
public:
|
||||
ScriptLogWindow();
|
||||
~ScriptLogWindow();
|
||||
|
||||
public slots:
|
||||
void AddLogMsg(int log_level, QString msg);
|
||||
void ClearWindow();
|
||||
void Clear();
|
||||
void ScrollChanged(int val);
|
||||
};
|
||||
|
||||
class ScriptsTool : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
Ui_ScriptsTool *ui;
|
||||
QWidget *propertiesView = nullptr;
|
||||
|
||||
public:
|
||||
ScriptsTool();
|
||||
~ScriptsTool();
|
||||
|
||||
void RemoveScript(const char *path);
|
||||
void ReloadScript(const char *path);
|
||||
void RefreshLists();
|
||||
|
||||
public slots:
|
||||
void on_close_clicked();
|
||||
|
||||
void on_addScripts_clicked();
|
||||
void on_removeScripts_clicked();
|
||||
void on_reloadScripts_clicked();
|
||||
void on_scriptLog_clicked();
|
||||
|
||||
void on_scripts_currentRowChanged(int row);
|
||||
|
||||
void on_pythonPathBrowse_clicked();
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue