mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 12:45:28 -05:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b25c1250e5 | ||
|
|
98f3f51ba9 | ||
|
|
f0df9ead3c | ||
|
|
7b1a57070d | ||
|
|
a412f2fd5e | ||
|
|
4f0c8c4ab5 | ||
|
|
946c90a749 | ||
|
|
7ba4eaab9c | ||
|
|
74553a82fc | ||
|
|
39fcb2d743 | ||
|
|
7041feaea3 | ||
|
|
9b1ffaeded | ||
|
|
07d397bdac | ||
|
|
a86ff4f1f0 | ||
|
|
953eca2732 | ||
|
|
d6c5fb149a | ||
|
|
12982708cf | ||
|
|
0cf9e1dd81 | ||
|
|
71e20c4983 | ||
|
|
2147f6d3bf | ||
|
|
23df42d2d3 | ||
|
|
bcf0a0b7fd | ||
|
|
dd78b03a28 | ||
|
|
84dd5e6930 | ||
|
|
dcee98fea7 | ||
|
|
9ffb982ae5 | ||
|
|
428850306f | ||
|
|
abfd6798e3 | ||
|
|
fffadd94de | ||
|
|
d0919776f3 | ||
|
|
267855fded | ||
|
|
4bdebb7feb | ||
|
|
ab5f69d2ef |
@@ -97,6 +97,8 @@ target_sources(
|
|||||||
src/macro-core/macro-action-clipboard.hpp
|
src/macro-core/macro-action-clipboard.hpp
|
||||||
src/macro-core/macro-action-edit.cpp
|
src/macro-core/macro-action-edit.cpp
|
||||||
src/macro-core/macro-action-edit.hpp
|
src/macro-core/macro-action-edit.hpp
|
||||||
|
src/macro-core/macro-action-factory.cpp
|
||||||
|
src/macro-core/macro-action-factory.hpp
|
||||||
src/macro-core/macro-action-file.cpp
|
src/macro-core/macro-action-file.cpp
|
||||||
src/macro-core/macro-action-file.hpp
|
src/macro-core/macro-action-file.hpp
|
||||||
src/macro-core/macro-action-filter.cpp
|
src/macro-core/macro-action-filter.cpp
|
||||||
@@ -173,6 +175,8 @@ target_sources(
|
|||||||
src/macro-core/macro-condition-display.hpp
|
src/macro-core/macro-condition-display.hpp
|
||||||
src/macro-core/macro-condition-edit.cpp
|
src/macro-core/macro-condition-edit.cpp
|
||||||
src/macro-core/macro-condition-edit.hpp
|
src/macro-core/macro-condition-edit.hpp
|
||||||
|
src/macro-core/macro-condition-factory.cpp
|
||||||
|
src/macro-core/macro-condition-factory.hpp
|
||||||
src/macro-core/macro-condition-file.cpp
|
src/macro-core/macro-condition-file.cpp
|
||||||
src/macro-core/macro-condition-file.hpp
|
src/macro-core/macro-condition-file.hpp
|
||||||
src/macro-core/macro-condition-filter.cpp
|
src/macro-core/macro-condition-filter.cpp
|
||||||
@@ -233,6 +237,8 @@ target_sources(
|
|||||||
src/macro-core/macro-condition.hpp
|
src/macro-core/macro-condition.hpp
|
||||||
src/macro-core/macro-dock.cpp
|
src/macro-core/macro-dock.cpp
|
||||||
src/macro-core/macro-dock.hpp
|
src/macro-core/macro-dock.hpp
|
||||||
|
src/macro-core/macro-helpers.cpp
|
||||||
|
src/macro-core/macro-helpers.hpp
|
||||||
src/macro-core/macro-properties.cpp
|
src/macro-core/macro-properties.cpp
|
||||||
src/macro-core/macro-properties.hpp
|
src/macro-core/macro-properties.hpp
|
||||||
src/macro-core/macro-ref.cpp
|
src/macro-core/macro-ref.cpp
|
||||||
@@ -291,8 +297,8 @@ target_sources(
|
|||||||
src/utils/obs-module-helper.hpp
|
src/utils/obs-module-helper.hpp
|
||||||
src/utils/osc-helpers.cpp
|
src/utils/osc-helpers.cpp
|
||||||
src/utils/osc-helpers.hpp
|
src/utils/osc-helpers.hpp
|
||||||
src/utils/plugin-state-helper.cpp
|
src/utils/plugin-state-helpers.cpp
|
||||||
src/utils/plugin-state-helper.hpp
|
src/utils/plugin-state-helpers.hpp
|
||||||
src/utils/priority-helper.cpp
|
src/utils/priority-helper.cpp
|
||||||
src/utils/priority-helper.hpp
|
src/utils/priority-helper.hpp
|
||||||
src/utils/process-config.cpp
|
src/utils/process-config.cpp
|
||||||
@@ -323,8 +329,8 @@ target_sources(
|
|||||||
src/utils/striped-frame.hpp
|
src/utils/striped-frame.hpp
|
||||||
src/utils/switch-button.cpp
|
src/utils/switch-button.cpp
|
||||||
src/utils/switch-button.hpp
|
src/utils/switch-button.hpp
|
||||||
src/utils/sync-helper.cpp
|
src/utils/sync-helpers.cpp
|
||||||
src/utils/sync-helper.hpp
|
src/utils/sync-helpers.hpp
|
||||||
src/utils/temp-variable.cpp
|
src/utils/temp-variable.cpp
|
||||||
src/utils/temp-variable.hpp
|
src/utils/temp-variable.hpp
|
||||||
src/utils/transition-selection.cpp
|
src/utils/transition-selection.cpp
|
||||||
|
|||||||
@@ -152,11 +152,13 @@ AdvSceneSwitcher.condition.file.type.contentChange="Inhalt geändert"
|
|||||||
AdvSceneSwitcher.condition.file.type.dateChange="Änderungsdatum geändert"
|
AdvSceneSwitcher.condition.file.type.dateChange="Änderungsdatum geändert"
|
||||||
AdvSceneSwitcher.condition.file.remote="Entfernte Datei"
|
AdvSceneSwitcher.condition.file.remote="Entfernte Datei"
|
||||||
AdvSceneSwitcher.condition.file.local="Lokale Datei"
|
AdvSceneSwitcher.condition.file.local="Lokale Datei"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Medien"
|
AdvSceneSwitcher.condition.media="Medien"
|
||||||
AdvSceneSwitcher.condition.media.source="Quelle"
|
AdvSceneSwitcher.condition.media.source="Quelle"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle in"
|
AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle in"
|
||||||
AdvSceneSwitcher.condition.media.allOnScene="Alle Medienquellen in"
|
AdvSceneSwitcher.condition.media.allOnScene="Alle Medienquellen in"
|
||||||
AdvSceneSwitcher.condition.media.matchOnChange="Nur bei Änderung übereinstimmen (Hinweis: Diese Option wird in einer zukünftigen Version entfernt werden - bitte stattdessen Dauer-Modifikatoren verwenden)"
|
|
||||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="Leider verhalten sich nicht alle Medien-Quell-Typen gleich (z.B. Medien-Quelle vs. VLC-Video-Quelle \"Gestoppt\"-Status).\nBitte experimentieren, was in eurem Setup funktioniert!"
|
AdvSceneSwitcher.condition.media.inconsistencyInfo="Leider verhalten sich nicht alle Medien-Quell-Typen gleich (z.B. Medien-Quelle vs. VLC-Video-Quelle \"Gestoppt\"-Status).\nBitte experimentieren, was in eurem Setup funktioniert!"
|
||||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}Status ist{{states}}und{{timeRestrictions}}{{time}}"
|
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}Status ist{{states}}und{{timeRestrictions}}{{time}}"
|
||||||
AdvSceneSwitcher.condition.video="Video"
|
AdvSceneSwitcher.condition.video="Video"
|
||||||
@@ -571,7 +573,6 @@ AdvSceneSwitcher.action.variable.invalidSelection="Ungültige Auswahl!"
|
|||||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Aktionen wird nicht unterstützt!"
|
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Aktionen wird nicht unterstützt!"
|
||||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Bedingungen wird nicht unterstützt!"
|
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Bedingungen wird nicht unterstützt!"
|
||||||
AdvSceneSwitcher.action.variable.currentSegmentValue="Aktueller Wert:"
|
AdvSceneSwitcher.action.variable.currentSegmentValue="Aktueller Wert:"
|
||||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}"
|
|
||||||
|
|
||||||
|
|
||||||
; Transition Tab
|
; Transition Tab
|
||||||
|
|||||||
@@ -195,22 +195,18 @@ AdvSceneSwitcher.condition.window.entry.text="{{checkText}}Window contains text{
|
|||||||
AdvSceneSwitcher.condition.window.entry.text.note="This option might not work on every text being displayed in a window.\nIf that is the case, you can consider using the Video conditions OCR check instead."
|
AdvSceneSwitcher.condition.window.entry.text.note="This option might not work on every text being displayed in a window.\nIf that is the case, you can consider using the Video conditions OCR check instead."
|
||||||
AdvSceneSwitcher.condition.window.entry.currentFocus="Current focus window:{{focusWindow}}"
|
AdvSceneSwitcher.condition.window.entry.currentFocus="Current focus window:{{focusWindow}}"
|
||||||
AdvSceneSwitcher.condition.file="File"
|
AdvSceneSwitcher.condition.file="File"
|
||||||
AdvSceneSwitcher.condition.file.type.match="Matches"
|
AdvSceneSwitcher.condition.file.type.match="matches"
|
||||||
AdvSceneSwitcher.condition.file.type.contentChange="Content changed"
|
AdvSceneSwitcher.condition.file.type.contentChange="content changed"
|
||||||
AdvSceneSwitcher.condition.file.type.dateChange="Modification date changed"
|
AdvSceneSwitcher.condition.file.type.dateChange="modification date changed"
|
||||||
AdvSceneSwitcher.condition.file.type.changesMatch="Changed lines match"
|
|
||||||
AdvSceneSwitcher.condition.file.remote="Remote file"
|
AdvSceneSwitcher.condition.file.remote="Remote file"
|
||||||
AdvSceneSwitcher.condition.file.local="Local file"
|
AdvSceneSwitcher.condition.file.local="Local file"
|
||||||
AdvSceneSwitcher.condition.file.changeMatchType.any="Any lines"
|
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
AdvSceneSwitcher.condition.file.changeMatchType.added="Added lines"
|
|
||||||
AdvSceneSwitcher.condition.file.changeMatchType.removed="Removed lines"
|
|
||||||
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{changeMatchType}}{{useRegex}}"
|
|
||||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Media"
|
AdvSceneSwitcher.condition.media="Media"
|
||||||
AdvSceneSwitcher.condition.media.source="Source"
|
AdvSceneSwitcher.condition.media.source="Source"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="Any media source on"
|
AdvSceneSwitcher.condition.media.anyOnScene="Any media source on"
|
||||||
AdvSceneSwitcher.condition.media.allOnScene="All media sources on"
|
AdvSceneSwitcher.condition.media.allOnScene="All media sources on"
|
||||||
AdvSceneSwitcher.condition.media.matchOnChange="Only match on change (Note: This option will be removed in a future version - please use duration modifiers instead)"
|
|
||||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="Unfortunately not all media source types behave the same (e.g. Media Source vs. VLC Video Source \"Stopped\" state).\nSo please experiment what works for your setup!"
|
AdvSceneSwitcher.condition.media.inconsistencyInfo="Unfortunately not all media source types behave the same (e.g. Media Source vs. VLC Video Source \"Stopped\" state).\nSo please experiment what works for your setup!"
|
||||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}state is{{states}}and{{timeRestrictions}}{{time}}"
|
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}state is{{states}}and{{timeRestrictions}}{{time}}"
|
||||||
AdvSceneSwitcher.condition.video="Video"
|
AdvSceneSwitcher.condition.video="Video"
|
||||||
@@ -613,6 +609,7 @@ AdvSceneSwitcher.action.streaming.type.username="Set username"
|
|||||||
AdvSceneSwitcher.action.streaming.type.password="Set password"
|
AdvSceneSwitcher.action.streaming.type.password="Set password"
|
||||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||||
AdvSceneSwitcher.action.run="Run"
|
AdvSceneSwitcher.action.run="Run"
|
||||||
|
AdvSceneSwitcher.action.run.entry.wait="{{wait}}Wait for process exit or at most {{timeout}}"
|
||||||
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
||||||
@@ -823,6 +820,7 @@ AdvSceneSwitcher.action.variable.type.sceneItemCount="Set to scene item count of
|
|||||||
AdvSceneSwitcher.action.variable.type.stringLength="Set to length of string"
|
AdvSceneSwitcher.action.variable.type.stringLength="Set to length of string"
|
||||||
AdvSceneSwitcher.action.variable.type.extractJson="Extract json field with name"
|
AdvSceneSwitcher.action.variable.type.extractJson="Extract json field with name"
|
||||||
AdvSceneSwitcher.action.variable.type.setToTempvar="Set to macro property"
|
AdvSceneSwitcher.action.variable.type.setToTempvar="Set to macro property"
|
||||||
|
AdvSceneSwitcher.action.variable.type.sceneItemName="Set to scene item name at index"
|
||||||
AdvSceneSwitcher.action.variable.askForValuePromptDefault="Assign value to variable \"%1\":"
|
AdvSceneSwitcher.action.variable.askForValuePromptDefault="Assign value to variable \"%1\":"
|
||||||
AdvSceneSwitcher.action.variable.askForValuePrompt="Assign value to variable:"
|
AdvSceneSwitcher.action.variable.askForValuePrompt="Assign value to variable:"
|
||||||
AdvSceneSwitcher.action.variable.mathExpression.example="( 1 + 2 * 3 ) / 4"
|
AdvSceneSwitcher.action.variable.mathExpression.example="( 1 + 2 * 3 ) / 4"
|
||||||
@@ -834,7 +832,7 @@ AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
|
|||||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!"
|
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!"
|
||||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!"
|
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!"
|
||||||
AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:"
|
AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:"
|
||||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}"
|
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{sceneItemIndex}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}}Substring size:{{subStringSize}}"
|
AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}}Substring size:{{subStringSize}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.substringRegex="Assign value of{{regexMatchIdx}}match using regular expression:"
|
AdvSceneSwitcher.action.variable.entry.substringRegex="Assign value of{{regexMatchIdx}}match using regular expression:"
|
||||||
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}"
|
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}"
|
||||||
@@ -1296,9 +1294,9 @@ AdvSceneSwitcher.tempVar.twitch.started_at.shoutoutReceived="Shoutout time"
|
|||||||
AdvSceneSwitcher.tempVar.twitch.started_at.shoutoutReceived.description="The UTC timestamp (in RFC3339 format) of when the moderator sent the Shoutout."
|
AdvSceneSwitcher.tempVar.twitch.started_at.shoutoutReceived.description="The UTC timestamp (in RFC3339 format) of when the moderator sent the Shoutout."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.id.reward="Reward id"
|
AdvSceneSwitcher.tempVar.twitch.id.reward="Reward id"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.reward="User id redeeming reward"
|
AdvSceneSwitcher.tempVar.twitch.user_id.reward="User id redeeming the reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.reward="User login redeeming reward"
|
AdvSceneSwitcher.tempVar.twitch.user_login.reward="User login redeeming the reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.reward="User login redeeming reward"
|
AdvSceneSwitcher.tempVar.twitch.user_name.reward="User name redeeming the reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_input.reward="User input for reward"
|
AdvSceneSwitcher.tempVar.twitch.user_input.reward="User input for reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.reward.reward="Reward Information"
|
AdvSceneSwitcher.tempVar.twitch.reward.reward="Reward Information"
|
||||||
AdvSceneSwitcher.tempVar.twitch.reward.reward.description="Basic information about the reward that was redeemed, at the time it was redeemed."
|
AdvSceneSwitcher.tempVar.twitch.reward.reward.description="Basic information about the reward that was redeemed, at the time it was redeemed."
|
||||||
|
|||||||
@@ -123,10 +123,12 @@ AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}
|
|||||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||||
AdvSceneSwitcher.condition.window="Ventana"
|
AdvSceneSwitcher.condition.window="Ventana"
|
||||||
AdvSceneSwitcher.condition.file="Archivo"
|
AdvSceneSwitcher.condition.file="Archivo"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line1="Contenido de{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Medios"
|
AdvSceneSwitcher.condition.media="Medios"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="Cualquier fuente multimedia activada"
|
AdvSceneSwitcher.condition.media.anyOnScene="Cualquier fuente multimedia activada"
|
||||||
AdvSceneSwitcher.condition.media.allOnScene="Todas las fuentes de medios activadas"
|
AdvSceneSwitcher.condition.media.allOnScene="Todas las fuentes de medios activadas"
|
||||||
AdvSceneSwitcher.condition.media.matchOnChange="Solo coincidir con el cambio (Nota: esta opción se eliminará en una versión futura; use modificadores de duración en su lugar)"
|
|
||||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="Desafortunadamente, no todos los tipos de fuentes de medios se comportan de la misma manera (p. ej., fuente de medios frente a estado \"Detenido\" de fuente de video VLC).\n¡Así que experimente lo que funciona para su configuración!"
|
AdvSceneSwitcher.condition.media.inconsistencyInfo="Desafortunadamente, no todos los tipos de fuentes de medios se comportan de la misma manera (p. ej., fuente de medios frente a estado \"Detenido\" de fuente de video VLC).\n¡Así que experimente lo que funciona para su configuración!"
|
||||||
AdvSceneSwitcher.condition.media.entry="El estado de{{sourceTypes}}{{mediaSources}}{{scenes}}es{{states}}y{{timeRestrictions}}{{time}}"
|
AdvSceneSwitcher.condition.media.entry="El estado de{{sourceTypes}}{{mediaSources}}{{scenes}}es{{states}}y{{timeRestrictions}}{{time}}"
|
||||||
AdvSceneSwitcher.condition.video="Video"
|
AdvSceneSwitcher.condition.video="Video"
|
||||||
|
|||||||
@@ -197,7 +197,6 @@ AdvSceneSwitcher.condition.media="Média"
|
|||||||
AdvSceneSwitcher.condition.media.source="Source"
|
AdvSceneSwitcher.condition.media.source="Source"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="Toute source média sur la scène"
|
AdvSceneSwitcher.condition.media.anyOnScene="Toute source média sur la scène"
|
||||||
AdvSceneSwitcher.condition.media.allOnScene="Toutes les sources média sur la scène"
|
AdvSceneSwitcher.condition.media.allOnScene="Toutes les sources média sur la scène"
|
||||||
AdvSceneSwitcher.condition.media.matchOnChange="Ne correspondre qu'au changement (Remarque : Cette option sera supprimée dans une version future - veuillez plutôt utiliser les modificateurs de durée)"
|
|
||||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="Malheureusement, toutes les sources média ne se comportent pas de la même manière (par exemple, l'état \"Arrêté\" de la source Media par rapport à la source Vidéo VLC).\nPar conséquent, veuillez expérimenter ce qui fonctionne le mieux pour votre configuration !"
|
AdvSceneSwitcher.condition.media.inconsistencyInfo="Malheureusement, toutes les sources média ne se comportent pas de la même manière (par exemple, l'état \"Arrêté\" de la source Media par rapport à la source Vidéo VLC).\nPar conséquent, veuillez expérimenter ce qui fonctionne le mieux pour votre configuration !"
|
||||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}l'état est{{states}}et{{timeRestrictions}}{{time}}"
|
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}l'état est{{states}}et{{timeRestrictions}}{{time}}"
|
||||||
AdvSceneSwitcher.condition.video="Vidéo"
|
AdvSceneSwitcher.condition.video="Vidéo"
|
||||||
@@ -740,7 +739,6 @@ AdvSceneSwitcher.action.twitch.type.channel.info.title.set="Définir le titre du
|
|||||||
AdvSceneSwitcher.action.twitch.type.channel.info.category.set="Définir la catégorie du flux"
|
AdvSceneSwitcher.action.twitch.type.channel.info.category.set="Définir la catégorie du flux"
|
||||||
AdvSceneSwitcher.action.twitch.type.commercial.start="Démarrer une publicité d'une durée de"
|
AdvSceneSwitcher.action.twitch.type.commercial.start="Démarrer une publicité d'une durée de"
|
||||||
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="Impossible de sélectionner une catégorie sans avoir d'abord sélectionné un compte Twitch !"
|
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="Impossible de sélectionner une catégorie sans avoir d'abord sélectionné un compte Twitch !"
|
||||||
AdvSceneSwitcher.action.twitch.entry.line1="Sur{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{channel}}"
|
|
||||||
|
|
||||||
; Transition Tab
|
; Transition Tab
|
||||||
AdvSceneSwitcher.transitionTab.title="Transition"
|
AdvSceneSwitcher.transitionTab.title="Transition"
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ AdvSceneSwitcher.condition.scene.type.current="Текущий"
|
|||||||
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
|
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
|
||||||
AdvSceneSwitcher.condition.window="Окно"
|
AdvSceneSwitcher.condition.window="Окно"
|
||||||
AdvSceneSwitcher.condition.file="Файл"
|
AdvSceneSwitcher.condition.file="Файл"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Медиа"
|
AdvSceneSwitcher.condition.media="Медиа"
|
||||||
AdvSceneSwitcher.condition.video="Видео"
|
AdvSceneSwitcher.condition.video="Видео"
|
||||||
AdvSceneSwitcher.condition.video.condition.match="точно соответствует"
|
AdvSceneSwitcher.condition.video.condition.match="точно соответствует"
|
||||||
|
|||||||
@@ -113,10 +113,12 @@ AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}
|
|||||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||||
AdvSceneSwitcher.condition.window="Pencere"
|
AdvSceneSwitcher.condition.window="Pencere"
|
||||||
AdvSceneSwitcher.condition.file="Dosya"
|
AdvSceneSwitcher.condition.file="Dosya"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line1="İçerik{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Medya"
|
AdvSceneSwitcher.condition.media="Medya"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="Herhangi bir medya kaynağı"
|
AdvSceneSwitcher.condition.media.anyOnScene="Herhangi bir medya kaynağı"
|
||||||
AdvSceneSwitcher.condition.media.allOnScene="Tüm medya kaynakları "
|
AdvSceneSwitcher.condition.media.allOnScene="Tüm medya kaynakları "
|
||||||
AdvSceneSwitcher.condition.media.matchOnChange="Yalnızca değişiklikle eşleştirin (Not: Bu seçenek gelecekteki bir sürümde kaldırılacaktır - lütfen bunun yerine zaman kısıtlamalarını kullanın)"
|
|
||||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}durumu{{states}}ve{{timeRestrictions}}{{time}}"
|
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}durumu{{states}}ve{{timeRestrictions}}{{time}}"
|
||||||
AdvSceneSwitcher.condition.video="Video"
|
AdvSceneSwitcher.condition.video="Video"
|
||||||
AdvSceneSwitcher.condition.video.condition.match="Tam olarak eşleşir"
|
AdvSceneSwitcher.condition.video.condition.match="Tam olarak eşleşir"
|
||||||
|
|||||||
@@ -178,11 +178,13 @@ AdvSceneSwitcher.condition.file.type.contentChange="内容已更改"
|
|||||||
AdvSceneSwitcher.condition.file.type.dateChange="修改日期已更改"
|
AdvSceneSwitcher.condition.file.type.dateChange="修改日期已更改"
|
||||||
AdvSceneSwitcher.condition.file.remote="远程文件"
|
AdvSceneSwitcher.condition.file.remote="远程文件"
|
||||||
AdvSceneSwitcher.condition.file.local="本地文件"
|
AdvSceneSwitcher.condition.file.local="本地文件"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="媒体"
|
AdvSceneSwitcher.condition.media="媒体"
|
||||||
AdvSceneSwitcher.condition.media.source="源"
|
AdvSceneSwitcher.condition.media.source="源"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="任何媒体源"
|
AdvSceneSwitcher.condition.media.anyOnScene="任何媒体源"
|
||||||
AdvSceneSwitcher.condition.media.allOnScene="所有媒体源"
|
AdvSceneSwitcher.condition.media.allOnScene="所有媒体源"
|
||||||
AdvSceneSwitcher.condition.media.matchOnChange="仅在更改时匹配(注意:此选项将在未来版本中删除-请改用时间限制)"
|
|
||||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="不幸的是,并非所有媒体源类型的行为都相同(例如,媒体源与VLC视频源“停止”状态)。\n所以,请尝试适合您的设置!"
|
AdvSceneSwitcher.condition.media.inconsistencyInfo="不幸的是,并非所有媒体源类型的行为都相同(例如,媒体源与VLC视频源“停止”状态)。\n所以,请尝试适合您的设置!"
|
||||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}} 的状态是 {{states}} 和 {{timeRestrictions}}{{time}}"
|
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}} 的状态是 {{states}} 和 {{timeRestrictions}}{{time}}"
|
||||||
AdvSceneSwitcher.condition.video="视频"
|
AdvSceneSwitcher.condition.video="视频"
|
||||||
@@ -647,7 +649,6 @@ AdvSceneSwitcher.action.variable.invalidSelection="无效选择!"
|
|||||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="不支持从 %1 个操作获取变量值!"
|
AdvSceneSwitcher.action.variable.actionNoVariableSupport="不支持从 %1 个操作获取变量值!"
|
||||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="不支持从 %1 条件中获取变量值!"
|
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="不支持从 %1 条件中获取变量值!"
|
||||||
AdvSceneSwitcher.action.variable.currentSegmentValue="当前值:"
|
AdvSceneSwitcher.action.variable.currentSegmentValue="当前值:"
|
||||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}"
|
|
||||||
AdvSceneSwitcher.action.variable.entry.substringIndex="子字符串开始:{{subStringStart}} 子字符串大小:{{subStringSize}}"
|
AdvSceneSwitcher.action.variable.entry.substringIndex="子字符串开始:{{subStringStart}} 子字符串大小:{{subStringSize}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.substringRegex="使用正则表达式为 {{regexMatchIdx}} 匹配的值:"
|
AdvSceneSwitcher.action.variable.entry.substringRegex="使用正则表达式为 {{regexMatchIdx}} 匹配的值:"
|
||||||
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}"
|
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}"
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
<string notr="true">ms</string>
|
<string notr="true">ms</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>50</number>
|
<number>10</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>20000</number>
|
<number>20000</number>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "switcher-data.hpp"
|
||||||
|
#include "macro-helpers.hpp"
|
||||||
#include "status-control.hpp"
|
#include "status-control.hpp"
|
||||||
#include "scene-switch-helpers.hpp"
|
#include "scene-switch-helpers.hpp"
|
||||||
#include "curl-helper.hpp"
|
#include "curl-helper.hpp"
|
||||||
@@ -10,6 +11,7 @@
|
|||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QTextStream>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@@ -135,7 +137,7 @@ bool AdvSceneSwitcher::eventFilter(QObject *obj, QEvent *event)
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Saving and loading
|
* Saving and loading
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
static void AskForBackup(obs_data_t *obj);
|
static void AskForBackup(const QString &json);
|
||||||
|
|
||||||
static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
||||||
{
|
{
|
||||||
@@ -156,16 +158,25 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||||||
switcher->Stop();
|
switcher->Stop();
|
||||||
|
|
||||||
switcher->m.lock();
|
switcher->m.lock();
|
||||||
obs_data_t *obj =
|
OBSDataAutoRelease obj =
|
||||||
obs_data_get_obj(save_data, "advanced-scene-switcher");
|
obs_data_get_obj(save_data, "advanced-scene-switcher");
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
obj = obs_data_create();
|
obj = obs_data_create();
|
||||||
}
|
}
|
||||||
if (switcher->VersionChanged(obj, g_GIT_SHA1)) {
|
if (switcher->VersionChanged(obj, g_GIT_SHA1)) {
|
||||||
AskForBackup(obj);
|
auto json = obs_data_get_json(obj);
|
||||||
|
static QString jsonQString = json ? json : "";
|
||||||
|
std::thread t([]() {
|
||||||
|
obs_queue_task(
|
||||||
|
OBS_TASK_UI,
|
||||||
|
[](void *) {
|
||||||
|
AskForBackup(jsonQString);
|
||||||
|
},
|
||||||
|
nullptr, false);
|
||||||
|
});
|
||||||
|
t.detach();
|
||||||
}
|
}
|
||||||
switcher->LoadSettings(obj);
|
switcher->LoadSettings(obj);
|
||||||
obs_data_release(obj);
|
|
||||||
switcher->m.unlock();
|
switcher->m.unlock();
|
||||||
|
|
||||||
if (!switcher->stop) {
|
if (!switcher->stop) {
|
||||||
@@ -174,12 +185,12 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AskForBackup(obs_data_t *obj)
|
static void AskForBackup(const QString &json)
|
||||||
{
|
{
|
||||||
bool backupSettings = DisplayMessage(
|
const bool backupWasConfirmed = DisplayMessage(
|
||||||
obs_module_text("AdvSceneSwitcher.askBackup"), true);
|
obs_module_text("AdvSceneSwitcher.askBackup"), true, false);
|
||||||
|
|
||||||
if (!backupSettings) {
|
if (!backupWasConfirmed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,8 +209,8 @@ static void AskForBackup(obs_data_t *obj)
|
|||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto out = QTextStream(&file);
|
||||||
obs_data_save_json(obj, file.fileName().toUtf8().constData());
|
out << json;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@@ -226,7 +237,6 @@ void SwitcherData::Thread()
|
|||||||
// if a longer transition is used than the configured check interval
|
// if a longer transition is used than the configured check interval
|
||||||
bool setPrevSceneAfterLinger = false;
|
bool setPrevSceneAfterLinger = false;
|
||||||
bool macroMatch = false;
|
bool macroMatch = false;
|
||||||
macroSceneSwitched = false;
|
|
||||||
endTime = std::chrono::high_resolution_clock::now();
|
endTime = std::chrono::high_resolution_clock::now();
|
||||||
auto runTime =
|
auto runTime =
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
@@ -337,12 +347,6 @@ void SwitcherData::SetPreconditions()
|
|||||||
// Process name
|
// Process name
|
||||||
GetForegroundProcessName(currentForegroundProcess);
|
GetForegroundProcessName(currentForegroundProcess);
|
||||||
|
|
||||||
// Cursor
|
|
||||||
std::pair<int, int> cursorPos = GetCursorPos();
|
|
||||||
cursorPosChanged = cursorPos.first != switcher->lastCursorPos.first ||
|
|
||||||
cursorPos.second != switcher->lastCursorPos.second;
|
|
||||||
lastCursorPos = GetCursorPos();
|
|
||||||
|
|
||||||
// Macro
|
// Macro
|
||||||
InvalidateMacroTempVarValues();
|
InvalidateMacroTempVarValues();
|
||||||
}
|
}
|
||||||
@@ -424,7 +428,7 @@ bool SwitcherData::CheckForMatch(OBSWeakSource &scene,
|
|||||||
|
|
||||||
static void ResetMacros()
|
static void ResetMacros()
|
||||||
{
|
{
|
||||||
for (auto &m : switcher->macros) {
|
for (auto &m : GetMacros()) {
|
||||||
m->ResetRunCount();
|
m->ResetRunCount();
|
||||||
m->ResetTimers();
|
m->ResetTimers();
|
||||||
}
|
}
|
||||||
@@ -467,9 +471,9 @@ void SwitcherData::Stop()
|
|||||||
if (th && th->isRunning()) {
|
if (th && th->isRunning()) {
|
||||||
stop = true;
|
stop = true;
|
||||||
cv.notify_all();
|
cv.notify_all();
|
||||||
abortMacroWait = true;
|
SetMacroAbortWait(true);
|
||||||
macroWaitCv.notify_all();
|
GetMacroWaitCV().notify_all();
|
||||||
macroTransitionCv.notify_all();
|
GetMacroTransitionCV().notify_all();
|
||||||
|
|
||||||
// Not waiting if a dialog was closed is a workaround to avoid
|
// Not waiting if a dialog was closed is a workaround to avoid
|
||||||
// deadlocks when a variable input dialog is opened while Stop()
|
// deadlocks when a variable input dialog is opened while Stop()
|
||||||
@@ -542,9 +546,6 @@ extern "C" void FreeSceneSwitcher()
|
|||||||
|
|
||||||
static void handleSceneChange()
|
static void handleSceneChange()
|
||||||
{
|
{
|
||||||
switcher->lastSceneChangeTime =
|
|
||||||
std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
// Stop waiting if scene was changed
|
// Stop waiting if scene was changed
|
||||||
if (switcher->SceneChangedDuringWait()) {
|
if (switcher->SceneChangedDuringWait()) {
|
||||||
switcher->cv.notify_one();
|
switcher->cv.notify_one();
|
||||||
@@ -611,28 +612,9 @@ static void handlePeviewSceneChange()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setReplayBufferSaved()
|
static void handleTransitionEnd()
|
||||||
{
|
{
|
||||||
switcher->replayBufferSaved = true;
|
GetMacroTransitionCV().notify_all();
|
||||||
}
|
|
||||||
|
|
||||||
static void setTranstionEnd()
|
|
||||||
{
|
|
||||||
switcher->lastTransitionEndTime =
|
|
||||||
std::chrono::high_resolution_clock::now();
|
|
||||||
switcher->macroTransitionCv.notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setStreamStarting()
|
|
||||||
{
|
|
||||||
switcher->lastStreamStartingTime =
|
|
||||||
std::chrono::high_resolution_clock::now();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setStreamStopping()
|
|
||||||
{
|
|
||||||
switcher->lastStreamStoppingTime =
|
|
||||||
std::chrono::high_resolution_clock::now();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleShutdown()
|
static void handleShutdown()
|
||||||
@@ -641,10 +623,10 @@ static void handleShutdown()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switcher->obsIsShuttingDown = true;
|
switcher->obsIsShuttingDown = true;
|
||||||
if (switcher->shutdownConditionCount) {
|
if (ShutdownCheckIsNecessary()) {
|
||||||
switcher->Stop();
|
switcher->Stop();
|
||||||
switcher->CheckMacros();
|
CheckMacros();
|
||||||
switcher->RunMacros();
|
RunMacros();
|
||||||
|
|
||||||
// Unfortunately this will not work as OBS will now allow saving
|
// Unfortunately this will not work as OBS will now allow saving
|
||||||
// the scene collection data at this point, So any OBS specific
|
// the scene collection data at this point, So any OBS specific
|
||||||
@@ -701,19 +683,8 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
|||||||
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
|
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
|
||||||
resetLiveTime();
|
resetLiveTime();
|
||||||
break;
|
break;
|
||||||
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(26, 0, 0)
|
|
||||||
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
|
|
||||||
setReplayBufferSaved();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case OBS_FRONTEND_EVENT_TRANSITION_STOPPED:
|
case OBS_FRONTEND_EVENT_TRANSITION_STOPPED:
|
||||||
setTranstionEnd();
|
handleTransitionEnd();
|
||||||
break;
|
|
||||||
case OBS_FRONTEND_EVENT_STREAMING_STARTING:
|
|
||||||
setStreamStarting();
|
|
||||||
break;
|
|
||||||
case OBS_FRONTEND_EVENT_STREAMING_STOPPING:
|
|
||||||
setStreamStopping();
|
|
||||||
break;
|
break;
|
||||||
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(27, 2, 0)
|
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(27, 2, 0)
|
||||||
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING:
|
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "status-control.hpp"
|
#include "status-control.hpp"
|
||||||
#include "file-selection.hpp"
|
#include "file-selection.hpp"
|
||||||
#include "filter-combo-box.hpp"
|
#include "filter-combo-box.hpp"
|
||||||
|
#include "variable.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
@@ -512,6 +513,7 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LoadMacros(obj);
|
LoadMacros(obj);
|
||||||
|
LoadGlobalMacroProperties(obj);
|
||||||
loadWindowTitleSwitches(obj);
|
loadWindowTitleSwitches(obj);
|
||||||
loadScreenRegionSwitches(obj);
|
loadScreenRegionSwitches(obj);
|
||||||
loadPauseSwitches(obj);
|
loadPauseSwitches(obj);
|
||||||
@@ -548,6 +550,7 @@ void SwitcherData::SaveSettings(obs_data_t *obj)
|
|||||||
|
|
||||||
saveSceneGroups(obj);
|
saveSceneGroups(obj);
|
||||||
SaveMacros(obj);
|
SaveMacros(obj);
|
||||||
|
SaveGlobalMacroProperties(obj);
|
||||||
SaveVariables(obj);
|
SaveVariables(obj);
|
||||||
saveWindowTitleSwitches(obj);
|
saveWindowTitleSwitches(obj);
|
||||||
saveScreenRegionSwitches(obj);
|
saveScreenRegionSwitches(obj);
|
||||||
|
|||||||
@@ -160,7 +160,9 @@ enum class HotkeyType {
|
|||||||
Key_NumpadMultiply,
|
Key_NumpadMultiply,
|
||||||
Key_NumpadDivide,
|
Key_NumpadDivide,
|
||||||
Key_NumpadDecimal,
|
Key_NumpadDecimal,
|
||||||
Key_NumpadEnter
|
Key_NumpadEnter,
|
||||||
|
|
||||||
|
Key_Tilde,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ namespace advss {
|
|||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
SceneGroupEditWidget *typeEdit = nullptr;
|
SceneGroupEditWidget *typeEdit = nullptr;
|
||||||
|
|
||||||
|
std::deque<SceneGroup> &GetSceneGroups()
|
||||||
|
{
|
||||||
|
return switcher->sceneGroups;
|
||||||
|
}
|
||||||
|
|
||||||
void SceneGroup::advanceIdx()
|
void SceneGroup::advanceIdx()
|
||||||
{
|
{
|
||||||
currentIdx++;
|
currentIdx++;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <deque>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
@@ -87,5 +87,6 @@ private:
|
|||||||
|
|
||||||
SceneGroup *GetSceneGroupByName(const char *name);
|
SceneGroup *GetSceneGroupByName(const char *name);
|
||||||
SceneGroup *GetSceneGroupByQString(const QString &name);
|
SceneGroup *GetSceneGroupByQString(const QString &name);
|
||||||
|
std::deque<SceneGroup> &GetSceneGroups();
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -177,17 +177,17 @@ static std::string getRemoteData(std::string &url)
|
|||||||
{
|
{
|
||||||
std::string readBuffer;
|
std::string readBuffer;
|
||||||
|
|
||||||
switcher->curl.SetOpt(CURLOPT_URL, url.c_str());
|
CurlHelper::SetOpt(CURLOPT_URL, url.c_str());
|
||||||
switcher->curl.SetOpt(CURLOPT_WRITEFUNCTION, WriteCallback);
|
CurlHelper::SetOpt(CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||||
switcher->curl.SetOpt(CURLOPT_WRITEDATA, &readBuffer);
|
CurlHelper::SetOpt(CURLOPT_WRITEDATA, &readBuffer);
|
||||||
|
|
||||||
// Set timeout to at least one second
|
// Set timeout to at least one second
|
||||||
int timeout = switcher->interval / 1000;
|
int timeout = switcher->interval / 1000;
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
timeout = 1;
|
timeout = 1;
|
||||||
}
|
}
|
||||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT, 1);
|
CurlHelper::SetOpt(CURLOPT_TIMEOUT, 1);
|
||||||
switcher->curl.Perform();
|
CurlHelper::Perform();
|
||||||
|
|
||||||
return readBuffer;
|
return readBuffer;
|
||||||
}
|
}
|
||||||
@@ -422,7 +422,7 @@ void AdvSceneSwitcher::SetupFileTab()
|
|||||||
obs_module_text("AdvSceneSwitcher.fileTab.remoteFileWarning2"));
|
obs_module_text("AdvSceneSwitcher.fileTab.remoteFileWarning2"));
|
||||||
ui->remoteFileWarningLabel->hide();
|
ui->remoteFileWarningLabel->hide();
|
||||||
|
|
||||||
if (switcher->curl.Initialized()) {
|
if (CurlHelper::Initialized()) {
|
||||||
ui->libcurlWarning->setVisible(false);
|
ui->libcurlWarning->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -555,6 +555,9 @@ static std::unordered_map<HotkeyType, long> keyTable = {
|
|||||||
{HotkeyType::Key_8, XK_8},
|
{HotkeyType::Key_8, XK_8},
|
||||||
{HotkeyType::Key_9, XK_9},
|
{HotkeyType::Key_9, XK_9},
|
||||||
|
|
||||||
|
// Other
|
||||||
|
{HotkeyType::Key_Tilde, XK_asciitilde},
|
||||||
|
|
||||||
{HotkeyType::Key_F1, XK_F1},
|
{HotkeyType::Key_F1, XK_F1},
|
||||||
{HotkeyType::Key_F2, XK_F2},
|
{HotkeyType::Key_F2, XK_F2},
|
||||||
{HotkeyType::Key_F3, XK_F3},
|
{HotkeyType::Key_F3, XK_F3},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "macro-action-audio.hpp"
|
#include "macro-action-audio.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "macro.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -36,6 +36,16 @@ const static std::map<MacroActionAudio::FadeType, std::string> fadeTypes = {
|
|||||||
"AdvSceneSwitcher.action.audio.fade.type.rate"},
|
"AdvSceneSwitcher.action.audio.fade.type.rate"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct FadeInfo {
|
||||||
|
std::atomic_bool active = {false};
|
||||||
|
std::atomic_int id = {0};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static FadeInfo masterAudioFade;
|
||||||
|
static std::unordered_map<std::string, FadeInfo> audioFades;
|
||||||
|
|
||||||
constexpr auto fadeInterval = std::chrono::milliseconds(100);
|
constexpr auto fadeInterval = std::chrono::milliseconds(100);
|
||||||
constexpr float minFade = 0.000001f;
|
constexpr float minFade = 0.000001f;
|
||||||
|
|
||||||
@@ -58,10 +68,9 @@ auto set_master_volume = obs_set_master_volume;
|
|||||||
void MacroActionAudio::SetFadeActive(bool value)
|
void MacroActionAudio::SetFadeActive(bool value)
|
||||||
{
|
{
|
||||||
if (_action == Action::SOURCE_VOLUME) {
|
if (_action == Action::SOURCE_VOLUME) {
|
||||||
switcher->activeAudioFades[_audioSource.ToString()].active =
|
audioFades[_audioSource.ToString()].active = value;
|
||||||
value;
|
|
||||||
} else {
|
} else {
|
||||||
switcher->masterAudioFade.active = value;
|
masterAudioFade.active = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,14 +78,13 @@ bool MacroActionAudio::FadeActive()
|
|||||||
{
|
{
|
||||||
bool active = true;
|
bool active = true;
|
||||||
if (_action == Action::SOURCE_VOLUME) {
|
if (_action == Action::SOURCE_VOLUME) {
|
||||||
auto it = switcher->activeAudioFades.find(
|
auto it = audioFades.find(_audioSource.ToString());
|
||||||
_audioSource.ToString());
|
if (it == audioFades.end()) {
|
||||||
if (it == switcher->activeAudioFades.end()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
active = it->second.active;
|
active = it->second.active;
|
||||||
} else {
|
} else {
|
||||||
active = switcher->masterAudioFade.active;
|
active = masterAudioFade.active;
|
||||||
}
|
}
|
||||||
|
|
||||||
return active;
|
return active;
|
||||||
@@ -86,14 +94,13 @@ std::atomic_int *MacroActionAudio::GetFadeIdPtr()
|
|||||||
{
|
{
|
||||||
|
|
||||||
if (_action == Action::SOURCE_VOLUME) {
|
if (_action == Action::SOURCE_VOLUME) {
|
||||||
auto it = switcher->activeAudioFades.find(
|
auto it = audioFades.find(_audioSource.ToString());
|
||||||
_audioSource.ToString());
|
if (it == audioFades.end()) {
|
||||||
if (it == switcher->activeAudioFades.end()) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &it->second.id;
|
return &it->second.id;
|
||||||
}
|
}
|
||||||
return &switcher->masterAudioFade.id;
|
return &masterAudioFade.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionAudio::SetVolume(float vol)
|
void MacroActionAudio::SetVolume(float vol)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "macro-action-clipboard.hpp"
|
#include "macro-action-clipboard.hpp"
|
||||||
#include "curl-helper.hpp"
|
#include "curl-helper.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
@@ -34,17 +33,17 @@ static std::optional<QImage> getImageFromUrl(const char *url)
|
|||||||
{
|
{
|
||||||
QByteArray response;
|
QByteArray response;
|
||||||
|
|
||||||
switcher->curl.SetOpt(CURLOPT_URL, url);
|
CurlHelper::SetOpt(CURLOPT_URL, url);
|
||||||
switcher->curl.SetOpt(CURLOPT_HTTPGET, 1L);
|
CurlHelper::SetOpt(CURLOPT_HTTPGET, 1L);
|
||||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, 30000);
|
CurlHelper::SetOpt(CURLOPT_TIMEOUT_MS, 30000);
|
||||||
switcher->curl.SetOpt(CURLOPT_WRITEFUNCTION, writeCallback);
|
CurlHelper::SetOpt(CURLOPT_WRITEFUNCTION, writeCallback);
|
||||||
switcher->curl.SetOpt(CURLOPT_WRITEDATA, &response);
|
CurlHelper::SetOpt(CURLOPT_WRITEDATA, &response);
|
||||||
auto code = switcher->curl.Perform();
|
auto code = CurlHelper::Perform();
|
||||||
|
|
||||||
if (code != CURLE_OK) {
|
if (code != CURLE_OK) {
|
||||||
blog(LOG_WARNING,
|
blog(LOG_WARNING,
|
||||||
"Retrieving image failed in %s with error: %s", __func__,
|
"Retrieving image failed in %s with error: %s", __func__,
|
||||||
switcher->curl.GetError(code));
|
CurlHelper::GetError(code));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "macro-helpers.hpp"
|
||||||
|
#include "macro.hpp"
|
||||||
|
#include "macro-properties.hpp"
|
||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "macro-action-scene-switch.hpp"
|
#include "macro-action-scene-switch.hpp"
|
||||||
#include "section.hpp"
|
#include "section.hpp"
|
||||||
#include "switch-button.hpp"
|
#include "switch-button.hpp"
|
||||||
@@ -10,61 +12,9 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
std::map<std::string, MacroActionInfo> &MacroActionFactory::GetMap()
|
|
||||||
{
|
|
||||||
static std::map<std::string, MacroActionInfo> _methods;
|
|
||||||
return _methods;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroActionFactory::Register(const std::string &id, MacroActionInfo info)
|
|
||||||
{
|
|
||||||
if (auto it = GetMap().find(id); it == GetMap().end()) {
|
|
||||||
GetMap()[id] = info;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<MacroAction> MacroActionFactory::Create(const std::string &id,
|
|
||||||
Macro *m)
|
|
||||||
{
|
|
||||||
if (auto it = GetMap().find(id); it != GetMap().end())
|
|
||||||
return it->second._createFunc(m);
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *MacroActionFactory::CreateWidget(const std::string &id,
|
|
||||||
QWidget *parent,
|
|
||||||
std::shared_ptr<MacroAction> action)
|
|
||||||
{
|
|
||||||
if (auto it = GetMap().find(id); it != GetMap().end())
|
|
||||||
return it->second._createWidgetFunc(parent, action);
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string MacroActionFactory::GetActionName(const std::string &id)
|
|
||||||
{
|
|
||||||
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
|
||||||
return it->second._name;
|
|
||||||
}
|
|
||||||
return "unknown action";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string MacroActionFactory::GetIdByName(const QString &name)
|
|
||||||
{
|
|
||||||
for (auto it : GetMap()) {
|
|
||||||
if (name == obs_module_text(it.second._name.c_str())) {
|
|
||||||
return it.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void populateActionSelection(QComboBox *list)
|
static inline void populateActionSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
for (auto &[_, action] : MacroActionFactory::GetActionTypes()) {
|
for (const auto &[_, action] : MacroActionFactory::GetActionTypes()) {
|
||||||
QString entry(obs_module_text(action._name.c_str()));
|
QString entry(obs_module_text(action._name.c_str()));
|
||||||
if (list->findText(entry) == -1) {
|
if (list->findText(entry) == -1) {
|
||||||
list->addItem(entry);
|
list->addItem(entry);
|
||||||
@@ -80,7 +30,8 @@ static inline void populateActionSelection(QComboBox *list)
|
|||||||
MacroActionEdit::MacroActionEdit(QWidget *parent,
|
MacroActionEdit::MacroActionEdit(QWidget *parent,
|
||||||
std::shared_ptr<MacroAction> *entryData,
|
std::shared_ptr<MacroAction> *entryData,
|
||||||
const std::string &id)
|
const std::string &id)
|
||||||
: MacroSegmentEdit(switcher->macroProperties._highlightActions, parent),
|
: MacroSegmentEdit(GetGlobalMacroProperties()._highlightActions,
|
||||||
|
parent),
|
||||||
_actionSelection(new FilterComboBox()),
|
_actionSelection(new FilterComboBox()),
|
||||||
_enable(new SwitchButton()),
|
_enable(new SwitchButton()),
|
||||||
_entryData(entryData)
|
_entryData(entryData)
|
||||||
@@ -134,7 +85,7 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
|
|||||||
auto idx = _entryData->get()->GetIndex();
|
auto idx = _entryData->get()->GetIndex();
|
||||||
auto macro = _entryData->get()->GetMacro();
|
auto macro = _entryData->get()->GetMacro();
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
_entryData->reset();
|
_entryData->reset();
|
||||||
*_entryData = MacroActionFactory::Create(id, macro);
|
*_entryData = MacroActionFactory::Create(id, macro);
|
||||||
(*_entryData)->SetIndex(idx);
|
(*_entryData)->SetIndex(idx);
|
||||||
@@ -185,7 +136,7 @@ void MacroActionEdit::ActionEnableChanged(bool value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
(*_entryData)->SetEnabled(value);
|
(*_entryData)->SetEnabled(value);
|
||||||
SetDisableEffect(!value);
|
SetDisableEffect(!value);
|
||||||
}
|
}
|
||||||
@@ -229,7 +180,7 @@ void AdvSceneSwitcher::AddMacroAction(int idx)
|
|||||||
id = temp.GetId();
|
id = temp.GetId();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
macro->Actions().emplace(
|
macro->Actions().emplace(
|
||||||
macro->Actions().begin() + idx,
|
macro->Actions().begin() + idx,
|
||||||
MacroActionFactory::Create(id, macro.get()));
|
MacroActionFactory::Create(id, macro.get()));
|
||||||
@@ -280,11 +231,11 @@ void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
ui->actionsList->Remove(idx);
|
ui->actionsList->Remove(idx);
|
||||||
macro->Actions().erase(macro->Actions().begin() + idx);
|
macro->Actions().erase(macro->Actions().begin() + idx);
|
||||||
switcher->abortMacroWait = true;
|
SetMacroAbortWait(true);
|
||||||
switcher->macroWaitCv.notify_all();
|
GetMacroWaitCV().notify_all();
|
||||||
macro->UpdateActionIndices();
|
macro->UpdateActionIndices();
|
||||||
SetActionData(*macro);
|
SetActionData(*macro);
|
||||||
}
|
}
|
||||||
@@ -425,7 +376,7 @@ void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
|
|||||||
std::swap(pos1, pos2);
|
std::swap(pos1, pos2);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
iter_swap(m->Actions().begin() + pos1, m->Actions().begin() + pos2);
|
iter_swap(m->Actions().begin() + pos1, m->Actions().begin() + pos2);
|
||||||
m->UpdateActionIndices();
|
m->UpdateActionIndices();
|
||||||
auto widget1 = static_cast<MacroActionEdit *>(
|
auto widget1 = static_cast<MacroActionEdit *>(
|
||||||
@@ -485,7 +436,7 @@ void AdvSceneSwitcher::MacroElseActionReorder(int to, int from)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
auto action = macro->ElseActions().at(from);
|
auto action = macro->ElseActions().at(from);
|
||||||
macro->ElseActions().erase(macro->ElseActions().begin() + from);
|
macro->ElseActions().erase(macro->ElseActions().begin() + from);
|
||||||
macro->ElseActions().insert(macro->ElseActions().begin() + to,
|
macro->ElseActions().insert(macro->ElseActions().begin() + to,
|
||||||
@@ -518,7 +469,7 @@ void AdvSceneSwitcher::AddMacroElseAction(int idx)
|
|||||||
id = temp.GetId();
|
id = temp.GetId();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
macro->ElseActions().emplace(
|
macro->ElseActions().emplace(
|
||||||
macro->ElseActions().begin() + idx,
|
macro->ElseActions().begin() + idx,
|
||||||
MacroActionFactory::Create(id, macro.get()));
|
MacroActionFactory::Create(id, macro.get()));
|
||||||
@@ -550,11 +501,11 @@ void AdvSceneSwitcher::RemoveMacroElseAction(int idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
ui->elseActionsList->Remove(idx);
|
ui->elseActionsList->Remove(idx);
|
||||||
macro->ElseActions().erase(macro->ElseActions().begin() + idx);
|
macro->ElseActions().erase(macro->ElseActions().begin() + idx);
|
||||||
switcher->abortMacroWait = true;
|
SetMacroAbortWait(true);
|
||||||
switcher->macroWaitCv.notify_all();
|
GetMacroWaitCV().notify_all();
|
||||||
macro->UpdateElseActionIndices();
|
macro->UpdateElseActionIndices();
|
||||||
SetActionData(*macro);
|
SetActionData(*macro);
|
||||||
}
|
}
|
||||||
@@ -572,7 +523,7 @@ void AdvSceneSwitcher::SwapElseActions(Macro *m, int pos1, int pos2)
|
|||||||
std::swap(pos1, pos2);
|
std::swap(pos1, pos2);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
iter_swap(m->ElseActions().begin() + pos1,
|
iter_swap(m->ElseActions().begin() + pos1,
|
||||||
m->ElseActions().begin() + pos2);
|
m->ElseActions().begin() + pos2);
|
||||||
m->UpdateElseActionIndices();
|
m->UpdateElseActionIndices();
|
||||||
@@ -635,7 +586,7 @@ void AdvSceneSwitcher::MacroActionReorder(int to, int from)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
auto action = macro->Actions().at(from);
|
auto action = macro->Actions().at(from);
|
||||||
macro->Actions().erase(macro->Actions().begin() + from);
|
macro->Actions().erase(macro->Actions().begin() + from);
|
||||||
macro->Actions().insert(macro->Actions().begin() + to, action);
|
macro->Actions().insert(macro->Actions().begin() + to, action);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-action.hpp"
|
#include "macro-action.hpp"
|
||||||
|
#include "macro-action-factory.hpp"
|
||||||
#include "filter-combo-box.hpp"
|
#include "filter-combo-box.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -8,32 +9,6 @@ namespace advss {
|
|||||||
|
|
||||||
class SwitchButton;
|
class SwitchButton;
|
||||||
|
|
||||||
struct MacroActionInfo {
|
|
||||||
using TCreateMethod = std::shared_ptr<MacroAction> (*)(Macro *m);
|
|
||||||
using TCreateWidgetMethod = QWidget *(*)(QWidget *parent,
|
|
||||||
std::shared_ptr<MacroAction>);
|
|
||||||
TCreateMethod _createFunc = nullptr;
|
|
||||||
TCreateWidgetMethod _createWidgetFunc = nullptr;
|
|
||||||
std::string _name;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MacroActionFactory {
|
|
||||||
public:
|
|
||||||
MacroActionFactory() = delete;
|
|
||||||
|
|
||||||
static bool Register(const std::string &id, MacroActionInfo);
|
|
||||||
static std::shared_ptr<MacroAction> Create(const std::string &id,
|
|
||||||
Macro *m);
|
|
||||||
static QWidget *CreateWidget(const std::string &id, QWidget *parent,
|
|
||||||
std::shared_ptr<MacroAction> action);
|
|
||||||
static auto GetActionTypes() { return GetMap(); }
|
|
||||||
static std::string GetActionName(const std::string &id);
|
|
||||||
static std::string GetIdByName(const QString &name);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::map<std::string, MacroActionInfo> &GetMap();
|
|
||||||
};
|
|
||||||
|
|
||||||
class MacroActionEdit : public MacroSegmentEdit {
|
class MacroActionEdit : public MacroSegmentEdit {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|||||||
57
src/macro-core/macro-action-factory.cpp
Normal file
57
src/macro-core/macro-action-factory.cpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include "macro-action-factory.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
std::map<std::string, MacroActionInfo> &MacroActionFactory::GetMap()
|
||||||
|
{
|
||||||
|
static std::map<std::string, MacroActionInfo> _methods;
|
||||||
|
return _methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionFactory::Register(const std::string &id, MacroActionInfo info)
|
||||||
|
{
|
||||||
|
if (auto it = GetMap().find(id); it == GetMap().end()) {
|
||||||
|
GetMap()[id] = info;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MacroAction> MacroActionFactory::Create(const std::string &id,
|
||||||
|
Macro *m)
|
||||||
|
{
|
||||||
|
if (auto it = GetMap().find(id); it != GetMap().end())
|
||||||
|
return it->second._create(m);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *MacroActionFactory::CreateWidget(const std::string &id,
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction> action)
|
||||||
|
{
|
||||||
|
if (auto it = GetMap().find(id); it != GetMap().end())
|
||||||
|
return it->second._createWidget(parent, action);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MacroActionFactory::GetActionName(const std::string &id)
|
||||||
|
{
|
||||||
|
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
||||||
|
return it->second._name;
|
||||||
|
}
|
||||||
|
return "unknown action";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MacroActionFactory::GetIdByName(const QString &name)
|
||||||
|
{
|
||||||
|
for (auto it : GetMap()) {
|
||||||
|
if (name == obs_module_text(it.second._name.c_str())) {
|
||||||
|
return it.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
34
src/macro-core/macro-action-factory.hpp
Normal file
34
src/macro-core/macro-action-factory.hpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-action.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
struct MacroActionInfo {
|
||||||
|
using CreateAction = std::shared_ptr<MacroAction> (*)(Macro *m);
|
||||||
|
using CreateActionWidget = QWidget *(*)(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction>);
|
||||||
|
CreateAction _create = nullptr;
|
||||||
|
CreateActionWidget _createWidget = nullptr;
|
||||||
|
std::string _name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroActionFactory {
|
||||||
|
public:
|
||||||
|
MacroActionFactory() = delete;
|
||||||
|
|
||||||
|
static bool Register(const std::string &id, MacroActionInfo);
|
||||||
|
static std::shared_ptr<MacroAction> Create(const std::string &id,
|
||||||
|
Macro *m);
|
||||||
|
static QWidget *CreateWidget(const std::string &id, QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction> action);
|
||||||
|
static auto GetActionTypes() { return GetMap(); }
|
||||||
|
static std::string GetActionName(const std::string &id);
|
||||||
|
static std::string GetIdByName(const QString &name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::map<std::string, MacroActionInfo> &GetMap();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -14,14 +14,14 @@ bool MacroActionHotkey::_registered = MacroActionFactory::Register(
|
|||||||
{MacroActionHotkey::Create, MacroActionHotkeyEdit::Create,
|
{MacroActionHotkey::Create, MacroActionHotkeyEdit::Create,
|
||||||
"AdvSceneSwitcher.action.hotkey"});
|
"AdvSceneSwitcher.action.hotkey"});
|
||||||
|
|
||||||
const static std::map<MacroActionHotkey::Action, std::string> actionTypes = {
|
static const std::map<MacroActionHotkey::Action, std::string> actionTypes = {
|
||||||
{MacroActionHotkey::Action::OBS_HOTKEY,
|
{MacroActionHotkey::Action::OBS_HOTKEY,
|
||||||
"AdvSceneSwitcher.action.hotkey.type.obs"},
|
"AdvSceneSwitcher.action.hotkey.type.obs"},
|
||||||
{MacroActionHotkey::Action::CUSTOM,
|
{MacroActionHotkey::Action::CUSTOM,
|
||||||
"AdvSceneSwitcher.action.hotkey.type.custom"},
|
"AdvSceneSwitcher.action.hotkey.type.custom"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const static std::map<obs_hotkey_registerer_type, std::string> hotkeyTypes = {
|
static const std::map<obs_hotkey_registerer_type, std::string> hotkeyTypes = {
|
||||||
{OBS_HOTKEY_REGISTERER_FRONTEND,
|
{OBS_HOTKEY_REGISTERER_FRONTEND,
|
||||||
"AdvSceneSwitcher.action.hotkey.type.obs.type.frontend"},
|
"AdvSceneSwitcher.action.hotkey.type.obs.type.frontend"},
|
||||||
{OBS_HOTKEY_REGISTERER_SOURCE,
|
{OBS_HOTKEY_REGISTERER_SOURCE,
|
||||||
@@ -34,7 +34,7 @@ const static std::map<obs_hotkey_registerer_type, std::string> hotkeyTypes = {
|
|||||||
"AdvSceneSwitcher.action.hotkey.type.obs.type.service"},
|
"AdvSceneSwitcher.action.hotkey.type.obs.type.service"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::unordered_map<HotkeyType, long> keyTable = {
|
static const std::unordered_map<HotkeyType, long> keyTable = {
|
||||||
// Chars
|
// Chars
|
||||||
{HotkeyType::Key_A, OBS_KEY_A},
|
{HotkeyType::Key_A, OBS_KEY_A},
|
||||||
{HotkeyType::Key_B, OBS_KEY_B},
|
{HotkeyType::Key_B, OBS_KEY_B},
|
||||||
@@ -75,6 +75,9 @@ static std::unordered_map<HotkeyType, long> keyTable = {
|
|||||||
{HotkeyType::Key_8, OBS_KEY_8},
|
{HotkeyType::Key_8, OBS_KEY_8},
|
||||||
{HotkeyType::Key_9, OBS_KEY_9},
|
{HotkeyType::Key_9, OBS_KEY_9},
|
||||||
|
|
||||||
|
// Other
|
||||||
|
{HotkeyType::Key_Tilde, OBS_KEY_ASCIITILDE},
|
||||||
|
|
||||||
{HotkeyType::Key_F1, OBS_KEY_F1},
|
{HotkeyType::Key_F1, OBS_KEY_F1},
|
||||||
{HotkeyType::Key_F2, OBS_KEY_F2},
|
{HotkeyType::Key_F2, OBS_KEY_F2},
|
||||||
{HotkeyType::Key_F3, OBS_KEY_F3},
|
{HotkeyType::Key_F3, OBS_KEY_F3},
|
||||||
@@ -525,6 +528,7 @@ static inline void populateKeySelection(QComboBox *list)
|
|||||||
list->addItem("NumpadDivide");
|
list->addItem("NumpadDivide");
|
||||||
list->addItem("NumpadDecimal");
|
list->addItem("NumpadDecimal");
|
||||||
list->addItem("NumpadEnter");
|
list->addItem("NumpadEnter");
|
||||||
|
list->addItem("Tilde");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void populateActionSelection(QComboBox *list)
|
static void populateActionSelection(QComboBox *list)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "macro-action-http.hpp"
|
#include "macro-action-http.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "curl-helper.hpp"
|
#include "curl-helper.hpp"
|
||||||
|
|
||||||
@@ -36,44 +35,44 @@ void MacroActionHttp::SetupHeaders()
|
|||||||
}
|
}
|
||||||
struct curl_slist *headers = nullptr;
|
struct curl_slist *headers = nullptr;
|
||||||
for (auto &header : _headers) {
|
for (auto &header : _headers) {
|
||||||
headers = switcher->curl.SlistAppend(headers, header.c_str());
|
headers = CurlHelper::SlistAppend(headers, header.c_str());
|
||||||
}
|
}
|
||||||
if (!_headers.empty()) {
|
if (!_headers.empty()) {
|
||||||
switcher->curl.SetOpt(CURLOPT_HTTPHEADER, headers);
|
CurlHelper::SetOpt(CURLOPT_HTTPHEADER, headers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionHttp::Get()
|
void MacroActionHttp::Get()
|
||||||
{
|
{
|
||||||
switcher->curl.SetOpt(CURLOPT_URL, _url.c_str());
|
CurlHelper::SetOpt(CURLOPT_URL, _url.c_str());
|
||||||
switcher->curl.SetOpt(CURLOPT_HTTPGET, 1L);
|
CurlHelper::SetOpt(CURLOPT_HTTPGET, 1L);
|
||||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.Milliseconds());
|
CurlHelper::SetOpt(CURLOPT_TIMEOUT_MS, _timeout.Milliseconds());
|
||||||
SetupHeaders();
|
SetupHeaders();
|
||||||
|
|
||||||
std::string response;
|
std::string response;
|
||||||
if (IsReferencedInVars()) {
|
if (IsReferencedInVars()) {
|
||||||
switcher->curl.SetOpt(CURLOPT_WRITEFUNCTION, WriteCB);
|
CurlHelper::SetOpt(CURLOPT_WRITEFUNCTION, WriteCB);
|
||||||
} else {
|
} else {
|
||||||
switcher->curl.SetOpt(CURLOPT_WRITEFUNCTION, DropCB);
|
CurlHelper::SetOpt(CURLOPT_WRITEFUNCTION, DropCB);
|
||||||
}
|
}
|
||||||
switcher->curl.SetOpt(CURLOPT_WRITEDATA, &response);
|
CurlHelper::SetOpt(CURLOPT_WRITEDATA, &response);
|
||||||
switcher->curl.Perform();
|
CurlHelper::Perform();
|
||||||
|
|
||||||
SetVariableValue(response);
|
SetVariableValue(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionHttp::Post()
|
void MacroActionHttp::Post()
|
||||||
{
|
{
|
||||||
switcher->curl.SetOpt(CURLOPT_URL, _url.c_str());
|
CurlHelper::SetOpt(CURLOPT_URL, _url.c_str());
|
||||||
switcher->curl.SetOpt(CURLOPT_POSTFIELDS, _data.c_str());
|
CurlHelper::SetOpt(CURLOPT_POSTFIELDS, _data.c_str());
|
||||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.Milliseconds());
|
CurlHelper::SetOpt(CURLOPT_TIMEOUT_MS, _timeout.Milliseconds());
|
||||||
SetupHeaders();
|
SetupHeaders();
|
||||||
switcher->curl.Perform();
|
CurlHelper::Perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionHttp::PerformAction()
|
bool MacroActionHttp::PerformAction()
|
||||||
{
|
{
|
||||||
if (!switcher->curl.Initialized()) {
|
if (!CurlHelper::Initialized()) {
|
||||||
blog(LOG_WARNING,
|
blog(LOG_WARNING,
|
||||||
"cannot perform http action (curl not found)");
|
"cannot perform http action (curl not found)");
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "macro-action-plugin-state.hpp"
|
#include "macro-action-plugin-state.hpp"
|
||||||
#include "plugin-state-helper.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|||||||
@@ -14,9 +14,14 @@ bool MacroActionRun::_registered = MacroActionFactory::Register(
|
|||||||
|
|
||||||
bool MacroActionRun::PerformAction()
|
bool MacroActionRun::PerformAction()
|
||||||
{
|
{
|
||||||
bool procStarted = QProcess::startDetached(
|
if (_wait) {
|
||||||
QString::fromStdString(_procConfig.Path()), _procConfig.Args(),
|
_procConfig.StartProcessAndWait(_timeout.Milliseconds());
|
||||||
QString::fromStdString(_procConfig.WorkingDir()));
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool procStarted = _procConfig.StartProcessDetached();
|
||||||
|
|
||||||
|
// Fall back to using default application to open given file
|
||||||
if (!procStarted && _procConfig.Args().empty()) {
|
if (!procStarted && _procConfig.Args().empty()) {
|
||||||
vblog(LOG_INFO, "run \"%s\" using QDesktopServices",
|
vblog(LOG_INFO, "run \"%s\" using QDesktopServices",
|
||||||
_procConfig.Path().c_str());
|
_procConfig.Path().c_str());
|
||||||
@@ -35,6 +40,9 @@ bool MacroActionRun::Save(obs_data_t *obj) const
|
|||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
_procConfig.Save(obj);
|
_procConfig.Save(obj);
|
||||||
|
_timeout.Save(obj);
|
||||||
|
obs_data_set_bool(obj, "wait", _wait);
|
||||||
|
obs_data_set_int(obj, "version", 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +50,12 @@ bool MacroActionRun::Load(obs_data_t *obj)
|
|||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_procConfig.Load(obj);
|
_procConfig.Load(obj);
|
||||||
|
// TODO: Remove this fallback in a future version
|
||||||
|
if (!obs_data_has_user_value(obj, "version")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_timeout.Load(obj);
|
||||||
|
_wait = obs_data_get_bool(obj, "wait");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,14 +66,30 @@ std::string MacroActionRun::GetShortDesc() const
|
|||||||
|
|
||||||
MacroActionRunEdit::MacroActionRunEdit(
|
MacroActionRunEdit::MacroActionRunEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroActionRun> entryData)
|
QWidget *parent, std::shared_ptr<MacroActionRun> entryData)
|
||||||
: QWidget(parent), _procConfig(new ProcessConfigEdit(this))
|
: QWidget(parent),
|
||||||
|
_procConfig(new ProcessConfigEdit(this)),
|
||||||
|
_waitLayout(new QHBoxLayout()),
|
||||||
|
_wait(new QCheckBox()),
|
||||||
|
_timeout(new DurationSelection(this, true, 0.1))
|
||||||
{
|
{
|
||||||
QWidget::connect(_procConfig,
|
QWidget::connect(_procConfig,
|
||||||
SIGNAL(ConfigChanged(const ProcessConfig &)), this,
|
SIGNAL(ConfigChanged(const ProcessConfig &)), this,
|
||||||
SLOT(ProcessConfigChanged(const ProcessConfig &)));
|
SLOT(ProcessConfigChanged(const ProcessConfig &)));
|
||||||
|
QWidget::connect(_procConfig, SIGNAL(AdvancedSettingsEnabled()), this,
|
||||||
|
SLOT(ProcessConfigAdvancedSettingsShown()));
|
||||||
|
QWidget::connect(_wait, SIGNAL(stateChanged(int)), this,
|
||||||
|
SLOT(WaitChanged(int)));
|
||||||
|
QWidget::connect(_timeout, SIGNAL(DurationChanged(const Duration &)),
|
||||||
|
this, SLOT(TimeoutChanged(const Duration &)));
|
||||||
|
|
||||||
auto *layout = new QVBoxLayout;
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.run.entry.wait"),
|
||||||
|
_waitLayout,
|
||||||
|
{{"{{wait}}", _wait}, {"{{timeout}}", _timeout}});
|
||||||
|
SetLayoutVisible(_waitLayout, false);
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout;
|
||||||
layout->addWidget(_procConfig);
|
layout->addWidget(_procConfig);
|
||||||
|
layout->addLayout(_waitLayout);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
@@ -73,6 +103,31 @@ void MacroActionRunEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_procConfig->SetProcessConfig(_entryData->_procConfig);
|
_procConfig->SetProcessConfig(_entryData->_procConfig);
|
||||||
|
_wait->setChecked(_entryData->_wait);
|
||||||
|
_timeout->SetDuration(_entryData->_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRunEdit::ProcessConfigAdvancedSettingsShown()
|
||||||
|
{
|
||||||
|
SetLayoutVisible(_waitLayout, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRunEdit::WaitChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_wait = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionRunEdit::TimeoutChanged(const Duration &timeout)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_timeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionRunEdit::ProcessConfigChanged(const ProcessConfig &conf)
|
void MacroActionRunEdit::ProcessConfigChanged(const ProcessConfig &conf)
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
#include "process-config.hpp"
|
#include "process-config.hpp"
|
||||||
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -19,6 +22,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ProcessConfig _procConfig;
|
ProcessConfig _procConfig;
|
||||||
|
bool _wait = false;
|
||||||
|
Duration _timeout = 1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
@@ -42,14 +47,19 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ProcessConfigChanged(const ProcessConfig &);
|
void ProcessConfigChanged(const ProcessConfig &);
|
||||||
|
void ProcessConfigAdvancedSettingsShown();
|
||||||
|
void WaitChanged(int);
|
||||||
|
void TimeoutChanged(const Duration &);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
protected:
|
|
||||||
std::shared_ptr<MacroActionRun> _entryData;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProcessConfigEdit *_procConfig;
|
ProcessConfigEdit *_procConfig;
|
||||||
|
QHBoxLayout *_waitLayout;
|
||||||
|
QCheckBox *_wait;
|
||||||
|
DurationSelection *_timeout;
|
||||||
|
|
||||||
|
std::shared_ptr<MacroActionRun> _entryData;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "macro-action-scene-collection.hpp"
|
#include "macro-action-scene-collection.hpp"
|
||||||
#include "plugin-state-helper.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "macro-action-scene-switch.hpp"
|
#include "macro-action-scene-switch.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "macro-helpers.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
|
#include "macro.hpp"
|
||||||
#include "scene-switch-helpers.hpp"
|
#include "scene-switch-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
@@ -7,7 +9,7 @@ namespace advss {
|
|||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
const std::string MacroActionSwitchScene::id = "scene_switch";
|
const std::string MacroActionSwitchScene::id = GetSceneSwitchActionId().data();
|
||||||
|
|
||||||
bool MacroActionSwitchScene::_registered = MacroActionFactory::Register(
|
bool MacroActionSwitchScene::_registered = MacroActionFactory::Register(
|
||||||
MacroActionSwitchScene::id,
|
MacroActionSwitchScene::id,
|
||||||
@@ -33,9 +35,9 @@ static void waitForTransitionChange(OBSWeakSource &transition,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool stillTransitioning = true;
|
bool stillTransitioning = true;
|
||||||
while (stillTransitioning && !switcher->abortMacroWait &&
|
while (stillTransitioning && !MacroWaitShouldAbort() &&
|
||||||
!macro->GetStop()) {
|
!macro->GetStop()) {
|
||||||
switcher->macroTransitionCv.wait_for(*lock, time);
|
GetMacroTransitionCV().wait_for(*lock, time);
|
||||||
float t = obs_transition_get_time(source);
|
float t = obs_transition_get_time(source);
|
||||||
stillTransitioning = t < 1.0f && t > 0.0f;
|
stillTransitioning = t < 1.0f && t > 0.0f;
|
||||||
}
|
}
|
||||||
@@ -49,8 +51,8 @@ static void waitForTransitionChangeFixedDuration(
|
|||||||
auto time = std::chrono::high_resolution_clock::now() +
|
auto time = std::chrono::high_resolution_clock::now() +
|
||||||
std::chrono::milliseconds(duration);
|
std::chrono::milliseconds(duration);
|
||||||
|
|
||||||
while (!switcher->abortMacroWait && !macro->GetStop()) {
|
while (!MacroWaitShouldAbort() && !macro->GetStop()) {
|
||||||
if (switcher->macroTransitionCv.wait_until(*lock, time) ==
|
if (GetMacroTransitionCV().wait_until(*lock, time) ==
|
||||||
std::cv_status::timeout) {
|
std::cv_status::timeout) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -91,11 +93,16 @@ static OBSWeakSource getOverrideTransition(OBSWeakSource &scene)
|
|||||||
return transition;
|
return transition;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getExpectedTransitionDuration(OBSWeakSource &scene, OBSWeakSource &t,
|
static int getExpectedTransitionDuration(OBSWeakSource &scene,
|
||||||
|
OBSWeakSource &transiton_,
|
||||||
double duration)
|
double duration)
|
||||||
{
|
{
|
||||||
OBSWeakSource transition = t;
|
OBSWeakSource transition = transiton_;
|
||||||
if (!switcher->transitionOverrideOverride) {
|
|
||||||
|
// If we are not modifying the transition override, we will have to
|
||||||
|
// check, if a transition override is set by the user and use its
|
||||||
|
// duration instead
|
||||||
|
if (!ShouldModifyTransitionOverrides()) {
|
||||||
auto overrideTransition = getOverrideTransition(scene);
|
auto overrideTransition = getOverrideTransition(scene);
|
||||||
if (overrideTransition) {
|
if (overrideTransition) {
|
||||||
transition = overrideTransition;
|
transition = overrideTransition;
|
||||||
@@ -104,6 +111,7 @@ static int getExpectedTransitionDuration(OBSWeakSource &scene, OBSWeakSource &t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUsingFixedLengthTransition(transition)) {
|
if (isUsingFixedLengthTransition(transition)) {
|
||||||
return -1; // no API is available to access the fixed duration
|
return -1; // no API is available to access the fixed duration
|
||||||
}
|
}
|
||||||
@@ -118,9 +126,9 @@ bool MacroActionSwitchScene::WaitForTransition(OBSWeakSource &scene,
|
|||||||
{
|
{
|
||||||
const int expectedTransitionDuration = getExpectedTransitionDuration(
|
const int expectedTransitionDuration = getExpectedTransitionDuration(
|
||||||
scene, transition, _duration.Seconds());
|
scene, transition, _duration.Seconds());
|
||||||
switcher->abortMacroWait = false;
|
SetMacroAbortWait(false);
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(switcher->m);
|
std::unique_lock<std::mutex> lock(*GetMutex());
|
||||||
if (expectedTransitionDuration < 0) {
|
if (expectedTransitionDuration < 0) {
|
||||||
waitForTransitionChange(transition, &lock, GetMacro());
|
waitForTransitionChange(transition, &lock, GetMacro());
|
||||||
} else {
|
} else {
|
||||||
@@ -128,7 +136,7 @@ bool MacroActionSwitchScene::WaitForTransition(OBSWeakSource &scene,
|
|||||||
&lock, GetMacro());
|
&lock, GetMacro());
|
||||||
}
|
}
|
||||||
|
|
||||||
return !switcher->abortMacroWait;
|
return !MacroWaitShouldAbort();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionSwitchScene::PerformAction()
|
bool MacroActionSwitchScene::PerformAction()
|
||||||
@@ -145,8 +153,7 @@ bool MacroActionSwitchScene::PerformAction()
|
|||||||
auto transition = _transition.GetTransition();
|
auto transition = _transition.GetTransition();
|
||||||
SwitchScene({scene, transition, (int)(_duration.Milliseconds())},
|
SwitchScene({scene, transition, (int)(_duration.Milliseconds())},
|
||||||
obs_frontend_preview_program_mode_active());
|
obs_frontend_preview_program_mode_active());
|
||||||
if (_blockUntilTransitionDone && scene &&
|
if (_blockUntilTransitionDone && scene && scene != GetCurrentScene()) {
|
||||||
scene != switcher->currentScene) {
|
|
||||||
return WaitForTransition(scene, transition);
|
return WaitForTransition(scene, transition);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "macro-action-variable.hpp"
|
#include "macro-action-variable.hpp"
|
||||||
#include "macro-condition-edit.hpp"
|
#include "macro-condition-edit.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "math-helpers.hpp"
|
#include "math-helpers.hpp"
|
||||||
@@ -51,6 +50,8 @@ const static std::map<MacroActionVariable::Type, std::string> actionTypes = {
|
|||||||
"AdvSceneSwitcher.action.variable.type.extractJson"},
|
"AdvSceneSwitcher.action.variable.type.extractJson"},
|
||||||
{MacroActionVariable::Type::SET_TO_TEMPVAR,
|
{MacroActionVariable::Type::SET_TO_TEMPVAR,
|
||||||
"AdvSceneSwitcher.action.variable.type.setToTempvar"},
|
"AdvSceneSwitcher.action.variable.type.setToTempvar"},
|
||||||
|
{MacroActionVariable::Type::SCENE_ITEM_NAME,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.sceneItemName"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void apppend(Variable &var, const std::string &value)
|
static void apppend(Variable &var, const std::string &value)
|
||||||
@@ -134,6 +135,49 @@ void MacroActionVariable::HandleMathExpression(Variable *var)
|
|||||||
var->SetValue(std::get<double>(result));
|
var->SetValue(std::get<double>(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GetSceneItemNameHelper {
|
||||||
|
int curIdx = 0;
|
||||||
|
int targetIdx = 0;
|
||||||
|
std::string name = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool getSceneItemAtIdx(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
||||||
|
{
|
||||||
|
auto data = reinterpret_cast<GetSceneItemNameHelper *>(ptr);
|
||||||
|
if (obs_sceneitem_is_group(item)) {
|
||||||
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||||
|
obs_scene_enum_items(scene, getSceneItemAtIdx, ptr);
|
||||||
|
}
|
||||||
|
if (data->curIdx == data->targetIdx) {
|
||||||
|
data->name =
|
||||||
|
obs_source_get_name(obs_sceneitem_get_source(item));
|
||||||
|
data->curIdx--;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data->curIdx--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariable::SetToSceneItemName(Variable *var)
|
||||||
|
{
|
||||||
|
auto weakSource = _scene.GetScene();
|
||||||
|
if (!weakSource) {
|
||||||
|
var->SetValue("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto index = _sceneItemIndex.GetValue();
|
||||||
|
if (index < 1) {
|
||||||
|
var->SetValue("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto sceneItemCount = GetSceneItemCount(weakSource);
|
||||||
|
OBSSourceAutoRelease source = obs_weak_source_get_source(weakSource);
|
||||||
|
auto scene = obs_scene_from_source(source);
|
||||||
|
GetSceneItemNameHelper data{sceneItemCount, index};
|
||||||
|
obs_scene_enum_items(scene, getSceneItemAtIdx, &data);
|
||||||
|
var->SetValue(data.name);
|
||||||
|
}
|
||||||
|
|
||||||
struct AskForInputParams {
|
struct AskForInputParams {
|
||||||
QString prompt;
|
QString prompt;
|
||||||
QString placeholder;
|
QString placeholder;
|
||||||
@@ -268,6 +312,9 @@ bool MacroActionVariable::PerformAction()
|
|||||||
var->SetValue(*value);
|
var->SetValue(*value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case Type::SCENE_ITEM_NAME:
|
||||||
|
SetToSceneItemName(var.get());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -299,6 +346,7 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
|||||||
_envVariableName.Save(obj, "environmentVariableName");
|
_envVariableName.Save(obj, "environmentVariableName");
|
||||||
_scene.Save(obj);
|
_scene.Save(obj);
|
||||||
_tempVar.Save(obj);
|
_tempVar.Save(obj);
|
||||||
|
_sceneItemIndex.Save(obj, "sceneItemIndex");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,6 +376,7 @@ bool MacroActionVariable::Load(obs_data_t *obj)
|
|||||||
_envVariableName.Load(obj, "environmentVariableName");
|
_envVariableName.Load(obj, "environmentVariableName");
|
||||||
_scene.Load(obj);
|
_scene.Load(obj);
|
||||||
_tempVar.Load(obj, GetMacro());
|
_tempVar.Load(obj, GetMacro());
|
||||||
|
_sceneItemIndex.Load(obj, "sceneItemIndex");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,7 +506,8 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_envVariable(new VariableLineEdit(this)),
|
_envVariable(new VariableLineEdit(this)),
|
||||||
_scenes(new SceneSelectionWidget(this, true, false, true, true,
|
_scenes(new SceneSelectionWidget(this, true, false, true, true,
|
||||||
true)),
|
true)),
|
||||||
_tempVars(new TempVariableSelection(this))
|
_tempVars(new TempVariableSelection(this)),
|
||||||
|
_sceneItemIndex(new VariableSpinBox())
|
||||||
{
|
{
|
||||||
_numValue->setMinimum(-9999999999);
|
_numValue->setMinimum(-9999999999);
|
||||||
_numValue->setMaximum(9999999999);
|
_numValue->setMaximum(9999999999);
|
||||||
@@ -475,6 +525,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_regexMatchIdx->setSuffix(".");
|
_regexMatchIdx->setSuffix(".");
|
||||||
_inputPrompt->setSizePolicy(QSizePolicy::MinimumExpanding,
|
_inputPrompt->setSizePolicy(QSizePolicy::MinimumExpanding,
|
||||||
QSizePolicy::Preferred);
|
QSizePolicy::Preferred);
|
||||||
|
_sceneItemIndex->setMinimum(1);
|
||||||
populateTypeSelection(_actions);
|
populateTypeSelection(_actions);
|
||||||
|
|
||||||
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
||||||
@@ -523,6 +574,10 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
QWidget::connect(_tempVars,
|
QWidget::connect(_tempVars,
|
||||||
SIGNAL(SelectionChanged(const TempVariableRef &)),
|
SIGNAL(SelectionChanged(const TempVariableRef &)),
|
||||||
this, SLOT(SelectionChanged(const TempVariableRef &)));
|
this, SLOT(SelectionChanged(const TempVariableRef &)));
|
||||||
|
QWidget::connect(
|
||||||
|
_sceneItemIndex,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(SceneItemIndexChanged(const NumberVariable<int> &)));
|
||||||
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{variables}}", _variables},
|
{"{{variables}}", _variables},
|
||||||
@@ -544,6 +599,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
{"{{envVariableName}}", _envVariable},
|
{"{{envVariableName}}", _envVariable},
|
||||||
{"{{scenes}}", _scenes},
|
{"{{scenes}}", _scenes},
|
||||||
{"{{tempVars}}", _tempVars},
|
{"{{tempVars}}", _tempVars},
|
||||||
|
{"{{sceneItemIndex}}", _sceneItemIndex},
|
||||||
};
|
};
|
||||||
auto entryLayout = new QHBoxLayout;
|
auto entryLayout = new QHBoxLayout;
|
||||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.variable.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.variable.entry"),
|
||||||
@@ -638,6 +694,7 @@ void MacroActionVariableEdit::UpdateEntryData()
|
|||||||
_envVariable->setText(_entryData->_envVariableName);
|
_envVariable->setText(_entryData->_envVariableName);
|
||||||
_scenes->SetScene(_entryData->_scene);
|
_scenes->SetScene(_entryData->_scene);
|
||||||
_tempVars->SetVariable(_entryData->_tempVar);
|
_tempVars->SetVariable(_entryData->_tempVar);
|
||||||
|
_sceneItemIndex->SetValue(_entryData->_sceneItemIndex);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -982,6 +1039,17 @@ void MacroActionVariableEdit::SelectionChanged(const TempVariableRef &var)
|
|||||||
_entryData->_tempVar = var;
|
_entryData->_tempVar = var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::SceneItemIndexChanged(
|
||||||
|
const NumberVariable<int> &value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_sceneItemIndex = value;
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::SetWidgetVisibility()
|
void MacroActionVariableEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
if (!_entryData) {
|
if (!_entryData) {
|
||||||
@@ -1058,10 +1126,15 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
}
|
}
|
||||||
_envVariable->setVisible(_entryData->_type ==
|
_envVariable->setVisible(_entryData->_type ==
|
||||||
MacroActionVariable::Type::ENV_VARIABLE);
|
MacroActionVariable::Type::ENV_VARIABLE);
|
||||||
_scenes->setVisible(_entryData->_type ==
|
_scenes->setVisible(
|
||||||
MacroActionVariable::Type::SCENE_ITEM_COUNT);
|
_entryData->_type ==
|
||||||
|
MacroActionVariable::Type::SCENE_ITEM_COUNT ||
|
||||||
|
_entryData->_type ==
|
||||||
|
MacroActionVariable::Type::SCENE_ITEM_NAME);
|
||||||
_tempVars->setVisible(_entryData->_type ==
|
_tempVars->setVisible(_entryData->_type ==
|
||||||
MacroActionVariable::Type::SET_TO_TEMPVAR);
|
MacroActionVariable::Type::SET_TO_TEMPVAR);
|
||||||
|
_sceneItemIndex->setVisible(_entryData->_type ==
|
||||||
|
MacroActionVariable::Type::SCENE_ITEM_NAME);
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "scene-selection.hpp"
|
#include "scene-selection.hpp"
|
||||||
#include "variable-line-edit.hpp"
|
#include "variable-line-edit.hpp"
|
||||||
#include "variable-text-edit.hpp"
|
#include "variable-text-edit.hpp"
|
||||||
|
#include "variable-spinbox.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -44,6 +45,7 @@ public:
|
|||||||
STRING_LENGTH,
|
STRING_LENGTH,
|
||||||
EXTRACT_JSON,
|
EXTRACT_JSON,
|
||||||
SET_TO_TEMPVAR,
|
SET_TO_TEMPVAR,
|
||||||
|
SCENE_ITEM_NAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
Type _type = Type::SET_FIXED_VALUE;
|
Type _type = Type::SET_FIXED_VALUE;
|
||||||
@@ -75,6 +77,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
SceneSelection _scene;
|
SceneSelection _scene;
|
||||||
TempVariableRef _tempVar;
|
TempVariableRef _tempVar;
|
||||||
|
IntVariable _sceneItemIndex = 1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DecrementCurrentSegmentVariableRef();
|
void DecrementCurrentSegmentVariableRef();
|
||||||
@@ -82,6 +85,7 @@ private:
|
|||||||
void HandleRegexSubString(Variable *);
|
void HandleRegexSubString(Variable *);
|
||||||
void HandleFindAndReplace(Variable *);
|
void HandleFindAndReplace(Variable *);
|
||||||
void HandleMathExpression(Variable *);
|
void HandleMathExpression(Variable *);
|
||||||
|
void SetToSceneItemName(Variable *);
|
||||||
|
|
||||||
std::weak_ptr<MacroSegment> _macroSegment;
|
std::weak_ptr<MacroSegment> _macroSegment;
|
||||||
int _segmentIdxLoadValue = -1;
|
int _segmentIdxLoadValue = -1;
|
||||||
@@ -129,6 +133,7 @@ private slots:
|
|||||||
void EnvVariableChanged();
|
void EnvVariableChanged();
|
||||||
void SceneChanged(const SceneSelection &);
|
void SceneChanged(const SceneSelection &);
|
||||||
void SelectionChanged(const TempVariableRef &var);
|
void SelectionChanged(const TempVariableRef &var);
|
||||||
|
void SceneItemIndexChanged(const NumberVariable<int> &);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
@@ -167,6 +172,7 @@ private:
|
|||||||
VariableLineEdit *_envVariable;
|
VariableLineEdit *_envVariable;
|
||||||
SceneSelectionWidget *_scenes;
|
SceneSelectionWidget *_scenes;
|
||||||
TempVariableSelection *_tempVars;
|
TempVariableSelection *_tempVars;
|
||||||
|
VariableSpinBox *_sceneItemIndex;
|
||||||
|
|
||||||
std::shared_ptr<MacroActionVariable> _entryData;
|
std::shared_ptr<MacroActionVariable> _entryData;
|
||||||
QTimer _timer;
|
QTimer _timer;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "macro-action-wait.hpp"
|
#include "macro-action-wait.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "macro-helpers.hpp"
|
||||||
|
#include "macro.hpp"
|
||||||
|
#include "sync-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
@@ -24,8 +26,8 @@ static std::default_random_engine re(rd());
|
|||||||
static void waitHelper(std::unique_lock<std::mutex> *lock, Macro *macro,
|
static void waitHelper(std::unique_lock<std::mutex> *lock, Macro *macro,
|
||||||
std::chrono::high_resolution_clock::time_point &time)
|
std::chrono::high_resolution_clock::time_point &time)
|
||||||
{
|
{
|
||||||
while (!switcher->abortMacroWait && !macro->GetStop()) {
|
while (!MacroWaitShouldAbort() && !macro->GetStop()) {
|
||||||
if (switcher->macroWaitCv.wait_until(*lock, time) ==
|
if (GetMacroWaitCV().wait_until(*lock, time) ==
|
||||||
std::cv_status::timeout) {
|
std::cv_status::timeout) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -53,11 +55,11 @@ bool MacroActionWait::PerformAction()
|
|||||||
auto time = std::chrono::high_resolution_clock::now() +
|
auto time = std::chrono::high_resolution_clock::now() +
|
||||||
std::chrono::milliseconds((int)(sleepDuration * 1000));
|
std::chrono::milliseconds((int)(sleepDuration * 1000));
|
||||||
|
|
||||||
switcher->abortMacroWait = false;
|
SetMacroAbortWait(false);
|
||||||
std::unique_lock<std::mutex> lock(switcher->m);
|
std::unique_lock<std::mutex> lock(*GetMutex());
|
||||||
waitHelper(&lock, GetMacro(), time);
|
waitHelper(&lock, GetMacro(), time);
|
||||||
|
|
||||||
return !switcher->abortMacroWait;
|
return !MacroWaitShouldAbort();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionWait::Save(obs_data_t *obj) const
|
bool MacroActionWait::Save(obs_data_t *obj) const
|
||||||
|
|||||||
@@ -62,17 +62,17 @@ MacroConditionAudio::~MacroConditionAudio()
|
|||||||
bool MacroConditionAudio::CheckOutputCondition()
|
bool MacroConditionAudio::CheckOutputCondition()
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
auto s = obs_weak_source_get_source(_audioSource.GetSource());
|
OBSSourceAutoRelease source =
|
||||||
|
obs_weak_source_get_source(_audioSource.GetSource());
|
||||||
|
|
||||||
|
// peak will have a value from -60 db to 0 db so we need to scale it
|
||||||
double curVolume = ((double)_peak + 60) * 1.7;
|
double curVolume = ((double)_peak + 60) * 1.7;
|
||||||
|
|
||||||
switch (_outputCondition) {
|
switch (_outputCondition) {
|
||||||
case OutputCondition::ABOVE:
|
case OutputCondition::ABOVE:
|
||||||
// peak will have a value from -60 db to 0 db
|
|
||||||
ret = curVolume > _volume;
|
ret = curVolume > _volume;
|
||||||
break;
|
break;
|
||||||
case OutputCondition::BELOW:
|
case OutputCondition::BELOW:
|
||||||
// peak will have a value from -60 db to 0 db
|
|
||||||
ret = curVolume < _volume;
|
ret = curVolume < _volume;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -84,21 +84,21 @@ bool MacroConditionAudio::CheckOutputCondition()
|
|||||||
|
|
||||||
// Reset for next check
|
// Reset for next check
|
||||||
_peak = -std::numeric_limits<float>::infinity();
|
_peak = -std::numeric_limits<float>::infinity();
|
||||||
obs_source_release(s);
|
|
||||||
if (_audioSource.GetType() == SourceSelection::Type::VARIABLE) {
|
if (_audioSource.GetType() == SourceSelection::Type::VARIABLE) {
|
||||||
ResetVolmeter();
|
ResetVolmeter();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret && source;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionAudio::CheckVolumeCondition()
|
bool MacroConditionAudio::CheckVolumeCondition()
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
auto s = obs_weak_source_get_source(_audioSource.GetSource());
|
OBSSourceAutoRelease source =
|
||||||
|
obs_weak_source_get_source(_audioSource.GetSource());
|
||||||
|
|
||||||
float curVolume = obs_source_get_volume(s);
|
float curVolume = obs_source_get_volume(source);
|
||||||
bool muted = obs_source_muted(s);
|
bool muted = obs_source_muted(source);
|
||||||
|
|
||||||
switch (_volumeCondition) {
|
switch (_volumeCondition) {
|
||||||
case VolumeCondition::ABOVE:
|
case VolumeCondition::ABOVE:
|
||||||
@@ -126,10 +126,9 @@ bool MacroConditionAudio::CheckVolumeCondition()
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetTempVarValue("configured_volume", std::to_string(curVolume));
|
SetTempVarValue("configured_volume", std::to_string(curVolume));
|
||||||
SetTempVarValue("muted", muted ? "true" : "false");
|
SetTempVarValue("muted", (source && muted) ? "true" : "false");
|
||||||
|
|
||||||
obs_source_release(s);
|
return ret && source;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionAudio::CheckSyncOffset()
|
bool MacroConditionAudio::CheckSyncOffset()
|
||||||
@@ -139,8 +138,9 @@ bool MacroConditionAudio::CheckSyncOffset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
auto s = obs_weak_source_get_source(_audioSource.GetSource());
|
OBSSourceAutoRelease source =
|
||||||
auto curOffset = obs_source_get_sync_offset(s) / nsPerMs;
|
obs_weak_source_get_source(_audioSource.GetSource());
|
||||||
|
auto curOffset = obs_source_get_sync_offset(source) / nsPerMs;
|
||||||
if (_outputCondition == OutputCondition::ABOVE) {
|
if (_outputCondition == OutputCondition::ABOVE) {
|
||||||
ret = curOffset > _syncOffset;
|
ret = curOffset > _syncOffset;
|
||||||
} else {
|
} else {
|
||||||
@@ -148,8 +148,7 @@ bool MacroConditionAudio::CheckSyncOffset()
|
|||||||
}
|
}
|
||||||
SetVariableValue(std::to_string(curOffset));
|
SetVariableValue(std::to_string(curOffset));
|
||||||
SetTempVarValue("sync_offset", std::to_string(curOffset));
|
SetTempVarValue("sync_offset", std::to_string(curOffset));
|
||||||
obs_source_release(s);
|
return ret && source;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionAudio::CheckMonitor()
|
bool MacroConditionAudio::CheckMonitor()
|
||||||
@@ -159,13 +158,13 @@ bool MacroConditionAudio::CheckMonitor()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
auto s = obs_weak_source_get_source(_audioSource.GetSource());
|
OBSSourceAutoRelease source =
|
||||||
ret = obs_source_get_monitoring_type(s) == _monitorType;
|
obs_weak_source_get_source(_audioSource.GetSource());
|
||||||
|
ret = obs_source_get_monitoring_type(source) == _monitorType;
|
||||||
SetVariableValue("");
|
SetVariableValue("");
|
||||||
SetTempVarValue("monitor",
|
SetTempVarValue("monitor",
|
||||||
std::to_string(obs_source_get_monitoring_type(s)));
|
std::to_string(obs_source_get_monitoring_type(source)));
|
||||||
obs_source_release(s);
|
return ret && source;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionAudio::CheckBalance()
|
bool MacroConditionAudio::CheckBalance()
|
||||||
@@ -175,8 +174,9 @@ bool MacroConditionAudio::CheckBalance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
auto s = obs_weak_source_get_source(_audioSource.GetSource());
|
OBSSourceAutoRelease source =
|
||||||
auto curBalance = obs_source_get_balance_value(s);
|
obs_weak_source_get_source(_audioSource.GetSource());
|
||||||
|
auto curBalance = obs_source_get_balance_value(source);
|
||||||
if (_outputCondition == OutputCondition::ABOVE) {
|
if (_outputCondition == OutputCondition::ABOVE) {
|
||||||
ret = curBalance > _balance;
|
ret = curBalance > _balance;
|
||||||
} else {
|
} else {
|
||||||
@@ -184,8 +184,7 @@ bool MacroConditionAudio::CheckBalance()
|
|||||||
}
|
}
|
||||||
SetVariableValue(std::to_string(curBalance));
|
SetVariableValue(std::to_string(curBalance));
|
||||||
SetTempVarValue("balance", std::to_string(curBalance));
|
SetTempVarValue("balance", std::to_string(curBalance));
|
||||||
obs_source_release(s);
|
return ret && source;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionAudio::CheckCondition()
|
bool MacroConditionAudio::CheckCondition()
|
||||||
@@ -239,13 +238,12 @@ obs_volmeter_t *AddVolmeterToSource(MacroConditionAudio *entry,
|
|||||||
obs_volmeter_t *volmeter = obs_volmeter_create(OBS_FADER_LOG);
|
obs_volmeter_t *volmeter = obs_volmeter_create(OBS_FADER_LOG);
|
||||||
obs_volmeter_add_callback(volmeter, MacroConditionAudio::SetVolumeLevel,
|
obs_volmeter_add_callback(volmeter, MacroConditionAudio::SetVolumeLevel,
|
||||||
entry);
|
entry);
|
||||||
obs_source_t *as = obs_weak_source_get_source(source);
|
OBSSourceAutoRelease audioSource = obs_weak_source_get_source(source);
|
||||||
if (!obs_volmeter_attach_source(volmeter, as)) {
|
if (!obs_volmeter_attach_source(volmeter, audioSource)) {
|
||||||
const char *name = obs_source_get_name(as);
|
const char *name = obs_source_get_name(audioSource);
|
||||||
blog(LOG_WARNING, "failed to attach volmeter to source %s",
|
blog(LOG_WARNING, "failed to attach volmeter to source %s",
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
obs_source_release(as);
|
|
||||||
|
|
||||||
return volmeter;
|
return volmeter;
|
||||||
}
|
}
|
||||||
@@ -455,10 +453,9 @@ MacroConditionAudioEdit::MacroConditionAudioEdit(
|
|||||||
void MacroConditionAudioEdit::UpdateVolmeterSource()
|
void MacroConditionAudioEdit::UpdateVolmeterSource()
|
||||||
{
|
{
|
||||||
delete _volMeter;
|
delete _volMeter;
|
||||||
obs_source_t *soruce = obs_weak_source_get_source(
|
OBSSourceAutoRelease soruce = obs_weak_source_get_source(
|
||||||
_entryData->_audioSource.GetSource());
|
_entryData->_audioSource.GetSource());
|
||||||
_volMeter = new VolControl(soruce);
|
_volMeter = new VolControl(soruce.Get());
|
||||||
obs_source_release(soruce);
|
|
||||||
|
|
||||||
QLayout *layout = this->layout();
|
QLayout *layout = this->layout();
|
||||||
layout->addWidget(_volMeter);
|
layout->addWidget(_volMeter);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "macro-condition-cursor.hpp"
|
#include "macro-condition-cursor.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "platform-funcs.hpp"
|
#include "platform-funcs.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
@@ -61,13 +60,15 @@ bool MacroConditionCursor::CheckCondition()
|
|||||||
std::to_string(cursorPos.second));
|
std::to_string(cursorPos.second));
|
||||||
break;
|
break;
|
||||||
case Condition::MOVING:
|
case Condition::MOVING:
|
||||||
ret = switcher->cursorPosChanged;
|
ret = cursorPos.first != _lastCursorPosition.first ||
|
||||||
|
cursorPos.second != _lastCursorPosition.second;
|
||||||
break;
|
break;
|
||||||
case Condition::CLICK:
|
case Condition::CLICK:
|
||||||
ret = CheckClick();
|
ret = CheckClick();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_lastCheckTime = std::chrono::high_resolution_clock::now();
|
_lastCheckTime = std::chrono::high_resolution_clock::now();
|
||||||
|
_lastCursorPosition = cursorPos;
|
||||||
|
|
||||||
if (GetVariableValue().empty()) {
|
if (GetVariableValue().empty()) {
|
||||||
SetVariableValue(ret ? "true" : "false");
|
SetVariableValue(ret ? "true" : "false");
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool CheckClick();
|
bool CheckClick();
|
||||||
std::chrono::high_resolution_clock::time_point _lastCheckTime{};
|
std::chrono::high_resolution_clock::time_point _lastCheckTime{};
|
||||||
|
std::pair<int, int> _lastCursorPosition;
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
|
|||||||
@@ -638,10 +638,24 @@ void MacroConditionDateEdit::AdvancedSettingsToggleClicked()
|
|||||||
{
|
{
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_dayOfWeekCheck = !_entryData->_dayOfWeekCheck;
|
_entryData->_dayOfWeekCheck = !_entryData->_dayOfWeekCheck;
|
||||||
_entryData->_condition = MacroConditionDate::Condition::AT;
|
|
||||||
}
|
}
|
||||||
_condition->setCurrentIndex(0);
|
|
||||||
_weekCondition->setCurrentIndex(0);
|
switch (_entryData->_condition) {
|
||||||
|
case MacroConditionDate::Condition::BETWEEN:
|
||||||
|
case MacroConditionDate::Condition::PATTERN:
|
||||||
|
_condition->setCurrentIndex(0);
|
||||||
|
_weekCondition->setCurrentIndex(0);
|
||||||
|
break;
|
||||||
|
case MacroConditionDate::Condition::AT:
|
||||||
|
case MacroConditionDate::Condition::AFTER:
|
||||||
|
case MacroConditionDate::Condition::BEFORE:
|
||||||
|
_weekCondition->setCurrentIndex(
|
||||||
|
static_cast<int>(_entryData->_condition));
|
||||||
|
_condition->setCurrentIndex(
|
||||||
|
static_cast<int>(_entryData->_condition));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
SetWidgetStatus();
|
SetWidgetStatus();
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
|
|||||||
@@ -1,84 +1,24 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "macro-condition-edit.hpp"
|
#include "macro-condition-edit.hpp"
|
||||||
|
#include "macro.hpp"
|
||||||
|
#include "macro-properties.hpp"
|
||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "macro-condition-scene.hpp"
|
#include "macro-condition-scene.hpp"
|
||||||
#include "section.hpp"
|
#include "section.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
std::map<std::string, MacroConditionInfo> &MacroConditionFactory::GetMap()
|
|
||||||
{
|
|
||||||
static std::map<std::string, MacroConditionInfo> _methods;
|
|
||||||
return _methods;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroConditionFactory::Register(const std::string &id,
|
|
||||||
MacroConditionInfo info)
|
|
||||||
{
|
|
||||||
if (auto it = GetMap().find(id); it == GetMap().end()) {
|
|
||||||
GetMap()[id] = info;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<MacroCondition>
|
|
||||||
MacroConditionFactory::Create(const std::string &id, Macro *m)
|
|
||||||
{
|
|
||||||
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
|
||||||
return it->second._createFunc(m);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *
|
|
||||||
MacroConditionFactory::CreateWidget(const std::string &id, QWidget *parent,
|
|
||||||
std::shared_ptr<MacroCondition> cond)
|
|
||||||
{
|
|
||||||
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
|
||||||
return it->second._createWidgetFunc(parent, cond);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string MacroConditionFactory::GetConditionName(const std::string &id)
|
|
||||||
{
|
|
||||||
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
|
||||||
return it->second._name;
|
|
||||||
}
|
|
||||||
return "unknown condition";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string MacroConditionFactory::GetIdByName(const QString &name)
|
|
||||||
{
|
|
||||||
for (auto it : GetMap()) {
|
|
||||||
if (name == obs_module_text(it.second._name.c_str())) {
|
|
||||||
return it.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroConditionFactory::UsesDurationModifier(const std::string &id)
|
|
||||||
{
|
|
||||||
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
|
||||||
return it->second._useDurationModifier;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void populateLogicSelection(QComboBox *list, bool root = false)
|
static inline void populateLogicSelection(QComboBox *list, bool root = false)
|
||||||
{
|
{
|
||||||
if (root) {
|
if (root) {
|
||||||
for (auto entry : MacroCondition::logicTypes) {
|
for (const auto &entry : MacroCondition::logicTypes) {
|
||||||
if (static_cast<int>(entry.first) < logic_root_offset) {
|
if (static_cast<int>(entry.first) < logic_root_offset) {
|
||||||
list->addItem(obs_module_text(
|
list->addItem(obs_module_text(
|
||||||
entry.second._name.c_str()));
|
entry.second._name.c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto entry : MacroCondition::logicTypes) {
|
for (const auto &entry : MacroCondition::logicTypes) {
|
||||||
if (static_cast<int>(entry.first) >=
|
if (static_cast<int>(entry.first) >=
|
||||||
logic_root_offset) {
|
logic_root_offset) {
|
||||||
list->addItem(obs_module_text(
|
list->addItem(obs_module_text(
|
||||||
@@ -90,7 +30,7 @@ static inline void populateLogicSelection(QComboBox *list, bool root = false)
|
|||||||
|
|
||||||
static inline void populateConditionSelection(QComboBox *list)
|
static inline void populateConditionSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
for (auto &[_, condition] :
|
for (const auto &[_, condition] :
|
||||||
MacroConditionFactory::GetConditionTypes()) {
|
MacroConditionFactory::GetConditionTypes()) {
|
||||||
QString entry(obs_module_text(condition._name.c_str()));
|
QString entry(obs_module_text(condition._name.c_str()));
|
||||||
if (list->findText(entry) == -1) {
|
if (list->findText(entry) == -1) {
|
||||||
@@ -179,7 +119,7 @@ void DurationModifierEdit::Collapse(bool collapse)
|
|||||||
MacroConditionEdit::MacroConditionEdit(
|
MacroConditionEdit::MacroConditionEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
|
QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
|
||||||
const std::string &id, bool root)
|
const std::string &id, bool root)
|
||||||
: MacroSegmentEdit(switcher->macroProperties._highlightConditions,
|
: MacroSegmentEdit(GetGlobalMacroProperties()._highlightConditions,
|
||||||
parent),
|
parent),
|
||||||
_logicSelection(new QComboBox()),
|
_logicSelection(new QComboBox()),
|
||||||
_conditionSelection(new FilterComboBox()),
|
_conditionSelection(new FilterComboBox()),
|
||||||
|
|||||||
@@ -1,38 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-condition.hpp"
|
#include "macro-condition.hpp"
|
||||||
|
#include "macro-condition-factory.hpp"
|
||||||
#include "filter-combo-box.hpp"
|
#include "filter-combo-box.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
struct MacroConditionInfo {
|
|
||||||
using TCreateMethod = std::shared_ptr<MacroCondition> (*)(Macro *m);
|
|
||||||
using TCreateWidgetMethod =
|
|
||||||
QWidget *(*)(QWidget *parent, std::shared_ptr<MacroCondition>);
|
|
||||||
TCreateMethod _createFunc = nullptr;
|
|
||||||
TCreateWidgetMethod _createWidgetFunc = nullptr;
|
|
||||||
std::string _name;
|
|
||||||
bool _useDurationModifier = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MacroConditionFactory {
|
|
||||||
public:
|
|
||||||
MacroConditionFactory() = delete;
|
|
||||||
static bool Register(const std::string &, MacroConditionInfo);
|
|
||||||
static std::shared_ptr<MacroCondition> Create(const std::string &,
|
|
||||||
Macro *m);
|
|
||||||
static QWidget *CreateWidget(const std::string &id, QWidget *parent,
|
|
||||||
std::shared_ptr<MacroCondition>);
|
|
||||||
static auto GetConditionTypes() { return GetMap(); }
|
|
||||||
static std::string GetConditionName(const std::string &);
|
|
||||||
static std::string GetIdByName(const QString &name);
|
|
||||||
static bool UsesDurationModifier(const std::string &id);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::map<std::string, MacroConditionInfo> &GetMap();
|
|
||||||
};
|
|
||||||
|
|
||||||
class DurationModifierEdit : public QWidget {
|
class DurationModifierEdit : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|||||||
66
src/macro-core/macro-condition-factory.cpp
Normal file
66
src/macro-core/macro-condition-factory.cpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#include "macro-condition-factory.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
std::map<std::string, MacroConditionInfo> &MacroConditionFactory::GetMap()
|
||||||
|
{
|
||||||
|
static std::map<std::string, MacroConditionInfo> _methods;
|
||||||
|
return _methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionFactory::Register(const std::string &id,
|
||||||
|
MacroConditionInfo info)
|
||||||
|
{
|
||||||
|
if (auto it = GetMap().find(id); it == GetMap().end()) {
|
||||||
|
GetMap()[id] = info;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MacroCondition>
|
||||||
|
MacroConditionFactory::Create(const std::string &id, Macro *m)
|
||||||
|
{
|
||||||
|
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
||||||
|
return it->second._create(m);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *
|
||||||
|
MacroConditionFactory::CreateWidget(const std::string &id, QWidget *parent,
|
||||||
|
std::shared_ptr<MacroCondition> cond)
|
||||||
|
{
|
||||||
|
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
||||||
|
return it->second._createWidget(parent, cond);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MacroConditionFactory::GetConditionName(const std::string &id)
|
||||||
|
{
|
||||||
|
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
||||||
|
return it->second._name;
|
||||||
|
}
|
||||||
|
return "unknown condition";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MacroConditionFactory::GetIdByName(const QString &name)
|
||||||
|
{
|
||||||
|
for (auto it : GetMap()) {
|
||||||
|
if (name == obs_module_text(it.second._name.c_str())) {
|
||||||
|
return it.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionFactory::UsesDurationModifier(const std::string &id)
|
||||||
|
{
|
||||||
|
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
||||||
|
return it->second._useDurationModifier;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
35
src/macro-core/macro-condition-factory.hpp
Normal file
35
src/macro-core/macro-condition-factory.hpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-condition.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
struct MacroConditionInfo {
|
||||||
|
using CreateCondition = std::shared_ptr<MacroCondition> (*)(Macro *m);
|
||||||
|
using CreateConditionWidget =
|
||||||
|
QWidget *(*)(QWidget *parent, std::shared_ptr<MacroCondition>);
|
||||||
|
CreateCondition _create = nullptr;
|
||||||
|
CreateConditionWidget _createWidget = nullptr;
|
||||||
|
std::string _name;
|
||||||
|
bool _useDurationModifier = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionFactory {
|
||||||
|
public:
|
||||||
|
MacroConditionFactory() = delete;
|
||||||
|
static bool Register(const std::string &, MacroConditionInfo);
|
||||||
|
static std::shared_ptr<MacroCondition> Create(const std::string &,
|
||||||
|
Macro *m);
|
||||||
|
static QWidget *CreateWidget(const std::string &id, QWidget *parent,
|
||||||
|
std::shared_ptr<MacroCondition>);
|
||||||
|
static auto GetConditionTypes() { return GetMap(); }
|
||||||
|
static std::string GetConditionName(const std::string &);
|
||||||
|
static std::string GetIdByName(const QString &name);
|
||||||
|
static bool UsesDurationModifier(const std::string &id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::map<std::string, MacroConditionInfo> &GetMap();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
#include "macro-condition-file.hpp"
|
#include "macro-condition-file.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "curl-helper.hpp"
|
#include "curl-helper.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
|
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <array>
|
#include <regex>
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -29,76 +28,99 @@ static size_t WriteCallback(void *contents, size_t size, size_t nmemb,
|
|||||||
static std::string getRemoteData(std::string &url)
|
static std::string getRemoteData(std::string &url)
|
||||||
{
|
{
|
||||||
std::string readBuffer;
|
std::string readBuffer;
|
||||||
switcher->curl.SetOpt(CURLOPT_URL, url.c_str());
|
CurlHelper::SetOpt(CURLOPT_URL, url.c_str());
|
||||||
switcher->curl.SetOpt(CURLOPT_WRITEFUNCTION, WriteCallback);
|
CurlHelper::SetOpt(CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||||
switcher->curl.SetOpt(CURLOPT_WRITEDATA, &readBuffer);
|
CurlHelper::SetOpt(CURLOPT_WRITEDATA, &readBuffer);
|
||||||
// Set timeout to at least one second
|
// Set timeout to at least one second
|
||||||
int timeout = switcher->interval / 1000;
|
int timeout = GetIntervalValue() / 1000;
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
timeout = 1;
|
timeout = 1;
|
||||||
}
|
}
|
||||||
switcher->curl.SetOpt(CURLOPT_TIMEOUT, 1);
|
CurlHelper::SetOpt(CURLOPT_TIMEOUT, 1);
|
||||||
switcher->curl.Perform();
|
CurlHelper::Perform();
|
||||||
return readBuffer;
|
return readBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stringsMatch(const QString &text, const std::string &pattern,
|
bool MacroConditionFile::MatchFileContent(QString &filedata)
|
||||||
const RegexConfig ®ex)
|
|
||||||
{
|
{
|
||||||
auto qpattern = QString::fromStdString(pattern);
|
if (_onlyMatchIfChanged) {
|
||||||
if (regex.Enabled()) {
|
size_t newHash = strHash(filedata.toUtf8().constData());
|
||||||
return regex.Matches(text, qpattern);
|
if (newHash == _lastHash) {
|
||||||
}
|
return false;
|
||||||
auto textCopy = text;
|
|
||||||
return CompareIgnoringLineEnding(qpattern, textCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::optional<QString> getFileContent(MacroConditionFile::FileType type,
|
|
||||||
const std::string &filePath)
|
|
||||||
{
|
|
||||||
QString filedata;
|
|
||||||
switch (type) {
|
|
||||||
case MacroConditionFile::FileType::LOCAL: {
|
|
||||||
std::string path = filePath;
|
|
||||||
QFile file(QString::fromStdString(path));
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
filedata = QTextStream(&file).readAll();
|
_lastHash = newHash;
|
||||||
file.close();
|
|
||||||
} break;
|
|
||||||
case MacroConditionFile::FileType::REMOTE: {
|
|
||||||
std::string path = filePath;
|
|
||||||
std::string data = getRemoteData(path);
|
|
||||||
filedata = QString::fromStdString(data);
|
|
||||||
} break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return filedata;
|
|
||||||
|
if (_regex.Enabled()) {
|
||||||
|
auto expr = _regex.GetRegularExpression(_text);
|
||||||
|
if (!expr.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto match = expr.match(filedata);
|
||||||
|
return match.hasMatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString text = QString::fromStdString(_text);
|
||||||
|
return CompareIgnoringLineEnding(text, filedata);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionFile::CheckFileContentMatch()
|
bool MacroConditionFile::CheckRemoteFileContent()
|
||||||
{
|
{
|
||||||
auto fileData = getFileContent(_fileType, _file);
|
std::string path = _file;
|
||||||
if (!fileData) {
|
std::string data = getRemoteData(path);
|
||||||
|
SetVariableValue(data);
|
||||||
|
QString qdata = QString::fromStdString(data);
|
||||||
|
return MatchFileContent(qdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionFile::CheckLocalFileContent()
|
||||||
|
{
|
||||||
|
QFile file(QString::fromStdString(_file));
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const bool match = stringsMatch(*fileData, _text, _regex);
|
|
||||||
SetVariableValue(fileData->toStdString());
|
if (_useTime) {
|
||||||
|
QDateTime newLastMod = QFileInfo(file).lastModified();
|
||||||
|
if (_lastMod == newLastMod) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_lastMod = newLastMod;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString filedata = QTextStream(&file).readAll();
|
||||||
|
SetVariableValue(filedata.toStdString());
|
||||||
|
bool match = MatchFileContent(filedata);
|
||||||
|
|
||||||
|
file.close();
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionFile::CheckChangeContent()
|
bool MacroConditionFile::CheckChangeContent()
|
||||||
{
|
{
|
||||||
auto filedata = getFileContent(_fileType, _file);
|
QString filedata;
|
||||||
if (!filedata) {
|
switch (_fileType) {
|
||||||
return false;
|
case FileType::LOCAL: {
|
||||||
|
std::string path = _file;
|
||||||
|
QFile file(QString::fromStdString(path));
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
filedata = QTextStream(&file).readAll();
|
||||||
|
file.close();
|
||||||
|
} break;
|
||||||
|
case FileType::REMOTE: {
|
||||||
|
std::string path = _file;
|
||||||
|
std::string data = getRemoteData(path);
|
||||||
|
QString filedata = QString::fromStdString(data);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
size_t newHash = strHash(filedata->toUtf8().constData());
|
|
||||||
|
size_t newHash = strHash(filedata.toUtf8().constData());
|
||||||
const bool contentChanged = newHash != _lastHash;
|
const bool contentChanged = newHash != _lastHash;
|
||||||
_lastHash = newHash;
|
_lastHash = newHash;
|
||||||
SetVariableValue(contentChanged ? "true" : "false");
|
|
||||||
return contentChanged;
|
return contentChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,94 +135,35 @@ bool MacroConditionFile::CheckChangeDate()
|
|||||||
SetVariableValue(newLastMod.toString().toStdString());
|
SetVariableValue(newLastMod.toString().toStdString());
|
||||||
const bool dateChanged = _lastMod != newLastMod;
|
const bool dateChanged = _lastMod != newLastMod;
|
||||||
_lastMod = newLastMod;
|
_lastMod = newLastMod;
|
||||||
SetVariableValue(dateChanged ? "true" : "false");
|
|
||||||
return dateChanged;
|
return dateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStringList splitLines(const QString &string)
|
|
||||||
{
|
|
||||||
static auto regex = QRegularExpression("\n|\r\n|\r");
|
|
||||||
return string.split(regex);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroConditionFile::CheckChangedMatch()
|
|
||||||
{
|
|
||||||
static bool setupDone = false;
|
|
||||||
if (!setupDone) {
|
|
||||||
auto content = getFileContent(_fileType, _file);
|
|
||||||
if (!content) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_previousContent = splitLines(*content);
|
|
||||||
setupDone = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto currentFileContent = getFileContent(_fileType, _file);
|
|
||||||
if (!currentFileContent) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto currentContent = splitLines(*currentFileContent);
|
|
||||||
auto newContent = currentContent;
|
|
||||||
|
|
||||||
QStringList addedLines;
|
|
||||||
QStringList removedLines;
|
|
||||||
|
|
||||||
for (const auto &line : newContent) {
|
|
||||||
if (auto it = std::find(_previousContent.begin(),
|
|
||||||
_previousContent.end(),
|
|
||||||
line) == _previousContent.end()) {
|
|
||||||
addedLines.push_back(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &line : _previousContent) {
|
|
||||||
if (std::find(newContent.begin(), newContent.end(), line) ==
|
|
||||||
newContent.end()) {
|
|
||||||
removedLines.push_back(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_previousContent = currentContent;
|
|
||||||
|
|
||||||
if (_changeMatchType == ChangeMatchType::ADDED ||
|
|
||||||
_changeMatchType == ChangeMatchType::ANY) {
|
|
||||||
for (const auto &line : addedLines) {
|
|
||||||
if (stringsMatch(line, _text, _regex)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_changeMatchType == ChangeMatchType::REMOVED ||
|
|
||||||
_changeMatchType == ChangeMatchType::ANY) {
|
|
||||||
for (const auto &line : removedLines) {
|
|
||||||
if (stringsMatch(line, _text, _regex)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroConditionFile::CheckCondition()
|
bool MacroConditionFile::CheckCondition()
|
||||||
{
|
{
|
||||||
|
bool ret = false;
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case MacroConditionFile::ConditionType::MATCH:
|
case MacroConditionFile::ConditionType::MATCH:
|
||||||
return CheckFileContentMatch();
|
if (_fileType == FileType::REMOTE) {
|
||||||
|
ret = CheckRemoteFileContent();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = CheckLocalFileContent();
|
||||||
|
break;
|
||||||
case MacroConditionFile::ConditionType::CONTENT_CHANGE:
|
case MacroConditionFile::ConditionType::CONTENT_CHANGE:
|
||||||
return CheckChangeContent();
|
ret = CheckChangeContent();
|
||||||
|
break;
|
||||||
case MacroConditionFile::ConditionType::DATE_CHANGE:
|
case MacroConditionFile::ConditionType::DATE_CHANGE:
|
||||||
return CheckChangeDate();
|
ret = CheckChangeDate();
|
||||||
case MacroConditionFile::ConditionType::CHANGES_MATCH:
|
break;
|
||||||
return CheckChangedMatch();
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if (GetVariableValue().empty()) {
|
||||||
|
SetVariableValue(ret ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionFile::Save(obs_data_t *obj) const
|
bool MacroConditionFile::Save(obs_data_t *obj) const
|
||||||
@@ -210,9 +173,9 @@ bool MacroConditionFile::Save(obs_data_t *obj) const
|
|||||||
_file.Save(obj, "file");
|
_file.Save(obj, "file");
|
||||||
_text.Save(obj, "text");
|
_text.Save(obj, "text");
|
||||||
obs_data_set_int(obj, "fileType", static_cast<int>(_fileType));
|
obs_data_set_int(obj, "fileType", static_cast<int>(_fileType));
|
||||||
obs_data_set_int(obj, "changeMatchType",
|
|
||||||
static_cast<int>(_changeMatchType));
|
|
||||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||||
|
obs_data_set_bool(obj, "useTime", _useTime);
|
||||||
|
obs_data_set_bool(obj, "onlyMatchIfChanged", _onlyMatchIfChanged);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,10 +191,10 @@ bool MacroConditionFile::Load(obs_data_t *obj)
|
|||||||
_file.Load(obj, "file");
|
_file.Load(obj, "file");
|
||||||
_text.Load(obj, "text");
|
_text.Load(obj, "text");
|
||||||
_fileType = static_cast<FileType>(obs_data_get_int(obj, "fileType"));
|
_fileType = static_cast<FileType>(obs_data_get_int(obj, "fileType"));
|
||||||
_changeMatchType = static_cast<ChangeMatchType>(
|
|
||||||
obs_data_get_int(obj, "changeMatchType"));
|
|
||||||
_condition =
|
_condition =
|
||||||
static_cast<ConditionType>(obs_data_get_int(obj, "condition"));
|
static_cast<ConditionType>(obs_data_get_int(obj, "condition"));
|
||||||
|
_useTime = obs_data_get_bool(obj, "useTime");
|
||||||
|
_onlyMatchIfChanged = obs_data_get_bool(obj, "onlyMatchIfChanged");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,79 +205,39 @@ std::string MacroConditionFile::GetShortDesc() const
|
|||||||
|
|
||||||
static void populateFileTypes(QComboBox *list)
|
static void populateFileTypes(QComboBox *list)
|
||||||
{
|
{
|
||||||
static constexpr std::array<
|
list->addItem(obs_module_text("AdvSceneSwitcher.condition.file.local"));
|
||||||
std::tuple<MacroConditionFile::FileType, std::string_view>, 2>
|
list->addItem(
|
||||||
fileTypes = {{{MacroConditionFile::FileType::LOCAL,
|
obs_module_text("AdvSceneSwitcher.condition.file.remote"));
|
||||||
"AdvSceneSwitcher.condition.file.local"},
|
|
||||||
{MacroConditionFile::FileType::REMOTE,
|
|
||||||
"AdvSceneSwitcher.condition.file.remote"}}};
|
|
||||||
|
|
||||||
for (const auto &[type, name] : fileTypes) {
|
|
||||||
list->addItem(obs_module_text(name.data()),
|
|
||||||
static_cast<int>(type));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void populateConditions(QComboBox *list)
|
static void populateConditions(QComboBox *list)
|
||||||
{
|
{
|
||||||
static constexpr std::array<
|
list->addItem(
|
||||||
std::tuple<MacroConditionFile::ConditionType, std::string_view>,
|
obs_module_text("AdvSceneSwitcher.condition.file.type.match"));
|
||||||
4>
|
list->addItem(obs_module_text(
|
||||||
conditionTypes = {{
|
"AdvSceneSwitcher.condition.file.type.contentChange"));
|
||||||
{MacroConditionFile::ConditionType::MATCH,
|
list->addItem(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.file.type.match"},
|
"AdvSceneSwitcher.condition.file.type.dateChange"));
|
||||||
{MacroConditionFile::ConditionType::CONTENT_CHANGE,
|
|
||||||
"AdvSceneSwitcher.condition.file.type.contentChange"},
|
|
||||||
{MacroConditionFile::ConditionType::DATE_CHANGE,
|
|
||||||
"AdvSceneSwitcher.condition.file.type.dateChange"},
|
|
||||||
{MacroConditionFile::ConditionType::CHANGES_MATCH,
|
|
||||||
"AdvSceneSwitcher.condition.file.type.changesMatch"},
|
|
||||||
}};
|
|
||||||
|
|
||||||
for (const auto &[type, name] : conditionTypes) {
|
|
||||||
list->addItem(obs_module_text(name.data()),
|
|
||||||
static_cast<int>(type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void populateChangeMatchTypes(QComboBox *list)
|
|
||||||
{
|
|
||||||
static constexpr std::array<
|
|
||||||
std::tuple<MacroConditionFile::ChangeMatchType, std::string_view>,
|
|
||||||
3>
|
|
||||||
matchTypes = {{
|
|
||||||
{MacroConditionFile::ChangeMatchType::ANY,
|
|
||||||
"AdvSceneSwitcher.condition.file.changeMatchType.any"},
|
|
||||||
{MacroConditionFile::ChangeMatchType::ADDED,
|
|
||||||
"AdvSceneSwitcher.condition.file.changeMatchType.added"},
|
|
||||||
{MacroConditionFile::ChangeMatchType::REMOVED,
|
|
||||||
"AdvSceneSwitcher.condition.file.changeMatchType.removed"},
|
|
||||||
}};
|
|
||||||
|
|
||||||
for (const auto &[type, name] : matchTypes) {
|
|
||||||
list->addItem(obs_module_text(name.data()),
|
|
||||||
static_cast<int>(type));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroConditionFileEdit::MacroConditionFileEdit(
|
MacroConditionFileEdit::MacroConditionFileEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroConditionFile> entryData)
|
QWidget *parent, std::shared_ptr<MacroConditionFile> entryData)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_fileTypes(new QComboBox()),
|
_fileTypes(new QComboBox()),
|
||||||
_changeMatchTypes(new QComboBox()),
|
|
||||||
_conditions(new QComboBox()),
|
_conditions(new QComboBox()),
|
||||||
_filePath(new FileSelection()),
|
_filePath(new FileSelection()),
|
||||||
_matchText(new VariableTextEdit(this)),
|
_matchText(new VariableTextEdit(this)),
|
||||||
_regex(new RegexConfigWidget(parent))
|
_regex(new RegexConfigWidget(parent)),
|
||||||
|
_checkModificationDate(new QCheckBox(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.fileTab.checkfileContentTime"))),
|
||||||
|
_checkFileContent(new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.fileTab.checkfileContent")))
|
||||||
{
|
{
|
||||||
populateFileTypes(_fileTypes);
|
populateFileTypes(_fileTypes);
|
||||||
populateConditions(_conditions);
|
populateConditions(_conditions);
|
||||||
populateChangeMatchTypes(_changeMatchTypes);
|
|
||||||
|
|
||||||
QWidget::connect(_fileTypes, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_fileTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(FileTypeChanged(int)));
|
SLOT(FileTypeChanged(int)));
|
||||||
QWidget::connect(_changeMatchTypes, SIGNAL(currentIndexChanged(int)),
|
|
||||||
this, SLOT(ChangeMatchTypeChanged(int)));
|
|
||||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ConditionChanged(int)));
|
SLOT(ConditionChanged(int)));
|
||||||
QWidget::connect(_filePath, SIGNAL(PathChanged(const QString &)), this,
|
QWidget::connect(_filePath, SIGNAL(PathChanged(const QString &)), this,
|
||||||
@@ -323,30 +246,41 @@ MacroConditionFileEdit::MacroConditionFileEdit(
|
|||||||
SLOT(MatchTextChanged()));
|
SLOT(MatchTextChanged()));
|
||||||
QWidget::connect(_regex, SIGNAL(RegexConfigChanged(RegexConfig)), this,
|
QWidget::connect(_regex, SIGNAL(RegexConfigChanged(RegexConfig)), this,
|
||||||
SLOT(RegexChanged(RegexConfig)));
|
SLOT(RegexChanged(RegexConfig)));
|
||||||
|
QWidget::connect(_checkModificationDate, SIGNAL(stateChanged(int)),
|
||||||
|
this, SLOT(CheckModificationDateChanged(int)));
|
||||||
|
QWidget::connect(_checkFileContent, SIGNAL(stateChanged(int)), this,
|
||||||
|
SLOT(OnlyMatchIfChangedChanged(int)));
|
||||||
|
|
||||||
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{fileType}}", _fileTypes},
|
{"{{fileType}}", _fileTypes},
|
||||||
{"{{changeMatchType}}", _changeMatchTypes},
|
|
||||||
{"{{conditions}}", _conditions},
|
{"{{conditions}}", _conditions},
|
||||||
{"{{filePath}}", _filePath},
|
{"{{filePath}}", _filePath},
|
||||||
{"{{matchText}}", _matchText},
|
{"{{matchText}}", _matchText},
|
||||||
{"{{useRegex}}", _regex},
|
{"{{useRegex}}", _regex},
|
||||||
|
{"{{checkModificationDate}}", _checkModificationDate},
|
||||||
|
{"{{checkFileContent}}", _checkFileContent},
|
||||||
};
|
};
|
||||||
|
|
||||||
auto line1Layout = new QHBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||||
|
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||||
|
QHBoxLayout *line3Layout = new QHBoxLayout;
|
||||||
line1Layout->setContentsMargins(0, 0, 0, 0);
|
line1Layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
line2Layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
line3Layout->setContentsMargins(0, 0, 0, 0);
|
||||||
PlaceWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.condition.file.entry.line1"),
|
obs_module_text("AdvSceneSwitcher.condition.file.entry.line1"),
|
||||||
line1Layout, widgetPlaceholders);
|
line1Layout, widgetPlaceholders);
|
||||||
auto line2Layout = new QHBoxLayout;
|
|
||||||
line2Layout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
PlaceWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.condition.file.entry.line2"),
|
obs_module_text("AdvSceneSwitcher.condition.file.entry.line2"),
|
||||||
line2Layout, widgetPlaceholders, false);
|
line2Layout, widgetPlaceholders, false);
|
||||||
|
PlaceWidgets(
|
||||||
auto mainLayout = new QVBoxLayout;
|
obs_module_text("AdvSceneSwitcher.condition.file.entry.line3"),
|
||||||
|
line3Layout, widgetPlaceholders);
|
||||||
mainLayout->addLayout(line1Layout);
|
mainLayout->addLayout(line1Layout);
|
||||||
mainLayout->addLayout(line2Layout);
|
mainLayout->addLayout(line2Layout);
|
||||||
|
mainLayout->addLayout(line3Layout);
|
||||||
|
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
@@ -360,15 +294,21 @@ void MacroConditionFileEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_fileTypes->setCurrentIndex(
|
_fileTypes->setCurrentIndex(static_cast<int>(_entryData->_fileType));
|
||||||
_fileTypes->findData(static_cast<int>(_entryData->_fileType)));
|
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||||
_conditions->setCurrentIndex(_conditions->findData(
|
|
||||||
static_cast<int>(_entryData->_condition)));
|
|
||||||
_changeMatchTypes->setCurrentIndex(_changeMatchTypes->findData(
|
|
||||||
static_cast<int>(_entryData->_changeMatchType)));
|
|
||||||
_filePath->SetPath(_entryData->_file);
|
_filePath->SetPath(_entryData->_file);
|
||||||
_matchText->setPlainText(_entryData->_text);
|
_matchText->setPlainText(_entryData->_text);
|
||||||
_regex->SetRegexConfig(_entryData->_regex);
|
_regex->SetRegexConfig(_entryData->_regex);
|
||||||
|
_checkModificationDate->setChecked(_entryData->_useTime);
|
||||||
|
_checkFileContent->setChecked(_entryData->_onlyMatchIfChanged);
|
||||||
|
|
||||||
|
// TODO: Remove in future version
|
||||||
|
if (!_entryData->_useTime) {
|
||||||
|
_checkModificationDate->hide();
|
||||||
|
}
|
||||||
|
if (!_entryData->_onlyMatchIfChanged) {
|
||||||
|
_checkFileContent->hide();
|
||||||
|
}
|
||||||
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
@@ -379,25 +319,19 @@ void MacroConditionFileEdit::FileTypeChanged(int index)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto type = static_cast<MacroConditionFile::FileType>(
|
MacroConditionFile::FileType type =
|
||||||
_fileTypes->itemData(index).toInt());
|
static_cast<MacroConditionFile::FileType>(index);
|
||||||
_filePath->Button()->setEnabled(type ==
|
|
||||||
MacroConditionFile::FileType::LOCAL);
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_fileType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionFileEdit::ChangeMatchTypeChanged(int index)
|
if (type == MacroConditionFile::FileType::LOCAL) {
|
||||||
{
|
_filePath->Button()->setDisabled(false);
|
||||||
if (_loading || !_entryData) {
|
_checkModificationDate->setDisabled(false);
|
||||||
return;
|
} else {
|
||||||
|
_filePath->Button()->setDisabled(true);
|
||||||
|
_checkModificationDate->setDisabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_changeMatchType =
|
_entryData->_fileType = type;
|
||||||
static_cast<MacroConditionFile::ChangeMatchType>(
|
|
||||||
_changeMatchTypes->itemData(index).toInt());
|
|
||||||
SetWidgetVisibility();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionFileEdit::ConditionChanged(int index)
|
void MacroConditionFileEdit::ConditionChanged(int index)
|
||||||
@@ -407,8 +341,8 @@ void MacroConditionFileEdit::ConditionChanged(int index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_condition = static_cast<MacroConditionFile::ConditionType>(
|
_entryData->_condition =
|
||||||
_conditions->itemData(index).toInt());
|
static_cast<MacroConditionFile::ConditionType>(index);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,25 +383,44 @@ void MacroConditionFileEdit::RegexChanged(RegexConfig conf)
|
|||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroConditionFileEdit::CheckModificationDateChanged(int state)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_useTime = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionFileEdit::OnlyMatchIfChangedChanged(int state)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = LockContext();
|
||||||
|
_entryData->_onlyMatchIfChanged = state;
|
||||||
|
}
|
||||||
|
|
||||||
void MacroConditionFileEdit::SetWidgetVisibility()
|
void MacroConditionFileEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
if (!_entryData) {
|
if (!_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_changeMatchTypes->setVisible(
|
_matchText->setVisible(_entryData->_condition ==
|
||||||
|
MacroConditionFile::ConditionType::MATCH);
|
||||||
|
_regex->setVisible(_entryData->_condition ==
|
||||||
|
MacroConditionFile::ConditionType::MATCH);
|
||||||
|
_checkModificationDate->setVisible(
|
||||||
|
_entryData->_useTime &&
|
||||||
_entryData->_condition ==
|
_entryData->_condition ==
|
||||||
MacroConditionFile::ConditionType::CHANGES_MATCH);
|
MacroConditionFile::ConditionType::MATCH);
|
||||||
_matchText->setVisible(
|
_checkFileContent->setVisible(
|
||||||
|
_entryData->_onlyMatchIfChanged &&
|
||||||
_entryData->_condition ==
|
_entryData->_condition ==
|
||||||
MacroConditionFile::ConditionType::MATCH ||
|
MacroConditionFile::ConditionType::MATCH);
|
||||||
_entryData->_condition ==
|
|
||||||
MacroConditionFile::ConditionType::CHANGES_MATCH);
|
|
||||||
_regex->setVisible(
|
|
||||||
_entryData->_condition ==
|
|
||||||
MacroConditionFile::ConditionType::MATCH ||
|
|
||||||
_entryData->_condition ==
|
|
||||||
MacroConditionFile::ConditionType::CHANGES_MATCH);
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -36,31 +35,27 @@ public:
|
|||||||
MATCH,
|
MATCH,
|
||||||
CONTENT_CHANGE,
|
CONTENT_CHANGE,
|
||||||
DATE_CHANGE,
|
DATE_CHANGE,
|
||||||
CHANGES_MATCH,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ChangeMatchType {
|
|
||||||
ANY,
|
|
||||||
ADDED,
|
|
||||||
REMOVED,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
StringVariable _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
StringVariable _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||||
StringVariable _text = obs_module_text("AdvSceneSwitcher.enterText");
|
StringVariable _text = obs_module_text("AdvSceneSwitcher.enterText");
|
||||||
FileType _fileType = FileType::LOCAL;
|
FileType _fileType = FileType::LOCAL;
|
||||||
ChangeMatchType _changeMatchType = ChangeMatchType::ANY;
|
|
||||||
ConditionType _condition = ConditionType::MATCH;
|
ConditionType _condition = ConditionType::MATCH;
|
||||||
RegexConfig _regex;
|
RegexConfig _regex;
|
||||||
|
|
||||||
|
// TODO: Remove in future version
|
||||||
|
bool _useTime = false;
|
||||||
|
bool _onlyMatchIfChanged = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CheckFileContentMatch();
|
bool MatchFileContent(QString &filedata);
|
||||||
|
bool CheckRemoteFileContent();
|
||||||
|
bool CheckLocalFileContent();
|
||||||
bool CheckChangeContent();
|
bool CheckChangeContent();
|
||||||
bool CheckChangeDate();
|
bool CheckChangeDate();
|
||||||
bool CheckChangedMatch();
|
|
||||||
|
|
||||||
QDateTime _lastMod;
|
QDateTime _lastMod;
|
||||||
size_t _lastHash = 0;
|
size_t _lastHash = 0;
|
||||||
QStringList _previousContent;
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
};
|
};
|
||||||
@@ -83,21 +78,23 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void FileTypeChanged(int index);
|
void FileTypeChanged(int index);
|
||||||
void ChangeMatchTypeChanged(int index);
|
|
||||||
void ConditionChanged(int index);
|
void ConditionChanged(int index);
|
||||||
void PathChanged(const QString &text);
|
void PathChanged(const QString &text);
|
||||||
void MatchTextChanged();
|
void MatchTextChanged();
|
||||||
void RegexChanged(RegexConfig);
|
void RegexChanged(RegexConfig);
|
||||||
|
void CheckModificationDateChanged(int state);
|
||||||
|
void OnlyMatchIfChangedChanged(int state);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QComboBox *_fileTypes;
|
QComboBox *_fileTypes;
|
||||||
QComboBox *_changeMatchTypes;
|
|
||||||
QComboBox *_conditions;
|
QComboBox *_conditions;
|
||||||
FileSelection *_filePath;
|
FileSelection *_filePath;
|
||||||
VariableTextEdit *_matchText;
|
VariableTextEdit *_matchText;
|
||||||
RegexConfigWidget *_regex;
|
RegexConfigWidget *_regex;
|
||||||
|
QCheckBox *_checkModificationDate;
|
||||||
|
QCheckBox *_checkFileContent;
|
||||||
std::shared_ptr<MacroConditionFile> _entryData;
|
std::shared_ptr<MacroConditionFile> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "macro-condition-media.hpp"
|
#include "macro-condition-media.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
|
#include "scene-switch-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -148,26 +150,20 @@ bool MacroConditionMedia::CheckMediaMatch()
|
|||||||
if (!_source.GetSource()) {
|
if (!_source.GetSource()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool match = false;
|
|
||||||
bool matched = CheckState() && CheckTime();
|
bool matched = CheckState() && CheckTime();
|
||||||
|
|
||||||
if (matched && !(_onlyMatchOnChagne && _alreadyMatched)) {
|
|
||||||
match = true;
|
|
||||||
}
|
|
||||||
_alreadyMatched = matched;
|
|
||||||
|
|
||||||
// reset for next check
|
// reset for next check
|
||||||
_stopped = false;
|
_stopped = false;
|
||||||
_ended = false;
|
_ended = false;
|
||||||
_next = false;
|
_next = false;
|
||||||
|
|
||||||
return match;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMedia::HandleSceneChange()
|
void MacroConditionMedia::HandleSceneChange()
|
||||||
{
|
{
|
||||||
UpdateMediaSourcesOfSceneList();
|
UpdateMediaSourcesOfSceneList();
|
||||||
_lastConfigureScene = switcher->currentScene;
|
_lastConfigureScene = GetCurrentScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionMedia::CheckCondition()
|
bool MacroConditionMedia::CheckCondition()
|
||||||
@@ -194,7 +190,7 @@ bool MacroConditionMedia::CheckCondition()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_lastConfigureScene != switcher->currentScene) {
|
if (_lastConfigureScene != GetCurrentScene()) {
|
||||||
HandleSceneChange();
|
HandleSceneChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +206,6 @@ bool MacroConditionMedia::Save(obs_data_t *obj) const
|
|||||||
obs_data_set_int(obj, "state", static_cast<int>(_state));
|
obs_data_set_int(obj, "state", static_cast<int>(_state));
|
||||||
obs_data_set_int(obj, "restriction", static_cast<int>(_restriction));
|
obs_data_set_int(obj, "restriction", static_cast<int>(_restriction));
|
||||||
_time.Save(obj);
|
_time.Save(obj);
|
||||||
obs_data_set_bool(obj, "matchOnChagne", _onlyMatchOnChagne);
|
|
||||||
obs_data_set_int(obj, "version", 0);
|
obs_data_set_int(obj, "version", 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -268,7 +263,6 @@ bool MacroConditionMedia::Load(obs_data_t *obj)
|
|||||||
_restriction = static_cast<MacroConditionMedia::Time>(
|
_restriction = static_cast<MacroConditionMedia::Time>(
|
||||||
obs_data_get_int(obj, "restriction"));
|
obs_data_get_int(obj, "restriction"));
|
||||||
_time.Load(obj);
|
_time.Load(obj);
|
||||||
_onlyMatchOnChagne = obs_data_get_bool(obj, "matchOnChagne");
|
|
||||||
|
|
||||||
if (_sourceType == Type::SOURCE) {
|
if (_sourceType == Type::SOURCE) {
|
||||||
obs_source_t *mediasource =
|
obs_source_t *mediasource =
|
||||||
@@ -408,9 +402,7 @@ MacroConditionMediaEdit::MacroConditionMediaEdit(
|
|||||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||||
_states(new QComboBox()),
|
_states(new QComboBox()),
|
||||||
_timeRestrictions(new QComboBox()),
|
_timeRestrictions(new QComboBox()),
|
||||||
_time(new DurationSelection()),
|
_time(new DurationSelection())
|
||||||
_onChange(new QCheckBox(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.condition.media.matchOnChange")))
|
|
||||||
{
|
{
|
||||||
_states->setToolTip(obs_module_text(
|
_states->setToolTip(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.media.inconsistencyInfo"));
|
"AdvSceneSwitcher.condition.media.inconsistencyInfo"));
|
||||||
@@ -432,14 +424,12 @@ MacroConditionMediaEdit::MacroConditionMediaEdit(
|
|||||||
this, SLOT(TimeRestrictionChanged(int)));
|
this, SLOT(TimeRestrictionChanged(int)));
|
||||||
QWidget::connect(_time, SIGNAL(DurationChanged(const Duration &)), this,
|
QWidget::connect(_time, SIGNAL(DurationChanged(const Duration &)), this,
|
||||||
SLOT(TimeChanged(const Duration &)));
|
SLOT(TimeChanged(const Duration &)));
|
||||||
QWidget::connect(_onChange, SIGNAL(stateChanged(int)), this,
|
|
||||||
SLOT(OnChangeChanged(int)));
|
|
||||||
|
|
||||||
populateSourceTypes(_sourceTypes);
|
populateSourceTypes(_sourceTypes);
|
||||||
populateMediaStates(_states);
|
populateMediaStates(_states);
|
||||||
populateMediaTimes(_timeRestrictions);
|
populateMediaTimes(_timeRestrictions);
|
||||||
|
|
||||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
auto layout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{sourceTypes}}", _sourceTypes},
|
{"{{sourceTypes}}", _sourceTypes},
|
||||||
{"{{mediaSources}}", _sources},
|
{"{{mediaSources}}", _sources},
|
||||||
@@ -449,11 +439,8 @@ MacroConditionMediaEdit::MacroConditionMediaEdit(
|
|||||||
{"{{time}}", _time},
|
{"{{time}}", _time},
|
||||||
};
|
};
|
||||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.condition.media.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.condition.media.entry"),
|
||||||
entryLayout, widgetPlaceholders);
|
layout, widgetPlaceholders);
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
setLayout(layout);
|
||||||
mainLayout->addLayout(entryLayout);
|
|
||||||
mainLayout->addWidget(_onChange);
|
|
||||||
setLayout(mainLayout);
|
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
UpdateEntryData();
|
UpdateEntryData();
|
||||||
@@ -572,28 +559,12 @@ void MacroConditionMediaEdit::TimeChanged(const Duration &dur)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMediaEdit::OnChangeChanged(int value)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_onlyMatchOnChagne = value;
|
|
||||||
if (_entryData->_sourceType != MacroConditionMedia::Type::SOURCE) {
|
|
||||||
_entryData->UpdateMediaSourcesOfSceneList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionMediaEdit::SetWidgetVisibility()
|
void MacroConditionMediaEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
_sources->setVisible(_entryData->_sourceType ==
|
_sources->setVisible(_entryData->_sourceType ==
|
||||||
MacroConditionMedia::Type::SOURCE);
|
MacroConditionMedia::Type::SOURCE);
|
||||||
_scenes->setVisible(_entryData->_sourceType !=
|
_scenes->setVisible(_entryData->_sourceType !=
|
||||||
MacroConditionMedia::Type::SOURCE);
|
MacroConditionMedia::Type::SOURCE);
|
||||||
if (!_onChange->isChecked()) {
|
|
||||||
_onChange->hide();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getIdxFromMediaState(MacroConditionMedia::State state)
|
static int getIdxFromMediaState(MacroConditionMedia::State state)
|
||||||
@@ -625,7 +596,6 @@ void MacroConditionMediaEdit::UpdateEntryData()
|
|||||||
MacroConditionMedia::Time::TIME_RESTRICTION_NONE) {
|
MacroConditionMedia::Time::TIME_RESTRICTION_NONE) {
|
||||||
_time->setDisabled(true);
|
_time->setDisabled(true);
|
||||||
}
|
}
|
||||||
_onChange->setChecked(_entryData->_onlyMatchOnChagne);
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ public:
|
|||||||
OBSWeakSource _rawSource = nullptr;
|
OBSWeakSource _rawSource = nullptr;
|
||||||
std::vector<MacroConditionMedia> _sourceGroup;
|
std::vector<MacroConditionMedia> _sourceGroup;
|
||||||
Duration _time;
|
Duration _time;
|
||||||
bool _onlyMatchOnChagne = false;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CheckTime();
|
bool CheckTime();
|
||||||
@@ -84,9 +83,7 @@ private:
|
|||||||
bool _stopped = false;
|
bool _stopped = false;
|
||||||
bool _ended = false;
|
bool _ended = false;
|
||||||
bool _next = false;
|
bool _next = false;
|
||||||
// TODO: Remove _alreadyMatched as it does not make much sense when
|
|
||||||
// time restrictions for macro conditions are available.
|
|
||||||
bool _alreadyMatched = false;
|
|
||||||
// Workaround to enable use of "ended" to specify end of VLC playlist
|
// Workaround to enable use of "ended" to specify end of VLC playlist
|
||||||
bool _previousStateEnded = false;
|
bool _previousStateEnded = false;
|
||||||
// Used to keep track of scene changes
|
// Used to keep track of scene changes
|
||||||
@@ -119,7 +116,6 @@ private slots:
|
|||||||
void StateChanged(int index);
|
void StateChanged(int index);
|
||||||
void TimeRestrictionChanged(int index);
|
void TimeRestrictionChanged(int index);
|
||||||
void TimeChanged(const Duration &seconds);
|
void TimeChanged(const Duration &seconds);
|
||||||
void OnChangeChanged(int);
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
@@ -130,7 +126,6 @@ protected:
|
|||||||
QComboBox *_states;
|
QComboBox *_states;
|
||||||
QComboBox *_timeRestrictions;
|
QComboBox *_timeRestrictions;
|
||||||
DurationSelection *_time;
|
DurationSelection *_time;
|
||||||
QCheckBox *_onChange;
|
|
||||||
std::shared_ptr<MacroConditionMedia> _entryData;
|
std::shared_ptr<MacroConditionMedia> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "macro-condition-plugin-state.hpp"
|
#include "macro-condition-plugin-state.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "macro-helpers.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -33,7 +34,7 @@ const static std::map<MacroConditionPluginState::Condition, std::string>
|
|||||||
MacroConditionPluginState::~MacroConditionPluginState()
|
MacroConditionPluginState::~MacroConditionPluginState()
|
||||||
{
|
{
|
||||||
if (_condition == Condition::OBS_SHUTDOWN) {
|
if (_condition == Condition::OBS_SHUTDOWN) {
|
||||||
switcher->shutdownConditionCount--;
|
GetShutdownConditionCount()--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,15 +42,15 @@ bool MacroConditionPluginState::CheckCondition()
|
|||||||
{
|
{
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case Condition::PLUGIN_SCENE_CHANGE:
|
case Condition::PLUGIN_SCENE_CHANGE:
|
||||||
return switcher->macroSceneSwitched;
|
return MacroSwitchedScene();
|
||||||
case Condition::PLUGIN_RUNNING:
|
case Condition::PLUGIN_RUNNING:
|
||||||
return true;
|
return true;
|
||||||
case Condition::OBS_SHUTDOWN:
|
case Condition::OBS_SHUTDOWN:
|
||||||
return switcher->obsIsShuttingDown;
|
return OBSIsShuttingDown();
|
||||||
case Condition::PLUGIN_START:
|
case Condition::PLUGIN_START:
|
||||||
return switcher->firstInterval;
|
return IsFirstInterval();
|
||||||
case Condition::PLUGIN_RESTART:
|
case Condition::PLUGIN_RESTART:
|
||||||
return switcher->firstIntervalAfterStop;
|
return IsFirstIntervalAfterStop();
|
||||||
case Condition::SCENE_COLLECTION_CHANGE:
|
case Condition::SCENE_COLLECTION_CHANGE:
|
||||||
if (_firstCheckAfterSceneCollectionChange) {
|
if (_firstCheckAfterSceneCollectionChange) {
|
||||||
_firstCheckAfterSceneCollectionChange = false;
|
_firstCheckAfterSceneCollectionChange = false;
|
||||||
@@ -83,25 +84,33 @@ bool MacroConditionPluginState::Load(obs_data_t *obj)
|
|||||||
obs_data_get_int(obj, "condition"));
|
obs_data_get_int(obj, "condition"));
|
||||||
switch (oldValue) {
|
switch (oldValue) {
|
||||||
case PluginStateCondition::SCENE_SWITCHED:
|
case PluginStateCondition::SCENE_SWITCHED:
|
||||||
_condition = Condition::PLUGIN_SCENE_CHANGE;
|
SetCondition(Condition::PLUGIN_SCENE_CHANGE);
|
||||||
break;
|
break;
|
||||||
case PluginStateCondition::RUNNING:
|
case PluginStateCondition::RUNNING:
|
||||||
_condition = Condition::PLUGIN_RUNNING;
|
SetCondition(Condition::PLUGIN_RUNNING);
|
||||||
break;
|
break;
|
||||||
case PluginStateCondition::SHUTDOWN:
|
case PluginStateCondition::SHUTDOWN:
|
||||||
_condition = Condition::OBS_SHUTDOWN;
|
SetCondition(Condition::OBS_SHUTDOWN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_condition = static_cast<Condition>(
|
SetCondition(static_cast<Condition>(
|
||||||
obs_data_get_int(obj, "condition"));
|
obs_data_get_int(obj, "condition")));
|
||||||
}
|
|
||||||
if (_condition == Condition::OBS_SHUTDOWN) {
|
|
||||||
switcher->shutdownConditionCount++;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroConditionPluginState::SetCondition(Condition newValue)
|
||||||
|
{
|
||||||
|
if (_condition == Condition::OBS_SHUTDOWN) {
|
||||||
|
GetShutdownConditionCount()--;
|
||||||
|
}
|
||||||
|
if (newValue == Condition::OBS_SHUTDOWN) {
|
||||||
|
GetShutdownConditionCount()++;
|
||||||
|
}
|
||||||
|
_condition = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void populateConditionSelection(QComboBox *list)
|
static inline void populateConditionSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
for (const auto &[action, name] : pluginStateConditionTypes) {
|
for (const auto &[action, name] : pluginStateConditionTypes) {
|
||||||
@@ -148,17 +157,9 @@ void MacroConditionPluginStateEdit::ConditionChanged(int idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
if (_entryData->_condition ==
|
_entryData->SetCondition(
|
||||||
MacroConditionPluginState::Condition::OBS_SHUTDOWN) {
|
|
||||||
switcher->shutdownConditionCount--;
|
|
||||||
}
|
|
||||||
_entryData->_condition =
|
|
||||||
static_cast<MacroConditionPluginState::Condition>(
|
static_cast<MacroConditionPluginState::Condition>(
|
||||||
_condition->itemData(idx).toInt());
|
_condition->itemData(idx).toInt()));
|
||||||
if (_entryData->_condition ==
|
|
||||||
MacroConditionPluginState::Condition::OBS_SHUTDOWN) {
|
|
||||||
switcher->shutdownConditionCount++;
|
|
||||||
}
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,15 +169,15 @@ void MacroConditionPluginStateEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_condition->setCurrentIndex(
|
_condition->setCurrentIndex(_condition->findData(
|
||||||
_condition->findData(static_cast<int>(_entryData->_condition)));
|
static_cast<int>(_entryData->GetCondition())));
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionPluginStateEdit::SetWidgetVisibility()
|
void MacroConditionPluginStateEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
_shutdownLimitation->setVisible(
|
_shutdownLimitation->setVisible(
|
||||||
_entryData->_condition ==
|
_entryData->GetCondition() ==
|
||||||
MacroConditionPluginState::Condition::OBS_SHUTDOWN);
|
MacroConditionPluginState::Condition::OBS_SHUTDOWN);
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ public:
|
|||||||
SCENE_COLLECTION_CHANGE,
|
SCENE_COLLECTION_CHANGE,
|
||||||
PLUGIN_SCENE_CHANGE,
|
PLUGIN_SCENE_CHANGE,
|
||||||
};
|
};
|
||||||
|
void SetCondition(Condition);
|
||||||
Condition _condition = Condition::PLUGIN_SCENE_CHANGE;
|
Condition GetCondition() const { return _condition; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Condition _condition = Condition::PLUGIN_SCENE_CHANGE;
|
||||||
bool _firstCheckAfterSceneCollectionChange = true;
|
bool _firstCheckAfterSceneCollectionChange = true;
|
||||||
|
|
||||||
const static uint32_t _version;
|
const static uint32_t _version;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "macro-condition-process.hpp"
|
#include "macro-condition-process.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "platform-funcs.hpp"
|
#include "platform-funcs.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
@@ -172,8 +171,9 @@ void MacroConditionProcessEdit::FocusChanged(int state)
|
|||||||
|
|
||||||
void MacroConditionProcessEdit::UpdateFocusProcess()
|
void MacroConditionProcessEdit::UpdateFocusProcess()
|
||||||
{
|
{
|
||||||
_focusProcess->setText(
|
std::string name;
|
||||||
QString::fromStdString(switcher->currentForegroundProcess));
|
GetForegroundProcessName(name);
|
||||||
|
_focusProcess->setText(QString::fromStdString(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionProcessEdit::SetWidgetVisibility()
|
void MacroConditionProcessEdit::SetWidgetVisibility()
|
||||||
|
|||||||
@@ -178,6 +178,8 @@ bool SetupRecordingTimer()
|
|||||||
case OBS_FRONTEND_EVENT_RECORDING_UNPAUSED:
|
case OBS_FRONTEND_EVENT_RECORDING_UNPAUSED:
|
||||||
recordingPaused = false;
|
recordingPaused = false;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
obs_frontend_add_event_callback(handleRecordingEvents, nullptr);
|
obs_frontend_add_event_callback(handleRecordingEvents, nullptr);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "macro-condition-replay-buffer.hpp"
|
#include "macro-condition-replay-buffer.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -11,35 +10,63 @@ bool MacroConditionReplayBuffer::_registered = MacroConditionFactory::Register(
|
|||||||
MacroConditionReplayBufferEdit::Create,
|
MacroConditionReplayBufferEdit::Create,
|
||||||
"AdvSceneSwitcher.condition.replay"});
|
"AdvSceneSwitcher.condition.replay"});
|
||||||
|
|
||||||
const static std::map<ReplayBufferState, std::string> ReplayBufferStates = {
|
const static std::map<MacroConditionReplayBuffer::Condition, std::string>
|
||||||
{ReplayBufferState::STOP,
|
conditions = {
|
||||||
"AdvSceneSwitcher.condition.replay.state.stopped"},
|
{MacroConditionReplayBuffer::Condition::STOP,
|
||||||
{ReplayBufferState::START,
|
"AdvSceneSwitcher.condition.replay.state.stopped"},
|
||||||
"AdvSceneSwitcher.condition.replay.state.started"},
|
{MacroConditionReplayBuffer::Condition::START,
|
||||||
{ReplayBufferState::SAVE,
|
"AdvSceneSwitcher.condition.replay.state.started"},
|
||||||
"AdvSceneSwitcher.condition.replay.state.saved"},
|
{MacroConditionReplayBuffer::Condition::SAVE,
|
||||||
|
"AdvSceneSwitcher.condition.replay.state.saved"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool replayBufferSaved = false;
|
||||||
|
|
||||||
|
static std::chrono::high_resolution_clock::time_point replayBufferSaveTime{};
|
||||||
|
static bool setupReplayBufferEventHandler();
|
||||||
|
static bool replayBufferEventHandlerIsSetup = setupReplayBufferEventHandler();
|
||||||
|
|
||||||
|
static bool setupReplayBufferEventHandler()
|
||||||
|
{
|
||||||
|
static auto handleReplayBufferEvent = [](enum obs_frontend_event event,
|
||||||
|
void *) {
|
||||||
|
switch (event) {
|
||||||
|
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
|
||||||
|
replayBufferSaveTime =
|
||||||
|
std::chrono::high_resolution_clock::now();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
obs_frontend_add_event_callback(handleReplayBufferEvent, nullptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionReplayBuffer::ReplayBufferWasSaved()
|
||||||
|
{
|
||||||
|
bool timersAreInitialized =
|
||||||
|
_saveTime.time_since_epoch().count() != 0 &&
|
||||||
|
replayBufferSaveTime.time_since_epoch().count() != 0;
|
||||||
|
bool newSaveOccurred = timersAreInitialized &&
|
||||||
|
_saveTime != replayBufferSaveTime;
|
||||||
|
_saveTime = replayBufferSaveTime;
|
||||||
|
return newSaveOccurred;
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroConditionReplayBuffer::CheckCondition()
|
bool MacroConditionReplayBuffer::CheckCondition()
|
||||||
{
|
{
|
||||||
bool stateMatch = false;
|
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
case ReplayBufferState::STOP:
|
case Condition::STOP:
|
||||||
stateMatch = !obs_frontend_replay_buffer_active();
|
return !obs_frontend_replay_buffer_active();
|
||||||
break;
|
case Condition::START:
|
||||||
case ReplayBufferState::START:
|
return obs_frontend_replay_buffer_active();
|
||||||
stateMatch = obs_frontend_replay_buffer_active();
|
case Condition::SAVE:
|
||||||
break;
|
return ReplayBufferWasSaved();
|
||||||
case ReplayBufferState::SAVE:
|
|
||||||
if (switcher->replayBufferSaved) {
|
|
||||||
stateMatch = true;
|
|
||||||
switcher->replayBufferSaved = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return stateMatch;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionReplayBuffer::Save(obs_data_t *obj) const
|
bool MacroConditionReplayBuffer::Save(obs_data_t *obj) const
|
||||||
@@ -52,37 +79,30 @@ bool MacroConditionReplayBuffer::Save(obs_data_t *obj) const
|
|||||||
bool MacroConditionReplayBuffer::Load(obs_data_t *obj)
|
bool MacroConditionReplayBuffer::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroCondition::Load(obj);
|
MacroCondition::Load(obj);
|
||||||
_state = static_cast<ReplayBufferState>(obs_data_get_int(obj, "state"));
|
_state = static_cast<Condition>(obs_data_get_int(obj, "state"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void populateStateSelection(QComboBox *list)
|
static inline void populateStateSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
for (auto entry : ReplayBufferStates) {
|
for (const auto &entry : conditions) {
|
||||||
list->addItem(obs_module_text(entry.second.c_str()));
|
list->addItem(obs_module_text(entry.second.c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroConditionReplayBufferEdit::MacroConditionReplayBufferEdit(
|
MacroConditionReplayBufferEdit::MacroConditionReplayBufferEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroConditionReplayBuffer> entryData)
|
QWidget *parent, std::shared_ptr<MacroConditionReplayBuffer> entryData)
|
||||||
: QWidget(parent)
|
: QWidget(parent), _state(new QComboBox())
|
||||||
{
|
{
|
||||||
_state = new QComboBox();
|
|
||||||
|
|
||||||
QWidget::connect(_state, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_state, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(StateChanged(int)));
|
SLOT(StateChanged(int)));
|
||||||
|
|
||||||
populateStateSelection(_state);
|
populateStateSelection(_state);
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
auto layout = new QHBoxLayout;
|
||||||
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
|
||||||
{"{{state}}", _state},
|
|
||||||
};
|
|
||||||
|
|
||||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.condition.replay.entry"),
|
PlaceWidgets(obs_module_text("AdvSceneSwitcher.condition.replay.entry"),
|
||||||
mainLayout, widgetPlaceholders);
|
layout, {{"{{state}}", _state}});
|
||||||
setLayout(mainLayout);
|
setLayout(layout);
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
UpdateEntryData();
|
UpdateEntryData();
|
||||||
@@ -96,7 +116,8 @@ void MacroConditionReplayBufferEdit::StateChanged(int value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_state = static_cast<ReplayBufferState>(value);
|
_entryData->_state =
|
||||||
|
static_cast<MacroConditionReplayBuffer::Condition>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionReplayBufferEdit::UpdateEntryData()
|
void MacroConditionReplayBufferEdit::UpdateEntryData()
|
||||||
|
|||||||
@@ -6,12 +6,6 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
enum class ReplayBufferState {
|
|
||||||
STOP,
|
|
||||||
START,
|
|
||||||
SAVE,
|
|
||||||
};
|
|
||||||
|
|
||||||
class MacroConditionReplayBuffer : public MacroCondition {
|
class MacroConditionReplayBuffer : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
MacroConditionReplayBuffer(Macro *m) : MacroCondition(m) {}
|
MacroConditionReplayBuffer(Macro *m) : MacroCondition(m) {}
|
||||||
@@ -24,9 +18,18 @@ public:
|
|||||||
return std::make_shared<MacroConditionReplayBuffer>(m);
|
return std::make_shared<MacroConditionReplayBuffer>(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReplayBufferState _state = ReplayBufferState::STOP;
|
enum class Condition {
|
||||||
|
STOP,
|
||||||
|
START,
|
||||||
|
SAVE,
|
||||||
|
};
|
||||||
|
|
||||||
|
Condition _state = Condition::STOP;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool ReplayBufferWasSaved();
|
||||||
|
|
||||||
|
std::chrono::high_resolution_clock::time_point _saveTime = {};
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QDesktopServices>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -28,17 +27,18 @@ bool MacroConditionRun::CheckCondition()
|
|||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
switch (_procStatus) {
|
switch (_error) {
|
||||||
case MacroConditionRun::Status::FAILED_TO_START:
|
case ProcessConfig::ProcStartError::FAILED_TO_START:
|
||||||
SetVariableValue("Failed to start process");
|
SetVariableValue("Failed to start process");
|
||||||
ret = false;
|
|
||||||
break;
|
break;
|
||||||
case MacroConditionRun::Status::TIMEOUT:
|
case ProcessConfig::ProcStartError::TIMEOUT:
|
||||||
SetVariableValue("Timeout while running process");
|
SetVariableValue("Timeout while running process");
|
||||||
ret = false;
|
|
||||||
break;
|
break;
|
||||||
case MacroConditionRun::Status::OK:
|
case ProcessConfig::ProcStartError::CRASH:
|
||||||
ret = _checkExitCode ? _exitCode == _procExitCode : true;
|
SetVariableValue("Timeout while running process");
|
||||||
|
break;
|
||||||
|
case ProcessConfig::ProcStartError::NONE:
|
||||||
|
ret = _checkExitCode ? _exitCodeToCheck == _procExitCode : true;
|
||||||
SetVariableValue(std::to_string(_procExitCode));
|
SetVariableValue(std::to_string(_procExitCode));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -56,42 +56,14 @@ bool MacroConditionRun::CheckCondition()
|
|||||||
|
|
||||||
void MacroConditionRun::RunProcess()
|
void MacroConditionRun::RunProcess()
|
||||||
{
|
{
|
||||||
QProcess process;
|
auto result = _procConfig.StartProcessAndWait(_timeout.Milliseconds());
|
||||||
process.setWorkingDirectory(
|
|
||||||
QString::fromStdString(_procConfig.WorkingDir()));
|
|
||||||
process.start(QString::fromStdString(_procConfig.Path()),
|
|
||||||
_procConfig.Args());
|
|
||||||
int timeout = _timeout.Milliseconds();
|
|
||||||
|
|
||||||
vblog(LOG_INFO, "run \"%s\" with a timeout of %d ms",
|
if (std::holds_alternative<ProcessConfig::ProcStartError>(result)) {
|
||||||
_procConfig.Path().c_str(), timeout);
|
_error = std::get<ProcessConfig::ProcStartError>(result);
|
||||||
|
} else {
|
||||||
bool procFinishedInTime = process.waitForFinished(timeout);
|
_error = ProcessConfig::ProcStartError::NONE;
|
||||||
|
_procExitCode = std::get<int>(result);
|
||||||
if (!procFinishedInTime) {
|
|
||||||
if (process.error() == QProcess::FailedToStart) {
|
|
||||||
vblog(LOG_INFO, "failed to start \"%s\"!",
|
|
||||||
_procConfig.Path().c_str());
|
|
||||||
_procStatus = Status::FAILED_TO_START;
|
|
||||||
} else {
|
|
||||||
vblog(LOG_INFO,
|
|
||||||
"timeout while running \"%s\"\nAttempting to kill process!",
|
|
||||||
_procConfig.Path().c_str());
|
|
||||||
process.kill();
|
|
||||||
process.waitForFinished();
|
|
||||||
_procStatus = Status::TIMEOUT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validExitCode = process.exitStatus() == QProcess::NormalExit;
|
|
||||||
|
|
||||||
if ((_checkExitCode && !validExitCode) || !procFinishedInTime) {
|
|
||||||
_threadDone = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_procExitCode = process.exitCode();
|
|
||||||
_procStatus = Status::OK;
|
|
||||||
_threadDone = true;
|
_threadDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +72,7 @@ bool MacroConditionRun::Save(obs_data_t *obj) const
|
|||||||
MacroCondition::Save(obj);
|
MacroCondition::Save(obj);
|
||||||
_procConfig.Save(obj);
|
_procConfig.Save(obj);
|
||||||
obs_data_set_bool(obj, "checkExitCode", _checkExitCode);
|
obs_data_set_bool(obj, "checkExitCode", _checkExitCode);
|
||||||
obs_data_set_int(obj, "exitCode", _exitCode);
|
obs_data_set_int(obj, "exitCode", _exitCodeToCheck);
|
||||||
_timeout.Save(obj, "timeout");
|
_timeout.Save(obj, "timeout");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -110,7 +82,7 @@ bool MacroConditionRun::Load(obs_data_t *obj)
|
|||||||
MacroCondition::Load(obj);
|
MacroCondition::Load(obj);
|
||||||
_procConfig.Load(obj);
|
_procConfig.Load(obj);
|
||||||
_checkExitCode = obs_data_get_bool(obj, "checkExitCode");
|
_checkExitCode = obs_data_get_bool(obj, "checkExitCode");
|
||||||
_exitCode = obs_data_get_int(obj, "exitCode");
|
_exitCodeToCheck = obs_data_get_int(obj, "exitCode");
|
||||||
_timeout.Load(obj, "timeout");
|
_timeout.Load(obj, "timeout");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -174,7 +146,7 @@ void MacroConditionRunEdit::UpdateEntryData()
|
|||||||
_procConfig->SetProcessConfig(_entryData->_procConfig);
|
_procConfig->SetProcessConfig(_entryData->_procConfig);
|
||||||
_timeout->SetDuration(_entryData->_timeout);
|
_timeout->SetDuration(_entryData->_timeout);
|
||||||
_checkExitCode->setChecked(_entryData->_checkExitCode);
|
_checkExitCode->setChecked(_entryData->_checkExitCode);
|
||||||
_exitCode->setValue(_entryData->_exitCode);
|
_exitCode->setValue(_entryData->_exitCodeToCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionRunEdit::TimeoutChanged(const Duration &dur)
|
void MacroConditionRunEdit::TimeoutChanged(const Duration &dur)
|
||||||
@@ -204,7 +176,7 @@ void MacroConditionRunEdit::ExitCodeChanged(int exitCode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_exitCode = exitCode;
|
_entryData->_exitCodeToCheck = exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionRunEdit::ProcessConfigChanged(const ProcessConfig &conf)
|
void MacroConditionRunEdit::ProcessConfigChanged(const ProcessConfig &conf)
|
||||||
|
|||||||
@@ -25,22 +25,15 @@ public:
|
|||||||
|
|
||||||
ProcessConfig _procConfig;
|
ProcessConfig _procConfig;
|
||||||
bool _checkExitCode = true;
|
bool _checkExitCode = true;
|
||||||
int _exitCode = 0;
|
int _exitCodeToCheck = 0;
|
||||||
Duration _timeout = Duration(0.1);
|
Duration _timeout = Duration(0.1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Status {
|
|
||||||
NONE,
|
|
||||||
FAILED_TO_START,
|
|
||||||
TIMEOUT,
|
|
||||||
OK,
|
|
||||||
};
|
|
||||||
|
|
||||||
void RunProcess();
|
void RunProcess();
|
||||||
|
|
||||||
std::thread _thread;
|
std::thread _thread;
|
||||||
std::atomic_bool _threadDone{true};
|
std::atomic_bool _threadDone{true};
|
||||||
Status _procStatus = Status::NONE;
|
ProcessConfig::ProcStartError _error =
|
||||||
|
ProcessConfig::ProcStartError::NONE;
|
||||||
int _procExitCode = 0;
|
int _procExitCode = 0;
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "macro-condition-scene.hpp"
|
#include "macro-condition-scene.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "scene-switch-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -53,23 +53,22 @@ static OBSWeakSource getCurrentSceneHelper(bool useTransitionTargetScene)
|
|||||||
obs_source_release(current);
|
obs_source_release(current);
|
||||||
return weak;
|
return weak;
|
||||||
}
|
}
|
||||||
return switcher->currentScene;
|
return GetCurrentScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
static OBSWeakSource getPreviousSceneHelper(bool useTransitionTargetScene)
|
static OBSWeakSource getPreviousSceneHelper(bool useTransitionTargetScene)
|
||||||
{
|
{
|
||||||
if (switcher->AnySceneTransitionStarted() && useTransitionTargetScene) {
|
if (AnySceneTransitionStarted() && useTransitionTargetScene) {
|
||||||
return switcher->currentScene;
|
return GetCurrentScene();
|
||||||
}
|
}
|
||||||
return switcher->previousScene;
|
return GetPreviousScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionScene::CheckCondition()
|
bool MacroConditionScene::CheckCondition()
|
||||||
{
|
{
|
||||||
bool sceneChanged = _lastSceneChangeTime !=
|
bool sceneChanged = _lastSceneChangeTime != GetLastSceneChangeTime();
|
||||||
switcher->lastSceneChangeTime;
|
|
||||||
if (sceneChanged) {
|
if (sceneChanged) {
|
||||||
_lastSceneChangeTime = switcher->lastSceneChangeTime;
|
_lastSceneChangeTime = GetLastSceneChangeTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
@@ -95,14 +94,14 @@ bool MacroConditionScene::CheckCondition()
|
|||||||
return scene == _scene.GetScene(false);
|
return scene == _scene.GetScene(false);
|
||||||
}
|
}
|
||||||
case Type::CHANGED:
|
case Type::CHANGED:
|
||||||
SetVariableValue(GetWeakSourceName(switcher->currentScene));
|
SetVariableValue(GetWeakSourceName(GetCurrentScene()));
|
||||||
SetTempVarValue("current",
|
SetTempVarValue("current",
|
||||||
GetWeakSourceName(switcher->currentScene));
|
GetWeakSourceName(GetCurrentScene()));
|
||||||
return sceneChanged;
|
return sceneChanged;
|
||||||
case Type::NOT_CHANGED:
|
case Type::NOT_CHANGED:
|
||||||
SetVariableValue(GetWeakSourceName(switcher->currentScene));
|
SetVariableValue(GetWeakSourceName(GetCurrentScene()));
|
||||||
SetTempVarValue("current",
|
SetTempVarValue("current",
|
||||||
GetWeakSourceName(switcher->currentScene));
|
GetWeakSourceName(GetCurrentScene()));
|
||||||
return !sceneChanged;
|
return !sceneChanged;
|
||||||
case Type::CURRENT_PATTERN: {
|
case Type::CURRENT_PATTERN: {
|
||||||
auto scene = getCurrentSceneHelper(_useTransitionTargetScene);
|
auto scene = getCurrentSceneHelper(_useTransitionTargetScene);
|
||||||
@@ -189,8 +188,8 @@ bool MacroConditionScene::Load(obs_data_t *obj)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
blog(LOG_WARNING,
|
blog(LOG_WARNING,
|
||||||
"failed to convert scene condition type (%d) for macro %s",
|
"failed to convert scene condition type (%d)",
|
||||||
oldType, GetMacro()->Name().c_str());
|
oldType);
|
||||||
_type = Type::CURRENT;
|
_type = Type::CURRENT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "macro-condition-streaming.hpp"
|
#include "macro-condition-streaming.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -25,6 +24,32 @@ const static std::map<MacroConditionStream::Condition, std::string>
|
|||||||
"AdvSceneSwitcher.condition.stream.state.keyFrameInterval"},
|
"AdvSceneSwitcher.condition.stream.state.keyFrameInterval"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool setupStreamingEventHandler();
|
||||||
|
static bool steamingEventHandlerIsSetup = setupStreamingEventHandler();
|
||||||
|
static std::chrono::high_resolution_clock::time_point streamStartTime{};
|
||||||
|
static std::chrono::high_resolution_clock::time_point streamStopTime{};
|
||||||
|
|
||||||
|
bool setupStreamingEventHandler()
|
||||||
|
{
|
||||||
|
static auto handleStreamingEvents = [](enum obs_frontend_event event,
|
||||||
|
void *) {
|
||||||
|
switch (event) {
|
||||||
|
case OBS_FRONTEND_EVENT_STREAMING_STARTING:
|
||||||
|
streamStartTime =
|
||||||
|
std::chrono::high_resolution_clock::now();
|
||||||
|
break;
|
||||||
|
case OBS_FRONTEND_EVENT_STREAMING_STOPPING:
|
||||||
|
streamStopTime =
|
||||||
|
std::chrono::high_resolution_clock::now();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
obs_frontend_add_event_callback(handleStreamingEvents, nullptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int MacroConditionStream::GetKeyFrameInterval()
|
int MacroConditionStream::GetKeyFrameInterval()
|
||||||
{
|
{
|
||||||
const auto configPath = GetPathInProfileDir("streamEncoder.json");
|
const auto configPath = GetPathInProfileDir("streamEncoder.json");
|
||||||
@@ -42,10 +67,8 @@ bool MacroConditionStream::CheckCondition()
|
|||||||
{
|
{
|
||||||
bool match = false;
|
bool match = false;
|
||||||
|
|
||||||
bool streamStarting = switcher->lastStreamStartingTime !=
|
bool streamStarting = streamStartTime != _lastStreamStartingTime;
|
||||||
_lastStreamStartingTime;
|
bool streamStopping = streamStopTime != _lastStreamStoppingTime;
|
||||||
bool streamStopping = switcher->lastStreamStoppingTime !=
|
|
||||||
_lastStreamStoppingTime;
|
|
||||||
|
|
||||||
switch (_condition) {
|
switch (_condition) {
|
||||||
case Condition::STOP:
|
case Condition::STOP:
|
||||||
@@ -68,10 +91,10 @@ bool MacroConditionStream::CheckCondition()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (streamStarting) {
|
if (streamStarting) {
|
||||||
_lastStreamStartingTime = switcher->lastStreamStartingTime;
|
_lastStreamStartingTime = streamStartTime;
|
||||||
}
|
}
|
||||||
if (streamStopping) {
|
if (streamStopping) {
|
||||||
_lastStreamStoppingTime = switcher->lastStreamStoppingTime;
|
_lastStreamStoppingTime = streamStopTime;
|
||||||
}
|
}
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "macro-condition-transition.hpp"
|
#include "macro-condition-transition.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "scene-switch-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -50,8 +50,8 @@ static bool isTargetScene(OBSWeakSource &target)
|
|||||||
bool MacroConditionTransition::CheckCondition()
|
bool MacroConditionTransition::CheckCondition()
|
||||||
{
|
{
|
||||||
bool anyTransitionEnded = _lastTransitionEndTime !=
|
bool anyTransitionEnded = _lastTransitionEndTime !=
|
||||||
switcher->lastTransitionEndTime;
|
GetLastTransitionEndTime();
|
||||||
bool anyTransitionStarted = switcher->AnySceneTransitionStarted();
|
bool anyTransitionStarted = AnySceneTransitionStarted();
|
||||||
bool transitionStarted = false;
|
bool transitionStarted = false;
|
||||||
bool transitionEnded = false;
|
bool transitionEnded = false;
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ bool MacroConditionTransition::CheckCondition()
|
|||||||
break;
|
break;
|
||||||
case TransitionCondition::TRANSITION_SOURCE:
|
case TransitionCondition::TRANSITION_SOURCE:
|
||||||
ret = anyTransitionStarted &&
|
ret = anyTransitionStarted &&
|
||||||
_scene.GetScene() == switcher->currentScene;
|
_scene.GetScene() == GetCurrentScene();
|
||||||
break;
|
break;
|
||||||
case TransitionCondition::TRANSITION_TARGET: {
|
case TransitionCondition::TRANSITION_TARGET: {
|
||||||
auto scene = _scene.GetScene();
|
auto scene = _scene.GetScene();
|
||||||
@@ -101,7 +101,7 @@ bool MacroConditionTransition::CheckCondition()
|
|||||||
_ended = false;
|
_ended = false;
|
||||||
}
|
}
|
||||||
if (anyTransitionEnded) {
|
if (anyTransitionEnded) {
|
||||||
_lastTransitionEndTime = switcher->lastTransitionEndTime;
|
_lastTransitionEndTime = GetLastTransitionEndTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "macro-condition-websocket.hpp"
|
#include "macro-condition-websocket.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "macro-condition-window.hpp"
|
#include "macro-condition-window.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "platform-funcs.hpp"
|
#include "platform-funcs.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
@@ -43,7 +43,8 @@ static bool windowContainsText(const std::string &window,
|
|||||||
bool MacroConditionWindow::WindowMatchesRequirements(
|
bool MacroConditionWindow::WindowMatchesRequirements(
|
||||||
const std::string &window) const
|
const std::string &window) const
|
||||||
{
|
{
|
||||||
const bool focusCheckOK = (!_focus || window == switcher->currentTitle);
|
const bool focusCheckOK =
|
||||||
|
(!_focus || window == ForegroundWindowTitle());
|
||||||
if (!focusCheckOK) {
|
if (!focusCheckOK) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -104,13 +105,13 @@ void MacroConditionWindow::SetVariableValueBasedOnMatch(
|
|||||||
auto text = GetTextInWindow(matchWindow);
|
auto text = GetTextInWindow(matchWindow);
|
||||||
SetVariableValue(text.value_or(""));
|
SetVariableValue(text.value_or(""));
|
||||||
} else {
|
} else {
|
||||||
SetVariableValue(switcher->currentTitle);
|
SetVariableValue(ForegroundWindowTitle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool foregroundWindowChanged()
|
static bool foregroundWindowChanged()
|
||||||
{
|
{
|
||||||
return switcher->currentTitle != switcher->lastTitle;
|
return ForegroundWindowTitle() != PreviousForegroundWindowTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionWindow::CheckCondition()
|
bool MacroConditionWindow::CheckCondition()
|
||||||
@@ -432,7 +433,7 @@ void MacroConditionWindowEdit::WindowFocusChanged(int state)
|
|||||||
|
|
||||||
void MacroConditionWindowEdit::UpdateFocusWindow()
|
void MacroConditionWindowEdit::UpdateFocusWindow()
|
||||||
{
|
{
|
||||||
_focusWindow->setText(QString::fromStdString(switcher->currentTitle));
|
_focusWindow->setText(QString::fromStdString(ForegroundWindowTitle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionWindowEdit::SetWidgetVisibility()
|
void MacroConditionWindowEdit::SetWidgetVisibility()
|
||||||
|
|||||||
59
src/macro-core/macro-helpers.cpp
Normal file
59
src/macro-core/macro-helpers.cpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include "macro-helpers.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
static std::atomic_bool abortMacroWait = {false};
|
||||||
|
static std::atomic_bool macroSceneSwitched = {false};
|
||||||
|
static std::atomic_int shutdownConditionCount = {0};
|
||||||
|
|
||||||
|
std::condition_variable &GetMacroWaitCV()
|
||||||
|
{
|
||||||
|
static std::condition_variable cv;
|
||||||
|
return cv;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::condition_variable &GetMacroTransitionCV()
|
||||||
|
{
|
||||||
|
static std::condition_variable cv;
|
||||||
|
return cv;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::atomic_bool &MacroWaitShouldAbort()
|
||||||
|
{
|
||||||
|
return abortMacroWait;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMacroAbortWait(bool value)
|
||||||
|
{
|
||||||
|
abortMacroWait = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShutdownCheckIsNecessary()
|
||||||
|
{
|
||||||
|
return shutdownConditionCount > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::atomic_int &GetShutdownConditionCount()
|
||||||
|
{
|
||||||
|
return shutdownConditionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMacroSwitchedScene(bool value)
|
||||||
|
{
|
||||||
|
static bool setupDone = false;
|
||||||
|
if (!setupDone) {
|
||||||
|
// Will always be called with switcher lock already held
|
||||||
|
AddIntervalResetStep([]() { macroSceneSwitched = false; },
|
||||||
|
false);
|
||||||
|
setupDone = true;
|
||||||
|
}
|
||||||
|
macroSceneSwitched = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroSwitchedScene()
|
||||||
|
{
|
||||||
|
return macroSceneSwitched;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
21
src/macro-core/macro-helpers.hpp
Normal file
21
src/macro-core/macro-helpers.hpp
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
constexpr std::string_view GetSceneSwitchActionId()
|
||||||
|
{
|
||||||
|
return "scene_switch";
|
||||||
|
}
|
||||||
|
std::condition_variable &GetMacroWaitCV();
|
||||||
|
std::condition_variable &GetMacroTransitionCV();
|
||||||
|
std::atomic_bool &MacroWaitShouldAbort();
|
||||||
|
void SetMacroAbortWait(bool);
|
||||||
|
bool ShutdownCheckIsNecessary();
|
||||||
|
std::atomic_int &GetShutdownConditionCount();
|
||||||
|
void SetMacroSwitchedScene(bool value);
|
||||||
|
bool MacroSwitchedScene();
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
|
static MacroProperties macroProperties;
|
||||||
|
|
||||||
void MacroProperties::Save(obs_data_t *obj) const
|
void MacroProperties::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
auto data = obs_data_create();
|
auto data = obs_data_create();
|
||||||
@@ -325,4 +327,19 @@ bool MacroPropertiesDialog::AskForSettings(QWidget *parent,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MacroProperties &GetGlobalMacroProperties()
|
||||||
|
{
|
||||||
|
return macroProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveGlobalMacroProperties(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
macroProperties.Save(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadGlobalMacroProperties(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
macroProperties.Load(obj);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -68,4 +68,8 @@ private:
|
|||||||
int _conditionsFalseTextRow = -1;
|
int _conditionsFalseTextRow = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MacroProperties &GetGlobalMacroProperties();
|
||||||
|
void SaveGlobalMacroProperties(obs_data_t *obj);
|
||||||
|
void LoadGlobalMacroProperties(obs_data_t *obj);
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -44,8 +44,28 @@ MacroSegmentList::~MacroSegmentList()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool posIsInScrollbar(const QScrollBar *scrollbar, const QPoint &pos)
|
||||||
|
{
|
||||||
|
if (!scrollbar) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!scrollbar->isVisible()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto geo = scrollbar->geometry();
|
||||||
|
const auto globalGeo = QRect(scrollbar->mapToGlobal(geo.topLeft()),
|
||||||
|
scrollbar->mapToGlobal(geo.bottomRight()));
|
||||||
|
return globalGeo.contains(pos);
|
||||||
|
}
|
||||||
|
|
||||||
int MacroSegmentList::GetDragIndex(const QPoint &pos)
|
int MacroSegmentList::GetDragIndex(const QPoint &pos)
|
||||||
{
|
{
|
||||||
|
// Don't drag widget when interacting with the scrollbars
|
||||||
|
if (posIsInScrollbar(horizontalScrollBar(), mapTo(this, pos)) ||
|
||||||
|
posIsInScrollbar(verticalScrollBar(), mapTo(this, pos))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
for (int idx = 0; idx < _contentLayout->count(); ++idx) {
|
for (int idx = 0; idx < _contentLayout->count(); ++idx) {
|
||||||
auto item = _contentLayout->itemAt(idx);
|
auto item = _contentLayout->itemAt(idx);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
@@ -161,7 +181,7 @@ void MacroSegmentList::mousePressEvent(QMouseEvent *event)
|
|||||||
#else
|
#else
|
||||||
_dragPosition = GetDragIndex(event->globalPosition().toPoint());
|
_dragPosition = GetDragIndex(event->globalPosition().toPoint());
|
||||||
#endif
|
#endif
|
||||||
emit SelectionChagned(_dragPosition);
|
emit SelectionChanged(_dragPosition);
|
||||||
} else {
|
} else {
|
||||||
_dragPosition = -1;
|
_dragPosition = -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public:
|
|||||||
QVBoxLayout *ContentLayout() { return _contentLayout; }
|
QVBoxLayout *ContentLayout() { return _contentLayout; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void SelectionChagned(int idx);
|
void SelectionChanged(int idx);
|
||||||
void Reorder(int source, int target);
|
void Reorder(int source, int target);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// so it makes sense to include them here:
|
// so it makes sense to include them here:
|
||||||
#include "log-helper.hpp"
|
#include "log-helper.hpp"
|
||||||
#include "obs-module-helper.hpp"
|
#include "obs-module-helper.hpp"
|
||||||
#include "sync-helper.hpp"
|
#include "sync-helpers.hpp"
|
||||||
#include "temp-variable.hpp"
|
#include "temp-variable.hpp"
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "macro-selection.hpp"
|
#include "macro-selection.hpp"
|
||||||
|
#include "macro.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
@@ -12,7 +12,7 @@ MacroSelection::MacroSelection(QWidget *parent)
|
|||||||
: FilterComboBox(parent,
|
: FilterComboBox(parent,
|
||||||
obs_module_text("AdvSceneSwitcher.selectMacro"))
|
obs_module_text("AdvSceneSwitcher.selectMacro"))
|
||||||
{
|
{
|
||||||
for (const auto &m : switcher->macros) {
|
for (const auto &m : GetMacros()) {
|
||||||
if (m->IsGroup()) {
|
if (m->IsGroup()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ bool AdvSceneSwitcher::AddNewMacro(std::shared_ptr<Macro> &res,
|
|||||||
}
|
}
|
||||||
|
|
||||||
res = std::make_shared<Macro>(
|
res = std::make_shared<Macro>(
|
||||||
name, switcher->macroProperties._newMacroRegisterHotkeys);
|
name, GetGlobalMacroProperties()._newMacroRegisterHotkeys);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,8 +197,8 @@ static void addGroupSubitems(std::vector<std::shared_ptr<Macro>> ¯os,
|
|||||||
subitems.reserve(group->GroupSize());
|
subitems.reserve(group->GroupSize());
|
||||||
|
|
||||||
// Find all subitems
|
// Find all subitems
|
||||||
for (auto it = switcher->macros.begin(); it < switcher->macros.end();
|
auto allMacros = GetMacros();
|
||||||
it++) {
|
for (auto it = allMacros.begin(); it < allMacros.end(); it++) {
|
||||||
if ((*it)->Name() == group->Name()) {
|
if ((*it)->Name() == group->Name()) {
|
||||||
for (uint32_t i = 1; i <= group->GroupSize(); i++) {
|
for (uint32_t i = 1; i <= group->GroupSize(); i++) {
|
||||||
subitems.emplace_back(*std::next(it, i));
|
subitems.emplace_back(*std::next(it, i));
|
||||||
@@ -243,7 +243,7 @@ void AdvSceneSwitcher::ExportMacros()
|
|||||||
obs_data_array_push_back(macroArray, obj);
|
obs_data_array_push_back(macroArray, obj);
|
||||||
}
|
}
|
||||||
obs_data_set_array(data, "macros", macroArray);
|
obs_data_set_array(data, "macros", macroArray);
|
||||||
switcher->SaveVariables(data);
|
SaveVariables(data);
|
||||||
obs_data_set_string(data, "version", g_GIT_TAG);
|
obs_data_set_string(data, "version", g_GIT_TAG);
|
||||||
auto json = obs_data_get_json(data);
|
auto json = obs_data_get_json(data);
|
||||||
QString exportString(json);
|
QString exportString(json);
|
||||||
@@ -382,7 +382,7 @@ static void importVariables(obs_data_t *obj)
|
|||||||
if (variableWithNameExists(var->Name())) {
|
if (variableWithNameExists(var->Name())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switcher->variables.emplace_back(var);
|
GetVariables().emplace_back(var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,7 +429,7 @@ void AdvSceneSwitcher::ImportMacros()
|
|||||||
}
|
}
|
||||||
|
|
||||||
importedMacros.emplace_back(macro);
|
importedMacros.emplace_back(macro);
|
||||||
switcher->macros.emplace_back(macro);
|
GetMacros().emplace_back(macro);
|
||||||
if (groupSize > 0 && !macro->IsGroup()) {
|
if (groupSize > 0 && !macro->IsGroup()) {
|
||||||
Macro::PrepareMoveToGroup(group, macro);
|
Macro::PrepareMoveToGroup(group, macro);
|
||||||
groupSize--;
|
groupSize--;
|
||||||
@@ -449,8 +449,8 @@ void AdvSceneSwitcher::ImportMacros()
|
|||||||
macro->PostLoad();
|
macro->PostLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->macros->Reset(switcher->macros,
|
ui->macros->Reset(GetMacros(),
|
||||||
switcher->macroProperties._highlightExecuted);
|
GetGlobalMacroProperties()._highlightExecuted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_macroName_editingFinished()
|
void AdvSceneSwitcher::on_macroName_editingFinished()
|
||||||
@@ -729,8 +729,8 @@ void AdvSceneSwitcher::MacroSelectionChanged()
|
|||||||
|
|
||||||
void AdvSceneSwitcher::HighlightOnChange()
|
void AdvSceneSwitcher::HighlightOnChange()
|
||||||
{
|
{
|
||||||
if (!switcher->macroProperties._highlightActions &&
|
if (!GetGlobalMacroProperties()._highlightActions &&
|
||||||
!switcher->macroProperties._highlightExecuted) {
|
!GetGlobalMacroProperties()._highlightExecuted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,13 +747,13 @@ void AdvSceneSwitcher::HighlightOnChange()
|
|||||||
|
|
||||||
void AdvSceneSwitcher::on_macroProperties_clicked()
|
void AdvSceneSwitcher::on_macroProperties_clicked()
|
||||||
{
|
{
|
||||||
MacroProperties prop = switcher->macroProperties;
|
MacroProperties prop = GetGlobalMacroProperties();
|
||||||
bool accepted = MacroPropertiesDialog::AskForSettings(
|
bool accepted = MacroPropertiesDialog::AskForSettings(
|
||||||
this, prop, GetSelectedMacro().get());
|
this, prop, GetSelectedMacro().get());
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switcher->macroProperties = prop;
|
GetGlobalMacroProperties() = prop;
|
||||||
emit HighlightMacrosChanged(prop._highlightExecuted);
|
emit HighlightMacrosChanged(prop._highlightExecuted);
|
||||||
emit HighlightActionsChanged(prop._highlightActions);
|
emit HighlightActionsChanged(prop._highlightActions);
|
||||||
emit HighlightConditionsChanged(prop._highlightConditions);
|
emit HighlightConditionsChanged(prop._highlightConditions);
|
||||||
@@ -789,11 +789,11 @@ void AdvSceneSwitcher::SetupMacroTab()
|
|||||||
{
|
{
|
||||||
ui->macroElseActions->installEventFilter(this);
|
ui->macroElseActions->installEventFilter(this);
|
||||||
|
|
||||||
if (switcher->macros.size() == 0 && !switcher->disableHints) {
|
if (GetMacros().size() == 0 && !switcher->disableHints) {
|
||||||
addPulse = PulseWidget(ui->macroAdd, QColor(Qt::green));
|
addPulse = PulseWidget(ui->macroAdd, QColor(Qt::green));
|
||||||
}
|
}
|
||||||
ui->macros->Reset(switcher->macros,
|
ui->macros->Reset(GetMacros(),
|
||||||
switcher->macroProperties._highlightExecuted);
|
GetGlobalMacroProperties()._highlightExecuted);
|
||||||
connect(ui->macros, SIGNAL(MacroSelectionAboutToChange()), this,
|
connect(ui->macros, SIGNAL(MacroSelectionAboutToChange()), this,
|
||||||
SLOT(MacroSelectionAboutToChange()));
|
SLOT(MacroSelectionAboutToChange()));
|
||||||
connect(ui->macros, SIGNAL(MacroSelectionChanged()), this,
|
connect(ui->macros, SIGNAL(MacroSelectionChanged()), this,
|
||||||
@@ -802,21 +802,21 @@ void AdvSceneSwitcher::SetupMacroTab()
|
|||||||
|
|
||||||
ui->conditionsList->SetHelpMsg(
|
ui->conditionsList->SetHelpMsg(
|
||||||
obs_module_text("AdvSceneSwitcher.macroTab.editConditionHelp"));
|
obs_module_text("AdvSceneSwitcher.macroTab.editConditionHelp"));
|
||||||
connect(ui->conditionsList, &MacroSegmentList::SelectionChagned, this,
|
connect(ui->conditionsList, &MacroSegmentList::SelectionChanged, this,
|
||||||
&AdvSceneSwitcher::MacroConditionSelectionChanged);
|
&AdvSceneSwitcher::MacroConditionSelectionChanged);
|
||||||
connect(ui->conditionsList, &MacroSegmentList::Reorder, this,
|
connect(ui->conditionsList, &MacroSegmentList::Reorder, this,
|
||||||
&AdvSceneSwitcher::MacroConditionReorder);
|
&AdvSceneSwitcher::MacroConditionReorder);
|
||||||
|
|
||||||
ui->actionsList->SetHelpMsg(
|
ui->actionsList->SetHelpMsg(
|
||||||
obs_module_text("AdvSceneSwitcher.macroTab.editActionHelp"));
|
obs_module_text("AdvSceneSwitcher.macroTab.editActionHelp"));
|
||||||
connect(ui->actionsList, &MacroSegmentList::SelectionChagned, this,
|
connect(ui->actionsList, &MacroSegmentList::SelectionChanged, this,
|
||||||
&AdvSceneSwitcher::MacroActionSelectionChanged);
|
&AdvSceneSwitcher::MacroActionSelectionChanged);
|
||||||
connect(ui->actionsList, &MacroSegmentList::Reorder, this,
|
connect(ui->actionsList, &MacroSegmentList::Reorder, this,
|
||||||
&AdvSceneSwitcher::MacroActionReorder);
|
&AdvSceneSwitcher::MacroActionReorder);
|
||||||
|
|
||||||
ui->elseActionsList->SetHelpMsg(obs_module_text(
|
ui->elseActionsList->SetHelpMsg(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.editElseActionHelp"));
|
"AdvSceneSwitcher.macroTab.editElseActionHelp"));
|
||||||
connect(ui->elseActionsList, &MacroSegmentList::SelectionChagned, this,
|
connect(ui->elseActionsList, &MacroSegmentList::SelectionChanged, this,
|
||||||
&AdvSceneSwitcher::MacroElseActionSelectionChanged);
|
&AdvSceneSwitcher::MacroElseActionSelectionChanged);
|
||||||
connect(ui->elseActionsList, &MacroSegmentList::Reorder, this,
|
connect(ui->elseActionsList, &MacroSegmentList::Reorder, this,
|
||||||
&AdvSceneSwitcher::MacroElseActionReorder);
|
&AdvSceneSwitcher::MacroElseActionReorder);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "macro-tree.hpp"
|
#include "macro-tree.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "sync-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "switcher-data.hpp"
|
|
||||||
|
|
||||||
#include <obs.h>
|
#include <obs.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -395,7 +395,7 @@ CountItemsVisibleInModel(const std::deque<std::shared_ptr<Macro>> ¯os)
|
|||||||
|
|
||||||
void MacroTreeModel::Add(std::shared_ptr<Macro> item)
|
void MacroTreeModel::Add(std::shared_ptr<Macro> item)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
auto idx = CountItemsVisibleInModel(_macros);
|
auto idx = CountItemsVisibleInModel(_macros);
|
||||||
beginInsertRows(QModelIndex(), idx, idx);
|
beginInsertRows(QModelIndex(), idx, idx);
|
||||||
_macros.emplace_back(item);
|
_macros.emplace_back(item);
|
||||||
@@ -408,7 +408,7 @@ void MacroTreeModel::Add(std::shared_ptr<Macro> item)
|
|||||||
|
|
||||||
void MacroTreeModel::Remove(std::shared_ptr<Macro> item)
|
void MacroTreeModel::Remove(std::shared_ptr<Macro> item)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
auto uiStartIdx = GetItemModelIndex(item);
|
auto uiStartIdx = GetItemModelIndex(item);
|
||||||
if (uiStartIdx == -1) {
|
if (uiStartIdx == -1) {
|
||||||
return;
|
return;
|
||||||
@@ -643,7 +643,7 @@ void MacroTreeModel::GroupSelectedItems(QModelIndexList &indices)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
QString name = GetNewGroupName();
|
QString name = GetNewGroupName();
|
||||||
std::vector<std::shared_ptr<Macro>> itemsToGroup;
|
std::vector<std::shared_ptr<Macro>> itemsToGroup;
|
||||||
itemsToGroup.reserve(indices.size());
|
itemsToGroup.reserve(indices.size());
|
||||||
@@ -691,7 +691,7 @@ void MacroTreeModel::UngroupSelectedGroups(QModelIndexList &indices)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
for (int i = indices.count() - 1; i >= 0; i--) {
|
for (int i = indices.count() - 1; i >= 0; i--) {
|
||||||
std::shared_ptr<Macro> item = _macros[ModelIndexToMacroIndex(
|
std::shared_ptr<Macro> item = _macros[ModelIndexToMacroIndex(
|
||||||
indices[i].row(), _macros)];
|
indices[i].row(), _macros)];
|
||||||
@@ -1055,7 +1055,7 @@ void MacroTree::dropEvent(QDropEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Move items in backend
|
// Move items in backend
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
int to = row;
|
int to = row;
|
||||||
try {
|
try {
|
||||||
to = ModelIndexToMacroIndex(row, items);
|
to = ModelIndexToMacroIndex(row, items);
|
||||||
@@ -1181,7 +1181,7 @@ void MacroTree::Remove(std::shared_ptr<Macro> item) const
|
|||||||
|
|
||||||
void MacroTree::Up(std::shared_ptr<Macro> item) const
|
void MacroTree::Up(std::shared_ptr<Macro> item) const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
auto above = GetModel()->Neighbor(item, true);
|
auto above = GetModel()->Neighbor(item, true);
|
||||||
if (!above) {
|
if (!above) {
|
||||||
return;
|
return;
|
||||||
@@ -1207,7 +1207,7 @@ void MacroTree::Up(std::shared_ptr<Macro> item) const
|
|||||||
|
|
||||||
void MacroTree::Down(std::shared_ptr<Macro> item) const
|
void MacroTree::Down(std::shared_ptr<Macro> item) const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
auto lock = LockContext();
|
||||||
auto below = GetModel()->Neighbor(item, false);
|
auto below = GetModel()->Neighbor(item, false);
|
||||||
if (!below) {
|
if (!below) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-factory.hpp"
|
||||||
#include "macro-condition-edit.hpp"
|
#include "macro-condition-factory.hpp"
|
||||||
#include "macro-dock.hpp"
|
#include "macro-dock.hpp"
|
||||||
#include "macro-action-scene-switch.hpp"
|
#include "macro-helpers.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "hotkey.hpp"
|
#include "hotkey.hpp"
|
||||||
|
#include "sync-helpers.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#undef max
|
#undef max
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <QAction>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
constexpr int perfLogThreshold = 300;
|
static constexpr int perfLogThreshold = 300;
|
||||||
|
static std::deque<std::shared_ptr<Macro>> macros;
|
||||||
|
|
||||||
Macro::Macro(const std::string &name, const bool addHotkey)
|
Macro::Macro(const std::string &name, const bool addHotkey)
|
||||||
{
|
{
|
||||||
@@ -33,7 +37,7 @@ Macro::~Macro()
|
|||||||
|
|
||||||
// Keep the dock widgets in case of shutdown so they can be restored by
|
// Keep the dock widgets in case of shutdown so they can be restored by
|
||||||
// OBS on startup
|
// OBS on startup
|
||||||
if (!switcher->obsIsShuttingDown) {
|
if (!OBSIsShuttingDown()) {
|
||||||
RemoveDock();
|
RemoveDock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,9 +57,8 @@ Macro::CreateGroup(const std::string &name,
|
|||||||
|
|
||||||
void Macro::RemoveGroup(std::shared_ptr<Macro> group)
|
void Macro::RemoveGroup(std::shared_ptr<Macro> group)
|
||||||
{
|
{
|
||||||
auto it = std::find(switcher->macros.begin(), switcher->macros.end(),
|
auto it = std::find(macros.begin(), macros.end(), group);
|
||||||
group);
|
if (it == macros.end()) {
|
||||||
if (it == switcher->macros.end()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,12 +68,12 @@ void Macro::RemoveGroup(std::shared_ptr<Macro> group)
|
|||||||
(*m)->SetParent(nullptr);
|
(*m)->SetParent(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
switcher->macros.erase(it);
|
macros.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Macro::PrepareMoveToGroup(Macro *group, std::shared_ptr<Macro> item)
|
void Macro::PrepareMoveToGroup(Macro *group, std::shared_ptr<Macro> item)
|
||||||
{
|
{
|
||||||
for (auto &m : switcher->macros) {
|
for (const auto &m : macros) {
|
||||||
if (m.get() == group) {
|
if (m.get() == group) {
|
||||||
PrepareMoveToGroup(m, item);
|
PrepareMoveToGroup(m, item);
|
||||||
return;
|
return;
|
||||||
@@ -351,7 +354,7 @@ void Macro::AddHelperThread(std::thread &&newThread)
|
|||||||
void Macro::Stop()
|
void Macro::Stop()
|
||||||
{
|
{
|
||||||
_stop = true;
|
_stop = true;
|
||||||
switcher->macroWaitCv.notify_all();
|
GetMacroWaitCV().notify_all();
|
||||||
for (auto &t : _helperThreads) {
|
for (auto &t : _helperThreads) {
|
||||||
if (t.joinable()) {
|
if (t.joinable()) {
|
||||||
t.join();
|
t.join();
|
||||||
@@ -743,15 +746,13 @@ bool Macro::PostLoad()
|
|||||||
|
|
||||||
bool Macro::SwitchesScene() const
|
bool Macro::SwitchesScene() const
|
||||||
{
|
{
|
||||||
MacroActionSwitchScene temp(nullptr);
|
|
||||||
auto sceneSwitchId = temp.GetId();
|
|
||||||
for (const auto &a : _actions) {
|
for (const auto &a : _actions) {
|
||||||
if (a->GetId() == sceneSwitchId) {
|
if (a->GetId() == GetSceneSwitchActionId()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto &a : _elseActions) {
|
for (const auto &a : _elseActions) {
|
||||||
if (a->GetId() == sceneSwitchId) {
|
if (a->GetId() == GetSceneSwitchActionId()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -947,7 +948,7 @@ void Macro::EnableDock(bool value)
|
|||||||
// geometry set here.
|
// geometry set here.
|
||||||
// The function calls here are only intended to attempt to restore the
|
// The function calls here are only intended to attempt to restore the
|
||||||
// dock status when switching scene collections.
|
// dock status when switching scene collections.
|
||||||
if (switcher->startupLoadDone) {
|
if (InitialLoadIsComplete()) {
|
||||||
_dock->setVisible(_dockIsVisible);
|
_dock->setVisible(_dockIsVisible);
|
||||||
if (window->dockWidgetArea(_dock) != _dockArea) {
|
if (window->dockWidgetArea(_dock) != _dockArea) {
|
||||||
window->addDockWidget(_dockArea, _dock);
|
window->addDockWidget(_dockArea, _dock);
|
||||||
@@ -1163,12 +1164,10 @@ void Macro::SetHotkeysDesc() const
|
|||||||
_name, _togglePauseHotkey);
|
_name, _togglePauseHotkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::SaveMacros(obs_data_t *obj)
|
void SaveMacros(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
switcher->macroProperties.Save(obj);
|
|
||||||
|
|
||||||
obs_data_array_t *macroArray = obs_data_array_create();
|
obs_data_array_t *macroArray = obs_data_array_create();
|
||||||
for (auto &m : macros) {
|
for (const auto &m : macros) {
|
||||||
obs_data_t *array_obj = obs_data_create();
|
obs_data_t *array_obj = obs_data_create();
|
||||||
|
|
||||||
m->Save(array_obj);
|
m->Save(array_obj);
|
||||||
@@ -1180,10 +1179,9 @@ void SwitcherData::SaveMacros(obs_data_t *obj)
|
|||||||
obs_data_array_release(macroArray);
|
obs_data_array_release(macroArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::LoadMacros(obs_data_t *obj)
|
void LoadMacros(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
Hotkey::ClearAllHotkeys();
|
Hotkey::ClearAllHotkeys();
|
||||||
switcher->macroProperties.Load(obj);
|
|
||||||
|
|
||||||
macros.clear();
|
macros.clear();
|
||||||
obs_data_array_t *macroArray = obs_data_get_array(obj, "macros");
|
obs_data_array_t *macroArray = obs_data_get_array(obj, "macros");
|
||||||
@@ -1200,7 +1198,7 @@ void SwitcherData::LoadMacros(obs_data_t *obj)
|
|||||||
int groupCount = 0;
|
int groupCount = 0;
|
||||||
std::shared_ptr<Macro> group;
|
std::shared_ptr<Macro> group;
|
||||||
std::vector<std::shared_ptr<Macro>> invalidGroups;
|
std::vector<std::shared_ptr<Macro>> invalidGroups;
|
||||||
for (auto &m : macros) {
|
for (const auto &m : macros) {
|
||||||
if (groupCount && m->IsGroup()) {
|
if (groupCount && m->IsGroup()) {
|
||||||
blog(LOG_ERROR,
|
blog(LOG_ERROR,
|
||||||
"nested group detected - will delete \"%s\"",
|
"nested group detected - will delete \"%s\"",
|
||||||
@@ -1235,23 +1233,28 @@ void SwitcherData::LoadMacros(obs_data_t *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwitcherData::CheckMacros()
|
std::deque<std::shared_ptr<Macro>> &GetMacros()
|
||||||
{
|
{
|
||||||
bool ret = false;
|
return macros;
|
||||||
for (auto &m : macros) {
|
}
|
||||||
|
|
||||||
|
bool CheckMacros()
|
||||||
|
{
|
||||||
|
bool matchFound = false;
|
||||||
|
for (const auto &m : macros) {
|
||||||
if (m->CeckMatch() || m->ElseActions().size() > 0) {
|
if (m->CeckMatch() || m->ElseActions().size() > 0) {
|
||||||
ret = true;
|
matchFound = true;
|
||||||
// This has to be performed here for now as actions are
|
// This has to be performed here for now as actions are
|
||||||
// not performed immediately after checking conditions.
|
// not performed immediately after checking conditions.
|
||||||
if (m->SwitchesScene()) {
|
if (m->SwitchesScene()) {
|
||||||
switcher->macroSceneSwitched = true;
|
SetMacroSwitchedScene(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return matchFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwitcherData::RunMacros()
|
bool RunMacros()
|
||||||
{
|
{
|
||||||
// Create copy of macro list as elements might be removed, inserted, or
|
// Create copy of macro list as elements might be removed, inserted, or
|
||||||
// reordered while macros are currently being executed.
|
// reordered while macros are currently being executed.
|
||||||
@@ -1269,15 +1272,16 @@ bool SwitcherData::RunMacros()
|
|||||||
// the constructor of AdvSceneSwitcher() to complete.
|
// the constructor of AdvSceneSwitcher() to complete.
|
||||||
// The constructor of AdvSceneSwitcher() cannot continue however as it
|
// The constructor of AdvSceneSwitcher() cannot continue however as it
|
||||||
// cannot lock the main switcher mutex.
|
// cannot lock the main switcher mutex.
|
||||||
if (GetLock()) {
|
auto lock = GetLoopLock();
|
||||||
GetLock()->unlock();
|
if (lock) {
|
||||||
|
lock->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &m : runPhaseMacros) {
|
for (auto &m : runPhaseMacros) {
|
||||||
if (!m || !m->ShouldRunActions()) {
|
if (!m || !m->ShouldRunActions()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (firstInterval && m->SkipExecOnStart()) {
|
if (IsFirstInterval() && m->SkipExecOnStart()) {
|
||||||
blog(LOG_INFO,
|
blog(LOG_INFO,
|
||||||
"skip execution of macro \"%s\" at startup",
|
"skip execution of macro \"%s\" at startup",
|
||||||
m->Name().c_str());
|
m->Name().c_str());
|
||||||
@@ -1288,15 +1292,15 @@ bool SwitcherData::RunMacros()
|
|||||||
blog(LOG_WARNING, "abort macro: %s", m->Name().c_str());
|
blog(LOG_WARNING, "abort macro: %s", m->Name().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GetLock()) {
|
if (lock) {
|
||||||
GetLock()->lock();
|
lock->lock();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Macro *GetMacroByName(const char *name)
|
Macro *GetMacroByName(const char *name)
|
||||||
{
|
{
|
||||||
for (auto &m : switcher->macros) {
|
for (const auto &m : macros) {
|
||||||
if (m->Name() == name) {
|
if (m->Name() == name) {
|
||||||
return m.get();
|
return m.get();
|
||||||
}
|
}
|
||||||
@@ -1312,7 +1316,7 @@ Macro *GetMacroByQString(const QString &name)
|
|||||||
|
|
||||||
std::weak_ptr<Macro> GetWeakMacroByName(const char *name)
|
std::weak_ptr<Macro> GetWeakMacroByName(const char *name)
|
||||||
{
|
{
|
||||||
for (auto &m : switcher->macros) {
|
for (const auto &m : macros) {
|
||||||
if (m->Name() == name) {
|
if (m->Name() == name) {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
@@ -1323,7 +1327,7 @@ std::weak_ptr<Macro> GetWeakMacroByName(const char *name)
|
|||||||
|
|
||||||
void InvalidateMacroTempVarValues()
|
void InvalidateMacroTempVarValues()
|
||||||
{
|
{
|
||||||
for (auto &m : switcher->macros) {
|
for (const auto &m : macros) {
|
||||||
m->InvalidateTempVarValues();
|
m->InvalidateTempVarValues();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,6 +202,11 @@ private:
|
|||||||
QAction *_dockAction = nullptr;
|
QAction *_dockAction = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void LoadMacros(obs_data_t *obj);
|
||||||
|
void SaveMacros(obs_data_t *obj);
|
||||||
|
std::deque<std::shared_ptr<Macro>> &GetMacros();
|
||||||
|
bool CheckMacros();
|
||||||
|
bool RunMacros();
|
||||||
Macro *GetMacroByName(const char *name);
|
Macro *GetMacroByName(const char *name);
|
||||||
Macro *GetMacroByQString(const QString &name);
|
Macro *GetMacroByQString(const QString &name);
|
||||||
std::weak_ptr<Macro> GetWeakMacroByName(const char *name);
|
std::weak_ptr<Macro> GetWeakMacroByName(const char *name);
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
#include <utility.hpp>
|
#include <utility.hpp>
|
||||||
#include <log-helper.hpp>
|
#include <log-helper.hpp>
|
||||||
#include <obs-module-helper.hpp>
|
#include <obs-module-helper.hpp>
|
||||||
#include <plugin-state-helper.hpp>
|
#include <plugin-state-helpers.hpp>
|
||||||
#include <sync-helper.hpp>
|
#include <sync-helpers.hpp>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include "twitch-helpers.hpp"
|
#include "twitch-helpers.hpp"
|
||||||
|
|
||||||
#include <log-helper.hpp>
|
#include <log-helper.hpp>
|
||||||
#include <plugin-state-helper.hpp>
|
#include <plugin-state-helpers.hpp>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include "twitch-helpers.hpp"
|
#include "twitch-helpers.hpp"
|
||||||
|
|
||||||
#include <log-helper.hpp>
|
#include <log-helper.hpp>
|
||||||
#include <plugin-state-helper.hpp>
|
#include <plugin-state-helpers.hpp>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "token.hpp"
|
#include "token.hpp"
|
||||||
#include "twitch-helpers.hpp"
|
#include "twitch-helpers.hpp"
|
||||||
|
|
||||||
#include <plugin-state-helper.hpp>
|
#include <plugin-state-helpers.hpp>
|
||||||
#include <log-helper.hpp>
|
#include <log-helper.hpp>
|
||||||
#include <obs-module-helper.hpp>
|
#include <obs-module-helper.hpp>
|
||||||
#include <utility.hpp>
|
#include <utility.hpp>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "macro-condition-video.hpp"
|
#include "macro-condition-video.hpp"
|
||||||
|
|
||||||
#include <macro-condition-edit.hpp>
|
#include <macro-condition-edit.hpp>
|
||||||
#include <switcher-data.hpp>
|
#include <plugin-state-helpers.hpp>
|
||||||
#include <utility.hpp>
|
#include <utility.hpp>
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
@@ -222,8 +222,8 @@ void MacroConditionVideo::GetScreenshot(bool blocking)
|
|||||||
_areaParameters.area.width,
|
_areaParameters.area.width,
|
||||||
_areaParameters.area.height);
|
_areaParameters.area.height);
|
||||||
}
|
}
|
||||||
new (&_screenshotData) ScreenshotHelper(
|
new (&_screenshotData) ScreenshotHelper(source, screenshotArea,
|
||||||
source, screenshotArea, blocking, GetSwitcher()->interval);
|
blocking, GetIntervalValue());
|
||||||
obs_source_release(source);
|
obs_source_release(source);
|
||||||
_getNextScreenshot = false;
|
_getNextScreenshot = false;
|
||||||
}
|
}
|
||||||
@@ -1110,9 +1110,9 @@ MacroConditionVideoEdit::MacroConditionVideoEdit(
|
|||||||
"AdvSceneSwitcher.condition.video.patternMatchMode.tip"));
|
"AdvSceneSwitcher.condition.video.patternMatchMode.tip"));
|
||||||
populatePatternMatchModeSelection(_patternMatchMode);
|
populatePatternMatchModeSelection(_patternMatchMode);
|
||||||
|
|
||||||
_throttleCount->setMinimum(1 * GetSwitcher()->interval);
|
_throttleCount->setMinimum(1 * GetIntervalValue());
|
||||||
_throttleCount->setMaximum(10 * GetSwitcher()->interval);
|
_throttleCount->setMaximum(10 * GetIntervalValue());
|
||||||
_throttleCount->setSingleStep(GetSwitcher()->interval);
|
_throttleCount->setSingleStep(GetIntervalValue());
|
||||||
|
|
||||||
_brightness->setSizePolicy(QSizePolicy::MinimumExpanding,
|
_brightness->setSizePolicy(QSizePolicy::MinimumExpanding,
|
||||||
QSizePolicy::Preferred);
|
QSizePolicy::Preferred);
|
||||||
@@ -1507,7 +1507,7 @@ void MacroConditionVideoEdit::ThrottleCountChanged(int value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_throttleCount = value / GetSwitcher()->interval;
|
_entryData->_throttleCount = value / GetIntervalValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionVideoEdit::ShowMatchClicked()
|
void MacroConditionVideoEdit::ShowMatchClicked()
|
||||||
@@ -1629,7 +1629,7 @@ void MacroConditionVideoEdit::UpdateEntryData()
|
|||||||
_entryData->_patternMatchParameters.matchMode));
|
_entryData->_patternMatchParameters.matchMode));
|
||||||
_throttleEnable->setChecked(_entryData->_throttleEnabled);
|
_throttleEnable->setChecked(_entryData->_throttleEnabled);
|
||||||
_throttleCount->setValue(_entryData->_throttleCount *
|
_throttleCount->setValue(_entryData->_throttleCount *
|
||||||
GetSwitcher()->interval);
|
GetIntervalValue());
|
||||||
UpdatePreviewTooltip();
|
UpdatePreviewTooltip();
|
||||||
SetupPreviewDialogParams();
|
SetupPreviewDialogParams();
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
|
|||||||
@@ -383,6 +383,9 @@ static std::map<HotkeyType, CGKeyCode> keyTable = {
|
|||||||
{HotkeyType::Key_8, kVK_ANSI_8},
|
{HotkeyType::Key_8, kVK_ANSI_8},
|
||||||
{HotkeyType::Key_9, kVK_ANSI_9},
|
{HotkeyType::Key_9, kVK_ANSI_9},
|
||||||
|
|
||||||
|
// Other
|
||||||
|
// Not sure which key to use for tilde
|
||||||
|
|
||||||
{HotkeyType::Key_F1, kVK_F1},
|
{HotkeyType::Key_F1, kVK_F1},
|
||||||
{HotkeyType::Key_F2, kVK_F2},
|
{HotkeyType::Key_F2, kVK_F2},
|
||||||
{HotkeyType::Key_F3, kVK_F3},
|
{HotkeyType::Key_F3, kVK_F3},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "status-control.hpp"
|
#include "status-control.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <obs-module.h>
|
#include <obs-module.h>
|
||||||
@@ -51,10 +51,10 @@ StatusControl::StatusControl(QWidget *parent, bool noLayout)
|
|||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switcher->stop) {
|
if (PluginIsRunning()) {
|
||||||
SetStopped();
|
|
||||||
} else {
|
|
||||||
SetStarted();
|
SetStarted();
|
||||||
|
} else {
|
||||||
|
SetStopped();
|
||||||
}
|
}
|
||||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(UpdateStatus()));
|
connect(&_timer, SIGNAL(timeout()), this, SLOT(UpdateStatus()));
|
||||||
_timer.start(1000);
|
_timer.start(1000);
|
||||||
@@ -62,22 +62,18 @@ StatusControl::StatusControl(QWidget *parent, bool noLayout)
|
|||||||
|
|
||||||
void StatusControl::ButtonClicked()
|
void StatusControl::ButtonClicked()
|
||||||
{
|
{
|
||||||
if (switcher->th && switcher->th->isRunning()) {
|
if (PluginIsRunning()) {
|
||||||
switcher->Stop();
|
StopPlugin();
|
||||||
SetStopped();
|
SetStopped();
|
||||||
} else {
|
} else {
|
||||||
switcher->Start();
|
StartPlugin();
|
||||||
SetStarted();
|
SetStarted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusControl::UpdateStatus()
|
void StatusControl::UpdateStatus()
|
||||||
{
|
{
|
||||||
if (!switcher) {
|
if (PluginIsRunning()) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switcher->th && switcher->th->isRunning()) {
|
|
||||||
if (!_setToStopped) {
|
if (!_setToStopped) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -104,7 +100,7 @@ void StatusControl::SetStopped()
|
|||||||
_button->setText(
|
_button->setText(
|
||||||
obs_module_text("AdvSceneSwitcher.generalTab.status.start"));
|
obs_module_text("AdvSceneSwitcher.generalTab.status.start"));
|
||||||
_status->setText(obs_module_text("AdvSceneSwitcher.status.inactive"));
|
_status->setText(obs_module_text("AdvSceneSwitcher.status.inactive"));
|
||||||
if (!switcher->disableHints) {
|
if (HighlightUIElementsEnabled()) {
|
||||||
_pulse = PulseWidget(_status, QColor(Qt::red),
|
_pulse = PulseWidget(_status, QColor(Qt::red),
|
||||||
QColor(0, 0, 0, 0));
|
QColor(0, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ std::mutex *GetSwitcherMutex()
|
|||||||
return switcher ? &switcher->m : nullptr;
|
return switcher ? &switcher->m : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> *GetSwitcherLoopLock()
|
||||||
|
{
|
||||||
|
return switcher ? switcher->mainLoopLock : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool VerboseLoggingEnabled()
|
bool VerboseLoggingEnabled()
|
||||||
{
|
{
|
||||||
return switcher ? switcher->verbose : false;
|
return switcher ? switcher->verbose : false;
|
||||||
@@ -168,8 +173,13 @@ void SwitcherData::SaveVersion(obs_data_t *obj,
|
|||||||
obs_data_set_string(obj, "version", currentVersion.c_str());
|
obs_data_set_string(obj, "version", currentVersion.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::AddIntervalResetStep(std::function<void()> function)
|
void SwitcherData::AddIntervalResetStep(std::function<void()> function,
|
||||||
|
bool tryLock)
|
||||||
{
|
{
|
||||||
|
if (!tryLock) {
|
||||||
|
resetIntervalSteps.emplace_back(function);
|
||||||
|
return;
|
||||||
|
}
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
resetIntervalSteps.emplace_back(function);
|
resetIntervalSteps.emplace_back(function);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,9 @@
|
|||||||
|
|
||||||
#include "macro-properties.hpp"
|
#include "macro-properties.hpp"
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
#include "curl-helper.hpp"
|
|
||||||
#include "priority-helper.hpp"
|
#include "priority-helper.hpp"
|
||||||
#include "log-helper.hpp"
|
#include "log-helper.hpp"
|
||||||
#include "plugin-state-helper.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -29,7 +28,6 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -47,6 +45,7 @@ class SwitcherData;
|
|||||||
extern SwitcherData *switcher;
|
extern SwitcherData *switcher;
|
||||||
SwitcherData *GetSwitcher();
|
SwitcherData *GetSwitcher();
|
||||||
std::mutex *GetSwitcherMutex();
|
std::mutex *GetSwitcherMutex();
|
||||||
|
std::unique_lock<std::mutex> *GetSwitcherLoopLock();
|
||||||
bool VerboseLoggingEnabled();
|
bool VerboseLoggingEnabled();
|
||||||
|
|
||||||
class SwitcherData {
|
class SwitcherData {
|
||||||
@@ -54,7 +53,6 @@ public:
|
|||||||
void Thread();
|
void Thread();
|
||||||
void Start();
|
void Start();
|
||||||
void Stop();
|
void Stop();
|
||||||
std::unique_lock<std::mutex> *GetLock() { return mainLoopLock; }
|
|
||||||
|
|
||||||
const char *Translate(const char *);
|
const char *Translate(const char *);
|
||||||
obs_module_t *GetModule();
|
obs_module_t *GetModule();
|
||||||
@@ -68,28 +66,22 @@ public:
|
|||||||
void AddSaveStep(std::function<void(obs_data_t *)>);
|
void AddSaveStep(std::function<void(obs_data_t *)>);
|
||||||
void AddLoadStep(std::function<void(obs_data_t *)>);
|
void AddLoadStep(std::function<void(obs_data_t *)>);
|
||||||
void AddPostLoadStep(std::function<void()>);
|
void AddPostLoadStep(std::function<void()>);
|
||||||
void AddIntervalResetStep(std::function<void()>);
|
void AddIntervalResetStep(std::function<void()>, bool lock = true);
|
||||||
bool CheckForMatch(OBSWeakSource &scene, OBSWeakSource &transition,
|
bool CheckForMatch(OBSWeakSource &scene, OBSWeakSource &transition,
|
||||||
int &linger, bool &setPreviousSceneAsMatch,
|
int &linger, bool &setPreviousSceneAsMatch,
|
||||||
bool ¯oMatch);
|
bool ¯oMatch);
|
||||||
bool CheckMacros();
|
|
||||||
bool RunMacros();
|
|
||||||
void CheckNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
void CheckNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
||||||
OBSWeakSource &transition, int &sleep);
|
OBSWeakSource &transition, int &sleep);
|
||||||
|
|
||||||
/* --- Start of saving / loading section --- */
|
/* --- Start of saving / loading section --- */
|
||||||
|
|
||||||
void SaveSettings(obs_data_t *obj);
|
void SaveSettings(obs_data_t *obj);
|
||||||
void SaveMacros(obs_data_t *obj);
|
|
||||||
void SaveVariables(obs_data_t *obj);
|
|
||||||
void SaveGeneralSettings(obs_data_t *obj);
|
void SaveGeneralSettings(obs_data_t *obj);
|
||||||
void SaveHotkeys(obs_data_t *obj);
|
void SaveHotkeys(obs_data_t *obj);
|
||||||
void SaveUISettings(obs_data_t *obj);
|
void SaveUISettings(obs_data_t *obj);
|
||||||
void SaveVersion(obs_data_t *obj, const std::string ¤tVersion);
|
void SaveVersion(obs_data_t *obj, const std::string ¤tVersion);
|
||||||
|
|
||||||
void LoadSettings(obs_data_t *obj);
|
void LoadSettings(obs_data_t *obj);
|
||||||
void LoadMacros(obs_data_t *obj);
|
|
||||||
void LoadVariables(obs_data_t *obj);
|
|
||||||
void LoadGeneralSettings(obs_data_t *obj);
|
void LoadGeneralSettings(obs_data_t *obj);
|
||||||
void LoadHotkeys(obs_data_t *obj);
|
void LoadHotkeys(obs_data_t *obj);
|
||||||
void LoadUISettings(obs_data_t *obj);
|
void LoadUISettings(obs_data_t *obj);
|
||||||
@@ -110,9 +102,6 @@ public:
|
|||||||
std::unique_lock<std::mutex> *mainLoopLock = nullptr;
|
std::unique_lock<std::mutex> *mainLoopLock = nullptr;
|
||||||
bool stop = false;
|
bool stop = false;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
std::condition_variable macroWaitCv;
|
|
||||||
std::atomic_bool abortMacroWait = {false};
|
|
||||||
std::condition_variable macroTransitionCv;
|
|
||||||
|
|
||||||
std::vector<std::function<void(obs_data_t *)>> saveSteps;
|
std::vector<std::function<void(obs_data_t *)>> saveSteps;
|
||||||
std::vector<std::function<void(obs_data_t *)>> loadSteps;
|
std::vector<std::function<void(obs_data_t *)>> loadSteps;
|
||||||
@@ -122,21 +111,14 @@ public:
|
|||||||
bool firstBoot = true;
|
bool firstBoot = true;
|
||||||
bool transitionActive = false;
|
bool transitionActive = false;
|
||||||
bool sceneColletionStop = false;
|
bool sceneColletionStop = false;
|
||||||
bool replayBufferSaved = false;
|
|
||||||
bool obsIsShuttingDown = false;
|
bool obsIsShuttingDown = false;
|
||||||
bool firstInterval = true;
|
bool firstInterval = true;
|
||||||
bool firstIntervalAfterStop = true;
|
bool firstIntervalAfterStop = true;
|
||||||
int shutdownConditionCount = 0;
|
|
||||||
bool startupLoadDone = false;
|
bool startupLoadDone = false;
|
||||||
|
|
||||||
obs_source_t *waitScene = nullptr;
|
obs_source_t *waitScene = nullptr;
|
||||||
OBSWeakSource currentScene = nullptr;
|
OBSWeakSource currentScene = nullptr;
|
||||||
OBSWeakSource previousScene = nullptr;
|
OBSWeakSource previousScene = nullptr;
|
||||||
std::chrono::high_resolution_clock::time_point lastSceneChangeTime{};
|
|
||||||
std::chrono::high_resolution_clock::time_point lastTransitionEndTime{};
|
|
||||||
std::chrono::high_resolution_clock::time_point lastStreamStartingTime{};
|
|
||||||
std::chrono::high_resolution_clock::time_point lastStreamStoppingTime{};
|
|
||||||
std::chrono::high_resolution_clock::time_point lastMatchTime;
|
|
||||||
|
|
||||||
/* --- Start of General tab section --- */
|
/* --- Start of General tab section --- */
|
||||||
|
|
||||||
@@ -161,25 +143,9 @@ public:
|
|||||||
|
|
||||||
/* --- End of General tab section --- */
|
/* --- End of General tab section --- */
|
||||||
|
|
||||||
struct AudioFadeInfo {
|
|
||||||
std::atomic_bool active = {false};
|
|
||||||
std::atomic_int id = {0};
|
|
||||||
};
|
|
||||||
AudioFadeInfo masterAudioFade;
|
|
||||||
std::unordered_map<std::string, AudioFadeInfo> activeAudioFades;
|
|
||||||
|
|
||||||
MacroProperties macroProperties;
|
|
||||||
std::deque<std::shared_ptr<Macro>> macros;
|
|
||||||
bool macroSceneSwitched = false;
|
|
||||||
|
|
||||||
Curlhelper curl;
|
|
||||||
std::deque<std::shared_ptr<Item>> variables;
|
|
||||||
|
|
||||||
std::string lastTitle;
|
std::string lastTitle;
|
||||||
std::string currentTitle;
|
std::string currentTitle;
|
||||||
std::string currentForegroundProcess;
|
std::string currentForegroundProcess;
|
||||||
std::pair<int, int> lastCursorPos = {0, 0};
|
|
||||||
bool cursorPosChanged = false;
|
|
||||||
|
|
||||||
std::vector<int> functionNamesByPriority =
|
std::vector<int> functionNamesByPriority =
|
||||||
GetDefaultFunctionPriorityList();
|
GetDefaultFunctionPriorityList();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "connection-manager.hpp"
|
#include "connection-manager.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "obs-module-helper.hpp"
|
#include "obs-module-helper.hpp"
|
||||||
#include "plugin-state-helper.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "name-dialog.hpp"
|
#include "name-dialog.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ constexpr auto curl_library_name = "libcurl.4.dylib";
|
|||||||
constexpr auto curl_library_name = "libcurl.so.4";
|
constexpr auto curl_library_name = "libcurl.so.4";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Curlhelper::Curlhelper()
|
CurlHelper::CurlHelper()
|
||||||
{
|
{
|
||||||
if (LoadLib()) {
|
if (LoadLib()) {
|
||||||
_curl = _init();
|
_curl = _init();
|
||||||
@@ -23,7 +23,7 @@ Curlhelper::Curlhelper()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Curlhelper::~Curlhelper()
|
CurlHelper::~CurlHelper()
|
||||||
{
|
{
|
||||||
if (_lib) {
|
if (_lib) {
|
||||||
if (_cleanup) {
|
if (_cleanup) {
|
||||||
@@ -34,32 +34,46 @@ Curlhelper::~Curlhelper()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_slist *Curlhelper::SlistAppend(curl_slist *list, const char *string)
|
CurlHelper &CurlHelper::GetInstance()
|
||||||
{
|
{
|
||||||
if (!_initialized) {
|
static CurlHelper curl;
|
||||||
|
return curl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CurlHelper::Initialized()
|
||||||
|
{
|
||||||
|
return GetInstance()._initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_slist *CurlHelper::SlistAppend(curl_slist *list, const char *string)
|
||||||
|
{
|
||||||
|
auto &curl = GetInstance();
|
||||||
|
if (!curl._initialized) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return _slistAppend(list, string);
|
return curl._slistAppend(list, string);
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLcode Curlhelper::Perform()
|
CURLcode CurlHelper::Perform()
|
||||||
{
|
{
|
||||||
if (!_initialized) {
|
auto &curl = GetInstance();
|
||||||
|
if (!curl._initialized) {
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
}
|
}
|
||||||
return _perform(_curl);
|
return curl._perform(curl._curl);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *Curlhelper::GetError(CURLcode code)
|
char *CurlHelper::GetError(CURLcode code)
|
||||||
{
|
{
|
||||||
if (!_initialized) {
|
auto &curl = GetInstance();
|
||||||
|
if (!curl._initialized) {
|
||||||
return (char *)"CURL initialization failed";
|
return (char *)"CURL initialization failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
return _error(code);
|
return curl._error(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Curlhelper::LoadLib()
|
bool CurlHelper::LoadLib()
|
||||||
{
|
{
|
||||||
_lib = new QLibrary(curl_library_name, nullptr);
|
_lib = new QLibrary(curl_library_name, nullptr);
|
||||||
if (Resolve()) {
|
if (Resolve()) {
|
||||||
@@ -103,7 +117,7 @@ bool Curlhelper::LoadLib()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Curlhelper::Resolve()
|
bool CurlHelper::Resolve()
|
||||||
{
|
{
|
||||||
_init = (initFunction)_lib->resolve("curl_easy_init");
|
_init = (initFunction)_lib->resolve("curl_easy_init");
|
||||||
_setopt = (setOptFunction)_lib->resolve("curl_easy_setopt");
|
_setopt = (setOptFunction)_lib->resolve("curl_easy_setopt");
|
||||||
|
|||||||
@@ -1,31 +1,35 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <QLibrary>
|
#include <QLibrary>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
typedef CURL *(*initFunction)(void);
|
class CurlHelper {
|
||||||
typedef CURLcode (*setOptFunction)(CURL *, CURLoption, ...);
|
|
||||||
typedef struct curl_slist *(*slistAppendFunction)(struct curl_slist *list,
|
|
||||||
const char *string);
|
|
||||||
typedef CURLcode (*performFunction)(CURL *);
|
|
||||||
typedef void (*cleanupFunction)(CURL *);
|
|
||||||
typedef char *(*errorFunction)(CURLcode);
|
|
||||||
|
|
||||||
class Curlhelper {
|
|
||||||
public:
|
public:
|
||||||
Curlhelper();
|
static bool Initialized();
|
||||||
~Curlhelper();
|
template<typename... Args> static CURLcode SetOpt(CURLoption, Args...);
|
||||||
|
static struct curl_slist *SlistAppend(struct curl_slist *list,
|
||||||
bool Initialized() { return _initialized; }
|
const char *string);
|
||||||
|
static CURLcode Perform();
|
||||||
template<typename... Args> CURLcode SetOpt(CURLoption, Args...);
|
static char *GetError(CURLcode code);
|
||||||
struct curl_slist *SlistAppend(struct curl_slist *list,
|
|
||||||
const char *string);
|
|
||||||
CURLcode Perform();
|
|
||||||
char *GetError(CURLcode code);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CurlHelper();
|
||||||
|
CurlHelper(const CurlHelper &) = delete;
|
||||||
|
CurlHelper &operator=(const CurlHelper &) = delete;
|
||||||
|
~CurlHelper();
|
||||||
|
|
||||||
|
typedef CURL *(*initFunction)(void);
|
||||||
|
typedef CURLcode (*setOptFunction)(CURL *, CURLoption, ...);
|
||||||
|
typedef struct curl_slist *(*slistAppendFunction)(
|
||||||
|
struct curl_slist *list, const char *string);
|
||||||
|
typedef CURLcode (*performFunction)(CURL *);
|
||||||
|
typedef void (*cleanupFunction)(CURL *);
|
||||||
|
typedef char *(*errorFunction)(CURLcode);
|
||||||
|
|
||||||
|
static CurlHelper &GetInstance();
|
||||||
|
|
||||||
bool LoadLib();
|
bool LoadLib();
|
||||||
bool Resolve();
|
bool Resolve();
|
||||||
|
|
||||||
@@ -37,16 +41,17 @@ private:
|
|||||||
errorFunction _error = nullptr;
|
errorFunction _error = nullptr;
|
||||||
CURL *_curl = nullptr;
|
CURL *_curl = nullptr;
|
||||||
QLibrary *_lib;
|
QLibrary *_lib;
|
||||||
bool _initialized = false;
|
std::atomic_bool _initialized = {false};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
inline CURLcode Curlhelper::SetOpt(CURLoption option, Args... args)
|
inline CURLcode CurlHelper::SetOpt(CURLoption option, Args... args)
|
||||||
{
|
{
|
||||||
if (!_initialized) {
|
auto &curl = GetInstance();
|
||||||
|
if (!curl._initialized) {
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
}
|
}
|
||||||
return _setopt(_curl, option, args...);
|
return curl._setopt(curl._curl, option, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ FilterComboBox::FilterComboBox(QWidget *parent, const QString &placehodler)
|
|||||||
connect(c, QOverload<const QModelIndex &>::of(&QCompleter::highlighted),
|
connect(c, QOverload<const QModelIndex &>::of(&QCompleter::highlighted),
|
||||||
this, &FilterComboBox::CompleterHighlightChanged);
|
this, &FilterComboBox::CompleterHighlightChanged);
|
||||||
connect(lineEdit(), &QLineEdit::textChanged, this,
|
connect(lineEdit(), &QLineEdit::textChanged, this,
|
||||||
&FilterComboBox::TextChagned);
|
&FilterComboBox::TextChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilterComboBox::SetFilterBehaviourEnabled(bool value)
|
void FilterComboBox::SetFilterBehaviourEnabled(bool value)
|
||||||
@@ -108,7 +108,7 @@ void FilterComboBox::CompleterHighlightChanged(const QModelIndex &index)
|
|||||||
emit currentTextChanged(text);
|
emit currentTextChanged(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilterComboBox::TextChagned(const QString &text)
|
void FilterComboBox::TextChanged(const QString &text)
|
||||||
{
|
{
|
||||||
auto c = completer();
|
auto c = completer();
|
||||||
const bool completerActive = c->completionCount() > 0;
|
const bool completerActive = c->completionCount() > 0;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ protected:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void CompleterHighlightChanged(const QModelIndex &);
|
void CompleterHighlightChanged(const QModelIndex &);
|
||||||
void TextChagned(const QString &);
|
void TextChanged(const QString &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _lastCompleterHighlightRow = -1;
|
int _lastCompleterHighlightRow = -1;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "macro-segment-selection.hpp"
|
#include "macro-segment-selection.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "obs-module-helper.hpp"
|
#include "obs-module-helper.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -108,7 +108,7 @@ void MacroSegmentSelection::IndexChanged(const IntVariable &value)
|
|||||||
|
|
||||||
void MacroSegmentSelection::MarkSelectedSegment()
|
void MacroSegmentSelection::MarkSelectedSegment()
|
||||||
{
|
{
|
||||||
if (!GetSwitcher() || GetSwitcher()->disableHints) {
|
if (!HighlightUIElementsEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "plugin-state-helper.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "switcher-data.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -23,9 +23,9 @@ void AddPostLoadStep(std::function<void()> step)
|
|||||||
GetSwitcher()->AddPostLoadStep(step);
|
GetSwitcher()->AddPostLoadStep(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddIntervalResetStep(std::function<void()> step)
|
void AddIntervalResetStep(std::function<void()> step, bool lock)
|
||||||
{
|
{
|
||||||
GetSwitcher()->AddIntervalResetStep(step);
|
GetSwitcher()->AddIntervalResetStep(step, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopPlugin()
|
void StopPlugin()
|
||||||
@@ -38,24 +38,70 @@ void StartPlugin()
|
|||||||
GetSwitcher()->Start();
|
GetSwitcher()->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PluginIsRunning()
|
||||||
|
{
|
||||||
|
return GetSwitcher() && GetSwitcher()->th &&
|
||||||
|
GetSwitcher()->th->isRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetIntervalValue()
|
||||||
|
{
|
||||||
|
return GetSwitcher()->interval;
|
||||||
|
}
|
||||||
|
|
||||||
void SetPluginNoMatchBehavior(NoMatchBehavior behavior)
|
void SetPluginNoMatchBehavior(NoMatchBehavior behavior)
|
||||||
{
|
{
|
||||||
GetSwitcher()->switchIfNotMatching = behavior;
|
GetSwitcher()->switchIfNotMatching = behavior;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNoMatchScene(const OBSWeakSource &scene)
|
|
||||||
{
|
|
||||||
GetSwitcher()->nonMatchingScene = scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
NoMatchBehavior GetPluginNoMatchBehavior()
|
NoMatchBehavior GetPluginNoMatchBehavior()
|
||||||
{
|
{
|
||||||
return GetSwitcher()->switchIfNotMatching;
|
return GetSwitcher()->switchIfNotMatching;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetNoMatchScene(const OBSWeakSource &scene)
|
||||||
|
{
|
||||||
|
GetSwitcher()->nonMatchingScene = scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ForegroundWindowTitle()
|
||||||
|
{
|
||||||
|
return GetSwitcher()->currentTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PreviousForegroundWindowTitle()
|
||||||
|
{
|
||||||
|
return GetSwitcher()->lastTitle;
|
||||||
|
}
|
||||||
|
|
||||||
bool SettingsWindowIsOpened()
|
bool SettingsWindowIsOpened()
|
||||||
{
|
{
|
||||||
return GetSwitcher()->settingsWindowOpened;
|
return GetSwitcher()->settingsWindowOpened;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HighlightUIElementsEnabled()
|
||||||
|
{
|
||||||
|
return GetSwitcher() && !GetSwitcher()->disableHints;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OBSIsShuttingDown()
|
||||||
|
{
|
||||||
|
return GetSwitcher()->obsIsShuttingDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitialLoadIsComplete()
|
||||||
|
{
|
||||||
|
return GetSwitcher()->startupLoadDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFirstInterval()
|
||||||
|
{
|
||||||
|
return GetSwitcher()->firstInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFirstIntervalAfterStop()
|
||||||
|
{
|
||||||
|
return GetSwitcher()->firstIntervalAfterStop;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -9,16 +10,27 @@ void LoadPluginSettings(obs_data_t *);
|
|||||||
void AddSaveStep(std::function<void(obs_data_t *)>);
|
void AddSaveStep(std::function<void(obs_data_t *)>);
|
||||||
void AddLoadStep(std::function<void(obs_data_t *)>);
|
void AddLoadStep(std::function<void(obs_data_t *)>);
|
||||||
void AddPostLoadStep(std::function<void()>);
|
void AddPostLoadStep(std::function<void()>);
|
||||||
void AddIntervalResetStep(std::function<void()>);
|
void AddIntervalResetStep(std::function<void()>, bool lock = true);
|
||||||
|
|
||||||
void StopPlugin();
|
void StopPlugin();
|
||||||
void StartPlugin();
|
void StartPlugin();
|
||||||
|
bool PluginIsRunning();
|
||||||
|
int GetIntervalValue();
|
||||||
|
|
||||||
enum class NoMatchBehavior { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 };
|
enum class NoMatchBehavior { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 };
|
||||||
void SetPluginNoMatchBehavior(NoMatchBehavior);
|
void SetPluginNoMatchBehavior(NoMatchBehavior);
|
||||||
NoMatchBehavior GetPluginNoMatchBehavior();
|
NoMatchBehavior GetPluginNoMatchBehavior();
|
||||||
void SetNoMatchScene(const OBSWeakSource &);
|
void SetNoMatchScene(const OBSWeakSource &);
|
||||||
|
|
||||||
|
std::string ForegroundWindowTitle();
|
||||||
|
std::string PreviousForegroundWindowTitle();
|
||||||
|
|
||||||
bool SettingsWindowIsOpened();
|
bool SettingsWindowIsOpened();
|
||||||
|
bool HighlightUIElementsEnabled();
|
||||||
|
|
||||||
|
bool OBSIsShuttingDown();
|
||||||
|
bool InitialLoadIsComplete();
|
||||||
|
bool IsFirstInterval();
|
||||||
|
bool IsFirstIntervalAfterStop();
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "process-config.hpp"
|
#include "process-config.hpp"
|
||||||
|
#include "log-helper.hpp"
|
||||||
#include "name-dialog.hpp"
|
#include "name-dialog.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ bool ProcessConfig::Load(obs_data_t *obj)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList ProcessConfig::Args()
|
QStringList ProcessConfig::Args() const
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
for (auto &arg : _args) {
|
for (auto &arg : _args) {
|
||||||
@@ -46,6 +47,42 @@ QStringList ProcessConfig::Args()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProcessConfig::StartProcessDetached() const
|
||||||
|
{
|
||||||
|
return QProcess::startDetached(QString::fromStdString(Path()), Args(),
|
||||||
|
QString::fromStdString(WorkingDir()));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::variant<int, ProcessConfig::ProcStartError>
|
||||||
|
ProcessConfig::StartProcessAndWait(int timeout) const
|
||||||
|
{
|
||||||
|
QProcess process;
|
||||||
|
process.setWorkingDirectory(QString::fromStdString(WorkingDir()));
|
||||||
|
process.start(QString::fromStdString(Path()), Args());
|
||||||
|
vblog(LOG_INFO, "run \"%s\" with a timeout of %d ms", Path().c_str(),
|
||||||
|
timeout);
|
||||||
|
|
||||||
|
if (!process.waitForFinished(timeout)) {
|
||||||
|
if (process.error() == QProcess::FailedToStart) {
|
||||||
|
vblog(LOG_INFO, "failed to start \"%s\"!",
|
||||||
|
Path().c_str());
|
||||||
|
return ProcStartError::FAILED_TO_START;
|
||||||
|
}
|
||||||
|
vblog(LOG_INFO,
|
||||||
|
"timeout while running \"%s\"\nAttempting to kill process!",
|
||||||
|
Path().c_str());
|
||||||
|
process.kill();
|
||||||
|
process.waitForFinished();
|
||||||
|
return ProcStartError::TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.exitStatus() == QProcess::NormalExit) {
|
||||||
|
return process.exitCode();
|
||||||
|
}
|
||||||
|
vblog(LOG_INFO, "process \"%s\" crashed!", Path().c_str());
|
||||||
|
return ProcStartError::CRASH;
|
||||||
|
}
|
||||||
|
|
||||||
ProcessConfigEdit::ProcessConfigEdit(QWidget *parent)
|
ProcessConfigEdit::ProcessConfigEdit(QWidget *parent)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_filePath(new FileSelection()),
|
_filePath(new FileSelection()),
|
||||||
@@ -91,7 +128,7 @@ ProcessConfigEdit::ProcessConfigEdit(QWidget *parent)
|
|||||||
_advancedSettingsLayout->addWidget(_argList);
|
_advancedSettingsLayout->addWidget(_argList);
|
||||||
_advancedSettingsLayout->addLayout(workingDirectoryLayout);
|
_advancedSettingsLayout->addLayout(workingDirectoryLayout);
|
||||||
|
|
||||||
auto *mainLayout = new QVBoxLayout;
|
auto mainLayout = new QVBoxLayout;
|
||||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
mainLayout->addLayout(entryLayout);
|
mainLayout->addLayout(entryLayout);
|
||||||
mainLayout->addLayout(_advancedSettingsLayout);
|
mainLayout->addLayout(_advancedSettingsLayout);
|
||||||
@@ -143,6 +180,9 @@ void ProcessConfigEdit::ShowAdvancedSettings(bool showAdvancedSettings)
|
|||||||
_showAdvancedSettings->setVisible(!showAdvancedSettings);
|
_showAdvancedSettings->setVisible(!showAdvancedSettings);
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
|
if (showAdvancedSettings) {
|
||||||
|
emit AdvancedSettingsEnabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
#include "string-list.hpp"
|
#include "string-list.hpp"
|
||||||
|
|
||||||
#include <obs-data.h>
|
#include <obs-data.h>
|
||||||
#include <obs-module.h>
|
#include <obs-module-helper.hpp>
|
||||||
|
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -17,10 +18,21 @@ public:
|
|||||||
bool Save(obs_data_t *obj) const;
|
bool Save(obs_data_t *obj) const;
|
||||||
bool Load(obs_data_t *obj);
|
bool Load(obs_data_t *obj);
|
||||||
|
|
||||||
std::string Path() { return _path; }
|
std::string Path() const { return _path; }
|
||||||
std::string UnresolvedPath() const { return _path.UnresolvedValue(); }
|
std::string UnresolvedPath() const { return _path.UnresolvedValue(); }
|
||||||
std::string WorkingDir() { return _workingDirectory; }
|
std::string WorkingDir() const { return _workingDirectory; }
|
||||||
QStringList Args(); // Resolves variables
|
QStringList Args() const; // Resolves variables
|
||||||
|
|
||||||
|
enum class ProcStartError {
|
||||||
|
NONE,
|
||||||
|
FAILED_TO_START,
|
||||||
|
TIMEOUT,
|
||||||
|
CRASH,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::variant<int, ProcStartError>
|
||||||
|
StartProcessAndWait(int timeoutInMs) const;
|
||||||
|
bool StartProcessDetached() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StringVariable _path = obs_module_text("AdvSceneSwitcher.enterPath");
|
StringVariable _path = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||||
@@ -44,6 +56,7 @@ private slots:
|
|||||||
void ArgsChanged(const StringList &);
|
void ArgsChanged(const StringList &);
|
||||||
signals:
|
signals:
|
||||||
void ConfigChanged(const ProcessConfig &);
|
void ConfigChanged(const ProcessConfig &);
|
||||||
|
void AdvancedSettingsEnabled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ShowAdvancedSettings(bool);
|
void ShowAdvancedSettings(bool);
|
||||||
|
|||||||
@@ -51,23 +51,6 @@ RegexConfig::GetRegularExpression(const std::string &expr) const
|
|||||||
return GetRegularExpression(QString::fromStdString(expr));
|
return GetRegularExpression(QString::fromStdString(expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RegexConfig::Matches(const QString &text, const QString &expression) const
|
|
||||||
{
|
|
||||||
auto regex = GetRegularExpression(expression);
|
|
||||||
if (!regex.isValid()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto match = regex.match(text);
|
|
||||||
return match.hasMatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RegexConfig::Matches(const std::string &text,
|
|
||||||
const std::string &expression) const
|
|
||||||
{
|
|
||||||
return Matches(QString::fromStdString(text),
|
|
||||||
QString::fromStdString(expression));
|
|
||||||
}
|
|
||||||
|
|
||||||
RegexConfig RegexConfig::PartialMatchRegexConfig()
|
RegexConfig RegexConfig::PartialMatchRegexConfig()
|
||||||
{
|
{
|
||||||
RegexConfig conf;
|
RegexConfig conf;
|
||||||
|
|||||||
@@ -29,9 +29,6 @@ public:
|
|||||||
};
|
};
|
||||||
QRegularExpression GetRegularExpression(const QString &) const;
|
QRegularExpression GetRegularExpression(const QString &) const;
|
||||||
QRegularExpression GetRegularExpression(const std::string &) const;
|
QRegularExpression GetRegularExpression(const std::string &) const;
|
||||||
bool Matches(const QString &text, const QString &expression) const;
|
|
||||||
bool Matches(const std::string &text,
|
|
||||||
const std::string &expression) const;
|
|
||||||
|
|
||||||
static RegexConfig PartialMatchRegexConfig();
|
static RegexConfig PartialMatchRegexConfig();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "resizing-text-edit.hpp"
|
#include "resizing-text-edit.hpp"
|
||||||
|
|
||||||
#include <obs-module.h>
|
#include <obs-module-helper.hpp>
|
||||||
|
#include <QScrollBar>
|
||||||
#include <utility.hpp>
|
#include <utility.hpp>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -14,10 +15,12 @@ ResizingPlainTextEdit::ResizingPlainTextEdit(QWidget *parent,
|
|||||||
_minLines(minLines),
|
_minLines(minLines),
|
||||||
_paddingLines(paddingLines)
|
_paddingLines(paddingLines)
|
||||||
{
|
{
|
||||||
|
setWordWrapMode(QTextOption::NoWrap);
|
||||||
QWidget::connect(this, SIGNAL(textChanged()), this,
|
QWidget::connect(this, SIGNAL(textChanged()), this,
|
||||||
SLOT(ResizeTexteditArea()));
|
SLOT(ResizeTexteditArea()));
|
||||||
QWidget::connect(this, SIGNAL(textChanged()), this,
|
QWidget::connect(this, SIGNAL(textChanged()), this,
|
||||||
SLOT(PreventExceedingMaxLength()));
|
SLOT(PreventExceedingMaxLength()));
|
||||||
|
verticalScrollBar()->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ResizingPlainTextEdit::maxLength()
|
int ResizingPlainTextEdit::maxLength()
|
||||||
@@ -30,19 +33,35 @@ void ResizingPlainTextEdit::setMaxLength(int maxLength)
|
|||||||
_maxLength = maxLength;
|
_maxLength = maxLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ResizingPlainTextEdit::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
if (obj == horizontalScrollBar()) {
|
||||||
|
if (event->type() == QEvent::Show) {
|
||||||
|
AddHeightForScrollBar(true);
|
||||||
|
} else if (event->type() == QEvent::Hide) {
|
||||||
|
AddHeightForScrollBar(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QPlainTextEdit::eventFilter(obj, event);
|
||||||
|
}
|
||||||
|
|
||||||
void ResizingPlainTextEdit::ResizeTexteditArea()
|
void ResizingPlainTextEdit::ResizeTexteditArea()
|
||||||
{
|
{
|
||||||
QFontMetrics f(font());
|
QFontMetrics f(font());
|
||||||
int rowHeight = f.lineSpacing();
|
int rowHeight = f.lineSpacing();
|
||||||
int numLines = document()->blockCount();
|
int numLines = document()->blockCount();
|
||||||
|
|
||||||
|
int height = 0;
|
||||||
if (numLines + _paddingLines < _minLines) {
|
if (numLines + _paddingLines < _minLines) {
|
||||||
setFixedHeight(_minLines * rowHeight);
|
height = _minLines * rowHeight;
|
||||||
} else if (numLines + _paddingLines < _scrollAt) {
|
} else if (numLines + _paddingLines < _scrollAt) {
|
||||||
setFixedHeight((numLines + _paddingLines) * rowHeight);
|
height = (numLines + _paddingLines) * rowHeight;
|
||||||
} else {
|
} else {
|
||||||
setFixedHeight(_scrollAt * rowHeight);
|
height = _scrollAt * rowHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setFixedHeight(height + _hScrollBarAddedHeight);
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
@@ -62,4 +81,21 @@ void ResizingPlainTextEdit::PreventExceedingMaxLength()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResizingPlainTextEdit::AddHeightForScrollBar(bool addHeight)
|
||||||
|
{
|
||||||
|
if (!addHeight) {
|
||||||
|
setFixedHeight(height() - _hScrollBarAddedHeight);
|
||||||
|
_hScrollBarAddedHeight = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we have already added space for the scroll bar
|
||||||
|
if (_hScrollBarAddedHeight > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_hScrollBarAddedHeight = verticalScrollBar()->height();
|
||||||
|
setFixedHeight(height() + _hScrollBarAddedHeight);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -13,15 +13,21 @@ public:
|
|||||||
int maxLength();
|
int maxLength();
|
||||||
void setMaxLength(int maxLength);
|
void setMaxLength(int maxLength);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ResizeTexteditArea();
|
void ResizeTexteditArea();
|
||||||
void PreventExceedingMaxLength();
|
void PreventExceedingMaxLength();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void AddHeightForScrollBar(bool addHeight);
|
||||||
|
|
||||||
const int _scrollAt;
|
const int _scrollAt;
|
||||||
const int _minLines;
|
const int _minLines;
|
||||||
const int _paddingLines;
|
const int _paddingLines;
|
||||||
int _maxLength = -1;
|
int _maxLength = -1;
|
||||||
|
int _hScrollBarAddedHeight = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "scene-selection.hpp"
|
#include "scene-selection.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "obs-module-helper.hpp"
|
||||||
|
#include "scene-group.hpp"
|
||||||
|
#include "scene-switch-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -108,9 +110,9 @@ OBSWeakSource SceneSelection::GetScene(bool advance) const
|
|||||||
}
|
}
|
||||||
return _group->getCurrentScene();
|
return _group->getCurrentScene();
|
||||||
case Type::PREVIOUS:
|
case Type::PREVIOUS:
|
||||||
return switcher->previousScene;
|
return GetPreviousScene();
|
||||||
case Type::CURRENT:
|
case Type::CURRENT:
|
||||||
return switcher->currentScene;
|
return GetCurrentScene();
|
||||||
case Type::PREVIEW: {
|
case Type::PREVIEW: {
|
||||||
auto s = obs_frontend_get_current_preview_scene();
|
auto s = obs_frontend_get_current_preview_scene();
|
||||||
auto scene = obs_source_get_weak_source(s);
|
auto scene = obs_source_get_weak_source(s);
|
||||||
@@ -237,7 +239,7 @@ static QStringList getScenesList()
|
|||||||
static QStringList getSceneGroupsList()
|
static QStringList getSceneGroupsList()
|
||||||
{
|
{
|
||||||
QStringList list;
|
QStringList list;
|
||||||
for (const auto &sg : switcher->sceneGroups) {
|
for (const auto &sg : GetSceneGroups()) {
|
||||||
list << QString::fromStdString(sg.name);
|
list << QString::fromStdString(sg.name);
|
||||||
}
|
}
|
||||||
list.sort();
|
list.sort();
|
||||||
|
|||||||
@@ -1,10 +1,36 @@
|
|||||||
#include "scene-switch-helpers.hpp"
|
#include "scene-switch-helpers.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "log-helper.hpp"
|
||||||
#include "obs-frontend-api.h"
|
#include "obs-frontend-api.h"
|
||||||
|
#include "switcher-data.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
|
static std::chrono::high_resolution_clock::time_point lastSceneChangeTime{};
|
||||||
|
static std::chrono::high_resolution_clock::time_point lastTransitionEndTime{};
|
||||||
|
static bool setupEventHandler();
|
||||||
|
static bool eventHandlerIsSetup = setupEventHandler();
|
||||||
|
|
||||||
|
static bool setupEventHandler()
|
||||||
|
{
|
||||||
|
static auto handleEvents = [](enum obs_frontend_event event, void *) {
|
||||||
|
switch (event) {
|
||||||
|
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
|
||||||
|
lastSceneChangeTime =
|
||||||
|
std::chrono::high_resolution_clock::now();
|
||||||
|
break;
|
||||||
|
case OBS_FRONTEND_EVENT_TRANSITION_STOPPED:
|
||||||
|
lastTransitionEndTime =
|
||||||
|
std::chrono::high_resolution_clock::now();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
obs_frontend_add_event_callback(handleEvents, nullptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static std::pair<obs_weak_source_t *, int>
|
static std::pair<obs_weak_source_t *, int>
|
||||||
getNextTransition(obs_weak_source_t *scene1, obs_weak_source_t *scene2)
|
getNextTransition(obs_weak_source_t *scene1, obs_weak_source_t *scene2)
|
||||||
{
|
{
|
||||||
@@ -35,10 +61,9 @@ void SetNextTransition(const SceneSwitchInfo &sceneSwitch,
|
|||||||
// 3. Current transition settings
|
// 3. Current transition settings
|
||||||
|
|
||||||
// Transition Tab
|
// Transition Tab
|
||||||
obs_weak_source_t *currentScene =
|
OBSWeakSourceAutoRelease currentScene =
|
||||||
obs_source_get_weak_source(currentSource);
|
obs_source_get_weak_source(currentSource);
|
||||||
auto tinfo = getNextTransition(currentScene, sceneSwitch.scene);
|
auto tinfo = getNextTransition(currentScene, sceneSwitch.scene);
|
||||||
obs_weak_source_release(currentScene);
|
|
||||||
|
|
||||||
OBSWeakSource nextTransition = tinfo.first;
|
OBSWeakSource nextTransition = tinfo.first;
|
||||||
int nextTransitionDuration = tinfo.second;
|
int nextTransitionDuration = tinfo.second;
|
||||||
@@ -53,23 +78,23 @@ void SetNextTransition(const SceneSwitchInfo &sceneSwitch,
|
|||||||
|
|
||||||
// Current transition settings
|
// Current transition settings
|
||||||
if (!nextTransition) {
|
if (!nextTransition) {
|
||||||
auto ct = obs_frontend_get_current_transition();
|
OBSSourceAutoRelease currentTransition =
|
||||||
nextTransition = obs_source_get_weak_source(ct);
|
obs_frontend_get_current_transition();
|
||||||
|
nextTransition = obs_source_get_weak_source(currentTransition);
|
||||||
obs_weak_source_release(nextTransition);
|
obs_weak_source_release(nextTransition);
|
||||||
obs_source_release(ct);
|
|
||||||
}
|
}
|
||||||
if (!nextTransitionDuration) {
|
if (!nextTransitionDuration) {
|
||||||
nextTransitionDuration = obs_frontend_get_transition_duration();
|
nextTransitionDuration = obs_frontend_get_transition_duration();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switcher->adjustActiveTransitionType) {
|
if (ShouldModifyActiveTransition()) {
|
||||||
obs_frontend_set_transition_duration(nextTransitionDuration);
|
obs_frontend_set_transition_duration(nextTransitionDuration);
|
||||||
auto t = obs_weak_source_get_source(nextTransition);
|
OBSSourceAutoRelease transition =
|
||||||
obs_frontend_set_current_transition(t);
|
obs_weak_source_get_source(nextTransition);
|
||||||
obs_source_release(t);
|
obs_frontend_set_current_transition(transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switcher->transitionOverrideOverride) {
|
if (ShouldModifyTransitionOverrides()) {
|
||||||
OverwriteTransitionOverride({sceneSwitch.scene, nextTransition,
|
OverwriteTransitionOverride({sceneSwitch.scene, nextTransition,
|
||||||
nextTransitionDuration},
|
nextTransitionDuration},
|
||||||
td);
|
td);
|
||||||
@@ -78,8 +103,8 @@ void SetNextTransition(const SceneSwitchInfo &sceneSwitch,
|
|||||||
|
|
||||||
void OverwriteTransitionOverride(const SceneSwitchInfo &ssi, TransitionData &td)
|
void OverwriteTransitionOverride(const SceneSwitchInfo &ssi, TransitionData &td)
|
||||||
{
|
{
|
||||||
obs_source_t *scene = obs_weak_source_get_source(ssi.scene);
|
OBSSourceAutoRelease scene = obs_weak_source_get_source(ssi.scene);
|
||||||
obs_data_t *data = obs_source_get_private_settings(scene);
|
OBSDataAutoRelease data = obs_source_get_private_settings(scene);
|
||||||
|
|
||||||
td.name = obs_data_get_string(data, "transition");
|
td.name = obs_data_get_string(data, "transition");
|
||||||
td.duration = obs_data_get_int(data, "transition_duration");
|
td.duration = obs_data_get_int(data, "transition_duration");
|
||||||
@@ -88,19 +113,13 @@ void OverwriteTransitionOverride(const SceneSwitchInfo &ssi, TransitionData &td)
|
|||||||
|
|
||||||
obs_data_set_string(data, "transition", name.c_str());
|
obs_data_set_string(data, "transition", name.c_str());
|
||||||
obs_data_set_int(data, "transition_duration", ssi.duration);
|
obs_data_set_int(data, "transition_duration", ssi.duration);
|
||||||
|
|
||||||
obs_data_release(data);
|
|
||||||
obs_source_release(scene);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestoreTransitionOverride(obs_source_t *scene, const TransitionData &td)
|
void RestoreTransitionOverride(obs_source_t *scene, const TransitionData &td)
|
||||||
{
|
{
|
||||||
obs_data_t *data = obs_source_get_private_settings(scene);
|
OBSDataAutoRelease data = obs_source_get_private_settings(scene);
|
||||||
|
|
||||||
obs_data_set_string(data, "transition", td.name.c_str());
|
obs_data_set_string(data, "transition", td.name.c_str());
|
||||||
obs_data_set_int(data, "transition_duration", td.duration);
|
obs_data_set_int(data, "transition_duration", td.duration);
|
||||||
|
|
||||||
obs_data_release(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitchScene(const SceneSwitchInfo &sceneSwitch, bool force)
|
void SwitchScene(const SceneSwitchInfo &sceneSwitch, bool force)
|
||||||
@@ -110,36 +129,67 @@ void SwitchScene(const SceneSwitchInfo &sceneSwitch, bool force)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_source_t *source = obs_weak_source_get_source(sceneSwitch.scene);
|
OBSSourceAutoRelease source =
|
||||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
obs_weak_source_get_source(sceneSwitch.scene);
|
||||||
|
OBSSourceAutoRelease currentSource = obs_frontend_get_current_scene();
|
||||||
|
|
||||||
if (source && (source != currentSource || force)) {
|
if (source && (source != currentSource || force)) {
|
||||||
TransitionData currentTransitionData;
|
TransitionData currentTransitionData;
|
||||||
SetNextTransition(sceneSwitch, currentSource,
|
SetNextTransition(sceneSwitch, currentSource,
|
||||||
currentTransitionData);
|
currentTransitionData);
|
||||||
obs_frontend_set_current_scene(source);
|
obs_frontend_set_current_scene(source);
|
||||||
if (switcher->transitionOverrideOverride) {
|
if (ShouldModifyTransitionOverrides()) {
|
||||||
RestoreTransitionOverride(source,
|
RestoreTransitionOverride(source,
|
||||||
currentTransitionData);
|
currentTransitionData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switcher->verbose) {
|
vblog(LOG_INFO, "switched scene");
|
||||||
blog(LOG_INFO, "switched scene");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switcher->networkConfig.ShouldSendSceneChange()) {
|
if (switcher->networkConfig.ShouldSendSceneChange()) {
|
||||||
switcher->server.sendMessage(sceneSwitch);
|
switcher->server.sendMessage(sceneSwitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
obs_source_release(currentSource);
|
|
||||||
obs_source_release(source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitchPreviewScene(const OBSWeakSource &ws)
|
void SwitchPreviewScene(const OBSWeakSource &ws)
|
||||||
{
|
{
|
||||||
auto source = obs_weak_source_get_source(ws);
|
OBSSourceAutoRelease source = obs_weak_source_get_source(ws);
|
||||||
obs_frontend_set_current_preview_scene(source);
|
obs_frontend_set_current_preview_scene(source);
|
||||||
obs_source_release(source);
|
}
|
||||||
|
|
||||||
|
std::chrono::high_resolution_clock::time_point GetLastTransitionEndTime()
|
||||||
|
{
|
||||||
|
return lastTransitionEndTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::high_resolution_clock::time_point GetLastSceneChangeTime()
|
||||||
|
{
|
||||||
|
return lastSceneChangeTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSWeakSource GetCurrentScene()
|
||||||
|
{
|
||||||
|
return switcher->currentScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSWeakSource GetPreviousScene()
|
||||||
|
{
|
||||||
|
return switcher->previousScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AnySceneTransitionStarted()
|
||||||
|
{
|
||||||
|
return switcher->AnySceneTransitionStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShouldModifyTransitionOverrides()
|
||||||
|
{
|
||||||
|
return switcher->transitionOverrideOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShouldModifyActiveTransition()
|
||||||
|
{
|
||||||
|
return switcher->adjustActiveTransitionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
|
#include <chrono>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -15,12 +16,24 @@ struct TransitionData {
|
|||||||
int duration = 0;
|
int duration = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetNextTransition(const SceneSwitchInfo &ssi, obs_source_t *currentSource,
|
void SwitchScene(const SceneSwitchInfo &, bool force = false);
|
||||||
TransitionData &td);
|
void SwitchPreviewScene(const OBSWeakSource &scene);
|
||||||
void OverwriteTransitionOverride(const SceneSwitchInfo &ssi,
|
|
||||||
TransitionData &td);
|
std::chrono::high_resolution_clock::time_point GetLastTransitionEndTime();
|
||||||
void RestoreTransitionOverride(obs_source_t *scene, const TransitionData &td);
|
std::chrono::high_resolution_clock::time_point GetLastSceneChangeTime();
|
||||||
void SwitchScene(const SceneSwitchInfo &ssi, bool force = false);
|
|
||||||
void SwitchPreviewScene(const OBSWeakSource &ws);
|
OBSWeakSource GetCurrentScene();
|
||||||
|
OBSWeakSource GetPreviousScene();
|
||||||
|
|
||||||
|
bool ShouldModifyTransitionOverrides();
|
||||||
|
bool ShouldModifyActiveTransition();
|
||||||
|
void OverwriteTransitionOverride(const SceneSwitchInfo &, TransitionData &);
|
||||||
|
void RestoreTransitionOverride(obs_source_t *scene, const TransitionData &);
|
||||||
|
|
||||||
|
bool AnySceneTransitionStarted();
|
||||||
|
|
||||||
|
// TODO: Remove at some point
|
||||||
|
void SetNextTransition(const SceneSwitchInfo &, obs_source_t *currentSource,
|
||||||
|
TransitionData &);
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ bool Section::eventFilter(QObject *obj, QEvent *event)
|
|||||||
// filter will cause a segfault for some reason
|
// filter will cause a segfault for some reason
|
||||||
SetupAnimations();
|
SetupAnimations();
|
||||||
}
|
}
|
||||||
|
setMinimumWidth(_content->sizeHint().width());
|
||||||
}
|
}
|
||||||
return QObject::eventFilter(obj, event);
|
return QObject::eventFilter(obj, event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
#include "sync-helper.hpp"
|
|
||||||
|
|
||||||
namespace advss {
|
|
||||||
|
|
||||||
std::mutex *GetSwitcherMutex();
|
|
||||||
std::lock_guard<std::mutex> LockContext()
|
|
||||||
{
|
|
||||||
return std::lock_guard<std::mutex>(*GetSwitcherMutex());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
|
||||||
23
src/utils/sync-helpers.cpp
Normal file
23
src/utils/sync-helpers.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include "sync-helpers.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
std::mutex *GetSwitcherMutex();
|
||||||
|
std::unique_lock<std::mutex> *GetSwitcherLoopLock();
|
||||||
|
|
||||||
|
std::mutex *GetMutex()
|
||||||
|
{
|
||||||
|
return GetSwitcherMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> LockContext()
|
||||||
|
{
|
||||||
|
return std::lock_guard<std::mutex>(*GetSwitcherMutex());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> *GetLoopLock()
|
||||||
|
{
|
||||||
|
return GetSwitcherLoopLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
|
[[nodiscard]] std::mutex *GetMutex();
|
||||||
[[nodiscard]] std::lock_guard<std::mutex> LockContext();
|
[[nodiscard]] std::lock_guard<std::mutex> LockContext();
|
||||||
|
[[nodiscard]] std::unique_lock<std::mutex> *GetLoopLock();
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "macro-segment.hpp"
|
#include "macro-segment.hpp"
|
||||||
#include "plugin-state-helper.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user