Compare commits

...

670 Commits
1.14 ... 1.21.0

Author SHA1 Message Date
WarmUpTill
2fdd39fba5 Use exprtk lib to evaluate mathematical expressions 2023-04-01 05:37:40 -07:00
WarmUpTill
fe1ddc3a94 Fix connection selection being lost after renaming connection 2023-04-01 05:37:40 -07:00
WarmUpTill
cff2d805db Fix variable selection being lost after renaming variable 2023-04-01 05:37:40 -07:00
WarmUpTill
34425d3e47 CI: minor improvements
* Print checksums in log
* Log if tests were skipped
* Switch to gh-release action version 1
2023-03-27 12:37:08 -07:00
WarmUpTill
4ac4f00620 Fix icons not loading on Linux and MacOS 2023-03-25 16:15:55 -07:00
WarmUpTill
e30a4623c5 Fix HideSelectedMacro() hiding the incorrect index 2023-03-25 15:17:19 -07:00
WarmUpTill
e2f4dcaaee Fix warnings 2023-03-25 15:17:19 -07:00
WarmUpTill
ebbf64ddae Add simple tests 2023-03-25 15:17:19 -07:00
WarmUpTill
8b105ad22b Add support for abs, sin, cos, tan, sqrt function in math expression 2023-03-25 15:17:19 -07:00
WarmUpTill
f3416c5b1d Add option to remove Run or Pause button from macro dock 2023-03-25 12:50:49 -07:00
WarmUpTill
e194fc5ee4 Fix crash when deleting multiple macros in combination with a group 2023-03-25 12:50:49 -07:00
WarmUpTill
e465c81bf1 Fix rename via contenxt menu not updating macro name line edit 2023-03-25 12:50:49 -07:00
WarmUpTill
9dce6a99fd Prevent crashes in case obs_module_text() is called during shutdown 2023-03-25 12:50:49 -07:00
WarmUpTill
6f2c53d14e Add option to create docks of macros
These docks allow to control the pause state and manual execution of the
macro actions
2023-03-25 12:50:49 -07:00
WarmUpTill
9044ae4ade Move OBSDock definition 2023-03-25 12:50:49 -07:00
WarmUpTill
0a422174bc Remove unnecessary cast 2023-03-25 12:50:49 -07:00
WarmUpTill
c2020fe77c Fix crash when selecting new audio source in audio condition 2023-03-24 14:39:41 -07:00
WarmUpTill
8beca6fcc7 Do not allow duplication of groups
Functionality has to be implemented first.
Otherwise visual issues might occur when expanding or collapsing the
new copy of the group entry.
2023-03-24 14:39:41 -07:00
WarmUpTill
18769df2ca Fix duplication of macro not copying references to macros or segments 2023-03-22 11:09:41 -07:00
WarmUpTill
2806fd6cdb Add support for variables in various path selections 2023-03-19 03:52:21 -07:00
WarmUpTill
b607940c8c Add variable support to OpenVR condition 2023-03-19 03:52:21 -07:00
WarmUpTill
dff599df4c Add variable support for scene item order condition
Also cleaned up condition type being defined globally
2023-03-19 03:52:21 -07:00
WarmUpTill
b3cd38e019 Add variable support for OBS stats condition
Also move definition of stat type and condition type into
MacroConditionStats
2023-03-19 03:52:21 -07:00
WarmUpTill
61975e1992 Fix macro list layout margins 2023-03-19 03:52:21 -07:00
WarmUpTill
1a8ad69f23 Add variable support for macro condition spinbox controls 2023-03-19 03:52:21 -07:00
WarmUpTill
f21e40151b Add variable support for cursor condition spinbox controls 2023-03-19 03:52:21 -07:00
WarmUpTill
4e58769648 Fix hotkey action not "holding" down keys for the specified duration 2023-03-19 03:52:21 -07:00
WarmUpTill
f9d6001025 Enable use of variables for hotkey action duration selection 2023-03-19 03:52:21 -07:00
WarmUpTill
ae5f5f90ff Add variable support for audio condition spinbox controls 2023-03-19 03:52:21 -07:00
WarmUpTill
89db21d734 Add variable support for video condition spinbox controls 2023-03-19 03:52:21 -07:00
WarmUpTill
0e4b072650 Add varaible support for audio action spinbox controls 2023-03-19 03:52:21 -07:00
WarmUpTill
13b0e00b27 Add variable support to SliderSpinbox 2023-03-19 03:52:21 -07:00
WarmUpTill
bf5d8ca19e Add option to assign value of math expressions to variable 2023-03-19 03:52:21 -07:00
WarmUpTill
4a3339c09c Add math helpers 2023-03-19 03:52:21 -07:00
WarmUpTill
b28c2b28b2 Adjust to Duration rework 2023-03-19 03:52:21 -07:00
WarmUpTill
fcb3e648d2 Enable use of variables in duration selections 2023-03-19 03:52:21 -07:00
WarmUpTill
5d6f08e38f Adjust to refactor of variable string 2023-03-19 03:52:21 -07:00
WarmUpTill
b932af1c97 Move string and number variables to separate files 2023-03-19 03:52:21 -07:00
WarmUpTill
8874eb2b1c Add widgets that allows using both fixed number values or variables 2023-03-19 03:52:21 -07:00
WarmUpTill
dcf9816a72 Add header support to http action 2023-03-19 03:52:21 -07:00
WarmUpTill
c8722c9f62 Add support for using variables in URL field of http action 2023-03-19 03:52:21 -07:00
WarmUpTill
a82a2ccffe Add option to find and replace strings in current value 2023-03-19 03:52:21 -07:00
WarmUpTill
0bf70e443e Move replaceAll() to utility 2023-03-19 03:52:21 -07:00
WarmUpTill
3d6d690583 Add variable support for custom screenshot path 2023-03-19 03:52:21 -07:00
WarmUpTill
783f76d55d Add support for variables in file FileSelection widget 2023-03-19 03:52:21 -07:00
WarmUpTill
1dd46fb777 Add VariableLineEdit helper 2023-03-19 03:52:21 -07:00
WarmUpTill
22bbd3a4ca Extract argument list to generic string list class and widget
* To be used for http header support
* Add variable support
2023-03-19 03:52:21 -07:00
WarmUpTill
3cd4b2251f CI: Remove zip file from windows installer 2023-03-19 03:51:28 -07:00
WarmUpTill
9e4b003608 Use theme based icons for status dock, group, and duration icon 2023-03-19 03:51:28 -07:00
WarmUpTill
e66d0bc6b8 Rework MacroRef
This should resolve issues of macro names / selections not properly
updating after renaming / grouping / un-grouping macros
2023-03-13 11:30:29 -07:00
WarmUpTill
9a4abd78ed Fix warnings 2023-03-13 11:30:29 -07:00
WarmUpTill
826bee8b1e Enable assigning value of scene item transform to variables 2023-03-11 06:06:18 -08:00
WarmUpTill
143020dc27 Prevent accidental duration changes while scrolling through settings
This was especially problematic with the "cooldown" option of the "Match
behavior" settings on the General tab as accidental changes here could
lead to macros not being executed unexpectedly, which is very hard to
diagnose without inspecting logs.
2023-03-10 13:52:32 -08:00
WarmUpTill
be23065988 Move MouseWheelWidgetAdjustmentGuard 2023-03-10 13:52:32 -08:00
WarmUpTill
2cb62eae96 Enable shrinking the status dock to smaller sizes 2023-03-10 13:52:32 -08:00
WarmUpTill
76c411d1e2 Extract argument list to generic string list class and widget
To be used for http header support.
2023-03-04 13:45:32 -08:00
WarmUpTill
16fa91c2a1 Add "Run" condition
Allows to use external programs as conditions
2023-03-04 13:45:32 -08:00
WarmUpTill
b77f8717fe Move process configuration to separate class and widget 2023-03-04 13:45:32 -08:00
WarmUpTill
59ecf43c5f Enable setting a minimum and initial duration 2023-03-04 13:45:32 -08:00
WarmUpTill
1fd8546354 Improve preview frame visibilty of cursor condition
* Add transparent diagonal stripes to frame
* Do not show frame if invalid selection was made
2023-03-04 13:40:14 -08:00
WarmUpTill
7cb95cb3f6 CI: Cache dependency builds for macOS and Windows 2023-02-19 09:48:03 -08:00
WarmUpTill
160d19d6c1 Clean up UI 2023-02-19 09:48:03 -08:00
WarmUpTill
a0550ca141 Add support for TM_SQDIFF_NORMED and TM_CCOEFF_NORMED for pattern match 2023-02-19 09:48:03 -08:00
WarmUpTill
ac68fc016d Adjust area selection layout
Prefix description instead of using tooltip and remove the "x"
2023-02-19 09:48:03 -08:00
WarmUpTill
5170307f72 Add leptonica and tesseract build 2023-02-19 09:48:03 -08:00
WarmUpTill
3af0e51bd2 Add submodules leptonica and tesseract (OCR) 2023-02-19 09:48:03 -08:00
WarmUpTill
f34d1fe081 Enable variable support 2023-02-19 09:48:03 -08:00
WarmUpTill
83c72ebba5 Add OCR support to video condition using tesseract 2023-02-19 09:48:03 -08:00
WarmUpTill
6ca8e6b3ea Fix preview not showing matches
This can happen if a new video condition was created and the condition
type was cahnged to one which supports displaying matches without
changing any parameters.
2023-02-19 09:48:03 -08:00
WarmUpTill
ba24fc2fab Use correct conversion method for object detection 2023-02-19 09:48:03 -08:00
WarmUpTill
7f28b22599 Add macro list context menu options for add, rename, remove 2023-02-19 09:47:46 -08:00
WarmUpTill
4345db0d2e Don't ask for confirmation when deleting empty groups 2023-02-19 09:47:46 -08:00
WarmUpTill
eddc10c3e2 Enable deleting multiple macros at once 2023-02-19 09:47:46 -08:00
WarmUpTill
46eaada0c4 Enable dragging macro segment by header 2023-02-19 09:47:46 -08:00
WarmUpTill
f8b2dea270 Clean up MacroSegmentList 2023-02-19 09:47:46 -08:00
WarmUpTill
90ebf0e0f8 Set default logic type of new non-root conditions to "or" 2023-02-19 09:47:46 -08:00
WarmUpTill
1a819c807e Create new groups at the top most selection index 2023-02-19 09:47:46 -08:00
WarmUpTill
3220809c04 Fix macro list displaying wrong contents after deleting group
This was only a visual issue - the correct macros were deleted in the
backend
2023-02-11 01:45:28 -08:00
WarmUpTill
72d5255c9e Fix typo 2023-02-11 01:45:28 -08:00
WarmUpTill
5995563a80 Add action to open projector 2023-02-04 08:34:20 -08:00
WarmUpTill
347743d93a Also trigger HighlightOnChange() if highlighting actions 2023-02-04 08:29:33 -08:00
WarmUpTill
3c067ce723 Rework preview dialog to use signals / slots to update image data
Previous implementation caused crashes on some setups
2023-02-03 13:36:51 -08:00
WarmUpTill
8dd2170dfa Update locale 2023-01-31 20:23:14 +01:00
WarmUpTill
5f3a3dd5cf Dynamically increase delay between screenshots up to one second
Otherwise users with a very low switcher interval might not be able to
use the preview dialog at all
2023-01-31 11:20:18 -08:00
WarmUpTill
8ad3563963 Always call obs_remove_tick_callback() in destructor
Seems like in some scenarios a screenshot thread would still be active
while the ScreenshotHelper object was deleted
2023-01-31 11:20:18 -08:00
WarmUpTill
492128ef86 Avoid deadlocks while opening settings window and calling frontend API 2023-01-31 11:20:18 -08:00
WarmUpTill
b4936274f2 Synchronize re-ordering and grouping of macros 2023-01-31 11:20:18 -08:00
WarmUpTill
64ccd5ba53 Detect invalid group setups and attempt to clean them up 2023-01-31 11:20:18 -08:00
WarmUpTill
7ae88f7560 Reset invalid transition behaviour settings 2023-01-28 12:42:32 -08:00
WarmUpTill
ae70af26d1 Add option to assign substring based on regex to variable 2023-01-28 12:42:32 -08:00
WarmUpTill
483bdc237c Add option to create partial matching RegexConf 2023-01-28 12:42:32 -08:00
WarmUpTill
2c564b47f4 Add option to assign substring of current value to a variable 2023-01-28 12:42:32 -08:00
WarmUpTill
fc80d0b5f3 Add option to round variable to nearest integer 2023-01-28 12:42:32 -08:00
WarmUpTill
d094c189d3 Handle invalid paths due to scene collection name in settings export 2023-01-28 12:42:32 -08:00
WarmUpTill
40d8819e77 Fix warnings 2023-01-28 12:42:32 -08:00
WarmUpTill
4a3d019f06 Remove workaround to avoid race conditions 2023-01-28 12:42:32 -08:00
WarmUpTill
5366a4a6ed Fix crash on exit if using scene condition
obs_source_get_name() returning nullptr was not handled
2023-01-28 12:42:32 -08:00
WarmUpTill
e8230d8e5b Fix themes displaying list item selections incorrectly
The issue was that the blue selection highlight was not visible and
instead, a grey box was painted around each item.
I am not sure what exactly was causing this.
2023-01-28 12:42:32 -08:00
WarmUpTill
ebdbb9011f Fix scene switch action aborting macro execution
abortMacroWait was not reset in waitForTransitionChangeFixedDuration()
leading to the scene switch action returning false
2023-01-28 12:42:32 -08:00
BlackScreen
e43793354e Update german translation to the latest version 2023-01-27 12:32:03 -08:00
WarmUpTill
438c54599e Reduce time it takes to close preview dialog 2023-01-20 12:30:47 -08:00
WarmUpTill
da42183177 Fix VariableResolvingString returning empty string if no variables exist 2023-01-20 12:30:47 -08:00
WarmUpTill
295fa3f122 Fix crash on import 2023-01-20 12:30:47 -08:00
WarmUpTill
cb87f1cc36 Fix file condition always returning false 2023-01-18 07:49:21 -08:00
WarmUpTill
19eb5074f2 Enable getting variable values from websocket condition 2023-01-17 12:12:44 -08:00
WarmUpTill
828a69bbf7 Save space by reducing size of "current value" text box 2023-01-17 12:12:44 -08:00
WarmUpTill
c01d471b5f Save space by moving settings button to the same layout as stop button 2023-01-15 09:33:46 -08:00
WarmUpTill
8751c0d296 Enable getting variable values from http action 2023-01-15 09:33:46 -08:00
WarmUpTill
334d173dc9 Add PostLoad()
Used to reslove values that only can be resolved after all macros /
macro segments have been set up initally.
2023-01-15 09:33:46 -08:00
WarmUpTill
1c3ff927a5 Enable getting variable values from window condition 2023-01-15 09:33:46 -08:00
WarmUpTill
b12c25fdf4 Enable getting variable values from studio mode condition 2023-01-15 09:33:46 -08:00
WarmUpTill
e9f4ac7ca7 Enable getting variable values from source condition 2023-01-15 09:33:46 -08:00
WarmUpTill
f1cdab80a9 Enable getting variable values from process condition 2023-01-15 09:33:46 -08:00
WarmUpTill
ae6f0bc470 Enable getting variable values from idle condition 2023-01-15 09:33:46 -08:00
WarmUpTill
3d4b69848c Enable getting variable values from filter condition 2023-01-15 09:33:46 -08:00
WarmUpTill
c4c4a27dcb Enable getting variable values from file condition 2023-01-15 09:33:46 -08:00
WarmUpTill
87ed11d3bf Enable getting variable values from date condition 2023-01-15 09:33:46 -08:00
WarmUpTill
23e2fb8d5a Enable getting variable values from cursor condition 2023-01-15 09:33:46 -08:00
WarmUpTill
af5950748d Switch to using RegexConfig for variable comparison check 2023-01-15 09:33:46 -08:00
WarmUpTill
df9dc1e002 Enable getting variable values from scene condition 2023-01-15 09:33:46 -08:00
WarmUpTill
5c7e0f292f Enable getting variable values from audio condition 2023-01-15 09:33:46 -08:00
WarmUpTill
a5f610b7b7 Add options to compare variable values 2023-01-15 09:33:46 -08:00
WarmUpTill
df8e84dd09 Add option to set variable value based on condition or action 2023-01-15 09:33:46 -08:00
WarmUpTill
ee5038106a Add MacroSegmentOrderChanged() signal 2023-01-15 09:33:46 -08:00
WarmUpTill
6617c08b89 Allow choosing highlight color 2023-01-15 09:33:46 -08:00
WarmUpTill
42773790e4 Enable getting varaible values from conditions and actions 2023-01-15 09:33:46 -08:00
WarmUpTill
1fd6f75ee1 Add variable support to video condition 2023-01-15 09:33:46 -08:00
WarmUpTill
8a2ccef8ec Only return source from variable if source is a scene 2023-01-15 09:33:46 -08:00
WarmUpTill
d30f389db7 Add variable support to source condition 2023-01-15 09:33:46 -08:00
WarmUpTill
a2906a534b Add variable support to media condition 2023-01-15 09:33:46 -08:00
WarmUpTill
30294842f2 Add variable support to filter condition 2023-01-15 09:33:46 -08:00
WarmUpTill
eb478d2948 Add variable support to audio condition 2023-01-15 09:33:46 -08:00
WarmUpTill
e4ee55cd3d Add variable support to source action 2023-01-15 09:33:46 -08:00
WarmUpTill
9c4fe38c97 Add variable support for screenshot action 2023-01-15 09:33:46 -08:00
WarmUpTill
81e64382c9 Add variable support to media action 2023-01-15 09:33:46 -08:00
WarmUpTill
b55db1a79a Add variable support to filter action 2023-01-15 09:33:46 -08:00
WarmUpTill
dcdcd23361 Add variable support to audio action 2023-01-15 09:33:46 -08:00
WarmUpTill
3ccc057547 Clean up utilty 2023-01-15 09:33:46 -08:00
WarmUpTill
d04884fe8b Resolve variables in log messages 2023-01-15 09:33:46 -08:00
WarmUpTill
7ae490ca25 Add option to resolve variable values in ToString() 2023-01-15 09:33:46 -08:00
WarmUpTill
cd74534e4c Add source selection helpers 2023-01-15 09:33:46 -08:00
WarmUpTill
e4f9ccec3f Add support for variables in text edit widgets of actions and conditions 2023-01-15 09:33:46 -08:00
WarmUpTill
f106329892 Enable use of multi-line values for variables 2023-01-15 09:33:46 -08:00
WarmUpTill
14f0194372 Add helper classes to support strings containing variables
* VariableResolvingString will accept strings potentially containing
   variables as inputs and will automatically resolve any variables when
   converting to std::string
 * VariableTextEdit is a simple wrapper around ResizingPlainTextEdit to
   enable working with VariableResolvingString
2023-01-15 09:33:46 -08:00
WarmUpTill
632ad5085f Remove duplicate "is" 2023-01-15 09:33:21 -08:00
WarmUpTill
fafaafd578 Fix crash when showing frame for cursor condition
Extreme values for setGeometry() could cause a crash.
Limit frame size to screen union to avoid these crashes.
2023-01-14 05:09:42 -08:00
WarmUpTill
e01f28f2bf Create archives for manual install on MacOS 2023-01-13 15:05:21 -08:00
WarmUpTill
fd4476c0b3 Fix warnings 2023-01-07 11:49:53 -08:00
WarmUpTill
c96c81cf1d Update macro properties dialog
* Visually group settings
 * Hide hotkey settings if no macro or a group is selected
2023-01-07 11:49:53 -08:00
WarmUpTill
3e4293f9b0 Set background of macro action / condition splitter transparent 2023-01-07 11:49:53 -08:00
WarmUpTill
a80af327d7 Enable grouping of macros
Based on OBS's source-tree model/view implementation
2023-01-07 11:49:53 -08:00
WarmUpTill
2116bd7a78 Adjust function signature for macro rename signal 2023-01-07 11:49:53 -08:00
WarmUpTill
11571751b9 Fix crash related to highlights
A crash could occur when macro segments would be deleted while
highlighting of a segment was triggered.
2023-01-07 11:49:53 -08:00
WarmUpTill
f9de63bc88 Rename "count" to "runCount" 2023-01-07 11:49:53 -08:00
WarmUpTill
378bf4dfd6 Add button to open settings window to dock
Also apply current OBS theme to status dock by using "OBSDock" wrapper
class
2023-01-07 11:49:53 -08:00
WarmUpTill
5444d6fd9e Adjust locale 2023-01-02 08:38:25 -08:00
WarmUpTill
15d7e2f972 Add option to check audio balance 2022-12-27 04:02:08 -08:00
WarmUpTill
357d9447f2 Add option to set audio balance 2022-12-27 04:02:08 -08:00
WarmUpTill
6c9d6095c9 Move slider spinbox to core lib 2022-12-27 04:02:08 -08:00
WarmUpTill
bba029e901 Only show audio monitoring options if monitoring is supported by OBS 2022-12-27 04:02:08 -08:00
WarmUpTill
4eafbb8f18 Improve plugin state action
Add options to check for ...
 * Initial plugin start
 * Plugin restart
 * Scene collection change
2022-12-27 03:55:40 -08:00
WarmUpTill
e147402250 Improve random action
* Allow duplicates to enable weighting macro occurance
 * Add option to allow consecutive execution of the same macro
2022-12-23 15:50:17 -08:00
WarmUpTill
e0602f8de2 Rename function and class 2022-12-23 14:10:37 -08:00
WarmUpTill
11f769cf09 Add option to check for change in visibilty 2022-12-23 14:10:37 -08:00
WarmUpTill
4ab88ea218 Add option to not reset seletion on any / all index type change 2022-12-23 14:10:37 -08:00
WarmUpTill
20cbe636df Update locale 2022-12-23 14:09:26 -08:00
WarmUpTill
601b035285 Fall back to OBS-only key press if global key press can't be simulated 2022-12-23 13:18:45 -08:00
WarmUpTill
0027ae9bb8 Reuse last import path 2022-12-23 13:17:58 -08:00
WarmUpTill
ffccc435ca Use unicode as chracter set for lib build 2022-12-23 13:17:58 -08:00
WarmUpTill
8d6b9e37d5 Prioritize manually specified variables 2022-12-23 13:17:58 -08:00
WarmUpTill
70c9a3bd83 Improve video condition and preview dialog
* Fix crashes in preview dialog
 * Pass copy of parameters instead of working directly with condition
   data
 * Set sensible default paths in file selection dialogs
 * Add maximize button to preview dialog
 * Derive preview dialog size from scene switcher settings window
 * Use parameter helper classes
2022-12-23 13:16:22 -08:00
WarmUpTill
b7c6deddde Add helper classes to more easily handle video condition parameters 2022-12-23 13:16:22 -08:00
WarmUpTill
feab4fe744 Add ValidPathOrDesktop() helper function 2022-12-23 13:16:22 -08:00
WarmUpTill
b5ec9e7586 Add const qualifier to various functions 2022-12-23 13:16:22 -08:00
WarmUpTill
a901f59f0f Add option to interact with source settings buttons 2022-12-21 11:52:48 -08:00
WarmUpTill
ea826f1be0 Add option to check for mouse button press
Implemented only for Windows for now.
2022-12-21 11:52:36 -08:00
WarmUpTill
f7afb9c446 Cleanup
* Add include
* Fix typo
2022-12-21 11:52:36 -08:00
WarmUpTill
42198a8773 Update locale 2022-12-18 11:02:09 -08:00
WarmUpTill
368034ad5a Combine hotkeys with the same description into a single hotkey 2022-12-15 11:46:38 -08:00
WarmUpTill
0d1a3e5646 Add missing virtual destructors 2022-12-15 11:46:38 -08:00
WarmUpTill
76be75474b Set default path for import to desktop folder 2022-12-15 11:46:38 -08:00
WarmUpTill
cca32e59c2 Do not allow running paused macros
The old behaviour was not consistent with the other action types.
(E.g. "Sequence" or "Random" ignore paused macros)
It would also only ever execute the first action of the given macro as
afterwards the plugin would realise the macro is paused and abort the
execution.
2022-12-10 13:06:55 -08:00
WarmUpTill
85bb0e62dc Clean up locale 2022-12-10 13:06:19 -08:00
WarmUpTill
0ce9c515af Add option to check / set audio monitoring of sources 2022-12-10 13:06:19 -08:00
WarmUpTill
03854376ef Remove outdated translations for cooldown option 2022-12-10 00:55:28 -08:00
WarmUpTill
88b7603ed1 CI: No longer manually install obs-frontend-api.h for debian build 2022-12-07 11:28:46 -08:00
WarmUpTill
c07ef3c699 Enable detection of user holding down hotkey
Previously only the key down event would trigger the condition
2022-12-05 07:23:13 -08:00
WarmUpTill
f3e5fb59f3 Reset duration modifier timers when stopping the plugin 2022-12-05 07:22:57 -08:00
WarmUpTill
ef0f6839e5 Remove unnecessary duration reset 2022-12-05 07:22:57 -08:00
WarmUpTill
6a488316d8 Update locale (provided by qwe1154323937) 2022-12-04 10:26:03 -08:00
WarmUpTill
8dc434f45e Add option to match scene name to pattern 2022-12-04 09:26:38 -08:00
WarmUpTill
7b65286181 Add error handling for non X11 windowing systems
This will only avoid crashes.
Functionality relying on X11 might not be available in such situations.
(E.g. window title, idle detection, key press simulation)
2022-12-02 20:14:13 -08:00
WarmUpTill
05fce566f4 Use existing Qt functionality to get cursor position
Might resolve issues with cursor position detection on non-X windows on
Linux
2022-12-02 20:14:13 -08:00
WarmUpTill
cc3ce3f0e0 Resolve libXss.so symbols at runtime
This enables running the advanced scene switcher in environments in
which this library is not available with only minimal loss of
functionality (idle detection)
2022-11-28 10:18:18 -08:00
WarmUpTill
20ba02be8d Fix MultiStateCondition not being saved 2022-11-26 08:46:31 -08:00
WarmUpTill
e3d9bf11a4 Fix windows build
The default cmake version used on the Windows runner was unable to
configure OpenCV
2022-11-26 08:46:31 -08:00
WarmUpTill
31511851c9 Add option to match date pattern 2022-11-26 08:46:31 -08:00
WarmUpTill
4f71c55034 Show simple date settings by default 2022-11-26 08:46:31 -08:00
WarmUpTill
46fb63e960 Add option to set working directory for new process 2022-11-26 05:47:24 -08:00
WarmUpTill
034a5255a5 Add option to select folder 2022-11-26 05:47:24 -08:00
WarmUpTill
1be2764d7b Allow setting / checking the audio sync offset of sources 2022-11-26 05:47:13 -08:00
WarmUpTill
34355379ca Clean up Linux platform code
* Fix foreground process check not working for large pids.
* Clean up memory leaks.
* Reduce code duplication.
* Style changes.
2022-11-21 11:15:07 -08:00
WarmUpTill
fd8e3c1e5c Add support for libproc2 (Linux)
Needed for Debian build. (#590)
Also cleaned up platform dependent sections of CMakeLists.txt.
2022-11-21 11:15:07 -08:00
WarmUpTill
7407bc7d82 Add option to toggle visibility 2022-11-20 10:09:56 -08:00
WarmUpTill
d636022576 Add support for additional source groups
Previous implementation missed source types like "scene" and "group"
2022-11-20 10:09:56 -08:00
WarmUpTill
ae9ef2bf3b Fix potential crash for sources of unkown type
This can happen if a source was created but the corresponding
functionality was later removed (e.g. when loading a scene collection
containing a browser source on an OBS build without browser source
support)
2022-11-20 10:09:56 -08:00
WarmUpTill
624ff9f5c6 Fix freeze when changing scene collection 2022-11-16 08:44:15 -08:00
WarmUpTill
9bcced524b Move transition behaviour related settings to General tab 2022-11-09 09:57:55 -08:00
WarmUpTill
3bb2ddfaac Update GitHub Actions for set-output deprecation
GitHub Actions has deprecated set-output. Replace usages of set-output
in stdout with the new syntax to save the output to the new environment
variable.

See:
https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
2022-11-06 09:53:25 -08:00
WarmUpTill
50e26aba72 Improve focus handling
* Display current focus window / process
 * Match against app name instead of window name on MacOS when using
   Process condition
 * Clean up
2022-11-06 09:53:25 -08:00
WarmUpTill
267ab6a7c1 Set Windows installer version to git tag 2022-11-05 12:24:50 -07:00
WarmUpTill
65ea7987c7 Add special handling for the "between" case when ignoring the date
In this case the left time value will be treated as the start of the
time range and the right one as the end.

This now enables specifying ranges that span over the 24h boundary.
E.g. 23:00:00 to 01:00:00.
This would have previously been treated as 01:00:00 to 23:00:00 instead.
2022-11-02 07:57:01 -07:00
WarmUpTill
a6839666ce Fix scene item selection not saving index 2022-11-02 07:56:37 -07:00
WarmUpTill
e5843de4fc Add option to check for average brightness 2022-10-21 13:15:11 -07:00
WarmUpTill
a330378c16 Improve option to check multiple media sources
* Added the option to select current, previous, variables, ...
 * Refresh the source list on scene change
 * General clean up of media condition
2022-10-21 13:15:00 -07:00
WarmUpTill
ddb7888e61 Enable word wrap for "on change" and "parallel" options on macro tab 2022-10-21 13:14:35 -07:00
WarmUpTill
73aef4f0b2 Workaround for macro drag / drop not working as expected
See:
 * QTBUG-106395
 * https://github.com/obsproject/obs-studio/issues/7321
2022-10-13 10:29:39 -07:00
WarmUpTill
67c3b73e10 Fix date condition showing incorrect date
This is only affecting the displayed value when reopening a macro.
The entered values were stored / used correctly.
2022-10-08 15:59:15 -07:00
WarmUpTill
9a3d381cf0 Improve macro examples 2022-10-08 15:59:07 -07:00
WarmUpTill
8b8829f7df Fix scene item selection not returning expected number of items 2022-10-04 23:35:58 -07:00
WarmUpTill
6fff3b54e6 Remove version number from dep package name 2022-10-04 12:01:47 -07:00
WarmUpTill
dd69ca1b35 Add libprocps-dev 2022-10-04 02:59:59 -07:00
WarmUpTill
66ddf3b4ef Rebase volume control widgets to new OBS version 2022-10-04 02:59:59 -07:00
WarmUpTill
c9b5bbfc14 Fix multi state count not being saved 2022-10-04 02:59:59 -07:00
WarmUpTill
3e1e8d01b6 Add option to check for value change 2022-10-04 02:59:59 -07:00
WarmUpTill
c22f40e333 Set SOVERSION to resolve Debian warning 2022-10-04 02:59:36 -07:00
WarmUpTill
b83acaca79 Set rpath for Debian package 2022-10-04 02:59:36 -07:00
Joao Eriberto Mota Filho
53bef18d15 Fix spelling and double word 2022-10-01 10:14:49 -07:00
WarmUpTill
ced1c7605a Add option to set default value on load 2022-10-01 08:24:11 -07:00
WarmUpTill
f78e91eec4 Add compatibility note 2022-10-01 08:24:11 -07:00
WarmUpTill
7fdff72a92 Only show duration selection if dynamic length transition is selected 2022-10-01 08:24:11 -07:00
WarmUpTill
d2d042bae3 Move transition type definition 2022-10-01 08:24:11 -07:00
WarmUpTill
f70ae803a3 Enable creating screenshots of scenes 2022-10-01 01:58:57 -07:00
WarmUpTill
cdefbf383c Add preview scene support 2022-10-01 01:58:57 -07:00
ubuntu
5f8641b18a Adjust cmake to support LIB_OUT_DIR and DATA_OUT_DIR for debian build 2022-10-01 01:52:22 -07:00
ubuntu
d107f653de Fix warnings 2022-10-01 01:52:22 -07:00
WarmUpTill
22f4c11ee3 Hide Scene Groups tab
The tabs functionality is often confused with the sequence tab.
With the introduction of variables / macros this tab is unlikely to find
much use so also hide when legacy-tabs are hidden.
2022-09-29 10:59:08 -07:00
WarmUpTill
7683957267 Add variable support for scene item selection 2022-09-28 02:21:05 -07:00
WarmUpTill
e0d4c7244d Add variable support for scene selection 2022-09-28 02:21:05 -07:00
WarmUpTill
b2ccd30f68 Clean up SceneSelection
* Adjust save and load functions to avoid conflicts with other values
 * Move enum definition
2022-09-28 02:21:05 -07:00
WarmUpTill
1dea2e5f5d Adjust to new Item, ItemSelection, and ItemSettingsDialog classes 2022-09-28 02:21:05 -07:00
WarmUpTill
c95fb6c2ea Add macro action "Variables" 2022-09-28 02:21:05 -07:00
WarmUpTill
d779ced27f Add macro condition "Variable" 2022-09-28 02:21:05 -07:00
WarmUpTill
c84c1638bf Add support for variables 2022-09-28 02:21:05 -07:00
WarmUpTill
3ac4e22600 Add generic item selection and settings configuration widgets
To be used for configuring variables and connections
2022-09-28 02:21:05 -07:00
WarmUpTill
a59d15a77a Add option to disable hotkey registration for new macros 2022-09-28 02:20:22 -07:00
Joao Eriberto Mota Filho
c2edc7c612 Fix spelling errors in final binary 2022-09-27 11:07:31 -07:00
WarmUpTill
77fe75f738 Fix websocket condition layout when enabling regular expressions 2022-09-24 00:45:58 -07:00
WarmUpTill
fdb70a32c6 Fix splitter position save data size growing on scene collection change 2022-09-24 00:45:58 -07:00
WarmUpTill
487db7302e Update OBS version 2022-09-21 10:04:09 -07:00
ubuntu
12a74caf62 Add obs-websocket-api.h to deps/
Using a submodule which is not available as a package on Debian makes it
difficult to package the plugin for Debian.

Instead add the obs-websocket header file directly to the repo.
2022-09-21 10:04:09 -07:00
ubuntu
742996fc83 Remove submodule deps/obs-websocket
Using a submodule which is not available as a package on Debian makes it
difficult to package the plugin for Debian.

Instead add the obs-websocket header file directly to the repo.
2022-09-21 10:04:09 -07:00
WarmUpTill
f5a0b2e91a Reintroduce debian build workflow 2022-09-20 14:01:22 -07:00
WarmUpTill
114ca7b545 Remove unused file 2022-09-20 14:01:22 -07:00
WarmUpTill
a8953f23f4 Add backwards compatability to at least OBS 26.1.2
Required for Debian Stable
2022-09-20 14:01:22 -07:00
WarmUpTill
106be642aa Set CPACK_DEBIAN_PACKAGE_DEPENDS to OBS 28 and correct Qt version 2022-09-19 11:36:28 -07:00
WarmUpTill
4c20ac605d Fix UI not showing correct logic type if removing root condition 2022-09-19 11:36:28 -07:00
WarmUpTill
75cdd3c80d Add option to reduce video matching latency 2022-09-19 11:36:28 -07:00
WarmUpTill
b2585ae176 Fix potential crash in video condition 2022-09-19 11:36:28 -07:00
WarmUpTill
d1e912cb24 Clean up video condition widget
* only show area selection widget if option is enabled
 * fix slight alignment issue
 * move "Show match" button to the bottom of the widget
2022-09-19 11:36:28 -07:00
WarmUpTill
bd5ecb3b3b Add "slideshow" to list of supported media sources 2022-09-17 00:40:10 -07:00
WarmUpTill
1a8a4584c1 Add support for websocket vendor events 2022-09-16 23:55:36 -07:00
WarmUpTill
6d755ad570 Add content / modification date changed as separate options
Previously this would require knowledge of regular expressions to match
any content.
2022-09-15 12:25:37 -07:00
WarmUpTill
99ceb6a42a Style changes
* Move FileType definition
* Change capitalization
2022-09-15 12:25:37 -07:00
WarmUpTill
7ddfdcf5be Switch to RegexConfig 2022-09-15 12:25:37 -07:00
WarmUpTill
a243e026c8 Add RegexConfig class and widget
This allow more control over regular expressions, when they are used
throughout the plugin, as it enables configuration of additional
QRegularExpression::PatternOptions.
2022-09-15 12:25:37 -07:00
WarmUpTill
f40f98c702 Move setButtonIcon to utility 2022-09-15 12:25:37 -07:00
WarmUpTill
d99618d2f6 Enable multiline regex pattern matching 2022-09-15 12:25:37 -07:00
WarmUpTill
a93305e16e Convert line endings to "\n" to allow easier matching 2022-09-15 12:25:37 -07:00
WarmUpTill
fa3ae607b5 Fix missing icon on macro up / down buttons 2022-09-07 12:08:01 -07:00
WarmUpTill
bddbcebece Slight layout adjustments to better support new OBS themes 2022-09-05 12:19:07 -07:00
WarmUpTill
aeaa13955c Hide password 2022-09-05 12:19:07 -07:00
WarmUpTill
f99eb6c3c8 Set sensible default paths when browsing using FileSelection
Previously FileSelection would default to the OBS run dir
2022-09-03 10:31:47 -07:00
WarmUpTill
c16b97e5cd Add option to save screenshot to custom path 2022-09-03 10:31:47 -07:00
WarmUpTill
0d29fb2ee1 Add support to save screenshots to file 2022-09-03 10:31:47 -07:00
WarmUpTill
0169f6c445 Drop 32 bit Windows build 2022-09-02 16:00:18 -07:00
WarmUpTill
886639fe24 Drop version number in name of generated build artifacts 2022-09-02 16:00:18 -07:00
WarmUpTill
7304fa349e Build both portable and non-portable artifacts for Linux 2022-09-02 16:00:18 -07:00
WarmUpTill
7b44c28767 Fix warnings 2022-09-01 13:20:35 -07:00
WarmUpTill
9bed6df2b5 Adjust macro list to new OBS layout changes 2022-09-01 13:20:35 -07:00
WarmUpTill
ad4c41c1dd Replace "\" with "/" 2022-09-01 13:20:35 -07:00
WarmUpTill
9e2ca1529c Save splitter positions on macro tab 2022-08-31 12:12:25 -07:00
WarmUpTill
e62504968c Move comment to correct line 2022-08-31 12:12:25 -07:00
WarmUpTill
97720a798c Waste less space in the UI
* Adjusted layout margins

   Nested layouts lead to lots of wasted space.
 * Removed unnecessary "Close" button

   Closing the settings dialog via "x" or the close button does not make
   a difference so it can savely be removed.
2022-08-31 12:12:25 -07:00
WarmUpTill
636630fdf3 Add splitter between macro list and macro edit area
This will make editing macros easier on smaller window sizes as the list
or edit area can be resized to the users needs
2022-08-31 12:12:25 -07:00
WarmUpTill
602622c841 Remove paths-ignore block
Didn't serve any purpose and is not allowed in combination with 'paths'
2022-08-31 07:58:24 -07:00
WarmUpTill
c3aa421bc5 Add option to split recording 2022-08-31 07:58:24 -07:00
WarmUpTill
c392004edf Remove duplicate line 2022-08-27 15:08:19 -07:00
WarmUpTill
9e4893abc3 Only run locale checks when locale was changed 2022-08-27 15:08:19 -07:00
WarmUpTill
54f940be0d Revert to old AppId for Windows installer and set new UUIDs for MacOS 2022-08-27 15:08:19 -07:00
WarmUpTill
046de4118f Rework curl helpers 2022-08-25 11:26:31 -07:00
WarmUpTill
c9177c4429 Add Http action 2022-08-25 11:26:31 -07:00
WarmUpTill
9704d5f1f4 Add AnimationFinished signal 2022-08-24 12:53:25 -07:00
WarmUpTill
5ce177bcd3 Add websocket files and dependencies 2022-08-24 12:53:25 -07:00
WarmUpTill
a7b6a4a67c Add websocket locale 2022-08-24 12:53:25 -07:00
WarmUpTill
1978b8f1a1 Save and load websocket connections 2022-08-24 12:53:25 -07:00
WarmUpTill
59cc37c90a Add websocket condition 2022-08-24 12:53:25 -07:00
WarmUpTill
866c49bffd Add websocket action 2022-08-24 12:53:25 -07:00
WarmUpTill
c9370c8929 Add websocket helper functions to receive and send messages 2022-08-24 12:53:25 -07:00
WarmUpTill
e97f41a356 Add connection-manager
Used to add, remove, and modify websocket connections
2022-08-24 12:53:25 -07:00
WarmUpTill
6c7ba4225b Add obs-websocket dependency 2022-08-24 12:53:25 -07:00
WarmUpTill
b694598d16 Disable the "Directory already exists" warning in Windows installer 2022-08-23 13:53:13 -07:00
WarmUpTill
954b634aa5 Update actions/cache from v2.1.7 to v3 2022-08-23 13:53:13 -07:00
WarmUpTill
c9820e77d8 Add option to check states of multiple macros at the same time 2022-08-23 11:31:48 -07:00
WarmUpTill
a268f98b73 Rework to use MacroList widget 2022-08-23 11:31:48 -07:00
WarmUpTill
700e75a2b5 Fix potential crashes when removing macros 2022-08-23 11:31:48 -07:00
WarmUpTill
19e79aff50 Add macro list widget 2022-08-23 11:31:48 -07:00
WarmUpTill
c8f684ce9f Add helper to get internal ref name 2022-08-23 11:31:48 -07:00
WarmUpTill
1027dda6f6 Enable inheriting from both MultiMacroRef* and MacroRef*
Initially to be used only for the "Macro" condition type
2022-08-23 11:31:48 -07:00
WarmUpTill
6f7bcc34af Add helper functions to save / load list of macro refs 2022-08-23 11:31:48 -07:00
WarmUpTill
face0f7f3c Add MultiMacroRefCondtition 2022-08-23 11:31:48 -07:00
WarmUpTill
7480e793b8 Adjust General tab layout for new Yami theme of OBS 28 2022-08-23 10:58:57 -07:00
WarmUpTill
bcdcaed136 Format example 2022-08-17 11:16:22 -07:00
WarmUpTill
85e715dc75 Update .gitignore 2022-08-17 11:08:53 -07:00
WarmUpTill
9e8e1a6e4d Set LINUX_PORTABLE to OFF to create valid .deb file 2022-08-17 11:08:53 -07:00
WarmUpTill
7fbfb7806b Add link to wiki and OBS forums 2022-08-17 11:08:53 -07:00
WarmUpTill
1556334c0e Update README.md and BUILDING.md
* Add "Contributing" section
 * Update build instructions
2022-08-17 11:08:53 -07:00
WarmUpTill
53a5fa6ff4 Restructure "src/" folder
Moving files from the "src/" folder into "src/legacy", "src/macro-core",
and "src/utils" was necessary as it was becoming a bit too cluttered.
2022-08-17 11:08:53 -07:00
WarmUpTill
5ae9e18044 Rework plugin to allow split into module and library part
This is mostly intended to allow easier bundling for MacOS but might
prove to be useful for other areas as well.
2022-08-17 11:08:53 -07:00
WarmUpTill
aef29d7d82 Update plugin build scripts
Based on OBS plugin template build scripts with some minor adjustments:

 * Adjust format check scripts to exclude ./deps folder
 * Adjust release scripts to only draft releases
 * Always build installers
 * Always upload build artefacts
 * Build opencv for Mac and Windows releases
2022-08-17 11:08:53 -07:00
WarmUpTill
f000758820 Add Qt version checks to support Qt5 2022-08-17 11:08:53 -07:00
WarmUpTill
786c9592a1 Fix depecrations and clean up backwards compatibility checks 2022-08-17 11:08:53 -07:00
WarmUpTill
5cb50821e0 Rewrite CMakeLists.txt to support new build system based on obs-plugintemplate 2022-08-17 11:08:53 -07:00
WarmUpTill
bcdfe79831 Add action to refresh sources 2022-08-03 11:35:06 -07:00
WarmUpTill
ec93babed6 Fix duration modifier of media conditions not saving 2022-08-03 11:34:25 -07:00
WarmUpTill
e075dcd4be Cleanup
Rename locale entry to match naming scheme
2022-06-28 11:25:50 -07:00
WarmUpTill
4113f94528 Add condition to check current profile 2022-06-28 11:25:50 -07:00
WarmUpTill
db3affc43d Set screenshot file extension to *.png
Files without any file extension are not properly loaded as an QImage and
thus pattern matching might not work
2022-06-28 11:25:38 -07:00
EliasDIPA
e11d882e87 Spanish translation of version 1.17.7 2022-06-28 11:24:57 -07:00
WarmUpTill
925729e6b8 Fix hotkeys not being registered for new macros 2022-06-22 14:13:34 -07:00
WarmUpTill
4d2c3e0f80 Copy settings of selected transition for show / hide transition 2022-06-13 11:40:12 -07:00
WarmUpTill
1665841589 Fix freeze on setting hide/show transition
A "private" copy of the transition source has to be used for show and
hide transitions as otherwise this can lead to an OBS freeze the next
time the show / hide transition is used
2022-06-13 11:40:12 -07:00
WarmUpTill
e89343b03e Fix crash when deleting last macro
A crash could occur if the last macro was deleted and the highlighting
of macro segments was enabled due to the macro segments already being
deleted while the widgets representing these segments were not
2022-06-12 06:45:11 -07:00
WarmUpTill
a9c79b02ff Fix UI elements shifting slightly
Content margins of scene item selection widget would cause Transition
action to shift slightly whenever the widget's visibility changed
2022-06-12 04:50:13 -07:00
WarmUpTill
c6541825f8 Add option to select before and after for time of simple date check 2022-06-12 03:46:18 -07:00
WarmUpTill
003a1aa696 Remove delay before saving replay buffer 2022-06-12 03:46:04 -07:00
WarmUpTill
20767630c0 Add option to set show, hide, and override transitions (#471) 2022-06-12 12:45:45 +02:00
WarmUpTill
70fb972f84 Add option to ignore time component in simple check 2022-05-18 04:55:55 -07:00
WarmUpTill
4d65956f25 Fix MacOS memory leak 2022-05-18 04:55:28 -07:00
WarmUpTill
a2e4580970 Fix media and audio condition unexpectedly returning true after unpause 2022-05-12 11:42:39 -07:00
WarmUpTill
8da1e3ad40 Rework time restriction to support "within" duration modifier
Also renamed duration constraint to duration modifier
2022-05-12 11:42:39 -07:00
WarmUpTill
92b6a057f6 Restructure files
- Move condition and action related parts into separate files
 - Move duration constraint to macro condition
 - Move duration constraint widget to macro condition edit
 - Adjust includes
2022-05-12 11:42:39 -07:00
WarmUpTill
70a3ae0245 Fix waiting for transition to complete with fixed duration transitions 2022-05-12 11:42:39 -07:00
WarmUpTill
8cc7b65436 Do not allow duplicates in condtion and action type selection 2022-05-12 11:42:39 -07:00
WarmUpTill
fd18e64e19 Add studio mode action (previously scene swap and preview scene action)
The option to enable and disable studio mode is new
2022-05-12 11:42:39 -07:00
WarmUpTill
e4526c4e81 Enable option to check previous scene during active transition 2022-05-07 16:55:36 -07:00
WarmUpTill
d6ef69a3d4 Add spinbox control to threshold slider 2022-05-06 11:37:43 -07:00
WarmUpTill
b5eb0b3f3e Add option to disable registering of pause control hotkeys 2022-05-06 11:37:28 -07:00
WarmUpTill
22a361f977 Fix scene group not being random 2022-05-04 06:20:10 -07:00
WarmUpTill
a0db023aae cleanup es-ES.ini 2022-05-04 02:28:10 -07:00
EliasDIPA
dc8a60a5e5 Traduccion al Español añadida 2022-05-04 02:18:32 -07:00
WarmUpTill
d47b878b56 Display next match time if repeat is selected 2022-04-24 09:45:22 -07:00
WarmUpTill
9105087036 Show update on repeat option only if repeat is selected 2022-04-24 09:45:22 -07:00
WarmUpTill
e26f41a1a8 Add option to preserve original date in combination with repeat option 2022-04-24 09:45:22 -07:00
WarmUpTill
ff513d8664 Fix cursor condition frame blocking mouse inputs 2022-04-24 06:28:28 -07:00
WarmUpTill
07f11c63f0 Don't allow manipulating area selection when highlighting match 2022-04-02 12:51:57 -07:00
WarmUpTill
6685a1ccaa Do not spam first time setup message 2022-04-02 09:14:26 -07:00
WarmUpTill
ecee919e0b Hide legacy tabs by default and adjust default tab order 2022-04-02 09:14:26 -07:00
WarmUpTill
e8c1b673c0 Allow accessing macro properties even without selecting any macro 2022-04-02 09:14:26 -07:00
WarmUpTill
1a8b185f7d Make date "At"-type check more robust
Previously the "At" check could skip the desired time window if e.g another
macro was performing a long wait wait action or condition was taking
a long time to check.
The date condition will now take into consideration when the last time
was the condition checked a date instead of simply applying a fixed
window of "switcher->interval".
2022-04-02 09:13:01 -07:00
WarmUpTill
eb8a9df627 Create cropped screenshot depending on selected area 2022-04-02 00:29:29 -07:00
WarmUpTill
123d308a0d Add option to select OSB' main video output 2022-03-29 10:02:44 -07:00
WarmUpTill
102b93d3b5 Fix deadlock when changing condition / action type
The video preview dialogs could not exit as the destructor was holding
the main mutex while joining the preview thread, which in turn was
waiting to get the access to the mutex to exit its main loop
2022-03-29 10:02:44 -07:00
WarmUpTill
eeceb7cbd9 Fix random action not being random 2022-03-27 11:45:50 -07:00
WarmUpTill
92add4f090 Update .gitignore 2022-03-26 15:55:48 -07:00
ubuntu
3ed7727c85 Fix warnings 2022-03-26 15:40:19 -07:00
ubuntu
a922d6a73d Add missing reordering of action widgets 2022-03-26 15:40:19 -07:00
WarmUpTill
9ba8a02a11 Add hotkey to move current macro segment selection up / down 2022-03-26 10:05:50 -07:00
WarmUpTill
e61539a878 Reuse macro segment widgets if possible 2022-03-26 10:05:50 -07:00
WarmUpTill
5a78c99703 Ignore delete hotkey if macro tab is not in focus 2022-03-26 10:05:50 -07:00
WarmUpTill
dbbcf04b8a Auto scroll during drag if touching top or bottom areas of list widget 2022-03-26 10:05:50 -07:00
WarmUpTill
6a8066795b Improve drag & drop behaviour of macro segments
- Depending on the drop position you can either drop before or after a
  widget
- Added a visual indicator where the macro segment will be dropped
2022-03-26 10:05:50 -07:00
WarmUpTill
e0763a4957 Improve performance for drag and drop
- Changing the style sheets for the selection frame dynamically considerably
  slowed down the handling of the mouse events.
  Instead two separate widgets with fixed style sheets are now used.
- Recreating the macro segments after dropping a widget took too much
  time leading to unresponsive drop operations
2022-03-26 10:05:50 -07:00
WarmUpTill
1ab9a38914 Selection idx handling was moved to macro segment list widget 2022-03-26 10:05:50 -07:00
WarmUpTill
a6ca266dab Fix potential crash / memory leak when clearing layouts 2022-03-26 10:05:50 -07:00
WarmUpTill
0a8f279e97 Rework macro segment list widget
- Allows drag and drop reorder
- Handles selection change
- Handles highlight
- Handles changing collapse change
- Handles add, insert, remove, and clear functionality
2022-03-26 10:05:50 -07:00
WarmUpTill
1b63978acb Add media seek action 2022-03-26 10:05:40 -07:00
WarmUpTill
8487ef4716 clean up locale 2022-03-26 10:05:40 -07:00
WarmUpTill
ddc2ee4fa5 Remove "Played to end" and replace it with "Playlist end" state
"Ended" can now be used to also detect the end of individual playlist
items.
2022-03-26 10:05:40 -07:00
WarmUpTill
11fede6cc3 Fix start streaming action only working every second attempt 2022-03-18 13:08:31 -07:00
WarmUpTill
1d45072c58 Recurse in setLayoutVisible() 2022-03-15 10:58:29 -07:00
WarmUpTill
d450210d39 Add option to visually select area to check 2022-03-15 10:58:29 -07:00
WarmUpTill
5462334693 Add option to perform video check only on parts of the video source
This will significantly reduce CPU usage if the video source larger than
the selected area and make it easier to only check parts of a video
source output image.
2022-03-15 10:58:29 -07:00
WarmUpTill
293d3dd16c Work around macro handle buttons not being redrawn
Not sure what exaclty causes this - investigating it further is not
worth the time at the moment
2022-03-12 06:35:59 -08:00
WarmUpTill
71b6ae4d78 Add additional settings dialog to macro tab
This settings dialog currently contains debug features to highlight
recently executed macros, actions and conditions.
2022-03-12 06:35:59 -08:00
WarmUpTill
69d6d63dfd Increase macroSplitter size by moving condition controls into handle 2022-03-12 06:35:59 -08:00
WarmUpTill
d693dbc844 Add highlighting of onChagne if actions were prevented recently 2022-03-12 06:35:59 -08:00
WarmUpTill
428e114a0a Highlight recently executed action and true conditions 2022-03-12 06:35:59 -08:00
WarmUpTill
001d8b4714 Move hightlight and update of paused state into MacroListEntryWidget 2022-03-12 06:35:59 -08:00
WarmUpTill
37734445e7 CI: Add automated check for invalid locale files
Also clean up issues found in the existing locale files
2022-03-05 17:09:58 -08:00
WarmUpTill
d1fe5beaeb Fix fade animation triggering unexpectedly for controls 2022-03-05 17:09:58 -08:00
WarmUpTill
036afb4a4f Add option to abort active fade when starting new fade 2022-03-05 15:38:46 -08:00
WarmUpTill
c87589d534 reduce duplicate code 2022-03-05 15:38:46 -08:00
WarmUpTill
1df513585d Add option to specifiy rate of change instead of duration for audio fade 2022-03-05 15:38:46 -08:00
WarmUpTill
e1bacd75b6 Move audio fade threads to generic _helperThreads of macro
This will allow waiting for and stopping audio fades when calling Stop()
for a particular macro
2022-03-05 15:38:46 -08:00
WarmUpTill
7095f4668c Rework wait action to support being interrupted by calling Stop() 2022-03-05 15:38:46 -08:00
WarmUpTill
8131ad3c24 Block when calling Stop() until macro is stopped 2022-03-05 15:38:46 -08:00
WarmUpTill
ac5b2c3f9e Rework handling of fade threads
Previous implementation did not allow ongoing fades to be stopped.
New implementations allows waiting for fade to complete.
2022-03-05 15:38:46 -08:00
WarmUpTill
a86f7d0fd4 Set background of openVR controls transparent 2022-03-05 07:40:14 -08:00
WarmUpTill
34736ffbda Update zh-CN locale (by qwe1154323937) 2022-03-05 01:19:48 -08:00
WarmUpTill
da28fea2e0 Fix potential freeze or crash with "Show match" dialog
This is a workaround to handle random segfaults triggered when using ...
QMetaObject::invokeMethod(this, "RedrawImage", -Qt::QueuedConnection,
		   Q_ARG(QImage, image));
... from within CheckForMatchLoop().
Even using BlockingQueuedConnection causes deadlocks.
2022-02-26 16:08:55 -08:00
WarmUpTill
b6b0531dbc Fix size ofi new collapsed segments containing ResizingPlainTextEdit 2022-02-26 16:08:55 -08:00
WarmUpTill
2de0a94756 Fix highlight animations never stopping 2022-02-26 16:08:55 -08:00
WarmUpTill
d018740442 Fix potential deadlock in ShowMatchDialog 2022-02-26 16:08:55 -08:00
WarmUpTill
d89f8a7972 Clear pixmap if screenshot creation failed 2022-02-26 16:08:55 -08:00
WarmUpTill
f7a2aa09cb Fix potential crash 2022-02-26 16:08:55 -08:00
WarmUpTill
04825e4b88 Fix warning 2022-02-26 08:23:10 -08:00
WarmUpTill
1cfd981245 Reduce text edit areas size of file, filter, source, transform segments 2022-02-26 08:23:10 -08:00
WarmUpTill
6fb8297275 Use QPropertyAnimation::DeleteWhenStopped PulseWidget() when once is set
Also fixes potential crash when waiting for single shot timer when
looping and widget and animations are deleted in the meantime
2022-02-26 08:23:10 -08:00
WarmUpTill
4253c99cf2 Fade out segment controls which will likely not be needed
This was done to give some hints which controls will likely need to be
used to avoid mistakenly clicking on the action controls when editing
conditions.
2022-02-26 08:23:10 -08:00
WarmUpTill
ae13a68cae Double click on list item in run and sequence action to edit 2022-02-26 08:23:10 -08:00
WarmUpTill
4e5aae7e5f Add 'OBS stats' condition type (#414)
It supports various different types of stats:
* fps
* cpu
* ram
* frame time
* skipped frames
* missed frames
* dropped frames
* data size sent
* bitrate
2022-02-26 11:37:54 +01:00
WarmUpTill
88dff37776 Allow drag and drop reordering of macros 2022-02-24 14:15:23 -08:00
WarmUpTill
83df1ab658 Skip collapse animation if section is already in the desired state 2022-02-24 14:15:23 -08:00
WarmUpTill
5298b14803 Use name of macro to be copied in addNewMacro() dialog 2022-02-24 14:15:23 -08:00
WarmUpTill
eeedf11c6a Add hotkey to delete macro segments 2022-02-24 14:15:23 -08:00
WarmUpTill
89efb6d1c8 Allow selecting either an action or condition but not both 2022-02-24 14:15:23 -08:00
WarmUpTill
1054bce4a7 Remove slight movement of macro segment when (de-)selecting them 2022-02-24 14:15:23 -08:00
WarmUpTill
d3cbddf0a4 Allow selecting scene groups in preview scene change action 2022-02-24 14:15:05 -08:00
WarmUpTill
a91fed1583 Simplify waitForTransitionChange()
Will now also work if the target scene is the already currently active
scene.
2022-02-24 14:15:05 -08:00
WarmUpTill
c94a791d19 Allow switching to already active scene if in studio mode
Preview and program scene can differ in regards to the active scene
items.
Thus it can make sense to switch to the already active scene.
2022-02-24 14:15:05 -08:00
WarmUpTill
02e380a9f2 Allow selecting current and previous scene in preview scene action 2022-02-24 14:15:05 -08:00
WarmUpTill
4349a98614 CI: Switch to Visual Studio 17 2022 2022-02-22 11:40:33 -08:00
WarmUpTill
f294283306 CI: Bump OBS version 2022-02-21 12:09:23 -08:00
WarmUpTill
cc9d5897da Add deprecation warning for legacy tabs 2022-02-20 04:50:12 -08:00
WarmUpTill
8e3eb8519b Fix potential crashes when adding or removing macro segments
I wrongly assumed that std::deque would guarantee that pointers to
elements in deque would not be invalidated by insert() or erase() but
this is not the case it seems.

""
An erase in the middle of the deque invalidates all the iterators and
references to elements of the deque. An erase at either end of the deque
invalidates only the iterators and the references to the erased
elements.
""

I guess I got lucky noone ran into these sorts of crashes for now?
2022-02-20 04:50:12 -08:00
WarmUpTill
354ef56070 Do not select any item if pressing add without any active selection 2022-02-20 04:50:12 -08:00
WarmUpTill
352dac5e32 Add MacroSegmentList to allow deselecting items
Previously once a macro segement was selected you could only deselect it
by clicking on different macro segment, thus never allowing the user to
deselect all macro segments
2022-02-20 04:50:12 -08:00
WarmUpTill
584fe4b3b6 Copy logic type when adding conditions 2022-02-20 04:50:12 -08:00
WarmUpTill
bdd489aea5 Fix crashes related to PulseWidget()
* Fix crash if widget was deleted during animation
* Fix crash if multiple animations were started at the same time
2022-02-20 04:50:12 -08:00
WarmUpTill
0b2e725471 Do not run collapse animation when calling SetContent() 2022-02-20 04:50:12 -08:00
WarmUpTill
45e8378021 Remove old macro segment controls 2022-02-20 04:50:12 -08:00
WarmUpTill
955f308c59 Add list-like controls to macro actions and conditions 2022-02-20 04:50:12 -08:00
WarmUpTill
2c25bb4dd4 Make slider background transparent
Sliders, e.g. in the video condition, would otherwise block parts of the
highlight frame around macro segments.
2022-02-18 13:40:33 -08:00
WarmUpTill
d8dcd91ed9 Split video condition into multiple files 2022-02-18 13:40:33 -08:00
WarmUpTill
03900e936b Rename class AdvSSScreenshotObj to ScreenshotHelper 2022-02-18 13:40:33 -08:00
WarmUpTill
6d2360eb87 Clean up AdvSSScreenshotObj usage in video condition 2022-02-18 13:40:33 -08:00
WarmUpTill
ab4a70a758 Refresh contents of "Show match" dialog every second 2022-02-18 13:40:33 -08:00
WarmUpTill
b48276bd5c Add option to check for OBS shutdown to MacroConditionPluginState 2022-02-18 13:35:15 -08:00
WarmUpTill
34167366db Add day of week based check to date condition 2022-02-12 17:57:35 -08:00
WarmUpTill
bfa8f4d9d5 Visually clean up date condition
- add "and" separator if "between" check is chosen
- split dateTimeEdit into a dateEdit and a timeEdit to make editing
  easier
- move ignore* checkboxes in front of respective edit widgets to make
  their intention more clear and add tooltips to further clarify their
  use
2022-02-12 17:57:35 -08:00
WarmUpTill
f8e3a3e275 CI: Fix MacOS build
Packages version bump
2022-02-10 12:19:56 -08:00
WarmUpTill
1328896801 Reopen last opened tab in current session
Will reset to General tab on startup / scene collection change
2022-02-10 11:29:44 -08:00
WarmUpTill
0effbd8ace Add context menu entry for expanding and collapsing edit areas 2022-02-04 11:38:42 -08:00
WarmUpTill
08a8157f3a Reduce spacing between macro segments 2022-02-04 11:38:42 -08:00
WarmUpTill
262bb3f1ee Keep size of individual macro sgements consistent
Previously the segments would expand if there was still room in the
condition and action area.
2022-02-04 11:38:42 -08:00
WarmUpTill
415f63c46c Fix warnings generated about missing icons 2022-02-04 11:38:42 -08:00
WarmUpTill
0771f939a6 Restore original color after PulseWidget() completes 2022-02-04 11:38:42 -08:00
WarmUpTill
a81ee605d6 Rename function 2022-02-04 11:38:42 -08:00
WarmUpTill
1e7726bcfc Add option to highlight recently executed macros on the Macro tab 2022-02-04 11:38:42 -08:00
WarmUpTill
dc698e426d Add MacroListEntryWidget
To be used for macro tab's macro list as regular QListWidgetItem are too
limited
2022-02-04 11:38:42 -08:00
WarmUpTill
a4f66dbbcd Fix warnings 2022-02-04 11:38:42 -08:00
WarmUpTill
1516b9a939 Add option to hide legacy tabs 2022-02-04 11:38:42 -08:00
WarmUpTill
e13f20c860 Adding frame highlighting individual macro segments 2022-02-04 11:38:42 -08:00
WarmUpTill
727992f1d0 Clean up stylesheet usage 2022-02-04 11:38:42 -08:00
WarmUpTill
4e75a15118 Clean up unnecessary variable 2022-02-04 11:38:42 -08:00
WarmUpTill
48368f4bd6 Move vertical / horizontal control handling to macro segment 2022-02-04 11:38:42 -08:00
WarmUpTill
61d9031933 Add option to toggle between vertical and horizontal macro controls 2022-02-04 11:38:42 -08:00
WarmUpTill
487c735e13 Delay show and hide of macro controls 2022-02-04 11:38:42 -08:00
WarmUpTill
7a34c334bd Highlight macro segments new position when moving it up or down 2022-02-04 11:38:42 -08:00
WarmUpTill
4988683e22 Resize conditions and actions areas on expand / collapse all 2022-02-04 11:38:42 -08:00
WarmUpTill
cb681643c8 Fix scene switch action blocking unexpectedly
If "wait for transition" was checked and no valid scene was selected the
waitForTransitionChange() function will wait for its maximum allowed
duration as switcher->currentScene will never be null.
2022-02-02 09:55:35 -08:00
WarmUpTill
d79e10ec97 Add tr-TR.ini locale (Provided by dargat) 2022-01-30 19:15:49 +01:00
WarmUpTill
af188b55df Move plugins to separate folder (#400) 2022-01-29 15:47:16 +01:00
WarmUpTill
f287a1041d Add option to also check for configured volume level 2022-01-25 12:46:16 -08:00
WarmUpTill
fda9b1c3ea Fix dock location and size not saving correctly
OBS will handle the docking position / window size and position as long
as an object name is set
2022-01-25 10:33:41 -08:00
WarmUpTill
9eb7f58525 CI: Save debian build result 2022-01-25 10:33:02 -08:00
WarmUpTill
abd6fd6b7e Add sequence action (#395) 2022-01-22 18:07:26 +01:00
WarmUpTill
2909b1300e Fix empty statusControl of general tab blocking mouse input 2022-01-22 06:14:03 -08:00
WarmUpTill
d1331a60b9 Fix crash on exit caused by status dock 2022-01-22 06:14:03 -08:00
WarmUpTill
d5fc3befb8 Remove QtConcurrent dependency 2022-01-22 06:14:03 -08:00
WarmUpTill
80f9c79907 CI: Bump windows QT version to 5.15.2 2022-01-22 06:14:03 -08:00
WarmUpTill
e4bd1fc180 Reduce amount of signals emitted on repopulate 2022-01-22 06:14:03 -08:00
WarmUpTill
59c87ca027 Emphasize that a duration of 0s means using default duration 2022-01-21 09:51:00 -08:00
WarmUpTill
eda161de39 Sort condition and action selection alphabetically 2022-01-21 09:51:00 -08:00
WarmUpTill
6033426a6e Enable word wrap for macro priority warning 2022-01-21 09:51:00 -08:00
WarmUpTill
caea16c6ad Hide selected macro for run or stop action
Running a macro from within itself is not supported and stopping it from
withint itself does not seem useful either.
2022-01-21 09:51:00 -08:00
WarmUpTill
e3a39a5df7 Add label clarifying the condition's intent 2022-01-21 09:51:00 -08:00
WarmUpTill
38b7e08711 Add macro action to stop other macros 2022-01-21 09:51:00 -08:00
WarmUpTill
7349841758 Fix unexpectedly returning true for hotkey condition
The condition would return true after unpause, if a configured hotkey was pressed
during the time the macro was paused.
2022-01-21 09:50:19 -08:00
WarmUpTill
5d58269b02 Add function to access parent macro from condition or action 2022-01-21 09:50:19 -08:00
WarmUpTill
8a4aef0f50 Update bug_report.md 2022-01-19 20:22:26 +01:00
WarmUpTill
4b877d865c Add issue templates 2022-01-16 19:43:51 +01:00
WarmUpTill
82503286ea Use the same widget for main settings window and status dock 2022-01-14 09:11:36 -08:00
WarmUpTill
16ee789c82 Add option to perform macro actions only on condition change 2022-01-06 08:41:18 -08:00
WarmUpTill
d040a01016 Reintroduce checkbox to change current scene check transition behaviour 2022-01-06 08:41:18 -08:00
WarmUpTill
eb952afe58 Enable time constraints for transition condition 2022-01-06 08:41:18 -08:00
WarmUpTill
34cff925fc CI: No longer query for 32 bit OBS install path 2022-01-05 20:21:03 +01:00
WarmUpTill
016d963598 Fix volume not changing when selecting fade with a duration of 0s 2022-01-04 19:32:53 -08:00
WarmUpTill
d31ae77176 Run macros even if they are paused when pressing "Run Macro" 2022-01-04 19:32:53 -08:00
WarmUpTill
2c1b97e5cd Abort macro early if it was paused 2022-01-05 03:39:37 +01:00
WarmUpTill
c498d1509a Adjust locale 2022-01-05 02:54:39 +01:00
WarmUpTill
2d61189655 Display message on first boot 2022-01-04 17:16:38 -08:00
WarmUpTill
82c20b871b Don't ask to backup settings if there is nothing to backup 2022-01-04 17:16:38 -08:00
WarmUpTill
bd52ef8e84 Don't abort build if OpenVR cannot be found 2022-01-04 15:50:26 -08:00
WarmUpTill
59e1ddd31e Add openvr condition 2022-01-04 15:50:26 -08:00
WarmUpTill
a320d78a08 Separate OpenCV dependency into its own lib
This should avoid issues of the whole plugin not loading if OpenCV is
not available.
This approach should also work for possible future external
dependencies.
2022-01-03 18:22:02 -08:00
WarmUpTill
ce5730428c Remove unnecessary uses of UNUSED_PARAMETER macro 2022-01-03 13:48:21 -08:00
WarmUpTill
f7b9795014 Add option to check if source is muted 2022-01-03 13:48:21 -08:00
WarmUpTill
3417fc5407 Add status dock 2022-01-03 11:32:22 -08:00
WarmUpTill
2649efe8b3 Adjust to SceneItemSelection and SceneItemSelectionWidget 2022-01-03 08:52:32 -08:00
WarmUpTill
3af5897427 Rename function 2022-01-03 08:52:32 -08:00
WarmUpTill
92877a6b30 Add SceneItemSelection and SceneItemSelectionWidget
Allows selecting individual scene items if there are duplicate entries
for the same source.
2022-01-03 08:52:32 -08:00
WarmUpTill
fbdaffcbf6 Clean up formatJsonString() 2022-01-03 08:52:32 -08:00
WarmUpTill
ba111c6caa Add action to import settings from file 2022-01-01 18:26:40 -08:00
WarmUpTill
5c8760ac0a Add action to switch scene collection 2022-01-01 18:26:40 -08:00
WarmUpTill
e0cca2a0d4 Add action to switch profile 2022-01-01 18:26:40 -08:00
WarmUpTill
d69aba8ab7 Remove dependency to SceneSwitcherEntry and SwitchWidget 2021-12-28 05:07:37 -08:00
WarmUpTill
a2ba7adc56 Add option to wait for transition to complete 2021-12-28 05:07:37 -08:00
WarmUpTill
0881146a25 Fix startup behavior not loading correctly 2021-12-22 13:12:41 -08:00
WarmUpTill
5224d6589e Reduce log output when running macro in background 2021-12-22 13:12:27 -08:00
WarmUpTill
15eeec8ebf Add condition "Studio Mode"
Can be used to check whether or not studio mode is active or to check
the current preview scene
2021-12-22 13:12:27 -08:00
WarmUpTill
ed7f375d64 Fix crash when reordering macros 2021-12-22 13:12:27 -08:00
WarmUpTill
82da6b3217 Update locale of "cooldown" and "no match" behaviour 2021-12-06 11:44:52 -08:00
WarmUpTill
8d83df9034 Add warning if macro functionality is not running with highest priority 2021-12-06 10:27:20 -08:00
WarmUpTill
0029977ae1 Adjust and move default priorities
New users will be confused if their macros are not executed,
if they are "blocked" by other scene switching methods.
2021-12-06 10:27:20 -08:00
WarmUpTill
0a481b3e31 Add example to data folder instructions for Linux 2021-12-04 08:32:52 -08:00
WarmUpTill
70b3c2e240 Workaround OpenCV MacOS build issue 2021-12-04 08:32:52 -08:00
WarmUpTill
1785035b96 Fix warnings 2021-12-04 08:32:52 -08:00
WarmUpTill
69ab101ba3 Fix header info for media and transition condition 2021-12-04 08:32:52 -08:00
WarmUpTill
d1e752cda1 Remove Linux workaround 2021-12-04 08:32:37 -08:00
WarmUpTill
e9d366f2b9 Update readme to include flatpak 2021-12-04 04:32:29 -08:00
WarmUpTill
b168518c60 Update zh-CN locale (provided by qwe1154323937) 2021-12-04 04:32:29 -08:00
WarmUpTill
845506f7e4 Allow running macros in parallel to other macros 2021-12-04 04:09:30 -08:00
WarmUpTill
9dd47b811b Add button to manually run macro actions 2021-12-04 04:09:30 -08:00
WarmUpTill
eafad7fe7f Add option to match any or all media sources of a specific scene 2021-12-04 04:04:55 -08:00
WarmUpTill
f36062859d Allow setting random duration in specified range 2021-12-04 03:37:46 -08:00
WarmUpTill
949e26781a Enable screenshots of scenes 2021-12-04 03:37:08 -08:00
WarmUpTill
2d70fbac36 Add compatability check for screenshot functionality 2021-12-04 03:37:08 -08:00
WarmUpTill
bb954a2e9a Add macro action for triggering screenshots 2021-12-04 03:37:08 -08:00
WarmUpTill
631423a251 Add condition to check if the plugin is running
This will only ever return true as the plugin cannot perform checks if
it is not running.
This is intended to be used in cases where it can be useful to trigger
actions once the plugin was stopped and restarted or if one wants to
perform actions after a certain amount of plugin "uptime".
2021-12-01 11:38:38 -08:00
WarmUpTill
c527f15744 Add hotkey to toggle pause state of macros 2021-12-01 09:23:04 -08:00
WarmUpTill
8fdacc3ef7 Suggest file name when saving settings 2021-11-28 09:57:30 -08:00
WarmUpTill
02918785ba Hide waitForTransition option if waiting for transition
The additions to the transition condition to check for target and source
scene of a ongoing transition fullfill the same role and this option
does not really fit the current scene check anyways.
2021-11-28 09:56:50 -08:00
WarmUpTill
2d9e6bcaa2 Add transition option to check for transition source and target scene 2021-11-28 09:56:50 -08:00
WarmUpTill
f2570e1deb Add the option to execute another macro's actions 2021-11-28 09:56:37 -08:00
WarmUpTill
f9afbcbc59 Add macro action to display system tray notifications 2021-11-28 09:56:17 -08:00
WarmUpTill
51b4ef326d Add fallback using QDesktopServices::openUrl() for "run" action
Users not familiar with launching processes with arguments might expect
the run action to behave like clicking on icons on the desktop and be
frustrated if the "file is not being opened".
Thus introducing this fallback might help some users out.
2021-11-23 11:11:41 -08:00
WarmUpTill
ad08df3d2f Clean up adding new macros to Random action 2021-11-23 11:11:41 -08:00
WarmUpTill
4d32e921f9 Resize list to minimum necessary height 2021-11-23 11:11:41 -08:00
WarmUpTill
5dfed8ac2a CI: Switch to OBS 27.1.3 2021-11-20 05:37:57 -08:00
WarmUpTill
d7102d395e Ensure contents of comboboxes are readable when changing scene/filter 2021-11-20 03:52:54 -08:00
WarmUpTill
82a41694a1 Allow interacting with OBS main window while plugin settings are opened 2021-11-20 03:52:54 -08:00
WarmUpTill
a1cae263c1 Add macro action "random" (#353)
This should be expanded upon by adding the ability to add weights to each macro.
2021-11-20 12:52:12 +01:00
WarmUpTill
cce6e240c2 Add option to fade in/out volume change 2021-11-17 12:30:10 -08:00
WarmUpTill
9d04b4d1a0 Move setLayoutVisible() to utility 2021-11-17 12:30:10 -08:00
WarmUpTill
fd7e48eff9 Add scene-visibility macro condition 2021-11-17 12:29:57 -08:00
WarmUpTill
0350a46004 Allow use of "previous scene" 2021-11-17 12:29:57 -08:00
WarmUpTill
00fec4b573 Fix macro hotkeys not working 2021-11-17 12:29:41 -08:00
WarmUpTill
c40a3af8ca Fix add, delete, reorder not working when changing macro segment type 2021-11-17 12:06:53 -08:00
WarmUpTill
e452d8cc8c Allow selecting source type for scene visibility action
This should allow to simplify some setups which required showing /
hiding all sources of a particular type.
2021-11-12 10:05:54 -08:00
WarmUpTill
fbc9818764 Fix macro count not updating correctly
The underlying issue are the potential deadlocks when triggering
frontent function calls while saving / loading is triggered in parallel
like it can happen when switching scene collections.

Hopefully the new frontend events allow for a cleaner solution.
2021-11-12 10:05:11 -08:00
WarmUpTill
5ef09f661f Show warning if macro is paused
And clean up timer handling for this condition type
2021-11-12 10:05:11 -08:00
WarmUpTill
2155a942f3 Do not check conditions of paused macros 2021-11-12 10:05:11 -08:00
WarmUpTill
5af206da60 Fix typo 2021-11-09 10:24:14 -08:00
WarmUpTill
924f68df64 Fix typo 2021-11-07 11:14:25 +01:00
WarmUpTill
2f3c4a6dae Cleanup 2021-11-06 22:30:26 +01:00
WarmUpTill
f955c07bda Fix warnings 2021-11-01 11:23:43 -07:00
WarmUpTill
6f1cd3cbcc Enable building without opencv 2021-11-01 11:23:43 -07:00
WarmUpTill
95537f39e4 Switch to using process names for process condition and executable tab (#337)
Previously the process condition and executable tab were just reusing
the window title functionality.
2021-10-31 14:05:54 +01:00
WarmUpTill
0490c97ad9 Add option to use pattern matching for "output changed" condition
This will allow you to ignore minor changes in the video output, for
example in noisy video streams.
2021-10-31 06:05:16 -07:00
WarmUpTill
4b17314c66 Add conditions "stream starting" and "stream stopping" 2021-10-31 05:40:28 -07:00
WarmUpTill
7459793fe3 Improve missing data dir error 2021-10-30 11:40:34 -07:00
WarmUpTill
8a39a859be Remove whitespace 2021-10-30 11:40:26 -07:00
WarmUpTill
f8a592f17a CI: Update readme 2021-10-30 11:40:26 -07:00
WarmUpTill
f824ac8f4e Add option to display plugin running state in system tray 2021-10-30 11:40:10 -07:00
WarmUpTill
8e9323173a CI: Run builds on tag creation also 2021-10-28 14:38:25 -07:00
WarmUpTill
9bc59c1082 Add option to not save remaining time 2021-10-25 11:19:53 -07:00
WarmUpTill
8b9f03a349 Add timer action
This action can be used to control the state of the timers on macro
conditions
2021-10-23 13:54:26 -07:00
WarmUpTill
093b0f9ec0 Add pause / continue and save / load remaining time for time condition 2021-10-23 13:54:26 -07:00
WarmUpTill
254eabfa8d Fix exact image match not wokring when using images with alpha channel
The screenshots taken from video sources were using the image format
Format_RGBX8888 instead of Format_RGBA8888.
The alpha channel of screenshots taken from OBS would be blended with a
black background while this step would be not performed for files loaded
to macht match the video sources.
2021-10-23 13:54:15 -07:00
WarmUpTill
b2da8faf37 Improve performance by not creating pattern data each interval 2021-10-23 13:54:15 -07:00
WarmUpTill
3eba20e2d8 Add option to use alpha channel as mask for pattern match 2021-10-23 13:54:15 -07:00
WarmUpTill
08841aa88e Use duration control class / widget for scene triggers 2021-10-23 13:53:56 -07:00
WarmUpTill
2e96c226b5 Improve performance of expand / collapse all 2021-10-23 13:53:56 -07:00
WarmUpTill
c34308f743 Fix scroll position being lost when adding or removing macro segments 2021-10-23 13:53:56 -07:00
WarmUpTill
4af07d9d55 Fix incorrectly set start scene type when extending scquence with groups
This would result in extended sequences being aborted early whenever one
would try to extend after a scene group entry
2021-10-23 13:53:56 -07:00
WarmUpTill
d743260ca8 Add wait for transition to complete option for currrent scene check
Previous behaviour was to always wait for the transition to complete, as
switcher->currentScene is only updated on
OBS_FRONTEND_EVENT_SCENE_CHANGED.
2021-10-23 13:53:56 -07:00
WarmUpTill
8ff50056f0 Fix crash when switching scene collection during macro wait
Also update comment stating why the main mutex needs to be unlocked
during the "action" phase of running macros
2021-10-23 13:53:56 -07:00
WarmUpTill
b786831f3b Remove unnecessary return value check 2021-10-23 13:53:56 -07:00
WarmUpTill
32e2a5f44c Add git tag to version info 2021-10-19 13:02:15 -07:00
WarmUpTill
e3f277c32a Reword date repeat option 2021-10-19 13:01:24 -07:00
WarmUpTill
5a7d76061c Clean up general tab
- Remove unnecessary spacer next to priority list
- Remove horizontal line in General behviour section
2021-10-19 13:01:01 -07:00
WarmUpTill
39a8c34fa6 Add description for the "min neighbors" parameter 2021-10-09 08:08:15 -07:00
WarmUpTill
ead51e2f13 Fix minNeighbors parameter not loading correctly 2021-10-09 08:08:15 -07:00
WarmUpTill
3b465e1fdc Fix crash while loading haar cascade 2021-10-03 12:30:45 -07:00
WarmUpTill
26fd26051b CI: Run on ubuntu-latest 2021-10-03 11:11:53 -07:00
WarmUpTill
08933a3683 Add transition condition 2021-10-03 07:51:09 -07:00
WarmUpTill
9be00ba3ca Rework to use transition selection widget 2021-10-03 07:51:09 -07:00
WarmUpTill
cce15529fe Adjust return type 2021-10-03 07:51:09 -07:00
WarmUpTill
588f90f0b1 Add transition selection widget 2021-10-03 07:51:09 -07:00
WarmUpTill
d3220c40dc Add any transition selection in populate function 2021-10-03 07:51:09 -07:00
WarmUpTill
79c659b4fa Reduce logging 2021-10-03 01:38:08 -07:00
WarmUpTill
292adb990d Add option to throttle object and pattern recognition 2021-10-03 01:38:08 -07:00
WarmUpTill
b7a0f6c5d0 Add object detection option 2021-10-03 01:38:08 -07:00
WarmUpTill
b3f1aff03c Add file selection widget
Rework the following macro conditions and actions to use this widget:
 - file action
 - run action
 - file condition
2021-10-03 01:38:08 -07:00
WarmUpTill
aea9d1b319 Update build instructions 2021-10-03 01:38:08 -07:00
WarmUpTill
1fd724e4f4 Include OpenCV in build 2021-10-03 01:38:08 -07:00
WarmUpTill
3d1c613f1c Add pattern match using openCV 2021-10-03 01:38:08 -07:00
WarmUpTill
9ca2f4470b Add opencv as submodule 2021-10-03 01:38:08 -07:00
WarmUpTill
34527b08a9 Fix crash in getSourceSettings() 2021-10-02 14:14:57 -07:00
WarmUpTill
3ae1050488 CI: Switch to obs tag 27.1.1 2021-09-30 12:13:15 -07:00
WarmUpTill
d7ec7c6e40 Limit key press to OBS by default on MacOS 2021-09-30 10:42:57 -07:00
WarmUpTill
e98ee64974 Set canSimulateKeyPresses to false on Macos (not implemented) 2021-09-30 10:42:57 -07:00
WarmUpTill
7c6428b27e Include press duration option and option to limit key press to OBS 2021-09-30 10:42:57 -07:00
WarmUpTill
aca9b84fc6 Fix rapid scene switch restarting certain transitions (#313)
When using certain transition types repeated scene switches to the same target scene will restart a transition that is already in progress.
This can be avoided by using obs_frontend_get_current_scene() instead of switcher->currentScene during the check if the target scene is already active.
obs_frontend_get_current_scene() will already point to the new scene, even if the transition is still in progess, while switcher->currentScene will only be updated once a transition is finished.
2021-09-26 14:04:01 +02:00
WarmUpTill
d397f5e406 Add transition action 2021-09-19 05:15:49 -07:00
WarmUpTill
97cbcd7e61 Add condition "scene has not changed" 2021-09-18 10:21:54 -07:00
WarmUpTill
64fd8dd50d Add "apt update" calls 2021-09-18 10:21:35 -07:00
WarmUpTill
a0dd1cf3ef Remove unused variable 2021-09-16 10:27:32 -07:00
WarmUpTill
25cf51abea Add option to specify lib and data install location 2021-09-13 12:50:10 -07:00
Joao Eriberto Mota Filho
3c8f5088d3 Fix word "unknown" 2021-09-13 10:58:39 -07:00
Joao Eriberto Mota Filho
66f3c74cf3 Fix some mistakes in debian CI test
Some mistakes found when packaging for Debian:
  - Remove trash from rules and enforce hardening.
  - Use the same licensing from Debian package to avoid a misinterpretation
    from FTP Master.
  - Fix target variable in debian/rules
2021-09-13 10:58:39 -07:00
WarmUpTill
6c23110fb9 Strip Linux binary debug symbols to reduce release artifact size 2021-09-12 11:09:00 -07:00
WarmUpTill
c9001df97c Add libxss-dev dependency 2021-09-12 11:09:00 -07:00
WarmUpTill
76fa1f8942 Add backward compatibility check to support OBS 25 2021-09-12 10:20:59 -07:00
Joao Eriberto Mota Filho
55ca146a82 Install missing obs-frontend-api.h 2021-09-12 10:20:59 -07:00
Joao Eriberto Mota Filho
a3625242de Create CI test for Debian packaging (in Ubuntu 20.04) 2021-09-12 10:20:59 -07:00
WarmUpTill
db4214c918 Remove dependency to <util/util.hpp> 2021-09-12 03:11:21 -07:00
WarmUpTill
f024199e2d Add backwards compatibility check 2021-09-12 03:11:21 -07:00
WarmUpTill
299e7bc868 Improve build instructions 2021-09-12 03:11:21 -07:00
WarmUpTill
0262e066bf Update cmake script to work better for out of tree builds
Use package name 'CURL' for out of tree builds.
Removed ObsPluginHelpers.cmake and FindLibObs.cmake as they disturbed
out of tree build.
2021-09-12 03:11:21 -07:00
WarmUpTill
bee75336d0 Add option to for macro condition scene to trigger on any scene change 2021-09-10 15:14:09 -07:00
WarmUpTill
96b472776a Remove unused variable 2021-09-10 15:14:09 -07:00
WarmUpTill
fb457f723a Add macro action scene swap 2021-09-10 14:21:29 -07:00
WarmUpTill
eee3e05c10 Add action to switch preview scene 2021-09-02 10:06:54 -07:00
WarmUpTill
ccc147a1b3 Fix empty paths not saving on file tab 2021-08-27 23:40:00 +02:00
WarmUpTill
45a149f6df Also save window geo when using ESC or the close button 2021-08-27 09:10:50 -07:00
WarmUpTill
076be21d40 Validate window position before setting it 2021-08-27 09:10:50 -07:00
WarmUpTill
ab5bdb32f5 Highlight newly added macro segments 2021-08-27 08:43:28 -07:00
WarmUpTill
8cfed048cc Create copy of previous macro segment when inserting new segment 2021-08-27 08:43:28 -07:00
WarmUpTill
c842595214 Add "size" section to scene item transform info 2021-08-27 08:43:08 -07:00
WarmUpTill
8fa3e8b038 Fix crash on clicking "Get settings" if source or filter is null 2021-08-27 08:43:08 -07:00
WarmUpTill
174c17edea Escape settings when pressing "Get settings" and regex is active 2021-08-27 08:43:08 -07:00
WarmUpTill
9d8fadda80 Remove unused include 2021-08-27 08:43:08 -07:00
WarmUpTill
58028d3c3d Add macro condition "scene transform" 2021-08-27 08:43:08 -07:00
WarmUpTill
3dcabe543f Add matchJson(), escapeRegex() move TransformState functions to utility 2021-08-27 08:43:08 -07:00
WarmUpTill
1a7ebc5569 Fix warning 2021-08-19 12:56:34 -07:00
WarmUpTill
522ab2963e Fix typo 2021-08-19 12:56:34 -07:00
WarmUpTill
d9bd98ce9c Parallelize windows build 2021-08-19 12:56:34 -07:00
WarmUpTill
2af0735a2f Expand date condition functionality
The date condition now supports the condition types "after", "before"
and specifying a time range.
2021-08-12 11:01:45 -07:00
WarmUpTill
556943c293 Fix writing current scene to file 2021-08-11 12:49:07 -07:00
WarmUpTill
e3004184c4 Format json strings of user input and source settings
Source settings and user specified settings might use different json
formatting and thus not match even though the json contents match.

It might not be possible to do the formatting for regex strings so
revert to the originally specified settings string if it cannot.
2021-08-09 11:39:48 -07:00
WarmUpTill
7b2c2e91db Rename function 2021-08-09 11:39:48 -07:00
WarmUpTill
06ea7bf1d9 Fix crash when deleting macro with wait action
Note that this might still not be completely race free but should
improve the situation a lot.
2021-08-09 11:39:20 -07:00
WarmUpTill
1474509cb9 Fix extended sequence abort when using non-instant transitions 2021-07-30 00:47:40 +02:00
WarmUpTill
87aa8d3b40 Remove code used for backwards compatibility 2021-07-29 15:16:29 -07:00
WarmUpTill
d3e8b76fa6 Do not apply MouseWheelWidgetAdjustmentGuard to QScrollBars
Without this change, it will be annoying to interact with expanded
QComboBoxes and there should be no danger of accidentally modifying
macro settings by interacting with QScrollBars
2021-07-29 15:16:19 -07:00
WarmUpTill
99c9b1a4a2 Fix macro video condition save
Logic, collapsed state and time constraint were not saved for video
condition.
2021-07-24 23:47:24 -07:00
WarmUpTill
8c0aad4c96 Add note to network tab
The requirement of the scene names having to match extactly was not made
clear and caused some confusion.
2021-07-24 23:31:35 -07:00
WarmUpTill
c964ed04d3 Clean up includes 2021-07-22 09:40:31 -07:00
WarmUpTill
810235e0b7 Clean up duplicate code 2021-07-22 09:40:31 -07:00
WarmUpTill
e2b3563810 Rename files 2021-07-22 09:40:31 -07:00
WarmUpTill
76c5ec480b Add MacroSegment and MacroSegmentEdit to remove duplicate code 2021-07-22 09:40:31 -07:00
WarmUpTill
84e4b740a8 Prevent accidental edits of actions and conditions when scrolling 2021-07-22 09:40:31 -07:00
WarmUpTill
95409dfa26 Add option to expand or collapse all macro actions or conditions 2021-07-22 09:40:31 -07:00
WarmUpTill
058af0d3bb Move GetShortDesc() and GetId() to MacroSegment class 2021-07-22 09:40:31 -07:00
WarmUpTill
fd789b476b Persist collapse / expand state 2021-07-22 09:40:31 -07:00
WarmUpTill
3fc82df278 Handle macro control signals 2021-07-22 09:40:31 -07:00
WarmUpTill
d541356fd3 Add macro control widget 2021-07-22 09:40:31 -07:00
WarmUpTill
5c2adacca1 Update build instructions and readme(#267)
* Adjust build instructions

* Add install instructions

* Add note regarding QtConcurrent
2021-07-22 18:39:34 +02:00
WarmUpTill
7200668158 Add option to show frame 2021-07-19 12:13:29 -07:00
WarmUpTill
7cf7fd6112 Show current cursor position 2021-07-19 12:13:29 -07:00
WarmUpTill
41821cbeb2 Add macro condition that triggers if cursor position changed
Extend condition previously named "region"
2021-07-19 12:13:29 -07:00
WarmUpTill
9537579235 Rename macro condition "region" to "cursor" 2021-07-19 12:13:29 -07:00
WarmUpTill
40a701a934 Add "--recursive" option to "git clone" calls 2021-07-18 19:37:16 +02:00
WarmUpTill
6c8556c66c Rework cmake and readme (#264)
* Add missing include

* Rework CMakeLists.txt to support out of tree builds

* Update build instructions

* Fix windows build issue and copy locale on Linux

* Update build instructions

* Add downloads section
2021-07-17 17:17:03 +02:00
WarmUpTill
a467dffd05 Fix crash on Fedora 2021-07-13 13:14:43 -07:00
WarmUpTill
497dbd89d4 Fix warning 2021-07-13 13:14:43 -07:00
WarmUpTill
0fdbce25a1 Clean up minor UI inconsistencies 2021-07-13 13:14:43 -07:00
432 changed files with 460462 additions and 13249 deletions

35
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,35 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Logs**
Please provide a log of your issue with verbose logging enabled (See General tab of the plugin).
See [here](https://obsproject.com/forum/threads/please-post-a-log-with-your-issue-heres-how.23074/) for a description where to find the log files and how to share them.
Please share the currently used plugin settings by exporting them them to a file (See General tab of the plugin).
If applicable, add screenshots to help explain your problem.
**Version information**
- OS: [e.g. Windows 10]
- OBS Version [e.g. 27.1.3]
- Plugin Version [e.g. 1.17.1]
**Additional context**
Add any other context about the problem here.

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: Help/Support
url: https://github.com/WarmUpTill/SceneSwitcher/wiki
about: For general questions about how to use and configure the plugin please have a look at the wiki (https://github.com/WarmUpTill/SceneSwitcher/wiki) or ask questions in the OBS forum (https://obsproject.com/forum/threads/advanced-scene-switcher.48264/)

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

89
.github/actions/build-plugin/action.yml vendored Normal file
View File

@@ -0,0 +1,89 @@
name: 'Setup and build plugin'
description: 'Builds the plugin for specified architecture and build config.'
inputs:
target:
description: 'Build target for dependencies'
required: true
config:
description: 'Build configuration'
required: false
default: 'Release'
codesign:
description: 'Enable codesigning (macOS only)'
required: false
default: 'false'
codesignIdent:
description: 'Developer ID for application codesigning (macOS only)'
required: false
default: '-'
visualStudio:
description: 'Visual Studio version (Windows only)'
required: false
default: 'Visual Studio 16 2019'
portable:
description: 'Set portable mode (Linux only)'
required: false
default: 'false'
workingDirectory:
description: 'Working directory for packaging'
required: false
default: ${{ github.workspace }}
runs:
using: 'composite'
steps:
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1.13
with:
cmake-version: '3.24.x'
- name: Run macOS Build
if: ${{ runner.os == 'macOS' }}
shell: zsh {0}
env:
CODESIGN_IDENT: ${{ inputs.codesignIdent }}
run: |
build_args=(
-c ${{ inputs.config }}
-t macos-${{ inputs.target }}
)
if [[ '${{ inputs.codesign }}' == 'true' ]] build_args+=(-s)
if (( ${+CI} && ${+RUNNER_DEBUG} )) build_args+=(--debug)
${{ inputs.workingDirectory }}/.github/scripts/build-macos.zsh ${build_args}
- name: Run Linux Build
if: ${{ runner.os == 'Linux' }}
shell: bash
run: |
build_args=(
-c ${{ inputs.config }}
-t linux-${{ inputs.target }}
)
if [[ -n "${CI}" && -n "${RUNNER_DEBUG}" ]]; then
build_args+=(--debug)
fi
if [[ '${{ inputs.portable }}' == 'true' ]]; then
build_args+=(-p)
fi
${{ inputs.workingDirectory }}/.github/scripts/build-linux.sh "${build_args[@]}"
- name: Run Windows Build
if: ${{ runner.os == 'Windows' }}
shell: pwsh
run: |
$BuildArgs = @{
Target = '${{ inputs.target }}'
Configuration = '${{ inputs.config }}'
CMakeGenerator = '${{ inputs.visualStudio }}'
}
if ( ( Test-Path env:CI ) -and ( Test-Path env:RUNNER_DEBUG ) ) {
$BuildArgs += @{
Debug = $true
}
}
${{ inputs.workingDirectory }}/.github/scripts/Build-Windows.ps1 @BuildArgs

View File

@@ -0,0 +1,109 @@
name: 'Package plugin'
description: 'Packages the plugin for specified architecture and build config.'
inputs:
target:
description: 'Build target for dependencies'
required: true
config:
description: 'Build configuration'
required: false
default: 'Release'
codesign:
description: 'Enable codesigning (macOS only)'
required: false
default: 'false'
notarize:
description: 'Enable notarization (macOS only)'
required: false
default: 'false'
codesignIdent:
description: 'Developer ID for application codesigning (macOS only)'
required: false
default: '-'
installerIdent:
description: 'Developer ID for installer package codesigning (macOS only)'
required: false
default: ''
codesignUser:
description: 'Apple ID username for notarization (macOS only)'
required: false
default: ''
codesignPass:
description: 'Apple ID password for notarization (macOS only)'
required: false
default: ''
createInstaller:
description: 'Create InnoSetup installer (Windows only)'
required: false
default: 'false'
portable:
description: 'Create deb package / portable archive (Linux only)'
required: false
default: 'false'
workingDirectory:
description: 'Working directory for packaging'
required: false
default: ${{ github.workspace }}
runs:
using: 'composite'
steps:
- name: Run macOS packaging
if: ${{ runner.os == 'macOS' }}
shell: zsh {0}
env:
CODESIGN_IDENT: ${{ inputs.codesignIdent }}
CODESIGN_IDENT_INSTALLER: ${{ inputs.installerIdent }}
CODESIGN_IDENT_USER: ${{ inputs.codesignUser }}
CODESIGN_IDENT_PASS: ${{ inputs.codesignPass }}
run: |
package_args=(
-c ${{ inputs.config }}
-t macos-${{ inputs.target }}
)
if [[ '${{ inputs.codesign }}' == 'true' ]] package_args+=(-s)
if [[ '${{ inputs.notarize }}' == 'true' ]] package_args+=(-n)
if (( ${+CI} && ${+RUNNER_DEBUG} )) build_args+=(--debug)
package_args+=(-z)
${{ inputs.workingDirectory }}/.github/scripts/package-macos.zsh ${package_args}
- name: Run Linux packaging
if: ${{ runner.os == 'Linux' }}
shell: bash
run: |
package_args=(
-c ${{ inputs.config }}
-t linux-${{ inputs.target }}
)
if [[ -n "${CI}" && -n "${RUNNER_DEBUG}" ]]; then
build_args+=(--debug)
fi
if [[ '${{ inputs.portable }}' == 'true' ]]; then
package_args+=(-z)
fi
${{ inputs.workingDirectory }}/.github/scripts/package-linux.sh "${package_args[@]}"
- name: Run Windows packaging
if: ${{ runner.os == 'Windows' }}
shell: pwsh
run: |
$PackageArgs = @{
Target = '${{ inputs.target }}'
Configuration = '${{ inputs.config }}'
}
if ( '${{ inputs.createInstaller }}' -eq 'true' ) {
$PackageArgs += @{BuildInstaller = $true}
}
if ( ( Test-Path env:CI ) -and ( Test-Path env:RUNNER_DEBUG ) ) {
$BuildArgs += @{
Debug = $true
}
}
${{ inputs.workingDirectory }}/.github/scripts/Package-Windows.ps1 @PackageArgs

37
.github/actions/run-tests/action.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: 'Package plugin'
description: 'Packages the plugin for specified architecture and build config.'
inputs:
target:
description: 'Build target'
required: true
workingDirectory:
description: 'Working directory'
required: false
default: ${{ github.workspace }}
runs:
using: 'composite'
steps:
- name: Run macOS tests
if: ${{ runner.os == 'macOS' }}
shell: zsh {0}
run: |
if [[ '${{ inputs.target }}' != 'x86_64' ]]; then
echo tests skipped!
exit 0
fi
${{ inputs.workingDirectory }}/build_x86_64/tests/advanced-scene-switcher-tests
- name: Run Linux packaging
if: ${{ runner.os == 'Linux' }}
shell: bash
run: |
if [[ '${{ inputs.target }}' != 'x86_64' ]]; then
exit 0
fi
${{ inputs.workingDirectory }}/build_x86_64/tests/advanced-scene-switcher-tests
- name: Run Windows packaging
if: ${{ runner.os == 'Windows' }}
shell: pwsh
run: |
${{ inputs.workingDirectory }}/build_x64/tests/RelWithDebInfo/advanced-scene-switcher-tests.exe

9
.github/scripts/.Aptfile vendored Normal file
View File

@@ -0,0 +1,9 @@
package 'cmake'
package 'ccache'
package 'curl'
package 'git'
package 'jq'
package 'ninja-build', bin: 'ninja'
package 'pkg-config'
package 'clang'
package 'clang-format-13'

6
.github/scripts/.Brewfile vendored Normal file
View File

@@ -0,0 +1,6 @@
brew "ccache"
brew "coreutils"
brew "cmake"
brew "git"
brew "jq"
brew "ninja"

3
.github/scripts/.Wingetfile vendored Normal file
View File

@@ -0,0 +1,3 @@
package '7zip.7zip', path: '7-zip', bin: '7z'
package 'cmake', path: 'Cmake\bin', bin: 'cmake'
package 'innosetup', path: 'Inno Setup 6', bin: 'iscc'

350
.github/scripts/.build.zsh vendored Executable file
View File

@@ -0,0 +1,350 @@
#!/usr/bin/env zsh
builtin emulate -L zsh
setopt EXTENDED_GLOB
setopt PUSHD_SILENT
setopt ERR_EXIT
setopt ERR_RETURN
setopt NO_UNSET
setopt PIPE_FAIL
setopt NO_AUTO_PUSHD
setopt NO_PUSHD_IGNORE_DUPS
setopt FUNCTION_ARGZERO
## Enable for script debugging
# setopt WARN_CREATE_GLOBAL
# setopt WARN_NESTED_VAR
# setopt XTRACE
autoload -Uz is-at-least && if ! is-at-least 5.2; then
print -u2 -PR "%F{1}${funcstack[1]##*/}:%f Running on Zsh version %B${ZSH_VERSION}%b, but Zsh %B5.2%b is the minimum supported version. Upgrade Zsh to fix this issue."
exit 1
fi
_trap_error() {
print -u2 -PR '%F{1} ✖︎ script execution error%f'
print -PR -e "
Callstack:
${(j:\n :)funcfiletrace}
"
exit 2
}
build() {
if (( ! ${+SCRIPT_HOME} )) typeset -g SCRIPT_HOME=${ZSH_ARGZERO:A:h}
local host_os=${${(s:-:)ZSH_ARGZERO:t:r}[2]}
local target="${host_os}-${CPUTYPE}"
local project_root=${SCRIPT_HOME:A:h:h}
local buildspec_file="${project_root}/buildspec.json"
trap '_trap_error' ZERR
fpath=("${SCRIPT_HOME}/utils.zsh" ${fpath})
autoload -Uz log_info log_error log_output set_loglevel check_${host_os} setup_${host_os} setup_obs setup_ccache
if [[ ! -r ${buildspec_file} ]] {
log_error \
'No buildspec.json found. Please create a build specification for your project.' \
'A buildspec.json.template file is provided in the repository to get you started.'
return 2
}
typeset -g -a skips=()
local -i _verbosity=1
local -r _version='1.0.0'
local -r -a _valid_targets=(
macos-x86_64
macos-arm64
macos-universal
linux-x86_64
)
local -r -a _valid_configs=(Debug RelWithDebInfo Release MinSizeRel)
if [[ ${host_os} == 'macos' ]] {
local -r -a _valid_generators=(Xcode Ninja 'Unix Makefiles')
local generator="${${CI:+Ninja}:-Xcode}"
} else {
local -r -a _valid_generators=(Ninja 'Unix Makefiles')
local generator='Ninja'
}
local -r _usage="
Usage: %B${functrace[1]%:*}%b <option> [<options>]
%BOptions%b:
%F{yellow} Build configuration options%f
-----------------------------------------------------------------------------
%B-t | --target%b Specify target - default: %B%F{green}${host_os}-${CPUTYPE}%f%b
%B-c | --config%b Build configuration - default: %B%F{green}RelWithDebInfo%f%b
%B-s | --codesign%b Enable codesigning (macOS only)
%B-p | --portable%b Enable portable mode (Linux only)
%B--generator%b Specify build system to generate - default: %B%F{green}Ninja%f%b
Available generators:
- Ninja
- Unix Makefiles
- Xcode (macOS only)
%F{yellow} Output options%f
-----------------------------------------------------------------------------
%B-q | --quiet%b Quiet (error output only)
%B-v | --verbose%b Verbose (more detailed output)
%B--skip-[all|build|deps|unpack]%b Skip all|building OBS|checking for dependencies|unpacking dependencies
%B--debug%b Debug (very detailed and added output)
%F{yellow} General options%f
-----------------------------------------------------------------------------
%B-h | --help%b Print this usage help
%B-V | --version%b Print script version information"
local -a args
while (( # )) {
case ${1} {
-t|--target|-c|--config|--generator)
if (( # == 1 )) || [[ ${2:0:1} == '-' ]] {
log_error "Missing value for option %B${1}%b"
log_output ${_usage}
exit 2
}
;;
}
case ${1} {
--)
shift
args+=($@)
break
;;
-t|--target)
if (( ! ${_valid_targets[(Ie)${2}]} )) {
log_error "Invalid value %B${2}%b for option %B${1}%b"
log_output ${_usage}
exit 2
}
target=${2}
shift 2
;;
-c|--config)
if (( ! ${_valid_configs[(Ie)${2}]} )) {
log_error "Invalid value %B${2}%b for option %B${1}%b"
log_output ${_usage}
exit 2
}
BUILD_CONFIG=${2}
shift 2
;;
-s|--codesign) CODESIGN=1; shift ;;
-p|--portable) typeset -g PORTABLE=1; shift ;;
-q|--quiet) (( _verbosity -= 1 )) || true; shift ;;
-v|--verbose) (( _verbosity += 1 )); shift ;;
-h|--help) log_output ${_usage}; exit 0 ;;
-V|--version) print -Pr "${_version}"; exit 0 ;;
--debug) _verbosity=3; shift ;;
--generator)
if (( ! ${_valid_generators[(Ie)${2}]} )) {
log_error "Invalid value %B${2}%b for option %B${1}%b"
log_output ${_usage}
exit 2
}
generator=${2}
shift 2
;;
--skip-*)
local _skip="${${(s:-:)1}[-1]}"
local _check=(all deps unpack build)
(( ${_check[(Ie)${_skip}]} )) || log_warning "Invalid skip mode %B${_skip}%b supplied"
typeset -g -a skips=(${skips} ${_skip})
shift
;;
*) log_error "Unknown option: %B${1}%b"; log_output ${_usage}; exit 2 ;;
}
}
set -- ${(@)args}
set_loglevel ${_verbosity}
check_${host_os}
setup_ccache
typeset -g QT_VERSION
typeset -g DEPLOYMENT_TARGET
typeset -g OBS_DEPS_VERSION
setup_${host_os}
local product_name
local product_version
read -r product_name product_version <<< \
"$(jq -r '. | {name, version} | join(" ")' ${buildspec_file})"
case ${host_os} {
macos)
sed -i '' \
"s/project(\(.*\) VERSION \(.*\))/project(${product_name} VERSION ${product_version})/" \
"${project_root}/CMakeLists.txt"
local opencv_dir="${project_root}/deps/opencv"
local opencv_build_dir="${opencv_dir}/build_${target##*-}"
local -a opencv_cmake_args=(
-DCMAKE_BUILD_TYPE=Release
-DBUILD_LIST=core,imgproc,objdetect
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
)
if [ "${target}" != "macos-x86_64" ]; then
opencv_cmake_args+=(-DWITH_IPP=OFF)
fi
pushd ${opencv_dir}
log_info "Configure OpenCV ..."
cmake -S . -B ${opencv_build_dir} -G ${generator} ${opencv_cmake_args}
log_info "Building OpenCV ..."
cmake --build ${opencv_build_dir} --config Release
log_info "Installing OpenCV..."
cmake --install ${opencv_build_dir} --config Release || true
popd
local leptonica_dir="${project_root}/deps/leptonica"
local leptonica_build_dir="${leptonica_dir}/build_${target##*-}"
local -a leptonica_cmake_args=(
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
-DSW_BUILD=OFF
-DOPENJPEG_SUPPORT=OFF
-DLIBWEBP_SUPPORT=OFF
-DCMAKE_DISABLE_FIND_PACKAGE_GIF=TRUE
-DCMAKE_DISABLE_FIND_PACKAGE_JPEG=TRUE
-DCMAKE_DISABLE_FIND_PACKAGE_TIFF=TRUE
-DCMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE
)
pushd ${leptonica_dir}
log_info "Configure Leptonica ..."
cmake -S . -B ${leptonica_build_dir} -G ${generator} ${leptonica_cmake_args}
log_info "Building Leptonica ..."
cmake --build ${leptonica_build_dir} --config Release
log_info "Installing Leptonica..."
# Workaround for "unknown file attribute: H" errors when running install
cmake --install ${leptonica_build_dir} --config Release || :
popd
local tesseract_dir="${project_root}/deps/tesseract"
local tesseract_build_dir="${tesseract_dir}/build_${target##*-}"
local -a tesseract_cmake_args=(
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
-DSW_BUILD=OFF
-DBUILD_TRAINING_TOOLS=OFF
)
if [ "${target}" != "macos-x86_64" ]; then
tesseract_cmake_args+=(
-DCMAKE_SYSTEM_PROCESSOR=aarch64
-DHAVE_AVX=FALSE
-DHAVE_AVX2=FALSE
-DHAVE_AVX512F=FALSE
-DHAVE_FMA=FALSE
-DHAVE_SSE4_1=FALSE
-DHAVE_NEON=TRUE
)
sed -i'.original' 's/HAVE_NEON FALSE/HAVE_NEON TRUE/g' "${tesseract_dir}/CMakeLists.txt"
fi
pushd ${tesseract_dir}
log_info "Configure Tesseract ..."
cmake -S . -B ${tesseract_build_dir} -G ${generator} ${tesseract_cmake_args}
log_info "Building Tesseract ..."
#cmake --build ${tesseract_build_dir} --config Release --target libtesseract
cmake --build ${tesseract_build_dir} --config Release
log_info "Installing Tesseract..."
#cmake --install ${tesseract_build_dir} --config Release --component libtesseract
cmake --install ${tesseract_build_dir} --config Release
popd
;;
linux)
sed -i'' \
"s/project(\(.*\) VERSION \(.*\))/project(${product_name} VERSION ${product_version})/"\
"${project_root}/CMakeLists.txt"
;;
}
setup_obs
pushd ${project_root}
if (( ! (${skips[(Ie)all]} + ${skips[(Ie)build]}) )) {
log_info "Configuring ${product_name}..."
local _plugin_deps="${project_root:h}/obs-build-dependencies/plugin-deps-${OBS_DEPS_VERSION}-qt${QT_VERSION}-${target##*-}"
local -a cmake_args=(
-DCMAKE_BUILD_TYPE=${BUILD_CONFIG:-RelWithDebInfo}
-DQT_VERSION=${QT_VERSION}
-DCMAKE_PREFIX_PATH="${_plugin_deps}"
)
if (( _loglevel == 0 )) cmake_args+=(-Wno_deprecated -Wno-dev --log-level=ERROR)
if (( _loglevel > 2 )) cmake_args+=(--debug-output)
local num_procs
case ${target} {
macos-*)
autoload -Uz read_codesign
if (( ${+CODESIGN} )) {
read_codesign
}
num_procs=$(( $(sysctl -n hw.ncpu) + 1 ))
cmake_args+=(
-DCMAKE_FRAMEWORK_PATH="${_plugin_deps}/Frameworks"
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
-DOBS_CODESIGN_LINKER=ON
-DOBS_BUNDLE_CODESIGN_IDENTITY="${CODESIGN_IDENT:--}"
)
;;
linux-*)
if (( ${+PORTABLE} )) {
cmake_args+=(
-DLINUX_PORTABLE=ON
)
} else {
cmake_args+=(
-DCMAKE_INSTALL_PREFIX=/usr
-DLINUX_PORTABLE=OFF
)
}
num_procs=$(( $(nproc) + 1 ))
;;
}
log_debug "Attempting to configure ${product_name} with CMake arguments: ${cmake_args}"
cmake -S . -B build_${target##*-} -G ${generator} ${cmake_args}
log_info "Building ${product_name}..."
local -a cmake_args=()
if (( _loglevel > 1 )) cmake_args+=(--verbose)
if [[ ${generator} == 'Unix Makefiles' ]] cmake_args+=(--parallel ${num_procs})
cmake --build build_${target##*-} --config ${BUILD_CONFIG:-RelWithDebInfo} ${cmake_args}
}
log_info "Installing ${product_name}..."
local -a cmake_args=()
if (( _loglevel > 1 )) cmake_args+=(--verbose)
cmake --install build_${target##*-} --config ${BUILD_CONFIG:-RelWithDebInfo} --prefix "${project_root}/release" ${cmake_args}
popd
}
build ${@}

207
.github/scripts/.package.zsh vendored Executable file
View File

@@ -0,0 +1,207 @@
#!/usr/bin/env zsh
builtin emulate -L zsh
setopt EXTENDED_GLOB
setopt PUSHD_SILENT
setopt ERR_EXIT
setopt ERR_RETURN
setopt NO_UNSET
setopt PIPE_FAIL
setopt NO_AUTO_PUSHD
setopt NO_PUSHD_IGNORE_DUPS
setopt FUNCTION_ARGZERO
## Enable for script debugging
# setopt WARN_CREATE_GLOBAL
# setopt WARN_NESTED_VAR
# setopt XTRACE
autoload -Uz is-at-least && if ! is-at-least 5.2; then
print -u2 -PR "%F{1}${funcstack[1]##*/}:%f Running on Zsh version %B${ZSH_VERSION}%b, but Zsh %B5.2%b is the minimum supported version. Upgrade Zsh to fix this issue."
exit 1
fi
_trap_error() {
print -u2 -PR '%F{1} ✖︎ script execution error%f'
print -PR -e "
Callstack:
${(j:\n :)funcfiletrace}
"
exit 2
}
package() {
if (( ! ${+SCRIPT_HOME} )) typeset -g SCRIPT_HOME=${ZSH_ARGZERO:A:h}
local host_os=${${(s:-:)ZSH_ARGZERO:t:r}[2]}
local target="${host_os}-${CPUTYPE}"
local project_root=${SCRIPT_HOME:A:h:h}
local buildspec_file="${project_root}/buildspec.json"
trap '_trap_error' ZERR
fpath=("${SCRIPT_HOME}/utils.zsh" ${fpath})
autoload -Uz set_loglevel log_info log_error log_output check_${host_os}
local -i _verbosity=1
local -r _version='1.0.0'
local -r -a _valid_targets=(
macos-x86_64
macos-arm64
macos-universal
linux-x86_64
)
local -r -a _valid_configs=(Debug RelWithDebInfo Release MinSizeRel)
local -r _usage="
Usage: %B${functrace[1]%:*}%b <option> [<options>]
%BOptions%b:
%F{yellow} Package configuration options%f
-----------------------------------------------------------------------------
%B-t | --target%b Specify target - default: %B%F{green}${host_os}-${CPUTYPE}%f%b
%B-c | --config%b Build configuration - default: %B%F{green}RelWithDebInfo%f%b
%B-s | --codesign%b Enable codesigning (macOS only)
%B-n | --notarize%b Enable notarization (macOS only)
%B-z | --zip%b Zip only (Linux only)
%F{yellow} Output options%f
-----------------------------------------------------------------------------
%B-q | --quiet%b Quiet (error output only)
%B-v | --verbose%b Verbose (more detailed output)
%B--debug%b Debug (very detailed and added output)
%F{yellow} General options%f
-----------------------------------------------------------------------------
%B-h | --help%b Print this usage help
%B-V | --version%b Print script version information"
local -a args
while (( # )) {
case ${1} {
-t|--target|-c|--config)
if (( # == 1 )) || [[ ${2:0:1} == '-' ]] {
log_error "Missing value for option %B${1}%b"
log_output ${_usage}
exit 2
}
;;
}
case ${1} {
--)
shift
args+=($@)
break
;;
-t|--target)
if (( ! ${_valid_targets[(Ie)${2}]} )) {
log_error "Invalid value %B${2}%b for option %B${1}%b"
log_output ${_usage}
exit 2
}
target=${2}
shift 2
;;
-c|--config)
if (( ! ${_valid_configs[(Ie)${2}]} )) {
log_error "Invalid value %B${2}%b for option %B${1}%b"
log_output ${_usage}
exit 2
}
BUILD_CONFIG=${2}
shift 2
;;
-s|--codesign) typeset -g CODESIGN=1; shift ;;
-n|--notarize) typeset -g NOTARIZE=1; typeset -g CODESIGN=1; shift ;;
-z|--zip) typeset -g ZIP=1; shift ;;
-q|--quiet) (( _verbosity -= 1 )) || true; shift ;;
-v|--verbose) (( _verbosity += 1 )); shift ;;
-h|--help) log_output ${_usage}; exit 0 ;;
-V|--version) print -Pr "${_version}"; exit 0 ;;
--debug) _verbosity=3; shift ;;
*) log_error "Unknown option: %B${1}%b"; log_output ${_usage}; exit 2 ;;
}
}
set -- ${(@)args}
set_loglevel ${_verbosity}
check_${host_os}
local product_name
local product_version
read -r product_name product_version <<< \
"$(jq -r '. | {name, version} | join(" ")' ${project_root}/buildspec.json)"
if [[ ${host_os} == 'macos' ]] {
autoload -Uz check_packages read_codesign read_codesign_installer read_codesign_pass
local output_name="${product_name}-${host_os}-${target##*-}.pkg"
if [[ ! -d ${project_root}/release/${product_name}.plugin ]] {
log_error 'No release artifact found. Run the build script or the CMake install procedure first.'
return 2
}
if [[ ! -f ${project_root}/build_${target##*-}/installer-macos.generated.pkgproj ]] {
log_error 'Packages project file not found. Run the build script or the CMake build and install procedures first.'
return 2
}
check_packages
log_info "Packaging ${product_name}..."
pushd ${project_root}
packagesbuild \
--build-folder ${project_root}/release \
${project_root}/build_${target##*-}/installer-macos.generated.pkgproj
if (( ${+CODESIGN} )) {
read_codesign_installer
productsign \
--sign "${CODESIGN_IDENT_INSTALLER}" \
"${project_root}/release/${product_name}.pkg" \
"${project_root}/release/${output_name}"
rm "${project_root}/release/${product_name}.pkg"
} else {
mv "${project_root}/release/${product_name}.pkg" \
"${project_root}/release/${output_name}"
}
if (( ${+CODESIGN} && ${+NOTARIZE} )) {
if [[ ! -f "${project_root}/release/${output_name}" ]] {
log_error "No package for notarization found."
return 2
}
read_codesign_installer
read_codesign_pass
xcrun notarytool submit "${project_root}/release/${output_name}" \
--keychain-profile "OBS-Codesign-Password" --wait
xcrun stapler staple "${project_root}/release/${output_name}"
}
if (( ${+ZIP} )) {
local output_name="${product_name}-${host_os}-${target##*-}.zip"
pushd ${project_root}/release
zip -r "${output_name}" *~*.pkg
popd
}
popd
} elif [[ ${host_os} == 'linux' ]] {
if (( ${+ZIP} )) {
local output_name="${product_name}-${host_os}-${target##*-}.zip"
pushd ${project_root}/release
zip -r "${output_name}" *
popd
} else {
local -a cmake_args=()
if (( _loglevel > 1 )) cmake_args+=(--verbose)
pushd ${project_root}
cmake --build build_${target##*-} --config ${BUILD_CONFIG:-RelWithDebInfo} -t package ${cmake_args}
popd
}
}
}
package ${@}

210
.github/scripts/Build-Windows.ps1 vendored Normal file
View File

@@ -0,0 +1,210 @@
[CmdletBinding()]
param(
[ValidateSet('Debug', 'RelWithDebInfo', 'Release', 'MinSizeRel')]
[string] $Configuration = 'RelWithDebInfo',
[ValidateSet('x86', 'x64')]
[string] $Target,
[ValidateSet('Visual Studio 17 2022', 'Visual Studio 16 2019')]
[string] $CMakeGenerator,
[switch] $SkipAll,
[switch] $SkipBuild,
[switch] $SkipDeps,
[switch] $SkipUnpack
)
$ErrorActionPreference = 'Stop'
if ( $DebugPreference -eq 'Continue' ) {
$VerbosePreference = 'Continue'
$InformationPreference = 'Continue'
}
if ( $PSVersionTable.PSVersion -lt '7.0.0' ) {
Write-Warning 'The obs-deps PowerShell build script requires PowerShell Core 7. Install or upgrade your PowerShell version: https://aka.ms/pscore6'
exit 2
}
function Build {
trap {
Pop-Location -Stack BuildTemp -ErrorAction 'SilentlyContinue'
Write-Error $_
exit 2
}
$ScriptHome = $PSScriptRoot
$ProjectRoot = Resolve-Path -Path "$PSScriptRoot/../.."
$BuildSpecFile = "${ProjectRoot}/buildspec.json"
$UtilityFunctions = Get-ChildItem -Path $PSScriptRoot/utils.pwsh/*.ps1 -Recurse
foreach ($Utility in $UtilityFunctions) {
Write-Debug "Loading $($Utility.FullName)"
. $Utility.FullName
}
$BuildSpec = Get-Content -Path ${BuildSpecFile} -Raw | ConvertFrom-Json
$ProductName = $BuildSpec.name
$ProductVersion = $BuildSpec.version
$script:DepsVersion = ''
$script:QtVersion = '5'
$script:VisualStudioVersion = ''
$script:PlatformSDK = '10.0.18363.657'
Setup-Host
if ( $CmakeGenerator -eq '' ) {
$CmakeGenerator = $script:VisualStudioVersion
}
$DepsPath = "plugin-deps-${script:DepsVersion}-qt${script:QtVersion}-${script:Target}"
$DepInstallPath = "$(Resolve-Path -Path ${ProjectRoot}/../obs-build-dependencies/${DepsPath})"
$OpenCVPath = "${ProjectRoot}/deps/opencv"
$OpenCVBuildPath = "${OpenCVPath}/build"
Push-Location -Stack BuildOpenCVTemp
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
Ensure-Location $ProjectRoot
$OpenCVCmakeArgs = @(
'-G', $CmakeGenerator
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
"-DCMAKE_BUILD_TYPE=Release"
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
"-DBUILD_LIST=core,imgproc,objdetect"
)
Log-Information "Configuring OpenCV..."
Invoke-External cmake -S ${OpenCVPath} -B ${OpenCVBuildPath} @OpenCVCmakeArgs
$OpenCVCmakeArgs = @(
'--config', "Release"
)
if ( $VerbosePreference -eq 'Continue' ) {
$OpenCVCmakeArgs += ('--verbose')
}
Log-Information "Building OpenCV..."
Invoke-External cmake --build "${OpenCVBuildPath}" @OpenCVCmakeArgs
}
Log-Information "Install OpenCV}..."
Invoke-External cmake --install "${OpenCVBuildPath}" --prefix "${DepInstallPath}" @OpenCVCmakeArgs
$LeptonicaPath = "${ProjectRoot}/deps/leptonica"
$LeptonicaBuildPath = "${LeptonicaPath}/build"
Push-Location -Stack BuildLeptonicaTemp
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
Ensure-Location $ProjectRoot
$LeptonicaCmakeArgs = @(
'-G', $CmakeGenerator
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
"-DCMAKE_BUILD_TYPE=Release"
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
"-DCMAKE_INSTALL_PREFIX:PATH=${DepInstallPath}"
"-DSW_BUILD=OFF"
"-DLIBWEBP_SUPPORT=OFF"
)
Log-Information "Configuring leptonica..."
Invoke-External cmake -S ${LeptonicaPath} -B ${LeptonicaBuildPath} @LeptonicaCmakeArgs
$LeptonicaCmakeArgs = @(
'--config', "Release"
)
if ( $VerbosePreference -eq 'Continue' ) {
$LeptonicaCmakeArgs += ('--verbose')
}
Log-Information "Building leptonica..."
Invoke-External cmake --build "${LeptonicaBuildPath}" @LeptonicaCmakeArgs
}
Log-Information "Install leptonica..."
Invoke-External cmake --install "${LeptonicaBuildPath}" --prefix "${DepInstallPath}" @LeptonicaCmakeArgs
Push-Location -Stack BuildTesseractTemp
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
Ensure-Location $ProjectRoot
$TesseractPath = "${ProjectRoot}/deps/tesseract"
$TesseractBuildPath = "${TesseractPath}/build"
# Explicitly disable PkgConfig and tiff as it will lead build errors
$TesseractCmakeArgs = @(
'-G', $CmakeGenerator
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
"-DCMAKE_BUILD_TYPE=Release"
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
"-DCMAKE_INSTALL_PREFIX:PATH=${DepInstallPath}"
"-DSW_BUILD=OFF"
"-DDISABLE_CURL=ON"
"-DBUILD_TRAINING_TOOLS=OFF"
"-DCMAKE_DISABLE_FIND_PACKAGE_TIFF=TRUE"
"-DCMAKE_DISABLE_FIND_PACKAGE_PkgConfig=TRUE"
)
Log-Information "Configuring tesseract..."
Invoke-External cmake -S ${TesseractPath} -B ${TesseractBuildPath} @TesseractCmakeArgs
$TesseractCmakeArgs = @(
'--config', "Release"
)
if ( $VerbosePreference -eq 'Continue' ) {
$TesseractCmakeArgs += ('--verbose')
}
Log-Information "Building tesseract..."
Invoke-External cmake --build "${TesseractBuildPath}" @TesseractCmakeArgs
}
Log-Information "Install tesseract..."
Invoke-External cmake --install "${TesseractBuildPath}" --prefix "${DepInstallPath}" @TesseractCmakeArgs
(Get-Content -Path ${ProjectRoot}/CMakeLists.txt -Raw) `
-replace "project\((.*) VERSION (.*)\)", "project(${ProductName} VERSION ${ProductVersion})" `
| Out-File -Path ${ProjectRoot}/CMakeLists.txt
Setup-Obs
Push-Location -Stack BuildTemp
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
Ensure-Location $ProjectRoot
$CmakeArgs = @(
'-G', $CmakeGenerator
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
"-DCMAKE_BUILD_TYPE=${Configuration}"
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
"-DQT_VERSION=${script:QtVersion}"
)
Log-Debug "Attempting to configure OBS with CMake arguments: $($CmakeArgs | Out-String)"
Log-Information "Configuring ${ProductName}..."
Invoke-External cmake -S . -B build_${script:Target} @CmakeArgs
$CmakeArgs = @(
'--config', "${Configuration}"
)
if ( $VerbosePreference -eq 'Continue' ) {
$CmakeArgs += ('--verbose')
}
Log-Information "Building ${ProductName}..."
Invoke-External cmake --build "build_${script:Target}" @CmakeArgs
}
Log-Information "Install ${ProductName}..."
Invoke-External cmake --install "build_${script:Target}" --prefix "${ProjectRoot}/release" @CmakeArgs
Pop-Location -Stack BuildTemp
}
Build

91
.github/scripts/Package-Windows.ps1 vendored Normal file
View File

@@ -0,0 +1,91 @@
[CmdletBinding()]
param(
[ValidateSet('Debug', 'RelWithDebInfo', 'Release', 'MinSizeRel')]
[string] $Configuration = 'RelWithDebInfo',
[ValidateSet('x86', 'x64', 'x86+x64')]
[string] $Target,
[switch] $BuildInstaller = $false
)
$ErrorActionPreference = 'Stop'
if ( $DebugPreference -eq 'Continue' ) {
$VerbosePreference = 'Continue'
$InformationPreference = 'Continue'
}
if ( $PSVersionTable.PSVersion -lt '7.0.0' ) {
Write-Warning 'The obs-deps PowerShell build script requires PowerShell Core 7. Install or upgrade your PowerShell version: https://aka.ms/pscore6'
exit 2
}
function Package {
trap {
Write-Error $_
exit 2
}
$ScriptHome = $PSScriptRoot
$ProjectRoot = Resolve-Path -Path "$PSScriptRoot/../.."
$BuildSpecFile = "${ProjectRoot}/buildspec.json"
$UtilityFunctions = Get-ChildItem -Path $PSScriptRoot/utils.pwsh/*.ps1 -Recurse
foreach( $Utility in $UtilityFunctions ) {
Write-Debug "Loading $($Utility.FullName)"
. $Utility.FullName
}
$BuildSpec = Get-Content -Path ${BuildSpecFile} -Raw | ConvertFrom-Json
$ProductName = $BuildSpec.name
$OutputName = "${ProductName}-windows-${Target}"
Install-BuildDependencies -WingetFile "${ScriptHome}/.Wingetfile"
Log-Information "Packaging ${ProductName}..."
$RemoveArgs = @{
ErrorAction = 'SilentlyContinue'
Path = @(
"${ProjectRoot}/release/${ProductName}-*-windows-*.zip"
"${ProjectRoot}/release/${ProductName}-*-windows-*.exe"
)
}
Remove-Item @RemoveArgs
if ( ( $BuildInstaller ) ) {
if ( $Target -eq 'x86+x64' ) {
$IsccCandidates = Get-ChildItem -Recurse -Path '*.iss'
if ( $IsccCandidates.length -gt 0 ) {
$IsccFile = $IsccCandidates[0].FullName
} else {
$IsccFile = ''
}
} else {
$IsccFile = "${ProjectRoot}/build_${Target}/installer-Windows.generated.iss"
}
if ( ! ( Test-Path -Path $IsccFile ) ) {
throw 'InnoSetup install script not found. Run the build script or the CMake build and install procedures first.'
}
Log-Information 'Creating InnoSetup installer...'
Push-Location -Stack BuildTemp
Ensure-Location -Path "${ProjectRoot}/release"
Invoke-External iscc ${IsccFile} /O. /F"${OutputName}-Installer"
Pop-Location -Stack BuildTemp
}
$CompressArgs = @{
Path = (Get-ChildItem -Path "${ProjectRoot}/release" -Exclude "${OutputName}*.*")
CompressionLevel = 'Optimal'
DestinationPath = "${ProjectRoot}/release/${OutputName}.zip"
}
Compress-Archive -Force @CompressArgs
}
Package

13
.github/scripts/build-linux.sh vendored Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/sh
if ! type zsh > /dev/null 2>&1; then
echo ' => Installing script dependency Zsh.'
sudo apt-get -y update
sudo apt-get -y install zsh
fi
SCRIPT=$(readlink -f "${0}")
SCRIPT_DIR=$(dirname "${SCRIPT}")
zsh ${SCRIPT_DIR}/build-linux.zsh "${@}"

1
.github/scripts/build-linux.zsh vendored Symbolic link
View File

@@ -0,0 +1 @@
.build.zsh

1
.github/scripts/build-macos.zsh vendored Symbolic link
View File

@@ -0,0 +1 @@
.build.zsh

53
.github/scripts/check-cmake.sh vendored Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
set -o errexit
set -o pipefail
if [ ${#} -eq 1 -a "${1}" = "VERBOSE" ]; then
VERBOSITY="-l debug"
else
VERBOSITY=""
fi
if [ "${CI}" ]; then
MODE="--check"
else
MODE="-i"
fi
# Runs the formatter in parallel on the code base.
# Return codes:
# - 1 there are files to be formatted
# - 0 everything looks fine
# Get CPU count
OS=$(uname)
NPROC=1
if [[ ${OS} = "Linux" ]] ; then
NPROC=$(nproc)
elif [[ ${OS} = "Darwin" ]] ; then
NPROC=$(sysctl -n hw.physicalcpu)
fi
# Discover clang-format
if ! type cmake-format 2> /dev/null ; then
echo "Required cmake-format not found"
exit 1
fi
find . -type d \( \
-path ./\*build -o \
-path ./deps/jansson -o \
-path ./plugins/decklink/\*/decklink-sdk -o \
-path ./plugins/enc-amf -o \
-path ./plugins/mac-syphon/syphon-framework -o \
-path ./plugins/obs-outputs/ftl-sdk -o \
-path ./plugins/obs-vst -o \
-path ./plugins/obs-browser -o \
-path ./plugins/win-dshow/libdshowcapture -o \
-path ./plugins/obs-websocket/deps -o \
-path ./deps \
\) -prune -false -type f -o \
-name 'CMakeLists.txt' -or \
-name '*.cmake' \
| xargs -L10 -P ${NPROC} cmake-format ${MODE} ${VERBOSITY}

60
.github/scripts/check-format.sh vendored Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env bash
# Original source https://github.com/Project-OSRM/osrm-backend/blob/master/scripts/format.sh
set -o errexit
set -o pipefail
set -o nounset
if [ ${#} -eq 1 ]; then
VERBOSITY="--verbose"
else
VERBOSITY=""
fi
# Runs the Clang Formatter in parallel on the code base.
# Return codes:
# - 1 there are files to be formatted
# - 0 everything looks fine
# Get CPU count
OS=$(uname)
NPROC=1
if [[ ${OS} = "Linux" ]] ; then
NPROC=$(nproc)
elif [[ ${OS} = "Darwin" ]] ; then
NPROC=$(sysctl -n hw.physicalcpu)
fi
# Discover clang-format
if type clang-format-13 2> /dev/null ; then
CLANG_FORMAT=clang-format-13
elif type clang-format 2> /dev/null ; then
# Clang format found, but need to check version
CLANG_FORMAT=clang-format
V=$(clang-format --version)
if [[ $V != *"version 13.0"* ]]; then
echo "clang-format is not 13.0 (returned ${V})"
exit 1
fi
else
echo "No appropriate clang-format found (expected clang-format-13.0.0, or clang-format)"
exit 1
fi
find . -type d \( \
-path ./\*build -o \
-path ./cmake -o \
-path ./plugins/decklink/\*/decklink-sdk -o \
-path ./plugins/enc-amf -o \
-path ./plugins/mac-syphon/syphon-framework -o \
-path ./plugins/obs-outputs/ftl-sdk -o \
-path ./plugins/obs-websocket/deps -o \
-path ./deps \
\) -prune -false -type f -o \
-name '*.h' -or \
-name '*.hpp' -or \
-name '*.m' -or \
-name '*.mm' -or \
-name '*.c' -or \
-name '*.cpp' \
| xargs -L100 -P ${NPROC} "${CLANG_FORMAT}" ${VERBOSITY} -i -style=file -fallback-style=none

13
.github/scripts/package-linux.sh vendored Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/sh
if ! type zsh > /dev/null 2>&1; then
echo ' => Installing script dependency Zsh.'
sudo apt-get update
sudo apt-get install zsh
fi
SCRIPT=$(readlink -f "${0}")
SCRIPT_DIR=$(dirname "${SCRIPT}")
zsh ${SCRIPT_DIR}/package-linux.zsh "${@}"

1
.github/scripts/package-linux.zsh vendored Symbolic link
View File

@@ -0,0 +1 @@
.package.zsh

1
.github/scripts/package-macos.zsh vendored Symbolic link
View File

@@ -0,0 +1 @@
.package.zsh

View File

@@ -0,0 +1,25 @@
function Check-Git {
<#
.SYNOPSIS
Ensures available git executable on host system.
.DESCRIPTION
Checks whether a git command is available on the host system. If none is found,
Git is installed via winget.
.EXAMPLE
Check-Git
#>
if ( ! ( Test-Path function:Log-Info ) ) {
. $PSScriptRoot/Logger.ps1
}
Log-Information 'Checking for Git executable...'
if ( ! ( Get-Command git ) ) {
Log-Warning 'No Git executable found. Will try to install via winget.'
winget install git
} else {
Log-Debug "Git found at $(Get-Command git)."
Log-Status "Git found."
}
}

View File

@@ -0,0 +1,29 @@
function Ensure-Location {
<#
.SYNOPSIS
Ensures current location to be set to specified directory.
.DESCRIPTION
If specified directory exists, switch to it. Otherwise create it,
then switch.
.EXAMPLE
Ensure-Location "My-Directory"
Ensure-Location -Path "Path-To-My-Directory"
#>
param(
[Parameter(Mandatory)]
[string] $Path
)
if ( ! ( Test-Path $Path ) ) {
$_Params = @{
ItemType = "Directory"
Path = ${Path}
ErrorAction = "SilentlyContinue"
}
New-Item @_Params | Set-Location
} else {
Set-Location -Path ${Path}
}
}

View File

@@ -0,0 +1,70 @@
function Expand-ArchiveExt {
<#
.SYNOPSIS
Expands archive files.
.DESCRIPTION
Allows extraction of zip, 7z, gz, and xz archives.
Requires tar and 7-zip to be available on the system.
Archives ending with .zip but created using LZMA compression are
expanded using 7-zip as a fallback.
.EXAMPLE
Expand-ArchiveExt -Path <Path-To-Your-Archive>
Expand-ArchiveExt -Path <Path-To-Your-Archive> -DestinationPath <Expansion-Path>
#>
param(
[Parameter(Mandatory)]
[string] $Path,
[string] $DestinationPath = [System.IO.Path]::GetFileNameWithoutExtension($Path),
[switch] $Force
)
switch ( [System.IO.Path]::GetExtension($Path) ) {
.zip {
try {
Expand-Archive -Path $Path -DestinationPath $DestinationPath -Force:$Force
} catch {
if ( Get-Command 7z ) {
Invoke-External 7z x -y $Path "-o${DestinationPath}"
} else {
throw "Fallback utility 7-zip not found. Please install 7-zip first."
}
}
break
}
{ ( $_ -eq ".7z" ) -or ( $_ -eq ".exe" ) } {
if ( Get-Command 7z ) {
Invoke-External 7z x -y $Path "-o${DestinationPath}"
} else {
throw "Extraction utility 7-zip not found. Please install 7-zip first."
}
break
}
.gz {
try {
Invoke-External tar -x -o $DestinationPath -f $Path
} catch {
if ( Get-Command 7z ) {
Invoke-External 7z x -y $Path "-o${DestinationPath}"
} else {
throw "Fallback utility 7-zip not found. Please install 7-zip first."
}
}
break
}
.xz {
try {
Invoke-External tar -x -o $DestinationPath -f $Path
} catch {
if ( Get-Command 7z ) {
Invoke-External 7z x -y $Path "-o${DestinationPath}"
} else {
throw "Fallback utility 7-zip not found. Please install 7-zip first."
}
}
}
default {
throw "Unsupported archive extension provided."
}
}
}

View File

@@ -0,0 +1,60 @@
function Install-BuildDependencies {
<#
.SYNOPSIS
Installs required build dependencies.
.DESCRIPTION
Additional packages might be needed for successful builds. This module contains additional
dependencies available for installation via winget and, if possible, adds their locations
to the environment path for future invocation.
.EXAMPLE
Install-BuildDependencies
#>
param(
[string] $WingetFile = "$PSScriptRoot/.Wingetfile"
)
if ( ! ( Test-Path function:Log-Warning ) ) {
. $PSScriptRoot/Logger.ps1
}
$Host64Bit = [System.Environment]::Is64BitOperatingSystem
$Paths = $Env:Path -split [System.IO.Path]::PathSeparator
$WingetOptions = @('install', '--accept-package-agreements', '--accept-source-agreements')
if ( $script:Quiet ) {
$WingetOptions += '--silent'
}
Get-Content $WingetFile | ForEach-Object {
$_, $Package, $_, $Path, $_, $Binary = ([regex]::Split($_, " (?=(?:[^']|'[^']*')*$)")) -replace ',', '' -replace "'",''
(${Env:ProgramFiles(x86)}, $Env:ProgramFiles) | ForEach-Object {
$Prefix = $_
$FullPath = "${Prefix}\${Path}"
if ( ( Test-Path $FullPath ) -and ! ( $Paths -contains $FullPath ) ) {
$Paths += $FullPath
$Env:Path = $Paths -join [System.IO.Path]::PathSeparator
}
}
Log-Debug "Checking for command ${Binary}"
$Found = Get-Command -ErrorAction SilentlyContinue $Binary
if ( $Found ) {
Log-Status "Found dependency ${Binary} as $($Found.Source)"
} else {
Log-Status "Installing package ${Package}"
try {
$Params = $WingetOptions + $Package
winget @Params
} catch {
throw "Error while installing winget package ${Package}: $_"
}
}
}
}

View File

@@ -0,0 +1,40 @@
function Invoke-External {
<#
.SYNOPSIS
Invokes a non-PowerShell command.
.DESCRIPTION
Runs a non-PowerShell command, and captures its return code.
Throws an exception if the command returns non-zero.
.EXAMPLE
Invoke-External 7z x $MyArchive
#>
if ( $args.Count -eq 0 ) {
throw 'Invoke-External called without arguments.'
}
if ( ! ( Test-Path function:Log-Information ) ) {
. $PSScriptRoot/Logger.ps1
}
$Command = $args[0]
$CommandArgs = @()
if ( $args.Count -gt 1) {
$CommandArgs = $args[1..($args.Count - 1)]
}
$_EAP = $ErrorActionPreference
$ErrorActionPreference = "Continue"
Log-Debug "Invoke-External: ${Command} ${CommandArgs}"
& $command $commandArgs
$Result = $LASTEXITCODE
$ErrorActionPreference = $_EAP
if ( $Result -ne 0 ) {
throw "${Command} ${CommandArgs} exited with non-zero code ${Result}."
}
}

View File

@@ -0,0 +1,117 @@
function Set-GitConfig {
<#
.SYNOPSIS
Sets a git config value.
.DESCRIPTION
Allows setting single or multiple config values in a PowerShell-friendly fashion.
.EXAMPLE
Set-GitConfig advice.detachedHead false
#>
if ( $args.Count -lt 2 ) {
throw 'Set-GitConfig called without required arguments <OPTION> <VALUE>.'
}
Invoke-External git config @args
}
function Invoke-GitCheckout {
<#
.SYNOPSIS
Checks out a specified git repository.
.DESCRIPTION
Wraps the git executable with PowerShell syntax to check out
a specified Git repository with a given commit hash and branch,
or a GitHub pull request ID.
.EXAMPLE
Invoke-GitCheckout -Uri "My-Repo-Uri" -Commit "My-Commit-Hash"
Invoke-GitCheckout -Uri "My-Repo-Uri" -Commit "My-Commit-Hash" -Branch "main"
Invoke-GitCheckout -Uri "My-Repo-Uri" -Commit "My-Commit-Hash" -PullRequest 250
#>
param(
[Parameter(Mandatory)]
[string] $Uri,
[Parameter(Mandatory)]
[string] $Commit,
[string] $Path,
[string] $Branch = "master",
[string] $PullRequest
)
if ( ! ( $Uri -like "*github.com*" ) -and ( $PullRequest -ne "" ) ) {
throw 'Fetching pull requests is only supported with GitHub-based repositories.'
}
if ( ! ( Test-Path function:Log-Information ) ) {
. $PSScriptRoot/Logger.ps1
}
if ( ! ( Test-Path function:Invoke-External ) ) {
. $PSScriptRoot/Invoke-External.ps1
}
$RepositoryName = [System.IO.Path]::GetFileNameWithoutExtension($Uri)
if ( $Path -eq "" ) {
$Path = "$(Get-Location | Convert-Path)\${RepositoryName}"
}
Push-Location -Stack GitCheckoutTemp
if ( Test-Path $Path/.git ) {
Write-Information "Repository ${RepositoryName} found in ${Path}"
Set-Location $Path
Set-GitConfig advice.detachedHead false
Set-GitConfig remote.origin.url $Uri
Set-GitConfig remote.origin.tapOpt --no-tags
$Ref = "+refs/heads/{0}:refs/remotes/origin/{0}" -f $Branch
Set-GitConfig --replace-all remote.origin.fetch $Ref
if ( $PullRequest -ne "" ) {
try {
Invoke-External git show-ref --quiet --verify refs/heads/pr-$PullRequest
} catch {
Invoke-External git fetch origin $("pull/{0}/head:pull-{0}" -f $PullRequest)
} finally {
Invoke-External git checkout -f "pull-${PullRequest}"
}
}
try {
$null = Invoke-External git rev-parse -q --verify "${Commit}^{commit}"
} catch {
Invoke-External git fetch origin
}
Invoke-External git checkout -f $Commit -- | Log-Information
} else {
Invoke-External git clone $Uri $Path
Set-Location $Path
Set-GitConfig advice.detachedHead false
if ( $PullRequest -ne "" ) {
$Ref = "pull/{0}/head:pull-{0}" -f $PullRequest
$Branch = "pull-${PullRequest}"
Invoke-External git fetch origin $Ref
Invoke-External git checkout $Branch
}
Invoke-External git checkout -f $Commit
}
Log-Information "Checked out commit ${Commit} on branch ${Branch}"
if ( Test-Path ${Path}/.gitmodules ) {
Invoke-External git submodule foreach --recursive git submodule sync
Invoke-External git submodule update --init --recursive
}
Pop-Location -Stack GitCheckoutTemp
}

123
.github/scripts/utils.pwsh/Logger.ps1 vendored Normal file
View File

@@ -0,0 +1,123 @@
function Log-Debug {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Debug $m
}
}
}
function Log-Verbose {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Verbose $m
}
}
}
function Log-Warning {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Warning $m
}
}
}
function Log-Error {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Error $m
}
}
}
function Log-Information {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
if ( ! ( $script:Quiet ) ) {
$StageName = $( if ( $script:StageName -ne $null ) { $script:StageName } else { '' })
$Icon = ' =>'
foreach($m in $Message) {
Write-Host -NoNewLine -ForegroundColor Blue " ${StageName} $($Icon.PadRight(5)) "
Write-Host "${m}"
}
}
}
}
function Log-Status {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
if ( ! ( $script:Quiet ) ) {
$StageName = $( if ( $StageName -ne $null ) { $StageName } else { '' })
$Icon = ' >'
foreach($m in $Message) {
Write-Host -NoNewLine -ForegroundColor Green " ${StageName} $($Icon.PadRight(5)) "
Write-Host "${m}"
}
}
}
}
function Log-Output {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
if ( ! ( $script:Quiet ) ) {
$StageName = $( if ( $script:StageName -ne $null ) { $script:StageName } else { '' })
$Icon = ''
foreach($m in $Message) {
Write-Output " ${StageName} $($Icon.PadRight(5)) ${m}"
}
}
}
}
$Columns = (Get-Host).UI.RawUI.WindowSize.Width - 5

View File

@@ -0,0 +1,103 @@
function Setup-Host {
if ( ! ( Test-Path function:Log-Output ) ) {
. $PSScriptRoot/Logger.ps1
}
if ( ! ( Test-Path function:Ensure-Location ) ) {
. $PSScriptRoot/Ensure-Location.ps1
}
if ( ! ( Test-Path function:Install-BuildDependencies ) ) {
. $PSScriptRoot/Install-BuildDependencies.ps1
}
if ( ! ( Test-Path function:Expand-ArchiveExt ) ) {
. $PSScriptRoot/Expand-ArchiveExt.ps1
}
Install-BuildDependencies -WingetFile "${ScriptHome}/.Wingetfile"
if ( $script:Target -eq '' ) { $script:Target = $script:HostArchitecture }
$script:QtVersion = $BuildSpec.platformConfig."windows-${script:Target}".qtVersion
$script:VisualStudioVersion = $BuildSpec.platformConfig."windows-${script:Target}".visualStudio
$script:PlatformSDK = $BuildSpec.platformConfig."windows-${script:Target}".platformSDK
if ( ! ( ( $script:SkipAll ) -or ( $script:SkipDeps ) ) ) {
('prebuilt', "qt${script:QtVersion}") | ForEach-Object {
$_Dependency = $_
$_Version = $BuildSpec.dependencies."${_Dependency}".version
$_BaseUrl = $BuildSpec.dependencies."${_Dependency}".baseUrl
$_Label = $BuildSpec.dependencies."${_Dependency}".label
$_Hash = $BuildSpec.dependencies."${_Dependency}".hashes."windows-${script:Target}"
if ( $BuildSpec.dependencies."${_Dependency}".PSobject.Properties.Name -contains "pdb-hashes" ) {
$_PdbHash = $BuildSpec.dependencies."${_Dependency}".'pdb-hashes'."$windows-${script:Target}"
}
if ( $_Version -eq '' ) {
throw "No ${_Dependency} spec found in ${script:BuildSpecFile}."
}
Log-Information "Setting up ${_Label}..."
Push-Location -Stack BuildTemp
Ensure-Location -Path "$(Resolve-Path -Path "${ProjectRoot}/..")/obs-build-dependencies"
switch -wildcard ( $_Dependency ) {
prebuilt {
$_Filename = "windows-deps-${_Version}-${script:Target}.zip"
$_Uri = "${_BaseUrl}/${_Version}/${_Filename}"
$_Target = "plugin-deps-${_Version}-qt${script:QtVersion}-${script:Target}"
$script:DepsVersion = ${_Version}
}
"qt*" {
$_Filename = "windows-deps-qt${script:QtVersion}-${_Version}-${script:Target}.zip"
$_Uri = "${_BaseUrl}/${_Version}/${_Filename}"
$_Target = "plugin-deps-${_Version}-qt${script:QtVersion}-${script:Target}"
}
}
if ( ! ( Test-Path -Path $_Filename ) ) {
$Params = @{
UserAgent = 'NativeHost'
Uri = $_Uri
OutFile = $_Filename
UseBasicParsing = $true
ErrorAction = 'Stop'
}
Invoke-WebRequest @Params
Log-Status "Downloaded ${_Label} for ${script:Target}."
} else {
Log-Status "Found downloaded ${_Label}."
}
$_FileHash = Get-FileHash -Path $_Filename -Algorithm SHA256
if ( $_FileHash.Hash.ToLower() -ne $_Hash ) {
throw "Checksum of downloaded ${_Label} does not match specification. Expected '${_Hash}', 'found $(${_FileHash}.Hash.ToLower())'"
}
Log-Status "Checksum of downloaded ${_Label} matches."
if ( ! ( ( $script:SkipAll ) -or ( $script:SkipUnpack ) ) ) {
Push-Location -Stack BuildTemp
Ensure-Location -Path $_Target
Expand-ArchiveExt -Path "../${_Filename}" -DestinationPath . -Force
Pop-Location -Stack BuildTemp
}
Pop-Location -Stack BuildTemp
}
}
}
function Get-HostArchitecture {
$Host64Bit = [System.Environment]::Is64BitOperatingSystem
$HostArchitecture = ('x86', 'x64')[$Host64Bit]
return $HostArchitecture
}
$script:HostArchitecture = Get-HostArchitecture

View File

@@ -0,0 +1,84 @@
function Setup-Obs {
if ( ! ( Test-Path function:Log-Output ) ) {
. $PSScriptRoot/Logger.ps1
}
if ( ! ( Test-Path function:Check-Git ) ) {
. $PSScriptRoot/Check-Git.ps1
}
Check-Git
if ( ! ( Test-Path function:Ensure-Location ) ) {
. $PSScriptRoot/Ensure-Location.ps1
}
if ( ! ( Test-Path function:Invoke-GitCheckout ) ) {
. $PSScriptRoot/Invoke-GitCheckout.ps1
}
if ( ! ( Test-Path function:Invoke-External ) ) {
. $PSScriptRoot/Invoke-External.ps1
}
Log-Information 'Setting up OBS Studio...'
$ObsVersion = $BuildSpec.dependencies.'obs-studio'.version
$ObsRepository = $BuildSpec.dependencies.'obs-studio'.repository
$ObsBranch = $BuildSpec.dependencies.'obs-studio'.branch
$ObsHash = $BuildSpec.dependencies.'obs-studio'.hash
if ( $ObsVersion -eq '' ) {
throw 'No obs-studio version found in buildspec.json.'
}
Push-Location -Stack BuildTemp
Ensure-Location -Path "$(Resolve-Path -Path "${ProjectRoot}/../")/obs-studio"
if ( ! ( ( $script:SkipAll ) -or ( $script:SkipUnpack ) ) ) {
Invoke-GitCheckout -Uri $ObsRepository -Commit $ObsHash -Path . -Branch $ObsBranch
}
if ( ! ( ( $script:SkipAll ) -or ( $script:SkipBuild ) ) ) {
Log-Information 'Configuring OBS Studio...'
$NumProcessors = (Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors
if ( $NumProcessors -gt 1 ) {
$env:UseMultiToolTask = $true
$env:EnforceProcessCountAcrossBuilds = $true
}
$DepsPath = "plugin-deps-${script:DepsVersion}-qt${script:QtVersion}-${script:Target}"
$CmakeArgs = @(
'-G', $CmakeGenerator
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
"-DCMAKE_BUILD_TYPE=${script:Configuration}"
"-DQT_VERSION=${script:QtVersion}"
'-DENABLE_PLUGINS=OFF'
'-DENABLE_UI=OFF'
'-DENABLE_SCRIPTING=OFF'
"-DCMAKE_INSTALL_PREFIX:PATH=$(Resolve-Path -Path "${ProjectRoot}/../obs-build-dependencies/${DepsPath}")"
"-DCMAKE_PREFIX_PATH:PATH=$(Resolve-Path -Path "${ProjectRoot}/../obs-build-dependencies/${DepsPath}")"
)
Log-Debug "Attempting to configure OBS with CMake arguments: $($CmakeArgs | Out-String)"
Log-Information "Configuring OBS..."
Invoke-External cmake -S . -B plugin_build_${script:Target} @CmakeArgs
Log-Information 'Building libobs and obs-frontend-api...'
$CmakeArgs = @(
'--config', "$( if ( $script:Configuration -eq '' ) { 'RelWithDebInfo' } else { $script:Configuration })"
)
if ( $VerbosePreference -eq 'Continue' ) {
$CmakeArgs+=('--verbose')
}
Invoke-External cmake --build plugin_build_${script:Target} @CmakeArgs -t obs-frontend-api
Invoke-External cmake --install plugin_build_${script:Target} @CmakeArgs --component obs_libraries
}
Pop-Location -Stack BuildTemp
}

36
.github/scripts/utils.zsh/check_linux vendored Executable file
View File

@@ -0,0 +1,36 @@
autoload -Uz log_info log_status log_error log_debug log_warning
log_debug 'Checking for apt-get...'
if (( ! ${+commands[apt-get]} )) {
log_error 'No apt-get command found. Please install apt'
return 2
} else {
log_debug "Apt-get located at ${commands[apt-get]}"
}
local -a dependencies=("${(f)$(<${SCRIPT_HOME}/.Aptfile)}")
local -a install_list
local binary
for dependency (${dependencies}) {
local -a tokens=(${(s: :)dependency//(,|:|\')/})
if [[ ! ${tokens[1]} == 'package' ]] continue
if [[ ${#tokens} -gt 2 && ${tokens[3]} == 'bin' ]] {
binary=${tokens[4]}
} else {
binary=${tokens[2]}
}
if (( ! ${+commands[${binary}]} )) install_list+=(${tokens[2]})
}
local -a _quiet=('' '--quiet')
log_debug "List of dependencies to install: ${install_list}"
if (( ${#install_list} )) {
if (( ! ${+CI} )) log_warning 'Dependency installation via apt may require elevated privileges'
sudo apt-get -y install ${install_list} ${_quiet[(( (_loglevel == 0) + 1 ))]}
}

20
.github/scripts/utils.zsh/check_macos vendored Executable file
View File

@@ -0,0 +1,20 @@
autoload -Uz is-at-least log_info log_error log_status read_codesign
local macos_version=$(sw_vers -productVersion)
log_info 'Checking macOS version...'
if ! is-at-least 11.0 "${macos_version}"; then
log_error "Minimum required macOS version is 11.0, but running on macOS ${macos_version}"
return 2
else
log_status "macOS ${macos_version} is recent"
fi
log_info 'Checking for Homebrew...'
if (( ! ${+commands[brew]} )) {
log_error 'No Homebrew command found. Please install Homebrew (https://brew.sh)'
return 2
}
brew bundle --file "${SCRIPT_HOME}/.Brewfile"
rehash

52
.github/scripts/utils.zsh/check_packages vendored Executable file
View File

@@ -0,0 +1,52 @@
if (( ! ${+commands[packagesbuild]} )) {
autoload -Uz log_info log_status mkcd
if (( ! ${+commands[curl]} )) {
log_error 'curl not found. Please install curl.'
return 2
}
if (( ! ${+project_root} )) {
log_error "'project_root' not set. Please set before running ${0}."
return 2
}
local -a curl_opts=()
if (( ! ${+CI} )) {
curl_opts+=(--progress-bar)
} else {
curl_opts+=(--show-error --silent)
}
curl_opts+=(--location -O ${@})
log_info 'Installing Packages.app...'
pushd
mkcd ${project_root:h}/obs-build-dependencies
local packages_url='http://s.sudre.free.fr/Software/files/Packages.dmg'
local packages_hash='6afdd25386295974dad8f078b8f1e41cabebd08e72d970bf92f707c7e48b16c9'
if [[ ! -f Packages.dmg ]] {
log_status 'Download Packages.app'
curl ${curl_opts} ${packages_url}
}
local image_checksum
read -r image_checksum _ <<< "$(sha256sum Packages.dmg)"
if [[ ${packages_hash} != ${image_checksum} ]] {
log_error "Checksum mismatch of Packages.app download.
Expected : ${packages_hash}
Actual : ${image_checksum}"
return 2
}
hdiutil attach -noverify Packages.dmg &> /dev/null && log_status 'Packages.dmg image mounted.'
log_info 'Installing Packages.app...'
packages_volume=$(hdiutil info -plist | grep '<string>/Volumes/Packages' | sed 's/.*<string>\(\/Volumes\/[^<]*\)<\/string>/\1/')
sudo installer -pkg "${packages_volume}/packages/Packages.pkg" -target / && rehash
hdiutil detach ${packages_volume} &> /dev/null && log_status 'Packages.dmg image unmounted.'
}

3
.github/scripts/utils.zsh/log_debug vendored Executable file
View File

@@ -0,0 +1,3 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 2 )) print -PR -e -- "%F{220}DEBUG: ${@}%f"

3
.github/scripts/utils.zsh/log_error vendored Executable file
View File

@@ -0,0 +1,3 @@
local icon=' ✖︎ '
print -u2 -PR "%F{1} ${icon} %f ${@}"

7
.github/scripts/utils.zsh/log_info vendored Executable file
View File

@@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=' =>'
print -PR "%F{4} ${(r:5:)icon}%f %B${@}%b"
}

7
.github/scripts/utils.zsh/log_output vendored Executable file
View File

@@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=''
print -PR " ${(r:5:)icon} ${@}"
}

7
.github/scripts/utils.zsh/log_status vendored Executable file
View File

@@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=' >'
print -PR "%F{2} ${(r:5:)icon}%f ${@}"
}

5
.github/scripts/utils.zsh/log_warning vendored Executable file
View File

@@ -0,0 +1,5 @@
if (( _loglevel > 0 )) {
local icon=' =>'
print -PR "%F{3} ${(r:5:)icon} ${@}%f"
}

1
.github/scripts/utils.zsh/mkcd vendored Executable file
View File

@@ -0,0 +1 @@
[[ -n ${1} ]] && mkdir -p ${1} && builtin cd ${1}

7
.github/scripts/utils.zsh/read_codesign vendored Executable file
View File

@@ -0,0 +1,7 @@
autoload -Uz log_info
if (( ! ${+CODESIGN_IDENT} )) {
typeset -g CODESIGN_IDENT
log_info 'Setting up identity for application codesigning...'
read CODESIGN_IDENT'?Apple Developer Application ID: '
}

View File

@@ -0,0 +1,7 @@
autoload -Uz log_info
if (( ! ${+CODESIGN_IDENT_INSTALLER} )) {
typeset -g CODESIGN_IDENT_INSTALLER
log_info 'Setting up identity for installer package codesigning...'
read CODESIGN_IDENT_INSTALLER'?Apple Developer Installer ID: '
}

33
.github/scripts/utils.zsh/read_codesign_pass vendored Executable file
View File

@@ -0,0 +1,33 @@
##############################################################################
# Apple Developer credentials necessary:
#
# + Signing for distribution and notarization require an active Apple
# Developer membership
# + An Apple Development identity is needed for code signing
# (i.e. 'Apple Development: YOUR APPLE ID (PROVIDER)')
# + Your Apple developer ID is needed for notarization
# + An app-specific password is necessary for notarization from CLI
# + This password will be stored in your macOS keychain under the identifier
# 'OBS-Codesign-Password'with access Apple's 'altool' only.
##############################################################################
autoload -Uz read_codesign read_codesign_user log_info
if (( ! ${+CODESIGN_IDENT} )) {
read_codesign
}
local codesign_ident_short=$(print "${CODESIGN_IDENT}" | /usr/bin/sed -En 's/.+\((.+)\)/\1/p')
if (( ! ${+CODESIGN_IDENT_USER} )) {
read_codesign_user
}
log_info 'Setting up password for notarization keychain...'
if (( ! ${+CODESIGN_IDENT_PASS} )) {
read -s CODESIGN_IDENT_PASS'?Apple Developer ID password: '
}
print ''
log_info 'Setting up notarization keychain...'
xcrun notarytool store-credentials 'OBS-Codesign-Password' --apple-id "${CODESIGN_IDENT_USER}" --team-id "${codesign_ident_short}" --password "${CODESIGN_IDENT_PASS}"

View File

@@ -0,0 +1,7 @@
autoload -Uz log_info
if (( ! ${+CODESIGN_IDENT_USER} )) {
typeset -g CODESIGN_IDENT_USER
log_info 'Setting up developer id for codesigning...'
read CODESIGN_IDENT_USER'?Apple Developer ID: '
}

17
.github/scripts/utils.zsh/set_loglevel vendored Executable file
View File

@@ -0,0 +1,17 @@
autoload -Uz log_debug log_error
local -r _usage="Usage: %B${0}%b <loglevel>
Set log level, following levels are supported: 0 (quiet), 1 (normal), 2 (verbose), 3 (debug)"
if (( ! # )); then
log_error 'Called without arguments.'
log_output ${_usage}
return 2
elif (( ${1} >= 4 )); then
log_error 'Called with loglevel > 3.'
log_output ${_usage}
fi
typeset -g -i -r _loglevel=${1}
log_debug "Log level set to '${1}'"

14
.github/scripts/utils.zsh/setup_ccache vendored Executable file
View File

@@ -0,0 +1,14 @@
autoload -Uz log_debug log_warning
if (( ${+commands[ccache]} )) {
log_debug "Found ccache at ${commands[ccache]}"
if (( ${+CI} )) {
ccache --set-config=cache_dir="${GITHUB_WORKSPACE:-${HOME}}/.ccache"
ccache --set-config=max_size="${CCACHE_SIZE:-500M}"
ccache --set-config=compression=true
ccache -z > /dev/null
}
} else {
log_warning "No ccache found on the system"
}

71
.github/scripts/utils.zsh/setup_linux vendored Executable file
View File

@@ -0,0 +1,71 @@
autoload -Uz log_error log_status log_info mkcd
if (( ! ${+project_root} )) {
log_error "'project_root' not set. Please set before running ${0}."
return 2
}
if (( ! ${+target} )) {
log_error "'target' not set. Please set before running ${0}."
return 2
}
pushd ${project_root}
typeset -g QT_VERSION
read -r QT_VERSION <<< \
"$(jq -r --arg target "${target}" \
'.platformConfig[$target] | { qtVersion } | join(" ")' \
${project_root}/buildspec.json)"
if (( ! (${skips[(Ie)all]} + ${skips[(Ie)deps]}) )) {
log_info 'Installing obs build dependencies...'
sudo apt-get install -y \
build-essential \
libcurl4-openssl-dev \
libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavutil-dev \
libswresample-dev libswscale-dev \
libjansson-dev \
libx11-xcb-dev \
libgles2-mesa-dev \
libwayland-dev \
libpulse-dev
log_info 'Installing obs plugin dependencies...'
sudo apt-get install -y \
libxtst-dev \
libxss-dev \
libopencv-dev \
libtesseract-dev \
libprocps-dev
local -a _qt_packages=()
if (( QT_VERSION == 5 )) {
_qt_packages+=(
qtbase5-dev
libqt5svg5-dev
qtbase5-private-dev
libqt5x11extras5-dev
)
} elif (( QT_VERSION == 6 )) {
_qt_packages+=(
qt6-base-dev
libqt6svg6-dev
qt6-base-private-dev
)
} else {
log_error "Unsupported Qt version '${QT_VERSION}' specified."
return 2
}
sudo apt-get install -y ${_qt_packages}
}
local deps_version
read -r deps_version <<< \
"$(jq -r '.dependencies.prebuilt.version' ${buildspec_file})"
typeset -g OBS_DEPS_VERSION=${deps_version}

127
.github/scripts/utils.zsh/setup_macos vendored Executable file
View File

@@ -0,0 +1,127 @@
autoload -Uz log_error log_status log_info mkcd
if (( ! ${+commands[curl]} )) {
log_error 'curl not found. Please install curl.'
return 2
}
if (( ! ${+commands[jq]} )) {
log_error 'jq not found. Please install jq.'
return 2
}
if (( ! ${+project_root} )) {
log_error "'project_root' not set. Please set before running ${0}."
return 2
}
if (( ! ${+target} )) {
log_error "'target' not set. Please set before running ${0}."
return 2
}
local -a curl_opts=()
if (( ! ${+CI} )) {
curl_opts+=(--progress-bar)
} else {
curl_opts+=(--show-error --silent)
}
curl_opts+=(--location -O ${@})
pushd ${project_root}
local _qt_version
local _deployment_target
read -r _qt_version _deployment_target <<< \
"$(jq -r --arg target "${target}" \
'.platformConfig[$target] | { qtVersion, deploymentTarget } | join (" ")' \
${buildspec_file})"
typeset -g QT_VERSION=${_qt_version}
typeset -g DEPLOYMENT_TARGET=${_deployment_target}
if (( ! (${skips[(Ie)all]} + ${skips[(Ie)deps]}) )) {
mkdir -p ${project_root:h}/obs-build-dependencies
local dependency
local deps_version
local deps_baseurl
local deps_label
local deps_hash
local _filename
local _url
local _target
local artifact_checksum
for dependency ('prebuilt' "qt${QT_VERSION}") {
IFS=';' read -r deps_version deps_baseurl deps_label deps_hash <<< \
"$(jq -r --arg dependency "${dependency}" --arg target "${target}" \
'.dependencies[$dependency] | {version, baseUrl, "label", "hash": .hashes[$target]} | join(";")' \
${buildspec_file})"
if [[ -z "${deps_version}" ]] {
log_error "No ${dependency} spec found in ${buildspec_file}."
return 2
}
log_info "Setting up ${deps_label}..."
pushd ${project_root:h}/obs-build-dependencies
case ${dependency} {
prebuilt)
_filename="macos-deps-${deps_version}-${target##*-}.tar.xz"
_url="${deps_baseurl}/${deps_version}/${_filename}"
_target="plugin-deps-${deps_version}-qt${QT_VERSION}-${target##*-}"
typeset -g OBS_DEPS_VERSION=${deps_version}
;;
qt*)
if (( ${+CI} )) {
_filename="macos-deps-qt${QT_VERSION}-${deps_version}-universal.tar.xz"
deps_hash="$(jq -r --arg dependency "${dependency}" \
'.dependencies[$dependency].hashes["macos-universal"]' \
${buildspec_file})"
} else {
_filename="macos-deps-qt${QT_VERSION}-${deps_version}-${target##*-}.tar.xz"
}
_url="${deps_baseurl}/${deps_version}/${_filename}"
_target="plugin-deps-${deps_version}-qt${QT_VERSION}-${target##*-}"
;;
}
if [[ ! -f ${_filename} ]] {
log_debug "Running curl ${curl_opts} ${_url}"
curl ${curl_opts} ${_url} && \
log_status "Downloaded ${deps_label} for ${target}."
} else {
log_status "Found downloaded ${deps_label}"
}
read -r artifact_checksum _ <<< "$(sha256sum ${_filename})"
if [[ ${deps_hash} != ${artifact_checksum} ]] {
log_error "Checksum of downloaded ${deps_label} does not match specification.
Expected : ${deps_hash}
Actual : ${artifact_checksum}"
return 2
}
log_status "Checksum of downloaded ${deps_label} matches."
if (( ! (${skips[(Ie)all]} + ${skips[(Ie)unpack]}) )) {
mkdir -p ${_target} && pushd ${_target}
XZ_OPT=-T0 tar -xzf ../${_filename} && log_status "${deps_label} extracted."
popd
}
}
popd
pushd ${project_root:h}/obs-build-dependencies
xattr -r -d com.apple.quarantine *
log_status 'Removed quarantine flag from downloaded dependencies...'
popd
} else {
local deps_version
read -r deps_version <<< \
"$(jq -r '.dependencies.prebuilt.version' ${buildspec_file})"
typeset -g OBS_DEPS_VERSION=${deps_version}
}

122
.github/scripts/utils.zsh/setup_obs vendored Executable file
View File

@@ -0,0 +1,122 @@
autoload -Uz log_error log_info log_status
if (( ! ${+buildspec_file} )) {
log_error "'buildspec_file' not set. Please set before running ${0}."
return 2
}
if (( ! ${+commands[git]} )) {
log_error 'git not found. Please install git.'
return 2
}
if (( ! ${+commands[jq]} )) {
log_error 'jq not found. Please install jq.'
return 2
}
if (( ! ${+project_root} )) {
log_error "'project_root' not set. Please set before running ${0}."
return 2
}
if (( ! ${+target} )) {
log_error "'target' not set. Please set before running ${0}."
return 2
}
log_info 'Setting up OBS-Studio...'
local obs_version
local obs_repo
local obs_branch
local obs_hash
read -r obs_version obs_repo obs_branch obs_hash <<< \
"$(jq -r --arg key "obs-studio" \
'.dependencies[$key] | {version, repository, branch, hash} | join(" ")' \
${buildspec_file})"
if [[ -z ${obs_version} ]] {
log_error "No obs-studio version found in buildspec.json"
return 2
}
pushd
mkcd ${project_root:h}/obs-studio
if (( ! (${skips[(Ie)all]} + ${skips[(Ie)unpack]}) )) {
if [[ -d .git ]] {
git config advice.detachedHead false
git config remote.pluginbuild.url "${obs_repo:-https://github.com/obsproject/obs-studio.git}"
git config remote.pluginbuild.fetch "+refs/heads/${obs_branch:-master}:refs/remotes/origin/${obs_branch:-master}"
git rev-parse -q --verify "${obs_hash}^{commit}" > /dev/null || git fetch pluginbuild
git checkout ${obs_branch:-master} -B ${product_name}
git reset --hard "${obs_hash}"
log_status 'Found existing obs-studio repository.'
} else {
git clone "${obs_repo:-https://github.com/obsproject/obs-studio.git}" "${PWD}"
git config advice.detachedHead false
git checkout -f "${obs_hash}" --
git checkout ${obs_branch:-master} -b ${product_name}
log_status 'obs-studio checked out.'
}
git submodule foreach --recursive git submodule sync
git submodule update --init --recursive
}
if (( ! (${skips[(Ie)all]} + ${skips[(Ie)build]}) )) {
log_info 'Configuring obs-studio...'
local -a cmake_args=(
-DCMAKE_BUILD_TYPE=${BUILD_CONFIG:-Release}
-DQT_VERSION=${QT_VERSION}
-DENABLE_PLUGINS=OFF
-DENABLE_UI=OFF
-DENABLE_SCRIPTING=OFF
-DCMAKE_INSTALL_PREFIX="${project_root:h}/obs-build-dependencies/plugin-deps-${OBS_DEPS_VERSION}-qt${QT_VERSION}-${target##*-}"
-DCMAKE_PREFIX_PATH="${project_root:h}/obs-build-dependencies/plugin-deps-${OBS_DEPS_VERSION}-qt${QT_VERSION}-${target##*-}"
)
if (( _loglevel == 0 )) cmake_args+=(-Wno_deprecated -Wno-dev --log-level=ERROR)
if (( _loglevel > 2 )) cmake_args+=(--debug-output)
local num_procs
case ${target} {
macos-*)
autoload -Uz read_codesign
if (( ${+CODESIGN} )) {
read_codesign
}
cmake_args+=(
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
-DOBS_CODESIGN_LINKER=ON
-DOBS_BUNDLE_CODESIGN_IDENTITY="${CODESIGN_IDENT:--}"
)
num_procs=$(( $(sysctl -n hw.ncpu) + 1 ))
;;
linux-*)
cmake_args+=(
-DENABLE_PIPEWIRE=OFF
)
num_procs=$(( $(nproc) + 1 ))
;;
}
log_debug "Attempting to configure OBS with CMake arguments: ${cmake_args}"
cmake -S . -B plugin_build_${target##*-} -G ${generator} ${cmake_args}
log_info 'Building libobs and obs-frontend-api...'
local -a cmake_args=()
if (( _loglevel > 1 )) cmake_args+=(--verbose)
if [[ ${generator} == 'Unix Makefiles' ]] cmake_args+=(--parallel ${num_procs})
cmake --build plugin_build_${target##*-} --config ${BUILD_CONFIG:-Release} ${cmake_args} -t obs-frontend-api
cmake --install plugin_build_${target##*-} --config ${BUILD_CONFIG:-Release} --component obs_libraries ${cmake_args}
}
popd

56
.github/workflows/build-debian.yml vendored Normal file
View File

@@ -0,0 +1,56 @@
name: debian-build
on:
push:
paths-ignore:
- '**.md'
- 'data/locale/**'
branches:
- master
tags:
- '*'
pull_request:
paths-ignore:
- '**.md'
- 'data/locale/**'
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: "recursive"
- name: check_libobs_revision
run: |
sudo apt update
sudo apt install devscripts libobs-dev
mkdir source
cd source
dpkg -l libobs-dev | tr -s " "| grep libobs | cut -d" " -f3 > libobs.rev
- name: create_tarball
run: |
cd ..
tar --exclude=.git -cvzf obs-scene-switcher_0.1+testonly.orig.tar.gz SceneSwitcher
- name: create_debian_dir
run: |
cp -a CI/linux/debian .
- name: install_dependencies
run: |
# devscripts and libobs-dev are needed but they were already installed
# from check_libobs_revision and install_frontend_header sections.
sudo apt update
sudo apt install cmake debhelper libcurl4-openssl-dev libxss-dev libxtst-dev qtbase5-dev libopencv-dev libprocps-dev
- name: build
run: |
debuild --no-lintian --no-sign
mv ../*.deb .
- name: Publish
if: success()
uses: actions/upload-artifact@v2.2.1
with:
name: "obs-scene-switcher.deb"
path: ${{ github.workspace }}/*.deb

View File

@@ -1,307 +0,0 @@
name: build obs plugin
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
PLUGIN_NAME: SceneSwitcher
LIB_NAME: advanced-scene-switcher
jobs:
macos64:
name: "macOS 64-bit"
runs-on: [macos-latest]
env:
QT_VERSION: '5.15.2'
MACOS_DEPS_VERSION: '2020-12-11'
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
with:
repository: obsproject/obs-studio
submodules: 'recursive'
- name: "Checkout plugin"
uses: actions/checkout@v2.3.4
with:
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
submodules: 'recursive'
- name: Fetch Git Tags
run: |
cd UI/frontend-plugins/${{ env.PLUGIN_NAME }}
git fetch --prune --tags --unshallow
- name: 'Install prerequisites (Homebrew)'
shell: bash
run: |
if [ -d /usr/local/opt/openssl@1.0.2t ]; then
brew uninstall openssl@1.0.2t
brew untap local/openssl
fi
if [ -d /usr/local/opt/python@2.7.17 ]; then
brew uninstall python@2.7.17
brew untap local/python2
fi
brew bundle --file ./CI/scripts/macos/Brewfile
- name: 'Install prerequisite: Pre-built dependencies'
if: steps.deps-cache.outputs.cache-hit != 'true'
shell: bash
run: |
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.MACOS_DEPS_VERSION }}/macos-deps-${{ env.MACOS_DEPS_VERSION }}.tar.gz
tar -xf ./macos-deps-${{ env.MACOS_DEPS_VERSION }}.tar.gz -C "/tmp"
- name: 'Install prerequisite: Pre-built dependency Qt'
if: steps.deps-qt-cache.outputs.cache-hit != 'true'
shell: bash
run: |
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.MACOS_DEPS_VERSION }}/macos-qt-${{ env.QT_VERSION }}-${{ env.MACOS_DEPS_VERSION }}.tar.gz
tar -xf ./macos-qt-${{ env.QT_VERSION }}-${{ env.MACOS_DEPS_VERSION }}.tar.gz -C "/tmp"
xattr -r -d com.apple.quarantine /tmp/obsdeps
- name: Configure
shell: bash
run: |
echo "add_subdirectory(${{ env.PLUGIN_NAME }})" >> UI/frontend-plugins/CMakeLists.txt
mkdir ./build
cd ./build
cmake -DBUILD_BROWSER=OFF -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DDISABLE_PYTHON=ON -DDepsPath="/tmp/obsdeps" -DQTDIR="/tmp/obsdeps" ..
cd -
- name: Build
shell: bash
run: |
set -e
cd ./build
make -j4
cd -
- name: 'Install prerequisite: Packages app'
if: success()
shell: bash
run: |
curl -L -O http://s.sudre.free.fr/Software/files/Packages.dmg
sudo hdiutil attach ./Packages.dmg
sudo installer -pkg /Volumes/Packages\ 1.2.9/Install\ Packages.pkg -target /
- name: Package
if: success()
shell: bash
run: |
cd UI/frontend-plugins/${{ env.PLUGIN_NAME }}
install_name_tool -change @rpath/libobs-frontend-api.dylib @executable_path/../Frameworks/libobs-frontend-api.dylib ../../../build/UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib ../../../build/UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
install_name_tool -change /tmp/obsdeps/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets ../../../build/UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
install_name_tool -change /tmp/obsdeps/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui ../../../build/UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
install_name_tool -change /tmp/obsdeps/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ../../../build/UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
FILE_DATE=$(date +%Y-%m-%d)
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-macos.pkg
echo "FILE_NAME=${FILE_NAME}" >> $GITHUB_ENV
packagesbuild ./CI/macos/${{ env.PLUGIN_NAME }}.pkgproj
cd -
mkdir ./nightly
mv UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.PLUGIN_NAME }}.pkg ./nightly/${FILE_NAME}
- name: Publish
if: success()
uses: actions/upload-artifact@v2.2.1
with:
name: '${{ env.FILE_NAME }}'
path: ./nightly/*.pkg
ubuntu64:
name: 'Linux/Ubuntu 64-bit'
runs-on: [ubuntu-18.04]
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
with:
repository: obsproject/obs-studio
submodules: 'recursive'
- name: "Checkout plugin"
uses: actions/checkout@v2.3.4
with:
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
submodules: 'recursive'
- name: Add plugin to obs cmake
shell: bash
run: echo "add_subdirectory(${{ env.PLUGIN_NAME }})" >> UI/frontend-plugins/CMakeLists.txt
- name: Fetch Git Tags
run: git fetch --prune --tags --unshallow
- name: Install prerequisites (Apt)
shell: bash
run: |
sudo dpkg --add-architecture amd64
sudo apt-get -qq update
sudo apt-get install -y \
build-essential \
checkinstall \
cmake \
libasound2-dev \
libavcodec-dev \
libavdevice-dev \
libavfilter-dev \
libavformat-dev \
libavutil-dev \
libcurl4-openssl-dev \
libfdk-aac-dev \
libfontconfig-dev \
libfreetype6-dev \
libgl1-mesa-dev \
libjack-jackd2-dev \
libjansson-dev \
libluajit-5.1-dev \
libpulse-dev \
libqt5x11extras5-dev \
libspeexdsp-dev \
libswresample-dev \
libswscale-dev \
libudev-dev \
libv4l-dev \
libva-dev \
libvlc-dev \
libx11-dev \
libx264-dev \
libxcb-randr0-dev \
libxcb-shm0-dev \
libxcb-xinerama0-dev \
libxcomposite-dev \
libxinerama-dev \
libxtst-dev \
libmbedtls-dev \
pkg-config \
python3-dev \
qtbase5-dev \
qtbase5-private-dev \
libqt5svg5-dev \
swig \
libxss-dev
- name: 'Configure'
shell: bash
run: |
mkdir ./build
cd ./build
cmake -DENABLE_PIPEWIRE=OFF -DUNIX_STRUCTURE=0 -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/obs-studio-portable" -DWITH_RTMPS=OFF -DBUILD_BROWSER=OFF ..
- name: 'Build'
shell: bash
working-directory: ${{ github.workspace }}/build
run: make -j4
- name: 'Package'
shell: bash
run: |
FILE_DATE=$(date +%Y-%m-%d)
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-linux64.tar.gz
echo "FILE_NAME=${FILE_NAME}" >> $GITHUB_ENV
mkdir -p ./${{ env.LIB_NAME }}/bin/64bit/
mv ./build/UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.LIB_NAME }}.so ./${{ env.LIB_NAME }}/bin/64bit/${{ env.LIB_NAME }}.so
mv ./UI/frontend-plugins/${{ env.PLUGIN_NAME }}/data ./${{ env.LIB_NAME }}/data
tar -cvzf "${FILE_NAME}" ${{ env.LIB_NAME }}
- name: 'Publish'
uses: actions/upload-artifact@v2.2.1
with:
name: '${{ env.FILE_NAME }}'
path: '*.tar.gz'
windows:
name: Windows
runs-on: [windows-latest]
env:
QT_VERSION: 5.10.1
CMAKE_GENERATOR: "Visual Studio 16 2019"
CMAKE_SYSTEM_VERSION: "10.0.18363.657"
WINDOWS_DEPS_VERSION: '2019'
steps:
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
- name: Checkout obs
uses: actions/checkout@v2.3.4
with:
repository: obsproject/obs-studio
submodules: 'recursive'
- name: Checkout plugin
uses: actions/checkout@v2.3.4
with:
path: UI/frontend-plugins/${{ env.PLUGIN_NAME}}
submodules: 'recursive'
- name: Add plugin to obs cmake
shell: cmd
run: echo add_subdirectory(${{ env.PLUGIN_NAME }}) >> UI/frontend-plugins/CMakeLists.txt
- name: Fetch Git Tags
run: git fetch --prune --tags --unshallow
- name: 'Install prerequisite: QT'
run: |
curl -kLO https://cdn-fastly.obsproject.com/downloads/Qt_${{ env.QT_VERSION }}.7z -f --retry 5 -C -
7z x Qt_${{ env.QT_VERSION }}.7z -o"${{ github.workspace }}/cmbuild/QT"
- name: 'Install prerequisite: Pre-built dependencies'
run: |
curl -kLO https://cdn-fastly.obsproject.com/downloads/dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -f --retry 5 -C -
7z x dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -o"${{ github.workspace }}/cmbuild/deps"
- name: Configure
run: |
mkdir ./package
mkdir ./build32
cd ./build32
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win32" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
cd ..
mkdir ./build64
cd ./build64
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win64" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017_64" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
- name: Build
run: |
msbuild /m /p:Configuration=RelWithDebInfo .\build32\obs-studio.sln
msbuild /m /p:Configuration=RelWithDebInfo .\build64\obs-studio.sln
- name: Package
if: success()
run: |
$env:FILE_DATE=(Get-Date -UFormat "%F")
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-windows"
echo "FILE_NAME=${env:FILE_NAME}" >> ${env:GITHUB_ENV}
robocopy .\build32\rundir\RelWithDebInfo\obs-plugins\32bit\ .\package\obs-plugins\32bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
robocopy .\build64\rundir\RelWithDebInfo\obs-plugins\64bit\ .\package\obs-plugins\64bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
robocopy .\build64\rundir\RelWithDebInfo\data\obs-plugins\${{ env.LIB_NAME }}\ .\package\data\obs-plugins\${{ env.LIB_NAME }}\ /E /XF .gitignore
exit 0
- name: Publish zip
if: success()
uses: actions/upload-artifact@v2.2.1
with:
name: '${{ env.FILE_NAME }}'
path: package/*
- name: "Package Installer (Prereqs)"
run: |
curl "-kL" "https://github.com/Xaymar/msvc-redist-helper/releases/download/0.1/msvc-redist-helper-64.exe" "-f" "--retry" "5" "-o" "msvc-redist-helper-64.exe"
curl "-kL" "https://github.com/Xaymar/msvc-redist-helper/releases/download/0.1/msvc-redist-helper-32.exe" "-f" "--retry" "5" "-o" "msvc-redist-helper-32.exe"
curl "-kL" "https://files.jrsoftware.org/is/6/innosetup-6.0.3.exe" "-f" "--retry" "5" "-o" "inno.exe"
.\inno.exe /VERYSILENT /SP- /SUPPRESSMSGBOXES /NORESTART
- name: "Package Installer (Compile)"
run: |
& 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' /Qp ".\build64\UI\frontend-plugins\${{ env.PLUGIN_NAME }}\CI\windows\setup.iss"
- name: Publish installer
if: success()
uses: actions/upload-artifact@v2.2.0
with:
name: '${{ env.FILE_NAME }}-installer'
path: build64/UI/frontend-plugins/SceneSwitcher/CI/windows/Output/*.exe
release:
needs: [macos64, ubuntu64, windows]
name: 'Create Release'
runs-on: [ubuntu-18.04]
steps:
- name: "Checkout plugin"
uses: actions/checkout@v2.3.4
with:
path: plugin/${{ env.PLUGIN_NAME }}
- name: Download artifacts
uses: actions/download-artifact@v2
with:
path: artifacts
- name: 'Package'
shell: bash
run: |
mkdir -p ${{ env.PLUGIN_NAME }}/Linux ${{ env.PLUGIN_NAME }}/MacOs ${{ env.PLUGIN_NAME }}/Windows
tar xf artifacts/${{ env.PLUGIN_NAME }}*-linux64.tar.gz/${{ env.PLUGIN_NAME }}*-linux64.tar.gz -C ${{ env.PLUGIN_NAME }}/Linux/
mv artifacts/${{ env.PLUGIN_NAME }}*-macos.pkg/${{ env.PLUGIN_NAME }}*-macos.pkg ${{ env.PLUGIN_NAME }}/MacOs/${{ env.PLUGIN_NAME }}.pkg
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows/* ${{ env.PLUGIN_NAME }}/Windows/
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows-installer/*.exe ${{ env.PLUGIN_NAME }}/Windows/
rm ${{ env.PLUGIN_NAME }}/Windows/obs-plugins/32bit/advanced-scene-switcher.pdb
rm ${{ env.PLUGIN_NAME }}/Windows/obs-plugins/64bit/advanced-scene-switcher.pdb
cp plugin/${{ env.PLUGIN_NAME }}/CI/release/README.txt ${{ env.PLUGIN_NAME }}/
FILE_NAME=${{ env.PLUGIN_NAME }}.zip
zip -r ${FILE_NAME} ${{ env.PLUGIN_NAME }}/
- name: Publish
if: success()
uses: actions/upload-artifact@v2.2.1
with:
name: "Release"
path: '*.zip'

View File

@@ -1,19 +0,0 @@
name: Clang Format Check
on: [push, pull_request]
jobs:
ubuntu64:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install clang format
run: |
sudo apt-get install -y clang-format-10
- name: Check the Formatting
run: |
./CI/formatcode.sh
./CI/check-format.sh

26
.github/workflows/locale-check.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Check locale
on:
push:
branches:
- master
tags:
- '*'
paths:
- 'data/locale/**'
pull_request:
branches:
- master
paths:
- 'data/locale/**'
jobs:
ubuntu64:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check locale files
run: |
python3 ./CI/checkLocale.py -p data/locale/

443
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,443 @@
name: Plugin Build
on:
push:
paths-ignore:
- '**.md'
branches:
- master
tags:
- '*'
pull_request:
paths-ignore:
- '**.md'
branches:
- master
env:
PLUGIN_NAME: SceneSwitcher
LIB_NAME: advanced-scene-switcher
jobs:
clang_check:
name: 01 - Code Format Check
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install clang-format
run: sudo apt-get install -y clang-format-13
- name: Run clang-format
run: ./.github/scripts/check-format.sh && ./.github/scripts/check-changes.sh
- name: Install cmake-format
run: sudo pip install cmakelang
- name: Run cmake-format
run: ./.github/scripts/check-cmake.sh
macos_build:
name: 02 - macOS
runs-on: macos-12
strategy:
fail-fast: true
matrix:
arch: [x86_64, arm64, universal]
if: always()
needs: [clang_check]
outputs:
commitHash: ${{ steps.setup.outputs.commitHash }}
env:
CODESIGN_IDENT: '-'
CODESIGN_IDENT_INSTALLER: ''
MACOSX_DEPLOYMENT_TARGET: '10.15'
defaults:
run:
shell: zsh {0}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
path: plugin
submodules: recursive
- name: Checkout obs-studio
uses: actions/checkout@v3
with:
repository: 'obsproject/obs-studio'
path: obs-studio
fetch-depth: 0
submodules: recursive
- name: Setup Environment
id: setup
working-directory: ${{ github.workspace }}/plugin
run: |
## SETUP ENVIRONMENT SCRIPT
print '::group::Clean Homebrew Environment'
typeset -a to_remove=()
for formula (speexdsp curl php) {
if [[ -d ${HOMEBREW_PREFIX}/opt/${formula} ]] to_remove+=(${formula})
}
if (( #to_remove > 0 )) brew uninstall --ignore-dependencies ${to_remove}
print '::endgroup::'
print '::group::Set up code signing'
if [[ '${{ secrets.MACOS_SIGNING_APPLICATION_IDENTITY }}' != '' && \
'${{ secrets.MACOS_SIGNING_INSTALLER_IDENTITY }}' != '' && \
'${{ secrets.MACOS_SIGNING_CERT }}' != '' ]] {
print 'haveCodesignIdent=true' >> $GITHUB_OUTPUT
} else {
print 'haveCodesignIdent=false' >> $GITHUB_OUTPUT
}
if [[ '${{ secrets.MACOS_NOTARIZATION_USERNAME }}' != '' && \
'${{ secrets.MACOS_NOTARIZATION_PASSWORD }}' != '' ]] {
print 'haveNotarizationUser=true' >> $GITHUB_OUTPUT
} else {
print 'haveNotarizationUser=false' >> $GITHUB_OUTPUT
}
print '::endgroup::'
print "ccacheDate=$(date +"%Y-%m-%d")" >> $GITHUB_OUTPUT
print "commitHash=${"$(git rev-parse HEAD)"[0,9]}" >> $GITHUB_OUTPUT
echo "$PWD/.github/scripts" >> $GITHUB_PATH
- name: Restore Compilation Cache
id: ccache-cache
uses: actions/cache@v3
with:
path: |
${{ github.workspace }}/.ccache
${{ github.workspace }}/plugin/deps/opencv/build_*
${{ github.workspace }}/plugin/deps/leptonica/build_*
${{ github.workspace }}/plugin/deps/tesseract/build*
key: macos-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
restore-keys: |
macos-${{ matrix.arch }}-ccache-plugin-
- name: Check for GitHub Labels
id: seekingTesters
if: ${{ github.event_name == 'pull_request' }}
run: |
if [[ -n "$(curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -s "${{ github.event.pull_request.url }}" | jq -e '.labels[] | select(.name == "Seeking Testers")')" ]] {
print 'found=true' >> $GITHUB_OUTPUT
} else {
print 'found=false' >> $GITHUB_OUTPUT
}
- name: Install Apple Developer Certificate
if: ${{ steps.setup.outputs.haveCodesignIdent == 'true' }}
uses: apple-actions/import-codesign-certs@253ddeeac23f2bdad1646faac5c8c2832e800071
with:
keychain-password: ${{ github.run_id }}
p12-file-base64: ${{ secrets.MACOS_SIGNING_CERT }}
p12-password: ${{ secrets.MACOS_SIGNING_CERT_PASSWORD }}
- name: Set Signing Identity
if: ${{ steps.setup.outputs.haveCodesignIdent == 'true' }}
run: |
print "CODESIGN_IDENT=${{ secrets.MACOS_SIGNING_APPLICATION_IDENTITY }}" >> $GITHUB_ENV
print "CODESIGN_IDENT_INSTALLER=${{ secrets.MACOS_SIGNING_INSTALLER_IDENTITY }}" >> $GITHUB_ENV
- name: Build Plugin
uses: ./plugin/.github/actions/build-plugin
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
config: RelWithDebInfo
codesign: 'true'
codesignIdent: ${{ env.CODESIGN_IDENT }}
- name: Run tests
uses: ./plugin/.github/actions/run-tests
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
- name: Package Plugin
uses: ./plugin/.github/actions/package-plugin
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
config: RelWithDebInfo
codesign: ${{ steps.setup.outputs.haveCodesignIdent == 'true' }}
notarize: ${{ startsWith(github.ref, 'refs/tags/') && steps.setup.outputs.haveNotarizationUser == 'true' }}
codesignIdent: ${{ env.CODESIGN_IDENT }}
installerIdent: ${{ env.CODESIGN_IDENT_INSTALLER }}
codesignUser: ${{ secrets.MACOS_NOTARIZATION_USERNAME }}
codesignPass: ${{ secrets.MACOS_NOTARIZATION_PASSWORD }}
- name: Upload Installer Artifact
if: ${{ success() }}
uses: actions/upload-artifact@v3
with:
name: ${{ env.PLUGIN_NAME }}-macos-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}-installer
path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}*-macos-${{ matrix.arch }}.pkg
- name: Upload Build Artifact
if: ${{ success() }}
uses: actions/upload-artifact@v3
with:
name: ${{ env.PLUGIN_NAME }}-macos-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}
path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}-*.zip
linux_build:
name: 02 - Linux
runs-on: ubuntu-22.04
strategy:
fail-fast: true
matrix:
arch: [x86_64]
portable: [true, false]
if: always()
needs: [clang_check]
outputs:
commitHash: ${{ steps.setup.outputs.commitHash }}
defaults:
run:
shell: bash
steps:
- name: Checkout
uses: actions/checkout@v3
with:
path: plugin
submodules: recursive
- name: Checkout obs-studio
uses: actions/checkout@v3
with:
repository: 'obsproject/obs-studio'
path: obs-studio
fetch-depth: 0
submodules: recursive
- name: Setup Environment
working-directory: ${{ github.workspace }}/plugin
id: setup
run: |
## SETUP ENVIRONMENT SCRIPT
echo "ccacheDate=$(date +"%Y-%m-%d")" >> $GITHUB_OUTPUT
echo "commitHash=$(git rev-parse HEAD | cut -c1-9)" >> $GITHUB_OUTPUT
echo "$PWD/.github/scripts" >> $GITHUB_PATH
- name: Restore Compilation Cache
id: ccache-cache
uses: actions/cache@v3
with:
path: |
${{ github.workspace }}/.ccache
key: linux-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
restore-keys: |
linux-${{ matrix.arch }}-ccache-plugin-
- name: Check for GitHub Labels
id: seekingTesters
if: ${{ github.event_name == 'pull_request' }}
run: |
## GITHUB LABEL SCRIPT
if [[ -n "$(curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -s "${{ github.event.pull_request.url }}" | jq -e '.labels[] | select(.name == "Seeking Testers")')" ]]; then
echo 'found=true' >> $GITHUB_OUTPUT
else
echo 'found=false' >> $GITHUB_OUTPUT
fi
- name: Build Plugin
uses: ./plugin/.github/actions/build-plugin
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
config: RelWithDebInfo
portable: ${{ matrix.portable }}
- name: Run tests
uses: ./plugin/.github/actions/run-tests
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
- name: Package Plugin
uses: ./plugin/.github/actions/package-plugin
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
config: RelWithDebInfo
portable: ${{ matrix.portable }}
- name: Upload Package Artifact
if: ${{ matrix.portable }}
uses: actions/upload-artifact@v3
with:
name: ${{ env.PLUGIN_NAME }}-linux-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}-portable
path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}*-linux-${{ matrix.arch }}.*
- name: Upload Build Artifact
if: ${{ ! matrix.portable }}
uses: actions/upload-artifact@v3
with:
name: ${{ env.PLUGIN_NAME }}-linux-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}
path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}*-linux-${{ matrix.arch }}.*
windows_build:
name: 02 - Windows
runs-on: windows-2022
strategy:
fail-fast: true
matrix:
arch: [x64]
if: always()
needs: [clang_check]
outputs:
commitHash: ${{ steps.setup.outputs.commitHash }}
defaults:
run:
shell: pwsh
steps:
- name: Checkout
uses: actions/checkout@v3
with:
path: plugin
submodules: recursive
- name: Checkout obs-studio
uses: actions/checkout@v3
with:
repository: 'obsproject/obs-studio'
path: obs-studio
fetch-depth: 0
submodules: recursive
- name: Setup Environment
working-directory: ${{ github.workspace }}/plugin
id: setup
run: |
## SETUP ENVIRONMENT SCRIPT
$CcacheDate = (Get-Date -Format "yyyy-M-d")
"ccacheDate=${CcacheDate}" >> $env:GITHUB_OUTPUT
$CommitHash = (git rev-parse HEAD)[0..8] -join ''
"commitHash=${CommitHash}" >> $env:GITHUB_OUTPUT
- name: Restore Compilation Cache
id: ccache-cache
uses: actions/cache@v3
with:
path: |
${{ github.workspace }}/.ccache
${{ github.workspace }}/plugin/deps/opencv/build_*
${{ github.workspace }}/plugin/deps/leptonica/build_*
${{ github.workspace }}/plugin/deps/tesseract/build*
key: windows-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
restore-keys: |
windows-${{ matrix.arch }}-ccache-plugin-
- name: Check for GitHub Labels
id: seekingTesters
working-directory: ${{ github.workspace }}/plugin
if: ${{ github.event_name == 'pull_request' }}
run: |
## GITHUB LABEL SCRIPT
$LabelFound = try {
$Params = @{
Authentication = 'Bearer'
Token = (ConvertTo-SecureString '${{ secrets.GITHUB_TOKEN }}' -AsPlainText)
Uri = '${{ github.event.pull_request.url }}'
UseBasicParsing = $true
}
(Invoke-RestMethod @Params).labels.name.contains('Seeking Testers')
} catch {
$false
}
"found=$(([string]${LabelFound}).ToLower())" >> $env:GITHUB_OUTPUT
- name: Build Plugin
uses: ./plugin/.github/actions/build-plugin
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
config: RelWithDebInfo
visualStudio: 'Visual Studio 17 2022'
- name: Run tests
uses: ./plugin/.github/actions/run-tests
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
- name: Package Plugin
uses: ./plugin/.github/actions/package-plugin
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
config: RelWithDebInfo
- name: Upload Build Artifact
if: ${{ success() }}
uses: actions/upload-artifact@v3
with:
name: ${{ env.PLUGIN_NAME }}-windows-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}
path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}-*.zip
- name: Package Plugin Installer
uses: ./plugin/.github/actions/package-plugin
with:
workingDirectory: ${{ github.workspace }}/plugin
target: ${{ matrix.arch }}
config: RelWithDebInfo
createInstaller: true
- name: Upload Installer Artifact
uses: actions/upload-artifact@v3
with:
name: ${{ env.PLUGIN_NAME }}-windows-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}-installer
path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}-*.exe
make-release:
name: 03 - Create and upload release
runs-on: ubuntu-22.04
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
needs: [macos_build, linux_build, windows_build]
defaults:
run:
shell: bash
steps:
- name: Get Metadata
id: metadata
run: |
## METADATA SCRIPT
echo "version=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT
- name: Download build artifacts
uses: actions/download-artifact@v3
- name: Generate Checksums
run: |
## CHECKSUM GENERATION SCRIPT
shopt -s extglob
echo "### Checksums" > ${{ github.workspace }}/CHECKSUMS.txt
for file in ${{ github.workspace }}/**/@(*.pkg|*.exe|*.deb|*.zip); do
echo " ${file##*/}: $(sha256sum "${file}" | cut -d " " -f 1)" >> ${{ github.workspace }}/CHECKSUMS.txt
done
cat ${{ github.workspace }}/CHECKSUMS.txt
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v1
with:
draft: true
prerelease: true
tag_name: ${{ steps.metadata.outputs.version }}
name: "${{ env.PLUGIN_NAME }} ${{ steps.metadata.outputs.version }}"
body_path: ${{ github.workspace }}/CHECKSUMS.txt
files: |
${{ github.workspace }}/**/*.zip
${{ github.workspace }}/**/*.exe
${{ github.workspace }}/**/*.deb
${{ github.workspace }}/**/*.pkg

18
.gitignore vendored
View File

@@ -77,6 +77,8 @@ CTestTestfile.cmake_install
ehthumbs.db
Thumbs.db
*.directory
*.generated.*
**/.Brewfile.lock.json
# backup text files generated by an editor #
############################################
@@ -92,7 +94,21 @@ Thumbs.db
*.iml
*.ipr
*.sublime*
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
.history/
*.vsix
forms/advanced-scene-switcher.ui.autosave
# Directories #
###############
build/
*~
.DS_Store
/build/
/build_*/
/release/
/installer/Output/

12
.gitmodules vendored
View File

@@ -4,3 +4,15 @@
[submodule "deps/websocketpp"]
path = deps/websocketpp
url = https://github.com/zaphoyd/websocketpp.git
[submodule "deps/opencv"]
path = deps/opencv
url = https://github.com/opencv/opencv.git
[submodule "deps/openvr"]
path = deps/openvr
url = https://github.com/ValveSoftware/openvr.git
[submodule "deps/leptonica"]
path = deps/leptonica
url = https://github.com/DanBloomberg/leptonica.git
[submodule "deps/tesseract"]
path = deps/tesseract
url = https://github.com/tesseract-ocr/tesseract.git

198
BUILDING.md Normal file
View File

@@ -0,0 +1,198 @@
# Compiling the plugin
You have the option to ...
- either add the plugin to the OBS source tree directly and build the plugin while building OBS itself. (**in tree**)
- or you can move the sources of this plugin outside of the OBS source tree and build it separately from OBS. (**out of tree**)
As both methods require you to have a working [OBS Studio development environment](https://obsproject.com/wiki/Building-OBS-Studio) and [CMake](https://cmake.org/download/) it is recommended to build the plugin in tree as it is easier to set up and will enable straightforward debugging.
The plugin can be compiled for OBS 25 and above, although using the latest version of OBS is recommended to support all features.
## Compiling in tree (recommended for development)
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
```
cd obs-studio/UI/frontend-plugins/
git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git
```
Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt Example and add an entry for the scene switcher:
```
add_subdirectory(SceneSwitcher)
```
Now follow the [build instructions for obs-studio](https://obsproject.com/wiki/Building-OBS-Studio) for your particular platform.
Note that on Linux systems it might be necessary to additionally install the following packages to fulfill the dependencies to `XTest`, `XScreensaver` and `OpenCV` - exact command may differ:
```
sudo apt-get install \
libxtst-dev \
libxss-dev \
libprocps-dev \
libopencv-dev
```
## Compiling out of tree
First you will need to clone the plugin sources by running the following command:
```
git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git
cd SceneSwitcher
```
You'll need [CMake](https://cmake.org/download/) and a working [OBS Studio development environment](https://obsproject.com/wiki/Building-OBS-Studio) installed on your computer.
The easiest way to set this up is to call the corresponding CI scripts, as they will automatically download all required dependencies and start build of the plugin:
| Platform | Command |
| ----------- | ----------- |
| Windows | `./.github/scripts/Build-Windows.ps1` |
| Linux | `./.github/scripts/build-linux.sh` |
| MacOS | `./.github/scripts/build-macos.zsh` |
Alternatively you can download the OBS dependencies from https://github.com/obsproject/obs-deps/releases and manually configure and start the build.
Start by creating a build directory:
```
mkdir build && cd build
```
Next configure the build.
```
cmake -DCMAKE_PREFIX_PATH=<path-to-obs-deps> -Dlibobs_DIR=<path-to-libobs-dir> -Dobs-frontend-api_DIR=<path-to-frontend-api-dir> ..
```
It might be necessary to provide additional variables depending on your build setup.
Finally, start the plugin build using your provided generator. (E.g. Ninja on Linux or a Visual Studio solution on Windows)
# Contributing
Contributions to the plugin are always welcome and if you need any assistance do not hesitate to reach out.
If you would like to expand upon the macro system by adding a new condition or action type have a loot at the examples in `src/macro-core`.
In general changes in the `src/legacy` folder should be avoided.
## Macro condition
Macro conditions should inherit from the `MacroCondition` class and must implement the following functions:
```
class MacroConditionExample : public MacroCondition {
public:
MacroConditionExample(Macro *m) : MacroCondition(m) {}
// This function should perfrom the condition check
bool CheckCondition();
// This function should store the required condition data to "obj"
// For example called on OBS shutdown
bool Save(obs_data_t *obj);
// This function should load the condition data from "obj"
// For example called on OBS startup
bool Load(obs_data_t *obj);
// This function should return a unique id for this condition type
// The _id is defined below
std::string GetId() { return _id; };
// Helper function called when new conditions are created
// Will be used later when regeistering the new condition type
static std::shared_ptr<MacroCondition> Create(Macro *m)
{
return std::make_shared<MacroConditionExample>(m);
}
private:
// Used to register new condition type
static bool _registered;
// Unique id identifying this condition type
static const std::string _id;
};
```
When defining the widget used to control the settings of the condition type, it is important to add a static `Create()` method.
It will be called whenever a new condition MacroConditionExample is created. (See `MacroConditionFactory::Register()`)
```
class MacroConditionExampleEdit : public QWidget {
Q_OBJECT
public:
// ...
MacroConditionExampleEdit(
QWidget *parent,
std::shared_ptr<MacroConditionExample> cond = nullptr);
// Function will be used to create the widget for editing the settings of the condition
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroCondition> cond)
{
return new MacroConditionExampleEdit(
parent,
std::dynamic_pointer_cast<MacroConditionExample>(cond));
}
// ...
};
```
To finally register the new condition type you will have to add the following call to `MacroConditionFactory::Register()`.
```
bool MacroConditionExample::_registered = MacroConditionFactory::Register(
MacroConditionExample::id, // Unique string identifying this condition type
{
MacroConditionExample::Create, // Function called to create the object performing the condition
MacroConditionExampleEdit::Create, // Function called to create the widget configure the condition
"AdvSceneSwitcher.condition.example", // User facing name of the condition type (will be translated)
true // Condition type supports duration modifiers (default true)
}
);
```
## Macro action
The process of adding a new action type is very similar to adding a new condition.
The differences are highlighted in the comments below.
```
class MacroActionExample : public MacroAction {
public:
MacroActionExample(Macro *m) : MacroAction(m) {}
// This function should perfrom the action
// If false is returned the macro will aborted
bool PerformAction();
bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj);
std::string GetId() { return _id; };
static std::shared_ptr<MacroAction> Create(Macro *m)
{
return std::make_shared<MacroActionExample>(m);
}
private:
static bool _registered;
static const std::string _id;
};
```
```
class MacroActionExampleEdit : public QWidget {
Q_OBJECT
public:
// ...
MacroActionExampleEdit(
QWidget *parent,
std::shared_ptr<MacroActionExample> entryData = nullptr);
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroAction> action)
{
return new MacroActionExampleEdit(
parent,
std::dynamic_pointer_cast<MacroActionExample>(action));
}
// ...
};
```
```
MacroActionFactory::Register(
MacroActionExample::id, // Unique string identifying this action type
{
MacroActionExample::Create, // Function called to create the object performing the action
MacroActionExampleEdit::Create, // Function called to create the widget configure the action
"AdvSceneSwitcher.action.example" // User facing name of the action type
}
);
```
## External dependencies
If your intention is to add macro functionality which depends on external libraries, which is likely not to exist on all user setups, try to follow the examples under `src/macro-external`.
These are basically plugins themselves that get attempted to be loaded on startup of the advanced scene switcher.

93
CI/checkLocale.py Normal file
View File

@@ -0,0 +1,93 @@
#!/usr/bin/env python3
import os
import sys
import argparse
defaultLocaleFile = "en-US.ini"
class localeEntry:
locale = ""
placeholders = []
def __init__(self, locale, widgets) -> None:
self.locale = locale
self.placeholders = widgets
def getNonDefaultLocales(dir):
files = []
for filename in os.listdir(dir):
f = os.path.join(dir, filename)
if os.path.isfile(f) and not f.endswith(defaultLocaleFile):
files.append(f)
return files
def getAllLocaleEntriesWithWidgetPlaceholders(file):
localeEntries = []
with open(file, 'r', encoding='UTF-8') as f:
for line in f.readlines():
widgetPlaceholders = []
for word in line.split("{{"):
if not "}}" in word:
continue
word = "{{" + word[:word.rfind("}}")] + "}}"
widgetPlaceholders.append(word)
localeEntries.append(localeEntry(
line.split("=")[0], widgetPlaceholders))
return localeEntries
def getLocaleEntryFrom(entry, list):
for element in list:
if element.locale == entry.locale:
return element
return None
def checkWidgetPlacehodlers(file, expectedPlaceholders):
localeEntries = getAllLocaleEntriesWithWidgetPlaceholders(file)
result = True
for localeEntry in localeEntries:
expectedEntry = getLocaleEntryFrom(localeEntry, expectedPlaceholders)
if expectedEntry is None:
print(
"WARNING: Locale entry \"{}\" from \"{}\" not found in \"{}\"".format(localeEntry.locale, file, defaultLocaleFile))
continue
for p in localeEntry.placeholders:
if p not in expectedEntry.placeholders:
print("WARNING: Locale entry \"{}\" from \"{}\" does contain \"{}\" while \"{}\" does not".format(
localeEntry.locale, file, p, defaultLocaleFile))
for p in expectedEntry.placeholders:
if p not in localeEntry.placeholders:
result = False
print("ERROR: Locale entry \"{}\" from \"{}\" does not contain \"{}\"".format(
localeEntry.locale, file, p))
return result
def main():
parser = argparse.ArgumentParser(
description='Checks for inconsistencies regarding widget placeholders in the different locale files.')
parser.add_argument(
'-p', '--path', help='Path to locale folder', required=True)
args = parser.parse_args()
placeholders = getAllLocaleEntriesWithWidgetPlaceholders(
os.path.join(args.path, defaultLocaleFile))
nonDefaultLocales = getNonDefaultLocales(args.path)
result = True
for f in nonDefaultLocales:
if checkWidgetPlacehodlers(f, placeholders) == False:
result = False
if result == False:
sys.exit(1)
print("SUCCESS: No issues found!")
sys.exit(0)
if __name__ == "__main__":
main()

View File

@@ -1,35 +0,0 @@
#!/usr/bin/env bash
# Original source https://github.com/Project-OSRM/osrm-backend/blob/master/scripts/format.sh
set +x
set -o errexit
set -o pipefail
set -o nounset
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
# Runs the Clang Formatter in parallel on the code base.
# Return codes:
# - 1 there are files to be formatted
# - 0 everything looks fine
# Get CPU count
OS=$(uname)
NPROC=1
if [[ $OS = "Linux" || $OS = "Darwin" ]] ; then
NPROC=$(getconf _NPROCESSORS_ONLN)
fi
# Discover clang-format
if type clang-format-10 2> /dev/null ; then
CLANG_FORMAT=clang-format-10
elif type clang-format-8 2> /dev/null ; then
CLANG_FORMAT=clang-format-8
else
CLANG_FORMAT=clang-format
fi
find $SCRIPTPATH/.. -type d \( -path $SCRIPTPATH/../deps \
-o -path $SCRIPTPATH/../cmake \
-o -path $SCRIPTPATH/../build \) -prune -type f -o -name '*.h' -or -name '*.hpp' -or -name '*.m' -or -name '*.mm' -or -name '*.c' -or -name '*.cpp' \
| xargs -L100 -P${NPROC} ${CLANG_FORMAT} -i -style=file -fallback-style=none

View File

@@ -0,0 +1,5 @@
obs-scene-switcher (0.1+testonly) focal; urgency=medium
* Initial release (Closes: #123456)
-- Joao Eriberto Mota Filho <eriberto@debian.org> Fri, 03 Sep 2021 11:39:52 -0300

22
CI/linux/debian/control Normal file
View File

@@ -0,0 +1,22 @@
Source: obs-scene-switcher
Section: video
Priority: optional
Maintainer: Joao Eriberto Mota Filho <eriberto@debian.org>
Build-Depends: cmake,
debhelper-compat (= 12),
libcurl4-openssl-dev,
libobs-dev,
libxtst-dev,
qtbase5-dev,
libxss-dev,
libopencv-dev
Standards-Version: 4.6.0
Homepage: https://obsproject.com/forum/resources/advanced-scene-switcher.395/
Rules-Requires-Root: no
Package: obs-scene-switcher
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: automated scene switcher for OBS Studio (plugin)
Advanced Scene Switcher is based on the built in scene switcher. It extends
its functionality by adding several features.

60
CI/linux/debian/copyright Normal file
View File

@@ -0,0 +1,60 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: SceneSwitcher
Upstream-Contact: https://github.com/WarmUpTill/SceneSwitcher/issues
Source: https://github.com/WarmUpTill/SceneSwitcher
Files: *
Copyright: 2016-2021 WarmUpTill <WarmUpTill@web.de>
License: GPL-2
Files: cmake/GetGitRevisionDescription.cmake
cmake/GetGitRevisionDescription.cmake.in
Copyright: 2009-2013 Iowa State University
2013-2020 Contributors
2013-2020 Ryan Pavlik
License: BSL-1.0
Files: debian/*
Copyright: 2021 Joao Eriberto Mota Filho <eriberto@debian.org>
License: BSL-1.0
License: GPL-2
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
License: BSL-1.0
Boost Software License - Version 1.0 - August 17th, 2003
.
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
.
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

16
CI/linux/debian/rules Normal file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/make -f
#export DH_VERBOSE = 1
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
export QT_SELECT = qt5
%:
dh $@
dh_auto_configure -- -DBUILD_OUT_OF_TREE=1 \
-DLIBOBS_INCLUDE_DIR=/usr/include/obs \
-DLIBOBS_LIB=/usr/lib/${DEB_TARGET_MULTIARCH}/libobs.so \
-DLIBOBS_FRONTEND_INCLUDE_DIR=/usr/include/obs \
-DLIBOBS_FRONTEND_API_LIB=/usr/lib/${DEB_TARGET_MULTIARCH}/libobs-frontend-api.so

View File

@@ -0,0 +1 @@
3.0 (native)

View File

@@ -1,5 +0,0 @@
brew "jack"
brew "speexdsp"
brew "cmake"
brew "freetype"
brew "fdk-aac"

View File

@@ -1,776 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PROJECT</key>
<dict>
<key>PACKAGE_FILES</key>
<dict>
<key>DEFAULT_INSTALL_LOCATION</key>
<string>/</string>
<key>HIERARCHY</key>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>../../../../../build/UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so</string>
<key>PATH_TYPE</key>
<integer>3</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>3</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>bin</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>2</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>../../data</string>
<key>PATH_TYPE</key>
<integer>1</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>3</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>advanced-scene-switcher</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>2</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>plugins</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>2</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>obs-studio</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>2</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Application Support</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Automator</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Documentation</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Extensions</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Filesystems</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Frameworks</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Input Methods</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Internet Plug-Ins</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>LaunchAgents</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>LaunchDaemons</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>PreferencePanes</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Preferences</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Printers</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>PrivilegedHelperTools</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>1005</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>QuickLook</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>QuickTime</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Screen Savers</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Scripts</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Services</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Widgets</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Library</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Shared</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>1023</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Users</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Applications</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>509</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>/</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<key>PAYLOAD_TYPE</key>
<integer>0</integer>
<key>PRESERVE_EXTENDED_ATTRIBUTES</key>
<false/>
<key>SHOW_INVISIBLE</key>
<false/>
<key>SPLIT_FORKS</key>
<true/>
<key>TREAT_MISSING_FILES_AS_WARNING</key>
<false/>
<key>VERSION</key>
<integer>5</integer>
</dict>
<key>PACKAGE_SCRIPTS</key>
<dict>
<key>POSTINSTALL_PATH</key>
<dict>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>PREINSTALL_PATH</key>
<dict>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>RESOURCES</key>
<array/>
</dict>
<key>PACKAGE_SETTINGS</key>
<dict>
<key>AUTHENTICATION</key>
<integer>1</integer>
<key>CONCLUSION_ACTION</key>
<integer>0</integer>
<key>FOLLOW_SYMBOLIC_LINKS</key>
<false/>
<key>IDENTIFIER</key>
<string>com.warmuptill.SceneSwitcher</string>
<key>LOCATION</key>
<integer>0</integer>
<key>NAME</key>
<string></string>
<key>OVERWRITE_PERMISSIONS</key>
<false/>
<key>PAYLOAD_SIZE</key>
<integer>-1</integer>
<key>REFERENCE_PATH</key>
<string></string>
<key>RELOCATABLE</key>
<false/>
<key>USE_HFS+_COMPRESSION</key>
<false/>
<key>VERSION</key>
<string>0.0.2</string>
</dict>
<key>PROJECT_COMMENTS</key>
<dict>
<key>NOTES</key>
<data>
PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1M
IDQuMDEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQv
c3RyaWN0LmR0ZCI+CjxodG1sPgo8aGVhZD4KPG1ldGEgaHR0cC1l
cXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7
IGNoYXJzZXQ9VVRGLTgiPgo8bWV0YSBodHRwLWVxdWl2PSJDb250
ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp
dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u
dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD
b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjE0MDQuMTMiPgo8c3R5bGUg
dHlwZT0idGV4dC9jc3MiPgo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5
Pgo8L2JvZHk+CjwvaHRtbD4K
</data>
</dict>
<key>PROJECT_SETTINGS</key>
<dict>
<key>BUILD_PATH</key>
<dict>
<key>PATH</key>
<string>../..</string>
<key>PATH_TYPE</key>
<integer>1</integer>
</dict>
<key>EXCLUDED_FILES</key>
<array>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.DS_Store</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove .DS_Store files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove ".DS_Store" files created by the Finder.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.pbdevelopment</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove .pbdevelopment files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove ".pbdevelopment" files created by ProjectBuilder or Xcode.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>CVS</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.cvsignore</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.cvspass</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.svn</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.git</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.gitignore</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove SCM metadata</string>
<key>PROXY_TOOLTIP</key>
<string>Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>classes.nib</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>designable.db</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>info.nib</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Optimize nib files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>Resources Disabled</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove Resources Disabled folders</string>
<key>PROXY_TOOLTIP</key>
<string>Remove "Resources Disabled" folders.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>SEPARATOR</key>
<true/>
</dict>
</array>
<key>NAME</key>
<string>SceneSwitcher</string>
<key>PAYLOAD_ONLY</key>
<false/>
</dict>
</dict>
<key>TYPE</key>
<integer>1</integer>
<key>VERSION</key>
<integer>2</integer>
</dict>
</plist>

View File

@@ -1,42 +0,0 @@
Note that you will have to use OBS version 26.1 or newer!
--- Windows ---
Recommended: Run the provided installer. (You might have to click 'More info' and select 'Run anyway' if it is blocked by Windows)
Alternatively manually copy the 'obs-plugins' and 'data' folders in the respective OBS Studio installation directory.
It is usually located at 'C:\Program Files (x86)\obs-studio\'.
Remember to install the Visual C++ Redistributable for Visual Studio 2019, if you have not done so already. (See plugin overview page)
--- macOS ---
Recommended: Run the provided installer. (You might have to right-click or control-click and select 'open' if it is blocked)
Alternatively extract the *so file and data folder and either ...
... right-click the OBS app inside your Applications folder and choose 'Show Package Contents'.
Copy the advanced-scene-switcher.so file to 'Contents/Plugins' and the 'data' folder to 'Contents/Resources'.
... or copy the advanced-scene-switcher.so file to Library/Application Support/obs-studio/plugins/advanced-scene-switcher/bin/ .
And the 'data' folder to 'Library/Application Support/obs-studio/plugins/advanced-scene-switcher/'.
--- Linux ---
Copy the advanced-scene-switcher.so file and into the OBS Studio plugin folder.
The location of this folder can vary, so you might have to look around a bit.
Examples are ...
/usr/lib/obs-plugins/
/usr/lib/x86_64-linux-gnu/obs-plugins/
/usr/share/obs/obs-plugins/
~/.config/obs-studio/plugins/advanced-scene-switcher/bin/64bit/
~/.local/share/flatpak/app/com.obsproject.Studio/x86_64/stable/active/files/lib/obs-plugins/
/var/lib/flatpak/app/com.obsproject.Studio/x86_64/stable/active/files/lib/obs-plugins/
Unfortunately the expected location of the locale, which can be found in the data folder, can vary also.
The data folder usually should be copied to:
~/.config/obs-studio/plugins/advanced-scene-switcher/
If this does not work you can try to copy the "locale" folder found inside the data folder to:
/usr/share/obs/obs-plugins/advanced-scene-switcher/locale
~/.local/share/flatpak/app/com.obsproject.Studio/x86_64/stable/active/files/share/obs/obs-plugins/advanced-scene-switcher/locale
/var/lib/flatpak/app/com.obsproject.Studio/x86_64/stable/active/files/share/obs/obs-plugins/advanced-scene-switcher/locale
In doubt please check where other "en-US.ini" files are located on your system.

View File

@@ -1,64 +0,0 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "Advanced Scene Switcher"
#define MyAppVersion "@GIT_SHA1@"
#define MyAppURL "https://github.com/WarmUpTill/SceneSwitcher"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{A4ADDF26-4426-4D2E-B26A-C7C878DA8FC9}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={code:GetDirName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
; Uncomment the following line to run in non administrative install mode (install for current user only.)
;PrivilegesRequired=lowest
OutputBaseFilename=AdvancedSceneSwitcherSetup
Compression=lzma
SolidCompression=yes
WizardStyle=modern
ArchitecturesInstallIn64BitMode=x64
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "@ISS_MSVC_REDIST_HELPER_DIR@\msvc-redist-helper-64.exe"; DestDir: "{app}"; DestName: "msvc-redist-helper.exe"; Flags: ignoreversion dontcopy; Check: Is64BitInstallMode
Source: "@ISS_MSVC_REDIST_HELPER_DIR@\msvc-redist-helper-32.exe"; DestDir: "{app}"; DestName: "msvc-redist-helper.exe"; Flags: ignoreversion dontcopy; Check: not Is64BitInstallMode
Source: "@ISS_PLUGIN_FILES_DIR@\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
[Code]
// credit where it's due:
// following function comes from https://github.com/Xaymar/obs-studio_amf-encoder-plugin/blob/master/%23Resources/Installer.in.iss#L45
function GetDirName(Value: string): string;
var
InstallPath: string;
begin
// initialize default path, which will be returned when the following registry
// key queries fail due to missing keys or for some different reason
Result := ExpandConstant('{pf}\obs-studio');
// query the first registry value; if this succeeds, return the obtained value
if RegQueryStringValue(HKLM32, 'SOFTWARE\OBS Studio', '', InstallPath) then
Result := InstallPath
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
ResultCode: Integer;
begin
if (CurStep=ssPostInstall) then
begin
ExtractTemporaryFile('msvc-redist-helper.exe');
Exec(ExpandConstant('{tmp}\msvc-redist-helper.exe'), '2019', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;
end;

View File

@@ -1,317 +1,476 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.16.3)
project(advanced-scene-switcher)
add_definitions(-DASIO_STANDALONE)
project(advanced-scene-switcher VERSION 1.0.0)
set(LIB_NAME "${PROJECT_NAME}-lib")
add_library(${PROJECT_NAME} MODULE)
add_library(${LIB_NAME} SHARED)
set(PLUGIN_AUTHOR "WarmUpTill")
set(MACOS_BUNDLEID "com.warmuptill.${PROJECT_NAME}")
set(LINUX_MAINTAINER_EMAIL "noone@nothing.com")
set(MACOS_PACKAGE_UUID "3F0D2A6A-2583-11ED-861D-0242AC120002")
set(MACOS_INSTALLER_UUID "B7F15A6E-2583-11ED-861D-0242AC120002")
set(WINDOWS_INSTALLER_UUID "A4ADDF26-4426-4D2E-B26A-C7C878DA8FC9")
message(STATUS "CMAKE_PROJECT_NAME is ${CMAKE_PROJECT_NAME}")
if(${CMAKE_PROJECT_NAME} STREQUAL "obs-studio")
if(NOT DEFINED BUILD_OUT_OF_TREE)
message(STATUS "${PROJECT_NAME} configured for in-tree build")
endif()
else()
set(BUILD_OUT_OF_TREE ON)
message(STATUS "${PROJECT_NAME} configured for out-of-tree build")
endif()
# generate version info
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
if(WIN32)
get_filename_component(ISS_PLUGIN_FILES_DIR "${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}" ISS_MSVC_REDIST_HELPER_DIR)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
endif()
git_describe(GIT_TAG)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in"
"${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
if(WIN32)
get_filename_component(ISS_PLUGIN_FILES_DIR "${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}" ISS_MSVC_REDIST_HELPER_DIR)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
endif()
# --- Set target sources ---
# Module sources
target_sources(${PROJECT_NAME} PRIVATE src/advanced-scene-switcher-module.c)
# Generic sources
target_sources(
${LIB_NAME}
PRIVATE src/advanced-scene-switcher.cpp
src/advanced-scene-switcher.hpp
src/general.cpp
src/hotkey.cpp
src/hotkey.hpp
src/hotkey.hpp
src/platform-funcs.hpp
src/scene-group.cpp
src/scene-group.hpp
src/status-control.cpp
src/status-control.hpp
src/switcher-data-structs.cpp
src/switcher-data-structs.hpp
src/version.cpp
src/version.h)
# Legacy function sources
target_sources(
${LIB_NAME}
PRIVATE src/legacy/scene-trigger.cpp
src/legacy/scene-trigger.hpp
src/legacy/switch-audio.cpp
src/legacy/switch-audio.hpp
src/legacy/switch-executable.cpp
src/legacy/switch-executable.hpp
src/legacy/switch-file.cpp
src/legacy/switch-file.hpp
src/legacy/switch-generic.cpp
src/legacy/switch-generic.hpp
src/legacy/switch-idle.cpp
src/legacy/switch-idle.hpp
src/legacy/switch-media.cpp
src/legacy/switch-media.hpp
src/legacy/switch-network.cpp
src/legacy/switch-network.hpp
src/legacy/switch-pause.cpp
src/legacy/switch-pause.hpp
src/legacy/switch-priority.cpp
src/legacy/switch-random.cpp
src/legacy/switch-random.hpp
src/legacy/switch-screen-region.cpp
src/legacy/switch-screen-region.hpp
src/legacy/switch-sequence.cpp
src/legacy/switch-sequence.hpp
src/legacy/switch-time.cpp
src/legacy/switch-time.hpp
src/legacy/switch-transitions.cpp
src/legacy/switch-transitions.hpp
src/legacy/switch-video.cpp
src/legacy/switch-video.hpp
src/legacy/switch-window.cpp
src/legacy/switch-window.hpp)
# Maro sources
target_sources(
${LIB_NAME}
PRIVATE src/macro-core/macro-action-audio.cpp
src/macro-core/macro-action-audio.hpp
src/macro-core/macro-action-edit.cpp
src/macro-core/macro-action-edit.hpp
src/macro-core/macro-action-file.cpp
src/macro-core/macro-action-file.hpp
src/macro-core/macro-action-filter.cpp
src/macro-core/macro-action-filter.hpp
src/macro-core/macro-action-hotkey.cpp
src/macro-core/macro-action-hotkey.hpp
src/macro-core/macro-action-http.cpp
src/macro-core/macro-action-http.hpp
src/macro-core/macro-action-macro.cpp
src/macro-core/macro-action-macro.hpp
src/macro-core/macro-action-media.cpp
src/macro-core/macro-action-media.hpp
src/macro-core/macro-action-plugin-state.cpp
src/macro-core/macro-action-plugin-state.hpp
src/macro-core/macro-action-profile.cpp
src/macro-core/macro-action-profile.hpp
src/macro-core/macro-action-projector.cpp
src/macro-core/macro-action-projector.hpp
src/macro-core/macro-action-random.cpp
src/macro-core/macro-action-random.hpp
src/macro-core/macro-action-recording.cpp
src/macro-core/macro-action-recording.hpp
src/macro-core/macro-action-replay-buffer.cpp
src/macro-core/macro-action-replay-buffer.hpp
src/macro-core/macro-action-run.cpp
src/macro-core/macro-action-run.hpp
src/macro-core/macro-action-scene-collection.cpp
src/macro-core/macro-action-scene-collection.hpp
src/macro-core/macro-action-scene-order.cpp
src/macro-core/macro-action-scene-order.hpp
src/macro-core/macro-action-scene-switch.cpp
src/macro-core/macro-action-scene-switch.hpp
src/macro-core/macro-action-scene-transform.cpp
src/macro-core/macro-action-scene-transform.hpp
src/macro-core/macro-action-scene-visibility.cpp
src/macro-core/macro-action-scene-visibility.hpp
src/macro-core/macro-action-screenshot.cpp
src/macro-core/macro-action-screenshot.hpp
src/macro-core/macro-action-sequence.cpp
src/macro-core/macro-action-sequence.hpp
src/macro-core/macro-action-source.cpp
src/macro-core/macro-action-source.hpp
src/macro-core/macro-action-streaming.cpp
src/macro-core/macro-action-streaming.hpp
src/macro-core/macro-action-studio-mode.cpp
src/macro-core/macro-action-studio-mode.hpp
src/macro-core/macro-action-systray.cpp
src/macro-core/macro-action-systray.hpp
src/macro-core/macro-action-timer.cpp
src/macro-core/macro-action-timer.hpp
src/macro-core/macro-action-transition.cpp
src/macro-core/macro-action-transition.hpp
src/macro-core/macro-action-variable.cpp
src/macro-core/macro-action-variable.hpp
src/macro-core/macro-action-virtual-cam.cpp
src/macro-core/macro-action-virtual-cam.hpp
src/macro-core/macro-action-wait.cpp
src/macro-core/macro-action-wait.hpp
src/macro-core/macro-action-websocket.cpp
src/macro-core/macro-action-websocket.hpp
src/macro-core/macro-action.cpp
src/macro-core/macro-action.hpp
src/macro-core/macro-condition-audio.cpp
src/macro-core/macro-condition-audio.hpp
src/macro-core/macro-condition-cursor.cpp
src/macro-core/macro-condition-cursor.hpp
src/macro-core/macro-condition-date.cpp
src/macro-core/macro-condition-date.hpp
src/macro-core/macro-condition-edit.cpp
src/macro-core/macro-condition-edit.hpp
src/macro-core/macro-condition-file.cpp
src/macro-core/macro-condition-file.hpp
src/macro-core/macro-condition-filter.cpp
src/macro-core/macro-condition-filter.hpp
src/macro-core/macro-condition-hotkey.cpp
src/macro-core/macro-condition-hotkey.hpp
src/macro-core/macro-condition-idle.cpp
src/macro-core/macro-condition-idle.hpp
src/macro-core/macro-condition-macro.cpp
src/macro-core/macro-condition-macro.hpp
src/macro-core/macro-condition-media.cpp
src/macro-core/macro-condition-media.hpp
src/macro-core/macro-condition-obs-stats.cpp
src/macro-core/macro-condition-obs-stats.hpp
src/macro-core/macro-condition-plugin-state.cpp
src/macro-core/macro-condition-plugin-state.hpp
src/macro-core/macro-condition-process.cpp
src/macro-core/macro-condition-process.hpp
src/macro-core/macro-condition-profile.cpp
src/macro-core/macro-condition-profile.hpp
src/macro-core/macro-condition-recording.cpp
src/macro-core/macro-condition-recording.hpp
src/macro-core/macro-condition-replay-buffer.cpp
src/macro-core/macro-condition-replay-buffer.hpp
src/macro-core/macro-condition-run.cpp
src/macro-core/macro-condition-run.hpp
src/macro-core/macro-condition-scene-order.cpp
src/macro-core/macro-condition-scene-order.hpp
src/macro-core/macro-condition-scene-transform.cpp
src/macro-core/macro-condition-scene-transform.hpp
src/macro-core/macro-condition-scene-visibility.cpp
src/macro-core/macro-condition-scene-visibility.hpp
src/macro-core/macro-condition-scene.cpp
src/macro-core/macro-condition-scene.hpp
src/macro-core/macro-condition-source.cpp
src/macro-core/macro-condition-source.hpp
src/macro-core/macro-condition-streaming.cpp
src/macro-core/macro-condition-streaming.hpp
src/macro-core/macro-condition-studio-mode.cpp
src/macro-core/macro-condition-studio-mode.hpp
src/macro-core/macro-condition-timer.cpp
src/macro-core/macro-condition-timer.hpp
src/macro-core/macro-condition-transition.cpp
src/macro-core/macro-condition-transition.hpp
src/macro-core/macro-condition-variable.cpp
src/macro-core/macro-condition-variable.hpp
src/macro-core/macro-condition-virtual-cam.cpp
src/macro-core/macro-condition-virtual-cam.hpp
src/macro-core/macro-condition-websocket.cpp
src/macro-core/macro-condition-websocket.hpp
src/macro-core/macro-condition-window.cpp
src/macro-core/macro-condition-window.hpp
src/macro-core/macro-condition.cpp
src/macro-core/macro-condition.hpp
src/macro-core/macro-dock.cpp
src/macro-core/macro-dock.hpp
src/macro-core/macro-properties.cpp
src/macro-core/macro-properties.hpp
src/macro-core/macro-ref.cpp
src/macro-core/macro-ref.hpp
src/macro-core/macro-segment-list.cpp
src/macro-core/macro-segment-list.hpp
src/macro-core/macro-segment.cpp
src/macro-core/macro-segment.hpp
src/macro-core/macro-selection.cpp
src/macro-core/macro-selection.hpp
src/macro-core/macro-tab.cpp
src/macro-core/macro-tree.cpp
src/macro-core/macro-tree.hpp
src/macro-core/macro.cpp
src/macro-core/macro.hpp)
# Utility function sources
target_sources(
${LIB_NAME}
PRIVATE src/utils/connection-manager.cpp
src/utils/connection-manager.hpp
src/utils/curl-helper.cpp
src/utils/curl-helper.hpp
src/utils/duration-control.cpp
src/utils/duration-control.hpp
src/utils/item-selection-helpers.cpp
src/utils/item-selection-helpers.hpp
src/utils/file-selection.cpp
src/utils/file-selection.hpp
src/utils/macro-list.cpp
src/utils/macro-list.hpp
src/utils/math-helpers.cpp
src/utils/math-helpers.hpp
src/utils/mouse-wheel-guard.cpp
src/utils/mouse-wheel-guard.hpp
src/utils/name-dialog.cpp
src/utils/name-dialog.hpp
src/utils/obs-dock.hpp
src/utils/process-config.cpp
src/utils/process-config.hpp
src/utils/regex-config.cpp
src/utils/regex-config.hpp
src/utils/resizing-text-edit.cpp
src/utils/resizing-text-edit.hpp
src/utils/scene-item-selection.cpp
src/utils/scene-item-selection.hpp
src/utils/scene-selection.cpp
src/utils/scene-selection.hpp
src/utils/screenshot-helper.cpp
src/utils/screenshot-helper.hpp
src/utils/section.cpp
src/utils/section.hpp
src/utils/slider-spinbox.cpp
src/utils/slider-spinbox.hpp
src/utils/source-selection.cpp
src/utils/source-selection.hpp
src/utils/string-list.cpp
src/utils/string-list.hpp
src/utils/striped-frame.cpp
src/utils/striped-frame.hpp
src/utils/transition-selection.cpp
src/utils/transition-selection.hpp
src/utils/utility.cpp
src/utils/utility.hpp
src/utils/variable.cpp
src/utils/variable.hpp
src/utils/variable-line-edit.cpp
src/utils/variable-line-edit.hpp
src/utils/variable-number.tpp
src/utils/variable-number.hpp
src/utils/variable-spinbox.cpp
src/utils/variable-spinbox.hpp
src/utils/variable-string.cpp
src/utils/variable-string.hpp
src/utils/variable-text-edit.cpp
src/utils/variable-text-edit.hpp
src/utils/volume-control.cpp
src/utils/volume-control.hpp
src/utils/websocket-helpers.cpp
src/utils/websocket-helpers.hpp)
# --- End of section ---
if(BUILD_OUT_OF_TREE)
set(CMAKE_PREFIX_PATH "${QTDIR}")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/external")
include(external/FindLibObs.cmake)
find_package(LibObs REQUIRED)
find_package(Qt5Core REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Libcurl REQUIRED)
find_path(LIBOBS_FRONTEND_INCLUDE_DIR HINTS ${LIBOBS_INCLUDE_DIRS})
find_file(LIBOBS_FRONTEND_API_LIB NAMES libobs-frontend-api.* HINTS ${LIBOBS_LIB} )
include(cmake/ObsPluginHelpers.cmake)
endif()
include(cmake/AdvSSHelpers.cmake)
setup_obs_lib_dependency(${LIB_NAME})
setup_obs_lib_dependency(${PROJECT_NAME})
if(APPLE)
find_library(COCOA Cocoa)
if(BUILD_OUT_OF_TREE)
find_package(Qt5MacExtras REQUIRED)
endif()
include_directories(${COCOA})
endif()
target_link_libraries(${PROJECT_NAME} PUBLIC ${LIB_NAME})
find_qt(COMPONENTS Widgets Core)
target_link_libraries(${LIB_NAME} PUBLIC Qt::Core Qt::Widgets)
if(UNIX AND NOT APPLE)
find_package(X11 REQUIRED)
link_libraries(${X11_LIBRARIES})
include_directories(${X11_INCLUDE_DIR})
endif()
# --- Platform-independent build settings ---
include_directories(
"${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp"
)
target_include_directories(
${LIB_NAME}
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src"
"${CMAKE_CURRENT_SOURCE_DIR}/src/legacy"
"${CMAKE_CURRENT_SOURCE_DIR}/src/macro-core"
"${CMAKE_CURRENT_SOURCE_DIR}/src/utils"
"${CMAKE_CURRENT_BINARY_DIR}/forms")
set(advanced-scene-switcher_HEADERS
${advanced-scene-switcher_HEADERS}
src/headers/advanced-scene-switcher.hpp
src/headers/switcher-data-structs.hpp
src/headers/scene-group.hpp
src/headers/scene-trigger.hpp
src/headers/switch-audio.hpp
src/headers/switch-executable.hpp
src/headers/switch-file.hpp
src/headers/switch-idle.hpp
src/headers/switch-media.hpp
src/headers/switch-network.hpp
src/headers/switch-pause.hpp
src/headers/switch-random.hpp
src/headers/switch-screen-region.hpp
src/headers/switch-time.hpp
src/headers/switch-transitions.hpp
src/headers/switch-window.hpp
src/headers/switch-sequence.hpp
src/headers/switch-video.hpp
src/headers/switch-generic.hpp
src/headers/macro-action-edit.hpp
src/headers/macro-action-audio.hpp
src/headers/macro-action-file.hpp
src/headers/macro-action-filter.hpp
src/headers/macro-action-hotkey.hpp
src/headers/macro-action-macro.hpp
src/headers/macro-action-media.hpp
src/headers/macro-action-plugin-state.hpp
src/headers/macro-action-recording.hpp
src/headers/macro-action-replay-buffer.hpp
src/headers/macro-action-run.hpp
src/headers/macro-action-scene-order.hpp
src/headers/macro-action-scene-switch.hpp
src/headers/macro-action-scene-transform.hpp
src/headers/macro-action-scene-visibility.hpp
src/headers/macro-action-source.hpp
src/headers/macro-action-streaming.hpp
src/headers/macro-action-virtual-cam.hpp
src/headers/macro-action-wait.hpp
src/headers/macro-condition-edit.hpp
src/headers/macro-condition-audio.hpp
src/headers/macro-condition-date.hpp
src/headers/macro-condition-macro.hpp
src/headers/macro-condition-file.hpp
src/headers/macro-condition-filter.hpp
src/headers/macro-condition-hotkey.hpp
src/headers/macro-condition-idle.hpp
src/headers/macro-condition-media.hpp
src/headers/macro-condition-plugin-state.hpp
src/headers/macro-condition-process.hpp
src/headers/macro-condition-recording.hpp
src/headers/macro-condition-region.hpp
src/headers/macro-condition-replay-buffer.hpp
src/headers/macro-condition-scene-order.hpp
src/headers/macro-condition-scene.hpp
src/headers/macro-condition-source.hpp
src/headers/macro-condition-streaming.hpp
src/headers/macro-condition-timer.hpp
src/headers/macro-condition-video.hpp
src/headers/macro-condition-virtual-cam.hpp
src/headers/macro-condition-window.hpp
src/headers/macro.hpp
src/headers/macro-selection.hpp
src/headers/curl-helper.hpp
src/headers/hotkey.hpp
src/headers/scene-selection.hpp
src/headers/screenshot-helper.hpp
src/headers/name-dialog.hpp
src/headers/duration-control.hpp
src/headers/section.hpp
src/headers/platform-funcs.hpp
src/headers/utility.hpp
src/headers/volume-control.hpp
src/headers/version.h
)
set_target_properties(
${LIB_NAME}
PROPERTIES AUTOMOC ON
AUTOUIC ON
AUTORCC ON
AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/forms")
set(advanced-scene-switcher_SOURCES
${advanced-scene-switcher_SOURCES}
src/advanced-scene-switcher.cpp
src/advanced-scene-switcher-module.c
src/switcher-data-structs.cpp
src/scene-group.cpp
src/scene-trigger.cpp
src/switch-transitions.cpp
src/switch-screen-region.cpp
src/switch-priority.cpp
src/switch-executable.cpp
src/switch-idle.cpp
src/switch-sequence.cpp
src/switch-file.cpp
src/switch-window.cpp
src/switch-media.cpp
src/switch-network.cpp
src/hotkey.cpp
src/general.cpp
src/switch-pause.cpp
src/switch-random.cpp
src/switch-time.cpp
src/switch-audio.cpp
src/switch-video.cpp
src/switch-generic.cpp
src/macro-action-edit.cpp
src/macro-action-audio.cpp
src/macro-action-file.cpp
src/macro-action-filter.cpp
src/macro-action-hotkey.cpp
src/macro-action-macro.cpp
src/macro-action-media.cpp
src/macro-action-plugin-state.cpp
src/macro-action-recording.cpp
src/macro-action-replay-buffer.cpp
src/macro-action-run.cpp
src/macro-action-scene-order.cpp
src/macro-action-scene-switch.cpp
src/macro-action-scene-transform.cpp
src/macro-action-scene-visibility.cpp
src/macro-action-source.cpp
src/macro-action-streaming.cpp
src/macro-action-virtual-cam.cpp
src/macro-action-wait.cpp
src/macro-condition-edit.cpp
src/macro-condition-audio.cpp
src/macro-condition-date.cpp
src/macro-condition-macro.cpp
src/macro-condition-file.cpp
src/macro-condition-filter.cpp
src/macro-condition-hotkey.cpp
src/macro-condition-idle.cpp
src/macro-condition-media.cpp
src/macro-condition-plugin-state.cpp
src/macro-condition-process.cpp
src/macro-condition-recording.cpp
src/macro-condition-region.cpp
src/macro-condition-replay-buffer.cpp
src/macro-condition-scene-order.cpp
src/macro-condition-scene.cpp
src/macro-condition-source.cpp
src/macro-condition-streaming.cpp
src/macro-condition-timer.cpp
src/macro-condition-video.cpp
src/macro-condition-virtual-cam.cpp
src/macro-condition-window.cpp
src/macro.cpp
src/macro-selection.cpp
src/macro-tab.cpp
src/curl-helper.cpp
src/scene-selection.cpp
src/screenshot-helper.cpp
src/name-dialog.cpp
src/duration-control.cpp
src/section.cpp
src/utility.cpp
src/volume-control.cpp
src/version.cpp
)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)
target_compile_features(${LIB_NAME} PUBLIC cxx_std_17)
set(advanced-scene-switcher_UI
${advanced-scene-switcher_UI}
forms/advanced-scene-switcher.ui
)
add_definitions(-DASIO_STANDALONE)
target_include_directories(
${LIB_NAME}
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp"
"${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib"
"${CMAKE_CURRENT_SOURCE_DIR}/deps/exprtk")
if(WIN32)
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
# --- End of section ---
set(advanced-scene-switcher_PLATFORM_SOURCES
src/win/advanced-scene-switcher-win.cpp)
elseif(APPLE)
set(advanced-scene-switcher_PLATFORM_SOURCES
src/osx/advanced-scene-switcher-osx.mm)
set_source_files_properties(advanced-scene-switcher-osx.mm
PROPERTIES COMPILE_FLAGS "-fobjc-arc")
set(advanced-scene-switcher_PLATFORM_LIBS
${COCOA})
# --- Windows-specific build settings and tasks ---
if(OS_WINDOWS)
configure_file(cmake/bundle/windows/installer-Windows.iss.in
${CMAKE_CURRENT_BINARY_DIR}/installer-Windows.generated.iss)
target_compile_definitions(${LIB_NAME} PRIVATE UNICODE _UNICODE)
if(MSVC)
target_compile_options(${LIB_NAME} PUBLIC /MP /d2FH4- /wd4267 /wd4267
/bigobj)
endif()
target_sources(${LIB_NAME} PRIVATE src/win/advanced-scene-switcher-win.cpp)
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
set_property(TARGET ${LIB_NAME} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS true)
# --- End of section ---
# -- macOS specific build settings and tasks --
elseif(OS_MACOS)
configure_file(cmake/bundle/macos/installer-macos.pkgproj.in
${CMAKE_CURRENT_BINARY_DIR}/installer-macos.generated.pkgproj)
set(MACOSX_PLUGIN_GUI_IDENTIFIER "${MACOS_BUNDLEID}")
set(MACOSX_PLUGIN_BUNDLE_VERSION "${PROJECT_VERSION}")
set(MACOSX_PLUGIN_SHORT_VERSION_STRING "1")
target_compile_options(
${LIB_NAME} PRIVATE -Wall -Wextra -Werror-implicit-function-declaration
-stdlib=libc++ -fvisibility=default)
set_target_properties(${LIB_NAME} PROPERTIES PREFIX "" SUFFIX ".so")
find_library(COCOA Cocoa)
target_include_directories(${LIB_NAME} PRIVATE ${COCOA})
target_link_libraries(${LIB_NAME} PRIVATE ${COCOA})
find_package(CURL)
find_package(Libcurl)
if(CURL_FOUND)
target_include_directories(${LIB_NAME} PRIVATE "${CURL_INCLUDE_DIRS}")
elseif(Libcurl_FOUND)
target_include_directories(${LIB_NAME} PRIVATE "${LIBCURL_INCLUDE_DIRS}")
else()
message(FATAL_ERROR "Couldn't find CURL or Libcurl - abort")
endif()
target_sources(${LIB_NAME} PRIVATE src/osx/advanced-scene-switcher-osx.mm)
set_source_files_properties(advanced-scene-switcher-osx.mm
PROPERTIES COMPILE_FLAGS "-fobjc-arc")
# --- End of section ---
# --- Linux-specific build settings and tasks ---
else()
set(advanced-scene-switcher_PLATFORM_SOURCES
src/linux/advanced-scene-switcher-nix.cpp)
set(advanced-scene-switcher_PLATFORM_LIBS
Xss)
set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN")
target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra)
set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
set_target_properties(${LIB_NAME} PROPERTIES SOVERSION 1)
find_package(X11 REQUIRED COMPONENTS Xtst Xss)
target_include_directories(
${LIB_NAME} PRIVATE "${X11_INCLUDE_DIR}" "${X11_Xtst_INCLUDE_PATH}"
"${X11_Xss_INCLUDE_PATH}")
target_link_libraries(${LIB_NAME} PRIVATE ${X11_LIBRARIES})
find_path(PROCPS_INCLUDE_DIR NAMES proc/procps.h)
find_path(PROCPS2_INCLUDE_DIR NAMES libproc2/pids.h)
find_library(PROCPS_LIBRARY NAMES procps)
find_library(PROCPS2_LIBRARY NAMES proc2)
if(PROCPS_INCLUDE_DIR AND PROCPS_LIBRARY)
message(STATUS "${PROJECT_NAME} using procps")
set(PROC_INCLUDE_DIR "${PROCPS_INCLUDE_DIR}")
set(PROC_LIBRARY "${PROCPS_LIBRARY}")
target_compile_definitions(${LIB_NAME} PRIVATE USE_PROCPS)
elseif(PROCPS2_INCLUDE_DIR AND PROCPS2_LIBRARY)
message(STATUS "${PROJECT_NAME} using libproc2")
set(PROC_INCLUDE_DIR "${PROCPS2_INCLUDE_DIR}")
set(PROC_LIBRARY "${PROCPS2_LIBRARY}")
else()
message(
FATAL_ERROR
"found neither procps nor libproc2!
please either set ...
PROCPS_INCLUDE_DIR and PROCPS_LIBRARY
... or ...
PROCPS2_INCLUDE_DIR and PROCPS2_LIBRARY")
endif()
target_link_libraries(${LIB_NAME} PRIVATE "${PROC_LIBRARY}")
target_include_directories(${LIB_NAME} PRIVATE "${PROC_INCLUDE_DIR}")
find_package(CURL)
find_package(Libcurl)
if(CURL_FOUND)
target_include_directories(${LIB_NAME} PRIVATE "${CURL_INCLUDE_DIRS}")
elseif(Libcurl_FOUND)
target_include_directories(${LIB_NAME} PRIVATE "${LIBCURL_INCLUDE_DIRS}")
else()
message(FATAL_ERROR "Couldn't find CURL or Libcurl - abort")
endif()
target_sources(${LIB_NAME} PRIVATE src/linux/advanced-scene-switcher-nix.cpp)
endif()
# --- End of section ---
qt5_wrap_ui(advanced-scene-switcher_UI_HEADERS
${advanced-scene-switcher_UI}
${advanced-scene-switcher_PLATFORM_UI})
add_library(advanced-scene-switcher MODULE
${advanced-scene-switcher_HEADERS}
${advanced-scene-switcher_SOURCES}
${advanced-scene-switcher_UI_HEADERS}
${advanced-scene-switcher_PLATFORM_SOURCES}
${advanced-scene-switcher_PLATFORM_HEADERS}
)
if(BUILD_OUT_OF_TREE)
include_directories(
"${LIBOBS_INCLUDE_DIRS}"
"${LIBOBS_FRONTEND_INCLUDE_DIR}"
${Qt5Core_INCLUDES}
${Qt5Widgets_INCLUDES}
${LIBCURL_INCLUDE_DIRS})
target_link_libraries(advanced-scene-switcher
${advanced-scene-switcher_PLATFORM_LIBS}
${LIBOBS_LIB}
${LIBOBS_FRONTEND_API_LIB}
Qt5::Core
Qt5::Widgets)
# Additional commands to install the module in the correct place.
# Find all the translation files so we can copy them to the correct
# place later on.
file(GLOB ASS_TRANSLATION_FILES
"data/locale/*.ini"
)
# Windows
if(WIN32)
string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
message("${CMAKE_CXX_FLAGS_RELEASE}")
find_package(w32-pthreads REQUIRED)
target_link_libraries(advanced-scene-switcher
w32-pthreads)
endif()
# OSX
if(APPLE)
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
endif()
# Linux
if(UNIX AND NOT APPLE)
set(CMAKE_C_FLAGS "-Wall -Wextra -Wvla -Wno-unused-function -Werror-implicit-function-declaration -Wno-missing-braces -Wno-missing-field-initializers ${CMAKE_C_FLAGS} -std=c99 -fno-strict-aliasing")
if(ARCH EQUAL 64)
set(ARCH_NAME "x86_64")
else()
set(ARCH_NAME "i686")
endif()
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
install(TARGETS advanced-scene-switcher
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/obs-plugins)
install(FILES ${ASS_TRANSLATION_FILES}
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/obs/obs-plugins/advanced-scene-switcher/locale")
endif()
if(DEB_INSTALL)
file(GLOB ASS_TRANSLATION_FILES "data/locale/*.ini")
if(NOT LIB_OUT_DIR)
set(LIB_OUT_DIR "/lib/obs-plugins")
endif()
if(NOT DATA_OUT_DIR)
set(DATA_OUT_DIR "/share/obs/obs-plugins/${PROJECT_NAME}")
endif()
install(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_OUT_DIR})
install(TARGETS ${LIB_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_OUT_DIR})
install(DIRECTORY data/locale
DESTINATION ${CMAKE_INSTALL_PREFIX}/${DATA_OUT_DIR})
install(DIRECTORY data/res
DESTINATION ${CMAKE_INSTALL_PREFIX}/${DATA_OUT_DIR})
else()
target_link_libraries(advanced-scene-switcher
${advanced-scene-switcher_PLATFORM_LIBS}
obs-frontend-api
Qt5::Widgets
libobs)
install_obs_plugin_with_data(advanced-scene-switcher data)
setup_plugin_target(${PROJECT_NAME})
install_advss_lib(${LIB_NAME})
endif()
# --- End of section ---
add_subdirectory(src/macro-external)
add_subdirectory(tests)

134
README.md
View File

@@ -1,119 +1,37 @@
# SceneSwitcher
An automated scene switcher for OBS Studio
An automation plugin for OBS Studio.
More information can be found on https://obsproject.com/forum/resources/automatic-scene-switching.395/ and see https://github.com/WarmUpTill/SceneSwitcher/blob/master/CI/release/README.txt for installing releases.
More information can be found on https://obsproject.com/forum/resources/automatic-scene-switching.395/.
## Compiling in tree (recommended)
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
## Downloads
Binaries for Windows, MacOS, and Linux are available in the [Releases](https://github.com/WarmUpTill/SceneSwitcher/releases) section.
## Installing the plugin
For the **Windows** and **MacOS** platforms, it is recommended to run the provided installers.
For **Linux** the **Snap** package manager offers an OBS Studio installation which is bundled with the plugin:
```
cd obs-studio/UI/frontend-plugins/
git clone https://github.com/WarmUpTill/SceneSwitcher.git
sudo snap install obs-studio
```
The plugin is also available via the **Flatpak** package manager for users who installed OBS via Flatpak:
```
flatpak install com.obsproject.Studio.Plugin.SceneSwitcher
```
Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt file and add an entry for the scene switcher:
add_subdirectory(SceneSwitcher)
## Compiling out of tree
### Prerequisites
You'll need CMake and a working development environment for OBS Studio installed
on your computer. Once you've done that, do the following:
Also note that the Linux version of this plugin has the following dependencies to `XTest`, `XScreensaver` and optionally `OpenCV`.
If `apt` is supported on your system they can be installed using:
```
git clone https://github.com/WarmUpTill/SceneSwitcher.git
cd SceneSwitcher
mkdir build && cd build
sudo apt-get install \
libxtst-dev \
libxss-dev \
libprocps-dev \
libopencv-dev
```
### Windows
In cmake-gui, you'll have to set these CMake variables :
- **BUILD_OUT_OF_TREE** (bool) : true
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
code of OBS Studio, located at [source_directory]/libobs/.
- **LIBOBS_LIB** (filepath) : location of the obs.dll file (usually set to
C:\Program Files\obs-studio\bin\64bit\obs.dll)
## Contributing
Assuming that you installed Qt via the regular Qt App way:
- **Qt5Core_DIR** (path) : C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Core
- **Qt5Gui_DIR** (path): C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Gui
- **Qt5Widgets_DIR** (path) : C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Widgets
- If you wish to contribute code to the project, have a look at this [section](BUILDING.md) describing how to compile the plugin.
- If you wish to contribute translations, feel free to submit pull requests for the corresponding files under `data/locale`.
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.dll
file, usually C:/Program Files/obs-studio/bin/64bit/obs-frontend-api.dll
(usually in the same place as LIBOBS_LIB)
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
subfolder in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
Just keep hitting configure until all the vars are filled out. Then hit generate.
### Linux
Most versions of Linux you can use cmake-gui or the command line.
**For the command line:**
```
cmake -DBUILD_OUT_OF_TREE=1 -DLIBOBS_INCLUDE_DIR="<path to the libobs/ sub-folder in obs-studio's source code>" \
-DLIBOBS_FRONTEND_INCLUDE_DIR="<path to the UI/obs-frontend-api/ sub-folder in obs-studio's source code>" \
-DLIBOBS_LIB="<path to the libobs.so file>" \
-DLIBOBS_FRONTEND_API_LIB="<path to the libobs-frontend-api.so file (usually in the same place as LIBOBS_LIB)>" \
-DCMAKE_INSTALL_PREFIX=/usr ..
make -j4
sudo make install
```
For cmake-gui you'll have to set the following variables:
- **BUILD_OUT_OF_TREE** (bool) : true
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
code of OBS Studio, located at [source_directory]/libobs/.
- **LIBOBS_LIB** (filepath) : location of the libobs.so file (usually CMake finds
this, but if not it'll usually be in /usr/lib/libobs.so)
Assuming that you installed Qt via your system package manager, it should be
found automatically. If not, then usually you'll find it in something like:
- **Qt5Core_DIR** (path) : /usr/lib64/cmake/Qt5Core
- **Qt5Gui_DIR** (path): /usr/lib64/cmake/Qt5Gui
- **Qt5Widgets_DIR** (path) : /usr/lib64/cmake/Qt5Widgets
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.so
file (usually in the same place as LIBOBS_LIB)
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
subfolder in the source code of OBS Studio, located at
[source_directory]/UI/obs-frontend-api.
Just keep hitting configure until all the vars are filled out. Then hit generate.
Then open a terminal in the build folder and type:
```
make -j4
sudo make install
```
NOTE: The Linux version of this plugin is dependent on libXScrnSaver.
### OS X
In cmake-gui, you'll have to set these CMake variables :
- **BUILD_OUT_OF_TREE** (bool) : true
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
code of OBS Studio, located at [source_directory]/libobs/.
- **LIBOBS_LIB** (filepath) : location of the libobs.0.dylib file (usually
in /Applications/OBS.app/Contents/Resources/bin/libobs.0.dylib)
Assuming that you installed Qt via the regular Qt App way:
- **Qt5Core_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Core
- **Qt5Widgets_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Widgets
- **Qt5MacExtras_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5MacExtras
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.0.dylib
file (usually in usually in /Applications/OBS.app/Contents/Resources/bin/libobs-frontend-api.0.dylib)
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api subfolder
in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
Just keep hitting configure until all the vars are filled out. Then hit generate.
Open xcode (or a terminal, depending on the build type you chose), build and copy
the advanced-scene-switcher.so file to /Applications/OBS.app/Contents/PlugIns
Note that you might have to adjust the library search paths using the install_name_tool if you want the plugin to run on machines other than your build machine:
```
install_name_tool -change @rpath/libobs-frontend-api.dylib @executable_path/../Frameworks/libobs-frontend-api.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
install_name_tool -change /usr/local/opt/qt5/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
install_name_tool -change /usr/local/opt/qt5/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
install_name_tool -change /usr/local/opt/qt5/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
```

83
buildspec.json Normal file
View File

@@ -0,0 +1,83 @@
{
"dependencies": {
"obs-studio": {
"version": "28.0.1",
"repository": "https://github.com/obsproject/obs-studio.git",
"branch": "master",
"hash": "e8dc70d0eef4503378d6ac300e680215eb5c9379"
},
"prebuilt": {
"version": "2022-08-02",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-built obs-deps",
"hashes": {
"macos-x86_64": "7637e52305e6fc53014b5aabd583f1a4490b1d97450420e977cae9a336a29525",
"macos-arm64": "755e0fa69b17a3ae444e1befa9d91d77e3cafe628fbd1c6333686091826595cd",
"macos-universal": "de057e73e6fe0825664c258ca2dd6798c41ae580bf4d896e1647676a4941934a",
"windows-x64": "2192d8ce780c4281b807cd457994963669e5202659ecd92f19b54c3e7d0c1915",
"windows-x86": "9f8582ab5891b000869d6484ea591add9fbac9f1c91b56c7b85fdfd56a261c1b"
}
},
"qt5": {
"version": "2022-08-02",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-built Qt5",
"hashes": {
"macos-x86_64": "3d0381a52b0e4d49967936c4357f79ac711f43564329304a6db5c90edadd2697",
"macos-arm64": "f4b32548c0530f121956bf0a9a70c36ecbbfca81073d39c396a1759baf2a05c3",
"macos-universal": "9a6cf3b9a6c9efee6ba10df649202e8075e99f3c54ae88dc9a36dbc9d7471c1e",
"windows-x64": "6488a33a474f750d5a4a268a5e20c78bb40799d99136a1b7ce3365a843cb2fd7",
"windows-x86": "a916e09b0a874036801deab2c8a7ec14fdf5d268aa5511eac5bf40727e0c4e33"
},
"pdb-hashes": {
"windows-x64": "e0e5070143fcad9311a68ce5685d8ba8f34f581ed6942b7a92d360f94ca1ba11",
"windows-x86": "36642d1052aa461964f46c17610477b0d9b9defbe2d745ccaacb85f805c1bec2"
}
},
"qt6": {
"version": "2022-08-02",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-built Qt6",
"hashes": {
"macos-x86_64": "a83f72a11023b03b6cb2dc365f0a66ad9df31163bbb4fe2df32d601856a9fad3",
"macos-arm64": "2f30af90c049670a5660656adbb440668aa1b0567f75a5f29e1def9108928403",
"macos-universal": "252e6684f43ab9c6f262c73af739e2296ce391b998da2c4ee04c254aaa07db18",
"windows-x64": "e5509b54196a3f935250cc4b9c54160c8e588fd0f92bc078a2a64f9d9e2e4e93",
"windows-x86": "24fc03bef153a0e027c1479e42eb08097a4ea1d70a4710825be0783d0626cb0d"
},
"pdb-hashes": {
"windows-x64": "60e5b1d2bc4d7c431bc05f14e3b1e85e088788c372fa85f58717cd6c49555a46",
"windows-x86": "f34d1a89fc85d92913bd6c7f75ec5c28471d74db708c98161100bc8b75f8fc63"
}
}
},
"platformConfig": {
"macos-x86_64": {
"qtVersion": 6,
"deploymentTarget": "10.15"
},
"macos-arm64": {
"qtVersion": 6,
"deploymentTarget": "11.0"
},
"macos-universal": {
"qtVersion": 6,
"deploymentTarget": "10.15"
},
"windows-x64": {
"qtVersion": 6,
"visualStudio": "Visual Studio 17 2022",
"platformSDK": "10.0.20348.0"
},
"windows-x86": {
"qtVersion": 6,
"visualStudio": "Visual Studio 17 2022",
"platformSDK": "10.0.20348.0"
},
"linux-x86_64": {
"qtVersion": 6
}
},
"name": "advanced-scene-switcher",
"version": "1.0.0"
}

312
cmake/AdvSSHelpers.cmake Normal file
View File

@@ -0,0 +1,312 @@
# --- Helper functions ---#
# Subfolder for advanced scene switcher plugins
set(_PLUGIN_FOLDER "adv-ss-plugins")
# --- MACOS section ---
if(OS_MACOS)
set(ADVSS_BUNDLE_DIR "${CMAKE_INSTALL_PREFIX}/advanced-scene-switcher.plugin")
set(ADVSS_BUNDLE_MODULE_DIR "${ADVSS_BUNDLE_DIR}/Contents/MacOS")
set(ADVSS_BUNDLE_PLUGIN_DIR ${ADVSS_BUNDLE_MODULE_DIR}/${_PLUGIN_FOLDER})
function(resign_advss target)
set(_COMMAND "codesign --force --deep --sign - ${ADVSS_BUNDLE_DIR}")
install(CODE "execute_process(COMMAND /bin/sh -c \"${_COMMAND}\")")
endfunction()
function(install_advss_lib_helper target where)
install(
TARGETS ${target}
RUNTIME DESTINATION "${where}" COMPONENT advss_plugins
LIBRARY DESTINATION "${where}" COMPONENT advss_plugins
FRAMEWORK DESTINATION "${where}" COMPONENT advss_plugins)
resign_advss(${target})
endfunction()
function(install_advss_lib target)
install_advss_lib_helper(${target} "${ADVSS_BUNDLE_MODULE_DIR}")
set(_COMMAND
"${CMAKE_INSTALL_NAME_TOOL} \\
-change @rpath/advanced-scene-switcher-lib.so @loader_path/advanced-scene-switcher-lib.so \\
\\\"${ADVSS_BUNDLE_MODULE_DIR}/advanced-scene-switcher\\\"")
install(CODE "execute_process(COMMAND /bin/sh -c \"${_COMMAND}\")"
COMPONENT obs_plugins)
endfunction()
function(install_advss_plugin target)
install_advss_lib_helper(${target} "${ADVSS_BUNDLE_PLUGIN_DIR}")
endfunction()
function(install_advss_plugin_dependency_target target dep)
install(
IMPORTED_RUNTIME_ARTIFACTS
${dep}
RUNTIME
DESTINATION
"${ADVSS_BUNDLE_PLUGIN_DIR}"
COMPONENT
${dep}_Runtime
LIBRARY
DESTINATION
"${ADVSS_BUNDLE_PLUGIN_DIR}"
COMPONENT
${dep}_Runtime
NAMELINK_COMPONENT
${dep}_Development)
resign_advss(${target})
endfunction()
function(install_advss_plugin_dependency_file ${target} dep)
target_sources(advanced-scene-switcher PRIVATE ${dep})
set_source_files_properties(${dep} PROPERTIES MACOSX_PACKAGE_LOCATION
${ADVSS_BUNDLE_PLUGIN_DIR})
resign_advss(${target})
endfunction()
# --- End of section ---
else()
# --- Windows / Linux section ---
function(plugin_install_helper what where where_deb)
if(DEB_INSTALL)
if(NOT LIB_OUT_DIR)
set(LIB_OUT_DIR "/lib/obs-plugins")
endif()
install(
TARGETS ${what}
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_OUT_DIR}/${where_deb})
else()
install(
TARGETS ${what}
RUNTIME DESTINATION "${where}" COMPONENT ${what}_Runtime
LIBRARY DESTINATION "${where}"
COMPONENT ${what}_Runtime
NAMELINK_COMPONENT ${what}_Development)
install(
FILES $<TARGET_FILE:${what}>
DESTINATION $<CONFIG>/${where}
COMPONENT ${what}_rundir
EXCLUDE_FROM_ALL)
endif()
if(OS_WINDOWS)
install(
FILES $<TARGET_PDB_FILE:${what}>
CONFIGURATIONS "RelWithDebInfo" "Debug"
DESTINATION ${where}
COMPONENT ${what}_Runtime
OPTIONAL)
install(
FILES $<TARGET_PDB_FILE:${what}>
CONFIGURATIONS "RelWithDebInfo" "Debug"
DESTINATION $<CONFIG>/${where}
COMPONENT ${what}_rundir
OPTIONAL EXCLUDE_FROM_ALL)
endif()
add_custom_command(
TARGET ${what}
POST_BUILD
COMMAND
"${CMAKE_COMMAND}" -DCMAKE_INSTALL_PREFIX=${OBS_OUTPUT_DIR}
-DCMAKE_INSTALL_COMPONENT=${what}_rundir
-DCMAKE_INSTALL_CONFIG_NAME=$<CONFIG> -P
${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake
COMMENT "Installing ${what} to plugin rundir ${OBS_OUTPUT_DIR}/${where}\n"
VERBATIM)
endfunction()
function(install_advss_lib target)
plugin_install_helper("${target}" "${OBS_PLUGIN_DESTINATION}" "")
if(OS_POSIX)
set_target_properties(${target} PROPERTIES INSTALL_RPATH "$ORIGIN")
endif()
endfunction()
function(install_advss_plugin target)
plugin_install_helper(
"${target}" "${OBS_PLUGIN_DESTINATION}/${_PLUGIN_FOLDER}"
"${_PLUGIN_FOLDER}")
if(OS_POSIX)
set_target_properties(${target} PROPERTIES INSTALL_RPATH
"$ORIGIN:$ORIGIN/..")
endif()
message(STATUS "ADVSS: ENABLED PLUGIN ${target}")
endfunction()
function(install_advss_plugin_dependency_target target dep)
install(
IMPORTED_RUNTIME_ARTIFACTS
${dep}
RUNTIME
DESTINATION
"${OBS_PLUGIN_DESTINATION}/${_PLUGIN_FOLDER}"
COMPONENT
${dep}_Runtime
LIBRARY
DESTINATION
"${OBS_PLUGIN_DESTINATION}/${_PLUGIN_FOLDER}"
COMPONENT
${dep}_Runtime
NAMELINK_COMPONENT
${dep}_Development)
install(
IMPORTED_RUNTIME_ARTIFACTS
${dep}
RUNTIME
DESTINATION
"${OBS_PLUGIN_DESTINATION}/${_PLUGIN_FOLDER}"
COMPONENT
obs_${dep}
EXCLUDE_FROM_ALL
LIBRARY
DESTINATION
"${OBS_PLUGIN_DESTINATION}/${_PLUGIN_FOLDER}"
COMPONENT
obs_${dep}
EXCLUDE_FROM_ALL)
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND
"${CMAKE_COMMAND}" --install .. --config $<CONFIG> --prefix
${OBS_OUTPUT_DIR}/$<CONFIG> --component obs_${dep} >
"$<IF:$<PLATFORM_ID:Windows>,nul,/dev/null>"
COMMENT "Installing ${dep} to OBS rundir\n"
VERBATIM)
endfunction()
function(install_advss_plugin_dependency_file target dep)
get_filename_component(_FILENAME ${dep} NAME)
string(REGEX REPLACE "\\.[^.]*$" "" _FILENAMENOEXT ${_FILENAME})
set(_DEP_NAME "${target}-${_FILENAMENOEXT}")
install(
FILES "${dep}"
DESTINATION "${OBS_PLUGIN_DESTINATION}/${_PLUGIN_FOLDER}"
COMPONENT ${_DEP_NAME}_Runtime
DESTINATION "${OBS_PLUGIN_DESTINATION}/${_PLUGIN_FOLDER}"
COMPONENT ${_DEP_NAME}_Runtime
NAMELINK_COMPONENT ${_DEP_NAME}_Development)
install(
FILES "${dep}"
DESTINATION "${OBS_PLUGIN_DESTINATION}/${_PLUGIN_FOLDER}"
COMPONENT obs_${_DEP_NAME}
EXCLUDE_FROM_ALL
DESTINATION "${OBS_PLUGIN_DESTINATION}/${_PLUGIN_FOLDER}"
COMPONENT obs_${_DEP_NAME}
EXCLUDE_FROM_ALL)
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND
"${CMAKE_COMMAND}" --install .. --config $<CONFIG> --prefix
${OBS_OUTPUT_DIR}/$<CONFIG> --component obs_${_DEP_NAME} >
"$<IF:$<PLATFORM_ID:Windows>,nul,/dev/null>"
COMMENT "Installing ${_DEP_NAME} to OBS rundir\n"
VERBATIM)
endfunction()
endif()
# --- End of section ---
function(setup_obs_lib_dependency target)
if(BUILD_OUT_OF_TREE)
find_package(libobs)
if(libobs_FOUND AND NOT LIBOBS_LIB)
target_link_libraries(${target} PUBLIC OBS::libobs)
else()
if(NOT LIBOBS_LIB)
message(FATAL_ERROR "obs library not found - please set LIBOBS_LIB")
endif()
target_link_libraries(${target} PUBLIC ${LIBOBS_LIB})
if(NOT LIBOBS_INCLUDE_DIR)
message(
FATAL_ERROR "obs.hpp header not found - please set LIBOBS_INCLUDE_DIR"
)
endif()
target_include_directories(${target} PRIVATE ${LIBOBS_INCLUDE_DIR})
endif()
find_package(obs-frontend-api)
if(obs-frontend-api_FOUND AND NOT LIBOBS_FRONTEND_API_LIB)
target_link_libraries(${target} PUBLIC OBS::obs-frontend-api)
else()
if(NOT LIBOBS_FRONTEND_API_LIB)
message(
FATAL_ERROR
"libobs frontend-api library not found - please set LIBOBS_FRONTEND_API_LIB"
)
endif()
target_link_libraries(${target} PUBLIC ${LIBOBS_FRONTEND_API_LIB})
if(NOT LIBOBS_FRONTEND_INCLUDE_DIR)
message(
FATAL_ERROR
" obs-frontend-api.h not found - please set LIBOBS_FRONTEND_INCLUDE_DIR"
)
endif()
target_include_directories(${target}
PRIVATE ${LIBOBS_FRONTEND_INCLUDE_DIR})
endif()
else()
target_link_libraries(${target} PUBLIC OBS::libobs OBS::frontend-api)
endif()
endfunction()
function(setup_advss_plugin target)
setup_obs_lib_dependency(${target})
find_qt(COMPONENTS Widgets Core)
target_link_libraries(${target} PRIVATE Qt::Core Qt::Widgets)
set_target_properties(
${target}
PROPERTIES AUTOMOC ON
AUTOUIC ON
AUTORCC ON)
target_link_libraries(${target} PRIVATE advanced-scene-switcher-lib)
get_target_property(ADVSS_SOURCE_DIR advanced-scene-switcher-lib SOURCE_DIR)
get_target_property(ADVSS_BINARY_DIR advanced-scene-switcher-lib BINARY_DIR)
if(OS_MACOS)
set(_INSTALL_RPATH "@loader_path" "@loader_path/..")
set_target_properties(${target} PROPERTIES INSTALL_RPATH
"${_INSTALL_RPATH}")
endif()
# Set up include directories for headers generated by Qt
target_include_directories(
${target}
PRIVATE "${ADVSS_BINARY_DIR}/advanced-scene-switcher-lib_autogen/include")
foreach(_CONF Release RelWithDebInfo Debug MinSizeRe)
target_include_directories(
${target}
PRIVATE
"${ADVSS_BINARY_DIR}/advanced-scene-switcher-lib_autogen/include_${_CONF}"
)
endforeach()
# General includes
target_include_directories(
${target}
PRIVATE "${ADVSS_SOURCE_DIR}/src" "${ADVSS_SOURCE_DIR}/src/legacy"
"${ADVSS_SOURCE_DIR}/src/macro-core"
"${ADVSS_SOURCE_DIR}/src/utils" "${ADVSS_SOURCE_DIR}/forms")
endfunction()
function(install_advss_plugin_dependency)
cmake_parse_arguments(PARSED_ARGS "" "TARGET" "DEPENDENCIES" ${ARGN})
if(NOT PARSED_ARGS_TARGET)
message(FATAL_ERROR "You must provide a target")
endif()
set(_PLUGIN_FOLDER "adv-ss-plugins")
foreach(_DEPENDENCY ${PARSED_ARGS_DEPENDENCIES})
if(EXISTS ${_DEPENDENCY})
install_advss_plugin_dependency_file(${PARSED_ARGS_TARGET} ${_DEPENDENCY})
else()
install_advss_plugin_dependency_target(${PARSED_ARGS_TARGET}
${_DEPENDENCY})
endif()
endforeach()
endfunction()

View File

@@ -1,279 +1,269 @@
# - Returns a version string from Git
# * Returns a version string from Git
#
# These functions force a re-configure on each git commit so that you can
# trust the values of the variables in your build system.
# These functions force a re-configure on each git commit so that you can trust
# the values of the variables in your build system.
#
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git
# describe> ...])
#
# Returns the refspec and sha hash of the current head revision
#
# git_describe(<var> [<additional arguments to git describe> ...])
# git_describe(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the source tree, and adjusting
# the output so that it tests false if an error occurs.
# Returns the results of git describe on the source tree, and adjusting the
# output so that it tests false if an error occurs.
#
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the working tree (--dirty option),
# and adjusting the output so that it tests false if an error occurs.
# Returns the results of git describe on the working tree (--dirty option), and
# adjusting the output so that it tests false if an error occurs.
#
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe --exact-match on the source tree,
# and adjusting the output so that it tests false if there was no exact
# matching tag.
# Returns the results of git describe --exact-match on the source tree, and
# adjusting the output so that it tests false if there was no exact matching
# tag.
#
# git_local_changes(<var>)
# git_local_changes(<var>)
#
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
# Uses the return code of "git diff-index --quiet HEAD --".
# Does not regard untracked files.
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. Uses
# the return code of "git diff-index --quiet HEAD --". Does not regard untracked
# files.
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Original Author: 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com>
# <abiryan@ryand.net> http://academic.cleardefinition.com
#
# Copyright 2009-2013, Iowa State University.
# Copyright 2013-2020, Ryan Pavlik
# Copyright 2013-2020, Contributors
# SPDX-License-Identifier: BSL-1.0
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# Copyright 2009-2013, Iowa State University. Copyright 2013-2020, Ryan Pavlik
# Copyright 2013-2020, Contributors SPDX-License-Identifier: BSL-1.0 Distributed
# under the Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
if(__get_git_revision_description)
return()
return()
endif()
set(__get_git_revision_description YES)
# We must run the following at "include" time, not at function call time,
# to find the path to this module rather than the path to a calling list file
# We must run the following at "include" time, not at function call time, to
# find the path to this module rather than the path to a calling list file
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
# Function _git_find_closest_git_dir finds the next closest .git directory
# that is part of any directory in the path defined by _start_dir.
# The result is returned in the parent scope variable whose name is passed
# as variable _git_dir_var. If no .git directory can be found, the
# function returns an empty string via _git_dir_var.
# Function _git_find_closest_git_dir finds the next closest .git directory that
# is part of any directory in the path defined by _start_dir. The result is
# returned in the parent scope variable whose name is passed as variable
# _git_dir_var. If no .git directory can be found, the function returns an empty
# string via _git_dir_var.
#
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
# neither foo nor bar contain a file/directory .git. This wil return
# C:/bla/.git
# neither foo nor bar contain a file/directory .git. This wil return C:/bla/.git
#
function(_git_find_closest_git_dir _start_dir _git_dir_var)
set(cur_dir "${_start_dir}")
set(git_dir "${_start_dir}/.git")
while(NOT EXISTS "${git_dir}")
# .git dir not found, search parent directories
set(git_previous_parent "${cur_dir}")
get_filename_component(cur_dir ${cur_dir} DIRECTORY)
if(cur_dir STREQUAL git_previous_parent)
# We have reached the root directory, we are not in git
set(${_git_dir_var}
""
PARENT_SCOPE)
return()
endif()
set(git_dir "${cur_dir}/.git")
endwhile()
set(${_git_dir_var}
"${git_dir}"
PARENT_SCOPE)
set(cur_dir "${_start_dir}")
set(git_dir "${_start_dir}/.git")
while(NOT EXISTS "${git_dir}")
# .git dir not found, search parent directories
set(git_previous_parent "${cur_dir}")
get_filename_component(cur_dir ${cur_dir} DIRECTORY)
if(cur_dir STREQUAL git_previous_parent)
# We have reached the root directory, we are not in git
set(${_git_dir_var}
""
PARENT_SCOPE)
return()
endif()
set(git_dir "${cur_dir}/.git")
endwhile()
set(${_git_dir_var}
"${git_dir}"
PARENT_SCOPE)
endfunction()
function(get_git_head_revision _refspecvar _hashvar)
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
if(NOT "${GIT_DIR}" STREQUAL "")
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
"${GIT_DIR}")
if("${_relative_to_source_dir}" MATCHES "[.][.]")
# We've gone above the CMake root dir.
set(GIT_DIR "")
endif()
if(NOT "${GIT_DIR}" STREQUAL "")
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
"${GIT_DIR}")
if("${_relative_to_source_dir}" MATCHES "[.][.]")
# We've gone above the CMake root dir.
set(GIT_DIR "")
endif()
if("${GIT_DIR}" STREQUAL "")
set(${_refspecvar}
"GITDIR-NOTFOUND"
PARENT_SCOPE)
set(${_hashvar}
"GITDIR-NOTFOUND"
PARENT_SCOPE)
return()
endif()
# Check if the current source dir is a git submodule or a worktree.
# In both cases .git is a file instead of a directory.
#
if(NOT IS_DIRECTORY ${GIT_DIR})
# The following git command will return a non empty string that
# points to the super project working tree if the current
# source dir is inside a git submodule.
# Otherwise the command will return an empty string.
#
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse
--show-superproject-working-tree
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT "${out}" STREQUAL "")
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
${submodule})
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
ABSOLUTE)
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
else()
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
file(READ ${GIT_DIR} worktree_ref)
# The .git directory contains a path to the worktree information directory
# inside the parent git repo of the worktree.
#
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
${worktree_ref})
string(STRIP ${git_worktree_dir} git_worktree_dir)
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
endif()
else()
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
"${GIT_DATA}/grabRef.cmake" @ONLY)
include("${GIT_DATA}/grabRef.cmake")
endif()
if("${GIT_DIR}" STREQUAL "")
set(${_refspecvar}
"${HEAD_REF}"
"GITDIR-NOTFOUND"
PARENT_SCOPE)
set(${_hashvar}
"${HEAD_HASH}"
"GITDIR-NOTFOUND"
PARENT_SCOPE)
return()
endif()
# Check if the current source dir is a git submodule or a worktree. In both
# cases .git is a file instead of a directory.
#
if(NOT IS_DIRECTORY ${GIT_DIR})
# The following git command will return a non empty string that points to
# the super project working tree if the current source dir is inside a git
# submodule. Otherwise the command will return an empty string.
#
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse --show-superproject-working-tree
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT "${out}" STREQUAL "")
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE ${submodule})
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
ABSOLUTE)
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
else()
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
file(READ ${GIT_DIR} worktree_ref)
# The .git directory contains a path to the worktree information directory
# inside the parent git repo of the worktree.
#
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
${worktree_ref})
string(STRIP ${git_worktree_dir} git_worktree_dir)
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
endif()
else()
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
"${GIT_DATA}/grabRef.cmake" @ONLY)
include("${GIT_DATA}/grabRef.cmake")
set(${_refspecvar}
"${HEAD_REF}"
PARENT_SCOPE)
set(${_hashvar}
"${HEAD_HASH}"
PARENT_SCOPE)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
# TODO sanitize
#if((${ARGN}" MATCHES "&&") OR
# (ARGN MATCHES "||") OR
# (ARGN MATCHES "\\;"))
# message("Please report the following error to the project!")
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
#endif()
#message(STATUS "Arguments to execute_process: ${ARGN}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"${out}"
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
# TODO sanitize if((${ARGN}" MATCHES "&&") OR (ARGN MATCHES "||") OR (ARGN
# MATCHES "\\;")) message("Please report the following error to the project!")
# message(FATAL_ERROR "Looks like someone's doing something nefarious with
# git_describe! Passed arguments ${ARGN}") endif()
# message(STATUS "Arguments to execute_process: ${ARGN}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_describe_working_tree _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var}
"${out}"
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
set(${_var}
"${out}"
PARENT_SCOPE)
git_describe(out --exact-match ${ARGN})
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_local_changes _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(res EQUAL 0)
set(${_var}
"CLEAN"
PARENT_SCOPE)
else()
set(${_var}
"DIRTY"
PARENT_SCOPE)
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(res EQUAL 0)
set(${_var}
"CLEAN"
PARENT_SCOPE)
else()
set(${_var}
"DIRTY"
PARENT_SCOPE)
endif()
endfunction()

View File

@@ -0,0 +1,492 @@
if(POLICY CMP0087)
cmake_policy(SET CMP0087 NEW)
endif()
set(OBS_STANDALONE_PLUGIN_DIR ${CMAKE_SOURCE_DIR}/release)
set(INCLUDED_LIBOBS_CMAKE_MODULES ON)
include(GNUInstallDirs)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
set(OS_MACOS ON)
set(OS_POSIX ON)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD")
set(OS_POSIX ON)
string(TOUPPER "${CMAKE_SYSTEM_NAME}" _SYSTEM_NAME_U)
set(OS_${_SYSTEM_NAME_U} ON)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
set(OS_WINDOWS ON)
set(OS_POSIX OFF)
endif()
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND (OS_WINDOWS OR OS_MACOS))
set(CMAKE_INSTALL_PREFIX
${OBS_STANDALONE_PLUGIN_DIR}
CACHE STRING "Directory to install OBS plugin after building" FORCE)
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE
"RelWithDebInfo"
CACHE STRING
"OBS build type [Release, RelWithDebInfo, Debug, MinSizeRel]" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Release RelWithDebInfo
Debug MinSizeRel)
endif()
if(NOT QT_VERSION)
set(QT_VERSION
AUTO
CACHE STRING "OBS Qt version [AUTO, 5, 6]" FORCE)
set_property(CACHE QT_VERSION PROPERTY STRINGS AUTO 5 6)
endif()
macro(find_qt)
set(multiValueArgs COMPONENTS COMPONENTS_WIN COMPONENTS_MAC COMPONENTS_LINUX)
cmake_parse_arguments(FIND_QT "" "${oneValueArgs}" "${multiValueArgs}"
${ARGN})
set(QT_NO_CREATE_VERSIONLESS_TARGETS ON)
find_package(
Qt5
COMPONENTS Core
QUIET)
find_package(
Qt6
COMPONENTS Core
QUIET)
if(NOT _QT_VERSION AND QT_VERSION STREQUAL AUTO)
if(TARGET Qt6::Core)
set(_QT_VERSION
6
CACHE INTERNAL "")
elseif(TARGET Qt5::Core)
set(_QT_VERSION
5
CACHE INTERNAL "")
endif()
message(STATUS "Qt version: ${_QT_VERSION}")
elseif(NOT _QT_VERSION)
if(TARGET Qt${QT_VERSION}::Core)
set(_QT_VERSION
${QT_VERSION}
CACHE INTERNAL "")
else()
if(QT_VERSION EQUAL 6)
set(FALLBACK_QT_VERSION 5)
else()
set(FALLBACK_QT_VERSION 6)
endif()
message(
WARNING
"Qt${QT_VERSION} was not found, falling back to Qt${FALLBACK_QT_VERSION}"
)
if(TARGET Qt${FALLBACK_QT_VERSION}::Core)
set(_QT_VERSION
${FALLBACK_QT_VERSION}
CACHE INTERNAL "")
endif()
endif()
message(STATUS "Qt version: ${_QT_VERSION}")
endif()
set(QT_NO_CREATE_VERSIONLESS_TARGETS OFF)
if(NOT _QT_VERSION)
message(FATAL_ERROR "Neither Qt5 or Qt6 were found")
endif()
if(OS_WINDOWS)
find_package(
Qt${_QT_VERSION}
COMPONENTS ${FIND_QT_COMPONENTS} ${FIND_QT_COMPONENTS_WIN}
REQUIRED)
elseif(OS_MACOS)
find_package(
Qt${_QT_VERSION}
COMPONENTS ${FIND_QT_COMPONENTS} ${FIND_QT_COMPONENTS_MAC}
REQUIRED)
else()
find_package(
Qt${_QT_VERSION}
COMPONENTS ${FIND_QT_COMPONENTS} ${FIND_QT_COMPONENTS_LINUX}
REQUIRED)
endif()
list(APPEND FIND_QT_COMPONENTS "Core")
if("Gui" IN_LIST FIND_QT_COMPONENTS_LINUX)
list(APPEND FIND_QT_COMPONENTS_LINUX "GuiPrivate")
endif()
foreach(_COMPONENT IN LISTS FIND_QT_COMPONENTS FIND_QT_COMPONENTS_WIN
FIND_QT_COMPONENTS_MAC FIND_QT_COMPONENTS_LINUX)
if(NOT TARGET Qt::${_COMPONENT} AND TARGET Qt${_QT_VERSION}::${_COMPONENT})
add_library(Qt::${_COMPONENT} INTERFACE IMPORTED)
set_target_properties(
Qt::${_COMPONENT} PROPERTIES INTERFACE_LINK_LIBRARIES
"Qt${_QT_VERSION}::${_COMPONENT}")
endif()
endforeach()
endmacro()
file(RELATIVE_PATH RELATIVE_INSTALL_PATH ${CMAKE_SOURCE_DIR}
${CMAKE_INSTALL_PREFIX})
file(RELATIVE_PATH RELATIVE_BUILD_PATH ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
# Set up OS-specific environment and helper functions
if(OS_POSIX)
find_program(CCACHE_PROGRAM "ccache")
set(CCACHE_SUPPORT
ON
CACHE BOOL "Enable ccache support")
mark_as_advanced(CCACHE_PROGRAM)
if(CCACHE_PROGRAM AND CCACHE_SUPPORT)
set(CMAKE_CXX_COMPILER_LAUNCHER
${CCACHE_PROGRAM}
CACHE INTERNAL "")
set(CMAKE_C_COMPILER_LAUNCHER
${CCACHE_PROGRAM}
CACHE INTERNAL "")
set(CMAKE_OBJC_COMPILER_LAUNCHER
${CCACHE_PROGRAM}
CACHE INTERNAL "")
set(CMAKE_OBJCXX_COMPILER_LAUNCHER
${CCACHE_PROGRAM}
CACHE INTERNAL "")
set(CMAKE_CUDA_COMPILER_LAUNCHER
${CCACHE_PROGRAM}
CACHE INTERNAL "") # CMake 3.9+
endif()
endif()
if(OS_MACOS)
set(CMAKE_OSX_ARCHITECTURES
"x86_64"
CACHE STRING
"OBS build architecture for macOS - x86_64 required at least")
set_property(CACHE CMAKE_OSX_ARCHITECTURES PROPERTY STRINGS x86_64 arm64
"x86_64;arm64")
set(CMAKE_OSX_DEPLOYMENT_TARGET
"10.15"
CACHE STRING "OBS deployment target for macOS - 10.15+ required")
set_property(CACHE CMAKE_OSX_DEPLOYMENT_TARGET PROPERTY STRINGS 10.15 11.0
12.0 13.0)
set(OBS_BUNDLE_CODESIGN_IDENTITY
"-"
CACHE STRING "OBS code signing identity for macOS")
set(OBS_CODESIGN_ENTITLEMENTS
${CMAKE_SOURCE_DIR}/cmake/bundle/macos/entitlements.plist
CACHE INTERNAL "Path to codesign entitlements plist")
set(OBS_CODESIGN_LINKER
ON
CACHE BOOL "Enable linker code-signing on macOS (macOS 11+ required)")
# Xcode configuration
if(XCODE)
# Tell Xcode to pretend the linker signed binaries so that editing with
# install_name_tool preserves ad-hoc signatures. This option is supported by
# codesign on macOS 11 or higher. See CMake Issue 21854:
# https://gitlab.kitware.com/cmake/cmake/-/issues/21854
set(CMAKE_XCODE_GENERATE_SCHEME ON)
if(OBS_CODESIGN_LINKER)
set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "-o linker-signed")
endif()
endif()
# Set default options for bundling on macOS
set(CMAKE_MACOSX_RPATH ON)
set(CMAKE_SKIP_BUILD_RPATH OFF)
set(CMAKE_BUILD_WITH_INSTALL_RPATH OFF)
set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks/")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH OFF)
function(setup_plugin_target target)
if(NOT DEFINED MACOSX_PLUGIN_GUI_IDENTIFIER)
message(
FATAL_ERROR
"No 'MACOSX_PLUGIN_GUI_IDENTIFIER' set, but is required to build plugin bundles on macOS - example: 'com.yourname.pluginname'"
)
endif()
if(NOT DEFINED MACOSX_PLUGIN_BUNDLE_VERSION)
message(
FATAL_ERROR
"No 'MACOSX_PLUGIN_BUNDLE_VERSION' set, but is required to build plugin bundles on macOS - example: '25'"
)
endif()
if(NOT DEFINED MACOSX_PLUGIN_SHORT_VERSION_STRING)
message(
FATAL_ERROR
"No 'MACOSX_PLUGIN_SHORT_VERSION_STRING' set, but is required to build plugin bundles on macOS - example: '1.0.2'"
)
endif()
set(MACOSX_PLUGIN_BUNDLE_NAME
"${target}"
PARENT_SCOPE)
set(MACOSX_PLUGIN_BUNDLE_VERSION
"${MACOSX_BUNDLE_BUNDLE_VERSION}"
PARENT_SCOPE)
set(MACOSX_PLUGIN_SHORT_VERSION_STRING
"${MACOSX_BUNDLE_SHORT_VERSION_STRING}"
PARENT_SCOPE)
set(MACOSX_PLUGIN_EXECUTABLE_NAME
"${target}"
PARENT_SCOPE)
set(MACOSX_PLUGIN_BUNDLE_TYPE
"BNDL"
PARENT_SCOPE)
install(
TARGETS ${target}
LIBRARY DESTINATION "."
COMPONENT obs_plugins
NAMELINK_COMPONENT ${target}_Development)
if(${QT_VERSION} EQUAL 5)
set(_QT_FW_VERSION "${QT_VERSION}")
else()
set(_QT_FW_VERSION "A")
endif()
set(_COMMAND
"${CMAKE_INSTALL_NAME_TOOL} \\
-change ${CMAKE_PREFIX_PATH}/lib/QtWidgets.framework/Versions/${QT_VERSION}/QtWidgets @rpath/QtWidgets.framework/Versions/${_QT_FW_VERSION}/QtWidgets \\
-change ${CMAKE_PREFIX_PATH}/lib/QtCore.framework/Versions/${QT_VERSION}/QtCore @rpath/QtCore.framework/Versions/${_QT_FW_VERSION}/QtCore \\
-change ${CMAKE_PREFIX_PATH}/lib/QtGui.framework/Versions/${QT_VERSION}/QtGui @rpath/QtGui.framework/Versions/${_QT_FW_VERSION}/QtGui \\
\\\"\${CMAKE_INSTALL_PREFIX}/${target}.plugin/Contents/MacOS/${target}\\\""
)
install(CODE "execute_process(COMMAND /bin/sh -c \"${_COMMAND}\")"
COMPONENT obs_plugins)
unset(_QT_FW_VERSION)
if(NOT XCODE)
set(_COMMAND
"/usr/bin/codesign --force \\
--sign \\\"${OBS_BUNDLE_CODESIGN_IDENTITY}\\\" \\
--options runtime \\
--entitlements \\\"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/bundle/macOS/entitlements.plist\\\" \\
\\\"\${CMAKE_INSTALL_PREFIX}/${target}.plugin\\\"")
install(CODE "execute_process(COMMAND /bin/sh -c \"${_COMMAND}\")"
COMPONENT obs_plugins)
endif()
set_target_properties(
${target}
PROPERTIES
BUNDLE ON
BUNDLE_EXTENSION "plugin"
OUTPUT_NAME ${target}
MACOSX_BUNDLE_INFO_PLIST
"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/bundle/macOS/Plugin-Info.plist.in"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER
"${MACOSX_PLUGIN_GUI_IDENTIFIER}"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${OBS_BUNDLE_CODESIGN_IDENTITY}"
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS
"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/bundle/macOS/entitlements.plist")
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND
/bin/sh -c
"codesign --force --sign \"-\" $<$<BOOL:${OBS_CODESIGN_LINKER}>:--options linker-signed >\"$<TARGET_BUNDLE_DIR:${target}>\""
COMMENT "Codesigning ${target}"
VERBATIM)
install_bundle_resources(${target})
endfunction()
function(install_bundle_resources target)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/data)
file(GLOB_RECURSE _DATA_FILES "${CMAKE_CURRENT_SOURCE_DIR}/data/*")
foreach(_DATA_FILE IN LISTS _DATA_FILES)
file(RELATIVE_PATH _RELATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/data/
${_DATA_FILE})
get_filename_component(_RELATIVE_PATH ${_RELATIVE_PATH} PATH)
target_sources(${target} PRIVATE ${_DATA_FILE})
set_source_files_properties(
${_DATA_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION
Resources/${_RELATIVE_PATH})
string(REPLACE "\\" "\\\\" _GROUP_NAME ${_RELATIVE_PATH})
source_group("Resources\\${_GROUP_NAME}" FILES ${_DATA_FILE})
endforeach()
endif()
endfunction()
else()
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_ARCH_SUFFIX 64)
else()
set(_ARCH_SUFFIX 32)
endif()
set(OBS_OUTPUT_DIR ${CMAKE_BINARY_DIR}/rundir)
if(OS_POSIX)
option(LINUX_PORTABLE "Build portable version (Linux)" ON)
if(NOT LINUX_PORTABLE)
set(OBS_LIBRARY_DESTINATION ${CMAKE_INSTALL_LIBDIR})
set(OBS_PLUGIN_DESTINATION ${OBS_LIBRARY_DESTINATION}/obs-plugins)
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
set(OBS_DATA_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/obs)
else()
set(OBS_LIBRARY_DESTINATION bin/${_ARCH_SUFFIX}bit)
set(OBS_PLUGIN_DESTINATION obs-plugins/${_ARCH_SUFFIX}bit)
set(CMAKE_INSTALL_RPATH
"$ORIGIN/" "${CMAKE_INSTALL_PREFIX}/${OBS_LIBRARY_DESTINATION}")
set(OBS_DATA_DESTINATION "data")
endif()
if(OS_LINUX)
set(CPACK_PACKAGE_NAME "${CMAKE_PROJECT_NAME}")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${LINUX_MAINTAINER_EMAIL}")
set(CPACK_PACKAGE_VERSION "${CMAKE_PROJECT_VERSION}")
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-linux-x86_64")
set(CPACK_GENERATOR "DEB")
if(${QT_VERSION} STREQUAL "6")
set(CPACK_DEBIAN_PACKAGE_DEPENDS
"obs-studio (>= 28.0.0), libqt6core6 (>= 6.2.0), libqt6gui6 (>= 6.1.2), libqt6widgets6 (>= 6.1.2)"
)
else()
set(CPACK_DEBIAN_PACKAGE_DEPENDS
"obs-studio (>= 28.0.0), libqt5core5a (>= 5.9.0~beta), libqt5gui5 (>= 5.3.0), libqt5widgets5 (>= 5.7.0)"
)
endif()
set(CPACK_OUTPUT_FILE_PREFIX ${CMAKE_SOURCE_DIR}/release)
if(NOT LINUX_PORTABLE)
set(CPACK_SET_DESTDIR ON)
endif()
include(CPack)
endif()
else()
set(OBS_LIBRARY_DESTINATION "bin/${_ARCH_SUFFIX}bit")
set(OBS_LIBRARY32_DESTINATION "bin/32bit")
set(OBS_LIBRARY64_DESTINATION "bin/64bit")
set(OBS_PLUGIN_DESTINATION "obs-plugins/${_ARCH_SUFFIX}bit")
set(OBS_PLUGIN32_DESTINATION "obs-plugins/32bit")
set(OBS_PLUGIN64_DESTINATION "obs-plugins/64bit")
set(OBS_DATA_DESTINATION "data")
endif()
function(setup_plugin_target target)
set_target_properties(${target} PROPERTIES PREFIX "")
install(
TARGETS ${target}
RUNTIME DESTINATION "${OBS_PLUGIN_DESTINATION}"
COMPONENT ${target}_Runtime
LIBRARY DESTINATION "${OBS_PLUGIN_DESTINATION}"
COMPONENT ${target}_Runtime
NAMELINK_COMPONENT ${target}_Development)
install(
FILES $<TARGET_FILE:${target}>
DESTINATION $<CONFIG>/${OBS_PLUGIN_DESTINATION}
COMPONENT obs_rundir
EXCLUDE_FROM_ALL)
if(OS_WINDOWS)
install(
FILES $<TARGET_PDB_FILE:${target}>
CONFIGURATIONS "RelWithDebInfo" "Debug"
DESTINATION ${OBS_PLUGIN_DESTINATION}
COMPONENT ${target}_Runtime
OPTIONAL)
install(
FILES $<TARGET_PDB_FILE:${target}>
CONFIGURATIONS "RelWithDebInfo" "Debug"
DESTINATION $<CONFIG>/${OBS_PLUGIN_DESTINATION}
COMPONENT obs_rundir
OPTIONAL EXCLUDE_FROM_ALL)
endif()
if(MSVC)
target_link_options(
${target}
PRIVATE
"LINKER:/OPT:REF"
"$<$<NOT:$<EQUAL:${CMAKE_SIZEOF_VOID_P},8>>:LINKER\:/SAFESEH\:NO>"
"$<$<CONFIG:DEBUG>:LINKER\:/INCREMENTAL:NO>"
"$<$<CONFIG:RELWITHDEBINFO>:LINKER\:/INCREMENTAL:NO>")
endif()
setup_target_resources(${target} obs-plugins/${target})
if(OS_WINDOWS AND DEFINED OBS_BUILD_DIR)
setup_target_for_testing(${target} obs-plugins/${target})
endif()
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND
"${CMAKE_COMMAND}" -DCMAKE_INSTALL_PREFIX=${OBS_OUTPUT_DIR}
-DCMAKE_INSTALL_COMPONENT=obs_rundir
-DCMAKE_INSTALL_CONFIG_NAME=$<CONFIG> -P
${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake
COMMENT "Installing to plugin rundir"
VERBATIM)
endfunction()
function(setup_target_resources target destination)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/data)
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data/
DESTINATION ${OBS_DATA_DESTINATION}/${destination}
USE_SOURCE_PERMISSIONS
COMPONENT obs_plugins)
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data
DESTINATION $<CONFIG>/${OBS_DATA_DESTINATION}/${destination}
USE_SOURCE_PERMISSIONS
COMPONENT obs_rundir
EXCLUDE_FROM_ALL)
endif()
endfunction()
if(OS_WINDOWS)
function(setup_target_for_testing target destination)
install(
FILES $<TARGET_FILE:${target}>
DESTINATION $<CONFIG>/${OBS_PLUGIN_DESTINATION}
COMPONENT obs_testing
EXCLUDE_FROM_ALL)
install(
FILES $<TARGET_PDB_FILE:${target}>
CONFIGURATIONS "RelWithDebInfo" "Debug"
DESTINATION $<CONFIG>/${OBS_PLUGIN_DESTINATION}
COMPONENT obs_testing
OPTIONAL EXCLUDE_FROM_ALL)
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data/
DESTINATION $<CONFIG>/${OBS_DATA_DESTINATION}/${destination}
USE_SOURCE_PERMISSIONS
COMPONENT obs_testing
EXCLUDE_FROM_ALL)
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND
"${CMAKE_COMMAND}" -DCMAKE_INSTALL_PREFIX=${OBS_BUILD_DIR}/rundir
-DCMAKE_INSTALL_COMPONENT=obs_testing
-DCMAKE_INSTALL_CONFIG_NAME=$<CONFIG> -P
${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake
COMMENT "Installing to OBS test directory"
VERBATIM)
endfunction()
endif()
endif()

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>${MACOSX_PLUGIN_BUNDLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_PLUGIN_GUI_IDENTIFIER}</string>
<key>CFBundleVersion</key>
<string>${MACOSX_PLUGIN_BUNDLE_VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_PLUGIN_SHORT_VERSION_STRING}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_PLUGIN_EXECUTABLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>${MACOSX_PLUGIN_BUNDLE_TYPE}</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>LSMinimumSystemVersion</key>
<string>10.13</string>
</dict>
</plist>

View File

@@ -0,0 +1,17 @@
<!--?xml version="1.0" encoding="UTF-8"?-->
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<!-- Allows @executable_path to load libaries from within the .app bundle. -->
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,920 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PACKAGES</key>
<array>
<dict>
<key>MUST-CLOSE-APPLICATION-ITEMS</key>
<array/>
<key>MUST-CLOSE-APPLICATIONS</key>
<false/>
<key>PACKAGE_FILES</key>
<dict>
<key>DEFAULT_INSTALL_LOCATION</key>
<string>/</string>
<key>HIERARCHY</key>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Applications</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>509</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>BUNDLE_CAN_DOWNGRADE</key>
<false/>
<key>BUNDLE_POSTINSTALL_PATH</key>
<dict>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>BUNDLE_PREINSTALL_PATH</key>
<dict>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>../@RELATIVE_INSTALL_PATH@/@CMAKE_PROJECT_NAME@.plugin</string>
<key>PATH_TYPE</key>
<integer>1</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>3</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>plugins</string>
<key>PATH_TYPE</key>
<integer>2</integer>
<key>PERMISSIONS</key>
<integer>509</integer>
<key>TYPE</key>
<integer>2</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>obs-studio</string>
<key>PATH_TYPE</key>
<integer>2</integer>
<key>PERMISSIONS</key>
<integer>509</integer>
<key>TYPE</key>
<integer>2</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Application Support</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Automator</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Documentation</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Extensions</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Filesystems</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Frameworks</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Input Methods</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Internet Plug-Ins</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>LaunchAgents</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>LaunchDaemons</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>PreferencePanes</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Preferences</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Printers</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>PrivilegedHelperTools</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>1005</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>QuickLook</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>QuickTime</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Screen Savers</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Scripts</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Services</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Widgets</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Library</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Shared</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>1023</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Users</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>/</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<key>PAYLOAD_TYPE</key>
<integer>0</integer>
<key>PRESERVE_EXTENDED_ATTRIBUTES</key>
<false/>
<key>SHOW_INVISIBLE</key>
<false/>
<key>SPLIT_FORKS</key>
<true/>
<key>TREAT_MISSING_FILES_AS_WARNING</key>
<false/>
<key>VERSION</key>
<integer>5</integer>
</dict>
<key>PACKAGE_SCRIPTS</key>
<dict>
<key>POSTINSTALL_PATH</key>
<dict>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>PREINSTALL_PATH</key>
<dict>
<key>PATH_TYPE</key>
<integer>0</integer>
</dict>
<key>RESOURCES</key>
<array/>
</dict>
<key>PACKAGE_SETTINGS</key>
<dict>
<key>AUTHENTICATION</key>
<integer>0</integer>
<key>CONCLUSION_ACTION</key>
<integer>0</integer>
<key>FOLLOW_SYMBOLIC_LINKS</key>
<false/>
<key>IDENTIFIER</key>
<string>@MACOS_BUNDLEID@</string>
<key>LOCATION</key>
<integer>0</integer>
<key>NAME</key>
<string>@CMAKE_PROJECT_NAME@</string>
<key>OVERWRITE_PERMISSIONS</key>
<false/>
<key>PAYLOAD_SIZE</key>
<integer>-1</integer>
<key>REFERENCE_PATH</key>
<string></string>
<key>RELOCATABLE</key>
<false/>
<key>USE_HFS+_COMPRESSION</key>
<false/>
<key>VERSION</key>
<string>@CMAKE_PROJECT_VERSION@</string>
</dict>
<key>TYPE</key>
<integer>0</integer>
<key>UUID</key>
<string>@MACOS_PACKAGE_UUID@</string>
</dict>
</array>
<key>PROJECT</key>
<dict>
<key>PROJECT_COMMENTS</key>
<dict>
<key>NOTES</key>
<data>
</data>
</dict>
<key>PROJECT_PRESENTATION</key>
<dict>
<key>BACKGROUND</key>
<dict>
<key>APPAREANCES</key>
<dict>
<key>DARK_AQUA</key>
<dict/>
<key>LIGHT_AQUA</key>
<dict/>
</dict>
<key>SHARED_SETTINGS_FOR_ALL_APPAREANCES</key>
<true/>
</dict>
<key>INSTALLATION TYPE</key>
<dict>
<key>HIERARCHIES</key>
<dict>
<key>INSTALLER</key>
<dict>
<key>LIST</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>DESCRIPTION</key>
<array/>
<key>OPTIONS</key>
<dict>
<key>HIDDEN</key>
<false/>
<key>STATE</key>
<integer>1</integer>
</dict>
<key>PACKAGE_UUID</key>
<string>@MACOS_PACKAGE_UUID@</string>
<key>TITLE</key>
<array/>
<key>TYPE</key>
<integer>0</integer>
<key>UUID</key>
<string>@MACOS_INSTALLER_UUID@</string>
</dict>
</array>
<key>REMOVED</key>
<dict/>
</dict>
</dict>
<key>MODE</key>
<integer>0</integer>
</dict>
<key>INSTALLATION_STEPS</key>
<array>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewIntroductionController</string>
<key>INSTALLER_PLUGIN</key>
<string>Introduction</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewReadMeController</string>
<key>INSTALLER_PLUGIN</key>
<string>ReadMe</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewLicenseController</string>
<key>INSTALLER_PLUGIN</key>
<string>License</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewDestinationSelectController</string>
<key>INSTALLER_PLUGIN</key>
<string>TargetSelect</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewInstallationTypeController</string>
<key>INSTALLER_PLUGIN</key>
<string>PackageSelection</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewInstallationController</string>
<key>INSTALLER_PLUGIN</key>
<string>Install</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewSummaryController</string>
<key>INSTALLER_PLUGIN</key>
<string>Summary</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
</array>
<key>INTRODUCTION</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
</dict>
<key>LICENSE</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
<key>MODE</key>
<integer>0</integer>
</dict>
<key>README</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
</dict>
<key>SUMMARY</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
</dict>
<key>TITLE</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
</dict>
</dict>
<key>PROJECT_REQUIREMENTS</key>
<dict>
<key>LIST</key>
<array>
<dict>
<key>BEHAVIOR</key>
<integer>3</integer>
<key>DICTIONARY</key>
<dict>
<key>IC_REQUIREMENT_OS_DISK_TYPE</key>
<integer>1</integer>
<key>IC_REQUIREMENT_OS_DISTRIBUTION_TYPE</key>
<integer>0</integer>
<key>IC_REQUIREMENT_OS_MINIMUM_VERSION</key>
<integer>101300</integer>
</dict>
<key>IC_REQUIREMENT_CHECK_TYPE</key>
<integer>0</integer>
<key>IDENTIFIER</key>
<string>fr.whitebox.Packages.requirement.os</string>
<key>MESSAGE</key>
<array/>
<key>NAME</key>
<string>Operating System</string>
<key>STATE</key>
<true/>
</dict>
</array>
<key>RESOURCES</key>
<array/>
<key>ROOT_VOLUME_ONLY</key>
<true/>
</dict>
<key>PROJECT_SETTINGS</key>
<dict>
<key>ADVANCED_OPTIONS</key>
<dict>
<key>installer-script.domains:enable_currentUserHome</key>
<integer>1</integer>
</dict>
<key>BUILD_FORMAT</key>
<integer>0</integer>
<key>BUILD_PATH</key>
<dict>
<key>PATH</key>
<string>../@RELATIVE_BUILD_PATH@</string>
<key>PATH_TYPE</key>
<integer>1</integer>
</dict>
<key>EXCLUDED_FILES</key>
<array>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.DS_Store</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove .DS_Store files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove ".DS_Store" files created by the Finder.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.pbdevelopment</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove .pbdevelopment files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove ".pbdevelopment" files created by ProjectBuilder or Xcode.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>CVS</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.cvsignore</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.cvspass</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.svn</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.git</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.gitignore</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove SCM metadata</string>
<key>PROXY_TOOLTIP</key>
<string>Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>classes.nib</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>designable.db</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>info.nib</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Optimize nib files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>Resources Disabled</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove Resources Disabled folders</string>
<key>PROXY_TOOLTIP</key>
<string>Remove "Resources Disabled" folders.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>SEPARATOR</key>
<true/>
</dict>
</array>
<key>NAME</key>
<string>@CMAKE_PROJECT_NAME@</string>
<key>PAYLOAD_ONLY</key>
<false/>
<key>TREAT_MISSING_PRESENTATION_DOCUMENTS_AS_WARNING</key>
<false/>
</dict>
</dict>
<key>TYPE</key>
<integer>0</integer>
<key>VERSION</key>
<integer>2</integer>
</dict>
</plist>

View File

@@ -0,0 +1,64 @@
#define MyAppName "@CMAKE_PROJECT_NAME@"
#define MyAppVersion "@GIT_TAG@"
#define MyAppPublisher "@PLUGIN_AUTHOR@"
#define MyAppURL "http://www.mywebsite.com"
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{@WINDOWS_INSTALLER_UUID@}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={code:GetDirName}
DefaultGroupName={#MyAppName}
OutputBaseFilename={#MyAppName}-{#MyAppVersion}-Windows-Installer
Compression=lzma
SolidCompression=yes
DirExistsWarning=no
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "..\release\*"; Excludes: "*.zip"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\LICENSE"; Flags: dontcopy
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
[Code]
procedure InitializeWizard();
var
GPLText: AnsiString;
Page: TOutputMsgMemoWizardPage;
begin
ExtractTemporaryFile('LICENSE');
LoadStringFromFile(ExpandConstant('{tmp}\LICENSE'), GPLText);
Page := CreateOutputMsgMemoPage(wpWelcome,
'License Information', 'Please review the license terms before installing {#MyAppName}',
'Press Page Down to see the rest of the agreement. Once you are aware of your rights, click Next to continue.',
String(GPLText)
);
end;
// credit where it's due :
// following function come from https://github.com/Xaymar/obs-studio_amf-encoder-plugin/blob/master/%23Resources/Installer.in.iss#L45
function GetDirName(Value: string): string;
var
InstallPath: string;
begin
// initialize default path, which will be returned when the following registry
// key queries fail due to missing keys or for some different reason
Result := '{autopf}\obs-studio';
// query the first registry value; if this succeeds, return the obtained value
if RegQueryStringValue(HKLM32, 'SOFTWARE\OBS Studio', '', InstallPath) then
Result := InstallPath
end;

View File

@@ -1,3 +1,5 @@
#include "src/headers/version.h"
#include "version.h"
#define GIT_SHA1 "@GIT_SHA1@"
const char g_GIT_SHA1[] = GIT_SHA1;
#define GIT_TAG "@GIT_TAG@"
const char g_GIT_SHA1[] = GIT_SHA1;
const char g_GIT_TAG[] = GIT_TAG;

View File

@@ -24,11 +24,14 @@ AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Kann nur so gen
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Nicht wechseln"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Wechsle zu einer Szene auf dem Zufall-Tab"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Wechsle zu:"
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Nach einem automatisierten Szenenwechsel wechsle nicht mehr für"
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Nach Ausführen von Aktionen überspringe das Ausführen von Aktionen für"
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="In diesem Zeitraum werden potentielle erfüllte Bedingungen ignoriert!"
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ausführliches Logging"
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Fensterposition und -größe speichern"
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Benachrichtigungen im System-Tray anzeigen"
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Deaktiviere UI Tipps"
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Tabs verstecken, die in Makros repräsentiert sind"
AdvSceneSwitcher.generalTab.matchBehavior="Verhalten anpassen"
AdvSceneSwitcher.generalTab.priority="Priorität"
AdvSceneSwitcher.generalTab.priority.description="Szenenwechselmethoden sortiert nach Priorität"
AdvSceneSwitcher.generalTab.priority.threadPriority="Benutze Thread Priorität"
@@ -45,19 +48,550 @@ AdvSceneSwitcher.generalTab.priority.fileContent="Datei Inhalt"
AdvSceneSwitcher.generalTab.priority.sceneSequence="Szenenfolge"
AdvSceneSwitcher.generalTab.priority.idleDetection="Inaktivitätserkennung"
AdvSceneSwitcher.generalTab.priority.executable="Prozess"
AdvSceneSwitcher.generalTab.priority.screenRegion="Bildschrimbereich"
AdvSceneSwitcher.generalTab.priority.screenRegion="Bildschirmbereich"
AdvSceneSwitcher.generalTab.priority.windowTitle="Fenstername"
AdvSceneSwitcher.generalTab.priority.media="Medien"
AdvSceneSwitcher.generalTab.priority.time="Zeit"
AdvSceneSwitcher.generalTab.priority.audio="Audio"
AdvSceneSwitcher.generalTab.priority.video="Video"
AdvSceneSwitcher.generalTab.priority.macro="Makro"
AdvSceneSwitcher.generalTab.transition="Übergänge"
AdvSceneSwitcher.generalTab.setTransitionBy="Beim Ändern des Szenenübergangs:"
AdvSceneSwitcher.generalTab.transitionOverride="Verwende Übergangsüberschreibungen"
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="Wechsle den aktiven Szenenübergangtyp"
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="Mindestens eine Option muss aktiv sein:\n\n - Verwende Übergangsüberschreibungen\n\n - Wechsle den aktiven Szenenübergangtyp"
; Macro Tab
AdvSceneSwitcher.macroTab.title="Makro"
AdvSceneSwitcher.macroTab.macros="Makros"
AdvSceneSwitcher.macroTab.priorityWarning="Hinweis: Es wird empfohlen, Makros als Funktion mit höchster Priorität zu konfigurieren.\nDiese Einstellung kann im Allgemein-Tab geändert werden."
AdvSceneSwitcher.macroTab.help="Mit Makros können eine Reihe von Aktionen in Abhängigkeit von mehreren Bedingungen ausgeführt werden.\n\nKlicke auf das hervorgehobene Plus-Symbol, um ein neues Makro hinzuzufügen."
AdvSceneSwitcher.macroTab.editConditionHelp="In diesem Abschnitt können Bedingungen für die Makros definiert werden.\n\nWähle auf der linken Seite ein vorhandenes Makro aus oder füge ein neues hinzu.\nKlicke dann auf die Plus-Schaltfläche unten, um eine neue Bedingung hinzuzufügen."
AdvSceneSwitcher.macroTab.editActionHelp="In diesem Abschnitt können Aktionen für die Makros definiert werden.\n\nWähle auf der linken Seite ein vorhandenes Makro aus oder füge ein neues hinzu.\nKlicke dann auf die Plus-Schaltfläche unten, um eine neue Aktion hinzuzufügen."
AdvSceneSwitcher.macroTab.edit="Makro bearbeiten"
AdvSceneSwitcher.macroTab.edit.logic="Logik-Typ:"
AdvSceneSwitcher.macroTab.edit.condition="Bedingungs-Typ:"
AdvSceneSwitcher.macroTab.edit.action="Aktions-Typ:"
AdvSceneSwitcher.macroTab.add="Neues Makro hinzufügen"
AdvSceneSwitcher.macroTab.name="Name:"
AdvSceneSwitcher.macroTab.run="Makro ausführen"
AdvSceneSwitcher.macroTab.runFail="Ausführen von \"%1\" fehlgeschlagen!\nEntweder ist eine der Aktionen fehlgeschlagen oder das Makro wird bereits ausgeführt."
AdvSceneSwitcher.macroTab.runInParallel="Parallel zu anderen Makros ausführen"
AdvSceneSwitcher.macroTab.onChange="Nur bei Änderung ausführen"
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
AdvSceneSwitcher.macroTab.defaultGroupName="Gruppe %1"
AdvSceneSwitcher.macroTab.exists="Makro-Name existiert bereits"
AdvSceneSwitcher.macroTab.groupDeleteConfirm="Sicher, dass \"%1\" und alle zugehörigen Elemente gelöscht werden?"
AdvSceneSwitcher.macroTab.copy="Kopie des aktuellen Makros erstellen"
AdvSceneSwitcher.macroTab.group="Ausgewählte Elemente gruppieren"
AdvSceneSwitcher.macroTab.ungroup="Gruppierung ausgewählter Gruppen aufheben"
AdvSceneSwitcher.macroTab.expandAll="Alle erweitern"
AdvSceneSwitcher.macroTab.collapseAll="Alle einklappen"
AdvSceneSwitcher.macroTab.maximize="Maximieren"
AdvSceneSwitcher.macroTab.minimize="Minimieren"
AdvSceneSwitcher.macroTab.highlightSettings="Visuelle Einstellungen"
AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey-Einstellungen"
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Kürzlich ausgeführte Makros hervorheben"
AdvSceneSwitcher.macroTab.highlightTrueConditions="Bedingungen des aktuell ausgewählten Makros hervorheben, die kürzlich als wahr bewertet wurden"
AdvSceneSwitcher.macroTab.highlightPerformedActions="Zuletzt ausgeführte Aktionen des aktuell ausgewählten Makros hervorheben"
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Hotkeys zur Steuerung des Pausen-Status neuer Makros registrieren"
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Hotkeys zur Steuerung des Pausen-Status ausgewählter Makros registrieren"
; Macro List
AdvSceneSwitcher.macroList.deleted="gelöscht"
AdvSceneSwitcher.macroList.duplicate="\"%1\" ist bereits ausgewählt!"
; Macro Logic
AdvSceneSwitcher.logic.none="Eintrag ignorieren"
AdvSceneSwitcher.logic.and="Und"
AdvSceneSwitcher.logic.or="Oder"
AdvSceneSwitcher.logic.andNot="Und nicht"
AdvSceneSwitcher.logic.orNot="Oder nicht"
AdvSceneSwitcher.logic.rootNone="Wenn"
AdvSceneSwitcher.logic.not="Wenn nicht"
; Macro Conditions
AdvSceneSwitcher.condition.audio="Audio"
AdvSceneSwitcher.condition.audio.state.below="unter"
AdvSceneSwitcher.condition.audio.state.exact="genau"
AdvSceneSwitcher.condition.audio.state.above="über"
AdvSceneSwitcher.condition.audio.state.mute="stummgeschaltet"
AdvSceneSwitcher.condition.audio.state.unmute="nicht stummgeschaltet"
AdvSceneSwitcher.condition.audio.type.output="Ausgabe-Lautstärke"
AdvSceneSwitcher.condition.audio.type.volume="Konfigurierter Lautstärkepegel"
AdvSceneSwitcher.condition.audio.type.syncOffset="Sync-Offset"
AdvSceneSwitcher.condition.audio.type.monitor="Audio-Monitoring"
AdvSceneSwitcher.condition.audio.type.balance="Audio-Balance"
AdvSceneSwitcher.condition.audio.entry="{{checkType}} von {{audioSources}} ist {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.condition.cursor="Cursor"
AdvSceneSwitcher.condition.cursor.type.region="ist in der Region"
AdvSceneSwitcher.condition.cursor.type.moving="bewegt sich"
AdvSceneSwitcher.condition.cursor.type.click="geklickt"
AdvSceneSwitcher.condition.cursor.button.left="Linke Maustaste"
AdvSceneSwitcher.condition.cursor.button.middle="Mittlere Maustaste"
AdvSceneSwitcher.condition.cursor.button.right="Rechte Maustaste"
AdvSceneSwitcher.condition.cursor.showFrame="Rahmen anzeigen"
AdvSceneSwitcher.condition.cursor.hideFrame="Rahmen ausblenden"
AdvSceneSwitcher.condition.cursor.entry.line1="Cursor {{conditions}}{{buttons}}{{minX}}{{minY}}{{maxX}}{{maxY}}{{toggleFrameButton}}"
AdvSceneSwitcher.condition.cursor.entry.line2="Cursor ist aktuell bei {{xPos}} x {{yPos}}"
AdvSceneSwitcher.condition.scene="Szene"
AdvSceneSwitcher.condition.scene.type.current="Aktuelle Szene ist"
AdvSceneSwitcher.condition.scene.type.previous="Vorherige Szene ist"
AdvSceneSwitcher.condition.scene.type.changed="Szene geändert"
AdvSceneSwitcher.condition.scene.type.notChanged="Szene hat sich nicht verändert"
AdvSceneSwitcher.condition.scene.type.currentPattern="Aktuelle Szene entspricht"
AdvSceneSwitcher.condition.scene.type.previousPattern="Vorherige Szene entspricht"
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Während des Übergangs die Ziel-Szene überprüfen"
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Während des Übergangs die Quell-Szene überprüfen"
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
AdvSceneSwitcher.condition.window="Fenster"
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} existiert und ..."
AdvSceneSwitcher.condition.window.entry.line2="... ist {{fullscreen}} Vollbild {{maximized}} Maximiert {{focused}} Fokusiert {{windowFocusChanged}} Vordergrundfenster geändert"
AdvSceneSwitcher.condition.window.entry.line3="Aktuelles Vordergrundfenster: {{focusWindow}}"
AdvSceneSwitcher.condition.file="Datei"
AdvSceneSwitcher.condition.file.type.match="entspricht"
AdvSceneSwitcher.condition.file.type.contentChange="Inhalt geändert"
AdvSceneSwitcher.condition.file.type.dateChange="Änderungsdatum geändert"
AdvSceneSwitcher.condition.file.remote="Entfernte Datei"
AdvSceneSwitcher.condition.file.local="Lokale Datei"
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}"
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.condition.media="Medien"
AdvSceneSwitcher.condition.media.source="Quelle"
AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle 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.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}Status ist{{states}}und{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="Video"
AdvSceneSwitcher.condition.video.condition.match="entspricht genau"
AdvSceneSwitcher.condition.video.condition.differ="stimmt nicht überein"
AdvSceneSwitcher.condition.video.condition.hasChanged="hat sich geändert"
AdvSceneSwitcher.condition.video.condition.hasNotChanged="hat sich nicht verändert"
AdvSceneSwitcher.condition.video.condition.noImage="hat keine Ausgabe"
AdvSceneSwitcher.condition.video.condition.pattern="entspricht dem Muster"
AdvSceneSwitcher.condition.video.condition.object="enthält Objekt"
AdvSceneSwitcher.condition.video.condition.brightness="Helligkeit"
AdvSceneSwitcher.condition.video.askFileAction="Vorhandene Datei verwenden oder einen Screenshot der aktuell ausgewählten Quelle erstellen?"
AdvSceneSwitcher.condition.video.askFileAction.file="Vorhandene Datei verwenden"
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Screenshot erstellen"
AdvSceneSwitcher.condition.video.reduceLatency="Reduzierung der Abgleichslatenz"
AdvSceneSwitcher.condition.video.reduceLatency.tooltip="Durch die Aktivierung wird die Abgleichslatenz verringert, aber die Bedingungsprüfungen aller Makros werden insgesamt langsamer."
AdvSceneSwitcher.condition.video.usePatternForChangedCheck="Musterabgleich verwenden"
AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="So kann gesteuert werden, wie stark sich das Bild ändern muss, damit die Bedingung erfüllt ist."
AdvSceneSwitcher.condition.video.patternThreshold="Schwellenwert: "
AdvSceneSwitcher.condition.video.patternThresholdDescription="Ein höherer Schwellenwert bedeutet, dass das Muster stärker an die Videoquelle angepasst werden muss."
AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="Alphakanal als Maske für Muster verwenden."
AdvSceneSwitcher.condition.video.brightnessThreshold="Durchschnittliche Helligkeit liegt über:"
AdvSceneSwitcher.condition.video.brightnessThresholdDescription="Ein hoher Wert steht für ein helles Bild, ein niedriger Wert für ein dunkles Bild."
AdvSceneSwitcher.condition.video.currentBrightness="Aktuelle durchschnittliche Helligkeit: %1"
AdvSceneSwitcher.condition.video.objectScaleThreshold="Skalierungsfaktor: "
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="Ein niedrigerer Skalierungsfaktor führt zu mehr Übereinstimmungen, aber zu einer höheren CPU-Belastung."
AdvSceneSwitcher.condition.video.minNeighborDescription="Ein höherer Wert für die Mindestanzahl von Nachbarn führt zu weniger, aber qualitativ besseren Übereinstimmungen."
AdvSceneSwitcher.condition.video.showMatch="Treffer anzeigen"
AdvSceneSwitcher.condition.video.showMatch.loading="Treffer werden gesucht"
AdvSceneSwitcher.condition.video.screenshotFail="Screenshot der Quelle konnte nicht erstellt werden!"
AdvSceneSwitcher.condition.video.screenshotEmpty="Screenshot ist leer - Ist die Quelle sichtbar?"
AdvSceneSwitcher.condition.video.patternMatchFail="Das Muster wurde nicht gefunden!"
AdvSceneSwitcher.condition.video.patternMatchSuccess="Das Muster ist rot hervorgehoben."
AdvSceneSwitcher.condition.video.objectMatchFail="Objekt wurde nicht gefunden!"
AdvSceneSwitcher.condition.video.objectMatchSuccess="Objekt ist rot hervorgehoben."
AdvSceneSwitcher.condition.video.modelLoadFail="Modelldaten konnten nicht geladen werden!"
AdvSceneSwitcher.condition.video.type.main="OBS's Haupt-Ausgabe"
AdvSceneSwitcher.condition.video.type.source="Quelle"
AdvSceneSwitcher.condition.video.type.scene="Szene"
AdvSceneSwitcher.condition.video.entry="{{videoInputTypes}}{{sources}}{{scenes}}{{condition}}{{imagePath}}"
AdvSceneSwitcher.condition.video.entry.modelPath="Modelldaten (Haar-Kaskaden-Klassifikator): {{modelDataPath}}"
AdvSceneSwitcher.condition.video.entry.minNeighbor="Minimale Anzahl von Nachbarn: {{minNeighbors}}"
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}Reduzieren Sie die CPU-Belastung, indem Sie die Prüfung nur alle {{throttleCount}} Millisekunden"
AdvSceneSwitcher.condition.video.entry.checkAreaEnable="Kontrolle nur im Bereich durchführen"
AdvSceneSwitcher.condition.video.entry.checkArea="{{checkAreaEnable}}{{checkArea}}{{selectArea}}"
AdvSceneSwitcher.condition.video.minSize="Minimale Größe:"
AdvSceneSwitcher.condition.video.maxSize="Maximale Größe:"
AdvSceneSwitcher.condition.video.selectArea="Bereich auswählen"
AdvSceneSwitcher.condition.video.selectArea.status="Nur der markierte Bereich wird überprüft"
AdvSceneSwitcher.condition.video.width="Breite"
AdvSceneSwitcher.condition.video.height="Höhe"
AdvSceneSwitcher.condition.stream="Stream"
AdvSceneSwitcher.condition.stream.state.start="Stream läuft"
AdvSceneSwitcher.condition.stream.state.stop="Stream gestoppt"
AdvSceneSwitcher.condition.stream.state.starting="Stream wird gestartet"
AdvSceneSwitcher.condition.stream.state.stopping="Stream wird gestoppt"
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
AdvSceneSwitcher.condition.record="Aufnahme"
AdvSceneSwitcher.condition.record.state.start="Aufnahme läuft"
AdvSceneSwitcher.condition.record.state.pause="Aufnahme pausiert"
AdvSceneSwitcher.condition.record.state.stop="Aufnahme gestoppt"
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
AdvSceneSwitcher.condition.process="Prozess"
AdvSceneSwitcher.condition.process.entry="{{processes}} läuft {{focused}} und ist fokusiert"
AdvSceneSwitcher.condition.process.entry.focus="Aktueller Vordergrundprozess: {{focusProcess}}"
AdvSceneSwitcher.condition.idle="Leerlauf"
AdvSceneSwitcher.condition.idle.entry="Keine Tastatur- oder Mauseingaben für {{duration}}"
AdvSceneSwitcher.condition.pluginState="Plugin-Status"
AdvSceneSwitcher.condition.pluginState.state.start="Plugin gestartet"
AdvSceneSwitcher.condition.pluginState.state.restart="Plugin neu gestartet"
AdvSceneSwitcher.condition.pluginState.state.running="Plugin läuft"
AdvSceneSwitcher.condition.pluginState.state.shutdown="OBS wird runtergefahren"
AdvSceneSwitcher.condition.pluginState.state.sceneCollection="Szenensammlung geladen"
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Szene durch vorheriges Makro geändert"
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
AdvSceneSwitcher.condition.timer="Timer"
AdvSceneSwitcher.condition.timer.type.fixed="Fixe"
AdvSceneSwitcher.condition.timer.type.random="Zufällige"
AdvSceneSwitcher.condition.timer.pause="Pausieren"
AdvSceneSwitcher.condition.timer.continue="Fortfahren"
AdvSceneSwitcher.condition.timer.entry.line1.fixed="{{type}} Dauer von {{duration}} ist abgelaufen"
AdvSceneSwitcher.condition.timer.entry.line1.random="{{type}} Dauer von {{duration}} bis {{duration2}} ist abgelaufen"
AdvSceneSwitcher.condition.timer.entry.line2="Restliche Zeit: {{remaining}} Sekunden"
AdvSceneSwitcher.condition.timer.entry.line3="{{pauseContinue}} {{reset}} {{saveRemaining}} Verbleibende Zeit speichern {{autoReset}} Automatisches Zurücksetzen des Timers nach Erreichen der Dauer"
AdvSceneSwitcher.condition.timer.reset="Zurücksetzen"
AdvSceneSwitcher.condition.macro="Makro"
AdvSceneSwitcher.condition.macro.type.count="Zähler"
AdvSceneSwitcher.condition.macro.type.state="Zustand"
AdvSceneSwitcher.condition.macro.type.multiState="Mehrere Zustände"
AdvSceneSwitcher.condition.macro.type.selection="Bedingungs-Typ: {{types}}"
AdvSceneSwitcher.condition.macro.count.type.below="Weniger als"
AdvSceneSwitcher.condition.macro.count.type.above="Mehr als"
AdvSceneSwitcher.condition.macro.count.type.equal="Exakt"
AdvSceneSwitcher.condition.macro.state.type.below="Weniger als"
AdvSceneSwitcher.condition.macro.state.type.above="Mehr als"
AdvSceneSwitcher.condition.macro.state.type.equal="Exakt"
AdvSceneSwitcher.condition.macro.count.reset="Zurücksetzen"
AdvSceneSwitcher.condition.macro.pausedWarning="Ausgewähltes Makro ist derzeit pausiert!"
AdvSceneSwitcher.condition.macro.state.entry="Bedingungen für {{macros}} sind wahr"
AdvSceneSwitcher.condition.macro.multistate.entry="Bedingungen für {{multiStateConditions}}{{multiStateCount}} der folgenden Makros wahr sind:"
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} wurde ausgeführt {{conditions}} {{count}} Mal"
AdvSceneSwitcher.condition.macro.count.entry.line2="Aktuelle Anzahl: {{currentCount}} {{resetCount}}"
AdvSceneSwitcher.condition.source="Quelle"
AdvSceneSwitcher.condition.source.type.active="Ist aktiv"
AdvSceneSwitcher.condition.source.type.showing="Wird angezeigt"
AdvSceneSwitcher.condition.source.type.settings="Einstellungen stimmen überein"
AdvSceneSwitcher.condition.source.getSettings="Aktuelle Einstellungen abfragen"
AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}"
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.source.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.virtualCamera="Virtuelle Kamera"
AdvSceneSwitcher.condition.virtualCamera.state.start="Virtuelle Kamera gestartet"
AdvSceneSwitcher.condition.virtualCamera.state.stop="Virtuelle Kamera gestoppt"
AdvSceneSwitcher.condition.virtualCamera.entry="{{states}}"
AdvSceneSwitcher.condition.filter="Filter"
AdvSceneSwitcher.condition.filter.type.active="Ist aktiviert"
AdvSceneSwitcher.condition.filter.type.showing="Ist deaktiviert"
AdvSceneSwitcher.condition.filter.type.settings="Einstellungen passen"
AdvSceneSwitcher.condition.filter.getSettings="Aktuelle Einstellungen abrufen"
AdvSceneSwitcher.condition.filter.entry.line1="Auf {{sources}} {{filters}} {{conditions}}"
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.sceneOrder="Reihenfolge der Szenenelemente"
AdvSceneSwitcher.condition.sceneOrder.type.above="Ist über"
AdvSceneSwitcher.condition.sceneOrder.type.below="Ist unter"
AdvSceneSwitcher.condition.sceneOrder.type.position="Ist in Position"
AdvSceneSwitcher.condition.sceneOrder.positionInfo="Der Positionswert beginnt ganz unten bei 0 und erhöht sich für jedes Szenenelement, auch in Szenengruppen, um eins"
AdvSceneSwitcher.condition.sceneOrder.entry="Auf{{scenes}}{{sources}}{{conditions}}{{sources2}}{{position}}"
AdvSceneSwitcher.condition.hotkey="Hotkey"
AdvSceneSwitcher.condition.hotkey.name="Makro-Trigger-Hotkey"
AdvSceneSwitcher.condition.hotkey.tip="Hinweis: Die Tastenkombinationen für diesen Hotkey können in den OBS-Einstellungen konfiguriert werden"
AdvSceneSwitcher.condition.hotkey.entry.line1="Hotkey ist gedrückt"
AdvSceneSwitcher.condition.hotkey.entry.line2="Name: {{name}}"
AdvSceneSwitcher.condition.replay="Replay Buffer"
AdvSceneSwitcher.condition.replay.state.stopped="Replay Buffer gestoppt"
AdvSceneSwitcher.condition.replay.state.started="Replay Buffer gestartet"
AdvSceneSwitcher.condition.replay.state.saved="Replay Buffer gespeichert"
AdvSceneSwitcher.condition.replay.entry="{{state}}"
AdvSceneSwitcher.condition.date="Datum"
AdvSceneSwitcher.condition.date.anyDay="Beliebiger Tag"
AdvSceneSwitcher.condition.date.monday="Montag"
AdvSceneSwitcher.condition.date.tuesday="Dienstag"
AdvSceneSwitcher.condition.date.wednesday="Mittwoch"
AdvSceneSwitcher.condition.date.thursday="Donnerstag"
AdvSceneSwitcher.condition.date.friday="Freitag"
AdvSceneSwitcher.condition.date.saturday="Samstag"
AdvSceneSwitcher.condition.date.sunday="Sonntag"
AdvSceneSwitcher.condition.date.state.at="Am"
AdvSceneSwitcher.condition.date.state.after="Nach"
AdvSceneSwitcher.condition.date.state.before="Vor"
AdvSceneSwitcher.condition.date.state.between="Zwischen"
AdvSceneSwitcher.condition.date.state.pattern="Muster"
AdvSceneSwitcher.condition.date.separator="und"
AdvSceneSwitcher.condition.date.ignoreDate="Wenn diese Option nicht aktiviert ist, wird die Datumskomponente ignoriert"
AdvSceneSwitcher.condition.date.ignoreTime="Wenn diese Option nicht aktiviert ist, wird die Zeitkomponente ignoriert"
AdvSceneSwitcher.condition.date.showAdvancedSettings="Erweiterte Einstellungen anzeigen"
AdvSceneSwitcher.condition.date.showSimpleSettings="Einfache Einstellungen anzeigen"
AdvSceneSwitcher.condition.date.entry.simple="Am {{dayOfWeek}} {{weekCondition}} {{ignoreWeekTime}}{{weekTime}}"
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} Wiederholen alle {{duration}} bei Datumsübereinstimmung"
AdvSceneSwitcher.condition.date.entry.pattern="Aktuelles Datum \"{{currentDate}}\" entspricht dem Muster {{pattern}}"
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Nächster Treffer bei: %1"
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} Bei Wiederholung ausgewähltes Datum auf Wiederholungsdatum aktualisieren"
AdvSceneSwitcher.condition.sceneTransform="Szenenelement transformieren"
AdvSceneSwitcher.condition.sceneTransform.getTransform="Transformation erhalten"
AdvSceneSwitcher.condition.sceneTransform.entry.line1="Auf{{scenes}}{{sources}}passt zur Transformation"
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.transition="Übergang"
AdvSceneSwitcher.condition.transition.type.current="Aktueller Übergangstyp ist"
AdvSceneSwitcher.condition.transition.type.duration="Aktuelle Übergangsdauer beträgt"
AdvSceneSwitcher.condition.transition.type.started="Übergang gestartet"
AdvSceneSwitcher.condition.transition.type.ended="Übergang beendet"
AdvSceneSwitcher.condition.transition.type.transitionSource="Übergang von"
AdvSceneSwitcher.condition.transition.type.transitionTarget="Übergang zu"
AdvSceneSwitcher.condition.transition.durationSuffix="Sekunden"
AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{scenes}}{{duration}}{{durationSuffix}}"
AdvSceneSwitcher.condition.sceneVisibility="Sichtbarkeit von Szenenelementen"
AdvSceneSwitcher.condition.sceneVisibility.type.shown="ist sichtbar"
AdvSceneSwitcher.condition.sceneVisibility.type.hidden="ist versteckt"
AdvSceneSwitcher.condition.sceneVisibility.type.changed="Sichtbarkeit verändert"
AdvSceneSwitcher.condition.sceneVisibility.entry="Auf{{scenes}}{{sources}}{{conditions}}"
AdvSceneSwitcher.condition.studioMode="Studio-Modus"
AdvSceneSwitcher.condition.studioMode.state.active="Studio-Modus ist aktiviert"
AdvSceneSwitcher.condition.studioMode.state.notActive="Studio-Modus ist nicht aktiviert"
AdvSceneSwitcher.condition.studioMode.state.previewScene="Vorschau-Szene ist"
AdvSceneSwitcher.condition.studioMode.entry="{{conditions}}{{scenes}}"
AdvSceneSwitcher.condition.openvr="OpenVR"
AdvSceneSwitcher.condition.openvr.errorStatus="OpenVR Fehler: "
AdvSceneSwitcher.condition.openvr.entry.line1="HMD ist in ..."
AdvSceneSwitcher.condition.openvr.entry.line2="{{controls}}"
AdvSceneSwitcher.condition.openvr.entry.line3="HMD ist derzeit bei {{xPos}} x {{yPos}} x {{zPos}}"
AdvSceneSwitcher.condition.stats="OBS-Statistiken"
AdvSceneSwitcher.condition.stats.type.fps="FPS"
AdvSceneSwitcher.condition.stats.type.CPUUsage="CPU-Auslastung"
AdvSceneSwitcher.condition.stats.type.HDDSpaceAvailable="Verfügbarer Speicherplatz"
AdvSceneSwitcher.condition.stats.type.memoryUsage="Speicherverbrauch"
AdvSceneSwitcher.condition.stats.type.averageTimeToRender="Durchschnittliche Zeit zum Rendern eines Frames"
AdvSceneSwitcher.condition.stats.type.skippedFrames="Übersprungene Frames aufgrund der Kodierungsverzögerung"
AdvSceneSwitcher.condition.stats.type.missedFrames="Verpasste Frames durch Rendering-Verzögerung"
AdvSceneSwitcher.condition.stats.type.droppedFrames.stream="Verlorene Frames im Stream"
AdvSceneSwitcher.condition.stats.type.megabytesSent.stream="Gesamtdatenmenge des Streams"
AdvSceneSwitcher.condition.stats.type.bitrate.stream="Stream-Bitrate"
AdvSceneSwitcher.condition.stats.type.droppedFrames.recording="Verlorene Frames bei der Aufnahme"
AdvSceneSwitcher.condition.stats.type.megabytesSent.recording="Gesamtdatenmenge der Aufnahme"
AdvSceneSwitcher.condition.stats.type.bitrate.recording="Aufnahme-Bitrate"
AdvSceneSwitcher.condition.stats.condition.above="über"
AdvSceneSwitcher.condition.stats.condition.equals="gleich"
AdvSceneSwitcher.condition.stats.condition.below="unter"
AdvSceneSwitcher.condition.stats.dockHint="Das Dock \"Stats\" öffnen, um den aktuellen Status anzuzeigen"
AdvSceneSwitcher.condition.stats.entry="{{stats}} ist {{condition}} {{value}}"
AdvSceneSwitcher.condition.profile="Profil"
AdvSceneSwitcher.condition.profile.entry="Derzeit aktives Profil ist {{profiles}}"
AdvSceneSwitcher.condition.websocket="Websocket"
AdvSceneSwitcher.condition.websocket.type.request="Anfrage"
AdvSceneSwitcher.condition.websocket.type.event="Ereignis"
AdvSceneSwitcher.condition.websocket.useRegex="Reguläre Ausdrücke verwenden"
AdvSceneSwitcher.condition.websocket.entry.request="{{type}} wurde empfangen:"
AdvSceneSwitcher.condition.websocket.entry.event="{{type}} wurde empfangen von {{connection}}:"
AdvSceneSwitcher.condition.variable="Variabel"
AdvSceneSwitcher.condition.variable.type.compare="entspricht"
AdvSceneSwitcher.condition.variable.type.empty="ist leer"
AdvSceneSwitcher.condition.variable.type.number="ist eine Zahl"
AdvSceneSwitcher.condition.variable.type.lessThan="ist kleiner als"
AdvSceneSwitcher.condition.variable.type.greaterThan="ist größer als"
AdvSceneSwitcher.condition.variable.type.valueChanged="Wert verändert"
AdvSceneSwitcher.condition.variable.type.equalsVariable="entspricht Variable"
AdvSceneSwitcher.condition.variable.type.lessThanVariable="ist kleiner als die Variable"
AdvSceneSwitcher.condition.variable.type.greaterThanVariable="ist größer als die Variable"
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
; Macro Actions
AdvSceneSwitcher.action.switchScene="Szene wechseln"
AdvSceneSwitcher.action.scene.entry="Wechsle zu Szene{{scenes}}mittels{{transitions}}mit einer Dauer von{{duration}}Sekunden"
AdvSceneSwitcher.action.scene.entry.noDuration="Wechsle zu Szene{{scenes}}mittels{{transitions}}"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Warten, bis der Übergang zur Zielszene abgeschlossen ist"
AdvSceneSwitcher.action.wait="Warten"
AdvSceneSwitcher.action.wait.type.fixed="fixe"
AdvSceneSwitcher.action.wait.type.random="zufällig"
AdvSceneSwitcher.action.wait.entry.fixed="Warte für {{waitType}} Dauer von {{duration}}"
AdvSceneSwitcher.action.wait.entry.random="Warte für {{waitType}} Dauer von {{duration}} bis {{duration2}}"
AdvSceneSwitcher.action.audio="Audio"
AdvSceneSwitcher.action.audio.type.mute="Stummgeschaltet"
AdvSceneSwitcher.action.audio.type.unmute="Nicht stummgeschaltet"
AdvSceneSwitcher.action.audio.type.sourceVolume="Quell-Lautstärke einstellen"
AdvSceneSwitcher.action.audio.type.masterVolume="Master-Lautstärke einstellen"
AdvSceneSwitcher.action.audio.type.syncOffset="Sync-Offset einstellen"
AdvSceneSwitcher.action.audio.type.monitor="Audio-Monitoring einstellen"
AdvSceneSwitcher.action.audio.type.balance="Audio-Balance einstellen"
AdvSceneSwitcher.action.audio.balance.description="Den Schieberegler in die Richtung des Audiokanals drehen, auf den fokussiert werden soll."
AdvSceneSwitcher.action.audio.fade.type.duration="über eine Dauer von"
AdvSceneSwitcher.action.audio.fade.type.rate="mit einer Rate von"
AdvSceneSwitcher.action.audio.fade.duration="{{fade}}Blende {{fadeTypes}} {{duration}} Sekunden."
AdvSceneSwitcher.action.audio.fade.rate="{{fade}}Blende {{fadeTypes}} {{rate}}pro Sekunde."
AdvSceneSwitcher.action.audio.fade.wait="Warten, bis die Blende abgeschlossen ist."
AdvSceneSwitcher.action.audio.fade.abort="Abbruch einer bereits aktiven Blende."
AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.action.recording="Aufnahme"
AdvSceneSwitcher.action.recording.type.stop="Aufnahme stoppen"
AdvSceneSwitcher.action.recording.type.start="Aufnahme starten"
AdvSceneSwitcher.action.recording.type.pause="Aufnahme pausieren"
AdvSceneSwitcher.action.recording.type.unpause="Aufnahme nicht mehr pausieren"
AdvSceneSwitcher.action.recording.type.split="Aufnahme-Datei teilen"
AdvSceneSwitcher.action.recording.pause.hint="Bitte beachten, dass je nach Aufnahmeeinstellung die Aufnahme möglicherweise nicht unterbrochen werden kann"
AdvSceneSwitcher.action.recording.split.hint="Vergewissern, dass die automatische Dateiaufteilung in den OBS-Einstellungen aktiviert ist!"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="Replay Buffer"
AdvSceneSwitcher.action.replay.saveWarn="Warnung: Ein zu häufiges Speichern kann dazu führen, dass der Replay Buffer nicht gespeichert wird!"
AdvSceneSwitcher.action.replay.type.stop="Replay Buffer stoppen"
AdvSceneSwitcher.action.replay.type.start="Replay Buffer starten"
AdvSceneSwitcher.action.replay.type.save="Replay Buffer speichern"
AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Stream"
AdvSceneSwitcher.action.streaming.type.stop="Stream stoppen"
AdvSceneSwitcher.action.streaming.type.start="Stream starten"
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="Ausführen"
AdvSceneSwitcher.action.run.arguments="Argumente:"
AdvSceneSwitcher.action.run.addArgument="Argument hinzufügen"
AdvSceneSwitcher.action.run.addArgumentDescription="Neues Argument hinzufügen:"
AdvSceneSwitcher.action.run.entry="Ausführen {{filePath}}"
AdvSceneSwitcher.action.run.entry.workingDirectory="Arbeitsverzeichnis:{{workingDirectory}}"
AdvSceneSwitcher.action.sceneVisibility="Sichtbarkeit von Szenenelementen"
AdvSceneSwitcher.action.sceneVisibility.type.show="Anzeigen"
AdvSceneSwitcher.action.sceneVisibility.type.hide="Verstecken"
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Umschalten"
AdvSceneSwitcher.action.sceneVisibility.type.source="Quelle"
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Beliebig"
AdvSceneSwitcher.action.sceneVisibility.entry="Auf{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
AdvSceneSwitcher.action.filter="Filter"
AdvSceneSwitcher.action.filter.type.enable="Aktivieren"
AdvSceneSwitcher.action.filter.type.disable="Deaktivieren"
AdvSceneSwitcher.action.filter.type.settings="Einstellungen festlegen"
AdvSceneSwitcher.action.filter.entry="Auf {{sources}} {{actions}} {{filters}}"
AdvSceneSwitcher.action.filter.getSettings="Aktuelle Einstellungen abfragen"
AdvSceneSwitcher.action.source="Quelle"
AdvSceneSwitcher.action.source.type.enable="Aktivieren"
AdvSceneSwitcher.action.source.type.disable="Deaktivieren"
AdvSceneSwitcher.action.source.type.settings="Einstellungen festlegen"
AdvSceneSwitcher.action.source.type.refreshSettings="Aktualisieren der Quelleneinstellungen"
AdvSceneSwitcher.action.source.type.pressSettingsButton="Drücken der Einstellungstaste"
AdvSceneSwitcher.action.source.type.refreshSettings.tooltip="Kann verwendet werden, um Browser-, Medien- usw. Quellen zu aktualisieren"
AdvSceneSwitcher.action.source.noSettingsButtons="Keine Buttons gefunden!"
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
AdvSceneSwitcher.action.source.warning="Warnung: Das globale Aktivieren und Deaktivieren von Quellen kann nicht über die OBS-Benutzeroberfläche gesteuert werden"
AdvSceneSwitcher.action.source.getSettings="Aktuelle Einstellungen abfragen"
AdvSceneSwitcher.action.media="Medien"
AdvSceneSwitcher.action.media.type.play="Abspielen"
AdvSceneSwitcher.action.media.type.pause="Pausieren"
AdvSceneSwitcher.action.media.type.stop="Stoppen"
AdvSceneSwitcher.action.media.type.restart="Neu starten"
AdvSceneSwitcher.action.media.type.next="Nächste"
AdvSceneSwitcher.action.media.type.previous="Vorherige"
AdvSceneSwitcher.action.media.type.seek="Suche nach"
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
AdvSceneSwitcher.action.macro="Makro"
AdvSceneSwitcher.action.macro.type.pause="Pausieren"
AdvSceneSwitcher.action.macro.type.unpause="Nicht mehr pausieren"
AdvSceneSwitcher.action.macro.type.resetCounter="Zähler zurücksetzen"
AdvSceneSwitcher.action.macro.type.run="Aktionen ausführen"
AdvSceneSwitcher.action.macro.type.stop="Aktionen stoppen"
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
AdvSceneSwitcher.action.pluginState="Plugin-Status"
AdvSceneSwitcher.action.pluginState.type.stop="Erweiterten Automatischen Szenenwechsler stoppen"
AdvSceneSwitcher.action.pluginState.type.noMatch="Ändern des Nichtübereinstimmungsverhaltens:"
AdvSceneSwitcher.action.pluginState.type.import="Einstellungen importieren aus"
AdvSceneSwitcher.action.pluginState.importWarning="Hinweis: Die Aktion wird ignoriert, solange das Einstellungsfenster geöffnet ist."
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
AdvSceneSwitcher.action.virtualCamera="Virtuelle Kamera"
AdvSceneSwitcher.action.virtualCamera.type.stop="Virtuelle Kamera stoppen"
AdvSceneSwitcher.action.virtualCamera.type.start="Virtuelle Kamera starten"
AdvSceneSwitcher.action.virtualCamera.entry="{{actions}}"
AdvSceneSwitcher.action.hotkey="Hotkey"
AdvSceneSwitcher.action.hotkey.leftShift="Linke Umschalttaste"
AdvSceneSwitcher.action.hotkey.rightShift="Rechte Umschalttaste"
AdvSceneSwitcher.action.hotkey.leftCtrl="Linke Strg-Taste"
AdvSceneSwitcher.action.hotkey.rightCtrl="Rechte Strg-Taste"
AdvSceneSwitcher.action.hotkey.leftAlt="Linke Alt-Taste"
AdvSceneSwitcher.action.hotkey.rightAlt="Rechte Alt-Taste"
AdvSceneSwitcher.action.hotkey.leftMeta="Linke Meta-Taste"
AdvSceneSwitcher.action.hotkey.rightMeta="Rechte Meta-Taste"
AdvSceneSwitcher.action.hotkey.onlyOBS="Tastendruck nur an OBS senden"
AdvSceneSwitcher.action.hotkey.disabled="Globale Tastendrücke können nicht simuliert werden - die Funktionalität beschränkt sich auf das Senden von Tastendrücken an OBS!"
AdvSceneSwitcher.action.hotkey.entry="Drücke {{keys}} für {{duration}}"
AdvSceneSwitcher.action.sceneOrder="Reihenfolge der Szenenelemente"
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Nach oben verschieben"
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Nach unten verschieben"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="An erste Stelle verschieben"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="An letzte Stelle verschieben"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="An Position verschieben"
AdvSceneSwitcher.action.sceneOrder.entry="Auf{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Szenenelement transformieren"
AdvSceneSwitcher.action.sceneTransform.getTransform="Transformation erhalten"
AdvSceneSwitcher.action.sceneTransform.entry="Auf{{scenes}}transformieren{{sources}}"
AdvSceneSwitcher.action.file="Datei"
AdvSceneSwitcher.action.file.type.write="Schreiben"
AdvSceneSwitcher.action.file.type.append="Anhängen"
AdvSceneSwitcher.action.file.entry="{{actions}} in {{filePath}}:"
AdvSceneSwitcher.action.studioMode="Studio-Modus"
AdvSceneSwitcher.action.studioMode.type.swap="Vorschau- und Programm-Szene tauschen"
AdvSceneSwitcher.action.studioMode.type.setScene="Vorschau-Szene einstellen auf"
AdvSceneSwitcher.action.studioMode.type.enable="Studio-Modus aktivieren"
AdvSceneSwitcher.action.studioMode.type.disable="Studio-Modus deaktivieren"
AdvSceneSwitcher.action.studioMode.entry="{{actions}}{{scenes}}"
AdvSceneSwitcher.action.transition="Übergang"
AdvSceneSwitcher.action.transition.type.scene="Szenenübergang"
AdvSceneSwitcher.action.transition.type.sceneOverride="Szenenübergang überschreiben"
AdvSceneSwitcher.action.transition.type.sourceShow="Übergang der Quelle anzeigen"
AdvSceneSwitcher.action.transition.type.sourceHide="Übergang der Quelle verstecken"
AdvSceneSwitcher.action.transition.entry.line1="Anpassen {{type}}{{scenes}}{{sources}}"
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Übergangstyp festlegen auf {{transitions}}"
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Übergangsdauer festlegen auf {{duration}}Sekunden"
AdvSceneSwitcher.action.timer="Timer"
AdvSceneSwitcher.action.timer.type.pause="Pausieren"
AdvSceneSwitcher.action.timer.type.continue="Fortsetzen"
AdvSceneSwitcher.action.timer.type.reset="Zurücksetzen"
AdvSceneSwitcher.action.timer.type.setTimeRemaining="Verbleibende Zeit einstellen der"
AdvSceneSwitcher.action.timer.entry="{{timerAction}} Timer von {{macros}} {{duration}}"
AdvSceneSwitcher.action.random="Zufall"
AdvSceneSwitcher.action.random.allowRepeat="Aufeinanderfolgende Ausführung desselben Makros zulassen"
AdvSceneSwitcher.action.random.entry="Zufällige Ausführung eines der folgenden Makros (pausierte Makros werden ignoriert)"
AdvSceneSwitcher.action.systray="Benachrichtigung im System-Tray"
AdvSceneSwitcher.action.systray.entry="Benachrichtigung anzeigen: {{message}}"
AdvSceneSwitcher.action.screenshot="Screenshot"
AdvSceneSwitcher.action.screenshot.save.default="Standard"
AdvSceneSwitcher.action.screenshot.save.custom="Benutzerdefiniert"
AdvSceneSwitcher.action.screenshot.type.source="Quelle"
AdvSceneSwitcher.action.screenshot.type.scene="Szene"
AdvSceneSwitcher.action.screenshot.mainOutput="OBS's Haupt-Ausgabe"
AdvSceneSwitcher.action.screenshot.blackscreenNote="Quellen oder Szenen, die nicht immer gerendert werden, können dazu führen, dass einige Teile der Screenshots leer bleiben."
AdvSceneSwitcher.action.screenshot.entry="Screenshot{{targetType}}{{sources}}{{scenes}}und speichere in{{saveType}}Pfad"
AdvSceneSwitcher.action.profile="Profil"
AdvSceneSwitcher.action.profile.entry="Aktives Profil umschalten auf {{profiles}}"
AdvSceneSwitcher.action.sceneCollection="Szenensammlung"
AdvSceneSwitcher.action.sceneCollection.entry="Aktive Szenensammlung umschalten auf {{sceneCollections}}"
AdvSceneSwitcher.action.sceneCollection.warning="Hinweis: Alle danach folgenden Aktionen werden nicht ausgeführt, da durch die Änderung der Szenensammlung auch die Einstellungen des Szenenwechslers neu geladen werden.\nDie Szenensammlungsaktion wird ignoriert, solange das Einstellungsfenster geöffnet ist."
AdvSceneSwitcher.action.sequence="Sequenz"
AdvSceneSwitcher.action.sequence.entry="Jedes Mal, wenn diese Aktion ausgeführt wird, wird das nächste Makro in der Liste ausgeführt (pausierte Makros werden ignoriert)"
AdvSceneSwitcher.action.sequence.status="Zuletzt ausgeführtes Makro: %1 - Nächstes auszuführendes Makro: %2"
AdvSceneSwitcher.action.sequence.status.none="keines"
AdvSceneSwitcher.action.sequence.restart="Neustart am Anfang, wenn das Ende der Liste erreicht ist"
AdvSceneSwitcher.action.sequence.continueFrom="Weiter mit ausgewähltem Element"
AdvSceneSwitcher.action.websocket="Websocket"
AdvSceneSwitcher.action.websocket.type.request="Anfrage"
AdvSceneSwitcher.action.websocket.type.event="Ereignis"
AdvSceneSwitcher.action.websocket.entry.request="Szenenwechsler {{type}} via {{connection}} senden"
AdvSceneSwitcher.action.websocket.entry.event="Szenenwechsler {{type}} an verbundene Clients senden"
AdvSceneSwitcher.action.http="HTTP"
AdvSceneSwitcher.action.http.type.get="GET"
AdvSceneSwitcher.action.http.type.post="POST"
AdvSceneSwitcher.action.http.entry.line1="Sende {{method}} an {{url}}"
AdvSceneSwitcher.action.http.entry.line2="Timeout: {{timeout}} Sekunden"
AdvSceneSwitcher.action.variable="Variabel"
AdvSceneSwitcher.action.variable.type.set="Auf festen Wert einstellen"
AdvSceneSwitcher.action.variable.type.append="Anhängen"
AdvSceneSwitcher.action.variable.type.appendVar="Variable anhängen"
AdvSceneSwitcher.action.variable.type.increment="Erhöhen"
AdvSceneSwitcher.action.variable.type.decrement="Verringern"
AdvSceneSwitcher.action.variable.type.setActionValue="Auf Aktionswert setzen"
AdvSceneSwitcher.action.variable.type.setConditionValue="Auf Bedingungswert setzen"
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.conditionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Bedingungen wird nicht unterstützt!"
AdvSceneSwitcher.action.variable.currentSegmentValue="Aktueller Wert:"
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
; Transition Tab
AdvSceneSwitcher.transitionTab.title="Szenenübergänge"
AdvSceneSwitcher.transitionTab.setTransitionBy="Beim Ändern des Szenenübergangs:"
AdvSceneSwitcher.transitionTab.transitionOverride="Verwende Übergangsüberschreibungen"
AdvSceneSwitcher.transitionTab.adjustActiveTransitionType="Wechsle den aktiven Szenenübergangtyp"
AdvSceneSwitcher.transitionTab.transitionBehaviorSelectionError="Mindestens eine Option muss aktiv sein:\n\n - Verwende Übergangsüberschreibungen\n\n - Wechsle den aktiven Szenenübergangtyp"
AdvSceneSwitcher.transitionTab.transitionForAToB="Szenenübergänge für automatisierte Szenenwechsel von Szene A zu Szene B"
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>Diese Einstellungen beeinflussen <span style=\"font-style:italic;\">nur</span> vom Szenenwechsler ausgelöste Szenenübergänge - Siehe <a href=\"https://obsproject.com/forum/resources/transition-table.1174/\"><span style=\" text-decoration: underline; color:#268bd2;\">Transition Table</span></a> um auch manuelle Szenenübergänge zu konfigurieren.<br/>Einstellungen auf diesem Tab haben Vorrang, vor denen welche auf den übrigen Tabs konfiguriert wurden.<br/><br/>Klicke auf das Plus Symbol, um einen neuen Eintrag hinzuzufügen.</p></body></html>"
AdvSceneSwitcher.transitionTab.defaultTransition="Ändere den Szenenübergang wenn eine Szene aktiv ist"
@@ -98,7 +632,7 @@ AdvSceneSwitcher.executableTab.entry="Wenn {{processes}} läuft wechsle zu {{sce
AdvSceneSwitcher.executableTab.help="Dieser Tab erlaubt es Szenen zu wechseln, wenn bestimmte Prozesse laufen.\nDas kann nützlich sein, wenn sich der Name eines Fensters ändern kann oder dieser nicht bekannt ist.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
; Screen Region Tab
AdvSceneSwitcher.screenRegionTab.title="Bildschrimbereich"
AdvSceneSwitcher.screenRegionTab.title="Bildschirmbereich"
AdvSceneSwitcher.screenRegionTab.currentPosition="Mauszeiger ist bei:"
AdvSceneSwitcher.screenRegionTab.showGuideFrames="Hilfsrahmen einblenden"
AdvSceneSwitcher.screenRegionTab.hideGuideFrames="Hilfsrahmen ausblenden"
@@ -117,7 +651,7 @@ AdvSceneSwitcher.mediaTab.states.Paused="Pausiert"
AdvSceneSwitcher.mediaTab.states.stopped="Gestoppt"
AdvSceneSwitcher.mediaTab.states.ended="Beendet"
AdvSceneSwitcher.mediaTab.states.error="Fehler"
AdvSceneSwitcher.mediaTab.states.playedToEnd="Zu Ende gespielt"
AdvSceneSwitcher.mediaTab.states.playlistEnd="Ended(Playlist)"
AdvSceneSwitcher.mediaTab.states.any="Beliebig"
AdvSceneSwitcher.mediaTab.timeRestriction.none="Keine Auswahl"
AdvSceneSwitcher.mediaTab.timeRestriction.shorter="Dauer kürzer"
@@ -191,10 +725,10 @@ AdvSceneSwitcher.sceneSequenceTab.loadFail="Laden der Einstellungen ist fehlgesc
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="Laden der Einstellungen war erfolgreich!"
AdvSceneSwitcher.sceneSequenceTab.fileType="Text Dateien (*.txt)"
AdvSceneSwitcher.sceneSequenceTab.interruptible="kann unterbrochen werden"
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Andere Szenenwechselmethoden können diese Sequenz unterbrechen"
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Andere Szenenwechselmethoden können diese Sequenz unterbrechen"
AdvSceneSwitcher.sceneSequenceTab.entry="Wenn {{startScenes}} aktiv ist wechsle zu {{scenes}} nach {{delay}} mit {{transitions}} {{interruptible}}"
AdvSceneSwitcher.sceneSequenceTab.extendEdit="Szenenfolge erweitern"
AdvSceneSwitcher.sceneSequenceTab.extendEntry="Nach {{delay}} wechsle zu {{scenes}} mit {{transitions}}"
AdvSceneSwitcher.sceneSequenceTab.entry="Wenn {{startScenes}} aktiv ist wechsle zu {{scenes}} nach {{delay}} mit {{transitions}} {{interruptible}}"
AdvSceneSwitcher.sceneSequenceTab.help="Dieser Tab ermöglicht es automatisiert zu einer anderen Szene zu wechseln, nachdem eine Szene für die konfigurierte Zeit aktiv war.\nZum Beispiel kann so automatisch zwischen zwei Szenen hin und her gewechselt werden.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
; Audio Tab
@@ -222,8 +756,8 @@ AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Dieser Tab ermöglicht es
; Network Tab
AdvSceneSwitcher.networkTab.title="Netzwerk"
AdvSceneSwitcher.networkTab.description="Über diesen Tab kann die aktive Szene einer anderen OBS-Instanz ferngesteuert werden.\nBitte beachten, dass die Szenennamen auf allen OBS-Instanzen exakt übereinstimmen müssen."
AdvSceneSwitcher.networkTab.warning="Die Verwendung des Servers außerhalb eines lokalen Netzwerks kann dazu führen, dass die aktive Szene von dritten Personen ausgelesen werden kann."
AdvSceneSwitcher.networkTab.Disabledwarning="Diese Funktionalität musste unter macOS leider aufgrund von Bibliotheksinkompatibilitäten mit dem obs-websocket plugin deaktiviert werden."
AdvSceneSwitcher.networkTab.server="Server starten (Sendet Szenenwechselnachrichten zu allen verbundenen Clients)"
AdvSceneSwitcher.networkTab.server.port="Port"
AdvSceneSwitcher.networkTab.server.lockToIPv4="Nur IPv4 verwenden (deaktiviert IPv6)"
@@ -289,35 +823,111 @@ AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="Virtuelle
AdvSceneSwitcher.sceneTriggerTab.entry="Wenn {{scenes}} {{triggers}} {{actions}} {{audioSources}} nach {{duration}} "
AdvSceneSwitcher.sceneTriggerTab.help="Dieser Tab ermöglicht es automatisiert Handlungen, wie etwa das Stoppen von einer Aufnahme oder des Streamens, bei einem Szenenwechsel auszuführen."
; Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Starte den Erweiteren Szenenwechsler"
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stoppe den Erweiteren Szenenwechsler"
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="Starte/Stoppe den Erweiteren Szenenwechsler"
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Starte den Erweiterten Szenenwechsler"
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stoppe den Erweiterten Szenenwechsler"
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="Starte/Stoppe den Erweiterten Szenenwechsler"
AdvSceneSwitcher.hotkey.macro.pause="Pausiere Makro %1"
AdvSceneSwitcher.hotkey.macro.unpause="Makro %1 nicht mehr pausieren"
AdvSceneSwitcher.hotkey.macro.togglePause="Pause von Makro %1 togglen"
AdvSceneSwitcher.hotkey.upMacroSegmentHotkey="Makro-Segmentauswahl nach oben verschieben"
AdvSceneSwitcher.hotkey.downMacroSegmentHotkey="Makro-Segmentauswahl nach unten verschieben"
AdvSceneSwitcher.hotkey.removeMacroSegmentHotkey="Ausgewähltes Makro-Segment entfernen"
AdvSceneSwitcher.askBackup="Neue Version des Erweiterten Automatischen Szenenwechslers wurde erkannt.\nSoll ein Backup der alten Einstellungen angelegt werden?"
AdvSceneSwitcher.askForMacro="Makro auswählen {{macroSelection}}"
AdvSceneSwitcher.close="Schließen"
AdvSceneSwitcher.browse="Öffnen"
AdvSceneSwitcher.item.select="--Element auswählen--"
AdvSceneSwitcher.item.add="Neues Element hinzufügen"
AdvSceneSwitcher.item.rename="Umbenennen"
AdvSceneSwitcher.item.remove="Entfernen"
AdvSceneSwitcher.item.properties="Einstellungen"
AdvSceneSwitcher.item.newName="Neuer Name:"
AdvSceneSwitcher.item.emptyName="Leerer Name nicht zulässig!"
AdvSceneSwitcher.item.nameNotAvailable="Name nicht verfügbar!"
AdvSceneSwitcher.item.nameReserved="Name reserviert!"
AdvSceneSwitcher.variable.select="--Variable auswählen--"
AdvSceneSwitcher.variable.add="Neue Variable hinzufügen"
AdvSceneSwitcher.variable.name="Name:"
AdvSceneSwitcher.variable.value="Aktueller Wert:"
AdvSceneSwitcher.variable.save="Verhalten speichern / laden"
AdvSceneSwitcher.variable.save.dontSave="Variablenwert nicht speichern"
AdvSceneSwitcher.variable.save.save="Variablenwert speichern"
AdvSceneSwitcher.variable.save.default="Auf Wert setzen"
AdvSceneSwitcher.connection.select="--Verbindung auswählen--"
AdvSceneSwitcher.connection.add="Neue Verbindung hinzufügen"
AdvSceneSwitcher.connection.name="Name:"
AdvSceneSwitcher.connection.address="Adresse:"
AdvSceneSwitcher.connection.port="Port:"
AdvSceneSwitcher.connection.password="Passwort:"
AdvSceneSwitcher.connection.reconnect="Automatisch neu verbinden:"
AdvSceneSwitcher.connection.reconnectDelay="Automatisch neu verbinden nach:"
AdvSceneSwitcher.connection.connectOnStart="Beim Start verbinden:"
AdvSceneSwitcher.connection.test="Verbindung testen"
AdvSceneSwitcher.connection.status.disconnected="Verbindung getrennt"
AdvSceneSwitcher.connection.status.connecting="Verbindung wird aufgebaut"
AdvSceneSwitcher.connection.status.connected="Verbunden, aber nicht authentifiziert"
AdvSceneSwitcher.connection.status.authenticated="Verbunden und authentifiziert"
AdvSceneSwitcher.regex.enable="Reguläre Ausdrücke aktivieren"
AdvSceneSwitcher.regex.partialMatch="Teilweise Übereinstimmung zulassen"
AdvSceneSwitcher.regex.caseInsensitive="Groß- und Kleinschreibung wird nicht berücksichtigt"
AdvSceneSwitcher.regex.dotMatchNewline=". erkennt Zeilenumbrüche"
AdvSceneSwitcher.regex.multiLine="^ und $ erkennen Start/Ende einer Zeile"
AdvSceneSwitcher.regex.extendedPattern="Qt's ExtendedPatternSyntax aktivieren"
AdvSceneSwitcher.selectScene="--Szene auswählen--"
AdvSceneSwitcher.selectPreviousScene="Vorhergehende Szene"
AdvSceneSwitcher.currentTransition="Aktueller Szenenübergang"
AdvSceneSwitcher.selectTransition="--Szenenübergang auswählen--"
AdvSceneSwitcher.selectPreviousScene="Vorherige Szene"
AdvSceneSwitcher.selectCurrentScene="Aktuelle Szene"
AdvSceneSwitcher.selectPreviewScene="Vorschau-Szene"
AdvSceneSwitcher.selectAnyScene="Beliebige Szene"
AdvSceneSwitcher.currentTransition="Aktueller Übergang"
AdvSceneSwitcher.anyTransition="Beliebiger Übergang"
AdvSceneSwitcher.selectTransition="--Übergang auswählen--"
AdvSceneSwitcher.selectWindow="--Fenster auswählen--"
AdvSceneSwitcher.selectAudioSource="--Audio Quelle auswählen--"
AdvSceneSwitcher.selectVideoSource="--Video Quelle auswählen--"
AdvSceneSwitcher.selectMediaSource="--Medien Quelle auswählen--"
AdvSceneSwitcher.selectSource="--Quelle auswählen--"
AdvSceneSwitcher.selectAudioSource="--Audio-Quelle auswählen--"
AdvSceneSwitcher.selectVideoSource="--Video-Quelle auswählen--"
AdvSceneSwitcher.OBSVideoOutput="OBS's Haupt-Ausgabe"
AdvSceneSwitcher.selectMediaSource="--Medien-Quelle auswählen--"
AdvSceneSwitcher.selectProcess="--Prozess auswählen--"
AdvSceneSwitcher.selectFilter="--Filter auswählen--"
AdvSceneSwitcher.selectMacro="--Makro auswählen--"
AdvSceneSwitcher.selectItem="--Element auswählen--"
AdvSceneSwitcher.selectProfile="--Profil auswählen--"
AdvSceneSwitcher.selectSceneCollection="--Szenensammlung auswählen--"
AdvSceneSwitcher.enterPath="--Pfad eingeben--"
AdvSceneSwitcher.enterText="--Text eingeben--"
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="Ungültige Einträge werden nicht gespeichert"
AdvSceneSwitcher.selectWindowTip="Benutze \"OBS\" um das OBS-Studio Fenster auszuwählen\nBenutze\"Task Switching\"um die ALT + TAB Tastenkombination auszuwählen"
AdvSceneSwitcher.enterURL="--URL eingebenL--"
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="ungültige Einträge werden nicht gespeichert"
AdvSceneSwitcher.selectWindowTip="Verwende \"OBS\", um das OBS-Fenster zu definieren.\n Verwende \"Task Switching\", um ALT + TAB festzulegen."
AdvSceneSwitcher.sceneItemSelection.all="Alle"
AdvSceneSwitcher.sceneItemSelection.any="Beliebige"
AdvSceneSwitcher.status.active="Aktiv"
AdvSceneSwitcher.status.inactive="Inaktiv"
AdvSceneSwitcher.running="Plugin läuft"
AdvSceneSwitcher.stopped="Plugin gestoppt"
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Dies scheint das erste Mal zu sein, dass der Erweiterte Szenenwechsler gestartet wurde.<br>Bitte schaue ins <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> für eine Liste von Anleitungen und Beispielen.<br>Nicht zögern und Fragen im <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">Thread</span></a> des Plugins im OBS-Forum stellen!!</p></body></html>"
AdvSceneSwitcher.deprecatedTabWarning="Die Entwicklung für dieses Tab wurde gestoppt!\nBitte stattdessen zur Verwendung des Makros-Tab übergehen.\nDieser Hinweis kann im Allgemein-Tab deaktiviert werden."
AdvSceneSwitcher.unit.milliseconds="Millisekunden"
AdvSceneSwitcher.unit.secends="Sekunden"
AdvSceneSwitcher.unit.minutes="Minuten"
AdvSceneSwitcher.unit.hours="Stunden"
AdvSceneSwitcher.duration.condition.none="Kein Dauer-Modifikator"
AdvSceneSwitcher.duration.condition.more="Mindestens für"
AdvSceneSwitcher.duration.condition.equal="Für genau"
AdvSceneSwitcher.duration.condition.less="Höchstens für"
AdvSceneSwitcher.duration.condition.within="In den letzten"
AdvSceneSwitcher.audio.monitor.none="Monitoring aus"
AdvSceneSwitcher.audio.monitor.monitorOnly="Nur Monitoring (Ausgabe stummschalten)"
AdvSceneSwitcher.audio.monitor.both="Monitoring und Ausgabe"

View File

@@ -17,18 +17,21 @@ AdvSceneSwitcher.generalTab.status.autoStart.never="Never"
AdvSceneSwitcher.generalTab.status.autoStart.recording="Recording"
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streaming"
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Recording or Streaming"
AdvSceneSwitcher.generalTab.status.checkInterval="Check switch conditions every"
AdvSceneSwitcher.generalTab.status.checkInterval="Check conditions every"
AdvSceneSwitcher.generalTab.generalBehavior="General behavior"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="If no switch condition is met for"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="If no actions are performed for"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Will only ever be as accurate as the configured check interval."
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Don't switch"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Switch to any scene in Random tab"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Switch to:"
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="After a match do not switch scenes for"
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="After performing actions skip performing actions for"
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="During this time potential matches will be ignored!"
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Enable verbose logging"
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Save window position and size"
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Show system tray notifications"
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Disable UI hints"
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Hide tabs which can be represented via macros"
AdvSceneSwitcher.generalTab.matchBehavior="Match behavior"
AdvSceneSwitcher.generalTab.priority="Priority"
AdvSceneSwitcher.generalTab.priority.description="Switching methods priority (Highest priority is at the top)"
AdvSceneSwitcher.generalTab.priority.threadPriority="Use thread priority"
@@ -52,10 +55,16 @@ AdvSceneSwitcher.generalTab.priority.time="Time"
AdvSceneSwitcher.generalTab.priority.audio="Audio"
AdvSceneSwitcher.generalTab.priority.video="Video"
AdvSceneSwitcher.generalTab.priority.macro="Macro"
AdvSceneSwitcher.generalTab.transition="Transitions"
AdvSceneSwitcher.generalTab.setTransitionBy="When changing transitions:"
AdvSceneSwitcher.generalTab.transitionOverride="Set transition overrides"
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="Change active transition type"
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="At least one option must be enabled:\n\n - Use transition overrides\n\n - Change active transition type"
; Macro Tab
AdvSceneSwitcher.macroTab.title="Macro"
AdvSceneSwitcher.macroTab.macros="Macros"
AdvSceneSwitcher.macroTab.priorityWarning="Note: It is recommended to configure macros to be the highest priority functionality.\nThis setting can be changed on the General tab."
AdvSceneSwitcher.macroTab.help="Macros allow you to execute a string of actions depending on multiple conditions.\n\nClick on the highlighted plus symbol to add a new Macro."
AdvSceneSwitcher.macroTab.editConditionHelp="This section allows you to define Macro conditions.\n\nSelect an existing or add a new Macro on the left.\nThen click the plus button below to add a new condition."
AdvSceneSwitcher.macroTab.editActionHelp="This section allows you to define Macro actions.\n\nSelect an existing or add a new Macro on the left.\nThen click the plus button below to add a new action."
@@ -65,9 +74,44 @@ AdvSceneSwitcher.macroTab.edit.condition="Condition type:"
AdvSceneSwitcher.macroTab.edit.action="Action type:"
AdvSceneSwitcher.macroTab.add="Add new macro"
AdvSceneSwitcher.macroTab.name="Name:"
AdvSceneSwitcher.macroTab.run="Run macro"
AdvSceneSwitcher.macroTab.runFail="Running \"%1\" failed!\nEither one of the actions failed or the macro is running already."
AdvSceneSwitcher.macroTab.runInParallel="Run macro in parallel to other macros"
AdvSceneSwitcher.macroTab.onChange="Perform actions only on condition change"
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
AdvSceneSwitcher.macroTab.defaultGroupName="Group %1"
AdvSceneSwitcher.macroTab.exists="Macro name exists already"
AdvSceneSwitcher.macroTab.copy="Create copy"
AdvSceneSwitcher.macroTab.groupDeleteConfirm="Are you sure you want to delete \"%1\" and all its elements?"
AdvSceneSwitcher.macroTab.deleteMultipleMacrosConfirmation="Are you sure you want to delete %1 macros?"
AdvSceneSwitcher.macroTab.contextMenuAdd="Add"
AdvSceneSwitcher.macroTab.copy="Duplicate Macro"
AdvSceneSwitcher.macroTab.group="Group Selected Macros"
AdvSceneSwitcher.macroTab.ungroup="Ungroup Selected Groups"
AdvSceneSwitcher.macroTab.rename="Rename"
AdvSceneSwitcher.macroTab.remove="Remove"
AdvSceneSwitcher.macroTab.expandAll="Expand all"
AdvSceneSwitcher.macroTab.collapseAll="Collapse all"
AdvSceneSwitcher.macroTab.maximize="Maximize"
AdvSceneSwitcher.macroTab.minimize="Minimize"
AdvSceneSwitcher.macroTab.highlightSettings="Visual settings"
AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey settings"
AdvSceneSwitcher.macroTab.dockSettings="Dock settings"
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Highlight recently executed macros"
AdvSceneSwitcher.macroTab.highlightTrueConditions="Highlight conditions of currently selected macro that evaluated to true recently"
AdvSceneSwitcher.macroTab.highlightPerformedActions="Highlight recently performed actions of currently selected macro"
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Register hotkeys to control the pause state of new macros"
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Register hotkeys to control the pause state of selected macro"
AdvSceneSwitcher.macroTab.currentRegisterDock="Register dock widget to control the pause state of selected macro or run it manually"
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Add button to run the macro"
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="Add button to pause or unpause the macro"
AdvSceneSwitcher.macroDock.pause="Pause"
AdvSceneSwitcher.macroDock.unpause="Unpause"
AdvSceneSwitcher.macroDock.run="Run"
; Macro List
AdvSceneSwitcher.macroList.deleted="deleted"
AdvSceneSwitcher.macroList.duplicate="\"%1\" is alreay selected!"
; Macro Logic
AdvSceneSwitcher.logic.none="Ignore entry"
@@ -80,37 +124,132 @@ AdvSceneSwitcher.logic.not="If not"
; Macro Conditions
AdvSceneSwitcher.condition.audio="Audio"
AdvSceneSwitcher.condition.audio.state.below="Below"
AdvSceneSwitcher.condition.audio.state.above="Above"
AdvSceneSwitcher.condition.audio.entry="Volume of {{audioSources}} is {{condition}} {{volume}}"
AdvSceneSwitcher.condition.region="Screen region"
AdvSceneSwitcher.condition.region.entry="Cursor is in {{minX}} {{minY}} x {{maxX}} {{maxY}}"
AdvSceneSwitcher.condition.audio.state.below="below"
AdvSceneSwitcher.condition.audio.state.exact="exactly"
AdvSceneSwitcher.condition.audio.state.above="above"
AdvSceneSwitcher.condition.audio.state.mute="muted"
AdvSceneSwitcher.condition.audio.state.unmute="unmuted"
AdvSceneSwitcher.condition.audio.type.output="Output volume"
AdvSceneSwitcher.condition.audio.type.volume="Configured volume level"
AdvSceneSwitcher.condition.audio.type.syncOffset="Sync offset"
AdvSceneSwitcher.condition.audio.type.monitor="Audio monitoring"
AdvSceneSwitcher.condition.audio.type.balance="Audio balance"
AdvSceneSwitcher.condition.audio.entry="{{checkType}} of {{audioSources}} is {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.condition.cursor="Cursor"
AdvSceneSwitcher.condition.cursor.type.region="is in region"
AdvSceneSwitcher.condition.cursor.type.moving="is moving"
AdvSceneSwitcher.condition.cursor.type.click="clicked"
AdvSceneSwitcher.condition.cursor.button.left="Left mouse button"
AdvSceneSwitcher.condition.cursor.button.middle="Middle mouse button"
AdvSceneSwitcher.condition.cursor.button.right="Right mouse button"
AdvSceneSwitcher.condition.cursor.showFrame="Show frame"
AdvSceneSwitcher.condition.cursor.hideFrame="Hide frame"
AdvSceneSwitcher.condition.cursor.entry.line1="Cursor {{conditions}}{{buttons}}{{minX}}{{minY}}{{maxX}}{{maxY}}{{toggleFrameButton}}"
AdvSceneSwitcher.condition.cursor.entry.line2="Cursor is currently at {{xPos}} x {{yPos}}"
AdvSceneSwitcher.condition.scene="Scene"
AdvSceneSwitcher.condition.scene.type.current="Current"
AdvSceneSwitcher.condition.scene.type.previous="Previous"
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} scene is {{scenes}}"
AdvSceneSwitcher.condition.scene.type.current="Current scene is"
AdvSceneSwitcher.condition.scene.type.previous="Previous scene is"
AdvSceneSwitcher.condition.scene.type.changed="Scene changed"
AdvSceneSwitcher.condition.scene.type.notChanged="Scene has not changed"
AdvSceneSwitcher.condition.scene.type.currentPattern="Current scene matches"
AdvSceneSwitcher.condition.scene.type.previousPattern="Previous scene matches"
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="During transition check for transition target scene"
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="During transition check for transition source scene"
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
AdvSceneSwitcher.condition.window="Window"
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} exist and ..."
AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused {{windowFocusChanged}} foreground window changed"
AdvSceneSwitcher.condition.window.entry.line3="Current foreground window: {{focusWindow}}"
AdvSceneSwitcher.condition.file="File"
AdvSceneSwitcher.condition.file.entry.line1="Content of {{fileType}} {{filePath}} {{browseButton}} matches:"
AdvSceneSwitcher.condition.file.type.match="matches"
AdvSceneSwitcher.condition.file.type.contentChange="content changed"
AdvSceneSwitcher.condition.file.type.dateChange="modification date changed"
AdvSceneSwitcher.condition.file.remote="Remote file"
AdvSceneSwitcher.condition.file.local="Local file"
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}"
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.condition.media="Media"
AdvSceneSwitcher.condition.media.entry="{{mediaSources}} state is {{states}} and {{timeRestrictions}} {{time}}"
AdvSceneSwitcher.condition.media.source="Source"
AdvSceneSwitcher.condition.media.anyOnScene="Any media source 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.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}state is{{states}}and{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="Video"
AdvSceneSwitcher.condition.video.condition.match="exactly matches"
AdvSceneSwitcher.condition.video.condition.differ="does not match"
AdvSceneSwitcher.condition.video.condition.hasChanged="has changed"
AdvSceneSwitcher.condition.video.condition.hasNotChanged="has not changed"
AdvSceneSwitcher.condition.video.condition.noImage="has no output"
AdvSceneSwitcher.condition.video.condition.pattern="matches pattern"
AdvSceneSwitcher.condition.video.condition.object="contains object"
AdvSceneSwitcher.condition.video.condition.brightness="brightness"
AdvSceneSwitcher.condition.video.condition.ocr="contains text"
AdvSceneSwitcher.condition.video.askFileAction="Do you want to use an existing file or create a screenshot of the currently selected source?"
AdvSceneSwitcher.condition.video.askFileAction.file="Use existing file"
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Create screenshot"
AdvSceneSwitcher.condition.video.entry="{{videoSources}} {{condition}} {{filePath}} {{browseButton}}"
AdvSceneSwitcher.condition.video.reduceLatency="Reduce matching latency"
AdvSceneSwitcher.condition.video.reduceLatency.tooltip="Enabling will reduce the matching latency, but will slow down the condition checks of all macros overall."
AdvSceneSwitcher.condition.video.usePatternForChangedCheck="Use pattern matching"
AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="This will allow you to control how much the image has to change for the condition to be true."
AdvSceneSwitcher.condition.video.patternThreshold="Threshold: "
AdvSceneSwitcher.condition.video.patternThresholdDescription="A higher threshold value means that the pattern needs to match the video source more closely."
AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="Use alpha channel as mask for pattern."
AdvSceneSwitcher.condition.video.patternMatchMode="Use pattern matching mode {{patternMatchingModes}}"
AdvSceneSwitcher.condition.video.patternMatchMode.crossCorrelation="Cross correlation"
AdvSceneSwitcher.condition.video.patternMatchMode.correlationCoefficient="Correlation coefficient"
AdvSceneSwitcher.condition.video.patternMatchMode.squaredDifference="Squared difference"
AdvSceneSwitcher.condition.video.patternMatchMode.tip="The best method to use depends on the specific problem and the characteristics of the images involved.\nIn practice, it's often necessary to experiment with different methods and parameters to find the best match for a particular use case."
AdvSceneSwitcher.condition.video.brightnessThreshold="Average brightness is above:"
AdvSceneSwitcher.condition.video.brightnessThresholdDescription="A high value is indicating a bright image and a low one a darker one."
AdvSceneSwitcher.condition.video.currentBrightness="Current average brightness: %1"
AdvSceneSwitcher.condition.video.objectScaleThreshold="Scale factor: "
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="A lower scale factor will lead to more matches but higher CPU load."
AdvSceneSwitcher.condition.video.minNeighborDescription="A higher minimum neighbors value will result in fewer but higher quality matches."
AdvSceneSwitcher.condition.video.showMatch="Show match"
AdvSceneSwitcher.condition.video.showMatch.loading="Checking for match"
AdvSceneSwitcher.condition.video.screenshotFail="Failed to get screenshot of source!"
AdvSceneSwitcher.condition.video.screenshotEmpty="Screenshot is empty - Is the source visible?"
AdvSceneSwitcher.condition.video.patternMatchFail="Pattern was not found!"
AdvSceneSwitcher.condition.video.patternMatchSuccess="Pattern is highlighted in red"
AdvSceneSwitcher.condition.video.objectMatchFail="Object was not found!"
AdvSceneSwitcher.condition.video.objectMatchSuccess="Object is highlighted in red"
AdvSceneSwitcher.condition.video.ocrMatchSuccess="Detected text:\n\n%1"
AdvSceneSwitcher.condition.video.modelLoadFail="Model data could not be loaded!"
AdvSceneSwitcher.condition.video.selectColor="Select Color"
AdvSceneSwitcher.condition.video.ocrMode.singleColumn="Single column of text of variable sizes"
AdvSceneSwitcher.condition.video.ocrMode.singleBlockVertText="Single uniform block of vertically aligned text"
AdvSceneSwitcher.condition.video.ocrMode.singleBlock="Single uniform block of text"
AdvSceneSwitcher.condition.video.ocrMode.singleLine="Single text line"
AdvSceneSwitcher.condition.video.ocrMode.singleWord="Single word"
AdvSceneSwitcher.condition.video.ocrMode.circleWord="Single word in a circle"
AdvSceneSwitcher.condition.video.ocrMode.singleChar="Single character"
AdvSceneSwitcher.condition.video.ocrMode.sparseText="Find text in no particular order"
AdvSceneSwitcher.condition.video.ocrMode.sparseTextOSD="Find text in no particular order (OSD)"
AdvSceneSwitcher.condition.video.type.main="OBS's main output"
AdvSceneSwitcher.condition.video.type.source="Source"
AdvSceneSwitcher.condition.video.type.scene="Scene"
AdvSceneSwitcher.condition.video.entry="{{videoInputTypes}}{{sources}}{{scenes}}{{condition}}{{imagePath}}"
AdvSceneSwitcher.condition.video.entry.modelPath="Model data (haar cascade classifier): {{modelDataPath}}"
AdvSceneSwitcher.condition.video.entry.minNeighbor="Minimum neighbors: {{minNeighbors}}"
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}Reduce CPU load by performing check only every {{throttleCount}} milliseconds"
AdvSceneSwitcher.condition.video.entry.checkAreaEnable="Perform check only in area"
AdvSceneSwitcher.condition.video.entry.checkArea="{{checkAreaEnable}}{{checkArea}}{{selectArea}}"
AdvSceneSwitcher.condition.video.entry.orcColorPick="Check for text color:{{textColor}}{{selectColor}}"
AdvSceneSwitcher.condition.video.entry.orcTextType="Check for text type:{{textType}}"
AdvSceneSwitcher.condition.video.minSize="Minimum size:"
AdvSceneSwitcher.condition.video.maxSize="Maximum size:"
AdvSceneSwitcher.condition.video.selectArea="Select area"
AdvSceneSwitcher.condition.video.selectArea.status="Only highlighted area will be checked"
AdvSceneSwitcher.condition.video.width="Width"
AdvSceneSwitcher.condition.video.height="Height"
AdvSceneSwitcher.condition.stream="Streaming"
AdvSceneSwitcher.condition.stream.state.start="Stream running"
AdvSceneSwitcher.condition.stream.state.stop="Stream stopped"
AdvSceneSwitcher.condition.stream.state.starting="Stream starting"
AdvSceneSwitcher.condition.stream.state.stopping="Stream stopping"
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
AdvSceneSwitcher.condition.record="Recording"
AdvSceneSwitcher.condition.record.state.start="Recording running"
@@ -119,32 +258,48 @@ AdvSceneSwitcher.condition.record.state.stop="Recording stopped"
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
AdvSceneSwitcher.condition.process="Process"
AdvSceneSwitcher.condition.process.entry="{{processes}} is running {{focused}} and is focused"
AdvSceneSwitcher.condition.process.entry.focus="Current foreground process: {{focusProcess}}"
AdvSceneSwitcher.condition.idle="Idle"
AdvSceneSwitcher.condition.idle.entry="No keyboard or mouse inputs for {{duration}}"
AdvSceneSwitcher.condition.pluginState="Plugin state"
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Automated scene change was triggered in this interval"
AdvSceneSwitcher.condition.pluginState.state.start="Plugin started"
AdvSceneSwitcher.condition.pluginState.state.restart="Plugin restarted"
AdvSceneSwitcher.condition.pluginState.state.running="Plugin is running"
AdvSceneSwitcher.condition.pluginState.state.shutdown="OBS is shutting down"
AdvSceneSwitcher.condition.pluginState.state.sceneCollection="Scene collection loaded"
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Scene changed by previous macro"
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
AdvSceneSwitcher.condition.timer="Timer"
AdvSceneSwitcher.condition.timer.entry.line1="{{duration}} have passed"
AdvSceneSwitcher.condition.timer.type.fixed="Fixed"
AdvSceneSwitcher.condition.timer.type.random="Random"
AdvSceneSwitcher.condition.timer.pause="Pause"
AdvSceneSwitcher.condition.timer.continue="Continue"
AdvSceneSwitcher.condition.timer.entry.line1.fixed="{{type}} duration of {{duration}} has passed"
AdvSceneSwitcher.condition.timer.entry.line1.random="{{type}} duration from {{duration}} to {{duration2}} has passed"
AdvSceneSwitcher.condition.timer.entry.line2="Time remaining: {{remaining}} seconds"
AdvSceneSwitcher.condition.timer.entry.line3="{{reset}} {{autoReset}} Automatically reset timer after duration was reached"
AdvSceneSwitcher.condition.timer.entry.line3="{{pauseContinue}} {{reset}} {{saveRemaining}} Save time remaining {{autoReset}} Automatically reset timer after duration was reached"
AdvSceneSwitcher.condition.timer.reset="Reset"
AdvSceneSwitcher.condition.macro="Macro"
AdvSceneSwitcher.condition.macro.type.count="Count"
AdvSceneSwitcher.condition.macro.type.state="State"
AdvSceneSwitcher.condition.macro.type.multiState="Multiple states"
AdvSceneSwitcher.condition.macro.type.selection="Condition type: {{types}}"
AdvSceneSwitcher.condition.macro.count.type.below="Less than"
AdvSceneSwitcher.condition.macro.count.type.above="More than"
AdvSceneSwitcher.condition.macro.count.type.equal="Exactly"
AdvSceneSwitcher.condition.macro.state.type.below="Less than"
AdvSceneSwitcher.condition.macro.state.type.above="More than"
AdvSceneSwitcher.condition.macro.state.type.equal="Exactly"
AdvSceneSwitcher.condition.macro.count.reset="Reset"
AdvSceneSwitcher.condition.macro.pausedWarning="Selected macro is currently paused!"
AdvSceneSwitcher.condition.macro.state.entry="Conditions of {{macros}} are true"
AdvSceneSwitcher.condition.macro.multistate.entry="Conditions of {{multiStateConditions}}{{multiStateCount}} of the following macros are true:"
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} was executed {{conditions}} {{count}} times"
AdvSceneSwitcher.condition.macro.count.entry.line2="Current count: {{currentCount}} {{resetCount}}"
AdvSceneSwitcher.condition.source="Source"
AdvSceneSwitcher.condition.source.type.active="Is active"
AdvSceneSwitcher.condition.source.type.showing="Is showing"
AdvSceneSwitcher.condition.source.type.settings="Settings match"
AdvSceneSwitcher.condition.source.regex="Use regular expressions"
AdvSceneSwitcher.condition.source.getSettings="Get current settings"
AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}"
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
@@ -157,7 +312,6 @@ AdvSceneSwitcher.condition.filter="Filter"
AdvSceneSwitcher.condition.filter.type.active="Is enabled"
AdvSceneSwitcher.condition.filter.type.showing="Is disabled"
AdvSceneSwitcher.condition.filter.type.settings="Settings match"
AdvSceneSwitcher.condition.filter.regex="Use regular expressions"
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
AdvSceneSwitcher.condition.filter.entry.line1="On {{sources}} {{filters}} {{conditions}}"
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
@@ -167,23 +321,118 @@ AdvSceneSwitcher.condition.sceneOrder.type.above="Is above"
AdvSceneSwitcher.condition.sceneOrder.type.below="Is below"
AdvSceneSwitcher.condition.sceneOrder.type.position="Is at position"
AdvSceneSwitcher.condition.sceneOrder.positionInfo="The position value starts at the bottom with 0 and increases by one for each scene item including the ones in scene groups"
AdvSceneSwitcher.condition.sceneOrder.entry="On {{scenes}} {{sources}} {{conditions}} {{sources2}} {{position}}"
AdvSceneSwitcher.condition.sceneOrder.entry="On{{scenes}}{{sources}}{{conditions}}{{sources2}}{{position}}"
AdvSceneSwitcher.condition.hotkey="Hotkey"
AdvSceneSwitcher.condition.hotkey.name="Macro trigger hotkey"
AdvSceneSwitcher.condition.hotkey.tip="Note: You can configure the keybindings for this hotkey in the OBS settings window"
AdvSceneSwitcher.condition.hotkey.entry="Name: {{name}}"
AdvSceneSwitcher.condition.hotkey.entry.line1="Hotkey is pressed"
AdvSceneSwitcher.condition.hotkey.entry.line2="Name: {{name}}"
AdvSceneSwitcher.condition.replay="Replay buffer"
AdvSceneSwitcher.condition.replay.state.stopped="Replay buffer stopped"
AdvSceneSwitcher.condition.replay.state.started="Replay buffer started"
AdvSceneSwitcher.condition.replay.state.saved="Replay buffer saved"
AdvSceneSwitcher.condition.replay.entry="{{state}}"
AdvSceneSwitcher.condition.date="Date"
AdvSceneSwitcher.condition.date.entry.line1="{{dateTime}} {{ignoreDate}} Ignore date selection {{ignoreTime}} Ignore time selection"
AdvSceneSwitcher.condition.date.entry.line2="{{repeat}} Repeat every {{duration}}"
AdvSceneSwitcher.condition.date.anyDay="Any day"
AdvSceneSwitcher.condition.date.monday="Monday"
AdvSceneSwitcher.condition.date.tuesday="Tuesday"
AdvSceneSwitcher.condition.date.wednesday="Wednesday"
AdvSceneSwitcher.condition.date.thursday="Thursday"
AdvSceneSwitcher.condition.date.friday="Friday"
AdvSceneSwitcher.condition.date.saturday="Saturday"
AdvSceneSwitcher.condition.date.sunday="Sunday"
AdvSceneSwitcher.condition.date.state.at="At"
AdvSceneSwitcher.condition.date.state.after="After"
AdvSceneSwitcher.condition.date.state.before="Before"
AdvSceneSwitcher.condition.date.state.between="Between"
AdvSceneSwitcher.condition.date.state.pattern="Pattern"
AdvSceneSwitcher.condition.date.separator="and"
AdvSceneSwitcher.condition.date.ignoreDate="If unchecked the date component will be ignored"
AdvSceneSwitcher.condition.date.ignoreTime="If unchecked the time component will be ignored"
AdvSceneSwitcher.condition.date.showAdvancedSettings="Show advanced settings"
AdvSceneSwitcher.condition.date.showSimpleSettings="Show simple settings"
AdvSceneSwitcher.condition.date.entry.simple="On {{dayOfWeek}} {{weekCondition}} {{ignoreWeekTime}}{{weekTime}}"
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} Repeat every {{duration}} on date match"
AdvSceneSwitcher.condition.date.entry.pattern="Current date \"{{currentDate}}\" matches pattern {{pattern}}"
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Next match at: %1"
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} On repeat update selected date to repeat date"
AdvSceneSwitcher.condition.sceneTransform="Scene item transform"
AdvSceneSwitcher.condition.sceneTransform.getTransform="Get transform"
AdvSceneSwitcher.condition.sceneTransform.entry.line1="On{{scenes}}{{sources}}matches transform"
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.transition="Transition"
AdvSceneSwitcher.condition.transition.type.current="Current transition type is"
AdvSceneSwitcher.condition.transition.type.duration="Current transition duration is"
AdvSceneSwitcher.condition.transition.type.started="Transition started"
AdvSceneSwitcher.condition.transition.type.ended="Transition ended"
AdvSceneSwitcher.condition.transition.type.transitionSource="Transitioning from"
AdvSceneSwitcher.condition.transition.type.transitionTarget="Transitioning to"
AdvSceneSwitcher.condition.transition.durationSuffix="seconds"
AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{scenes}}{{duration}}{{durationSuffix}}"
AdvSceneSwitcher.condition.sceneVisibility="Scene item visibility"
AdvSceneSwitcher.condition.sceneVisibility.type.shown="is visible"
AdvSceneSwitcher.condition.sceneVisibility.type.hidden="is hidden"
AdvSceneSwitcher.condition.sceneVisibility.type.changed="visibility changed"
AdvSceneSwitcher.condition.sceneVisibility.entry="On{{scenes}}{{sources}}{{conditions}}"
AdvSceneSwitcher.condition.studioMode="Studio mode"
AdvSceneSwitcher.condition.studioMode.state.active="Studio mode is active"
AdvSceneSwitcher.condition.studioMode.state.notActive="Studio mode is not active"
AdvSceneSwitcher.condition.studioMode.state.previewScene="Preview scene is"
AdvSceneSwitcher.condition.studioMode.entry="{{conditions}}{{scenes}}"
AdvSceneSwitcher.condition.openvr="OpenVR"
AdvSceneSwitcher.condition.openvr.errorStatus="OpenVR error: "
AdvSceneSwitcher.condition.openvr.entry.line1="HMD is in ..."
AdvSceneSwitcher.condition.openvr.entry.line2="{{controls}}"
AdvSceneSwitcher.condition.openvr.entry.line3="HMD is currently at {{xPos}} x {{yPos}} x {{zPos}}"
AdvSceneSwitcher.condition.stats="OBS stats"
AdvSceneSwitcher.condition.stats.type.fps="FPS"
AdvSceneSwitcher.condition.stats.type.CPUUsage="CPU Usage"
AdvSceneSwitcher.condition.stats.type.HDDSpaceAvailable="Disk space available"
AdvSceneSwitcher.condition.stats.type.memoryUsage="Memory Usage"
AdvSceneSwitcher.condition.stats.type.averageTimeToRender="Average time to render frame"
AdvSceneSwitcher.condition.stats.type.skippedFrames="Skipped frames due to encoding lag"
AdvSceneSwitcher.condition.stats.type.missedFrames="Frames missed due to rendering lag"
AdvSceneSwitcher.condition.stats.type.droppedFrames.stream="Stream dropped frames"
AdvSceneSwitcher.condition.stats.type.megabytesSent.stream="Stream total data output"
AdvSceneSwitcher.condition.stats.type.bitrate.stream="Stream bitrate"
AdvSceneSwitcher.condition.stats.type.droppedFrames.recording="Recording dropped frames"
AdvSceneSwitcher.condition.stats.type.megabytesSent.recording="Recording total data output"
AdvSceneSwitcher.condition.stats.type.bitrate.recording="Recording bitrate"
AdvSceneSwitcher.condition.stats.condition.above="above"
AdvSceneSwitcher.condition.stats.condition.equals="equal to"
AdvSceneSwitcher.condition.stats.condition.below="below"
AdvSceneSwitcher.condition.stats.dockHint="You can open the \"Stats\" dock to view the current status"
AdvSceneSwitcher.condition.stats.entry="{{stats}} is {{condition}} {{value}}"
AdvSceneSwitcher.condition.profile="Profile"
AdvSceneSwitcher.condition.profile.entry="Current active profile is {{profiles}}"
AdvSceneSwitcher.condition.websocket="Websocket"
AdvSceneSwitcher.condition.websocket.type.request="Request"
AdvSceneSwitcher.condition.websocket.type.event="Event"
AdvSceneSwitcher.condition.websocket.useRegex="Use regular expressions"
AdvSceneSwitcher.condition.websocket.entry.request="{{type}} was received:"
AdvSceneSwitcher.condition.websocket.entry.event="{{type}} was received from {{connection}}:"
AdvSceneSwitcher.condition.variable="Variable"
AdvSceneSwitcher.condition.variable.type.compare="equals"
AdvSceneSwitcher.condition.variable.type.empty="is empty"
AdvSceneSwitcher.condition.variable.type.number="is a number"
AdvSceneSwitcher.condition.variable.type.lessThan="is less than"
AdvSceneSwitcher.condition.variable.type.greaterThan="is greater than"
AdvSceneSwitcher.condition.variable.type.valueChanged="value changed"
AdvSceneSwitcher.condition.variable.type.equalsVariable="equals variable"
AdvSceneSwitcher.condition.variable.type.lessThanVariable="is less than variable"
AdvSceneSwitcher.condition.variable.type.greaterThanVariable="is greater than variable"
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
AdvSceneSwitcher.condition.run="Run"
AdvSceneSwitcher.condition.run.entry="Process exits before timeout of{{timeout}} seconds"
AdvSceneSwitcher.condition.run.entry.exit="{{checkExitCode}}Check for exit code{{exitCode}}"
; Macro Actions
AdvSceneSwitcher.action.switchScene="Switch scene"
AdvSceneSwitcher.action.scene.entry="Switch to scene {{scenes}} using {{transitions}} with a duration of {{duration}} seconds"
AdvSceneSwitcher.action.scene.entry="Switch to scene{{scenes}}using{{transitions}}with a duration of{{duration}}seconds"
AdvSceneSwitcher.action.scene.entry.noDuration="Switch to scene{{scenes}}using{{transitions}}"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Wait until transition to target scene is complete"
AdvSceneSwitcher.action.wait="Wait"
AdvSceneSwitcher.action.wait.type.fixed="fixed"
AdvSceneSwitcher.action.wait.type.random="random"
@@ -194,15 +443,28 @@ AdvSceneSwitcher.action.audio.type.mute="Mute"
AdvSceneSwitcher.action.audio.type.unmute="Unmute"
AdvSceneSwitcher.action.audio.type.sourceVolume="Set source volume"
AdvSceneSwitcher.action.audio.type.masterVolume="Set master volume"
AdvSceneSwitcher.action.audio.entry="{{actions}} {{audioSources}} {{volume}}"
AdvSceneSwitcher.action.audio.type.syncOffset="Set sync offset"
AdvSceneSwitcher.action.audio.type.monitor="Set audio monitoring"
AdvSceneSwitcher.action.audio.type.balance="Set balance"
AdvSceneSwitcher.action.audio.balance.description="Move the slider in the direction of the audio channel you want to focus on."
AdvSceneSwitcher.action.audio.fade.type.duration="over a duration of"
AdvSceneSwitcher.action.audio.fade.type.rate="at a rate of"
AdvSceneSwitcher.action.audio.fade.duration="{{fade}}Fade {{fadeTypes}} {{duration}} seconds."
AdvSceneSwitcher.action.audio.fade.rate="{{fade}}Fade {{fadeTypes}} {{rate}}per second."
AdvSceneSwitcher.action.audio.fade.wait="Wait for fade to complete."
AdvSceneSwitcher.action.audio.fade.abort="Abort already active fade."
AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.action.recording="Recording"
AdvSceneSwitcher.action.recording.type.stop="Stop recording"
AdvSceneSwitcher.action.recording.type.start="Start recording"
AdvSceneSwitcher.action.recording.type.pause="Pause recording"
AdvSceneSwitcher.action.recording.type.unpause="Unpause recording"
AdvSceneSwitcher.action.recording.type.split="Split recording file"
AdvSceneSwitcher.action.recording.pause.hint="Note that depending on your recording settings you might not be able to pause recording"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}"
AdvSceneSwitcher.action.recording.split.hint="Make sure to enable automatic file splitting in the OBS settings first!"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="Replay buffer"
AdvSceneSwitcher.action.replay.saveWarn="Warning: Saving too frequently might result in the replay buffer not actually being saved!"
AdvSceneSwitcher.action.replay.type.stop="Stop replay buffer"
AdvSceneSwitcher.action.replay.type.start="Start replay buffer"
AdvSceneSwitcher.action.replay.type.save="Save replay buffer"
@@ -212,14 +474,13 @@ AdvSceneSwitcher.action.streaming.type.stop="Stop streaming"
AdvSceneSwitcher.action.streaming.type.start="Start streaming"
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="Run"
AdvSceneSwitcher.action.run.arguments="Arguments:"
AdvSceneSwitcher.action.run.addArgument="Add argument"
AdvSceneSwitcher.action.run.addArgumentDescription="Add new argument:"
AdvSceneSwitcher.action.run.entry="Run {{filePath}} {{browseButton}}"
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
AdvSceneSwitcher.action.sceneVisibility.entry="On {{scenes}} {{actions}} {{sources}}"
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Toggle"
AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Any"
AdvSceneSwitcher.action.sceneVisibility.entry="On{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
AdvSceneSwitcher.action.filter="Filter"
AdvSceneSwitcher.action.filter.type.enable="Enable"
AdvSceneSwitcher.action.filter.type.disable="Disable"
@@ -230,7 +491,11 @@ AdvSceneSwitcher.action.source="Source"
AdvSceneSwitcher.action.source.type.enable="Enable"
AdvSceneSwitcher.action.source.type.disable="Disable"
AdvSceneSwitcher.action.source.type.settings="Set settings"
AdvSceneSwitcher.action.source.entry="{{actions}} {{sources}}"
AdvSceneSwitcher.action.source.type.refreshSettings="Refresh source settings"
AdvSceneSwitcher.action.source.type.pressSettingsButton="Press settings button"
AdvSceneSwitcher.action.source.type.refreshSettings.tooltip="Can be used to refresh browser, media, etc. sources"
AdvSceneSwitcher.action.source.noSettingsButtons="No buttons found!"
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
AdvSceneSwitcher.action.source.warning="Warning: Enabling and disabling sources globally cannot be controlled by the OBS UI"
AdvSceneSwitcher.action.source.getSettings="Get current settings"
AdvSceneSwitcher.action.media="Media"
@@ -240,16 +505,21 @@ AdvSceneSwitcher.action.media.type.stop="Stop"
AdvSceneSwitcher.action.media.type.restart="Restart"
AdvSceneSwitcher.action.media.type.next="Next"
AdvSceneSwitcher.action.media.type.previous="Previous"
AdvSceneSwitcher.action.media.entry="{{actions}} {{mediaSources}}"
AdvSceneSwitcher.action.media.type.seek="Seek to"
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
AdvSceneSwitcher.action.macro="Macro"
AdvSceneSwitcher.action.macro.type.pause="Pause"
AdvSceneSwitcher.action.macro.type.unpause="Unpause"
AdvSceneSwitcher.action.macro.type.resetCounter="Reset counter"
AdvSceneSwitcher.action.macro.type.run="Run actions"
AdvSceneSwitcher.action.macro.type.stop="Stop actions"
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
AdvSceneSwitcher.action.pluginState="Plugin state"
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
AdvSceneSwitcher.action.pluginState.entry="{{actions}} {{values}} {{scenes}}"
AdvSceneSwitcher.action.pluginState.type.import="Import settings from"
AdvSceneSwitcher.action.pluginState.importWarning="Note: Action will be ignored while settings window is opened."
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
AdvSceneSwitcher.action.virtualCamera="Virtual camera"
AdvSceneSwitcher.action.virtualCamera.type.stop="Stop virtual camera"
AdvSceneSwitcher.action.virtualCamera.type.start="Start virtual camera"
@@ -263,29 +533,120 @@ AdvSceneSwitcher.action.hotkey.leftAlt="Left Alt"
AdvSceneSwitcher.action.hotkey.rightAlt="Right Alt"
AdvSceneSwitcher.action.hotkey.leftMeta="Left Meta"
AdvSceneSwitcher.action.hotkey.rightMeta="Right Meta"
AdvSceneSwitcher.action.hotkey.disabled="Cannot simulate key presses - functionality disabled!"
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}}"
AdvSceneSwitcher.action.hotkey.onlyOBS="Send keypress only to OBS"
AdvSceneSwitcher.action.hotkey.disabled="Cannot simulate global key presses - functionality limited to sending key press to OBS!"
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}} for {{duration}}"
AdvSceneSwitcher.action.sceneOrder="Scene item order"
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Move up"
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Move down"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Move to top"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Move to bottom"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Move to position"
AdvSceneSwitcher.action.sceneOrder.entry="On {{scenes}} {{actions}} {{sources}} {{position}}"
AdvSceneSwitcher.action.sceneOrder.entry="On{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Scene item transform"
AdvSceneSwitcher.action.sceneTransform.getTransform="Get transform"
AdvSceneSwitcher.action.sceneTransform.entry="On {{scenes}} transform {{sources}}"
AdvSceneSwitcher.action.sceneTransform.entry="On{{scenes}}transform{{sources}}"
AdvSceneSwitcher.action.file="File"
AdvSceneSwitcher.action.file.type.write="Write"
AdvSceneSwitcher.action.file.type.append="Append"
AdvSceneSwitcher.action.file.entry="{{actions}} to {{filePath}} {{browseButton}}:"
AdvSceneSwitcher.action.file.entry="{{actions}} to {{filePath}}:"
AdvSceneSwitcher.action.studioMode="Studio mode"
AdvSceneSwitcher.action.studioMode.type.swap="Swap preview and program scene"
AdvSceneSwitcher.action.studioMode.type.setScene="Set preview scene to"
AdvSceneSwitcher.action.studioMode.type.enable="Enable studio mode"
AdvSceneSwitcher.action.studioMode.type.disable="Disable studio mode"
AdvSceneSwitcher.action.studioMode.entry="{{actions}}{{scenes}}"
AdvSceneSwitcher.action.transition="Transition"
AdvSceneSwitcher.action.transition.type.scene="scene transition"
AdvSceneSwitcher.action.transition.type.sceneOverride="scene transition override"
AdvSceneSwitcher.action.transition.type.sourceShow="source show transition"
AdvSceneSwitcher.action.transition.type.sourceHide="source hide transition"
AdvSceneSwitcher.action.transition.entry.line1="Modify {{type}}{{scenes}}{{sources}}"
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Set transition type to {{transitions}}"
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Set transition duration to {{duration}}seconds"
AdvSceneSwitcher.action.timer="Timer"
AdvSceneSwitcher.action.timer.type.pause="Pause"
AdvSceneSwitcher.action.timer.type.continue="Continue"
AdvSceneSwitcher.action.timer.type.reset="Reset"
AdvSceneSwitcher.action.timer.type.setTimeRemaining="Set time remaining of"
AdvSceneSwitcher.action.timer.entry="{{timerAction}} timers on {{macros}} {{duration}}"
AdvSceneSwitcher.action.random="Random"
AdvSceneSwitcher.action.random.allowRepeat="Allow consecutive execution of the same macro"
AdvSceneSwitcher.action.random.entry="Randomly run any of the following macros (paused macros are ignored)"
AdvSceneSwitcher.action.systray="System tray notification"
AdvSceneSwitcher.action.systray.entry="Show notification: {{message}}"
AdvSceneSwitcher.action.screenshot="Screenshot"
AdvSceneSwitcher.action.screenshot.save.default="Default"
AdvSceneSwitcher.action.screenshot.save.custom="Custom"
AdvSceneSwitcher.action.screenshot.type.source="Source"
AdvSceneSwitcher.action.screenshot.type.scene="Scene"
AdvSceneSwitcher.action.screenshot.mainOutput="OBS's main output"
AdvSceneSwitcher.action.screenshot.blackscreenNote="Sources or scenes, which are not always rendered, may result in some parts of screenshots to remain blank."
AdvSceneSwitcher.action.screenshot.entry="Screenshot{{targetType}}{{sources}}{{scenes}}and save to{{saveType}}location"
AdvSceneSwitcher.action.profile="Profile"
AdvSceneSwitcher.action.profile.entry="Switch active profile to {{profiles}}"
AdvSceneSwitcher.action.sceneCollection="Scene collection"
AdvSceneSwitcher.action.sceneCollection.entry="Switch active scene collection to {{sceneCollections}}"
AdvSceneSwitcher.action.sceneCollection.warning="Note: Any actions following after this will not be executed as the changing scene collection will also reload the scene switcher settings.\nThe scene collection action will be ignored while the settings window is opened."
AdvSceneSwitcher.action.sequence="Sequence"
AdvSceneSwitcher.action.sequence.entry="Each time this action is performed run the next macro in the list (paused macros are ignored)"
AdvSceneSwitcher.action.sequence.status="Last executed macro: %1 - Next macro to be executed: %2"
AdvSceneSwitcher.action.sequence.status.none="none"
AdvSceneSwitcher.action.sequence.restart="Restart from beginning once end of list is reached"
AdvSceneSwitcher.action.sequence.continueFrom="Continue with selected item"
AdvSceneSwitcher.action.websocket="Websocket"
AdvSceneSwitcher.action.websocket.type.request="Request"
AdvSceneSwitcher.action.websocket.type.event="Event"
AdvSceneSwitcher.action.websocket.entry.request="Send scene switcher {{type}} via {{connection}}"
AdvSceneSwitcher.action.websocket.entry.event="Send scene switcher {{type}} to connected clients"
AdvSceneSwitcher.action.http="Http"
AdvSceneSwitcher.action.http.setHeaders="Set headers"
AdvSceneSwitcher.action.http.headers="Headers:"
AdvSceneSwitcher.action.http.addHeader="Add header"
AdvSceneSwitcher.action.http.type.get="GET"
AdvSceneSwitcher.action.http.type.post="POST"
AdvSceneSwitcher.action.http.entry.line1="Send {{method}} to {{url}}"
AdvSceneSwitcher.action.http.entry.line2="Timeout: {{timeout}} seconds"
AdvSceneSwitcher.action.variable="Variable"
AdvSceneSwitcher.action.variable.type.set="Set to fixed value"
AdvSceneSwitcher.action.variable.type.append="Append"
AdvSceneSwitcher.action.variable.type.appendVar="Append variable"
AdvSceneSwitcher.action.variable.type.increment="Increment"
AdvSceneSwitcher.action.variable.type.decrement="Decrement"
AdvSceneSwitcher.action.variable.type.setActionValue="Set to action value"
AdvSceneSwitcher.action.variable.type.setConditionValue="Set to condition value"
AdvSceneSwitcher.action.variable.type.roundToInt="Round to nearest integer"
AdvSceneSwitcher.action.variable.type.subString="Set to substring of current value"
AdvSceneSwitcher.action.variable.type.findAndReplace="Find and replace in current value"
AdvSceneSwitcher.action.variable.type.mathExpression="Mathematical expression"
AdvSceneSwitcher.action.variable.mathExpression.example="( 1 + 2 * 3 ) / 4"
AdvSceneSwitcher.action.variable.findAndReplace.find="Text to find"
AdvSceneSwitcher.action.variable.findAndReplace.replace="Text to replace with"
AdvSceneSwitcher.action.variable.subString.begin="Beginning"
AdvSceneSwitcher.action.variable.subString.all="All"
AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
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.currentSegmentValue="Current value:"
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
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.findAndReplace="{{findStr}}{{replaceStr}}"
AdvSceneSwitcher.action.projector="Projector"
AdvSceneSwitcher.action.projector.type.source="Source"
AdvSceneSwitcher.action.projector.type.scene="Scene"
AdvSceneSwitcher.action.projector.type.preview="Preview"
AdvSceneSwitcher.action.projector.type.program="Program"
AdvSceneSwitcher.action.projector.type.multiview="Multiview"
AdvSceneSwitcher.action.projector.display="Display"
AdvSceneSwitcher.action.projector.windowed="Windowed"
AdvSceneSwitcher.action.projector.fullscreen="Fullscreen"
AdvSceneSwitcher.action.projector.entry="Open{{windowTypes}}projector of{{types}}{{scenes}}{{sources}}"
AdvSceneSwitcher.action.projector.entry.monitor="on{{monitors}}"
; Transition Tab
AdvSceneSwitcher.transitionTab.title="Transition"
AdvSceneSwitcher.transitionTab.setTransitionBy="When changing transitions:"
AdvSceneSwitcher.transitionTab.transitionOverride="Set transition overrides"
AdvSceneSwitcher.transitionTab.adjustActiveTransitionType="Change active transition type"
AdvSceneSwitcher.transitionTab.transitionBehaviorSelectionError="At least one option must be enabled:\n\n - Use transition overrides\n\n - Change active transition type"
AdvSceneSwitcher.transitionTab.transitionForAToB="Use transition for automated scene switch from scene A to scene B"
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>These settings <span style=\"font-style:italic;\">only</span> affect transitions caused by the scene switcher - Check out <a href=\"https://obsproject.com/forum/resources/transition-table.1174/\"><span style=\" text-decoration: underline; color:#268bd2;\">Transition Table</span></a> if you want to configure this for manual scene changes.<br/>Settings defined here take priority over transition settings configured elsewhere in the scene switcher.<br/><br/>Click the plus symbol below to add a new entry.</p></body></html>"
AdvSceneSwitcher.transitionTab.defaultTransition="Change transition if scene is active"
@@ -345,7 +706,7 @@ AdvSceneSwitcher.mediaTab.states.Paused="Paused"
AdvSceneSwitcher.mediaTab.states.stopped="Stopped"
AdvSceneSwitcher.mediaTab.states.ended="Ended"
AdvSceneSwitcher.mediaTab.states.error="Error"
AdvSceneSwitcher.mediaTab.states.playedToEnd="Played to end"
AdvSceneSwitcher.mediaTab.states.playlistEnd="Ended(Playlist)"
AdvSceneSwitcher.mediaTab.states.any="Any"
AdvSceneSwitcher.mediaTab.timeRestriction.none="None"
AdvSceneSwitcher.mediaTab.timeRestriction.shorter="Time shorter"
@@ -450,8 +811,8 @@ AdvSceneSwitcher.videoTab.help="<html><head/><body><p>This tab will allow you to
; Network Tab
AdvSceneSwitcher.networkTab.title="Network"
AdvSceneSwitcher.networkTab.description="This tab will allow you to remotely control the active scene of another OBS instance.\nPlease note that the scene names have to match exactly on all OBS instances."
AdvSceneSwitcher.networkTab.warning="Running the server outside of a local network will allow third parties to read the active scene."
AdvSceneSwitcher.networkTab.DisabledWarning="This functionality unfortunately had to be disabled on macOS due to library incompatibilities when running the obs-websocket plugin in parallel."
AdvSceneSwitcher.networkTab.server="Start server (Sends scene switch messages to all connected clients)"
AdvSceneSwitcher.networkTab.server.port="Port"
AdvSceneSwitcher.networkTab.server.lockToIPv4="Lock server to only using IPv4"
@@ -523,40 +884,114 @@ AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stop the Advanced Scene Switcher"
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="Toggle Start/Stop for the Advanced Scene Switcher"
AdvSceneSwitcher.hotkey.macro.pause="Pause macro %1"
AdvSceneSwitcher.hotkey.macro.unpause="Unpause macro %1"
AdvSceneSwitcher.hotkey.macro.togglePause="Toggle pause of macro %1"
AdvSceneSwitcher.hotkey.upMacroSegmentHotkey="Move macro segment selection up"
AdvSceneSwitcher.hotkey.downMacroSegmentHotkey="Move macro segment selection down"
AdvSceneSwitcher.hotkey.removeMacroSegmentHotkey="Remove selected macro segment"
AdvSceneSwitcher.askBackup="Detected a new version of the Advanced Scene Switcher.\nShould a backup of the old settings be created?"
AdvSceneSwitcher.askForMacro="Select macro {{macroSelection}}"
AdvSceneSwitcher.close="Close"
AdvSceneSwitcher.browse="Browse"
AdvSceneSwitcher.item.select="--select item--"
AdvSceneSwitcher.item.add="Add new item"
AdvSceneSwitcher.item.rename="Rename"
AdvSceneSwitcher.item.remove="Remove"
AdvSceneSwitcher.item.properties="Properties"
AdvSceneSwitcher.item.newName="New name:"
AdvSceneSwitcher.item.emptyName="Empty name not allowed!"
AdvSceneSwitcher.item.nameNotAvailable="Name not available!"
AdvSceneSwitcher.item.nameReserved="Name reserved!"
AdvSceneSwitcher.variable.select="--select variable--"
AdvSceneSwitcher.variable.add="Add new variable"
AdvSceneSwitcher.variable.name="Name:"
AdvSceneSwitcher.variable.value="Current value:"
AdvSceneSwitcher.variable.save="Save / load behavior"
AdvSceneSwitcher.variable.save.dontSave="Don't save variable value"
AdvSceneSwitcher.variable.save.save="Save variable value"
AdvSceneSwitcher.variable.save.default="Set to value"
AdvSceneSwitcher.connection.select="--select connection--"
AdvSceneSwitcher.connection.add="Add new connection"
AdvSceneSwitcher.connection.name="Name:"
AdvSceneSwitcher.connection.address="Address:"
AdvSceneSwitcher.connection.port="Port:"
AdvSceneSwitcher.connection.password="Password:"
AdvSceneSwitcher.connection.reconnect="Reconnect automatically:"
AdvSceneSwitcher.connection.reconnectDelay="Automatically reconnect after:"
AdvSceneSwitcher.connection.connectOnStart="Connect on startup:"
AdvSceneSwitcher.connection.test="Test connection"
AdvSceneSwitcher.connection.status.disconnected="Disconnected"
AdvSceneSwitcher.connection.status.connecting="Connecting"
AdvSceneSwitcher.connection.status.connected="Connected, but not authenticated"
AdvSceneSwitcher.connection.status.authenticated="Connected and authenticated"
AdvSceneSwitcher.regex.enable="Enable regular expressions"
AdvSceneSwitcher.regex.partialMatch="Allow partial match"
AdvSceneSwitcher.regex.caseInsensitive="Match case insensitive"
AdvSceneSwitcher.regex.dotMatchNewline=". matches newlines"
AdvSceneSwitcher.regex.multiLine="^ and $ match start/end of line"
AdvSceneSwitcher.regex.extendedPattern="Enable Qt's ExtendedPatternSyntax"
AdvSceneSwitcher.process.showAdvanced="Show advanced settings"
AdvSceneSwitcher.process.arguments="Arguments:"
AdvSceneSwitcher.process.addArgument="Add argument"
AdvSceneSwitcher.process.addArgumentDescription="Add new argument:"
AdvSceneSwitcher.process.entry="Run{{filePath}}{{advancedSettings}}"
AdvSceneSwitcher.process.entry.workingDirectory="Working directory:{{workingDirectory}}"
AdvSceneSwitcher.math.expressionFail="Failed evaluate expression"
AdvSceneSwitcher.selectScene="--select scene--"
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
AdvSceneSwitcher.selectCurrentScene="Current Scene"
AdvSceneSwitcher.selectPreviewScene="Preview Scene"
AdvSceneSwitcher.selectAnyScene="Any Scene"
AdvSceneSwitcher.currentTransition="Current Transition"
AdvSceneSwitcher.anyTransition="Any Transition"
AdvSceneSwitcher.selectTransition="--select transition--"
AdvSceneSwitcher.selectWindow="--select window--"
AdvSceneSwitcher.selectSource="--select source--"
AdvSceneSwitcher.selectAudioSource="--select audio source--"
AdvSceneSwitcher.selectVideoSource="--select video source--"
AdvSceneSwitcher.OBSVideoOutput="OBS's main output"
AdvSceneSwitcher.selectMediaSource="--select media source--"
AdvSceneSwitcher.selectProcess="--select process--"
AdvSceneSwitcher.selectFilter="--select filter--"
AdvSceneSwitcher.selectMacro="--select macro--"
AdvSceneSwitcher.selectItem="--select item--"
AdvSceneSwitcher.selectProfile="--select profile--"
AdvSceneSwitcher.selectSceneCollection="--select scene collection--"
AdvSceneSwitcher.enterPath="--enter path--"
AdvSceneSwitcher.enterText="--enter text--"
AdvSceneSwitcher.enterURL="--enter URL--"
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="invalid entries will not be saved"
AdvSceneSwitcher.selectWindowTip="Use \"OBS\" to specify OBS window\nUse \"Task Switching\"to specify ALT + TAB"
AdvSceneSwitcher.sceneItemSelection.all="All"
AdvSceneSwitcher.sceneItemSelection.any="Any"
AdvSceneSwitcher.status.active="Active"
AdvSceneSwitcher.status.inactive="Inactive"
AdvSceneSwitcher.running="Plugin running"
AdvSceneSwitcher.stopped="Plugin stopped"
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>This seems to be the first time the Advanced Scene Switcher was started.<br>Please have a look at the <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> for a list of guides and examples.<br>Do not hesitate to ask questions in the plugin's <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">thread</span></a> on the OBS forums!</p></body></html>"
AdvSceneSwitcher.deprecatedTabWarning="Development for this tab stopped!\nPlease consider transitioning to using Macros instead.\nThis hint can be disabled on the General tab."
AdvSceneSwitcher.unit.milliseconds="milliseconds"
AdvSceneSwitcher.unit.secends="seconds"
AdvSceneSwitcher.unit.minutes="minutes"
AdvSceneSwitcher.unit.hours="hours"
AdvSceneSwitcher.duration.condition.none="No time constraint"
AdvSceneSwitcher.duration.condition.none="No duration modifier"
AdvSceneSwitcher.duration.condition.more="For at least"
AdvSceneSwitcher.duration.condition.equal="For exactly"
AdvSceneSwitcher.duration.condition.less="For at most"
AdvSceneSwitcher.duration.condition.within="Within the last"
AdvSceneSwitcher.audio.monitor.none="Monitor Off"
AdvSceneSwitcher.audio.monitor.monitorOnly="Monitor Only (mute output)"
AdvSceneSwitcher.audio.monitor.both="Monitor and Output"

773
data/locale/es-ES.ini Normal file
View File

@@ -0,0 +1,773 @@
AdvSceneSwitcher.pluginName="Advanced Scene Switcher"
AdvSceneSwitcher.windowTitle="Advanced Scene Switcher"
; General Tab
AdvSceneSwitcher.generalTab.title="General"
AdvSceneSwitcher.generalTab.status="Estado"
AdvSceneSwitcher.generalTab.status.hotkeytips="Los atajos pueden ser definidos en los ajustes de OBS"
AdvSceneSwitcher.generalTab.status.currentStatus="Advanced Scene Switcher está:"
AdvSceneSwitcher.generalTab.status.onStartup="Al iniciar OBS:"
AdvSceneSwitcher.generalTab.status.onStartup.asLastRun="Empezar el selector de escenas si no estaba iniciado"
AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Siempre iniciar el selector de escenas"
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="No iniciar el selector de escenas"
AdvSceneSwitcher.generalTab.status.start="Iniciar"
AdvSceneSwitcher.generalTab.status.stop="Detener"
AdvSceneSwitcher.generalTab.status.autoStart="Iniciar automáticamente el selector de escenas cuando:"
AdvSceneSwitcher.generalTab.status.autoStart.never="Nunca"
AdvSceneSwitcher.generalTab.status.autoStart.recording="Grabando"
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Emitiendo"
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Grabando o emitiendo"
AdvSceneSwitcher.generalTab.status.checkInterval="Comprobar las condiciones de cambio cada"
AdvSceneSwitcher.generalTab.generalBehavior="Comportamiento general"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="Si no se cumple ninguna condición por"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Solo será tan preciso como el intervalo de comprobación configurado."
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="No cambiar"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Cambiar a una escena aleatoria"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Cambiar a:"
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="¡Durante este tiempo, se ignorarán las posibles coincidencias!"
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Habilitar el registro detallado"
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Guardar la posición y el tamaño de la ventana"
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Mostrar notificaciones del sistema"
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Deshabilitar sugerencias de interfaz de usuario"
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Ocultar pestañas que se pueden representar a través de macros"
AdvSceneSwitcher.generalTab.priority="Prioridad"
AdvSceneSwitcher.generalTab.priority.description="Prioridad de métodos de conmutación (la prioridad más alta está en la parte superior)"
AdvSceneSwitcher.generalTab.priority.threadPriority="Usar prioridad de subproceso"
AdvSceneSwitcher.generalTab.priority.threadPriorityNotice="(No se recomienda elevar la prioridad por encima de \"Normal\")"
AdvSceneSwitcher.generalTab.saveOrLoadsettings="Guardar / Cargar ajustes"
AdvSceneSwitcher.generalTab.saveOrLoadsettings.export="Exportar"
AdvSceneSwitcher.generalTab.saveOrLoadsettings.import="Importar"
AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle="Exportar los ajustes para Advanced Scene Switcher ..."
AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle="Importar los ajustes para Advanced Scene Switcher ..."
AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType="Archivos de texto (*.txt)"
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadFail="La importacion la configuracion de escenas fallo"
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadSuccess="Configuración de escenas importada correctamente"
AdvSceneSwitcher.generalTab.priority.fileContent="Contenido del archivo"
AdvSceneSwitcher.generalTab.priority.sceneSequence="Secuencia de escenas"
AdvSceneSwitcher.generalTab.priority.idleDetection="Detección de inactivos"
AdvSceneSwitcher.generalTab.priority.executable="Ejecutable"
AdvSceneSwitcher.generalTab.priority.screenRegion="Región de pantalla"
AdvSceneSwitcher.generalTab.priority.windowTitle="Título de la ventana"
AdvSceneSwitcher.generalTab.priority.media="Medios"
AdvSceneSwitcher.generalTab.priority.time="Tiempo"
AdvSceneSwitcher.generalTab.priority.audio="Audio"
AdvSceneSwitcher.generalTab.priority.video="Video"
AdvSceneSwitcher.generalTab.priority.macro="Macro"
AdvSceneSwitcher.generalTab.setTransitionBy="Al cambiar las transiciones:"
AdvSceneSwitcher.generalTab.transitionOverride="Establecer anulaciones de transición"
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="Cambiar tipo de transición activa"
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="Al menos una opción debe estar habilitada:\n\n - Usar anulaciones de transición\n\n - Cambiar el tipo de transición activo"
; Macro Tab
AdvSceneSwitcher.macroTab.title="Macro"
AdvSceneSwitcher.macroTab.macros="Macros"
AdvSceneSwitcher.macroTab.priorityWarning="Nota: Se recomienda configurar las macros para que sean la funcionalidad de máxima prioridad.\nEsta configuración se puede cambiar en la ficha General."
AdvSceneSwitcher.macroTab.help="Las macros le permiten ejecutar una cadena de acciones en función de varias condiciones.\n\nHaga clic en el símbolo más resaltado para agregar una nueva macro."
AdvSceneSwitcher.macroTab.editConditionHelp="Esta sección le permite definir las condiciones de la macro.\n\nSeleccione una macro existente o agregue una nueva a la izquierda.\nLuego haga clic en el botón más a continuación para agregar una nueva condición."
AdvSceneSwitcher.macroTab.editActionHelp="Esta sección le permite definir acciones de la macro.\n\nSeleccione una macro existente o agregue una nueva a la izquierda.\nLuego haga clic en el botón más a continuación para agregar una nueva acción"
AdvSceneSwitcher.macroTab.edit="Editar macro"
AdvSceneSwitcher.macroTab.edit.logic="Tipo de lógica:"
AdvSceneSwitcher.macroTab.edit.condition="Tipo de condición:"
AdvSceneSwitcher.macroTab.edit.action="Tipo de acción:"
AdvSceneSwitcher.macroTab.add="Agregar nueva macro"
AdvSceneSwitcher.macroTab.name="Nombre:"
AdvSceneSwitcher.macroTab.run="Ejecutar macro"
AdvSceneSwitcher.macroTab.runFail="Error al ejecutar \"%1\" si se ha producido un error en una de las acciones o si la macro ya se está ejecutando."
AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros"
AdvSceneSwitcher.macroTab.onChange="Realizar acciones solo en el cambio de condición"
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
AdvSceneSwitcher.macroTab.exists="El nombre de la macro ya existe"
AdvSceneSwitcher.macroTab.copy="Crear copia"
AdvSceneSwitcher.macroTab.expandAll="Expandir todo"
AdvSceneSwitcher.macroTab.collapseAll="Contraer todo"
AdvSceneSwitcher.macroTab.maximize="Maximizar"
AdvSceneSwitcher.macroTab.minimize="Minimizar"
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Resaltar macros ejecutadas recientemente"
AdvSceneSwitcher.macroTab.highlightTrueConditions="Resaltar condiciones de la macro seleccionada, que se evaluaron como verdaderas recientemente"
AdvSceneSwitcher.macroTab.highlightPerformedActions="Resaltar acciones realizadas recientemente de la macro seleccionada actualmente"
; Lógica de macros
AdvSceneSwitcher.logic.none="Omitir entrada"
AdvSceneSwitcher.logic.and="Y"
AdvSceneSwitcher.logic.or="O"
AdvSceneSwitcher.logic.andNot="Y no"
AdvSceneSwitcher.logic.orNot="O no"
AdvSceneSwitcher.logic.rootNone="Si"
AdvSceneSwitcher.logic.not="Si no"
; Macro Conditions
AdvSceneSwitcher.condition.audio="Audio"
AdvSceneSwitcher.condition.audio.state.below="abajo"
AdvSceneSwitcher.condition.audio.state.exact="exactamente"
AdvSceneSwitcher.condition.audio.state.above="arriba"
AdvSceneSwitcher.condition.audio.state.mute="silenciado"
AdvSceneSwitcher.condition.audio.state.unmute="no silenciado"
AdvSceneSwitcher.condition.audio.type.output="Volumen de salida"
AdvSceneSwitcher.condition.audio.type.volume="Nivel de volumen configurado"
AdvSceneSwitcher.condition.audio.entry="{{checkType}} de {{audioSources}} es {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.condition.cursor="Cursor"
AdvSceneSwitcher.condition.cursor.type.region="está en la región"
AdvSceneSwitcher.condition.cursor.type.moving="se está moviendo"
AdvSceneSwitcher.condition.cursor.showFrame="Mostrar cuadro"
AdvSceneSwitcher.condition.cursor.hideFrame="Ocultar cuadro"
AdvSceneSwitcher.condition.cursor.entry.line1="El cursor es {{conditions}}{{buttons}}{{minX}}{{minY}}{{maxX}}{{maxY}}{{toggleFrameButton}}"
AdvSceneSwitcher.condition.cursor.entry.line2="El cursor se encuentra actualmente en {{xPos}} x {{yPos}}"
AdvSceneSwitcher.condition.scene="Escena"
AdvSceneSwitcher.condition.scene.type.current="La escena actual es"
AdvSceneSwitcher.condition.scene.type.previous="La escena anterior es"
AdvSceneSwitcher.condition.scene.type.changed="Escena cambiada"
AdvSceneSwitcher.condition.scene.type.notChanged="La escena no ha cambiado"
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Durante la transición, verifique la escena de destino de la transición"
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Durante la transición, verifique la escena de origen de la transición"
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
AdvSceneSwitcher.condition.window="Ventana"
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} existen y ..."
AdvSceneSwitcher.condition.window.entry.line2="... es {{fullscreen}} pantalla completa {{maximized}} maximizada {{focused}} enfocada {{windowFocusChanged}} ventana de primer plano cambiada"
AdvSceneSwitcher.condition.file="Archivo"
AdvSceneSwitcher.condition.file.entry.line1="Contenido de{{fileType}}{{filePath}}{{conditions}}"
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.condition.media="Medios"
AdvSceneSwitcher.condition.media.anyOnScene="Cualquier fuente multimedia activada"
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.entry="El estado de{{sourceTypes}}{{mediaSources}}{{scenes}}es{{states}}y{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="Video"
AdvSceneSwitcher.condition.video.condition.match="coincide exactamente"
AdvSceneSwitcher.condition.video.condition.differ="no coincide"
AdvSceneSwitcher.condition.video.condition.hasChanged="ha cambiado"
AdvSceneSwitcher.condition.video.condition.hasNotChanged="no ha cambiado"
AdvSceneSwitcher.condition.video.condition.noImage="no tiene salida"
AdvSceneSwitcher.condition.video.condition.pattern="coincide con el patrón"
AdvSceneSwitcher.condition.video.condition.object="contiene objeto"
AdvSceneSwitcher.condition.video.askFileAction="¿Desea utilizar un archivo existente o crear una captura de pantalla de la fuente seleccionada actualmente?"
AdvSceneSwitcher.condition.video.askFileAction.file="Usar archivo existente"
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Crear captura de pantalla"
AdvSceneSwitcher.condition.video.usePatternForChangedCheck="Usar coincidencia de patrones"
AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="Esto le permitirá controlar cuánto debe cambiar la imagen para que la condición sea verdadera".
AdvSceneSwitcher.condition.video.patternThreshold="Umbral: "
AdvSceneSwitcher.condition.video.patternThresholdDescription="Un valor de umbral más alto significa que el patrón debe coincidir más estrechamente con la fuente de video".
AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="Usar canal alfa como máscara para el patrón."
AdvSceneSwitcher.condition.video.objectScaleThreshold="Factor de escala: "
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="Un factor de escala más bajo generará más coincidencias pero una mayor carga de CPU".
AdvSceneSwitcher.condition.video.minNeighborDescription="Un valor de vecinos mínimo más alto dará como resultado menos coincidencias pero de mayor calidad".
AdvSceneSwitcher.condition.video.showMatch="Mostrar coincidencia"
AdvSceneSwitcher.condition.video.showMatch.loading="Buscando coincidencias"
AdvSceneSwitcher.condition.video.screenshotFail="¡Error al obtener la captura de pantalla de la fuente!"
AdvSceneSwitcher.condition.video.screenshotEmpty="La captura de pantalla está vacía. ¿Está visible la fuente?"
AdvSceneSwitcher.condition.video.patternMatchFail="¡No se encontró el patrón!"
AdvSceneSwitcher.condition.video.patternMatchSuccess="El patrón está resaltado en rojo"
AdvSceneSwitcher.condition.video.objectMatchFail="¡No se encontró el objeto!"
AdvSceneSwitcher.condition.video.objectMatchSuccess="El objeto está resaltado en rojo"
AdvSceneSwitcher.condition.video.modelLoadFail="¡No se pudieron cargar los datos del modelo!"
AdvSceneSwitcher.condition.video.entry="{{videoInputTypes}}{{sources}}{{scenes}}{{condition}}{{imagePath}}"
AdvSceneSwitcher.condition.video.entry.modelPath="Datos del modelo (haar cascade classifier): {{modelDataPath}}"
AdvSceneSwitcher.condition.video.entry.minNeighbor="Mínimo de vecinos: {{minNeighbors}}"
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}Reduzca la carga de la CPU realizando una comprobación solo cada {{throttleCount}} milisegundos"
AdvSceneSwitcher.condition.video.entry.checkAreaEnable="Realizar comprobación solo en el área"
AdvSceneSwitcher.condition.video.entry.checkArea="{{checkAreaEnable}}Realizar comprobación solo en el área {{checkArea}} {{selectArea}}"
AdvSceneSwitcher.condition.video.minSize="Tamaño mínimo:"
AdvSceneSwitcher.condition.video.maxSize="Tamaño máximo:"
AdvSceneSwitcher.condition.video.selectArea="Seleccionar área"
AdvSceneSwitcher.condition.video.selectArea.status="Solo se comprobará el área resaltada"
AdvSceneSwitcher.condition.video.width="Ancho"
AdvSceneSwitcher.condition.video.height="Altura"
AdvSceneSwitcher.condition.stream="Transmisión"
AdvSceneSwitcher.condition.stream.state.start="Transmisión en ejecución"
AdvSceneSwitcher.condition.stream.state.stop="Transmisión detenida"
AdvSceneSwitcher.condition.stream.state.starting="Inicio de transmisión"
AdvSceneSwitcher.condition.stream.state.stopping="Detener transmisión"
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
AdvSceneSwitcher.condition.record="Grabación"
AdvSceneSwitcher.condition.record.state.start="Grabación en ejecución"
AdvSceneSwitcher.condition.record.state.pause="Grabación en pausa"
AdvSceneSwitcher.condition.record.state.stop="Grabación detenida"
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
AdvSceneSwitcher.condition.process="Proceso"
AdvSceneSwitcher.condition.process.entry="{{processes}} se está ejecutando {{focused}} y está enfocado"
AdvSceneSwitcher.condition.idle="Inactivo"
AdvSceneSwitcher.condition.idle.entry="No hay entradas de teclado o ratón durante {{duration}}"
AdvSceneSwitcher.condition.pluginState="Estado del complemento"
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Se activó un cambio de escena automático en este intervalo"
AdvSceneSwitcher.condition.pluginState.state.running="El conmutador de escenas avanzado se está ejecutando"
AdvSceneSwitcher.condition.pluginState.state.shutdown="OBS se está cerrando"
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
AdvSceneSwitcher.condition.timer="Temporizador"
AdvSceneSwitcher.condition.timer.type.fixed="Fijar"
AdvSceneSwitcher.condition.timer.type.random="Aleatorio"
AdvSceneSwitcher.condition.timer.pause="Pausa"
AdvSceneSwitcher.condition.timer.continue="Continuar"
AdvSceneSwitcher.condition.timer.entry.line1.fixed="{{type}} la duración de {{duration}} ha pasado"
AdvSceneSwitcher.condition.timer.entry.line1.random="La duración de {{type}} de {{duration}} a {{duration2}} ha pasado"
AdvSceneSwitcher.condition.timer.entry.line2="Tiempo restante: {{remaining}} segundos"
AdvSceneSwitcher.condition.timer.entry.line3="{{pauseContinue}} {{reset}} {{saveRemaining}} Ahorra tiempo restante {{autoReset}} Restablecer el temporizador después de alcanzar la duración"
AdvSceneSwitcher.condition.timer.reset="Reiniciar"
AdvSceneSwitcher.condition.macro="Macro"
AdvSceneSwitcher.condition.macro.type.count="Recuento"
AdvSceneSwitcher.condition.macro.type.state="Estado"
AdvSceneSwitcher.condition.macro.type.selection="Tipo de condición: {{types}}"
AdvSceneSwitcher.condition.macro.count.type.below="Menor que"
AdvSceneSwitcher.condition.macro.count.type.above="Más que"
AdvSceneSwitcher.condition.macro.count.type.equal="Exactamente"
AdvSceneSwitcher.condition.macro.count.reset="Reiniciar"
AdvSceneSwitcher.condition.macro.pausedWarning="¡La macro seleccionada está actualmente en pausa!"
AdvSceneSwitcher.condition.macro.state.entry="Las condiciones de {{macros}} son verdaderas"
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} se ejecutó {{conditions}} {{count}} veces"
AdvSceneSwitcher.condition.macro.count.entry.line2="Recuento actual: {{currentCount}} {{resetCount}}"
AdvSceneSwitcher.condition.source="Fuente"
AdvSceneSwitcher.condition.source.type.active="Está activo"
AdvSceneSwitcher.condition.source.type.showing="Se muestra"
AdvSceneSwitcher.condition.source.type.settings="Coincidencia de configuración"
AdvSceneSwitcher.condition.source.getSettings="Obtener la configuración actual"
AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}"
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.source.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.virtualCamera="Cámara virtual"
AdvSceneSwitcher.condition.virtualCamera.state.start="Cámara virtual iniciada"
AdvSceneSwitcher.condition.virtualCamera.state.stop="Cámara virtual detenida"
AdvSceneSwitcher.condition.virtualCamera.entry="{{states}}"
AdvSceneSwitcher.condition.filter="Filtro"
AdvSceneSwitcher.condition.filter.type.active="Está habilitado"
AdvSceneSwitcher.condition.filter.type.showing="Está deshabilitado"
AdvSceneSwitcher.condition.filter.type.settings="Coincidencia de configuración"
AdvSceneSwitcher.condition.filter.getSettings="Obtener la configuración actual"
AdvSceneSwitcher.condition.filter.entry.line1="En {{sources}} {{filters}} {{conditions}}"
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.sceneOrder="Orden de elementos de escena"
AdvSceneSwitcher.condition.sceneOrder.type.above="Está arriba"
AdvSceneSwitcher.condition.sceneOrder.type.below="Está debajo"
AdvSceneSwitcher.condition.sceneOrder.type.position="Está en la posición"
AdvSceneSwitcher.condition.sceneOrder.positionInfo="El valor de posición comienza en la parte inferior con 0 y aumenta en uno para cada elemento de la escena, incluidos los de los grupos de escenas"
AdvSceneSwitcher.condition.sceneOrder.entry="En{{scenes}}{{sources}}{{conditions}}{{sources2}}{{position}}"
AdvSceneSwitcher.condition.hotkey="Tecla de acceso rápido"
AdvSceneSwitcher.condition.hotkey.name="Tecla de acceso directo de activación de macro"
AdvSceneSwitcher.condition.hotkey.tip="Nota: puede configurar las combinaciones de teclas para esta tecla de acceso rápido en la ventana de configuración de OBS"
AdvSceneSwitcher.condition.hotkey.entry.line1="Se presiona la tecla de acceso rápido"
AdvSceneSwitcher.condition.hotkey.entry.line2="Nombre: {{name}}"
AdvSceneSwitcher.condition.replay="Búfer de reproducción"
AdvSceneSwitcher.condition.replay.state.stopped="Búfer de reproducción detenido"
AdvSceneSwitcher.condition.replay.state.started="Búfer de reproducción iniciado"
AdvSceneSwitcher.condition.replay.state.saved="Búfer de reproducción guardado"
AdvSceneSwitcher.condition.replay.entry="{{state}}"
AdvSceneSwitcher.condition.date="Fecha"
AdvSceneSwitcher.condition.date.anyDay="Cualquier día"
AdvSceneSwitcher.condition.date.monday="Lunes"
AdvSceneSwitcher.condition.date.tuesday="Martes"
AdvSceneSwitcher.condition.date.wednesday="Miércoles"
AdvSceneSwitcher.condition.date.thursday="Jueves"
AdvSceneSwitcher.condition.date.friday="Viernes"
AdvSceneSwitcher.condition.date.saturday="Sábado"
AdvSceneSwitcher.condition.date.sunday="Domingo"
AdvSceneSwitcher.condition.date.state.at="A las"
AdvSceneSwitcher.condition.date.state.after="Después"
AdvSceneSwitcher.condition.date.state.before="Antes"
AdvSceneSwitcher.condition.date.state.between="Entre"
AdvSceneSwitcher.condition.date.separator="y"
AdvSceneSwitcher.condition.date.ignoreDate="Si no se marca, se ignorará el componente de fecha"
AdvSceneSwitcher.condition.date.ignoreTime="Si no se marca, se ignorará el componente de tiempo"
AdvSceneSwitcher.condition.date.showAdvancedSettings="Mostrar configuración avanzada"
AdvSceneSwitcher.condition.date.showSimpleSettings="Mostrar configuración simple"
AdvSceneSwitcher.condition.date.entry.simple="El {{dayOfWeek}} {{weekCondition}} {{ignoreWeekTime}}{{weekTime}}"
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} Repetir cada {{duration}} en la coincidencia de fechas"
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Próxima coincidencia en: %1"
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} Al repetir actualizar la fecha seleccionada para repetir la fecha"
AdvSceneSwitcher.condition.sceneTransform="Transformar elemento de escena"
AdvSceneSwitcher.condition.sceneTransform.getTransform="Obtener transformación"
AdvSceneSwitcher.condition.sceneTransform.entry.line1="En{{scenes}}{{sources}}coincide con la transformación"
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.transition="Transición"
AdvSceneSwitcher.condition.transition.type.current="El tipo de transición actual es"
AdvSceneSwitcher.condition.transition.type.duration="La duración de la transición actual es"
AdvSceneSwitcher.condition.transition.type.started="Transición iniciada"
AdvSceneSwitcher.condition.transition.type.ended="Transición finalizada"
AdvSceneSwitcher.condition.transition.type.transitionSource="Transición desde"
AdvSceneSwitcher.condition.transition.type.transitionTarget="Transición a"
AdvSceneSwitcher.condition.transition.durationSuffix="segundos"
AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{scenes}}{{duration}}{{durationSuffix}}"
AdvSceneSwitcher.condition.sceneVisibility="Visibilidad del elemento de escena"
AdvSceneSwitcher.condition.sceneVisibility.type.shown="Mostrado"
AdvSceneSwitcher.condition.sceneVisibility.type.hidden="Oculto"
AdvSceneSwitcher.condition.sceneVisibility.entry="En{{scenes}}{{sources}}es{{conditions}}"
AdvSceneSwitcher.condition.studioMode="Modo de estudio"
AdvSceneSwitcher.condition.studioMode.state.active="El modo de estudio está activo"
AdvSceneSwitcher.condition.studioMode.state.notActive="El modo de estudio no está activo"
AdvSceneSwitcher.condition.studioMode.state.previewScene="La vista previa de la escena es"
AdvSceneSwitcher.condition.studioMode.entry="{{conditions}}{{scenes}}"
AdvSceneSwitcher.condition.openvr="OpenVR"
AdvSceneSwitcher.condition.openvr.errorStatus="Error de OpenVR: "
AdvSceneSwitcher.condition.openvr.entry.line1="HMD está en..."
AdvSceneSwitcher.condition.openvr.entry.line2="{{controls}}"
AdvSceneSwitcher.condition.openvr.entry.line3="HMD se encuentra actualmente en {{xPos}} x {{yPos}} x {{zPos}}"
AdvSceneSwitcher.condition.stats="Estadísticas OBS"
AdvSceneSwitcher.condition.stats.type.fps="FPS"
AdvSceneSwitcher.condition.stats.type.CPUUsage="Uso de CPU"
AdvSceneSwitcher.condition.stats.type.HDDSpaceAvailable="Espacio en disco disponible"
AdvSceneSwitcher.condition.stats.type.memoryUsage="Uso de memoria"
AdvSceneSwitcher.condition.stats.type.averageTimeToRender="Tiempo medio para renderizar fotograma"
AdvSceneSwitcher.condition.stats.type.skippedFrames="Fotogramas omitidos debido a un retraso en la codificación"
AdvSceneSwitcher.condition.stats.type.missedFrames="Frames perdidos debido al retraso en el procesamiento"
AdvSceneSwitcher.condition.stats.type.droppedFrames.stream="Transmitir fotogramas perdidos"
AdvSceneSwitcher.condition.stats.type.megabytesSent.stream="Transmisión total de salida de datos"
AdvSceneSwitcher.condition.stats.type.bitrate.stream="Tasa de bits de transmisión"
AdvSceneSwitcher.condition.stats.type.droppedFrames.recording="Grabando fotogramas caídos"
AdvSceneSwitcher.condition.stats.type.megabytesSent.recording="Grabando salida de datos total"
AdvSceneSwitcher.condition.stats.type.bitrate.recording="Tasa de bits de grabación"
AdvSceneSwitcher.condition.stats.condition.above="arriba de"
AdvSceneSwitcher.condition.stats.condition.equals="igual a"
AdvSceneSwitcher.condition.stats.condition.below="abajo de"
AdvSceneSwitcher.condition.stats.dockHint="Puede abrir el panel de \"Estadísticas\" para ver el estado actual"
AdvSceneSwitcher.condition.stats.entry="{{stats}} esta {{condition}} {{value}}"
; Macro Actions
AdvSceneSwitcher.action.switchScene="Cambiar escena"
AdvSceneSwitcher.action.scene.entry="Cambiar a la escena {{scenes}} usando {{transitions}} con una duración de {{duration}} segundos"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Espere hasta que se complete la transición a la escena de destino"
AdvSceneSwitcher.action.wait="Esperar"
AdvSceneSwitcher.action.wait.type.fixed="fijo"
AdvSceneSwitcher.action.wait.type.random="aleatorio"
AdvSceneSwitcher.action.wait.entry.fixed="Espere {{waitType}} de {{duration}}"
AdvSceneSwitcher.action.wait.entry.random="Espere {{waitType}} de {{duration}} a {{duration2}}"
AdvSceneSwitcher.action.audio="Audio"
AdvSceneSwitcher.action.audio.type.mute="Silencio"
AdvSceneSwitcher.action.audio.type.unmute="Activar silencio"
AdvSceneSwitcher.action.audio.type.sourceVolume="Establecer volumen de origen"
AdvSceneSwitcher.action.audio.type.masterVolume="Establecer volumen maestro"
AdvSceneSwitcher.action.audio.fade.type.duration="durante una duración de"
AdvSceneSwitcher.action.audio.fade.type.rate="a una velocidad de"
AdvSceneSwitcher.action.audio.fade.duration="{{fade}}Fade {{fadeTypes}} {{duration}} segundos."
AdvSceneSwitcher.action.audio.fade.rate="{{fade}}Fade {{fadeTypes}} {{rate}}por segundo."
AdvSceneSwitcher.action.audio.fade.wait="Espere a que se complete el desvanecimiento".
AdvSceneSwitcher.action.audio.fade.abort="Cancelar atenuación ya activa."
AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.action.recording="Grabando"
AdvSceneSwitcher.action.recording.type.stop="Detener grabación"
AdvSceneSwitcher.action.recording.type.start="Iniciar grabación"
AdvSceneSwitcher.action.recording.type.pause="Pausar grabación"
AdvSceneSwitcher.action.recording.type.unpause="Reanudar grabación"
AdvSceneSwitcher.action.recording.pause.hint="Tenga en cuenta que, dependiendo de la configuración de grabación, es posible que no pueda pausar la grabación"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="Búfer de reproducción"
AdvSceneSwitcher.action.replay.saveWarn="Advertencia: ¡Guardar con demasiada frecuencia puede hacer que el búfer de reproducción no se guarde realmente!"
AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción"
AdvSceneSwitcher.action.replay.type.start="Iniciar búfer de reproducción"
AdvSceneSwitcher.action.replay.type.save="Guardar búfer de reproducción"
AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Transmisión"
AdvSceneSwitcher.action.streaming.type.stop="Detener transmisión"
AdvSceneSwitcher.action.streaming.type.start="Iniciar transmisión"
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="Ejecutar"
AdvSceneSwitcher.action.run.arguments="Argumentos:"
AdvSceneSwitcher.action.run.addArgument="Agregar argumento"
AdvSceneSwitcher.action.run.addArgumentDescription="Añadir nuevo argumento:"
AdvSceneSwitcher.action.run.entry="Ejecutar {{filePath}}"
AdvSceneSwitcher.action.sceneVisibility="Visibilidad del elemento de escena"
AdvSceneSwitcher.action.sceneVisibility.type.show="Mostrar"
AdvSceneSwitcher.action.sceneVisibility.type.hide="Ocultar"
AdvSceneSwitcher.action.sceneVisibility.type.source="Fuente"
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Cualquiera"
AdvSceneSwitcher.action.sceneVisibility.entry="En{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
AdvSceneSwitcher.action.filter="Filtro"
AdvSceneSwitcher.action.filter.type.enable="Habilitar"
AdvSceneSwitcher.action.filter.type.disable="Deshabilitar"
AdvSceneSwitcher.action.filter.type.settings="Establecer configuración"
AdvSceneSwitcher.action.filter.entry="En {{sources}} {{actions}} {{filters}}"
AdvSceneSwitcher.action.filter.getSettings="Obtener la configuración actual"
AdvSceneSwitcher.action.source="Fuente"
AdvSceneSwitcher.action.source.type.enable="Habilitar"
AdvSceneSwitcher.action.source.type.disable="Deshabilitar"
AdvSceneSwitcher.action.source.type.settings="Establecer configuración"
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
AdvSceneSwitcher.action.source.warning="Advertencia: la IU de OBS no puede controlar la habilitación y deshabilitación global de fuentes"
AdvSceneSwitcher.action.source.getSettings="Obtener la configuración actual"
AdvSceneSwitcher.action.media="Medios"
AdvSceneSwitcher.action.media.type.play="Reproducir"
AdvSceneSwitcher.action.media.type.pause="Pausa"
AdvSceneSwitcher.action.media.type.stop="Detener"
AdvSceneSwitcher.action.media.type.restart="Reiniciar"
AdvSceneSwitcher.action.media.type.next="Siguiente"
AdvSceneSwitcher.action.media.type.previous="Anterior"
AdvSceneSwitcher.action.media.type.seek="Buscar"
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
AdvSceneSwitcher.action.macro="Macro"
AdvSceneSwitcher.action.macro.type.pause="Pausa"
AdvSceneSwitcher.action.macro.type.unpause="Reanudar"
AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador"
AdvSceneSwitcher.action.macro.type.run="Ejecutar"
AdvSceneSwitcher.action.macro.type.stop="Detener"
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
AdvSceneSwitcher.action.pluginState="Estado del complemento"
AdvSceneSwitcher.action.pluginState.type.stop="Detener el complemento Advanced Scene Switcher"
AdvSceneSwitcher.action.pluginState.type.noMatch="Cambiar el comportamiento de no coincidencia:"
AdvSceneSwitcher.action.pluginState.type.import="Importar configuración desde"
AdvSceneSwitcher.action.pluginState.importWarning="Nota: la acción se ignorará mientras se abra la ventana de configuración."
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
AdvSceneSwitcher.action.virtualCamera="Cámara virtual"
AdvSceneSwitcher.action.virtualCamera.type.stop="Detener cámara virtual"
AdvSceneSwitcher.action.virtualCamera.type.start="Iniciar cámara virtual"
AdvSceneSwitcher.action.virtualCamera.entry="{{actions}}"
AdvSceneSwitcher.action.hotkey="Tecla de acceso rápido"
AdvSceneSwitcher.action.hotkey.leftShift="Mayús a la izquierda"
AdvSceneSwitcher.action.hotkey.rightShift="Mayús a la derecha"
AdvSceneSwitcher.action.hotkey.leftCtrl="Ctrl izquierdo"
AdvSceneSwitcher.action.hotkey.rightCtrl="Ctrl derecho"
AdvSceneSwitcher.action.hotkey.leftAlt="Alt izquierdo"
AdvSceneSwitcher.action.hotkey.rightAlt="Alt derecho"
AdvSceneSwitcher.action.hotkey.leftMeta="Meta izquierda"
AdvSceneSwitcher.action.hotkey.rightMeta="Meta derecho"
AdvSceneSwitcher.action.hotkey.onlyOBS="Enviar pulsación de tecla solo a OBS"
AdvSceneSwitcher.action.hotkey.disabled="No se puede simular la pulsación de teclas: ¡funcionalidad desactivada!"
AdvSceneSwitcher.action.hotkey.entry="Presione {{keys}} durante {{duration}}"
AdvSceneSwitcher.action.sceneOrder="Orden de elementos de escena"
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Mover hacia arriba"
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Mover hacia abajo"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Mover al principio"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Mover al final"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Mover a la posición"
AdvSceneSwitcher.action.sceneOrder.entry="En{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Transformar elemento de escena"
AdvSceneSwitcher.action.sceneTransform.getTransform="Obtener transformación"
AdvSceneSwitcher.action.sceneTransform.entry="En{{scenes}}transformar{{sources}}"
AdvSceneSwitcher.action.file="Archivo"
AdvSceneSwitcher.action.file.type.write="Escribir"
AdvSceneSwitcher.action.file.type.append="Agregar"
AdvSceneSwitcher.action.file.entry="{{actions}} a {{filePath}}:"
AdvSceneSwitcher.action.studioMode="Modo estudio"
AdvSceneSwitcher.action.studioMode.type.swap="Intercambiar vista previa y escena del programa"
AdvSceneSwitcher.action.studioMode.type.setScene="Establecer escena de vista previa en"
AdvSceneSwitcher.action.studioMode.type.enable="Activar modo estudio"
AdvSceneSwitcher.action.studioMode.type.disable="Deshabilitar el modo de estudio"
AdvSceneSwitcher.action.studioMode.entry="{{actions}}{{scenes}}"
AdvSceneSwitcher.action.transition="Transición"
AdvSceneSwitcher.action.transition.type.scene="transición de escena"
AdvSceneSwitcher.action.transition.type.sceneOverride="anulación de transición de escena"
AdvSceneSwitcher.action.transition.type.sourceShow="transición del programa de origen"
AdvSceneSwitcher.action.transition.type.sourceHide="fuente ocultar transición"
AdvSceneSwitcher.action.transition.entry.line1="Modificar {{type}}{{scenes}}{{sources}}"
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Establecer el tipo de transición en {{transitions}}"
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Establecer la duración de la transición en {{duration}}segundos"
AdvSceneSwitcher.action.timer="Temporizador"
AdvSceneSwitcher.action.timer.type.pause="Pausa"
AdvSceneSwitcher.action.timer.type.continue="Continuar"
AdvSceneSwitcher.action.timer.type.reset="Reiniciar"
AdvSceneSwitcher.action.timer.type.setTimeRemaining="Establecer tiempo restante de"
AdvSceneSwitcher.action.timer.entry="{{timerAction}} temporizadores en {{macros}} {{duration}}"
AdvSceneSwitcher.action.random="Aleatorio"
AdvSceneSwitcher.action.random.entry="Ejecute aleatoriamente cualquiera de las siguientes macros (las macros en pausa se ignoran)"
AdvSceneSwitcher.action.systray="Notificación de la bandeja del sistema"
AdvSceneSwitcher.action.systray.entry="Mostrar notificación: {{message}}"
AdvSceneSwitcher.action.screenshot="Captura de pantalla"
AdvSceneSwitcher.action.screenshot.mainOutput="Salida principal de OBS"
AdvSceneSwitcher.action.profile="Perfil"
AdvSceneSwitcher.action.profile.entry="Cambiar perfil activo a {{profiles}}"
AdvSceneSwitcher.action.sceneCollection="Colección de escenas"
AdvSceneSwitcher.action.sceneCollection.entry="Cambiar la colección de escenas activa a {{sceneCollections}}"
AdvSceneSwitcher.action.sceneCollection.warning="Nota: Cualquier acción posterior a esta no se ejecutará, ya que la colección de escenas cambiante también volverá a cargar la configuración del conmutador de escenas.\nLa acción de la colección de escenas se ignorará mientras se abra la ventana de configuración".
AdvSceneSwitcher.action.sequence="Secuencia"
AdvSceneSwitcher.action.sequence.entry="Cada vez que se realiza esta acción, ejecute la siguiente macro de la lista (las macros en pausa se ignoran)"
AdvSceneSwitcher.action.sequence.status="Última macro ejecutada: %1 - Siguiente macro a ejecutar: %2"
AdvSceneSwitcher.action.sequence.status.none="ninguno"
AdvSceneSwitcher.action.sequence.restart="Reiniciar desde el principio una vez que se alcance el final de la lista"
AdvSceneSwitcher.action.sequence.continueFrom="Continuar con el elemento seleccionado"
; Transition Tab
AdvSceneSwitcher.transitionTab.title="Transición"
AdvSceneSwitcher.transitionTab.transitionForAToB="Utiliza la transición para el cambio de escena automatizado de la escena A a la escena B"
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body> <p> Estos ajustes <span style =\"font-style: italic; \"> solo </span> surgió a las transiciones causadas por el selector de escenas - Echa un vistazo a <a href =\"https://obsproject.com/forum/resources/transition-table.1174/\"> <span style=\" texto-decoración: subrayado; color: # 268bd2; \"> Tabla de transición </span> </a> si desea configurar esto para cambios de escena manuales. <br/> Los definiciones definidos aquí tienen prioridad sobre los ajustes de transición configurados en cualquier otro lugar del selector de escenas. < br/> <br/> Haz clic en el símbolo más a continuación para agregar una nueva entrada. </p></body></html>"
AdvSceneSwitcher.transitionTab.defaultTransition="Cambiar transición si la escena está activa"
AdvSceneSwitcher.transitionTab.entry="Cambiar de {{scenes}} a {{scenes2}} usando {{transitions}} con una duración de {{duration}}"
AdvSceneSwitcher.transitionTab.defaultTransitionEntry="Cuando la escena {{scenes}} está activa, cambie la transición de escena predeterminada a {{transitions}}"
AdvSceneSwitcher.transitionTab.defaultTransitionsHelp="Haga clic en el símbolo más para añadir una entrada."
AdvSceneSwitcher.transitionTab.defaultTransition.delay="Cambiar transición {{defTransitionDelay}} después del cambio de escena."
AdvSceneSwitcher.transitionTab.defaultTransition.delay.help="El retraso se usa para evitar cambios de escena cancelados, lo que puede suceder si se cambia el tipo de transición mientras una transición aún está en curso".
; Pause Scenes Tab
AdvSceneSwitcher.pauseTab.title="Pausar"
AdvSceneSwitcher.pauseTab.pauseOnScene="Pausar el selector de escenas en la escena"
AdvSceneSwitcher.pauseTab.pauseInFocus1="Pausar el selector de escena cuando "
AdvSceneSwitcher.pauseTab.pauseInFocus2="esté en foco"
AdvSceneSwitcher.pauseTab.pauseTypeScene="la escena esté activa"
AdvSceneSwitcher.pauseTab.pauseTypeWindow="la ventana esté en foco"
AdvSceneSwitcher.pauseTab.pauseTargetAll="Todas"
AdvSceneSwitcher.pauseTab.pauseEntry="Pausar {{pauseTargets}} cuando {{pauseTypes}} {{scenes}} {{windows}}"
AdvSceneSwitcher.pauseTab.help="En esta pestaña puedes configurar la pausa de métodos de cambio individuales si una escena está activa o una ventana está enfocada.\n\nHaz clic en el símbolo más resaltado para continuar."
; Window Title Tab
AdvSceneSwitcher.windowTitleTab.title="Titulo"
AdvSceneSwitcher.windowTitleTab.regexrDescription="<html><head/><body><p>Introduce el título directo de una ventana o un regex válido. Puedes verificar la sintaxis y las coincidencias para las expresiones regulares usando <a href=\"https://regexr.com\"><span style=\" text-decoration: underline; color:#268bd2;\">RegExr</span></a></p></body></html>"
AdvSceneSwitcher.windowTitleTab.stayInFocus1="Ignorar nombre de la ventana"
AdvSceneSwitcher.windowTitleTab.stayInFocus2=" "
AdvSceneSwitcher.windowTitleTab.fullscreen="si está en pantalla completa"
AdvSceneSwitcher.windowTitleTab.maximized="si está maximizada"
AdvSceneSwitcher.windowTitleTab.focused="si está en foco"
AdvSceneSwitcher.windowTitleTab.entry="{{windows}} {{scenes}} {{transitions}} {{fullscreen}} {{maximized}} {{focused}}"
AdvSceneSwitcher.windowTitleTab.windowsHelp="Cambia de escena según el título de la ventana de las aplicaciones en ejecución.\nSe pueden seleccionar las siguientes condiciones adicionales:\nLa ventana está en Pantalla completa\nLa ventana está maximizada\nLa ventana está enfocada\n\nHaz clic en el símbolo más resaltado para continuar."
AdvSceneSwitcher.windowTitleTab.ignoreWindowsHelp="Si se ignora el título de una ventana, el selector de escena actuará como si la ventana seleccionada anteriormente todavía estuviera enfocada.\nEsto te permitirá evitar cambios de escena, si cambias con frecuencia a una ventana diferente, lo que no provocará un cambio de escena.\n\nElige una ventana o introduce un título de ventana arriba y haz clic en el símbolo más a continuación para agregarlo a la lista."
; Executable Tab
AdvSceneSwitcher.executableTab.title="Ejecutable"
AdvSceneSwitcher.executableTab.implemented="Implementado por dasOven"
AdvSceneSwitcher.executableTab.requiresFocus="sólo si está en foco"
AdvSceneSwitcher.executableTab.entry="Cuando {{processes}} está ejectuándose cambiar a {{scenes}} usando {{transitions}} {{requiresFocus}}"
AdvSceneSwitcher.executableTab.help="Esta pestaña te permitirá cambiar de escena automáticamente si se está ejecutando un proceso.\nEsto puede ser útil en situaciones en las que el nombre de la ventana puede cambiar o no se conoce.\n\nHaz clic en el símbolo más resaltado para continuar."
; Screen Region Tab
AdvSceneSwitcher.screenRegionTab.title="Región"
AdvSceneSwitcher.screenRegionTab.currentPosition="El cursor está actualmente en:"
AdvSceneSwitcher.screenRegionTab.showGuideFrames="Mostrar marcos de guía"
AdvSceneSwitcher.screenRegionTab.hideGuideFrames="Ocultar guide frames"
AdvSceneSwitcher.screenRegionTab.excludeScenes.None="Sin selección"
AdvSceneSwitcher.screenRegionTab.entry="Si el cursor está en {{minX}} {{minY}} x {{maxX}} {{maxY}} cambiar a {{scenes}} usando {{transitions}} a menos que esté en {{excludeScenes}}"
AdvSceneSwitcher.screenRegionTab.help="Esta pestaña te permitirá cambiar escenas automáticamente según la posición actual del cursor del ratón.\n\nHaz clic en el símbolo más resaltado para continuar."
; Media Tab
AdvSceneSwitcher.mediaTab.title="Medios"
AdvSceneSwitcher.mediaTab.implemented="Implementado por Exeldro"
AdvSceneSwitcher.mediaTab.states.none="Ninguno"
AdvSceneSwitcher.mediaTab.states.playing="Reproduciéndose"
AdvSceneSwitcher.mediaTab.states.opening="Abriendo"
AdvSceneSwitcher.mediaTab.states.buffering="Almacenando en búfer"
AdvSceneSwitcher.mediaTab.states.Paused="Pausado"
AdvSceneSwitcher.mediaTab.states.stopped="Detenido"
AdvSceneSwitcher.mediaTab.states.ended="Finalizado"
AdvSceneSwitcher.mediaTab.states.error="Error"
AdvSceneSwitcher.mediaTab.states.playlistEnd="Finalizado(lista de reproducción)"
AdvSceneSwitcher.mediaTab.states.any="Cualquiera"
AdvSceneSwitcher.mediaTab.timeRestriction.none="Ninguno"
AdvSceneSwitcher.mediaTab.timeRestriction.shorter="Tiempo es más corto"
AdvSceneSwitcher.mediaTab.timeRestriction.longer="Tiempo es más largo"
AdvSceneSwitcher.mediaTab.timeRestriction.remainShorter="Tiempo que quede es más corto"
AdvSceneSwitcher.mediaTab.timeRestriction.remainLonger="Tiempo que quede es más largo"
AdvSceneSwitcher.mediaTab.entry="Cuando el estado de {{mediaSources}} es {{states}} y el {{timeRestrictions}} que {{time}} cambiar a {{scenes}} usando {{transitions}}"
AdvSceneSwitcher.mediaTab.help="Esta pestaña te permitirá cambiar de escena según los estados de las fuentes de medios.\nPor ejemplo, puede volver automáticamente a la escena anterior una vez que la fuente de medios seleccionada finalizó su reproducción.\n\nHaz clic en el símbolo más resaltado para continuar."
; File Tab
AdvSceneSwitcher.fileTab.title="Archivo"
AdvSceneSwitcher.fileTab.readWriteSceneFile="Leer / escribir escena desde / a un archivo"
AdvSceneSwitcher.fileTab.currentSceneOutputFile="Escribe el nombre de la escena actual en este archivo:"
AdvSceneSwitcher.fileTab.switchSceneBaseOnFile="Habilitar el cambio de escenas según la entrada de archivos"
AdvSceneSwitcher.fileTab.switchSceneNameInputFile="Leer el nombre de la escena a la que se cambiará desde este archivo:"
AdvSceneSwitcher.fileTab.switchSceneBaseOnFileContent="Cambiar de escena según el contenido del archivo"
AdvSceneSwitcher.fileTab.remoteFileWarning="Ten en cuenta que si eliges la opción remota, el selector de escenas intentará acceder a la ubicación remota cada x ms como se especifica en la pestaña General."
AdvSceneSwitcher.fileTab.remoteFileWarning1="Ten en cuenta que el selector de escenas intentará acceder a la ubicación remota cada "
AdvSceneSwitcher.fileTab.remoteFileWarning2="ms"
AdvSceneSwitcher.fileTab.libcurlWarning="¡Error al cargar libcurl! ¡No será posible acceder a archivos remotos!"
AdvSceneSwitcher.fileTab.selectWrite="Selecciona un archivo para escribir ..."
AdvSceneSwitcher.fileTab.selectRead="Seleccione un archivo para leer ..."
AdvSceneSwitcher.fileTab.textFileType="Archivos de texto (*.txt)"
AdvSceneSwitcher.fileTab.anyFileType="Cualquier archivo (*.*)"
AdvSceneSwitcher.fileTab.remote="archivo remoto"
AdvSceneSwitcher.fileTab.local="archivo local"
AdvSceneSwitcher.fileTab.useRegExp="usar expresiones regulares (coincidencia de patrones)"
AdvSceneSwitcher.fileTab.checkfileContentTime="si la fecha de modificación cambió"
AdvSceneSwitcher.fileTab.checkfileContent="si el contenido cambia"
AdvSceneSwitcher.fileTab.entry="Cambiar a {{scenes}} usando {{transitions}} si el contenido de {{fileType}} {{filePath}} {{browseButton}} coincide con:"
AdvSceneSwitcher.fileTab.entry2="{{matchText}}"
AdvSceneSwitcher.fileTab.entry3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.fileTab.help="Esta pestaña te permitirá cambiar escenas automáticamente según el contenido de archivos remotos o locales.\n\nHaz clic en el símbolo más resaltado para continuar."
; Random Tab
AdvSceneSwitcher.randomTab.title="Aleatorio"
AdvSceneSwitcher.randomTab.randomDisabledWarning="Funcionalidad deshabilitada - para activarla, selecciona \"Si no se cumple ninguna condición de cambio, cambiar a cualquier escena en la pestaña Aleatorio\" en la pestaña General"
AdvSceneSwitcher.randomTab.entry="Si no se cumple ninguna condición de cambio, cambiar a {{scenes}} usando {{transitions}} después de {{delay}}"
AdvSceneSwitcher.randomTab.help="El selector de escenas elegirá aleatoriamente una entrada en esta pestaña para cambiar durante el tiempo configurado.\nTen en cuenta que la misma entrada no se elegirá dos veces seguidas.\n\nHaz clic en el símbolo más resaltado para continuar."
; Time Tab
AdvSceneSwitcher.timeTab.title="Tiempo"
AdvSceneSwitcher.timeTab.anyDay="En cualquier día"
AdvSceneSwitcher.timeTab.mondays="Lunes"
AdvSceneSwitcher.timeTab.tuesdays="Martes"
AdvSceneSwitcher.timeTab.wednesdays="Miércoles"
AdvSceneSwitcher.timeTab.thursdays="Jueves"
AdvSceneSwitcher.timeTab.fridays="Viernes"
AdvSceneSwitcher.timeTab.saturdays="Sábados"
AdvSceneSwitcher.timeTab.sundays="Domingos"
AdvSceneSwitcher.timeTab.afterstart="Empezar al iniciar emisión/grabación"
AdvSceneSwitcher.timeTab.afterstart.tip="Se utilizará el tiempo relativo al inicio de la transmisión / grabación"
AdvSceneSwitcher.timeTab.entry="{{triggers}} a las {{time}} cambiar a {{scenes}} usando {{transitions}}"
AdvSceneSwitcher.timeTab.help="Esta pestaña te permitirá cambiar automáticamente a una escena diferente en función de la hora local actual.\n\nTen en cuenta que el selector de escenas solo cambiará de escena a la hora exacta que especificaste.\nAsegúrate de haber configurado los ajustes de prioridad en la pestaña General a tu gusto para que no se pierda el punto de tiempo seleccionado debido a que otros métodos de cambio tengan una prioridad más alta.\n\nHaz clic en el símbolo más resaltado para continuar."
; Idle Tab
AdvSceneSwitcher.idleTab.title="Inactividad"
AdvSceneSwitcher.idleTab.enable="Habilitar la detección de inactividad"
AdvSceneSwitcher.idleTab.idleswitch="Después de {{duration}} sin entradas de teclado o ratón, cambiar a la escena {{scenes}} usando la {{transitions}}"
AdvSceneSwitcher.idleTab.dontSwitchIfFocus1="No cambiar si"
AdvSceneSwitcher.idleTab.dontSwitchIfFocus2="está en foco"
; Scene Sequence Tab
AdvSceneSwitcher.sceneSequenceTab.title="Secuencia"
AdvSceneSwitcher.sceneSequenceTab.description="Se puede cancelar una secuencia de cambios de escena automática pausando / deteniendo el selector de escenas o cambiando manualmente a una escena diferente"
AdvSceneSwitcher.sceneSequenceTab.save="Guardar secuencias de escenas en un archivo"
AdvSceneSwitcher.sceneSequenceTab.load="Cargar secuencias de escenas desde un archivo"
AdvSceneSwitcher.sceneSequenceTab.saveTitle="Guardar la secuencia de escenas en un archivo ..."
AdvSceneSwitcher.sceneSequenceTab.loadTitle="Seleccionar un archivo para leer la secuencia de escenas ..."
AdvSceneSwitcher.sceneSequenceTab.loadFail="¡Advanced Scene Switcher no ha podido cargar los ajustes!"
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="¡Advanced Scene Switcher ha importando los ajustes correctamente!"
AdvSceneSwitcher.sceneSequenceTab.fileType="Archivos de texto (*.txt)"
AdvSceneSwitcher.sceneSequenceTab.interruptible="interrumpible"
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Se permiten otros métodos de cambio para interrumpir esta secuencia de escenas."
AdvSceneSwitcher.sceneSequenceTab.entry="Cuando {{startScenes}} esté activo, cambiar a {{scenes}} después de {{delay}} usando {{transitions}} {{interruptible}}"
AdvSceneSwitcher.sceneSequenceTab.extendEdit="Extender secuencia"
AdvSceneSwitcher.sceneSequenceTab.extendEntry="Después de {{delay}} cambiar a {{scenes}} usando {{transitions}}"
AdvSceneSwitcher.sceneSequenceTab.help="Esta pestaña te permitirá cambiar automáticamente a una escena diferente si una escena estuvo activa durante un período de tiempo configurado.\nPor ejemplo, podrías alternar automáticamente entre dos escenas automáticamente.\n\nHaz clic en el símbolo más resaltado para seguir."
; Audio Tab
AdvSceneSwitcher.audioTab.title="Audio"
AdvSceneSwitcher.audioTab.condition.above="por encima del"
AdvSceneSwitcher.audioTab.condition.below="por debajo del"
AdvSceneSwitcher.audioTab.ignoreInactiveSource="a menos que la fuente esté inactiva"
AdvSceneSwitcher.audioTab.entry="Cuando el volumen de {{audioSources}} es {{condition}} {{volumeWidget}} durante {{duration}} segundos, cambie a {{scenes}} usando {{transitions}} {{ignoreInactiveSource}}"
AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="Si múltiples entradas coinciden ..."
AdvSceneSwitcher.audioTab.multiMatchfallback="... durante {{duration}} cambiar a {{scenes}} usando {{transitions}}"
AdvSceneSwitcher.audioTab.help="Esta pestaña te permitirá cambiar de escena según el volumen de las fuentes.\nPor ejemplo, podrías cambiar automáticamente a una escena diferente si el volumen de su micrófono alcanza un cierto umbral.\n\nHaz clic en el símbolo más resaltado para continuar."
; Video Tab
AdvSceneSwitcher.videoTab.title="Vídeo"
AdvSceneSwitcher.videoTab.getScreenshot="Obtener captura de pantalla para la entrada seleccionada"
AdvSceneSwitcher.videoTab.getScreenshotHelp="Obtén una captura de pantalla de la fuente de vídeo de la entrada actualmente seleccionada y configúrala automáticamente como la imagen de destino"
AdvSceneSwitcher.videoTab.condition.match="coincide exactamente"
AdvSceneSwitcher.videoTab.condition.match.tooltip="Una coincidencia exacta requiere que el objetivo y la imagen de origen tengan la misma resolución.\nAdicionalmente, todos los píxeles deben coincidir, por lo que no se recomienda el uso de formatos de imagen que utilizan compresión (por ejemplo, .JPG)."
AdvSceneSwitcher.videoTab.condition.differ="no coincide"
AdvSceneSwitcher.videoTab.condition.hasNotChanged="no ha cambiado"
AdvSceneSwitcher.videoTab.condition.hasChanged="ha cambiado"
AdvSceneSwitcher.videoTab.ignoreInactiveSource="a menos que la fuente esté inactiva"
AdvSceneSwitcher.videoTab.entry="Cuando {{videoSources}} {{condition}} {{filePath}} {{browseButton}} durante {{duration}} cambiar a {{scenes}} usando {{transitions}} {{ignoreInactiveSource}}"
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Esta pestaña te permitirá cambiar escenas según la salida de vídeo actual de las fuentes seleccionadas.<br/>Asegúrate de revisar <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> para una implementación aún mejor de esta funcionalidad.<br/><br/> Haz clic en el símbolo más resaltado para continuar.</p></body></html>"
; Network Tab
AdvSceneSwitcher.networkTab.title="Red"
AdvSceneSwitcher.networkTab.description="Esta pestaña le permitirá controlar de forma remota la escena activa de otra instancia de OBS.\nTenga en cuenta que los nombres de las escenas deben coincidir exactamente en todas las instancias de OBS".
AdvSceneSwitcher.networkTab.warning="Ejecutar el servidor fuera de una red local permitirá que terceros lean la escena activa".
AdvSceneSwitcher.networkTab.server="Iniciar servidor (envía mensajes de cambio de escena a todos los clientes conectados)"
AdvSceneSwitcher.networkTab.server.port="Puerto"
AdvSceneSwitcher.networkTab.server.lockToIPv4="Bloquear servidor para usar solo IPv4"
AdvSceneSwitcher.networkTab.server.sendSceneChange="Enviar mensajes para cambios de escena"
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Solo enviar mensajes para cambios de escena automatizados"
AdvSceneSwitcher.networkTab.server.sendPreview="Enviar mensajes para obtener una vista previa del cambio de escena cuando se ejecuta en Modo Estudio"
AdvSceneSwitcher.networkTab.startFailed.message="El servidor WebSockets no pudo iniciarse, tal vez porque:\n - El puerto TCP %1 puede estar actualmente en uso en otro lugar de este sistema, posiblemente por otra aplicación. Intente configurar un puerto TCP diferente en el WebSocket configuración del servidor o detenga cualquier aplicación que pueda estar usando este puerto.\n - Mensaje de error: %2"
AdvSceneSwitcher.networkTab.server.status.currentStatus="Estado actual"
AdvSceneSwitcher.networkTab.server.status.notRunning="Desconectado"
AdvSceneSwitcher.networkTab.server.status.starting="Iniciando"
AdvSceneSwitcher.networkTab.server.status.running="En ejecución"
AdvSceneSwitcher.networkTab.server.restart="Reiniciar servidor"
AdvSceneSwitcher.networkTab.client="Iniciar cliente (Recibe mensajes de cambios de escena)"
AdvSceneSwitcher.networkTab.client.address="Nombre de host o dirección IP"
AdvSceneSwitcher.networkTab.client.port="Puerto"
AdvSceneSwitcher.networkTab.client.status.currentStatus="Estado actual"
AdvSceneSwitcher.networkTab.client.status.disconnected="Desconectado"
AdvSceneSwitcher.networkTab.client.status.connecting="Conectando"
AdvSceneSwitcher.networkTab.client.status.connected="Conectado"
AdvSceneSwitcher.networkTab.client.reconnect="Forzar reconexión"
; Scene Group Tab
AdvSceneSwitcher.sceneGroupTab.title="Grupo de escenas"
AdvSceneSwitcher.sceneGroupTab.list="Grupos de escenas"
AdvSceneSwitcher.sceneGroupTab.edit="Editar grupos de escenas"
AdvSceneSwitcher.sceneGroupTab.edit.name="Nombre:"
AdvSceneSwitcher.sceneGroupTab.edit.type="Tipo: {{type}}"
AdvSceneSwitcher.sceneGroupTab.type.count="Contar"
AdvSceneSwitcher.sceneGroupTab.type.time="Tiempo"
AdvSceneSwitcher.sceneGroupTab.type.random="Al azar"
AdvSceneSwitcher.sceneGroupTab.edit.count="Avanzar a la siguiente escena en la lista después de {{count}} coincidencias"
AdvSceneSwitcher.sceneGroupTab.edit.time="Avanzar a la siguiente escena de la lista después de que haya pasado {{time}}"
AdvSceneSwitcher.sceneGroupTab.edit.random="Elige la siguiente escena en la lista al azar"
AdvSceneSwitcher.sceneGroupTab.edit.repeat="Empezar desde el principio si se llega al final de la lista de escenas"
AdvSceneSwitcher.sceneGroupTab.edit.addScene="Agregar escena"
AdvSceneSwitcher.sceneGroupTab.add="Agregar grupo de escenas"
AdvSceneSwitcher.sceneGroupTab.defaultname="Grupo de escenas %1"
AdvSceneSwitcher.sceneGroupTab.exists="El grupo de escenas o el nombre de la escena ya existe"
AdvSceneSwitcher.sceneGroupTab.help="Los grupos de escenas se pueden seleccionar como un objetivo al igual que una escena normal.\n\nComo sugiere el nombre, un grupo de escenas es una colección de varias escenas.\nEl grupo de escenas avanzará a través de la lista de sus escenas asignadas según los ajustes configurados, que se puede encontrar en el lado derecho.\n\nPuedes configurar el grupo de escenas para avanzar a la siguiente escena en la lista:\nDespués de varias veces, el grupo de escenas se selecciona como objetivo.\nDespués de que un cierto período de tiempo haya pasado.\nO al azar.\n\nPor ejemplo, un grupo de escenas que contiene las escenas ... \nEscena 1 \nEscena 2 \nEscena 3 \n ... activará la \"Escena 1 \" la primera vez que se seleccione como objetivo. \nLa segunda vez se activará \"Escena 2 \". \nLas veces restantes \"Escena 3 \" se activarán. \n\nHaz clic en el símbolo más resaltado a continuación para agregar un nuevo grupo de escenas."
AdvSceneSwitcher.sceneGroupTab.scenes.help="Selecciona el grupo de escenas que deseas modificar a la izquierda. \n\nSelecciona una escena para agregar a este grupo de escenas seleccionando la escena de arriba y haciendo clic en el símbolo más a continuación. \n\nSe puede agregar una escena varias veces al mismo grupo de escenas."
; Scene Trigger Tab
AdvSceneSwitcher.sceneTriggerTab.title="Activadores de escena"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--selecciona el activador--"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="esté activo"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="no esté activo"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="cambie a otra escena"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--Selecciona la acción--"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="empezar a grabar"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="pausar la grabación"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="reanudar grabación"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="detener grabación"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="detener transmisión"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="iniciar transmisión"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="iniciar búfer de repetición"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="detener búfer de repetición"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="silenciar fuente"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="dejar de silenciar fuente"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="iniciar el selector de escenas"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="detener el selector de escenas"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="Iniciar Camara Virtual"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="Detener Camara Virtual"
AdvSceneSwitcher.sceneTriggerTab.entry="Cuando {{scenes}} {{triggers}} {{actions}} {{audioSources}} después de {{duration}}"
AdvSceneSwitcher.sceneTriggerTab.help="Esta pestaña te permite activar acciones sobre cambios de escena, como detener la grabación o la transmisión."
; Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Iniciar Advanced Scene Switcher"
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Detener Advanced Scene Switcher"
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="Alternar inicio / detención para Advanced Scene Switcher"
AdvSceneSwitcher.hotkey.macro.pause="Pausar macro %1"
AdvSceneSwitcher.hotkey.macro.unpause="Despausar macro %1"
AdvSceneSwitcher.hotkey.macro.togglePause="Alternar pausa de macro %1"
AdvSceneSwitcher.hotkey.upMacroSegmentHotkey="Mover selección de segmento de macro hacia arriba"
AdvSceneSwitcher.hotkey.downMacroSegmentHotkey="Mover selección de segmento de macro hacia abajo"
AdvSceneSwitcher.hotkey.removeMacroSegmentHotkey="Eliminar segmento de macro seleccionado"
AdvSceneSwitcher.askBackup="Se detectó una nueva versión de Advanced Scene Switcher.\n¿Crear una copia de seguridad de la configuración anterior?"
AdvSceneSwitcher.askForMacro="Select macro {{macroSelection}}"
AdvSceneSwitcher.close="Cerrar"
AdvSceneSwitcher.browse="Explorar"
AdvSceneSwitcher.selectScene="--seleccionar escena--"
AdvSceneSwitcher.selectPreviousScene="Escena anterior"
AdvSceneSwitcher.selectCurrentScene="Escena actual"
AdvSceneSwitcher.selectAnyScene="Cualquier escena"
AdvSceneSwitcher.currentTransition="Transición actual"
AdvSceneSwitcher.anyTransition="Cualquier transición"
AdvSceneSwitcher.selectTransition="--seleccionar transición--"
AdvSceneSwitcher.selectWindow="--seleccionar ventana--"
AdvSceneSwitcher.selectSource="--seleccionar fuente--"
AdvSceneSwitcher.selectAudioSource="--seleccione la fuente de audio--"
AdvSceneSwitcher.selectVideoSource="--seleccione la fuente de video--"
AdvSceneSwitcher.OBSVideoOutput="Salida de vídeo OBS"
AdvSceneSwitcher.selectMediaSource="--seleccione la fuente de medios--"
AdvSceneSwitcher.selectProcess="--seleccionar proceso--"
AdvSceneSwitcher.selectFilter="--seleccionar filtro--"
AdvSceneSwitcher.selectMacro="--seleccionar macro--"
AdvSceneSwitcher.selectItem="--seleccionar elemento--"
AdvSceneSwitcher.selectProfile="--seleccionar perfil--"
AdvSceneSwitcher.selectSceneCollection="--seleccionar colección de escenas--"
AdvSceneSwitcher.enterPath="--ingrese la ruta--"
AdvSceneSwitcher.enterText="--ingresar texto--"
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="las entradas no válidas no se guardarán"
AdvSceneSwitcher.selectWindowTip="Usa \"OBS \" para especificar la ventana de OBS\nUsa \"Cambiar de tarea \" para especificar ALT + TAB"
AdvSceneSwitcher.sceneItemSelection.all="Todos"
AdvSceneSwitcher.sceneItemSelection.any="Cualquiera"
AdvSceneSwitcher.status.active="Activo"
AdvSceneSwitcher.status.inactive="Inactivo"
AdvSceneSwitcher.running="Iniciar complemento"
AdvSceneSwitcher.stopped="Complemento de detención"
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Esta parece ser la primera vez que se inicia el conmutador de escena avanzado.<br>Por favor, eche un vistazo a <a href=\"https:/ /github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> para obtener una lista de guías y ejemplos.<br>No dude en hacer preguntas en el complemento <a href=\"https://obsproject.com /forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">hilo</span></a> en los foros de OBS!</p></body></html>"
AdvSceneSwitcher.deprecatedTabWarning="¡Se detuvo el desarrollo de esta pestaña!\nConsidere cambiar a macros en su lugar.\nEsta sugerencia se puede desactivar en la pestaña General".
AdvSceneSwitcher.unit.milliseconds="milisegundos"
AdvSceneSwitcher.unit.secends="segundos"
AdvSceneSwitcher.unit.minutes="minutos"
AdvSceneSwitcher.unit.hours="horas"
AdvSceneSwitcher.duration.condition.none="Sin límite de tiempo"
AdvSceneSwitcher.duration.condition.more="Al menos durante"
AdvSceneSwitcher.duration.condition.equal="Para exactamente"
AdvSceneSwitcher.duration.condition.less="Para como máximo"
AdvSceneSwitcher.duration.condition.within="Dentro de los últimos"
;Traducido por: @EliasDipa

View File

@@ -24,7 +24,6 @@ AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Будет то
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Не переключаться"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Переключиться на любую сцену на вкладке Random"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Переключиться на:"
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="После совпадения не переключаться между сценами в течение"
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="В течение этого времени потенциальные совпадения будут игнорироваться!"
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Включить ведение подробного журнала"
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Сохранять положение и размер окна"
@@ -52,6 +51,10 @@ AdvSceneSwitcher.generalTab.priority.time="Время"
AdvSceneSwitcher.generalTab.priority.audio="Аудио"
AdvSceneSwitcher.generalTab.priority.video="Видео"
AdvSceneSwitcher.generalTab.priority.macro="Макрос"
AdvSceneSwitcher.generalTab.setTransitionBy="При изменении переходов:"
AdvSceneSwitcher.generalTab.transitionOverride="Установить переопределение переходов"
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="Изменить тип активного перехода"
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="Должна быть включена хотя бы одна опция:\n\n - Использовать переопределения переходов\n\n - Изменить тип активного перехода"
; Macro Tab
AdvSceneSwitcher.macroTab.title="Макрос"
@@ -78,24 +81,16 @@ AdvSceneSwitcher.logic.rootNone="Если"
AdvSceneSwitcher.logic.not="Если нет"
; Macro Conditions
AdvSceneSwitcher.condition.audio="Аудио"
AdvSceneSwitcher.ondition.audio.state.below="Ниже"
AdvSceneSwitcher.ondition.audio.state.above="Выше"
AdvSceneSwitcher.condition.audio.entry="Громкость {{audioSources}} равна {{condition}} {{volume}} в течении {{duration}} секунд"
AdvSceneSwitcher.condition.region="Область экрана"
AdvSceneSwitcher.condition.region.entry="Курсор находится в {{minX}} {{minY}} x {{maxX}} {{maxY}}"
AdvSceneSwitcher.condition.cursor="Область экрана"
AdvSceneSwitcher.condition.scene="Сцена"
AdvSceneSwitcher.condition.scene.type.current="Текущий"
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} сцена является {{scenes}} на {{duration}}"
AdvSceneSwitcher.condition.window="Окно"
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} существует и ..."
AdvSceneSwitcher.condition.window.entry.line2="... это {{fullscreen}} полноэкранный {{maximized}} максимизированный {{focused}} сфокусированный"
AdvSceneSwitcher.condition.file="Файл"
AdvSceneSwitcher.condition.file.entry.line1="Содержимое {{fileType}} {{filePath}} {{browseButton}} соответствует:"
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.condition.media="Медиа"
AdvSceneSwitcher.condition.media.entry="{{mediaSources}} состояние {{states}} и {{timeRestrictions}} {{time}}"
AdvSceneSwitcher.condition.video="Видео"
AdvSceneSwitcher.condition.video.condition.match="точно соответствует"
AdvSceneSwitcher.condition.video.condition.differ="не совпадает"
@@ -105,16 +100,13 @@ AdvSceneSwitcher.condition.video.condition.noImage="не имеет вывода
AdvSceneSwitcher.condition.video.askFileAction="Вы хотите использовать существующий файл или создать скриншот текущего выбранного источника?"
AdvSceneSwitcher.condition.video.askFileAction.file="Использовать существующий файл"
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Создать скриншот"
AdvSceneSwitcher.condition.video.entry="{{videoSources}} {{condition}} {{filePath}} {{browseButton}} для {{duration}}"
AdvSceneSwitcher.condition.stream="Потоковое вещание"
AdvSceneSwitcher.condition.stream.state.start="Поток запущен"
AdvSceneSwitcher.condition.stream.state.stop="Поток остановлен"
AdvSceneSwitcher.condition.stream.entry="{{streamState}} для {{duration}}"
AdvSceneSwitcher.condition.record="Запись"
AdvSceneSwitcher.condition.record.state.start="Запись запущена"
AdvSceneSwitcher.condition.record.state.pause="Запись приостановлена"
AdvSceneSwitcher.condition.record.state.stop="Запись остановлена"
AdvSceneSwitcher.condition.record.entry="{{recordState}} для {{duration}}"
AdvSceneSwitcher.condition.process="Процесс"
AdvSceneSwitcher.condition.process.entry="{{processes}} запущен {{focused}} и сфокусирован"
AdvSceneSwitcher.condition.idle="Простой"
@@ -136,14 +128,14 @@ AdvSceneSwitcher.action.audio.type.mute="Замьютить"
AdvSceneSwitcher.action.audio.type.unmute="Размьютить"
AdvSceneSwitcher.action.audio.type.sourceVolume="Установить громкость источника"
AdvSceneSwitcher.action.audio.type.masterVolume="Установить главную громкость"
AdvSceneSwitcher.action.audio.entry="{{actions}} {{audioSources}} {{volume}}"
AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.action.recording="Запись"
AdvSceneSwitcher.action.recording.type.stop="Остановить запись"
AdvSceneSwitcher.action.recording.type.start="Начать запись"
AdvSceneSwitcher.action.recording.type.pause="Пауза записи"
AdvSceneSwitcher.action.recording.type.unpause="Снять запись с паузы"
AdvSceneSwitcher.action.recording.pause.hint="Обратите внимание, что в зависимости от настроек записи вы можете не иметь возможности приостановить запись"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="Буфер воспроизведения"
AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения"
AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера"
@@ -154,15 +146,10 @@ AdvSceneSwitcher.action.streaming.type.stop="Остановить потоков
AdvSceneSwitcher.action.streaming.type.start="Начать потоковое вещание"
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="Запустить"
AdvSceneSwitcher.action.run.entry="Запустить {{filePath}} {{browseButton}}"
; Transition Tab
AdvSceneSwitcher.transitionTab.title="Переход"
AdvSceneSwitcher.transitionTab.setTransitionBy="При изменении переходов:"
AdvSceneSwitcher.transitionTab.transitionOverride="Установить переопределение переходов"
AdvSceneSwitcher.transitionTab.adjustActiveTransitionType="Изменить тип активного перехода"
AdvSceneSwitcher.transitionTab.transitionBehaviorSelectionError="Должна быть включена хотя бы одна опция:\n\n - Использовать переопределения переходов\n\n - Изменить тип активного перехода"
AdvSceneSwitcher.transitionTab.transitionForAToB="Использовать переход для автоматического переключения сцены со сцены A на сцену B"
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>Эти настройки <span style=\"font-style:italic;\">только</span> влияют на переходы, вызванные переключателем сцен - Проверьте <a href=\"https://obsproject.com/forum/resources/transition-table.1174/\"><span style=\" text-decoration: underline; color:#268bd2;\">Transition Table</span></a> если вы хотите настроить его для ручного изменения сцены.<br/>Настройки, определенные здесь, имеют приоритет над настройками перехода, сконфигурированными в других местах переключателя сцен.<br/><br/>Нажмите на символ плюса ниже, чтобы добавить новую запись.</p></body></html>"
AdvSceneSwitcher.transitionTab.defaultTransition="Изменить переход, если сцена активна"
@@ -222,7 +209,6 @@ AdvSceneSwitcher.mediaTab.states.Paused="Приостановлено"
AdvSceneSwitcher.mediaTab.states.stopped="Остановлено"
AdvSceneSwitcher.mediaTab.states.ended="Закончилось"
AdvSceneSwitcher.mediaTab.states.error="Ошибка"
AdvSceneSwitcher.mediaTab.states.playedToEnd="Воспроизведено до конца"
AdvSceneSwitcher.mediaTab.states.any="Любой"
AdvSceneSwitcher.mediaTab.timeRestriction.none="Нет"
AdvSceneSwitcher.mediaTab.timeRestriction.shorter="Время короче"
@@ -328,7 +314,6 @@ AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Эта вкладка по
; Network Tab
AdvSceneSwitcher.networkTab.title="Сеть"
AdvSceneSwitcher.networkTab.warning="Запуск сервера вне локальной сети позволит третьим лицам читать активную сцену."
AdvSceneSwitcher.networkTab.DisabledWarning="ту функциональность, к сожалению, пришлось отключить на macOS из-за несовместимости библиотек при параллельном запуске плагина obs-websocket."
AdvSceneSwitcher.networkTab.server="Запустить сервер (отправляет сообщения о переключении сцены всем подключенным клиентам)"
AdvSceneSwitcher.networkTab.server.port="Порт"
AdvSceneSwitcher.networkTab.server.lockToIPv4="Заблокировать сервер на использование только IPv4"

674
data/locale/tr-TR.ini Normal file
View File

@@ -0,0 +1,674 @@
AdvSceneSwitcher.pluginName="Gelismis Otomatik Sahne Degistirici"
AdvSceneSwitcher.windowTitle="Gelismis Otomatik Sahne Degistirici"
; General Tab
AdvSceneSwitcher.generalTab.title="Genel"
AdvSceneSwitcher.generalTab.status="Durum"
AdvSceneSwitcher.generalTab.status.hotkeytips="OBS ayarlarinda yapılandırılabilir Kısayol tusları"
AdvSceneSwitcher.generalTab.status.currentStatus="Gelismis Otomatik Sahne Degistirici:"
AdvSceneSwitcher.generalTab.status.onStartup="OBS'yi baslatirken:"
AdvSceneSwitcher.generalTab.status.onStartup.asLastRun="Etkinse, sahne değiştiriciyi etkinleştirin"
AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Her zaman sahne değiştiriciyi etkinleştirin"
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Sahne değiştiriciyi başlatma"
AdvSceneSwitcher.generalTab.status.start="Başlat"
AdvSceneSwitcher.generalTab.status.stop="Durdur"
AdvSceneSwitcher.generalTab.status.autoStart="Aşağıdaki durumlarda sahne değiştiriciyi otomatik olarak başlatın:"
AdvSceneSwitcher.generalTab.status.autoStart.never="Asla"
AdvSceneSwitcher.generalTab.status.autoStart.recording="Kayıt"
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Yayın"
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Kayıt veya Yayın"
AdvSceneSwitcher.generalTab.status.checkInterval="Anahtar koşullarını her seferinde kontrol edin"
AdvSceneSwitcher.generalTab.generalBehavior="Genel davranış"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="...için herhangi bir işlem yapılmazsa"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Yalnızca yapılandırılmış kontrol aralığı kadar doğru olacaktır."
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Geçiş Yapma"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Rastgele sekmesinde herhangi bir sahneye geçin"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Değiştirmek:"
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Bir eşleşmeden sonra aşağıdakiler için işlem yapmayın:"
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="Bu süre zarfında olası eşleşmeler göz ardı edilecektir!"
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ayrıntılı günlük kaydını etkinleştir"
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Pencere konumunu ve boyutunu kaydet"
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Sistem tepsisi bildirimlerini göster"
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="UI ipuçlarını devre dışı bırak"
AdvSceneSwitcher.generalTab.priority="Öncelik"
AdvSceneSwitcher.generalTab.priority.description="Geçiş yöntemleri önceliği (En yüksek öncelik en üsttedir)"
AdvSceneSwitcher.generalTab.priority.threadPriority="Konu önceliğini kullan"
AdvSceneSwitcher.generalTab.priority.threadPriorityNotice="(Önceliği \"Normal\" üzerine çıkarmak önerilmez)"
AdvSceneSwitcher.generalTab.saveOrLoadsettings="Kayıt / Yükle Ayarları"
AdvSceneSwitcher.generalTab.saveOrLoadsettings.export="Dışa Aktar"
AdvSceneSwitcher.generalTab.saveOrLoadsettings.import="İçe Aktar"
AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle="Gelişmiş Sahne Değiştirici ayarlarını dosyaya aktar ..."
AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle="Gelişmiş Sahne Değiştirici ayarlarını dosyadan içe aktar ..."
AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType="Text dosyası (*.txt)"
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadFail="Gelişmiş Sahne Değiştirici ayarları dosyadan içe aktarmakta başarısız oldu"
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadSuccess="Gelişmiş Sahne Değiştirici ayarları başarılı bir şekilde dosyadan içe aktarıldı"
AdvSceneSwitcher.generalTab.priority.fileContent="Dosya İçeriği"
AdvSceneSwitcher.generalTab.priority.sceneSequence="Sahne Sıralama"
AdvSceneSwitcher.generalTab.priority.idleDetection="Boşta Algılama"
AdvSceneSwitcher.generalTab.priority.executable="Yürütülebilir"
AdvSceneSwitcher.generalTab.priority.screenRegion="Ekran Alanı"
AdvSceneSwitcher.generalTab.priority.windowTitle="Pencere Başlığı"
AdvSceneSwitcher.generalTab.priority.media="Medya"
AdvSceneSwitcher.generalTab.priority.time="Zaman"
AdvSceneSwitcher.generalTab.priority.audio="Ses"
AdvSceneSwitcher.generalTab.priority.video="Video"
AdvSceneSwitcher.generalTab.priority.macro="Makro"
AdvSceneSwitcher.generalTab.setTransitionBy="Geçişleri değiştirirken:"
AdvSceneSwitcher.generalTab.transitionOverride="Geçiş geçersiz kılmaları ayarla"
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="Etkin geçiş türünü değiştir"
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="En az bir seçenek etkinleştirilmelidir: \n\n - Geçiş geçersiz kılmalarını kullan \n\n - Etkin geçiş türünü değiştir"
; Macro Tab
AdvSceneSwitcher.macroTab.title="Makro"
AdvSceneSwitcher.macroTab.macros="Makrolar"
AdvSceneSwitcher.macroTab.priorityWarning="Not: Makroları en yüksek öncelikli işlev olacak şekilde yapılandırmanız önerilir.\n Bu ayar, Genel sekmesinde değiştirilebilir."
AdvSceneSwitcher.macroTab.help="Makrolar, birden çok koşula bağlı olarak bir dizi eylemi yürütmenize izin verir.\n\n Yeni bir Makro eklemek için vurgulanan artı sembolüne tıklayın."
AdvSceneSwitcher.macroTab.editConditionHelp="Bu bölüm, Makro koşullarını tanımlamanızı sağlar.\n\n Sol taraftan mevcut bir Makro seçin veya yeni bir Makro ekleyin.\n Ardından yeni bir koşul eklemek için aşağıdaki artı düğmesini tıklayın."
AdvSceneSwitcher.macroTab.editActionHelp="Bu bölüm, Makro eylemlerini tanımlamanızı sağlar.\n\n Soldan mevcut bir Makro seçin veya yeni bir Makro ekleyin.\n Ardından yeni bir eylem eklemek için aşağıdaki artı düğmesini tıklayın."
AdvSceneSwitcher.macroTab.edit="Makro Düzenleme"
AdvSceneSwitcher.macroTab.edit.logic="Mantık türü:"
AdvSceneSwitcher.macroTab.edit.condition="Durum türü:"
AdvSceneSwitcher.macroTab.edit.action="Eylem türü:"
AdvSceneSwitcher.macroTab.add="Yeni Makro ekle"
AdvSceneSwitcher.macroTab.name="İsim:"
AdvSceneSwitcher.macroTab.run="Makro Çalıştırma"
AdvSceneSwitcher.macroTab.runFail="\"%1\" çalıştırılamadı!\n Eylemlerden biri başarısız oldu veya makro zaten çalışıyor."
AdvSceneSwitcher.macroTab.runInParallel="Makroyu diğer makrolara paralel olarak çalıştırın"
AdvSceneSwitcher.macroTab.onChange="Eylemleri yalnızca koşul değişikliğinde gerçekleştirin"
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
AdvSceneSwitcher.macroTab.exists="Macro adı zaten mevcut"
AdvSceneSwitcher.macroTab.copy="Kopya oluştur"
AdvSceneSwitcher.macroTab.expandAll="Hepsini Genişlet"
AdvSceneSwitcher.macroTab.collapseAll="Hepsini Küçült"
; Macro Logic
AdvSceneSwitcher.logic.none="Girişi yoksay"
AdvSceneSwitcher.logic.and="Ve"
AdvSceneSwitcher.logic.or="Ya da"
AdvSceneSwitcher.logic.andNot="ve değil"
AdvSceneSwitcher.logic.orNot="ya da değil"
AdvSceneSwitcher.logic.rootNone="Eğer"
AdvSceneSwitcher.logic.not="Eğer değilse"
; Macro Conditions
AdvSceneSwitcher.condition.audio="Ses"
AdvSceneSwitcher.condition.audio.state.below="altında"
AdvSceneSwitcher.condition.audio.state.above="üstünde"
AdvSceneSwitcher.condition.audio.state.mute="sessiz"
AdvSceneSwitcher.condition.audio.state.unmute="ses açıldı"
AdvSceneSwitcher.condition.cursor="İmleç"
AdvSceneSwitcher.condition.cursor.type.region="alanında"
AdvSceneSwitcher.condition.cursor.type.moving="hareketlidir"
AdvSceneSwitcher.condition.cursor.showFrame="Çerçeveyi Göster"
AdvSceneSwitcher.condition.cursor.hideFrame="Çerçeveyi Gizle"
AdvSceneSwitcher.condition.cursor.entry.line1="İmleç {{conditions}}{{buttons}}{{minX}}{{minY}}{{maxX}}{{maxY}}{{toggleFrameButton}}"
AdvSceneSwitcher.condition.cursor.entry.line2="İmleç şuanda {{xPos}} x {{yPos}}"
AdvSceneSwitcher.condition.scene="Sahne"
AdvSceneSwitcher.condition.scene.type.current="Mevcut Sahne"
AdvSceneSwitcher.condition.scene.type.previous="Önceki Sahne"
AdvSceneSwitcher.condition.scene.type.changed="Sahne değişti"
AdvSceneSwitcher.condition.scene.type.notChanged="Sahne değişmedi"
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Geçiş hedefi sahnesi için geçiş kontrolü sırasında"
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
AdvSceneSwitcher.condition.window="Pencere"
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} Varolan ve ..."
AdvSceneSwitcher.condition.window.entry.line2="... {{fullscreen}} Tam ekran {{maximized}} büyütüldü {{focused}} odaklanıldı {{windowFocusChanged}} ön plan penceresi değişikliği"
AdvSceneSwitcher.condition.file="Dosya"
AdvSceneSwitcher.condition.file.entry.line1="İçerik{{fileType}}{{filePath}}{{conditions}}"
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.condition.media="Medya"
AdvSceneSwitcher.condition.media.anyOnScene="Herhangi bir medya kaynağı"
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.video="Video"
AdvSceneSwitcher.condition.video.condition.match="Tam olarak eşleşir"
AdvSceneSwitcher.condition.video.condition.differ="Eşleştirme"
AdvSceneSwitcher.condition.video.condition.hasChanged="Değişti"
AdvSceneSwitcher.condition.video.condition.hasNotChanged="Değişmedi"
AdvSceneSwitcher.condition.video.condition.noImage=ıktı yok"
AdvSceneSwitcher.condition.video.condition.pattern="Modelle eşleşir."
AdvSceneSwitcher.condition.video.condition.object="nesne içerir"
AdvSceneSwitcher.condition.video.askFileAction="Mevcut bir dosyayı kullanmak mı yoksa seçili olan kaynağın ekran görüntüsünü mü oluşturmak istiyorsunuz?"
AdvSceneSwitcher.condition.video.askFileAction.file="Mevcut dosyayı kullan"
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Ekran görüntüsü oluştur"
AdvSceneSwitcher.condition.video.usePatternForChangedCheck="Model eşleştirmeyi kullan"
AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="Bu, koşulun doğru olması için görüntünün ne kadar değişmesi gerektiğini kontrol etmenizi sağlar."
AdvSceneSwitcher.condition.video.patternThreshold="Eşik: "
AdvSceneSwitcher.condition.video.patternThresholdDescription="Daha yüksek bir eşik değeri, modelin video kaynağıyla daha yakından eşleşmesi gerektiği anlamına gelir."
AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="Desen için maske olarak alfa kanalını kullanın."
AdvSceneSwitcher.condition.video.objectScaleThreshold="Ölçek faktörü: "
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="Daha düşük bir ölçek faktörü, daha fazla eşleşmeye, ancak daha yüksek CPU yüküne yol açacaktır."
AdvSceneSwitcher.condition.video.minNeighborDescription="Daha yüksek bir minimum komşu değeri, daha az ancak daha kaliteli eşleşmelerle sonuçlanacaktır."
AdvSceneSwitcher.condition.video.showMatch="Eşleşmeyi Göster"
AdvSceneSwitcher.condition.video.screenshotFail="Kaynağın ekran görüntüsü alınamadı!"
AdvSceneSwitcher.condition.video.patternMatchFail="Desen bulunamadı!"
AdvSceneSwitcher.condition.video.objectMatchFail="Nesne bulunamadı!"
AdvSceneSwitcher.condition.video.modelLoadFail="Model verileri yüklenemedi!"
AdvSceneSwitcher.condition.video.entry="{{videoInputTypes}}{{sources}}{{scenes}}{{condition}}{{imagePath}}"
AdvSceneSwitcher.condition.video.entry.modelPath="Model verileri (haar kademeli sınıflandırıcı):{{modelDataPath}}"
AdvSceneSwitcher.condition.video.entry.minNeighbor="Minimum komşular: {{minNeighbors}}"
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}} Yalnızca her seferinde kontrol gerçekleştirerek CPU yükünü azaltın {{throttleCount}} millisaniyeler"
AdvSceneSwitcher.condition.stream="Yayınlama"
AdvSceneSwitcher.condition.stream.state.start="Yayın çalışıyor"
AdvSceneSwitcher.condition.stream.state.stop="Yayın durdu"
AdvSceneSwitcher.condition.stream.state.starting="Yayın başlıyor"
AdvSceneSwitcher.condition.stream.state.stopping="Yayın duruyor"
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
AdvSceneSwitcher.condition.record="Kayıt"
AdvSceneSwitcher.condition.record.state.start="Kayıt Çalışıyor"
AdvSceneSwitcher.condition.record.state.pause="Kayıt durakladı"
AdvSceneSwitcher.condition.record.state.stop="Kayıt durdu"
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
AdvSceneSwitcher.condition.process="İşlem"
AdvSceneSwitcher.condition.process.entry="{{processes}} çalışıyor {{focused}} ve odaklandı"
AdvSceneSwitcher.condition.idle="Boşta"
AdvSceneSwitcher.condition.idle.entry="...için klavye veya fare girişi yok {{duration}}"
AdvSceneSwitcher.condition.pluginState="Eklenti durumu"
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Bu aralıkta otomatik sahne değişikliği tetiklendi"
AdvSceneSwitcher.condition.pluginState.state.running="Gelişmiş sahne değiştirici çalışıyor"
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
AdvSceneSwitcher.condition.timer="Zamanlayıcı"
AdvSceneSwitcher.condition.timer.type.fixed="Sabit"
AdvSceneSwitcher.condition.timer.type.random="Rastgele"
AdvSceneSwitcher.condition.timer.pause="Duraklat"
AdvSceneSwitcher.condition.timer.continue="Devam etmek"
AdvSceneSwitcher.condition.timer.entry.line1.fixed="{{type}} süresi {{duration}} geçti"
AdvSceneSwitcher.condition.timer.entry.line1.random="{{type}} itibaren süre {{duration}} to {{duration2}} geçti"
AdvSceneSwitcher.condition.timer.entry.line2="Kalan Süre: {{remaining}} saniye"
AdvSceneSwitcher.condition.timer.entry.line3="{{pauseContinue}} {{reset}} {{saveRemaining}} Kalan zamanı kayıt {{autoReset}} Süreye ulaşıldıktan sonra zamanlayıcıyı otomatik olarak sıfırla"
AdvSceneSwitcher.condition.timer.reset="Sıfırlama"
AdvSceneSwitcher.condition.macro="Makro"
AdvSceneSwitcher.condition.macro.type.count="Saymak"
AdvSceneSwitcher.condition.macro.type.state="Belirtmek"
AdvSceneSwitcher.condition.macro.type.selection="Koşul türü: {{types}}"
AdvSceneSwitcher.condition.macro.count.type.below="Daha az"
AdvSceneSwitcher.condition.macro.count.type.above="Daha fazla"
AdvSceneSwitcher.condition.macro.count.type.equal="Aynen"
AdvSceneSwitcher.condition.macro.count.reset="Sıfırlama"
AdvSceneSwitcher.condition.macro.pausedWarning="Seçili makro şu anda duraklatıldı!"
AdvSceneSwitcher.condition.macro.state.entry="Koşulları {{macros}} doğru"
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} yürütüldü {{conditions}} {{count}} zaman"
AdvSceneSwitcher.condition.macro.count.entry.line2="Mevcut sayı: {{currentCount}} {{resetCount}}"
AdvSceneSwitcher.condition.source="Kaynak"
AdvSceneSwitcher.condition.source.type.active="Aktiftir"
AdvSceneSwitcher.condition.source.type.showing="gösteriyor"
AdvSceneSwitcher.condition.source.type.settings="Ayarlar eşleştirildi"
AdvSceneSwitcher.condition.source.getSettings="Mevcut ayarları al"
AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}"
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.source.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.virtualCamera="Sanal kamera"
AdvSceneSwitcher.condition.virtualCamera.state.start="Sanal kamera başladı"
AdvSceneSwitcher.condition.virtualCamera.state.stop="Sanal kamera durdu"
AdvSceneSwitcher.condition.virtualCamera.entry="{{states}}"
AdvSceneSwitcher.condition.filter="Filtrele"
AdvSceneSwitcher.condition.filter.type.active="Etkinleştirildi"
AdvSceneSwitcher.condition.filter.type.showing="Etkisizleştirildi"
AdvSceneSwitcher.condition.filter.type.settings="Ayarlar eşleşti"
AdvSceneSwitcher.condition.filter.getSettings="Mevcut ayarları al"
AdvSceneSwitcher.condition.filter.entry.line1="Açık {{sources}} {{filters}} {{conditions}}"
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.sceneOrder="Sahne öğesi sırası"
AdvSceneSwitcher.condition.sceneOrder.type.above="Üstünde"
AdvSceneSwitcher.condition.sceneOrder.type.below="Altında"
AdvSceneSwitcher.condition.sceneOrder.type.position="konumunda"
AdvSceneSwitcher.condition.sceneOrder.positionInfo="Konum değeri en altta 0 ile başlar ve sahne gruplarındakiler dahil her sahne öğesi için bir artar."
AdvSceneSwitcher.condition.sceneOrder.entry="Açık{{scenes}}{{sources}}{{conditions}}{{sources2}}{{position}}"
AdvSceneSwitcher.condition.hotkey="Kısayol tuşu"
AdvSceneSwitcher.condition.hotkey.name="Makro tetik kısayol tuşu"
AdvSceneSwitcher.condition.hotkey.tip="Not: Bu kısayol tuşu için tuş atamalarını OBS ayarları penceresinde yapılandırabilirsiniz."
AdvSceneSwitcher.condition.replay="Tekrar oynatma arabelleği"
AdvSceneSwitcher.condition.replay.state.stopped="Tekrar oynatma arabelleği durdu"
AdvSceneSwitcher.condition.replay.state.started="Tekrar oynatma arabelleği başladı"
AdvSceneSwitcher.condition.replay.state.saved="Tekrar oynatma arabelleği kaydedildi"
AdvSceneSwitcher.condition.replay.entry="{{state}}"
AdvSceneSwitcher.condition.date="Tarih"
AdvSceneSwitcher.condition.date.state.at="de"
AdvSceneSwitcher.condition.date.state.after="Sonra"
AdvSceneSwitcher.condition.date.state.before="Önce"
AdvSceneSwitcher.condition.date.state.between="Arasında"
AdvSceneSwitcher.condition.sceneTransform="Sahne öğesi dönüşümü"
AdvSceneSwitcher.condition.sceneTransform.getTransform="Dönüşümü al"
AdvSceneSwitcher.condition.sceneTransform.entry.line1="Açık{{scenes}}{{sources}} dönüşümle eşleşir"
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.transition="Geçiş"
AdvSceneSwitcher.condition.transition.type.current="Geçerli geçiş türü"
AdvSceneSwitcher.condition.transition.type.duration="Mevcut geçiş süresi"
AdvSceneSwitcher.condition.transition.type.started="Geçiş başladı"
AdvSceneSwitcher.condition.transition.type.ended="Geçiş sona erdi"
AdvSceneSwitcher.condition.transition.type.transitionSource="İtibaren geçiş"
AdvSceneSwitcher.condition.transition.type.transitionTarget="Geçiş "
AdvSceneSwitcher.condition.transition.durationSuffix="saniyesi"
AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{scenes}}{{duration}}{{durationSuffix}}"
AdvSceneSwitcher.condition.sceneVisibility="Sahne öğesi görünürlüğü"
AdvSceneSwitcher.condition.sceneVisibility.type.shown="Gösterilen"
AdvSceneSwitcher.condition.sceneVisibility.type.hidden="Gizli"
AdvSceneSwitcher.condition.sceneVisibility.entry="Açık {{scenes}}{{sources}}is{{conditions}}"
AdvSceneSwitcher.condition.studioMode="Stüdyo ingilizce"
AdvSceneSwitcher.condition.studioMode.state.active="Studyo modu Etkinleştirildi"
AdvSceneSwitcher.condition.studioMode.state.notActive="Studyo modu aktif değil"
AdvSceneSwitcher.condition.studioMode.state.previewScene="Önizleme sahnesi"
AdvSceneSwitcher.condition.studioMode.entry="{{conditions}}{{scenes}}"
AdvSceneSwitcher.condition.openvr="Aç VR"
AdvSceneSwitcher.condition.openvr.errorStatus="Aç VR hatası: "
AdvSceneSwitcher.condition.openvr.entry.line1="HMD içinde ..."
AdvSceneSwitcher.condition.openvr.entry.line2="{{controls}}"
AdvSceneSwitcher.condition.openvr.entry.line3="HMD mevcut {{xPos}} x {{yPos}} x {{zPos}}"
; Macro Actions
AdvSceneSwitcher.action.switchScene="Sahne Degistirici"
AdvSceneSwitcher.action.scene.entry="Sahneyi {{scenes}} kullanarak {{transitions}} süresi olan {{duration}} saniye"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Hedef sahneye geçiş tamamlanana kadar bekleyin"
AdvSceneSwitcher.action.wait="Bekle"
AdvSceneSwitcher.action.wait.type.fixed="sabit"
AdvSceneSwitcher.action.wait.type.random="rastgele"
AdvSceneSwitcher.action.wait.entry.fixed="Şunu bekle {{waitType}} süre {{duration}}"
AdvSceneSwitcher.action.wait.entry.random="Şunu bekle {{waitType}} bu aralıktan {{duration}} buna {{duration2}}"
AdvSceneSwitcher.action.audio="Ses"
AdvSceneSwitcher.action.audio.type.mute="Sessiz"
AdvSceneSwitcher.action.audio.type.unmute="Ses açmak"
AdvSceneSwitcher.action.audio.type.sourceVolume="Kaynak ses seviyesini ayarla"
AdvSceneSwitcher.action.audio.type.masterVolume="Ana ses seviyesini ayarla"
AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.action.recording="Kayıt"
AdvSceneSwitcher.action.recording.type.stop="Kayıt Durdur"
AdvSceneSwitcher.action.recording.type.start="Kayıt Başlat"
AdvSceneSwitcher.action.recording.type.pause="Kayıt Duraklat"
AdvSceneSwitcher.action.recording.type.unpause="Kayıt Duraklatma"
AdvSceneSwitcher.action.recording.pause.hint="Kayıt ayarlarınıza bağlı olarak kaydı duraklatamayabileceğinizi unutmayın."
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="Tekrar arabelleği"
AdvSceneSwitcher.action.replay.type.stop="Tekrar arabelleğini durdur"
AdvSceneSwitcher.action.replay.type.start="Tekrar arabelleğini başlat"
AdvSceneSwitcher.action.replay.type.save="Tekrar arabelleğini kaydet"
AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Yayın"
AdvSceneSwitcher.action.streaming.type.stop="Yayın durdur"
AdvSceneSwitcher.action.streaming.type.start="Yayın başlat"
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="Çalıştır"
AdvSceneSwitcher.action.run.arguments="Argümanlar:"
AdvSceneSwitcher.action.run.addArgument="Argüman ekle"
AdvSceneSwitcher.action.run.addArgumentDescription="Yeni Argüman ekle:"
AdvSceneSwitcher.action.run.entry="Çalıştır {{filePath}}"
AdvSceneSwitcher.action.sceneVisibility="Sahne öğesi görünürlüğü"
AdvSceneSwitcher.action.sceneVisibility.type.show="Göster"
AdvSceneSwitcher.action.sceneVisibility.type.hide="Gizle"
AdvSceneSwitcher.action.sceneVisibility.type.source="Kayıt"
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Herhangi"
AdvSceneSwitcher.action.sceneVisibility.entry="Açık{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
AdvSceneSwitcher.action.filter="Filtrele"
AdvSceneSwitcher.action.filter.type.enable="Etkin"
AdvSceneSwitcher.action.filter.type.disable="Etkisiz"
AdvSceneSwitcher.action.filter.type.settings="Ayarları yap"
AdvSceneSwitcher.action.filter.entry="Açık {{sources}} {{actions}} {{filters}}"
AdvSceneSwitcher.action.filter.getSettings="Mevcut ayarları al"
AdvSceneSwitcher.action.source="Kaynak"
AdvSceneSwitcher.action.source.type.enable="Etkin"
AdvSceneSwitcher.action.source.type.disable="Etkisiz"
AdvSceneSwitcher.action.source.type.settings="Ayarları yap"
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
AdvSceneSwitcher.action.source.warning="Uyarı: Kaynakların global olarak etkinleştirilmesi ve devre dışı bırakılması, OBS UI tarafından kontrol edilemez"
AdvSceneSwitcher.action.source.getSettings="Mevcut Ayarları yap"
AdvSceneSwitcher.action.media="Medya"
AdvSceneSwitcher.action.media.type.play="Oynat"
AdvSceneSwitcher.action.media.type.pause="Duraklat"
AdvSceneSwitcher.action.media.type.stop="Dur"
AdvSceneSwitcher.action.media.type.restart="Yeniden Başlat"
AdvSceneSwitcher.action.media.type.next="Sonraki"
AdvSceneSwitcher.action.media.type.previous="Önceki"
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
AdvSceneSwitcher.action.macro="Makro"
AdvSceneSwitcher.action.macro.type.pause="Duraklat"
AdvSceneSwitcher.action.macro.type.unpause="Duraklatma"
AdvSceneSwitcher.action.macro.type.resetCounter="Sayacı sıfırla"
AdvSceneSwitcher.action.macro.type.run="Çalıştır"
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
AdvSceneSwitcher.action.pluginState="Eklenti durumu"
AdvSceneSwitcher.action.pluginState.type.stop="Advanced Scene Switcher eklentisini durdurun"
AdvSceneSwitcher.action.pluginState.type.noMatch="Eşleşmeme davranışını değiştirin:"
AdvSceneSwitcher.action.pluginState.type.import="Ayarları şuradan içe aktar:"
AdvSceneSwitcher.action.pluginState.importWarning="Not: Ayarlar penceresi açılırken eylem göz ardı edilecektir."
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
AdvSceneSwitcher.action.virtualCamera="Sanal Kamera"
AdvSceneSwitcher.action.virtualCamera.type.stop="Sanal Kamerayı Durdur"
AdvSceneSwitcher.action.virtualCamera.type.start="Sanal Kamerayı Başlat"
AdvSceneSwitcher.action.virtualCamera.entry="{{actions}}"
AdvSceneSwitcher.action.hotkey="Kısayol tuşu"
AdvSceneSwitcher.action.hotkey.leftShift="Sol shift"
AdvSceneSwitcher.action.hotkey.rightShift="Sağ Shift"
AdvSceneSwitcher.action.hotkey.leftCtrl="Sol Ctrl"
AdvSceneSwitcher.action.hotkey.rightCtrl="Sağ Ctrl"
AdvSceneSwitcher.action.hotkey.leftAlt="Sol Alt"
AdvSceneSwitcher.action.hotkey.rightAlt="Sağ Alt"
AdvSceneSwitcher.action.hotkey.leftMeta="Sol Meta"
AdvSceneSwitcher.action.hotkey.rightMeta="Sağ Meta"
AdvSceneSwitcher.action.hotkey.onlyOBS="Tuşa basımı yalnızca OBS'ye gönder"
AdvSceneSwitcher.action.hotkey.disabled="Tuşa basma simülasyonu yapılamıyor - işlevsellik devre dışı!"
AdvSceneSwitcher.action.hotkey.entry="Bas {{keys}} uygun {{duration}}"
AdvSceneSwitcher.action.sceneOrder="Sahne öğesi sırası"
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Yukarı taşı"
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Aşağı indir"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="En üste taşı"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Aşağıya taşı"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Konuma taşı"
AdvSceneSwitcher.action.sceneOrder.entry="Açık{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Sahne öğesi dönüşümü"
AdvSceneSwitcher.action.sceneTransform.getTransform="Dönüşümü al"
AdvSceneSwitcher.action.sceneTransform.entry="Açık{{scenes}}transform{{sources}}"
AdvSceneSwitcher.action.file="Dosya"
AdvSceneSwitcher.action.file.type.write="Yaz"
AdvSceneSwitcher.action.file.type.append="Ekle"
AdvSceneSwitcher.action.file.entry="{{actions}} {{filePath}}:"
AdvSceneSwitcher.action.transition="Geçiş"
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Geçiş türünü ayarla {{transitions}}"
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Geçiş süresini şuna ayarla: {{duration}}saniyeler"
AdvSceneSwitcher.action.timer="Zamanlayıcı"
AdvSceneSwitcher.action.timer.type.pause="Duraklat"
AdvSceneSwitcher.action.timer.type.continue="Devam et"
AdvSceneSwitcher.action.timer.type.reset="Sıfırla"
AdvSceneSwitcher.action.timer.type.setTimeRemaining="Kalan süreyi ayarla"
AdvSceneSwitcher.action.timer.entry="{{timerAction}} zamanlayıcılar açık {{macros}} {{duration}}"
AdvSceneSwitcher.action.random="Rastgele"
AdvSceneSwitcher.action.random.entry="Aşağıdaki makrolardan herhangi birini rastgele çalıştırın (duraklatılmış makrolar yoksayılır)"
AdvSceneSwitcher.action.systray="Sistem tepsisi bildirimi"
AdvSceneSwitcher.action.systray.entry="Bildirimleri göster: {{message}}"
AdvSceneSwitcher.action.screenshot="Ekran görüntüsü"
AdvSceneSwitcher.action.screenshot.mainOutput="OBS'nin ana çıkışı"
AdvSceneSwitcher.action.profile="Profil"
AdvSceneSwitcher.action.profile.entry="Aktif profili şununla değiştir: {{profiles}}"
AdvSceneSwitcher.action.sceneCollection="Sahne koleksiyonu"
AdvSceneSwitcher.action.sceneCollection.entry="Aktif sahne koleksiyonunu şu şekilde değiştir: {{sceneCollections}}"
AdvSceneSwitcher.action.sceneCollection.warning="Not: Değişen sahne koleksiyonu sahne değiştirici ayarlarını da yeniden yükleyeceğinden, bundan sonraki eylemler yürütülmeyecektir.\n Ayarlar penceresi açılırken sahne toplama eylemi yok sayılacaktır."
; Transition Tab
AdvSceneSwitcher.transitionTab.title="Geçiş"
AdvSceneSwitcher.transitionTab.transitionForAToB="Sahne A'dan sahne B'ye otomatik sahne geçişi için geçişi kullanın"
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>Bu ayarlar <span style=\"font-style:italic;\">yalnızca</span>, sahne değiştiricinin neden olduğu geçişleri etkiler - <a href=\ Göz atın "https://obsproject.com/forum/resources/transition-table.1174/\"><span style=\" text-decoration: underline; color:#268bd2;\">Geçiş Tablosu</span></ a> bunu manuel sahne değişiklikleri için yapılandırmak istiyorsanız.<br/>Burada tanımlanan ayarlar, sahne değiştiricide başka bir yerde yapılandırılmış geçiş ayarlarına göre önceliklidir.<br/><br/>Yeni bir giriş eklemek için aşağıdaki artı simgesini tıklayın. .</p></body></html>"
AdvSceneSwitcher.transitionTab.defaultTransition="Sahne aktifse geçişi değiştir"
AdvSceneSwitcher.transitionTab.entry="Şuradan geçiş yap {{scenes}} buna {{scenes2}} kullanarak {{transitions}} süresinde {{duration}}"
AdvSceneSwitcher.transitionTab.defaultTransitionEntry="Ne zaman sahne {{scenes}} aktifse, varsayılan sahne geçişini değiştir{{transitions}}"
AdvSceneSwitcher.transitionTab.defaultTransitionsHelp="Bir giriş eklemek için artı sembolüne tıklayın."
AdvSceneSwitcher.transitionTab.defaultTransition.delay="Geçişi değiştirmek {{defTransitionDelay}} sahne değişikliğinden sonra."
AdvSceneSwitcher.transitionTab.defaultTransition.delay.help="Gecikme, bir geçiş devam ederken geçiş türü değiştirilirse meydana gelebilecek iptal edilen sahne geçişlerini önlemek için kullanılır."
; Pause Scenes Tab
AdvSceneSwitcher.pauseTab.title="Duraklat"
AdvSceneSwitcher.pauseTab.pauseOnScene="Sahne Değiştiriciyi sahnede duraklatın"
AdvSceneSwitcher.pauseTab.pauseInFocus1="Sahne Değiştiriciyi duraklat şu durumda: "
AdvSceneSwitcher.pauseTab.pauseInFocus2="odakta"
AdvSceneSwitcher.pauseTab.pauseTypeScene="sahne aktif"
AdvSceneSwitcher.pauseTab.pauseTypeWindow="pencere odakta"
AdvSceneSwitcher.pauseTab.pauseTargetAll="tümü"
AdvSceneSwitcher.pauseTab.pauseEntry="Duraklat {{pauseTargets}} kontrol edildiğinde {{pauseTypes}} {{scenes}} {{windows}}"
AdvSceneSwitcher.pauseTab.help="Bu sekmede, bir sahne etkinse veya pencere odaktaysa bireysel geçiş yöntemlerini duraklatmak için yapılandırabilirsiniz.\ve Devam etmek için vurgulanan artı sembolüne tıklayın."
; Window Title Tab
AdvSceneSwitcher.windowTitleTab.title="Başlık"
AdvSceneSwitcher.windowTitleTab.regexrDescription="<html><head/><body><p>Doğrudan pencere başlıklarını veya geçerli normal ifadeyi girin. <a href=\"https://regexr.com\"><span style=\" text-decoration: underline; color:#268bd2;\">RegExr</span'i kullanarak normal ifadeler için söz dizimini ve eşleşmeleri kontrol edebilirsiniz. ></a></p></body></html>"
AdvSceneSwitcher.windowTitleTab.stayInFocus1="Bu pencere adını yoksay"
AdvSceneSwitcher.windowTitleTab.stayInFocus2=" "
AdvSceneSwitcher.windowTitleTab.fullscreen="tam ekran ise"
AdvSceneSwitcher.windowTitleTab.maximized="maksimize edilirse"
AdvSceneSwitcher.windowTitleTab.focused="eğer odaklanmışsa"
AdvSceneSwitcher.windowTitleTab.entry="{{windows}} {{scenes}} {{transitions}} {{fullscreen}} {{maximized}} {{focused}}"
AdvSceneSwitcher.windowTitleTab.windowsHelp="Çalışan uygulamaların pencere başlığına göre sahneler arasında geçiş yapın.\nAşağıdaki ek koşullar seçilebilir:\nPencere Tam Ekrandır\nPencere büyütülür\nPencere odaklanılır\n\nDevam etmek için vurgulanan artı sembolüne tıklayın."
AdvSceneSwitcher.windowTitleTab.ignoreWindowsHelp="Bir pencere başlığı yoksayılırsa, sahne değiştirici, önceden seçilen pencere hala odaktaymış gibi davranacaktır.\nBu, sık sık farklı bir pencereye geçerseniz, sahne değişikliğini tetiklemeyecek olan sahne geçişlerinden kaçınmanıza olanak tanır.\ n\nBir pencere seçin veya yukarıya bir pencere başlığı girin ve listeye eklemek için aşağıdaki artı sembolüne tıklayın."
; Executable Tab
AdvSceneSwitcher.executableTab.title="yürütülebilir"
AdvSceneSwitcher.executableTab.implemented="dasOven tarafından uygulandı"
AdvSceneSwitcher.executableTab.requiresFocus="sadece odaklanmışsa"
AdvSceneSwitcher.executableTab.entry="Bu {{processes}} çalışıyorsa değiştir {{scenes}} kullanılır {{transitions}} {{requiresFocus}}"
AdvSceneSwitcher.executableTab.help="Bu sekme, bir işlem çalışıyorsa sahneleri otomatik olarak değiştirmenize olanak tanır.\nBu, pencere adının değişebileceği veya bilinmediği durumlarda faydalı olabilir.\n\nDevam etmek için vurgulanan artı sembolüne tıklayın."
; Screen Region Tab
AdvSceneSwitcher.screenRegionTab.title="Bölge"
AdvSceneSwitcher.screenRegionTab.currentPosition="İmleç şu anda şu konumda:"
AdvSceneSwitcher.screenRegionTab.showGuideFrames="Kılavuz çerçeveleri göster"
AdvSceneSwitcher.screenRegionTab.hideGuideFrames="Kılavuz çerçeveleri gizle"
AdvSceneSwitcher.screenRegionTab.excludeScenes.None="Seçim yok"
AdvSceneSwitcher.screenRegionTab.entry="Eğer imleç şuanda böyleyse {{minX}} {{minY}} x {{maxX}} {{maxY}} şuna çevir {{scenes}} kullanarak {{transitions}} sürece {{excludeScenes}}"
AdvSceneSwitcher.screenRegionTab.help="Bu sekme, fare imlecinizin geçerli konumuna göre sahneleri otomatik olarak değiştirmenize olanak tanır.\n\nDevam etmek için vurgulanan artı sembolüne tıklayın."
; Media Tab
AdvSceneSwitcher.mediaTab.title="Medya"
AdvSceneSwitcher.mediaTab.implemented="Exelero tarafından uygulandı"
AdvSceneSwitcher.mediaTab.states.none="Yok"
AdvSceneSwitcher.mediaTab.states.playing="Oynamak"
AdvSceneSwitcher.mediaTab.states.opening="Açmak"
AdvSceneSwitcher.mediaTab.states.buffering="Arabelleğe alma"
AdvSceneSwitcher.mediaTab.states.Paused="Duraklatıldı"
AdvSceneSwitcher.mediaTab.states.stopped="Durduruldu"
AdvSceneSwitcher.mediaTab.states.ended="Bitti"
AdvSceneSwitcher.mediaTab.states.error="Hata"
AdvSceneSwitcher.mediaTab.states.any="Herhangi"
AdvSceneSwitcher.mediaTab.timeRestriction.none="Yok"
AdvSceneSwitcher.mediaTab.timeRestriction.shorter="Zaman daha kısa"
AdvSceneSwitcher.mediaTab.timeRestriction.longer="Zaman daha uzun"
AdvSceneSwitcher.mediaTab.timeRestriction.remainShorter="Kalan süre daha kısa"
AdvSceneSwitcher.mediaTab.timeRestriction.remainLonger="Kalan süre daha uzun"
AdvSceneSwitcher.mediaTab.entry="Kaynak {{mediaSources}} durumu {{states}} ve {{timeRestrictions}} {{time}} şuna çevir {{scenes}} kullanarak {{transitions}}"
AdvSceneSwitcher.mediaTab.help="Bu sekme, medya kaynaklarının durumuna göre sahneler arasında geçiş yapmanızı sağlar.\nÖrneğin, seçilen medya kaynaklı oynatmayı bitirdiğinde otomatik olarak önceki sahneye dönebilirsiniz.\n\nDevam etmek için vurgulanan artı sembolüne tıklayın."
; File Tab
AdvSceneSwitcher.fileTab.title="Dosya"
AdvSceneSwitcher.fileTab.readWriteSceneFile="Oku / Sahneden yazdır / Dosyaya"
AdvSceneSwitcher.fileTab.currentSceneOutputFile="Mevcut sahnenin adını bu dosyaya yazın:"
AdvSceneSwitcher.fileTab.switchSceneBaseOnFile="Dosya girişine göre sahnelerin değiştirilmesini etkinleştirin"
AdvSceneSwitcher.fileTab.switchSceneNameInputFile="Bu dosyadan geçiş yapılacak sahne adını okuyun:"
AdvSceneSwitcher.fileTab.switchSceneBaseOnFileContent="Dosya içeriğine göre sahneyi değiştir"
AdvSceneSwitcher.fileTab.remoteFileWarning="Uzak seçeneğini seçerseniz, sahne değiştiricinin Genel sekmesinde belirtildiği gibi her x ms'de bir uzak konuma erişmeye çalışacağını lütfen unutmayın!"
AdvSceneSwitcher.fileTab.remoteFileWarning1="Sahne değiştiricinin her seferinde uzak konuma erişmeye çalışacağını unutmayın."
AdvSceneSwitcher.fileTab.remoteFileWarning2="ms"
AdvSceneSwitcher.fileTab.libcurlWarning="libcurl yüklenemedi! Uzak dosyalara erişim mümkün olmayacak!"
AdvSceneSwitcher.fileTab.selectWrite="Yazmak için bir dosya seçin..."
AdvSceneSwitcher.fileTab.selectRead="Okumak için bir dosya seçin..."
AdvSceneSwitcher.fileTab.textFileType="Text dosyası (*.txt)"
AdvSceneSwitcher.fileTab.anyFileType="Herhangi bir dosya türü (*.*)"
AdvSceneSwitcher.fileTab.remote="uzak dosya"
AdvSceneSwitcher.fileTab.local="yerel dosya"
AdvSceneSwitcher.fileTab.useRegExp="normal ifadeler kullan (desen eşleştirme)"
AdvSceneSwitcher.fileTab.checkfileContentTime="değişiklik tarihi değiştiyse"
AdvSceneSwitcher.fileTab.checkfileContent="İçerik değiştiyse"
AdvSceneSwitcher.fileTab.entry="Suna dönüştür {{scenes}} kullanıp {{transitions}} içerik şunlarla {{fileType}} {{filePath}} {{browseButton}} eşleşirse:"
AdvSceneSwitcher.fileTab.entry2="{{matchText}}"
AdvSceneSwitcher.fileTab.entry3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.fileTab.help="Bu sekme, uzak veya yerel dosyaların içeriğine göre sahneleri otomatik olarak değiştirmenize olanak tanır.\n\nDevam etmek için vurgulanan artı sembolüne tıklayın."
; Random Tab
AdvSceneSwitcher.randomTab.title="Rastgele"
AdvSceneSwitcher.randomTab.randomDisabledWarning="İşlevsellik devre dışı - Etkinleştirmek için Genel sekmesinde \"Herhangi bir geçiş koşulu karşılanmazsa Rastgele sekmesinde herhangi bir sahneye geç\"i seçin"
AdvSceneSwitcher.randomTab.entry="Herhangi bir geçiş koşulu karşılanmıyorsa, geçiş yapın {{scenes}} kullan {{transitions}} için {{delay}}"
AdvSceneSwitcher.randomTab.help="Sahne değiştirici, yapılandırılan süre için geçiş yapmak için bu sekmede rastgele bir giriş seçecektir.\nAynı girişin arka arkaya iki kez seçilmeyeceğini unutmayın.\n\nDevam etmek için vurgulanan artı sembolüne tıklayın."
; Time Tab
AdvSceneSwitcher.timeTab.title="Zaman"
AdvSceneSwitcher.timeTab.anyDay="Herhangi bir günde"
AdvSceneSwitcher.timeTab.mondays="Pazartesi günleri"
AdvSceneSwitcher.timeTab.tuesdays="Salı günleri"
AdvSceneSwitcher.timeTab.wednesdays="Çarşamba günleri"
AdvSceneSwitcher.timeTab.thursdays="Perşembe günleri"
AdvSceneSwitcher.timeTab.fridays="Cuma günleri"
AdvSceneSwitcher.timeTab.saturdays="Cumartesi günleri"
AdvSceneSwitcher.timeTab.sundays="Pazar günleri"
AdvSceneSwitcher.timeTab.afterstart="Akış/kayıt başladıktan sonra"
AdvSceneSwitcher.timeTab.afterstart.tip="Akışın / kaydın başlangıcına göre zaman kullanılacaktır"
AdvSceneSwitcher.timeTab.entry="{{triggers}} da/de {{time}} Değiştir {{scenes}} kullan {{transitions}}"
AdvSceneSwitcher.timeTab.help="Bu sekme, geçerli yerel saate göre otomatik olarak farklı bir sahneye geçmenizi sağlar.\n\nSahne değiştiricinin sahneleri yalnızca tam olarak belirttiğiniz saatte değiştireceğini unutmayın.\nGenel'de öncelik ayarlarını yapılandırdığınızdan emin olun. sekmesini beğeninize göre seçin, böylece daha yüksek önceliğe sahip diğer geçiş yöntemleri nedeniyle seçilen zaman noktası kaçırılmaz.\n\nDevam etmek için vurgulanan artı sembolüne tıklayın."
; Idle Tab
AdvSceneSwitcher.idleTab.title="Boşta"
AdvSceneSwitcher.idleTab.enable="Boşta Algılamayı Etkinleştir"
AdvSceneSwitcher.idleTab.idleswitch="Sonra {{duration}} klavye veya fare girişi olmadan sahneye geçiş {{scenes}} kullan {{transitions}}"
AdvSceneSwitcher.idleTab.dontSwitchIfFocus1="eğer geçiş yapmayın"
AdvSceneSwitcher.idleTab.dontSwitchIfFocus2="odakta"
; Scene Sequence Tab
AdvSceneSwitcher.sceneSequenceTab.title="Sıra"
AdvSceneSwitcher.sceneSequenceTab.description="Otomatik sahne geçişleri dizisi, sahne değiştiriciyi duraklatarak/durdurarak veya manuel olarak farklı bir sahneye geçerek iptal edilebilir."
AdvSceneSwitcher.sceneSequenceTab.save="Sahne dizilerini dosyaya kaydet"
AdvSceneSwitcher.sceneSequenceTab.load="Dosyadan sahne dizilerini yükle"
AdvSceneSwitcher.sceneSequenceTab.saveTitle="Sahne Sırasını dosyaya kaydet..."
AdvSceneSwitcher.sceneSequenceTab.loadTitle="Sahne Sırasını okumak için bir dosya seçin ..."
AdvSceneSwitcher.sceneSequenceTab.loadFail="Advanced Scene Switcher ayarları içe aktaramadı!"
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="Gelişmiş Sahne Değiştirici ayarları başarıyla içe aktarıldı!"
AdvSceneSwitcher.sceneSequenceTab.fileType="Text dosyaları (*.txt)"
AdvSceneSwitcher.sceneSequenceTab.interruptible="Kesilebilir"
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Diğer anahtarlama yöntemlerinin bu sahne dizisini kesmesine izin verilir"
AdvSceneSwitcher.sceneSequenceTab.entry=" {{startScenes}} aktif olduğunda değiştir {{scenes}} sonra {{delay}} kullan {{transitions}} {{interruptible}}"
AdvSceneSwitcher.sceneSequenceTab.extendEdit="Sırayı Uzat"
AdvSceneSwitcher.sceneSequenceTab.extendEntry="Sonra {{delay}} çevirmek {{scenes}} kullan {{transitions}}"
AdvSceneSwitcher.sceneSequenceTab.help="Bu sekme, bir sahne yapılandırılmış bir süre boyunca etkinse otomatik olarak farklı bir sahneye geçmenizi sağlar.\nÖrneğin, iki sahne arasında otomatik olarak ileri ve geri geçiş yapabilirsiniz.\n\nVurgulanan artı sembolüne tıklayarak devam et."
; Audio Tab
AdvSceneSwitcher.audioTab.title="Ses"
AdvSceneSwitcher.audioTab.condition.above="üstünde"
AdvSceneSwitcher.audioTab.condition.below="altında"
AdvSceneSwitcher.audioTab.ignoreInactiveSource="kaynak etkin olmadığı sürece"
AdvSceneSwitcher.audioTab.entry="Ses Hacmi{{audioSources}} durumu {{condition}} {{volumeWidget}} için {{duration}} saniye geçiş {{scenes}} kullanarak {{transitions}} {{ignoreInactiveSource}}"
AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="Birden çok giriş eşleşirse..."
AdvSceneSwitcher.audioTab.multiMatchfallback="... için {{duration}} saniye geçiş {{scenes}} kullan {{transitions}}"
AdvSceneSwitcher.audioTab.help="Bu sekme, kaynakların ses düzeyine göre sahneler arasında geçiş yapmanızı sağlar.\nÖrneğin, mikrofonunuzun ses düzeyi belirli bir eşiğe ulaşırsa otomatik olarak farklı bir sahneye geçebilirsiniz.\n\nDevam etmek için vurgulanan artı simgesini tıklayın."
; Video Tab
AdvSceneSwitcher.videoTab.title="Video"
AdvSceneSwitcher.videoTab.getScreenshot="Seçilen giriş için ekran görüntüsü al"
AdvSceneSwitcher.videoTab.getScreenshotHelp="Seçili olan girişin video kaynağının Ekran Görüntüsünü alın ve otomatik olarak hedef görüntü olarak ayarlayın"
AdvSceneSwitcher.videoTab.condition.match="tam olarak eşleşir"
AdvSceneSwitcher.videoTab.condition.match.tooltip="Tam eşleşme, hedef ve kaynak görüntünün aynı çözünürlükte olmasını gerektirir.\nAyrıca her bir pikselin eşleşmesi gerekir, bu nedenle sıkıştırma kullanan görüntü biçimlerinin (ör. .JPG) kullanılması önerilmez!"
AdvSceneSwitcher.videoTab.condition.differ="eşleşmiyor"
AdvSceneSwitcher.videoTab.condition.hasNotChanged="değişmedi"
AdvSceneSwitcher.videoTab.condition.hasChanged="değişti"
AdvSceneSwitcher.videoTab.ignoreInactiveSource="Kaynak etkin olmadığı sürece"
AdvSceneSwitcher.videoTab.entry="Zaman {{videoSources}} {{condition}} {{filePath}} {{browseButton}} için {{duration}} şuna dönüştür {{scenes}} kullan {{transitions}} {{ignoreInactiveSource}}"
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Bu sekme, seçilen kaynakların mevcut video çıkışına göre sahneler arasında geçiş yapmanızı sağlar.<br/><a href=\"https:// adresini kontrol ettiğinizden emin olun. obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> bu işlevin daha da iyi bir şekilde uygulanması için.<br/><br/> Devam etmek için vurgulanan artı simgesini tıklayın.</p></body></html>"
; Network Tab
AdvSceneSwitcher.networkTab.title="Ağ"
AdvSceneSwitcher.networkTab.description="Bu sekme, başka bir OBS örneğinin etkin sahnesini uzaktan kontrol etmenizi sağlar.\nSahne adlarının tüm OBS örneklerinde tam olarak eşleşmesi gerektiğini lütfen unutmayın."
AdvSceneSwitcher.networkTab.warning="Sunucuyu yerel bir ağın dışında çalıştırmak, üçüncü tarafların aktif sahneyi okumasına izin verecektir."
AdvSceneSwitcher.networkTab.server="Sunucuyu başlat (Bağlı tüm istemcilere sahne değiştirme mesajları gönderir)"
AdvSceneSwitcher.networkTab.server.port="Port"
AdvSceneSwitcher.networkTab.server.lockToIPv4="Sunucuyu yalnızca IPv4 kullanacak şekilde kilitleyin"
AdvSceneSwitcher.networkTab.server.sendSceneChange="Sahne değişiklikleri için mesaj gönder"
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Yalnızca otomatik sahne anahtarları için mesaj gönder"
AdvSceneSwitcher.networkTab.server.sendPreview="Stüdyo modunda çalışırken önizleme sahnesi değişikliği için mesajlar gönderin"
AdvSceneSwitcher.networkTab.startFailed.message="WebSockets sunucusu başlatılamadı, bunun nedeni şunlar olabilir:\n - %1 TCP bağlantı noktası şu anda bu sistemde başka bir yerde, muhtemelen başka bir uygulama tarafından kullanılıyor olabilir. WebSocket sunucu ayarlarında farklı bir TCP bağlantı noktası ayarlamayı deneyin veya bu bağlantı noktasını kullanabilecek herhangi bir uygulamayı durdurun.\n - Hata mesajı: %2"
AdvSceneSwitcher.networkTab.server.status.currentStatus="Şu anki durum"
AdvSceneSwitcher.networkTab.server.status.notRunning="Çalışmıyor"
AdvSceneSwitcher.networkTab.server.status.starting="Başlangıç"
AdvSceneSwitcher.networkTab.server.status.running="Çalışıyor"
AdvSceneSwitcher.networkTab.server.restart="Sunucuyu yeniden başlat"
AdvSceneSwitcher.networkTab.client="İstemciyi başlat (Sahne değiştirme mesajlarını alır)"
AdvSceneSwitcher.networkTab.client.address="Ana makine adı veya IP adresi"
AdvSceneSwitcher.networkTab.client.port="Port"
AdvSceneSwitcher.networkTab.client.status.currentStatus="Şu anki durum"
AdvSceneSwitcher.networkTab.client.status.disconnected="Bağlantı kesildi"
AdvSceneSwitcher.networkTab.client.status.connecting="Bağlanıyor"
AdvSceneSwitcher.networkTab.client.status.connected="Bağlandı"
AdvSceneSwitcher.networkTab.client.reconnect="Yeniden bağlanmaya zorla"
; Scene Group Tab
AdvSceneSwitcher.sceneGroupTab.title="Sahne Grubu"
AdvSceneSwitcher.sceneGroupTab.list="Sahne Grupları"
AdvSceneSwitcher.sceneGroupTab.edit="Sahne Gruplarını Düzenle"
AdvSceneSwitcher.sceneGroupTab.edit.name="İsim:"
AdvSceneSwitcher.sceneGroupTab.edit.type="Tip: {{type}}"
AdvSceneSwitcher.sceneGroupTab.type.count="Saymak"
AdvSceneSwitcher.sceneGroupTab.type.time="Zaman"
AdvSceneSwitcher.sceneGroupTab.type.random="Rastgele"
AdvSceneSwitcher.sceneGroupTab.edit.count="Sonra listedeki bir sonraki sahneye ilerleyin {{count}} karşılama"
AdvSceneSwitcher.sceneGroupTab.edit.time="Sonra listedeki bir sonraki sahneye ilerleyin {{time}} geçtiyse"
AdvSceneSwitcher.sceneGroupTab.edit.random="Listeden rastgele bir sonraki sahneyi seçin"
AdvSceneSwitcher.sceneGroupTab.edit.repeat="Sahne listesinin sonuna ulaşılırsa baştan başlayın"
AdvSceneSwitcher.sceneGroupTab.edit.addScene="Sahne ekle"
AdvSceneSwitcher.sceneGroupTab.add="Sahne Grubu Ekle"
AdvSceneSwitcher.sceneGroupTab.defaultname="Sahne Grubu %1"
AdvSceneSwitcher.sceneGroupTab.exists="Sahne Grubu veya Sahne adı zaten var"
AdvSceneSwitcher.sceneGroupTab.help="Sahne Grupları, normal bir sahne gibi bir hedef olarak seçilebilir.\n\nAdından da anlaşılacağı gibi, bir sahne grubu birden fazla sahneden oluşan bir koleksiyondur.\nSahne grubu, yapılandırılmış ayarlara bağlı olarak kendisine atanan sahneler listesinde ilerleyecektir. sağ tarafta bulunabilir.\n\nSahne grubunu listedeki bir sonraki sahneye geçecek şekilde yapılandırabilirsiniz:\nSahne grubu birkaç kez hedef olarak seçildikten sonra.\nBelirli bir süre sonra geçti.\nVeya rastgele.\n\nÖrneğin, sahneleri içeren bir sahne grubu ...\nSahne 1\nSahne 2\nSahne 3 \n... ilk seçildiğinde \"Sahne 1\"i etkinleştirecek bir hedef olarak.\nİkinci kez \"Sahne 2\"yi etkinleştirecek.\nKalan zamanlar \"Scene 3\" etkinleştirilecek.\n\nYeni bir sahne grubu eklemek için aşağıdaki vurgulanan artı sembolüne tıklayın."
AdvSceneSwitcher.sceneGroupTab.scenes.help="Soldan değiştirmek istediğiniz sahne grubunu seçin.\n\nYukarıdaki sahneyi seçip aşağıdaki artı simgesini tıklayarak bu sahne grubuna eklemek için bir sahne seçin.\n\nAynı sahneye birden fazla sahne eklenebilir grup."
; Scene Trigger Tab
AdvSceneSwitcher.sceneTriggerTab.title="Sahne Tetikleyicileri"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--tetikleyiciyi seçin--"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="aktif"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="aktif değil"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="uzaklaştı"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--eylemi seç--"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="Kayda başla"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="Kaydı duraklat"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="kaydı duraklatma"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="Kaydetmeyi bırak"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="Akışı durdur"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="Akışı başlat"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="Yeniden oynatma arabelleğini başlat"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="Tekrar arabelleğini durdur"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="Kaynağı sessize al"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="Kaynağı sesi aç"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="Sahne değiştiriciyi başlat"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="Sahne değiştiriciyi durdur"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="Sanal kamerayı başlat"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="Sanal kamerayı durdur"
AdvSceneSwitcher.sceneTriggerTab.entry="Şundan {{scenes}} {{triggers}} {{actions}} {{audioSources}} sonra {{duration}}"
AdvSceneSwitcher.sceneTriggerTab.help="Bu sekme, kaydı veya akışı durdurma gibi sahne değişikliklerinde eylemleri tetiklemenize olanak tanır."
; Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Advanced Scene Switcher'ı başlatın"
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Gelişmiş Sahne Değiştiriciyi Durdurun"
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="Gelişmiş Sahne Değiştirici için Başlat/Durdur arasında geçiş yapın"
AdvSceneSwitcher.hotkey.macro.pause="%1 makrosunu duraklat"
AdvSceneSwitcher.hotkey.macro.unpause="%1 makrosunu duraklatma"
AdvSceneSwitcher.hotkey.macro.togglePause="%1 makrosunun duraklatmasını aç/kapat"
AdvSceneSwitcher.askBackup="Advanced Scene Switcher'ın yeni bir sürümü algılandı.\nEski ayarların bir yedeği oluşturulsun mu?"
AdvSceneSwitcher.askForMacro="Makro seç {{macroSelection}}"
AdvSceneSwitcher.close="Kapat"
AdvSceneSwitcher.browse="Araştır"
AdvSceneSwitcher.selectScene="--sahne seç--"
AdvSceneSwitcher.selectPreviousScene="Önceki Sahne"
AdvSceneSwitcher.selectCurrentScene="Mevcut Sahne"
AdvSceneSwitcher.selectAnyScene="Herhangi bir Sahne"
AdvSceneSwitcher.currentTransition="Mevcut Geçiş"
AdvSceneSwitcher.anyTransition="Herhangi Bir Geçiş"
AdvSceneSwitcher.selectTransition="--geçişi seç--"
AdvSceneSwitcher.selectWindow="--pencereyi seç--"
AdvSceneSwitcher.selectSource="--kaynak Seç--"
AdvSceneSwitcher.selectAudioSource="--ses kaynağını seçin--"
AdvSceneSwitcher.selectVideoSource="--video kaynağını seçin--"
AdvSceneSwitcher.selectMediaSource="--medya kaynağını seçin--"
AdvSceneSwitcher.selectProcess="--işlemi seç--"
AdvSceneSwitcher.selectFilter="--filtre seç--"
AdvSceneSwitcher.selectMacro="--makroyu seçin--"
AdvSceneSwitcher.selectItem="--Öğeyi seçin--"
AdvSceneSwitcher.selectProfile="--profil seç--"
AdvSceneSwitcher.selectSceneCollection="--sahne koleksiyonunu seç--"
AdvSceneSwitcher.enterPath="--yolu girin--"
AdvSceneSwitcher.enterText="--metni girin--"
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="geçersiz girişler kaydedilmeyecek"
AdvSceneSwitcher.selectWindowTip="\"OBS\" OBS penceresini belirlemek için \nKullan \"Görev değiştirme\"için ALT + TAB"
AdvSceneSwitcher.sceneItemSelection.all="Hepsi"
AdvSceneSwitcher.sceneItemSelection.any="Herhangi"
AdvSceneSwitcher.status.active="Aktif"
AdvSceneSwitcher.status.inactive="İnaktif"
AdvSceneSwitcher.running="Eklenti çalışıyor"
AdvSceneSwitcher.stopped="Eklenti durdu"
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Gelişmiş Sahne Değiştirici ilk kez başlatılıyor gibi görünüyor.<br>Lütfen <a href=\"https://github.com/ adresine bir göz atın. WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> için kılavuzlar ve örnekler listesi.<br>Yapmayın. eklentinin <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:# sayfasında soru sormaktan çekinmeyin OBS forumlarında 268bd2;\">konu</span></a>!</p></body></html>"
AdvSceneSwitcher.unit.milliseconds="millisaniye"
AdvSceneSwitcher.unit.secends="saniye"
AdvSceneSwitcher.unit.minutes="dakika"
AdvSceneSwitcher.unit.hours="saat"
AdvSceneSwitcher.duration.condition.none="Zaman kısıtlaması yok"
AdvSceneSwitcher.duration.condition.more="En azından"
AdvSceneSwitcher.duration.condition.equal="Tam olarak"
AdvSceneSwitcher.duration.condition.less="En çoğu"

View File

@@ -12,18 +12,25 @@ AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="总是自动启动"
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="不要启动"
AdvSceneSwitcher.generalTab.status.start="启动"
AdvSceneSwitcher.generalTab.status.stop="停止"
AdvSceneSwitcher.generalTab.status.autoStart="在以下情况下自动启动场景切换程序:"
AdvSceneSwitcher.generalTab.status.autoStart.never="从不"
AdvSceneSwitcher.generalTab.status.autoStart.recording="录制"
AdvSceneSwitcher.generalTab.status.autoStart.streaming="推流"
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="录制和推流"
AdvSceneSwitcher.generalTab.status.checkInterval="检查切换条件时间间隔"
AdvSceneSwitcher.generalTab.generalBehavior="一般表现"
AdvSceneSwitcher.generalTab.generalBehavior="全局行为"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="如果不符合任何切换条件"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="时间精度最高只能达到配置的轮询间隔"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="不切换"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="切换到随机场景列表中任意随机场景"
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="切换到"
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="在此期间,可能的匹配项将被忽略!"
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="详细日志输出"
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="保存窗口位置和大小"
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="显示系统托盘通知"
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="禁用UI提示"
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="隐藏可通过宏操作的分组栏"
AdvSceneSwitcher.generalTab.matchBehavior="场景匹配设置"
AdvSceneSwitcher.generalTab.priority="优先级"
AdvSceneSwitcher.generalTab.priority.description="切换场景优先级 (最上方的项优先级最高)"
AdvSceneSwitcher.generalTab.priority.threadPriority="使用线程优先级"
@@ -45,22 +52,519 @@ AdvSceneSwitcher.generalTab.priority.windowTitle="窗口标题"
AdvSceneSwitcher.generalTab.priority.media="媒体"
AdvSceneSwitcher.generalTab.priority.time="时间"
AdvSceneSwitcher.generalTab.priority.audio="音频"
AdvSceneSwitcher.generalTab.priority.video="视频"
AdvSceneSwitcher.generalTab.priority.macro="宏"
AdvSceneSwitcher.generalTab.transition="转场特效"
AdvSceneSwitcher.generalTab.setTransitionBy="更改转场特效时:"
AdvSceneSwitcher.generalTab.transitionOverride="在场景切换器中设定的转场特效优先级高于场景设定的转场特效"
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="更改激活转场特效类型"
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="必须至少启用一个选项:\n\n - 使用转场特效替代\n\n - 改变激活的转场特效类型"
; Macro Tab
AdvSceneSwitcher.macroTab.title="宏"
AdvSceneSwitcher.macroTab.macros="宏文件"
AdvSceneSwitcher.macroTab.priorityWarning="注意:建议将宏配置为最高优先级的功能.\n可以在“常规”选项卡上更改此设置."
AdvSceneSwitcher.macroTab.help="宏允许您根据多种条件执行一系列操作。\n\n单击突出显示的加号可添加新宏."
AdvSceneSwitcher.macroTab.editConditionHelp="此部分允许您定义宏条件。\n\n在左侧选择现有宏或添加新宏。\n然后单击下面的加号按钮添加新条件。"
AdvSceneSwitcher.macroTab.editActionHelp="此部分允许您定义宏操作。\n\n在左侧选择现有宏或添加新宏。\n然后单击下面的加号按钮添加新操作."
AdvSceneSwitcher.macroTab.edit="编辑宏"
AdvSceneSwitcher.macroTab.edit.logic="逻辑类型:"
AdvSceneSwitcher.macroTab.edit.condition="条件类型:"
AdvSceneSwitcher.macroTab.edit.action="动作类型:"
AdvSceneSwitcher.macroTab.add="添加新宏"
AdvSceneSwitcher.macroTab.name="名称:"
AdvSceneSwitcher.macroTab.run="运行宏"
AdvSceneSwitcher.macroTab.runFail="运行 \"%1\" 失败!\n其中一个操作失败或者宏已在运行."
AdvSceneSwitcher.macroTab.runInParallel="与其他宏同时运行宏"
AdvSceneSwitcher.macroTab.onChange="仅在条件更改时执行操作"
AdvSceneSwitcher.macroTab.defaultname="宏 %1"
AdvSceneSwitcher.macroTab.exists="宏名称已存在"
AdvSceneSwitcher.macroTab.copy="创建副本"
AdvSceneSwitcher.macroTab.expandAll="全部展开"
AdvSceneSwitcher.macroTab.collapseAll="全部收回"
AdvSceneSwitcher.macroTab.maximize="最大化"
AdvSceneSwitcher.macroTab.minimize="最小化"
AdvSceneSwitcher.macroTab.highlightExecutedMacros="突出显示最近执行的宏"
AdvSceneSwitcher.macroTab.highlightTrueConditions="突出显示最近运算为 真 的当前选定宏的条件"
AdvSceneSwitcher.macroTab.highlightPerformedActions="突出显示当前选定宏的最近执行的操作"
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="使用快捷键控制新增宏的暂停状态"
AdvSceneSwitcher.macroTab.currentDisableHotkeys="使用快捷键控制所选宏的暂停状态"
; Macro List
AdvSceneSwitcher.macroList.deleted="删除"
AdvSceneSwitcher.macroList.duplicate="\"%1\" 已选择!"
; Macro Logic
AdvSceneSwitcher.logic.none="忽略条目"
AdvSceneSwitcher.logic.and="和"
AdvSceneSwitcher.logic.or="或"
AdvSceneSwitcher.logic.andNot="和 不"
AdvSceneSwitcher.logic.orNot="或 不"
AdvSceneSwitcher.logic.rootNone="如果"
AdvSceneSwitcher.logic.not="如果 不"
; Macro Conditions
AdvSceneSwitcher.condition.audio="音频"
AdvSceneSwitcher.condition.audio.state.below="少于"
AdvSceneSwitcher.condition.audio.state.exact="相等"
AdvSceneSwitcher.condition.audio.state.above="大于"
AdvSceneSwitcher.condition.audio.state.mute="静音"
AdvSceneSwitcher.condition.audio.state.unmute="取消静音"
AdvSceneSwitcher.condition.audio.type.output="输出音频"
AdvSceneSwitcher.condition.audio.type.volume="配置音量级别"
AdvSceneSwitcher.condition.audio.entry="{{checkType}} 的 {{audioSources}} 是 {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.condition.cursor="屏幕区域"
AdvSceneSwitcher.condition.cursor.type.region="当前位置"
AdvSceneSwitcher.condition.cursor.type.moving="正在移动"
AdvSceneSwitcher.condition.cursor.showFrame="显示帧率"
AdvSceneSwitcher.condition.cursor.hideFrame="隐藏帧率"
AdvSceneSwitcher.condition.cursor.entry.line1="鼠标 处于{{conditions}}{{buttons}}{{minX}}{{minY}}{{maxX}}{{maxY}}{{toggleFrameButton}}"
AdvSceneSwitcher.condition.cursor.entry.line2="鼠标当前位于 {{xPos}} x {{yPos}}"
AdvSceneSwitcher.condition.scene="场景"
AdvSceneSwitcher.condition.scene.type.current="当前场景是"
AdvSceneSwitcher.condition.scene.type.previous="上一个场景是"
AdvSceneSwitcher.condition.scene.type.changed="场景改变了"
AdvSceneSwitcher.condition.scene.type.notChanged="场景没有改变"
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="在转场过程中检查转场源场景"
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="在转场过程中检查转场源场景"
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
AdvSceneSwitcher.condition.window="窗口"
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} 存在..."
AdvSceneSwitcher.condition.window.entry.line2="... 并且是 {{fullscreen}} 全屏 {{maximized}} 最大化 {{focused}} 获得焦点 {{windowFocusChanged}} 焦点窗口已更改"
AdvSceneSwitcher.condition.window.entry.line3="当前焦点窗口: {{focusWindow}}"
AdvSceneSwitcher.condition.file="文件"
AdvSceneSwitcher.condition.file.type.match="内容完全匹配"
AdvSceneSwitcher.condition.file.type.contentChange="内容已更改"
AdvSceneSwitcher.condition.file.type.dateChange="修改日期已更改"
AdvSceneSwitcher.condition.file.entry.line1="文件内容来自{{fileType}}{{filePath}}{{conditions}}"
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.condition.media="媒体"
AdvSceneSwitcher.condition.media.anyOnScene="任何媒体来源"
AdvSceneSwitcher.condition.media.allOnScene="所有媒体来源"
AdvSceneSwitcher.condition.media.matchOnChange="仅在更改时匹配(注意:此选项将在未来版本中删除-请改用时间限制)"
AdvSceneSwitcher.condition.media.inconsistencyInfo="不幸的是并非所有媒体源类型的行为都相同例如媒体源与VLC视频源“停止”状态。\n所以请尝试适合您的设置"
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}的状态是{{states}}和{{timeRestrictions}}{{time}}"
AdvSceneSwitcher.condition.video="视频"
AdvSceneSwitcher.condition.video.condition.match="完全匹配"
AdvSceneSwitcher.condition.video.condition.differ="不匹配"
AdvSceneSwitcher.condition.video.condition.hasChanged="改变了"
AdvSceneSwitcher.condition.video.condition.hasNotChanged="没有改变"
AdvSceneSwitcher.condition.video.condition.noImage="没有输出"
AdvSceneSwitcher.condition.video.condition.pattern="匹配模式"
AdvSceneSwitcher.condition.video.condition.object="包含对象"
AdvSceneSwitcher.condition.video.condition.brightness="亮度"
AdvSceneSwitcher.condition.video.askFileAction="是否要使用现有文件或创建当前选定源的屏幕截图?"
AdvSceneSwitcher.condition.video.askFileAction.file="使用现有文件"
AdvSceneSwitcher.condition.video.askFileAction.screenshot="创建屏幕截图"
AdvSceneSwitcher.condition.video.reduceLatency="减少匹配延迟"
AdvSceneSwitcher.condition.video.reduceLatency.tooltip="启用将减少匹配延迟,但总体上会减慢所有宏的总体条件检查."
AdvSceneSwitcher.condition.video.usePatternForChangedCheck="使用模式匹配"
AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="这将允许您控制图像必须更改多少才能使条件为真."
AdvSceneSwitcher.condition.video.patternThreshold="阈值: "
AdvSceneSwitcher.condition.video.patternThresholdDescription="较高的阈值意味着模式需要更紧密地匹配视频源."
AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="使用alpha通道作为图案的遮罩."
AdvSceneSwitcher.condition.video.brightnessThreshold="平均亮度:"
AdvSceneSwitcher.condition.video.brightnessThresholdDescription="较高的值表示图像较亮,较低的值表示图像较暗。"
AdvSceneSwitcher.condition.video.currentBrightness="当前平均亮度: %1"
AdvSceneSwitcher.condition.video.objectScaleThreshold="模型比例: "
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="较低的模比例将导致更多的匹配但会导致更高的CPU负载."
AdvSceneSwitcher.condition.video.minNeighborDescription="较高的“最小区域”值将导致较少但质量较高的匹配."
AdvSceneSwitcher.condition.video.showMatch="显示模式"
AdvSceneSwitcher.condition.video.showMatch.loading="Checking for match"
AdvSceneSwitcher.condition.video.screenshotFail="无法获取源的屏幕截图!"
AdvSceneSwitcher.condition.video.screenshotEmpty="Screenshot is empty - Is the source visible?"
AdvSceneSwitcher.condition.video.patternMatchFail="没有找到模式!"
AdvSceneSwitcher.condition.video.patternMatchSuccess="Pattern is highlighted in red"
AdvSceneSwitcher.condition.video.objectMatchFail="找不到对象!"
AdvSceneSwitcher.condition.video.objectMatchSuccess="Object is highlighted in red"
AdvSceneSwitcher.condition.video.modelLoadFail="无法加载模型数据!"
AdvSceneSwitcher.condition.video.entry="{{videoInputTypes}}{{sources}}{{scenes}}{{condition}}{{imagePath}}"
AdvSceneSwitcher.condition.video.entry.modelPath="模型数据 (haar级联分类器): {{modelDataPath}}"
AdvSceneSwitcher.condition.video.entry.minNeighbor="最小区域: {{minNeighbors}}"
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}通过只执行每一次检查来减少CPU负载 {{throttleCount}} 毫秒"
AdvSceneSwitcher.condition.video.entry.checkAreaEnable="仅在区域内执行检查"
AdvSceneSwitcher.condition.video.entry.checkArea="{{checkAreaEnable}}{{checkArea}}{{selectArea}}"
AdvSceneSwitcher.condition.video.minSize="最小尺寸:"
AdvSceneSwitcher.condition.video.maxSize="最大尺寸:"
AdvSceneSwitcher.condition.video.selectArea="选择区域"
AdvSceneSwitcher.condition.video.selectArea.status="仅检查突出显示的区域"
AdvSceneSwitcher.condition.video.width="宽度"
AdvSceneSwitcher.condition.video.height="长度"
AdvSceneSwitcher.condition.stream="推流"
AdvSceneSwitcher.condition.stream.state.start="推流启动"
AdvSceneSwitcher.condition.stream.state.stop="推流停止"
AdvSceneSwitcher.condition.stream.state.starting="推流启动中"
AdvSceneSwitcher.condition.stream.state.stopping="推流停止中"
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
AdvSceneSwitcher.condition.record="录制"
AdvSceneSwitcher.condition.record.state.start="录制运行中"
AdvSceneSwitcher.condition.record.state.pause="录制暂停"
AdvSceneSwitcher.condition.record.state.stop="录制停止"
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
AdvSceneSwitcher.condition.process="进程"
AdvSceneSwitcher.condition.process.entry="{{processes}} 是正在运行 {{focused}} 而且是获得焦点"
AdvSceneSwitcher.condition.process.entry.focus="当前焦点进程: {{focusProcess}}"
AdvSceneSwitcher.condition.idle="闲置检测"
AdvSceneSwitcher.condition.idle.entry="没有键盘或鼠标输入{{duration}}"
AdvSceneSwitcher.condition.pluginState="插件状态"
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="在此时间间隔内触发了自动场景更改"
AdvSceneSwitcher.condition.pluginState.state.running="高级场景切换程序正在运行"
AdvSceneSwitcher.condition.pluginState.state.shutdown="OBS正在关闭"
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
AdvSceneSwitcher.condition.timer="计时器"
AdvSceneSwitcher.condition.timer.type.fixed="固定"
AdvSceneSwitcher.condition.timer.type.random="随机"
AdvSceneSwitcher.condition.timer.pause="暂停"
AdvSceneSwitcher.condition.timer.continue="继续"
AdvSceneSwitcher.condition.timer.entry.line1.fixed="{{type}} 持续时间 {{duration}} 后结束"
AdvSceneSwitcher.condition.timer.entry.line1.random="{{type}} 持续时间从 {{duration}} 到 {{duration2}} 后结束"
AdvSceneSwitcher.condition.timer.entry.line2="剩余时间: {{remaining}} 秒"
AdvSceneSwitcher.condition.timer.entry.line3="{{pauseContinue}} {{reset}} {{saveRemaining}} 保存剩余时间 {{autoReset}} 达到时间后自动重置计时器"
AdvSceneSwitcher.condition.timer.reset="重置"
AdvSceneSwitcher.condition.macro="宏"
AdvSceneSwitcher.condition.macro.type.count="计数"
AdvSceneSwitcher.condition.macro.type.state="状态"
AdvSceneSwitcher.condition.macro.type.multiState="多线宏状态"
AdvSceneSwitcher.condition.macro.type.selection="条件类型: {{types}}"
AdvSceneSwitcher.condition.macro.count.type.below="少于"
AdvSceneSwitcher.condition.macro.count.type.above="大于"
AdvSceneSwitcher.condition.macro.count.type.equal="等于"
AdvSceneSwitcher.condition.macro.state.type.below="少于"
AdvSceneSwitcher.condition.macro.state.type.above="大于"
AdvSceneSwitcher.condition.macro.state.type.equal="等于"
AdvSceneSwitcher.condition.macro.count.reset="重置"
AdvSceneSwitcher.condition.macro.pausedWarning="所选宏当前已暂停!"
AdvSceneSwitcher.condition.macro.state.entry="条件 {{macros}} 运行结果为真"
AdvSceneSwitcher.condition.macro.multistate.entry="条件 {{multiStateConditions}}{{multiStateCount}} 以下宏运行结果为真:"
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} 运行 {{conditions}} {{count}} 次(相对于下面计数匹配)"
AdvSceneSwitcher.condition.macro.count.entry.line2="当前计数: {{currentCount}} {{resetCount}}"
AdvSceneSwitcher.condition.source="来源"
AdvSceneSwitcher.condition.source.type.active="是激活状态"
AdvSceneSwitcher.condition.source.type.showing="是显示状态"
AdvSceneSwitcher.condition.source.type.settings="设置完全匹配"
AdvSceneSwitcher.condition.source.getSettings="获取当前设置"
AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}"
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.source.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.virtualCamera="虚拟摄像机"
AdvSceneSwitcher.condition.virtualCamera.state.start="虚拟摄像机启动"
AdvSceneSwitcher.condition.virtualCamera.state.stop="虚拟摄像机停止"
AdvSceneSwitcher.condition.virtualCamera.entry="{{states}}"
AdvSceneSwitcher.condition.filter="滤镜"
AdvSceneSwitcher.condition.filter.type.active="已启用"
AdvSceneSwitcher.condition.filter.type.showing="已关闭"
AdvSceneSwitcher.condition.filter.type.settings="设置完全匹配"
AdvSceneSwitcher.condition.filter.getSettings="获取当前设置"
AdvSceneSwitcher.condition.filter.entry.line1="在 {{sources}} {{filters}} {{conditions}}"
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.sceneOrder="场景项目顺序"
AdvSceneSwitcher.condition.sceneOrder.type.above="高于"
AdvSceneSwitcher.condition.sceneOrder.type.below="低于"
AdvSceneSwitcher.condition.sceneOrder.type.position="位置值排比"
AdvSceneSwitcher.condition.sceneOrder.positionInfo="位置值从底部以0开始对于每个场景项目包括场景组中的项目增加1自行测试按照上下往上排比数值。"
AdvSceneSwitcher.condition.sceneOrder.entry="在 {{scenes}} {{sources}} {{conditions}} {{sources2}} {{position}}"
AdvSceneSwitcher.condition.hotkey="热键"
AdvSceneSwitcher.condition.hotkey.name="宏触发热键"
AdvSceneSwitcher.condition.hotkey.tip="注意您可以在OBS设置窗口中为此热键配置按键绑定"
AdvSceneSwitcher.condition.hotkey.entry.line1="热键被按下"
AdvSceneSwitcher.condition.hotkey.entry.line2="名称: {{name}}"
AdvSceneSwitcher.condition.replay="回放缓存"
AdvSceneSwitcher.condition.replay.state.stopped="回放缓存已停止"
AdvSceneSwitcher.condition.replay.state.started="回放缓存已启动"
AdvSceneSwitcher.condition.replay.state.saved="已保存回放缓存"
AdvSceneSwitcher.condition.replay.entry="{{state}}"
AdvSceneSwitcher.condition.date="日期"
AdvSceneSwitcher.condition.date.anyDay="每一天"
AdvSceneSwitcher.condition.date.monday="周一"
AdvSceneSwitcher.condition.date.tuesday="周二"
AdvSceneSwitcher.condition.date.wednesday="周三"
AdvSceneSwitcher.condition.date.thursday="周四"
AdvSceneSwitcher.condition.date.friday="周五"
AdvSceneSwitcher.condition.date.saturday="周六"
AdvSceneSwitcher.condition.date.sunday="周日"
AdvSceneSwitcher.condition.date.state.at="现在"
AdvSceneSwitcher.condition.date.state.after="之后"
AdvSceneSwitcher.condition.date.state.before="之前"
AdvSceneSwitcher.condition.date.state.between="之间"
AdvSceneSwitcher.condition.date.separator="和"
AdvSceneSwitcher.condition.date.ignoreDate="如果未选中,日期组件将被忽略"
AdvSceneSwitcher.condition.date.ignoreTime="如果未选中,时间组件将被忽略"
AdvSceneSwitcher.condition.date.showAdvancedSettings="显示高级设置"
AdvSceneSwitcher.condition.date.showSimpleSettings="显示简单设置"
AdvSceneSwitcher.condition.date.entry.simple="在 {{dayOfWeek}} {{weekCondition}} {{ignoreWeekTime}}{{weekTime}}"
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} 在匹配到日期时间后,每隔 {{duration}} 重复一次"
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Next match at: %1"
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} On repeat update selected date to repeat date"
AdvSceneSwitcher.condition.sceneTransform="场景项目被改变"
AdvSceneSwitcher.condition.sceneTransform.getTransform="内容或者设置被改变了"
AdvSceneSwitcher.condition.sceneTransform.entry.line1="在 {{scenes}} {{sources}} 匹配变换"
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.transition="转场"
AdvSceneSwitcher.condition.transition.type.current="当前转场特效类型为"
AdvSceneSwitcher.condition.transition.type.duration="当前转场特效持续时间为"
AdvSceneSwitcher.condition.transition.type.started="转场特效开始"
AdvSceneSwitcher.condition.transition.type.ended="转场特效结束"
AdvSceneSwitcher.condition.transition.type.transitionSource="转场特效来自"
AdvSceneSwitcher.condition.transition.type.transitionTarget="转场特效到"
AdvSceneSwitcher.condition.transition.durationSuffix="秒"
AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{scenes}}{{duration}}{{durationSuffix}}"
AdvSceneSwitcher.condition.sceneVisibility="场景项目可见"
AdvSceneSwitcher.condition.sceneVisibility.type.shown="显示的"
AdvSceneSwitcher.condition.sceneVisibility.type.hidden="隐藏的"
AdvSceneSwitcher.condition.sceneVisibility.entry="在 {{scenes}} {{sources}} 是 {{conditions}} "
AdvSceneSwitcher.condition.studioMode="工作室模式"
AdvSceneSwitcher.condition.studioMode.state.active="工作室模式处于活动状态"
AdvSceneSwitcher.condition.studioMode.state.notActive="工作室模式未处于活动状态"
AdvSceneSwitcher.condition.studioMode.state.previewScene="预览场景是"
AdvSceneSwitcher.condition.studioMode.entry="{{conditions}}{{scenes}}"
AdvSceneSwitcher.condition.openvr="OpenVR"
AdvSceneSwitcher.condition.openvr.errorStatus="OpenVR 错误: "
AdvSceneSwitcher.condition.openvr.entry.line1="HMD在 ..."
AdvSceneSwitcher.condition.openvr.entry.line2="{{controls}}"
AdvSceneSwitcher.condition.openvr.entry.line3="HMD目前处于 {{xPos}} x {{yPos}} x {{zPos}}"
AdvSceneSwitcher.condition.stats="OBS统计数据"
AdvSceneSwitcher.condition.stats.type.fps="FPS"
AdvSceneSwitcher.condition.stats.type.CPUUsage="CPU使用率"
AdvSceneSwitcher.condition.stats.type.HDDSpaceAvailable="可用磁盘空间"
AdvSceneSwitcher.condition.stats.type.memoryUsage="内存使用"
AdvSceneSwitcher.condition.stats.type.averageTimeToRender="渲染帧的平均时间"
AdvSceneSwitcher.condition.stats.type.skippedFrames="由于编码延迟跳过的帧"
AdvSceneSwitcher.condition.stats.type.missedFrames="由于渲染延迟错过的帧"
AdvSceneSwitcher.condition.stats.type.droppedFrames.stream="串流丢弃的帧"
AdvSceneSwitcher.condition.stats.type.megabytesSent.stream="串流总数据输出"
AdvSceneSwitcher.condition.stats.type.bitrate.stream="串流比特率"
AdvSceneSwitcher.condition.stats.type.droppedFrames.recording="录制丢弃的帧"
AdvSceneSwitcher.condition.stats.type.megabytesSent.recording="录制总数据输出"
AdvSceneSwitcher.condition.stats.type.bitrate.recording="录制比特率"
AdvSceneSwitcher.condition.stats.condition.above="大于"
AdvSceneSwitcher.condition.stats.condition.equals="等于"
AdvSceneSwitcher.condition.stats.condition.below="少于"
AdvSceneSwitcher.condition.stats.dockHint="你可以打开“统计”窗口查看当前状态"
AdvSceneSwitcher.condition.stats.entry="{{stats}} is {{condition}} {{value}}"
AdvSceneSwitcher.condition.profile="配置文件"
AdvSceneSwitcher.condition.profile.entry="当前活动的配置文件为 {{profiles}}"
AdvSceneSwitcher.condition.websocket="websocket"
AdvSceneSwitcher.condition.websocket.type.request="request"
AdvSceneSwitcher.condition.websocket.type.event="event"
AdvSceneSwitcher.condition.websocket.useRegex="使用正则表达式"
AdvSceneSwitcher.condition.websocket.entry.request="{{type}} 收到内容:"
AdvSceneSwitcher.condition.websocket.entry.event="{{type}} 收到自 {{connection}}:"
AdvSceneSwitcher.condition.variable="变量"
AdvSceneSwitcher.condition.variable.type.compare="等于"
AdvSceneSwitcher.condition.variable.type.empty="为空"
AdvSceneSwitcher.condition.variable.type.number="是一个数字"
AdvSceneSwitcher.condition.variable.type.lessThan="小于"
AdvSceneSwitcher.condition.variable.type.greaterThan="大于"
AdvSceneSwitcher.condition.variable.type.valueChanged="值已更改"
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
; Macro Actions
AdvSceneSwitcher.action.switchScene="切换场景"
AdvSceneSwitcher.action.scene.entry="切换场景 {{scenes}} 使用 {{transitions}} 时长 {{duration}} 秒"
AdvSceneSwitcher.action.scene.entry.noDuration="切换到场景{{scenes}}使用{{transitions}}"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="等待目标场景的过渡完成"
AdvSceneSwitcher.action.wait="等待"
AdvSceneSwitcher.action.wait.type.fixed="固定数值"
AdvSceneSwitcher.action.wait.type.random="随机数值"
AdvSceneSwitcher.action.wait.entry.fixed="等待 {{waitType}} 持续时间为 {{duration}}"
AdvSceneSwitcher.action.wait.entry.random="等待 {{waitType}} 持续时间为 {{duration}} 到 {{duration2}}"
AdvSceneSwitcher.action.audio="音频"
AdvSceneSwitcher.action.audio.type.mute="静音"
AdvSceneSwitcher.action.audio.type.unmute="取消静音"
AdvSceneSwitcher.action.audio.type.sourceVolume="来源音量"
AdvSceneSwitcher.action.audio.type.masterVolume="主音量"
AdvSceneSwitcher.action.audio.fade.type.duration="持续时间"
AdvSceneSwitcher.action.audio.fade.type.rate="百分比"
AdvSceneSwitcher.action.audio.fade.duration="{{fade}}淡出 {{fadeTypes}} {{duration}} 秒."
AdvSceneSwitcher.action.audio.fade.rate="{{fade}}淡出 {{fadeTypes}} {{rate}}每秒."
AdvSceneSwitcher.action.audio.fade.wait="等待淡入淡出完成."
AdvSceneSwitcher.action.audio.fade.abort="中止已处于活动状态的淡入淡出."
AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}"
AdvSceneSwitcher.action.recording="录制"
AdvSceneSwitcher.action.recording.type.stop="停止录制"
AdvSceneSwitcher.action.recording.type.start="开始录制"
AdvSceneSwitcher.action.recording.type.pause="暂停录制"
AdvSceneSwitcher.action.recording.type.unpause="取消录制暂停"
AdvSceneSwitcher.action.recording.type.split="分割录制文件"
AdvSceneSwitcher.action.recording.pause.hint="请注意,根据您的录制设置,您可能无法暂停录制"
AdvSceneSwitcher.action.recording.split.hint="确保先在OBS设置中启用自动分割文件!"
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="回放缓冲区"
AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导致重播缓冲区实际上未保存!"
AdvSceneSwitcher.action.replay.type.stop="停止回放缓冲区"
AdvSceneSwitcher.action.replay.type.start="启动回放缓冲区"
AdvSceneSwitcher.action.replay.type.save="保存回放缓冲区"
AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="推流"
AdvSceneSwitcher.action.streaming.type.stop="停止推流"
AdvSceneSwitcher.action.streaming.type.start="开始推流"
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="运行"
AdvSceneSwitcher.action.run.arguments="参数:"
AdvSceneSwitcher.action.run.addArgument="添加参数"
AdvSceneSwitcher.action.run.addArgumentDescription="添加新参数:"
AdvSceneSwitcher.action.run.entry="运行 {{filePath}}"
AdvSceneSwitcher.action.sceneVisibility="场景项目可见性"
AdvSceneSwitcher.action.sceneVisibility.type.show="显示"
AdvSceneSwitcher.action.sceneVisibility.type.hide="隐藏"
AdvSceneSwitcher.action.sceneVisibility.type.source="来源"
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="全部"
AdvSceneSwitcher.action.sceneVisibility.entry="设置{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
AdvSceneSwitcher.action.filter="滤镜"
AdvSceneSwitcher.action.filter.type.enable="开启"
AdvSceneSwitcher.action.filter.type.disable="关闭"
AdvSceneSwitcher.action.filter.type.settings="参数设置"
AdvSceneSwitcher.action.filter.entry="在 {{sources}} {{actions}} {{filters}}"
AdvSceneSwitcher.action.filter.getSettings="获取当前设置"
AdvSceneSwitcher.action.source="来源"
AdvSceneSwitcher.action.source.type.enable="启用"
AdvSceneSwitcher.action.source.type.disable="停用"
AdvSceneSwitcher.action.source.type.settings="配置设置"
AdvSceneSwitcher.action.source.type.refreshSettings="刷新源设置"
AdvSceneSwitcher.action.source.type.refreshSettings.tooltip="可用于刷新浏览器、媒体等源"
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
AdvSceneSwitcher.action.source.warning="警告OBS UI无法控制全局启用和禁用源注意通过这个设置禁用我测试你必须通过这个在启用才行不然点击小眼睛你无法显示"
AdvSceneSwitcher.action.source.getSettings="获取当前设置"
AdvSceneSwitcher.action.media="媒体"
AdvSceneSwitcher.action.media.type.play="开始"
AdvSceneSwitcher.action.media.type.pause="暂停"
AdvSceneSwitcher.action.media.type.stop="停止"
AdvSceneSwitcher.action.media.type.restart="重新启动"
AdvSceneSwitcher.action.media.type.next="下一个"
AdvSceneSwitcher.action.media.type.previous="上一个"
AdvSceneSwitcher.action.media.type.seek="时间轴定位"
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
AdvSceneSwitcher.action.macro="宏"
AdvSceneSwitcher.action.macro.type.pause="暂停"
AdvSceneSwitcher.action.macro.type.unpause="取消暂停"
AdvSceneSwitcher.action.macro.type.resetCounter="复位计数器"
AdvSceneSwitcher.action.macro.type.run="运行"
AdvSceneSwitcher.action.macro.type.stop="停止"
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
AdvSceneSwitcher.action.pluginState="插件状态"
AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件"
AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项:"
AdvSceneSwitcher.action.pluginState.type.import="从设置导入"
AdvSceneSwitcher.action.pluginState.importWarning="注意:当“设置”窗口打开时,操作将被忽略。"
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
AdvSceneSwitcher.action.virtualCamera="虚拟摄像机"
AdvSceneSwitcher.action.virtualCamera.type.stop="停止虚拟摄像机"
AdvSceneSwitcher.action.virtualCamera.type.start="启动虚拟摄像机"
AdvSceneSwitcher.action.virtualCamera.entry="{{actions}}"
AdvSceneSwitcher.action.hotkey="热键"
AdvSceneSwitcher.action.hotkey.leftShift="左 Shift"
AdvSceneSwitcher.action.hotkey.rightShift="右 Shift"
AdvSceneSwitcher.action.hotkey.leftCtrl="左 Ctrl"
AdvSceneSwitcher.action.hotkey.rightCtrl="右 Ctrl"
AdvSceneSwitcher.action.hotkey.leftAlt="左 Alt"
AdvSceneSwitcher.action.hotkey.rightAlt="右 Alt"
AdvSceneSwitcher.action.hotkey.leftMeta="左 Meta"
AdvSceneSwitcher.action.hotkey.rightMeta="右 Meta"
AdvSceneSwitcher.action.hotkey.onlyOBS="仅向OBS发送按键"
AdvSceneSwitcher.action.hotkey.disabled="无法模拟按键-功能已禁用!"
AdvSceneSwitcher.action.hotkey.entry="按下 {{keys}} for {{duration}}"
AdvSceneSwitcher.action.sceneOrder="场景项目顺序"
AdvSceneSwitcher.action.sceneOrder.type.moveUp="上移"
AdvSceneSwitcher.action.sceneOrder.type.moveDown="下移"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="顶部"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="底部"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="移动到数值位置"
AdvSceneSwitcher.action.sceneOrder.entry="在 {{scenes}} {{actions}} {{sources}} {{position}}"
AdvSceneSwitcher.action.sceneTransform="场景项目变换"
AdvSceneSwitcher.action.sceneTransform.getTransform="得到变换"
AdvSceneSwitcher.action.sceneTransform.entry="在 {{scenes}} 变换 {{sources}}"
AdvSceneSwitcher.action.file="文件"
AdvSceneSwitcher.action.file.type.write="写入"
AdvSceneSwitcher.action.file.type.append="追加写入"
AdvSceneSwitcher.action.file.entry="{{actions}} 到 {{filePath}}:"
AdvSceneSwitcher.action.studioMode="工作室模式"
AdvSceneSwitcher.action.studioMode.type.swap="切换预览和编程场景"
AdvSceneSwitcher.action.studioMode.type.setScene="将预览场景设置为"
AdvSceneSwitcher.action.studioMode.type.enable="启用工作室模式"
AdvSceneSwitcher.action.studioMode.type.disable="停用工作室模式"
AdvSceneSwitcher.action.studioMode.entry="{{actions}}{{scenes}}"
AdvSceneSwitcher.action.transition="转场特效"
AdvSceneSwitcher.action.transition.type.scene="场景过渡"
AdvSceneSwitcher.action.transition.type.sceneOverride="场景过渡覆盖"
AdvSceneSwitcher.action.transition.type.sourceShow="源显示过渡"
AdvSceneSwitcher.action.transition.type.sourceHide="源隐藏过渡"
AdvSceneSwitcher.action.transition.entry.line1="修改 {{type}}{{scenes}}{{sources}}"
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}将过场特效类型设置为 {{transitions}}"
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}将过场特效持续时间设置为 {{duration}}秒"
AdvSceneSwitcher.action.timer="计时器"
AdvSceneSwitcher.action.timer.type.pause="暂停"
AdvSceneSwitcher.action.timer.type.continue="继续"
AdvSceneSwitcher.action.timer.type.reset="重置"
AdvSceneSwitcher.action.timer.type.setTimeRemaining="设置剩余时间"
AdvSceneSwitcher.action.timer.entry="{{timerAction}} 定时在 {{macros}} {{duration}}"
AdvSceneSwitcher.action.random="随机"
AdvSceneSwitcher.action.random.entry="随机运行以下任何宏(忽略暂停的宏)"
AdvSceneSwitcher.action.systray="系统托盘通知"
AdvSceneSwitcher.action.systray.entry="显示通知: {{message}}"
AdvSceneSwitcher.action.screenshot="截图"
AdvSceneSwitcher.action.screenshot.save.default="默认"
AdvSceneSwitcher.action.screenshot.save.custom="其他"
AdvSceneSwitcher.action.screenshot.type.source="来源"
AdvSceneSwitcher.action.screenshot.type.scene="场景"
AdvSceneSwitcher.action.screenshot.mainOutput="OBS 预览画面"
AdvSceneSwitcher.action.screenshot.blackscreenNote="源和场景并不总是呈现,可能会导致屏幕截图的某些部分保持空白。"
AdvSceneSwitcher.action.screenshot.entry="截图{{targetType}}{{sources}}{{scenes}}保存在{{saveType}}位置"
AdvSceneSwitcher.action.profile="配置文件"
AdvSceneSwitcher.action.profile.entry="将活动配置文件切换到 {{profiles}}"
AdvSceneSwitcher.action.sceneCollection="场景集合"
AdvSceneSwitcher.action.sceneCollection.entry="将活动场景集合切换到 {{sceneCollections}}"
AdvSceneSwitcher.action.sceneCollection.warning="注意:在此之后的任何操作都不会执行,因为更改场景集合也会重新加载场景切换器设置。\n打开“设置”窗口时场景采集操作将被忽略."
AdvSceneSwitcher.action.sequence="场景序列"
AdvSceneSwitcher.action.sequence.entry="每次执行此操作时,运行列表中的下一个宏(暂停的宏将被忽略)"
AdvSceneSwitcher.action.sequence.status="上次执行的宏:%1 - 要执行的下一个宏: %2"
AdvSceneSwitcher.action.sequence.status.none="无"
AdvSceneSwitcher.action.sequence.restart="到达列表末尾后,从开头重新启动"
AdvSceneSwitcher.action.sequence.continueFrom="继续所选项目"
AdvSceneSwitcher.action.websocket="websocket"
AdvSceneSwitcher.action.websocket.type.request="request"
AdvSceneSwitcher.action.websocket.type.event="event"
AdvSceneSwitcher.action.websocket.entry.request="发送场景切换器 {{type}}{{connection}}"
AdvSceneSwitcher.action.websocket.entry.event="发送场景切换器 {{type}} 到连接的客户端"
AdvSceneSwitcher.action.http="Http"
AdvSceneSwitcher.action.http.type.get="GET"
AdvSceneSwitcher.action.http.type.post="POST"
AdvSceneSwitcher.action.http.entry.line1="发送 {{method}} 到 {{url}}"
AdvSceneSwitcher.action.http.entry.line2="超时: {{timeout}} 秒"
AdvSceneSwitcher.action.variable="变量"
AdvSceneSwitcher.action.variable.type.set="设置"
AdvSceneSwitcher.action.variable.type.append="追加"
AdvSceneSwitcher.action.variable.type.appendVar="追加变量"
AdvSceneSwitcher.action.variable.type.increment="增加"
AdvSceneSwitcher.action.variable.type.decrement="减少"
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
; Transition Tab
AdvSceneSwitcher.transitionTab.title="转场特效"
AdvSceneSwitcher.transitionTab.transitionOverride="在场景切换器中设定的转场特效优先级高于场景设定的转场特效"
AdvSceneSwitcher.transitionTab.transitionForAToB="当自动从场景A切换到场景B时使用的转场特效"
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>这里的设定<span style=\"font-style:bold;\">只影响由场景切换器引起的转场有效</span>,不影响你手动的引起的转场。<br/>在这里设定的转场特效优先级高于场景切换器其他地方设置的<br/><br/>Click the plus symbol below to continue.</p></body></html>"
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>这里的设定<span style=\"font-style:bold;\">只影响由场景切换器引起的转场有效</span>,不影响你手动的引起的转场。<br/>在这里设定的转场特效优先级高于场景切换器其他地方设置的<br/><br/>单击加号添加项目.</p></body></html>"
AdvSceneSwitcher.transitionTab.defaultTransition="当切换到这个场景时修改默认转场特效"
AdvSceneSwitcher.transitionTab.switchDefaultLabel="活跃时切换默认转场特效为"
AdvSceneSwitcher.transitionTab.entry="从场景 {{scenes}} 切换到场景 {{scenes2}} 时使用转场特效 {{transitions}}"
AdvSceneSwitcher.transitionTab.entry="切换自 {{scenes}} 到 {{scenes2}} 使用 {{transitions}} 持续时间为 {{duration}}"
AdvSceneSwitcher.transitionTab.defaultTransitionEntry="当场景 {{scenes}} 被激活时更改默认转场特效为 {{transitions}}"
AdvSceneSwitcher.transitionTab.defaultTransitionsHelp="单击加号添加项目."
AdvSceneSwitcher.transitionTab.defaultTransition.delay="场景更改 {{defTransitionDelay}} 后切换转换特效."
AdvSceneSwitcher.transitionTab.defaultTransition.delay.help="延迟用于避免取消场景切换,如果在转换仍在进行时更改了转换类型,则可能会发生这种情况."
; Pause Scenes Tab
AdvSceneSwitcher.pauseTab.title="暂停"
AdvSceneSwitcher.pauseTab.pauseOnScene="当切换到这个场景时暂停场景切换器"
AdvSceneSwitcher.pauseTab.pauseInFocus1="当窗口"
AdvSceneSwitcher.pauseTab.pauseInFocus2="获得焦点时暂停场景切换器"
AdvSceneSwitcher.pauseTab.pauseTypeScene="场景处于活动状态"
AdvSceneSwitcher.pauseTab.pauseTypeWindow="窗口处于焦点位置"
AdvSceneSwitcher.pauseTab.pauseTargetAll="全部"
AdvSceneSwitcher.pauseTab.pauseEntry="暂停 {{pauseTargets}} 检查时 {{pauseTypes}} {{scenes}} {{windows}}"
AdvSceneSwitcher.pauseTab.help="在此选项卡上,您可以配置在场景处于活动状态或窗口处于焦点时暂停各个切换方法。\n\n单击高亮显示的加号继续."
; Window Title Tab
AdvSceneSwitcher.windowTitleTab.title="窗口标题"
@@ -71,31 +575,37 @@ AdvSceneSwitcher.windowTitleTab.fullscreen="全屏时"
AdvSceneSwitcher.windowTitleTab.maximized="最大化时"
AdvSceneSwitcher.windowTitleTab.focused="窗口聚集时"
AdvSceneSwitcher.windowTitleTab.entry="{{windows}} {{scenes}} {{transitions}} {{fullscreen}} {{maximized}} {{focused}}"
AdvSceneSwitcher.windowTitleTab.windowsHelp="根据正在运行的应用程序的窗口标题切换场景。\n可以选择以下附加条件\n窗口全屏显示\n窗口最大化\n窗口聚焦\n\n单击高亮显示的加号继续."
AdvSceneSwitcher.windowTitleTab.ignoreWindowsHelp="如果忽略某个窗口标题,则场景切换程序的作用将与之前选择的窗口仍处于焦点状态一样。\n如果您经常切换到其他窗口则这将允许您避免场景切换不会触发场景更改。\n\n请选择窗口或在上面输入窗口标题然后单击下面的加号将其添加到列表中."
; Executable Tab
AdvSceneSwitcher.executableTab.title="程序"
AdvSceneSwitcher.executableTab.implemented="感谢dasOven的实现"
AdvSceneSwitcher.executableTab.requiresFocus="仅获得焦点时"
AdvSceneSwitcher.executableTab.entry="当 {{processes}} 正在运行时使用 {{transitions}} 切换到 {{scenes}} {{requiresFocus}}"
AdvSceneSwitcher.executableTab.help="如果进程正在运行,此选项卡将允许您自动切换场景。\n这在窗口名称可能更改或未知的情况下非常有用。\n\n单击突出显示的加号继续."
; Screen Region Tab
AdvSceneSwitcher.screenRegionTab.title="屏幕区域"
AdvSceneSwitcher.screenRegionTab.currentPosition="鼠标当前位置:"
AdvSceneSwitcher.screenRegionTab.showGuideFrames="显示区域边界"
AdvSceneSwitcher.screenRegionTab.hideGuideFrames="隐藏区域边界"
AdvSceneSwitcher.screenRegionTab.excludeScenes.None="没有选择"
AdvSceneSwitcher.screenRegionTab.entry="如果鼠标在 {{minX}} {{minY}} x {{maxX}} {{maxY}} 使用转场特效 {{transitions}} 切换到场景 {{scenes}} unless in {{excludeScenes}}"
AdvSceneSwitcher.screenRegionTab.help="此选项卡允许您根据鼠标光标的当前位置自动切换场景。\n\n单击高亮显示的加号继续."
; Media Tab
AdvSceneSwitcher.mediaTab.title="媒体"
AdvSceneSwitcher.mediaTab.implemented="感谢Exeldro的实现"
AdvSceneSwitcher.mediaTab.states.none=""
AdvSceneSwitcher.mediaTab.states.none=""
AdvSceneSwitcher.mediaTab.states.playing="播放中"
AdvSceneSwitcher.mediaTab.states.opening="正在打开"
AdvSceneSwitcher.mediaTab.states.opening="打开"
AdvSceneSwitcher.mediaTab.states.buffering="缓冲中"
AdvSceneSwitcher.mediaTab.states.Paused="暂停"
AdvSceneSwitcher.mediaTab.states.stopped="停止"
AdvSceneSwitcher.mediaTab.states.ended="结束"
AdvSceneSwitcher.mediaTab.states.error="错误"
AdvSceneSwitcher.mediaTab.states.playlistEnd="已结束(播放列表)"
AdvSceneSwitcher.mediaTab.states.any="任意"
AdvSceneSwitcher.mediaTab.timeRestriction.none="无"
AdvSceneSwitcher.mediaTab.timeRestriction.shorter="播放时间小于"
@@ -103,6 +613,7 @@ AdvSceneSwitcher.mediaTab.timeRestriction.longer="播放时间大于"
AdvSceneSwitcher.mediaTab.timeRestriction.remainShorter="剩余时间少于"
AdvSceneSwitcher.mediaTab.timeRestriction.remainLonger="剩余时间多于"
AdvSceneSwitcher.mediaTab.entry="当 {{mediaSources}} 状态为 {{states}} 并且 {{timeRestrictions}} {{time}} 时使用转场特效 {{transitions}} 切换到场景 {{scenes}}"
AdvSceneSwitcher.mediaTab.help="此选项卡允许您根据媒体源的状态切换场景。\n例如一旦所选媒体源结束播放您可以自动切换回上一个场景。\n\n单击高亮显示的加号继续."
; File Tab
AdvSceneSwitcher.fileTab.title="文件"
@@ -127,11 +638,13 @@ AdvSceneSwitcher.fileTab.checkfileContent="仅当文件发生修改时"
AdvSceneSwitcher.fileTab.entry="如果 {{fileType}} 文件 {{filePath}} {{browseButton}} 匹配下列规则,使用转场特效 {{transitions}} 切换到场景 {{scenes}}"
AdvSceneSwitcher.fileTab.entry2="{{matchText}}"
AdvSceneSwitcher.fileTab.entry3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
AdvSceneSwitcher.fileTab.help="此选项卡允许您根据远程或本地文件的内容自动切换场景。\n\n单击突出显示的加号继续."
; Random Tab
AdvSceneSwitcher.randomTab.title="随机场景列表"
AdvSceneSwitcher.randomTab.randomDisabledWarning="功能已被禁用 - 可通过在通用页设置\"如果不符合任何切换条件切换到随机场景列表中任意随机场景\"启用"
AdvSceneSwitcher.randomTab.entry="如果没有切换器条件满足,使用转场特效 {{transitions}} 切换到场景 {{scenes}} 并停留 {{delay}}"
AdvSceneSwitcher.randomTab.help="场景切换程序将在此选项卡上随机选择一个条目,以便在配置的时间内切换到该条目。\n请注意同一条目不会连续选择两次。\n\n单击高亮显示的加号继续."
; Time Tab
AdvSceneSwitcher.timeTab.title="时间"
@@ -144,17 +657,14 @@ AdvSceneSwitcher.timeTab.fridays="每周五"
AdvSceneSwitcher.timeTab.saturdays="每周六"
AdvSceneSwitcher.timeTab.sundays="每周日"
AdvSceneSwitcher.timeTab.afterstart="推流或录制开始后"
AdvSceneSwitcher.timeTab.afterstart.tip="相对于直播或录制开始之后的时间点"
AdvSceneSwitcher.timeTab.afterstart.tip="相对于串流或录制开始之后的时间点"
AdvSceneSwitcher.timeTab.entry="{{triggers}} 的 {{time}} 使用转场特效 {{transitions}} 切换到场景 {{scenes}}"
AdvSceneSwitcher.timeTab.help="此选项卡将允许您根据当前本地时间自动切换到其他场景。\n\n请注意场景切换程序仅在您指定的确切时间切换场景。\n请确保您已根据自己的喜好在“常规”选项卡上配置了优先级设置以便不会因其他切换而错过选定的时间点具有较高优先级的方法。\n\n单击突出显示的加号继续."
; Idle Tab
AdvSceneSwitcher.idleTab.title="闲置检测"
AdvSceneSwitcher.idleTab.enable="启用闲置检测"
AdvSceneSwitcher.idleTab.condition1="超过"
AdvSceneSwitcher.idleTab.condition2="没有鼠标或键盘操作"
AdvSceneSwitcher.idleTab.switchToScene="切换到场景"
AdvSceneSwitcher.idleTab.usingTransition1="使用"
AdvSceneSwitcher.idleTab.usingTransition2="转场特效"
AdvSceneSwitcher.idleTab.idleswitch="超过 {{duration}} 如果没有键盘或鼠标输入,则切换到场景 {{scenes}} 使用 {{transitions}}"
AdvSceneSwitcher.idleTab.dontSwitchIfFocus1="如果当前窗口焦点在"
AdvSceneSwitcher.idleTab.dontSwitchIfFocus2="时不切换"
@@ -169,35 +679,205 @@ AdvSceneSwitcher.sceneSequenceTab.loadFail="导入失败"
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="导入失败成功"
AdvSceneSwitcher.sceneSequenceTab.fileType="文本文件 (*.txt)"
AdvSceneSwitcher.sceneSequenceTab.entry="当场景 {{startScenes}} 被激活 {{delay}} 后使用转场特效 {{transitions}} 切换到场景 {{scenes}} {{interruptible}}"
AdvSceneSwitcher.sceneSequenceTab.interruptible="中断"
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="允许使用其他切换方法中断此场景序列"
AdvSceneSwitcher.sceneSequenceTab.extendEdit="扩展序列"
AdvSceneSwitcher.sceneSequenceTab.extendEntry="之后 {{delay}} 切换到 {{scenes}} 使用 {{transitions}}"
AdvSceneSwitcher.sceneSequenceTab.help="如果某个场景在配置的时间段内处于活动状态,此选项卡将允许您自动切换到其他场景。\n例如您可以自动在两个场景之间来回循环。\n\n单击高亮显示的加号继续."
; Audio Tab
AdvSceneSwitcher.audioTab.title="音频"
AdvSceneSwitcher.audioTab.entry="当{{audioSources}} is {{condition}} {{volumeWidget}} for {{duration}} 使用转场特效 {{transitions}} 切换到场景 {{scenes}}"
AdvSceneSwitcher.audioTab.condition.above="高于"
AdvSceneSwitcher.audioTab.condition.below="低于"
AdvSceneSwitcher.audioTab.ignoreInactiveSource="除非源处于非活动状态"
AdvSceneSwitcher.audioTab.entry="当音量 {{audioSources}} 在 {{condition}} {{volumeWidget}} 时 {{duration}} 秒后 切换至 {{scenes}} 使用 {{transitions}} {{ignoreInactiveSource}}"
AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="如果多个条目匹配 ..."
AdvSceneSwitcher.audioTab.multiMatchfallback="... {{duration}} 秒切换到 {{scenes}} 使用 {{transitions}}"
AdvSceneSwitcher.audioTab.help="此选项卡允许您根据源音量切换场景。\n例如如果麦克风音量达到某个阈值您可以自动切换到其他场景。\n\n单击高亮显示的加号继续."
; Video Tab
AdvSceneSwitcher.videoTab.title="视频"
AdvSceneSwitcher.videoTab.getScreenshot="获取所选条目的屏幕截图"
AdvSceneSwitcher.videoTab.getScreenshotHelp="获取当前选定项目的视频源的屏幕截图,并自动将其设置为目标图像"
AdvSceneSwitcher.videoTab.condition.match="完全匹配"
AdvSceneSwitcher.videoTab.condition.match.tooltip="精确匹配要求目标图像和源图像具有相同的分辨率。\n另外每个像素都需要匹配这就是为什么不建议使用使用压缩例如.JPG的图像格式"
AdvSceneSwitcher.videoTab.condition.differ="不匹配"
AdvSceneSwitcher.videoTab.condition.hasNotChanged="没有改变"
AdvSceneSwitcher.videoTab.condition.hasChanged="改变了"
AdvSceneSwitcher.videoTab.entry="当 {{videoSources}} {{condition}} {{filePath}} {{browseButton}} for {{duration}} 切换 {{scenes}} using {{transitions}} {{ignoreInactiveSource}}"
AdvSceneSwitcher.videoTab.ignoreInactiveSource="除非源处于非活动状态"
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>此选项卡将允许您根据选定源的当前视频输出切换场景。<br/>请确保退出 <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> 以便更好地实现此功能.<br/><br/> 单击高亮显示的加号继续.</p></body></html>"
; Network Tab
AdvSceneSwitcher.networkTab.title="网络"
AdvSceneSwitcher.networkTab.description="此选项卡将允许您远程控制另一个OBS实例的活动场景。\n请注意所有OBS实例上的场景名称必须完全匹配."
AdvSceneSwitcher.networkTab.warning="在本地网络之外运行服务器将允许第三方读取活动场景."
AdvSceneSwitcher.networkTab.server="启动服务器(向所有连接的客户端发送场景切换消息)"
AdvSceneSwitcher.networkTab.server.port="端口"
AdvSceneSwitcher.networkTab.server.lockToIPv4="锁定为仅使用IPv4将服务器"
AdvSceneSwitcher.networkTab.server.sendSceneChange="发送更改场景的消息"
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="仅为自动场景切换发送消息"
AdvSceneSwitcher.networkTab.server.sendPreview="在Studio模式下运行时发送预览场景更改消息"
AdvSceneSwitcher.networkTab.startFailed.message="WebSockets服务器无法启动可能是因为\n-TCP端口%1当前可能正在该系统的其他位置使用可能是由其他应用程序使用。请尝试在WebSocket服务器设置中设置其他TCP端口或停止可能正在使用此端口的任何应用程序。\n-错误消息: %2"
AdvSceneSwitcher.networkTab.server.status.currentStatus="状态"
AdvSceneSwitcher.networkTab.server.status.notRunning="未运行"
AdvSceneSwitcher.networkTab.server.status.starting="启动中"
AdvSceneSwitcher.networkTab.server.status.running="运行中"
AdvSceneSwitcher.networkTab.server.restart="重新启动服务"
AdvSceneSwitcher.networkTab.client="启动客户端(接收场景切换消息)"
AdvSceneSwitcher.networkTab.client.address="主机名或IP地址"
AdvSceneSwitcher.networkTab.client.port="端口"
AdvSceneSwitcher.networkTab.client.status.currentStatus="状态"
AdvSceneSwitcher.networkTab.client.status.disconnected="未连接"
AdvSceneSwitcher.networkTab.client.status.connecting="连接中"
AdvSceneSwitcher.networkTab.client.status.connected="已连接"
AdvSceneSwitcher.networkTab.client.reconnect="强制重新连接"
; Scene Group Tab
AdvSceneSwitcher.sceneGroupTab.title="场景组"
AdvSceneSwitcher.sceneGroupTab.list="场景组"
AdvSceneSwitcher.sceneGroupTab.edit="编辑场景组"
AdvSceneSwitcher.sceneGroupTab.edit.name="名字:"
AdvSceneSwitcher.sceneGroupTab.edit.type="类型: {{type}}"
AdvSceneSwitcher.sceneGroupTab.type.count="计数"
AdvSceneSwitcher.sceneGroupTab.type.time="时间"
AdvSceneSwitcher.sceneGroupTab.type.random="随机"
AdvSceneSwitcher.sceneGroupTab.edit.count="完成后前进到列表中的下一个场景 {{count}} 完全匹配"
AdvSceneSwitcher.sceneGroupTab.edit.time="完成后前进到列表中的下一个场景 {{time}} 过去了"
AdvSceneSwitcher.sceneGroupTab.edit.random="随机选择列表中的下一个场景"
AdvSceneSwitcher.sceneGroupTab.edit.repeat="如果到达“场景结束”列表,则从头开始"
AdvSceneSwitcher.sceneGroupTab.edit.addScene="添加场景"
AdvSceneSwitcher.sceneGroupTab.add="添加场景组"
AdvSceneSwitcher.sceneGroupTab.defaultname="场景组 %1"
AdvSceneSwitcher.sceneGroupTab.exists="场景组或场景名称已存在"
AdvSceneSwitcher.sceneGroupTab.help="可以选择场景组作为目标,就像选择常规场景一样。\n\n名称表明场景组是多个场景的集合。\n场景组将根据配置的设置在其指定场景的列表中前进可以在右侧找到。\n\n您可以将场景组配置为前进到列表中的下一个场景\n在多次选择场景组作为目标后。\n在经过一定时间后。\n也可以是随机的。\n\n例如包含场景的场景组…\n场景1\n场景2\n场景3\n。。。将在第一次选择“场景1”作为目标时激活它。\n第二次将激活“场景2”\n剩余时间将激活“场景3”。\n\n单击下面突出显示的加号以添加新的场景组."
AdvSceneSwitcher.sceneGroupTab.scenes.help="在左侧选择要修改的场景组。\n\n通过选择上面的场景并单击下面的加号选择要添加到此场景组的场景。\n\n可以多次将场景添加到同一场景组."
; Scene Trigger Tab
AdvSceneSwitcher.sceneTriggerTab.title="场景触发器"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--选择触发器--"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="已激活"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="未激活"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="离开"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--选择动作--"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="开始录制"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="暂停录制"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="取消暂停录制"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="停止录制"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="停止推流"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="开始推流"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="启动重播缓冲区"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="停止重放缓冲区"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="静音源"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="取消静音源"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="启动场景切换程序"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="停止场景切换"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="启动虚拟摄像机"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="停止虚拟摄像机"
AdvSceneSwitcher.sceneTriggerTab.entry="当 {{scenes}} {{triggers}} {{actions}} {{audioSources}} 在 {{duration}} 后"
AdvSceneSwitcher.sceneTriggerTab.help="此选项卡允许您在场景更改时触发操作,如停止录制或流式处理."
; Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="启动高级场景切换器"
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="停止高级场景切换器"
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="切换(启动/停止)高级场景切换器"
AdvSceneSwitcher.hotkey.macro.pause="暂停宏 %1"
AdvSceneSwitcher.hotkey.macro.unpause="取消暂停宏 %1"
AdvSceneSwitcher.hotkey.macro.togglePause="切换暂停宏 %1"
AdvSceneSwitcher.hotkey.upMacroSegmentHotkey="上移选择宏"
AdvSceneSwitcher.hotkey.downMacroSegmentHotkey="下移选择宏"
AdvSceneSwitcher.hotkey.removeMacroSegmentHotkey="删除选定的宏"
AdvSceneSwitcher.askBackup="检测到新版本的高级场景切换程序。\n是否要创建旧设置的备份?"
AdvSceneSwitcher.askForMacro="选择宏 {{macroSelection}}"
AdvSceneSwitcher.close="关闭"
AdvSceneSwitcher.browse="浏览文件"
AdvSceneSwitcher.item.select="--选择项目--"
AdvSceneSwitcher.item.add="添加新项目"
AdvSceneSwitcher.item.rename="重命名"
AdvSceneSwitcher.item.remove="删除"
AdvSceneSwitcher.item.properties="属性"
AdvSceneSwitcher.item.newName="新名称:"
AdvSceneSwitcher.item.emptyName="不允许使用空名称!"
AdvSceneSwitcher.item.nameNotAvailable="名称不可用!"
AdvSceneSwitcher.item.nameReserved="保留名称!"
AdvSceneSwitcher.variable.select="--选择变量--"
AdvSceneSwitcher.variable.add="增加新变量"
AdvSceneSwitcher.variable.name="名称:"
AdvSceneSwitcher.variable.value="当前值:"
AdvSceneSwitcher.variable.save="保存 / 载入 行为"
AdvSceneSwitcher.variable.save.dontSave="不保存变量值"
AdvSceneSwitcher.variable.save.save="保存变量值"
AdvSceneSwitcher.variable.save.default="设置变量值"
AdvSceneSwitcher.connection.select="--选择连接--"
AdvSceneSwitcher.connection.add="增加新连接"
AdvSceneSwitcher.connection.name="名称:"
AdvSceneSwitcher.connection.address="地址:"
AdvSceneSwitcher.connection.port="端口:"
AdvSceneSwitcher.connection.password="密码:"
AdvSceneSwitcher.connection.reconnect="自动重新连接:"
AdvSceneSwitcher.connection.reconnectDelay="自动重新连接延迟:"
AdvSceneSwitcher.connection.connectOnStart="启动时自动连接:"
AdvSceneSwitcher.connection.test="测试连接"
AdvSceneSwitcher.connection.status.disconnected="断开"
AdvSceneSwitcher.connection.status.connecting="连接"
AdvSceneSwitcher.connection.status.connected="已连接,但未经过身份验证"
AdvSceneSwitcher.connection.status.authenticated="已连接,并经过身份验证"
AdvSceneSwitcher.regex.enable="启用正则表达式"
AdvSceneSwitcher.regex.partialMatch="允许部分匹配"
AdvSceneSwitcher.regex.caseInsensitive="匹配不区分大小写"
AdvSceneSwitcher.regex.dotMatchNewline=". 匹配换行符"
AdvSceneSwitcher.regex.multiLine="^ 和 $ 是匹配行的开始/结束"
AdvSceneSwitcher.regex.extendedPattern="启用Qt的扩展模式语法"
AdvSceneSwitcher.selectScene="--选择场景--"
AdvSceneSwitcher.selectPreviousScene="上个场景"
AdvSceneSwitcher.selectCurrentScene="当前场景"
AdvSceneSwitcher.selectPreviewScene="预览场景"
AdvSceneSwitcher.selectAnyScene="任何场景"
AdvSceneSwitcher.currentTransition="当前转场特效"
AdvSceneSwitcher.anyTransition="任何转场特效"
AdvSceneSwitcher.selectTransition="--选择转场特效--"
AdvSceneSwitcher.selectWindow="--选择窗口--"
AdvSceneSwitcher.selectSource="--选择来源--"
AdvSceneSwitcher.selectAudioSource="--选择音频源--"
AdvSceneSwitcher.selectVideoSource="--选择视频源--"
AdvSceneSwitcher.OBSVideoOutput="OBS的主要输出"
AdvSceneSwitcher.selectMediaSource="--选择媒体源--"
AdvSceneSwitcher.selectProcess="--选择进程--"
AdvSceneSwitcher.selectFilter="--选择滤镜--"
AdvSceneSwitcher.selectMacro="--选择宏--"
AdvSceneSwitcher.selectItem="--选择项目--"
AdvSceneSwitcher.selectProfile="--选择配置文件--"
AdvSceneSwitcher.selectSceneCollection="--选择场景集合--"
AdvSceneSwitcher.enterPath="--输入路径--"
AdvSceneSwitcher.enterText="--输入文本--"
AdvSceneSwitcher.enterURL="--输入网址--"
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="无效项将不会被保存"
AdvSceneSwitcher.selectWindowTip="使用 \"OBS\" 来指定OBS窗口\n使用 \"Task Switching\" 来指定 Alt + Tab"
AdvSceneSwitcher.selectWindowTip="使用 \"OBS\" 来指定OBS窗口\n使用 \"任务切换\" 来指定 Alt + Tab"
AdvSceneSwitcher.sceneItemSelection.all="全部"
AdvSceneSwitcher.sceneItemSelection.any="任何"
AdvSceneSwitcher.status.active="运行中"
AdvSceneSwitcher.status.inactive="已停止"
AdvSceneSwitcher.running="插件运行"
AdvSceneSwitcher.stopped="插件停止"
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>这似乎是第一次启动高级场景切换程序.<br>请看一下 <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> 查看指南和示例列表.<br>如果有问题在在OBS论坛插件帖子内提问 <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">thread</span></a></p></body></html>"
AdvSceneSwitcher.deprecatedTabWarning="此选项卡的开发已停止!请考虑转换为使用宏来代替。\n可以在“常规”选项卡上禁用此提示."
AdvSceneSwitcher.unit.milliseconds="毫秒"
AdvSceneSwitcher.unit.secends="秒"
AdvSceneSwitcher.unit.minutes="分钟"
AdvSceneSwitcher.unit.hours="小时"
AdvSceneSwitcher.duration.condition.none="没有时间限制"
AdvSceneSwitcher.duration.condition.more="时间少于"
AdvSceneSwitcher.duration.condition.equal="时间等于"
AdvSceneSwitcher.duration.condition.less="时间大于"
AdvSceneSwitcher.duration.condition.within="保留结果后余存"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 13.855469 0 l -1.539063 1.4375 c -0.453125 0.421875 -0.53125 1.148438 -0.269531 1.707031 l -5.886719 5.996094 c -0.011718 0 -0.019531 0 -0.03125 0 c -0.257812 -0.128906 -0.550781 -0.183594 -0.839844 -0.148437 c -0.328124 0.046874 -0.632812 0.199218 -0.867187 0.441406 l -3.945313 3.996094 c -0.3906245 0.375 -0.5468745 0.933593 -0.4062495 1.457031 c 0.1406255 0.523437 0.5546875 0.929687 1.0820315 1.058593 c 0.527344 0.132813 1.082031 -0.03125 1.453125 -0.425781 l 3.945312 -3.996093 c 0.472657 -0.453126 0.59375 -1.15625 0.296875 -1.738282 l 5.890625 -5.964844 c 0.558594 0.25 1.273438 0.148438 1.707031 -0.289062 l 1.414063 -1.5625 z m -10.308594 0.0898438 c -0.398437 0 -0.785156 0.0937502 -1.140625 0.2187502 l 1.882812 1.878906 c 0.390626 0.382812 0.390626 1 0 1.386719 l -0.710937 0.707031 c -0.386719 0.386719 -1 0.386719 -1.390625 0 l -1.882812 -1.878906 c -0.125 0.355468 -0.2187505 0.742187 -0.2187505 1.140625 c 0 1.90625 1.5507815 3.453125 3.4609375 3.453125 c 0.402344 0 0.789063 -0.09375 1.144531 -0.21875 l 1.175782 1.171875 h 0.058593 l 2.070313 -2.0625 l -1.203125 -1.203125 c 0.125 -0.359375 0.214843 -0.742188 0.214843 -1.140625 c 0 -1.90625 -1.546874 -3.4531252 -3.460937 -3.4531252 z m 6.550781 7.8906252 l -2.070312 2.066406 c 0.011718 0.027344 0.023437 0.058594 0.03125 0.089844 l 1.144531 1.140625 c -0.125 0.355468 -0.21875 0.742187 -0.21875 1.140625 c 0 1.902343 1.550781 3.449219 3.460937 3.449219 c 0.433594 0 0.855469 -0.101563 1.238282 -0.246094 l -2.007813 -2 c -0.386719 -0.386719 -0.386719 -1.035156 0 -1.417969 l 0.679688 -0.679687 c 0.195312 -0.191407 0.457031 -0.308594 0.710937 -0.308594 s 0.515625 0.117187 0.710938 0.308594 l 1.945312 1.941406 c 0.105469 -0.328125 0.183594 -0.683594 0.183594 -1.046875 c 0 -1.90625 -1.546875 -3.453125 -3.460938 -3.453125 c -0.398437 0 -0.785156 0.09375 -1.140624 0.21875 z m 0 0" fill="#fefefe"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<g fill="#fefefe">
<path d="m 3 1 c -1.644531 0 -3 1.355469 -3 3 v 8 c 0 1.644531 1.355469 3 3 3 h 8.882812 c 0.832032 0 1.578126 -0.402344 2.054688 -0.9375 c 0.472656 -0.53125 0.738281 -1.167969 0.910156 -1.800781 l 0.972656 -2.609375 c 0.390626 -1.449219 -0.09375 -2.652344 -0.820312 -3.167969 c -0.484375 -0.34375 -0.714844 -0.292969 -1 -0.324219 v -1.160156 c 0 -0.855469 -0.558594 -1.589844 -1.09375 -1.828125 c -0.53125 -0.238281 -1.011719 -0.167969 -1.011719 -0.167969 l 0.105469 -0.003906 h -3.585938 l -1.707031 -1.707031 c -0.1875 -0.1875 -0.441406 -0.292969 -0.707031 -0.292969 z m 0 2 h 2.585938 l 1.707031 1.707031 c 0.1875 0.1875 0.441406 0.292969 0.707031 0.292969 h 4 c 0.035156 0 0.070312 -0.003906 0.105469 -0.007812 c 0 0 0.019531 0.019531 -0.011719 0.003906 c -0.035156 -0.011719 -0.09375 -0.25 -0.09375 0.003906 v 2 c 0 0.550781 0.449219 1 1 1 c 1 0 1.046875 0.703125 0.886719 1.128906 l -0.972657 2.609375 c -0.117187 0.4375 -0.296874 0.800781 -0.472656 0.996094 c -0.175781 0.199219 -0.285156 0.265625 -0.558594 0.265625 h -8.882812 c -0.570312 0 -1 -0.429688 -1 -1 v -8 c 0 -0.570312 0.46875 -0.792969 1 -1 z m 0 0"/>
<path d="m 7 6 l 0.042969 0.003906 c -0.914063 -0.042968 -1.75 0.390625 -2.195313 0.96875 c -0.710937 1.222656 -1.15625 2.277344 -1.800781 3.71875 c -0.171875 0.523438 0.117187 1.089844 0.640625 1.261719 c 0.527344 0.171875 1.09375 -0.117187 1.261719 -0.640625 c 0.488281 -1.011719 0.921875 -1.816406 1.339843 -2.808594 c 0.210938 -0.503906 0.703126 -0.492187 0.898438 -0.503906 h 5.8125 c 0.550781 0 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 0 0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

Some files were not shown because too many files have changed in this diff Show More