Compare commits

...

197 Commits
5.0.0 ... 5.4.1

Author SHA1 Message Date
4a647c5262 base: Update to version 5.4.1
Bug Fixes:
- Updated scene item transform API to latest version to prevent
  deprecation warnings (obs_sceneitem_set_info2 and
  obs_sceneitem_get_info2)
2024-02-20 21:44:33 -06:00
3ea3d3228b requesthandler: Update scene item transform API
Updates:
obs_sceneitem_get_info to obs_sceneitem_get_info2
obs_sceneitem_set_info to obs_sceneitem_set_info2

Ensures that we're using the latest versions of these functions in order
to prevent future deprecation
2024-02-20 21:44:33 -06:00
e94f9194a2 CI: Update first-party GitHub Actions to v4
GitHub Actions has deprecated actions based on node16. The v4 actions
are based on node20. Replace first-party v2/v3 actions with their v4
counterparts.

GitHub Actions has deprecated actions based on node12 and forces them to
run on node16, which is also deprecated. Update to v4 actions to avoid
warnings on CI.

See:
https://github.blog/changelog/2023-06-13-github-actions-all-actions-will-run-on-node16-instead-of-node12-by-default/
https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/
2024-01-30 16:25:38 -08:00
9ee6e2ff2a Update translations from Crowdin 2024-01-29 20:47:37 +00:00
b61a5c2431 base: Update version to 5.4.0
New Features:
- Added `GetSourceFilterKindList` request
- Added `GetSceneItemSource` request
- Added `InputSettingsChanged` event
- Added `SourceFilterSettingsChanged` event
- Added UUID support to Sources (Inputs/Scenes), Inputs, Scenes,
Transitions
  - The `Source` requests/events use `sourceUuid`
  - The `Input` requests/events use `inputUuid`
  - The `Scene` requests/events use `sceneUuid`
  - The `Transition` requests/events use `transitionUuid`
  - Filters do not have support for UUIDs at this time.

Enhancements:
- Added `contextName` field to `TriggerHotkeyByName` (exeldro)

Bug Fixes:
- Fixed a crash on shutdown with notifications enabled (r1ch)
- Added safety check to prevent `null` `outputCongestion` values in
`GetStreamStatus`
- Fixed a memory leak when switching service kinds via
`SetStreamServiceSettings`

Other Notes:
- Documented missing `outputActive` `ToggleRecord` response field
- Added a few new client softwares to the README list
- Removed a mis-documented `imageData` field
- Added a note to the hotkey requests that they are as-is and we
will not provide support for them
2024-01-24 15:51:27 -08:00
fbd4cfb4af docs(ci): Update generated docs - e5aa4c2 [skip ci] 2024-01-19 03:35:08 +00:00
e5aa4c2f69 requesthandler: Rename GetSceneItemSourceName to GetSceneItemSource
Not an API break, this was introduced just a few commits ago.
2024-01-18 19:34:51 -08:00
4cf8de8382 docs(ci): Update generated docs - 7adfb58 [skip ci] 2024-01-19 03:30:20 +00:00
7adfb5874c requesthandler: Implement input, scene, and transition UUID support
Transition UUID support is partial due to the current state of the OBS
frontend API.

Most requests which accepted things like `sourceName` now allow
`sourceUuid` (or equivalent) to be specified instead. While both fields
on the various requests may be marked as optional, at least one field
will still be required.
2024-01-18 19:27:57 -08:00
f18f46543b eventhandler: Implement input, scene, and transition UUID support
Adds `inputUuid` next to `inputName` etc.
2024-01-18 16:58:40 -08:00
f40426efa1 utils: Implement input, scene, and transition UUID support 2024-01-18 16:56:20 -08:00
830f7eb931 utils: Use BPtr for strings instead of manual bfree() 2024-01-18 16:17:48 -08:00
5e3fff78f3 docs(ci): Update generated docs - b53527c [skip ci] 2024-01-19 00:06:25 +00:00
b53527cba8 requesthandler: Add note about as-is status of hotkey requests
Too much trouble for too little gain. Please stop using these requests.
2024-01-18 16:06:07 -08:00
b806a0cfb1 docs(ci): Update generated docs - 1d0db34 [skip ci] 2024-01-19 00:02:16 +00:00
1d0db34bb2 requesthandler: Add GetSceneItemSourceName request
Closes #1122
2024-01-18 16:01:41 -08:00
690726d281 docs(ci): Update generated docs - ef4142f [skip ci] 2024-01-18 23:54:27 +00:00
ef4142fe75 eventhandler: Add SourceFilterSettingsChanged event
Closes #1059
2024-01-18 15:54:08 -08:00
caaec5d97f requesthandler: Use Frontend API for CreateSceneCollection 2024-01-18 15:43:46 -08:00
6c67b276a7 lib: Fix compile errors on C and warnings on C++ 2024-01-16 01:39:27 -08:00
fad7dfd55c docs(ci): Update generated docs - a5c459b [skip ci] 2024-01-16 09:37:45 +00:00
a5c459b6d4 docs: Fix SaveSourceScreenshot's Response Field 2024-01-16 01:37:29 -08:00
899a9b3801 README: Bump Godot client library to 4.0.x 2024-01-16 01:36:49 -08:00
939e503736 README: Add MATRIC to client software list
Closes #1177
2024-01-16 01:35:11 -08:00
5b149add99 RequestHandler: Fix memory leak when setting streaming service 2024-01-16 01:33:29 -08:00
50b57d38d0 README: Add Macrograph to Client Software 2024-01-16 01:23:59 -08:00
9b58dd1627 docs(ci): Update generated docs - 81b307e [skip ci] 2024-01-16 08:41:23 +00:00
81b307e5ad eventhandler: Add InputSettingsChanged
Fired when an input's settings change, like via the properties dialog
or via `SetInputSettings`.

Closes #1157
2024-01-16 00:41:03 -08:00
52733ddce7 docs(ci): Update generated docs - 444caeb [skip ci] 2024-01-16 08:19:11 +00:00
444caeb1d7 requesthandler: Add GetSourceFilterKindList
Closes #1198
2024-01-16 00:18:52 -08:00
f03e82c3f8 docs(ci): Update generated docs - bbdc5bc [skip ci] 2024-01-16 07:46:34 +00:00
bbdc5bc823 requesthandler: Prevent NaN outputCongestion values (null) 2024-01-15 23:45:33 -08:00
9ecc9532e8 requesthandler: Document ToggleRecord outputActive response field 2024-01-15 23:44:50 -08:00
0189c3a3f5 Utils: Check system tray exists before trying to use it
Fixes https://github.com/obsproject/obs-studio/issues/9991
2024-01-15 23:19:09 -08:00
f48fcc06ec docs(ci): Update generated docs - f43ef8e [skip ci] 2024-01-09 07:06:29 +00:00
f43ef8e2da requesthandler: Add optional context to TriggerHotkeyByName 2024-01-08 23:06:12 -08:00
7a1c71bb96 base: Update version to 5.3.5
- CMake update, no functional changes
2023-12-22 16:38:27 -05:00
cf285b3761 cmake: Update formatting and switch to native find_package call for Qt6 2023-12-20 15:09:11 -05:00
ede66a68cb Update translations from Crowdin 2023-12-05 22:04:30 +00:00
e8089a5bbf base: Update version to 5.3.4
- eventhandler: Disconnect signals from all public sources on shutdown
- websocketserver: Check for EventHandler validity in de/constructor
2023-12-05 14:15:04 -05:00
07537a33fa websocketserver: Check for EventHandler validity in de/constructor
Redundant fix for shutdown crash
2023-11-14 00:07:05 -08:00
efeae8d640 eventhandler: Disconnect signals from all public sources on shutdown
Fixes crash on shutdown when memory leaks lead to un-destroyed
sources after plugin shutdown.
2023-11-14 00:07:05 -08:00
4ff109b62b base: Update version to 5.3.3
- Update translations and docs
2023-10-16 10:42:15 -04:00
42da47f81d docs(ci): Update generated docs - a889799 [skip ci] 2023-10-13 21:25:41 +00:00
a889799655 docs: Update introduction header to 5.x.x
We don't need to be having specific versions here, considering each event/request has its own "added at" version.
2023-10-13 14:25:23 -07:00
f52f47ec5d Update translations from Crowdin 2023-10-10 13:34:40 +00:00
08767ae5a7 base: Update version to 5.3.2
- Fix plugin tests being enabled by default
2023-10-09 16:34:30 -04:00
16bf61aab6 cmake: Fix condition to disable plugin tests
The CMake generator expression to enable plugin tests mistakenly used a
string literal, which evaluated to 1, which enabled the plugin tests by
default. Use variable notation to correctly test this value.
2023-10-02 14:37:04 -07:00
e9c0eee9e4 base: Update version to 5.3.1
- Fix issues with qrcodegencpp CMake preventing Debug builds
2023-09-19 13:21:47 -04:00
f4a3de575c cmake: Update library and target names for qrcodegen
qrcodegen is identified as such (without the "lib" prefix) and as the
target "qrcodegencpp::qrcodegencpp" by the CMake package generated by
obs-deps and the finders in obs-studio when using module fallback.
2023-09-19 13:13:57 -04:00
2bfa1b4c64 cmake: Ignore LNK4099 warning
Despite building the PDBs for qrcodegencpp debug builds, we do not
currently ship those PDBs, so MSVC emits an LNK4099 warning, which
causes a build failure. It's unlikely that we'll need to debug in linked
dependencies, so we can ignore this warning. Should we decide in the
future to ship PDBs for these dependencies, the warning would no longer
be emitted, and this flag would be superfluous without requiring a
change. For now, let's make sure we can build in Debug.
2023-09-19 10:52:15 -04:00
0e611f579b cmake: Update library and target names for qrcodegen
qrcodegen is identified as such (without the "lib" prefix) and as the
target "qrcodegencpp::qrcodegencpp" by the CMake package generated by
obs-deps.
2023-09-18 12:50:40 -04:00
ec2cdc8475 base: Update version to 5.3.0
- Various minor build process cleanups
- Various code cleanups
- requesthandler: Added NotReady request status
- base: Pause requests and events during start, SC change, and shutdown
- eventhandler: Use OBS_FRONTEND_EVENT_SCRIPTING_SHUTDOWN for exit
- requesthandler: Added SetRecordDirectory
- websocketserver: Retry listen on IPv4 if IPv6 is not available
2023-09-05 14:31:41 -04:00
3cd8163945 base: Fix error to save configuration at obs_module_unload
When `obs_module_unload` is called, the frontend API is no longer
available so that `_config->Save()` is failing with error messages.
Since the configuration is saved from the OK or the Apply button on the
dialog, it is not necessary to save it again at `obs_module_unload`.
2023-08-16 12:56:12 -07:00
132d4bafdd CI: Add obs-crowdin-sync 2023-08-16 12:51:54 -07:00
d991e21f29 Update translations from Crowdin 2023-08-13 14:09:13 +00:00
a74468e07e docs(ci): Update generated docs - 55b3f88 [skip ci] 2023-08-10 01:53:35 +00:00
55b3f88db9 base: Fix a comment for SetSceneSceneTransitionOverride 2023-08-09 21:53:17 -04:00
ba7839bb69 locale: Remove obsolete translations 2023-08-09 21:52:11 -04:00
417725801c base,deps,src: Replace qr submodule by prefix/system install 2023-07-15 16:58:18 -07:00
93713c438e docs: Fix URL in docs README 2023-05-29 13:20:53 -07:00
6db08f960e docs(ci): Update generated docs - 6434c42 [skip ci] 2023-05-28 05:54:49 +00:00
6434c42155 websocketserver: Retry listen on IPv4 if IPv6 is not available
Fixes #1311
2023-05-27 22:54:02 -07:00
ac00465565 requesthandler: Add SetRecordDirectory
I've admittedly done a pretty bad job of communicating the intention of
having `SetProfileParameter` be the go-to method of configuring the
record directory. In hindsight, such a commonly needed feature should
not be locked behind an arguably complex request.

Closes #1142
Closes #1062
Closes #1035
2023-05-27 22:30:08 -07:00
2606f262e6 docs: Add big text to README in the docs directory linking protocol.md
I bet people have been getting confused here
2023-05-27 22:14:16 -07:00
2caecf6c01 README: A few minor tweaks 2023-05-27 22:14:05 -07:00
19170fe6d9 WebSocketApi: Add missing GPL license headers 2023-05-27 22:06:46 -07:00
1fc7900b1c Config: Move default values to header file
Just to make the code style align with other places
2023-05-27 22:00:51 -07:00
53d7596160 base: Various random code nitpicks 2023-05-27 22:00:26 -07:00
886738547a websocketserver: Clean up WebSocketSession class implementation
Makes it header-only with inlines, so there's theoretically some very
small performance improvements too.
2023-05-27 21:50:55 -07:00
c11874eb17 eventhandler: Use OBS_FRONTEND_EVENT_SCRIPTING_SHUTDOWN for exit
Fixes #1136
2023-05-09 22:53:43 -07:00
a0ffe16e91 base: Pause requests and events during start, SC change, and shutdown
This implements the functionality described by the new NotReady request
status. Behavior should now be *much* more reliable.
2023-05-09 22:53:43 -07:00
e3d0751385 docs(ci): Update generated docs - d518541 [skip ci] 2023-05-10 01:38:50 +00:00
d5185417ec requesthandler: Add NotReady request status
During scene collection change and OBS exit, performing requests
constitutes undefined behavior. Previously, we attempted to help this
by providing the `SceneCollectionChanging` event for any clients to
pause requests client-side, but this method has proven to not be
adequate to fix the issue. As such, this allows us to tell clients
explicitly that a request cannot be fulfilled reliably, and they
may decide whether or not to retry.
2023-05-09 18:26:25 -07:00
f7637250f1 cmake: Silences Qt warnings emitted by clang with default Xcode settings 2023-05-09 15:01:45 -07:00
57a9c19f2c Update translations from Crowdin 2023-05-01 23:11:11 +00:00
6633144ce8 README: Prevent Firefox from flagging Macro Deck as a security risk
Removes the 'www․' in the Macro Deck link in README.md to Prevent
Firefox from flagging the Macro Deck website as a potential security
risk.
2023-04-19 12:06:36 -07:00
6ef055a369 base: Update version to 5.2.2
- Various minor build process cleanups
2023-04-04 15:13:15 -04:00
a4ee9c03ea base: Remove unneeded include directories
Asio and WebSocket++ are no longer added as submodules.
They are now included in obs-deps.
2023-04-04 12:15:33 -04:00
9912c9963c base: Remove unnecessary entries in .gitignore
the commit 21886adb3 moves the destination of the generated files into
the build directory so that it is unnecessary to hide the generated
files by .gitignore.
2023-04-04 12:14:11 -04:00
21886adb32 base: Fix generated header inclusion 2023-03-27 12:59:23 -04:00
c85d9143a9 Update translations from Crowdin 2023-03-27 13:39:01 +00:00
7ca8d5fc2b base: Update version to 5.2.0
- Fixed a crash caused if `authentication` payload field was not a
string
- Allow empty vendor request data
- Minor documentation fixes
- Replace submodules with obs-deps or system versions where possible
  - asio
  - websocketpp
  - nlohmann/json
- Refactor CMake to allow uplift to new obs-studio CMake
2023-03-26 19:30:00 -04:00
db2c251189 base: Re-add version CMake variables
Make sure that non-legacy builds have these version variables populated.
2023-03-26 19:09:51 -04:00
dd248faecb cmake: Add changes for CMake build framework 3.0
New code path only taken if OBS_CMAKE_VERSION is set to 3.0.0 or
greater, old functionality remains unchanged.
2023-03-26 18:21:05 -04:00
68d79b22af base: Disable Qt RCC timestamps only on Windows 2023-03-24 12:29:19 -04:00
b06da5fa63 base: Disable Qt RCC timestamps 2023-03-23 18:20:34 -04:00
78a1b54a47 base,deps: Replace submodules by prefix/system install
nlohmann JSON, WebSocket++ and Asio are moved from sudmodules to
prefix (obs-deps) or system-wide install (Linux).
2023-03-23 17:37:51 -04:00
bf277011f9 base: Refactor CMake Qt properties
- Allow obs-deps to be used by not changing CMAKE_PREFIX_PATH.
- Move Qt AUTO properties to the target.
2023-03-23 17:37:51 -04:00
96032e0e8c requesthandler: Allow empty vendor request data 2023-02-08 10:10:44 -08:00
ddd139255b Update translations from Crowdin 2023-01-08 04:10:35 +00:00
edf29e828c docs(ci): Update generated docs - 079ab31 [skip ci] 2022-12-31 22:55:24 +00:00
079ab31f88 docs: Fix small typo in introduction.md
- Corrected 'compatability' to 'compatibility' in docs/docs/partials/introduction.md
2022-12-31 14:55:04 -08:00
e797a3fb34 websocketserver: Validate data type of authentication payload field
Can cause crash if field is not a string

Reported by @tyami94
2022-12-31 14:54:11 -08:00
a792c59699 docs(ci): Update generated docs - 31f9845 [skip ci] 2022-11-18 10:29:29 +00:00
31f9845b61 base: Update version to 5.1.0
- Renamed the tools menu button title to `WebSocket Server Settings`
- WebSocket session disconnects are now logged with the close code and
reason
- Fixed a few UI formatting issues
- Fixed the `ObsOutputState` enum not being shown in protocol.md
- Implemented new reconnect output states to the stream output
  - `OBS_WEBSOCKET_OUTPUT_RECONNECTING`
  - `OBS_WEBSOCKET_OUTPUT_RECONNECTED`
- Added the `ScreenshotSaved` event for the screenshot hotkey
- Fixed a bug where `GetLastReplayBufferFileName` could return an empty
string
- Documented `CustomEvent`
- Various other documentation fixes
- Added the following new software and libraries to the README:
  - Macro Deck
  - Bitfocus Companion
  - Kruiz Control
  - Aitum
  - OBS Blade
  - Deckboard
  - Streamer.bot
  - OBS-web
  - obws (Rust)
  - goobs
  - obsws-python
2022-11-18 02:29:10 -08:00
cb6f0b8986 docs(ci): Update generated docs - 9959acb [skip ci] 2022-11-18 10:10:12 +00:00
9959acb0e8 forms: Various UI improvements 2022-11-18 02:09:48 -08:00
8b1ef17c25 docs: Fix initial version for reconnect enum fields 2022-11-18 02:09:48 -08:00
a254172c12 eventhandler: Add reconnecting and reconnected stream output states
Closes #1050
2022-11-18 02:09:48 -08:00
57a9e23f16 docs: Document ObsOutputState enum 2022-11-18 02:09:48 -08:00
4c3660c08d docs: Enable ObsMediaInputAction enum documentation
It should now show up in protocol.md
2022-11-18 02:09:48 -08:00
323b5d0b5d eventhandler, utils: Implement missing output states 2022-11-18 02:09:48 -08:00
23f883d906 eventhandler: Split some handling code into multi handlers
Code cleanup
2022-11-18 02:09:48 -08:00
60dbcc1b66 docs(ci): Update generated docs - 8cabe24 [skip ci] 2022-11-18 06:20:26 +00:00
8cabe24b77 eventhandler: Add ScreenshotSaved event
No, this does not trigger with `Get/SaveScreenshot`. I've tried to make
that super clear in the docs. Hopefully people don't get too confused.
2022-11-17 22:19:12 -08:00
9cfca3c7d1 utils: Use new method to get last replay
Uses the newer obs-frontend-api function instead of our original
method. It was cool, but is no longer necessary.
2022-11-17 22:18:18 -08:00
cfa0b4363e utils: Add function to get last screenshot file name 2022-11-17 22:16:59 -08:00
815d47e2ff README: Add Macro Deck software link 2022-11-17 18:40:27 -08:00
9bdf560bf8 utils: Fix use-after-free in GetLastReplayBufferFileName 2022-11-17 18:36:25 -08:00
47f9beb095 docs(ci): Update generated docs - 32d0834 [skip ci] 2022-11-13 00:00:45 +00:00
32d0834c3f docs: Fix description of "mul" volume notation 2022-11-12 16:00:28 -08:00
9722ed3df4 Add CustomEvent docs entry
Resolves #1031
2022-11-12 15:56:03 -08:00
9f72852588 doc: Update README to add Java library 2022-11-12 15:51:05 -08:00
6e0220ac7b Update translations from Crowdin 2022-10-25 22:32:12 +00:00
6d4b7c786e docs(ci): Update generated docs - 290e042 [skip ci] 2022-10-22 22:22:39 +00:00
290e042612 fix: Sleep request fields are exclusive so both optional fixes #1042 2022-10-22 15:22:20 -07:00
7e4c9529eb docs(ci): Update generated docs - bc18401 [skip ci] 2022-10-18 20:11:17 +00:00
bc18401fb0 docs: Fix ouputPaused typo 2022-10-18 13:10:58 -07:00
265899f76f docs(ci): Update generated docs - 9e1a41f [skip ci] 2022-09-19 01:02:32 +00:00
9e1a41f219 docs: Clarify that nested scenes are recommended instead of groups
Seems like it would be obvious, but apparently not
2022-09-18 18:02:13 -07:00
7893ae5caa docs: Add top-level headings to main TOC
It may be worth having the entire TOC up here, but this way, at least
it's possible to jump to the other TOCs.
2022-09-16 04:54:42 -07:00
a715639302 docs(ci): Update generated docs - 6038fe9 [skip ci] 2022-09-07 19:43:58 +00:00
6038fe9a0a docs: Start list of known propertyName values for common buttons 2022-09-07 12:43:29 -07:00
6fba48929a README: Add second contributor to obsws-python 2022-09-05 15:33:30 -07:00
7eb4eb101c README: Add Bitfocus Companion to client software 2022-09-05 15:32:51 -07:00
f2e595e1ab README: Add Kruiz Control and obsws-python to list 2022-09-04 17:11:30 -07:00
c1ffbf0111 README: Add Aitum 2022-09-03 15:16:30 -07:00
f08d3225ad README: Add OBS Blade to supported client software 2022-09-03 07:06:10 -07:00
84542e1ed5 README: Add deckboard to supported client software list 2022-09-03 06:53:41 -07:00
bb9371b0dc locale: Rename plugin settings title to match other plugins
Closes obsproject/obs-studio#7231
2022-09-02 00:11:59 -07:00
ab918faea8 README: Add streamer.bot to list of supported client software 2022-09-01 03:12:56 -07:00
5716577019 Update translations from Crowdin 2022-08-30 09:00:42 +00:00
b4a1266cf0 README: Add OBS-web to client software 2022-08-25 05:28:06 -07:00
6527381c91 docs(ci): Update generated docs - fb2abc4 [skip ci] 2022-08-24 08:45:11 +00:00
fb2abc45cf docs: Fix category of GetRecordDirectory` 2022-08-24 01:44:55 -07:00
54b0dc3781 docs: Update link to Rust client crate 2022-08-24 01:44:29 -07:00
0ff90d1687 base: Update non-MSVC compile options 2022-08-24 01:44:14 -07:00
62bdbb2e64 README: Update to show availability of Dart SDK for obs-websocket (#981) 2022-08-24 01:43:39 -07:00
5f8a0122bd Update translations from Crowdin 2022-08-17 04:17:13 +00:00
20ea6e3352 README: Add a Go client library to the list 2022-08-12 23:06:41 -07:00
b07dce821a websocketserver: Log disconnect code and reason on disconnects
No clue why I wasn't doing this before.
2022-08-02 14:35:50 -07:00
2f549b82a3 base: Fix version string when built as submodule 2022-08-01 22:22:43 -07:00
17243577c5 Update translations from Crowdin 2022-07-31 23:40:52 +00:00
c0ba751aaf base: Clean up find_qt macro 2022-07-30 16:31:24 -07:00
eba6c4c6f3 base: Add ENABLE_WEBSOCKET CMake option 2022-07-30 16:31:24 -07:00
59e7e3a307 base: Add checks for submodules in CMake 2022-07-30 16:31:24 -07:00
8bf8995ad8 base: Suppress C4996 warning 2022-07-28 12:15:38 -07:00
2b8dd47a6c Revert "base: Set the correct Windows preprocessor var for asio"
This reverts commit 420e600864.
2022-07-28 12:15:38 -07:00
268a45e8dd base: Format CMakeLists.txt (again) 2022-07-28 11:46:32 -07:00
e52d5402cf base: Add and use find_qt to support Qt5 and Qt6 2022-07-28 11:40:27 -07:00
0db223b148 base: Suppress deps warnings
/wd4267 is required by websocketpp
-Wno-error=format-overflow is required by asio

-Wno-error=null-pointer-subtraction is required by json on macOS

-Wno-error=deprecated-declarations is required on macOS because Xcode 14
deprecates sprintf()
2022-07-28 11:40:27 -07:00
420e600864 base: Set the correct Windows preprocessor var for asio
Fix C4996 warning

Co-authored-by: PatTheMav <PatTheMav@users.noreply.github.com>
2022-07-28 11:40:27 -07:00
190a9551f6 requesthandler,websocketserver: Fix C4101 warnings 2022-07-28 11:40:27 -07:00
773f85e0d7 requesthandler: Fix C4267 warnings 2022-07-28 11:40:27 -07:00
b5d50c4243 lib,requesthandler,eventhandler: Fix C4244 & C4334 warnings 2022-07-28 11:40:27 -07:00
e3314b3608 docs(ci): Update generated docs - 1902d7e [skip ci] 2022-07-25 15:31:39 +00:00
1902d7e1a3 base: Update version to 5.0.1 2022-07-25 08:30:34 -07:00
e0d322d4cc Config: Disable WebSocket server by default
I believe it would be bad to enable a network-based WebSocket server
for all OBS users, since obs-websocket usage is very likely less than
a majority of users. A password will still be generated on first run,
so there are no worries about weirdness if a user goes in to enable
the server later on.
2022-07-25 08:24:04 -07:00
ecde83a28d requesthandler: Allow empty object in Set*PrivateSettings requests
Requested by #958

Closes #958
2022-07-25 08:21:57 -07:00
b0167e6296 base: Update README with C library
May God have mercy on our souls for this one.

Closes #961
2022-07-25 08:10:49 -07:00
16f3ceb997 eventhandler: Provide outputPath on OUTPUT_STARTED too
4.x apparently included this path during output start along with stop.
It appears safe to include this on output start.

Closes #963
2022-07-25 08:05:03 -07:00
2875fc7313 docs: Use SetCurrentProgramScene in examples
Previously using `SetCurrentScene` was confusing users.

Closes #964
2022-07-25 08:02:30 -07:00
b9a63603c7 websocketserver: Validate op field type
Could cause a crash by assuming `op` is always a number.

Closes #965
2022-07-25 08:00:48 -07:00
de40b53d77 base: Format CMakeLists.txt using OBS formatter 2022-07-25 07:48:06 -07:00
1698b2895b base: Fix MSVC warning about misdeclared Config struct 2022-07-22 07:00:05 -07:00
1d25f97004 requesthandler: Fix OpenVideoMixProjector program option
It was stuck opening preview regardless of setting.
2022-07-22 01:59:23 -07:00
258bfc5689 docs(ci): Update generated docs - 35e3e27 [skip ci] 2022-07-12 17:11:15 +00:00
35e3e278bf requesthandler: Fix GetGroupSceneItemList name in docs 2022-07-12 10:10:53 -07:00
5341cb5951 README: Add Twitchat 2022-07-03 12:10:24 -07:00
00504a0d52 README: Add Touch Portal to supported software 2022-07-03 11:29:06 -07:00
ab743c2ee6 docs(ci): Update generated docs - 1dd57f6 [skip ci] 2022-07-02 17:33:05 +00:00
1dd57f6140 requesthandler: Add Outputs requests
Co-authored-by: Ruggero Tomaselli <ruggerotomaselli@gmail.com>
Co-authored-by: tt2468 <tt2468@irltoolkit.com>
2022-07-02 10:32:48 -07:00
a22a7cf993 docs(ci): Update generated docs - d9026c1 [skip ci] 2022-07-02 15:30:44 +00:00
d9026c1791 docs: Fix lint formatting error 2022-07-02 08:30:23 -07:00
2524dc47cf requesthandler: Fix oopsies in OpenVideoMixProjector 2022-07-02 08:27:18 -07:00
798eebf638 docs(ci): Update generated docs - 9cdfa41 [skip ci] 2022-07-02 15:26:00 +00:00
9cdfa41113 requesthandler: Add projector creation requests
I didn't think I'd be able to make remotely usable requests using OBS'
existing projector API, but I'm actually pretty happy with how it
turned out.

Closes #929

Co-authored-by: Brendan Allan <brendonovich@outlook.com>
2022-07-02 08:25:38 -07:00
aab925c0ed docs(ci): Update generated docs - be1b13f [skip ci] 2022-07-02 14:11:39 +00:00
be1b13f15d requesthandler: Echo request details in response of CallVendorRequest
I generally don't like to echo data provided to obs-websocket in
requests, but since we do that for the request type in base requests,
this particular case seems fair.

Closes #919
2022-07-02 07:09:31 -07:00
6122fe6ea7 docs(ci): Update generated docs - 4201664 [skip ci] 2022-07-02 14:04:41 +00:00
4201664c7b requesthandler, eventhandler: Add outputPath fields when record stops
Closes #934
2022-07-02 07:02:44 -07:00
3deea2b5da requesthandler: Rework and fix a few data consistency checks
Some stuff led to possible crashes, other stuff simply didn't work.
Should be much better now.

Closes #942
2022-06-08 01:32:27 -07:00
c3ee52c4fe docs(ci): Update generated docs - f4b72b6 [skip ci] 2022-06-08 08:05:27 +00:00
f4b72b69ce utils: Clean up a few iteration functions 2022-06-08 01:04:43 -07:00
5b8fd096d5 clang-format: Indent namespaces 2022-06-08 00:37:04 -07:00
22fee0312d utils: Move from explicit enum converters to nlohmann macros 2022-06-08 00:33:41 -07:00
17292520f2 utils: A few casting nitpicks 2022-06-07 23:36:47 -07:00
711746524c Revert "Config, websocketserver: Add feature to bind to loopback (default)"
This reverts commit 1da0214201.
2022-06-07 23:07:09 -07:00
e04bca0993 Revert "forms: Add configuration to enable external access"
This reverts commit 1cd12c1023.
2022-06-07 22:34:40 -07:00
c8d0ed2138 docs: Fix EventSubscription::All subscribes 2022-06-07 21:47:54 -07:00
6deadc25ac base: Change column limit to 132
A column limit of 80 is very restrictive and code readability was
suffering. A limit of 132 is more realistic for this plugin.
2022-06-07 21:36:51 -07:00
f73e78582b base: Format code 2022-05-13 21:19:29 -07:00
7b238793d0 cmakelists: Various fixes 2022-05-13 20:40:01 -07:00
7a09f38a64 base: Remove actions building and refactor CMake for submodule 2022-05-13 20:23:03 -07:00
27d21975f0 websocketapi: Fix build on Windows 64 bit 2022-05-13 19:06:03 -07:00
60e272e6f0 base: Update a few files with updated info 2022-05-13 18:58:45 -07:00
149 changed files with 8206 additions and 4808 deletions

107
.clang-format Normal file
View File

@ -0,0 +1,107 @@
# please use clang-format version 8 or later
Standard: Cpp11
AccessModifierOffset: -8
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
#AllowAllArgumentsOnNextLine: false # requires clang-format 9
#AllowAllConstructorInitializersOnNextLine: false # requires clang-format 9
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
#AllowShortLambdasOnASingleLine: Inline # requires clang-format 9
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakStringLiterals: false # apparently unpredictable
ColumnLimit: 132
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
FixNamespaceComments: false
ForEachMacros:
- 'json_object_foreach'
- 'json_object_foreach_safe'
- 'json_array_foreach'
IncludeBlocks: Preserve
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 8
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
#ObjCBinPackProtocolList: Auto # requires clang-format 7
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
#SpaceAfterLogicalNot: false # requires clang-format 9
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
#SpaceBeforeCtorInitializerColon: true # requires clang-format 7
#SpaceBeforeInheritanceColon: true # requires clang-format 7
SpaceBeforeParens: ControlStatements
#SpaceBeforeRangeBasedForLoopColon: true # requires clang-format 7
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
#StatementMacros: # requires clang-format 8
# - 'Q_OBJECT'
TabWidth: 8
#TypenameMacros: # requires clang-format 9
# - 'DARRAY'
UseTab: ForContinuationAndIndentation
---
Language: ObjC

46
.cmake-format.json Normal file
View File

@ -0,0 +1,46 @@
{
"format": {
"line_width": 120,
"tab_size": 2,
"enable_sort": true,
"autosort": true
},
"additional_commands": {
"find_qt": {
"flags": [],
"kwargs": {
"COMPONENTS": "+",
"COMPONENTS_WIN": "+",
"COMPONENTS_MACOS": "+",
"COMPONENTS_LINUX": "+"
}
},
"set_target_properties_obs": {
"pargs": 1,
"flags": [],
"kwargs": {
"PROPERTIES": {
"kwargs": {
"PREFIX": 1,
"OUTPUT_NAME": 1,
"FOLDER": 1,
"VERSION": 1,
"SOVERSION": 1,
"FRAMEWORK": 1,
"BUNDLE": 1,
"AUTOMOC": 1,
"AUTOUIC": 1,
"AUTORCC": 1,
"AUTOUIC_SEARCH_PATHS": 1,
"BUILD_RPATH": 1,
"INSTALL_RPATH": 1,
"XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC": 1,
"XCODE_ATTRIBUTE_CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION": 1,
"XCODE_ATTRIBUTE_GCC_WARN_SHADOW":1 ,
"LIBRARY_OUTPUT_DIRECTORY": 1
}
}
}
}
}
}

View File

@ -9,8 +9,16 @@ indent_style = tab
indent_size = 4 indent_size = 4
[CMakeLists.txt] [CMakeLists.txt]
indent_style = tab indent_style = space
indent_size = 4 indent_size = 2
[**/CMakeLists.txt]
indent_style = space
indent_size = 2
[cmake/**/*.cmake]
indent_style = space
indent_size = 2
[*.{yml,yaml}] [*.{yml,yaml}]
indent_style = space indent_style = space

View File

@ -27,10 +27,9 @@ body:
- macOS 10.15 - macOS 10.15
- macOS 10.14 - macOS 10.14
- macOS 10.13 - macOS 10.13
- Ubuntu 21.04 - Ubuntu 22.04 LTS
- Ubuntu 20.10 - Ubuntu 20.10
- Ubuntu 20.04 - Ubuntu 20.04 LTS
- Ubuntu 18.04
- Other - Other
validations: validations:
required: true required: true
@ -48,10 +47,10 @@ body:
label: OBS Studio Version label: OBS Studio Version
description: What version of OBS Studio are you using? description: What version of OBS Studio are you using?
options: options:
- 27.1.3 - 29.0.x
- 27.1.1 - 28.1.x
- 27.1.0 - 28.0.x
- 27.0.1 - 27.2.4
- Git - Git
- Other - Other
validations: validations:
@ -69,11 +68,9 @@ body:
label: obs-websocket Version label: obs-websocket Version
description: What version of obs-websocket are you using? description: What version of obs-websocket are you using?
options: options:
- 5.0.0-beta1 - 5.1.0
- 5.0.0-alpha3 - 5.0.1
- 5.0.0-alpha2 - 5.0.0
- 4.9.1
- 4.9.0
- Git - Git
validations: validations:
required: true required: true

View File

@ -29,6 +29,6 @@ Tested OS(s):
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] I have read the [Contributing Guidelines](https://github.com/obsproject/obs-websocket/wiki/Contributing-Guidelines). - [ ] I have read the [Contributing Guidelines](https://github.com/obsproject/obs-websocket/wiki/Contributing-Guidelines).
- [ ] All commit messages are properly formatted and commits squashed where appropriate. - [ ] All commit messages are properly formatted and commits squashed where appropriate.
- [ ] My code is not on the `master` branch. - [ ] My code is not on `master` or a `release/*` branch.
- [ ] The code has been tested. - [ ] The code has been tested.
- [ ] I have included updates to all appropriate documentation. - [ ] I have included updates to all appropriate documentation.

22
.github/workflows/crowdin_upload.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: Upload Language Files 🌐
on:
push:
branches:
- master
paths:
- "**/en-US.ini"
jobs:
upload-language-files:
name: Upload Language Files 🌐
if: github.repository_owner == 'obsproject'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 100
- name: Upload US English Language Files 🇺🇸
uses: obsproject/obs-crowdin-sync/upload@30b5446e3b5eb19595aa68a81ddf896a857302cf
env:
CROWDIN_PAT: ${{ secrets.CROWDIN_SYNC_CROWDIN_PAT }}
GITHUB_EVENT_BEFORE: ${{ github.event.before }}
SUBMODULE_NAME: obs-websocket

View File

@ -18,7 +18,7 @@ jobs:
IS_CI: "true" IS_CI: "true"
steps: steps:
- name: 'Checkout' - name: 'Checkout'
uses: actions/checkout@v2 uses: actions/checkout@v4
with: with:
path: ${{ github.workspace }}/obs-websocket path: ${{ github.workspace }}/obs-websocket
- name: 'Generate docs' - name: 'Generate docs'

View File

@ -15,7 +15,7 @@ jobs:
if: contains(github.event.head_commit.message, '[skip ci]') != true if: contains(github.event.head_commit.message, '[skip ci]') != true
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Generate docs - name: Generate docs
run: cd docs && ./build_docs.sh run: cd docs && ./build_docs.sh
- name: Run markdownlint-cli - name: Run markdownlint-cli

View File

@ -1,560 +0,0 @@
name: 'CI Multiplatform Build'
on:
push:
paths-ignore:
- 'docs/**'
branches:
- master
tags:
- '[45].[0-9]+.[0-9]+*'
pull_request:
paths-ignore:
- 'docs/**'
- '**.md'
branches:
- master
jobs:
windows:
name: 'Windows 32/64-bit'
runs-on: [windows-2019]
if: contains(github.event.head_commit.message, '[skip ci]') != true
env:
QT_CACHE_VERSION: '2' # Change whenever updating OBS dependencies URL, in order to force a cache reset
QT_VERSION: '5.15.2'
WINDOWS_DEPS_CACHE_VERSION: '1' # Change whenever updating Qt dependency URL, in order to force a cache reset
WINDOWS_DEPS_VERSION: '2019'
CMAKE_GENERATOR: 'Visual Studio 16 2019'
CMAKE_SYSTEM_VERSION: '10.0'
steps:
- name: 'Add msbuild to PATH'
uses: microsoft/setup-msbuild@v1.0.2
- name: 'Checkout obs-websocket'
uses: actions/checkout@v2
with:
path: ${{ github.workspace }}/obs-websocket
submodules: 'recursive'
- name: 'Checkout OBS Studio'
uses: actions/checkout@v2
with:
repository: obsproject/obs-studio
path: ${{ github.workspace }}/obs-studio
submodules: 'recursive'
- name: 'Get OBS Studio Git Info'
shell: bash
working-directory: ${{ github.workspace }}/obs-studio
run: |
git fetch --prune --unshallow
echo "OBS_GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
echo "OBS_GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV
- name: 'Checkout last OBS Studio release (${{ env.OBS_GIT_TAG }})'
shell: bash
working-directory: ${{ github.workspace }}/obs-studio
run: |
git checkout ${{ env.OBS_GIT_TAG }}
git submodule update
- name: 'Get obs-websocket Git Info'
shell: bash
working-directory: ${{ github.workspace }}/obs-websocket
run: |
git fetch --prune --unshallow
GIT_HASH=$(git rev-parse --short HEAD)
echo "GIT_HASH=$GIT_HASH" >> $GITHUB_ENV
GIT_TAG=$(git describe --exact-match --tags --abbrev=0) || GIT_TAG=""
echo "GIT_TAG=$GIT_TAG" >> $GITHUB_ENV
if [ "$GIT_TAG" ] ; then \
VERSION="$GIT_TAG" \
VERSION_SUFFIX=$(echo "$GIT_TAG" | cut -c6-20) ; \
else \
VERSION="$GIT_HASH-git" \
VERSION_SUFFIX="-$GIT_HASH-git" ; \
fi
echo "PACKAGE_VERSION=$VERSION" >> $GITHUB_ENV
echo "CMAKE_VERSION_SUFFIX=$VERSION_SUFFIX" >> $GITHUB_ENV
- name: 'Restore Cached Qt'
id: qtcache
uses: actions/cache@v2
with:
path: Qt_${{ env.QT_VERSION }}.7z
key: 'qtdep-${{ env.QT_CACHE_VERSION }} | ${{ runner.os }}'
- name: 'Download Prerequisite: Qt'
if: steps.qtcache.outputs.cache-hit != 'true'
run: |
curl -kLO https://tt2468.net/dl/Qt_${{ env.QT_VERSION }}.7z -f --retry 5 -C -
- name: 'Extract Prerequisite: Qt'
run: |
7z x Qt_${{ env.QT_VERSION }}.7z -o"${{ github.workspace }}\cmbuild\QT"
- name: 'Restore Cached OBS Studio Dependencies'
id: obscache
uses: actions/cache@v2
with:
path: ${{ github.workspace }}\cmbuild\deps\**
key: 'obsdep-${{ env.WINDOWS_DEPS_CACHE_VERSION }} | ${{ runner.os }}'
- name: 'Install Prerequisite: Pre-built OBS Studio dependencies'
if: steps.obscache.outputs.cache-hit != 'true'
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: 'Restore OBS Studio 32-bit Build v${{ env.OBS_GIT_TAG }} from Cache'
id: build-cache-obs-32
uses: actions/cache@v2
env:
CACHE_NAME: 'build-cache-obs-32'
with:
path: ${{ github.workspace }}/obs-studio/build32
key: ${{ runner.os }}-${{ env.CACHE_NAME }}-${{ env.OBS_GIT_TAG }}
- name: 'Configure OBS Studio 32-bit'
if: steps.build-cache-obs-32.outputs.cache-hit != 'true'
working-directory: ${{ github.workspace }}/obs-studio
run: |
if(!(Test-Path -Path ".\build32")){New-Item -ItemType directory -Path .\build32}
cd .\build32
cmake -G "${{ env.CMAKE_GENERATOR }}" -A Win32 -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DQTDIR="${{ github.workspace }}\cmbuild\QT\${{ env.QT_VERSION }}\msvc2019" -DDepsPath="${{ github.workspace }}\cmbuild\deps\win32" -DCOPIED_DEPENDENCIES=NO -DCOPY_DEPENDENCIES=YES -DBUILD_BROWSER=OFF ..
- name: 'Build OBS Studio 32-bit'
if: steps.build-cache-obs-32.outputs.cache-hit != 'true'
working-directory: ${{ github.workspace }}/obs-studio
run: |
msbuild /m /p:Configuration=RelWithDebInfo .\build32\libobs\libobs.vcxproj
msbuild /m /p:Configuration=RelWithDebInfo .\build32\UI\obs-frontend-api\obs-frontend-api.vcxproj
- name: 'Restore OBS Studio 64-bit Build v${{ env.OBS_GIT_TAG }} from Cache'
id: build-cache-obs-64
uses: actions/cache@v1
env:
CACHE_NAME: 'build-cache-obs-64'
with:
path: ${{ github.workspace }}/obs-studio/build64
key: ${{ runner.os }}-${{ env.CACHE_NAME }}-${{ env.OBS_GIT_TAG }}
- name: 'Configure OBS Studio 64-bit'
if: steps.build-cache-obs-64.outputs.cache-hit != 'true'
working-directory: ${{ github.workspace }}/obs-studio
run: |
if(!(Test-Path -Path ".\build64")){New-Item -ItemType directory -Path .\build64}
cd .\build64
cmake -G "${{ env.CMAKE_GENERATOR }}" -A x64 -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DQTDIR="${{ github.workspace }}\cmbuild\QT\${{ env.QT_VERSION }}\msvc2019_64" -DDepsPath="${{ github.workspace }}\cmbuild\deps\win64" -DCOPIED_DEPENDENCIES=NO -DCOPY_DEPENDENCIES=YES -DBUILD_BROWSER=OFF ..
- name: 'Build OBS Studio 64-bit'
if: steps.build-cache-obs-64.outputs.cache-hit != 'true'
working-directory: ${{ github.workspace }}/obs-studio
run: |
msbuild /m /p:Configuration=RelWithDebInfo .\build64\libobs\libobs.vcxproj
msbuild /m /p:Configuration=RelWithDebInfo .\build64\UI\obs-frontend-api\obs-frontend-api.vcxproj
- name: 'Configure obs-websocket 32-bit'
working-directory: ${{ github.workspace }}/obs-websocket
run: |
mkdir .\build32
cd .\build32
cmake -G "${{ env.CMAKE_GENERATOR }}" -A Win32 -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DQTDIR="${{ github.workspace }}\cmbuild\QT\${{ env.QT_VERSION }}\msvc2019" -DLibObs_DIR="${{ github.workspace }}\obs-studio\build32\libobs" -DLIBOBS_INCLUDE_DIR="${{ github.workspace }}\obs-studio\libobs" -DLIBOBS_LIB="${{ github.workspace }}\obs-studio\build32\libobs\RelWithDebInfo\obs.lib" -DOBS_FRONTEND_LIB="${{ github.workspace }}\obs-studio\build32\UI\obs-frontend-api\RelWithDebInfo\obs-frontend-api.lib" -DOBS_WEBSOCKET_VERSION_SUFFIX="${{ env.CMAKE_VERSION_SUFFIX }}" ..
- name: 'Configure obs-websocket 64-bit'
working-directory: ${{ github.workspace }}/obs-websocket
run: |
mkdir .\build64
cd .\build64
cmake -G "${{ env.CMAKE_GENERATOR }}" -A x64 -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DQTDIR="${{ github.workspace }}\cmbuild\QT\${{ env.QT_VERSION }}\msvc2019_64" -DLibObs_DIR="${{ github.workspace }}\obs-studio\build64\libobs" -DLIBOBS_INCLUDE_DIR="${{ github.workspace }}\obs-studio\libobs" -DLIBOBS_LIB="${{ github.workspace }}\obs-studio\build64\libobs\RelWithDebInfo\obs.lib" -DOBS_FRONTEND_LIB="${{ github.workspace }}\obs-studio\build64\UI\obs-frontend-api\RelWithDebInfo\obs-frontend-api.lib" -DOBS_WEBSOCKET_VERSION_SUFFIX="${{ env.CMAKE_VERSION_SUFFIX }}" ..
- name: 'Build obs-websocket 32-bit'
working-directory: ${{ github.workspace }}/obs-websocket
run: msbuild /m /p:Configuration=RelWithDebInfo .\build32\obs-websocket.sln
- name: 'Build obs-websocket 64-bit'
working-directory: ${{ github.workspace }}/obs-websocket
run: msbuild /m /p:Configuration=RelWithDebInfo .\build64\obs-websocket.sln
- name: 'Set PR Artifact Filename'
shell: bash
run: |
echo "WIN_FILENAME=obs-websocket-${{ env.PACKAGE_VERSION }}-Windows" >> $GITHUB_ENV
- name: 'Package obs-websocket'
working-directory: ${{ github.workspace }}/obs-websocket
run: |
mkdir package
cd package
7z a "${{ env.WIN_FILENAME }}.zip" "..\release\*"
iscc ..\installer\installer-windows.generated.iss /O. /F"${{ env.WIN_FILENAME }}-Installer"
- name: 'Publish ${{ env.WIN_FILENAME }}.zip'
if: success()
uses: actions/upload-artifact@v2-preview
with:
name: 'obs-websocket-${{ env.PACKAGE_VERSION }}-Windows'
path: ${{ github.workspace }}/obs-websocket/package/*.zip
- name: 'Publish ${{ env.WIN_FILENAME }}-Installer.exe'
if: success()
uses: actions/upload-artifact@v2-preview
with:
name: 'obs-websocket-${{ env.PACKAGE_VERSION }}-Windows-Installer'
path: ${{ github.workspace }}/obs-websocket/package/*.exe
ubuntu64:
name: 'Linux/Ubuntu 64-bit'
runs-on: [ubuntu-latest]
if: contains(github.event.head_commit.message, '[skip ci]') != true
steps:
- name: 'Checkout obs-websocket'
uses: actions/checkout@v2
with:
path: ${{ github.workspace }}/obs-websocket
submodules: 'recursive'
- name: 'Checkout OBS Studio'
uses: actions/checkout@v2
with:
repository: obsproject/obs-studio
path: ${{ github.workspace }}/obs-studio
submodules: 'recursive'
- name: 'Get OBS Studio Git Info'
shell: bash
working-directory: ${{ github.workspace }}/obs-studio
run: |
git fetch --prune --unshallow
echo "OBS_GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
echo "OBS_GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV
- name: 'Checkout last OBS Studio release (${{ env.OBS_GIT_TAG }})'
shell: bash
working-directory: ${{ github.workspace }}/obs-studio
run: |
git checkout ${{ env.OBS_GIT_TAG }}
git submodule update
- name: 'Get obs-websocket git info'
working-directory: ${{ github.workspace }}/obs-websocket
run: |
git fetch --prune --unshallow
GIT_HASH=$(git rev-parse --short HEAD)
echo "GIT_HASH=$GIT_HASH" >> $GITHUB_ENV
GIT_TAG=$(git describe --exact-match --tags --abbrev=0) || GIT_TAG=""
echo "GIT_TAG=$GIT_TAG" >> $GITHUB_ENV
if [ "$GIT_TAG" ] ; then \
VERSION="$GIT_TAG" \
VERSION_SUFFIX=$(echo "$GIT_TAG" | cut -c6-20) ; \
else \
VERSION="$GIT_HASH-git" \
VERSION_SUFFIX="-$GIT_HASH-git" ; \
fi
echo "PACKAGE_VERSION=$VERSION" >> $GITHUB_ENV
echo "CMAKE_VERSION_SUFFIX=$VERSION_SUFFIX" >> $GITHUB_ENV
- 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 \
libmbedtls-dev \
pkg-config \
python3-dev \
qtbase5-dev \
qtbase5-private-dev \
libqt5svg5-dev \
swig \
libxcb-randr0-dev \
libxcb-xfixes0-dev \
libx11-xcb-dev \
libxcb1-dev \
libxss-dev \
- name: 'Configure OBS Studio'
working-directory: ${{ github.workspace }}/obs-studio
shell: bash
run: |
mkdir ./build
cd ./build
cmake -DDISABLE_PLUGINS=YES -DENABLE_SCRIPTING=NO -DUNIX_STRUCTURE=YES -DCMAKE_INSTALL_PREFIX=/usr ..
- name: 'Build OBS Studio'
working-directory: ${{ github.workspace }}/obs-studio
shell: bash
run: |
set -e
cd ./build
make -j4 libobs obs-frontend-api
- name: 'Install OBS Studio'
working-directory: ${{ github.workspace }}/obs-studio
shell: bash
run: |
cd ./build
sudo cp ./libobs/libobs.so /usr/lib
sudo cp ./UI/obs-frontend-api/libobs-frontend-api.so /usr/lib
sudo mkdir -p /usr/include/obs
sudo cp ../UI/obs-frontend-api/obs-frontend-api.h /usr/include/obs/obs-frontend-api.h
- name: 'Configure obs-websocket'
working-directory: ${{ github.workspace }}/obs-websocket
shell: bash
run: |
mkdir ./build
cd ./build
if [ "${{ env.GIT_TAG }}" ] ; then \
cmake -DLIBOBS_INCLUDE_DIR=${{ github.workspace }}/obs-studio/libobs -DCMAKE_INSTALL_PREFIX=/usr -DUSE_UBUNTU_FIX=TRUE -DOBS_WEBSOCKET_VERSION_SUFFIX="${{ env.CMAKE_VERSION_SUFFIX }}" -DCMAKE_BUILD_TYPE=Release .. ; \
else \
cmake -DLIBOBS_INCLUDE_DIR=${{ github.workspace }}/obs-studio/libobs -DCMAKE_INSTALL_PREFIX=/usr -DUSE_UBUNTU_FIX=TRUE -DOBS_WEBSOCKET_VERSION_SUFFIX="${{ env.CMAKE_VERSION_SUFFIX }}" -DPLUGIN_TESTS=TRUE .. ; \
fi
- name: 'Build obs-websocket'
working-directory: ${{ github.workspace }}/obs-websocket
shell: bash
run: |
set -e
cd ./build
make -j4
- name: 'Set PR Artifact Filename'
shell: bash
run: |
echo "LINUX_FILENAME=obs-websocket-${{ env.PACKAGE_VERSION }}-Ubuntu64.deb" >> $GITHUB_ENV
- name: 'Package ${{ env.LINUX_FILENAME }}'
if: success()
working-directory: ${{ github.workspace }}/obs-websocket
shell: bash
run: |
if [ "${{ env.GIT_TAG }}" ] ; then \
CHECKINSTALL_VERSION="${{ env.PACKAGE_VERSION }}" ; \
else \
CHECKINSTALL_VERSION="1-${{ env.PACKAGE_VERSION }}" ; \
fi
cd ./build
sudo checkinstall -y --type=debian --fstrans=no -nodoc \
--backup=no --deldoc=yes --install=no --pkgname=obs-websocket --pkgversion="$CHECKINSTALL_VERSION" \
--pkglicense="GPLv2.0" --maintainer="${{ github.event.pusher.email }}" --pkggroup="video" \
--pkgsource="${{ github.event.repository.html_url }}" \
--requires="obs-studio,libqt5network5,libqt5concurrent5,qt5-image-formats-plugins" \
--pakdir="../package"
sudo chmod ao+r ../package/*
sudo mv ../package/* ../package/${{ env.LINUX_FILENAME }}
cd -
- name: 'Publish ${{ env.LINUX_FILENAME }}'
if: success()
uses: actions/upload-artifact@v2-preview
with:
name: 'obs-websocket-${{ env.PACKAGE_VERSION }}-Ubuntu64'
path: '${{ github.workspace }}/obs-websocket/package/*.deb'
macOS:
name: 'macOS 64-bit'
runs-on: [macos-latest]
if: contains(github.event.head_commit.message, '[skip ci]') != true
env:
MACOS_DEPS_VERSION: '2022-01-01'
MACOS_DEPS_CACHE_VERSION: '2' # Change whenever updating dependencies version, in order to force a cache reset
steps:
- name: 'Checkout obs-websocket'
uses: actions/checkout@v2
with:
path: ${{ github.workspace }}/obs-websocket
submodules: 'recursive'
- name: 'Checkout OBS Studio'
uses: actions/checkout@v2
with:
repository: obsproject/obs-studio
path: ${{ github.workspace }}/obs-studio
submodules: 'recursive'
- name: 'Install Prerequisite: Binary Signing Certificate'
if: github.event_name != 'pull_request'
uses: apple-actions/import-codesign-certs@v1
with:
p12-file-base64: ${{ secrets.MACOS_SIGNING_CERT }}
p12-password: ${{ secrets.MACOS_SIGNING_CERT_PASSWORD }}
create-keychain: true
keychain-password: ${{ secrets.MACOS_TEMP_CI_KEYCHAIN_PASSWORD }}
- name: 'Install Prerequisite: Installer Signing Certificate'
if: github.event_name != 'pull_request'
uses: apple-actions/import-codesign-certs@v1
with:
p12-file-base64: ${{ secrets.MACOS_INSTALLER_CERT }}
p12-password: ${{ secrets.MACOS_INSTALLER_CERT_PASSWORD }}
create-keychain: false
keychain-password: ${{ secrets.MACOS_TEMP_CI_KEYCHAIN_PASSWORD }}
- name: 'Get OBS Studio Git Info'
shell: bash
working-directory: ${{ github.workspace }}/obs-studio
run: |
git fetch --prune --unshallow
echo "OBS_GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
echo "OBS_GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV
- name: 'Checkout last OBS Studio release (${{ env.OBS_GIT_TAG }})'
shell: bash
working-directory: ${{ github.workspace }}/obs-studio
run: |
git checkout ${{ env.OBS_GIT_TAG }}
git submodule update
- name: 'Get obs-websocket git info'
shell: bash
working-directory: ${{ github.workspace }}/obs-websocket
run: |
git fetch --prune --unshallow
GIT_HASH=$(git rev-parse --short HEAD)
echo "GIT_HASH=$GIT_HASH" >> $GITHUB_ENV
GIT_TAG=$(git describe --exact-match --tags --abbrev=0) || GIT_TAG=""
echo "GIT_TAG=$GIT_TAG" >> $GITHUB_ENV
if [ "$GIT_TAG" ] ; then \
VERSION="$GIT_TAG" \
VERSION_SUFFIX=$(echo "$GIT_TAG" | cut -c6-20) ; \
else \
VERSION="$GIT_HASH-git" \
VERSION_SUFFIX="-$GIT_HASH-git" ; \
fi
echo "PACKAGE_VERSION=$VERSION" >> $GITHUB_ENV
echo "CMAKE_VERSION_SUFFIX=$VERSION_SUFFIX" >> $GITHUB_ENV
- name: 'Install Packages'
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.10/Install\ Packages.pkg -target /
- name: 'Restore Cached Qt & OBS Studio dependencies'
id: deps-cache
uses: actions/cache@v2
with:
path: ${{ github.workspace }}/obsdeps/**
key: 'deps-cache-${{ env.MACOS_DEPS_CACHE_VERSION }} | ${{ runner.os }}'
- name: 'Install Prerequisite: Qt + OBS Studio dependencies'
if: steps.deps-cache.outputs.cache-hit != 'true'
shell: bash
run: |
mkdir -p obsdeps
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.MACOS_DEPS_VERSION }}/macos-deps-qt-${{ env.MACOS_DEPS_VERSION }}-universal.tar.xz
tar -xf macos-deps-qt-${{ env.MACOS_DEPS_VERSION }}-universal.tar.xz -C "./obsdeps"
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.MACOS_DEPS_VERSION }}/macos-deps-${{ env.MACOS_DEPS_VERSION }}-universal.tar.xz
tar -xf macos-deps-${{ env.MACOS_DEPS_VERSION }}-universal.tar.xz -C "./obsdeps"
- run: xattr -r -d com.apple.quarantine ./obsdeps
shell: bash
- name: 'Configue OBS Studio'
if: steps.cache-obs-build.outputs.cache-hit != 'true'
working-directory: ${{ github.workspace }}/obs-studio
shell: bash
run: |
mkdir -p ./build
cd ./build
cmake .. \
-DQTDIR=${{ github.workspace }}/obsdeps \
-DDepsPath=${{ github.workspace }}/obsdeps \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 \
-DDISABLE_PLUGINS=true \
-DENABLE_SCRIPTING=0 \
-DCMAKE_PREFIX_PATH=${{ github.workspace }}/obsdeps/lib/cmake
- name: 'Build OBS Studio'
if: steps.cache-obs-build.outputs.cache-hit != 'true'
working-directory: ${{ github.workspace }}/obs-studio/build
shell: bash
run: |
set -e
make -j4 libobs obs-frontend-api
- name: 'Configure obs-websocket'
working-directory: ${{ github.workspace }}/obs-websocket
shell: bash
run: |
mkdir -p build
cd build
cmake .. \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 \
-DQTDIR=${{ github.workspace }}/obsdeps \
-DLIBOBS_INCLUDE_DIR=${{ github.workspace }}/obs-studio/libobs \
-DLIBOBS_LIB=${{ github.workspace }}/obs-studio/libobs \
-DOBS_FRONTEND_LIB="${{ github.workspace }}/obs-studio/build/UI/obs-frontend-api/libobs-frontend-api.dylib" \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_INSTALL_PREFIX=/usr \
-DOBS_WEBSOCKET_VERSION_SUFFIX="${{ env.CMAKE_VERSION_SUFFIX }}"
- name: 'Build obs-websocket'
working-directory: ${{ github.workspace }}/obs-websocket/build
shell: bash
run: |
set -e
make -j4
- name: 'Relink Qt'
shell: bash
working-directory: ${{ github.workspace }}/obs-websocket/build
run: |
install_name_tool \
-change /tmp/obsdeps/lib/QtWidgets.framework/Versions/5/QtWidgets \
@executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets \
-change /tmp/obsdeps/lib/QtGui.framework/Versions/5/QtGui \
@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui \
-change /tmp/obsdeps/lib/QtCore.framework/Versions/5/QtCore \
@executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore \
-change /tmp/obsdeps/lib/QtNetwork.framework/Versions/5/QtNetwork \
@executable_path/../Frameworks/QtNetwork.framework/Versions/5/QtNetwork \
-change /tmp/obsdeps/lib/QtSvg.framework/Versions/5/QtSvg \
@executable_path/../Frameworks/QtSvg.framework/Versions/5/QtSvg \
./obs-websocket.so
- name: 'Sign plugin binary'
if: github.event_name != 'pull_request'
shell: bash
working-directory: ${{ github.workspace }}/obs-websocket/build
run: |
codesign --sign "${{ secrets.MACOS_SIGNING_IDENTITY }}" ./obs-websocket.so
- name: 'Set PR Artifact Filename'
shell: bash
run: |
echo "MACOS_FILENAME=obs-websocket-${{ env.PACKAGE_VERSION }}-macOS.pkg" >> $GITHUB_ENV
echo "MACOS_FILENAME_UNSIGNED=obs-websocket-${{ env.PACKAGE_VERSION }}-macOS-Unsigned.pkg" >> $GITHUB_ENV
- name: 'Package ${{ env.MACOS_FILENAME_UNSIGNED }}'
if: success()
working-directory: ${{ github.workspace }}/obs-websocket
shell: bash
run: |
packagesbuild ./CI/macos/obs-websocket.pkgproj
mv ./release/obs-websocket.pkg ./release/${{ env.MACOS_FILENAME_UNSIGNED }}
- name: 'Sign plugin package'
if: ${{ env.GIT_TAG != '' }}
shell: bash
working-directory: ${{ github.workspace }}/obs-websocket
run: |
productsign \
--sign "${{ secrets.MACOS_INSTALLER_IDENTITY }}" \
./release/${{ env.MACOS_FILENAME_UNSIGNED }} \
./release/${{ env.MACOS_FILENAME }}
rm ./release/${{ env.MACOS_FILENAME_UNSIGNED }}
- name: 'Notarize package'
if: ${{ env.GIT_TAG != '' }}
shell: bash
working-directory: ${{ github.workspace }}/obs-websocket
run: |
zip -r ./release/${{ env.MACOS_FILENAME }}.zip ./release/${{ env.MACOS_FILENAME }}
UPLOAD_RESULT=$(xcrun altool --notarize-app \
--primary-bundle-id "com.obsproject.obs-websocket" \
--username "${{ secrets.MACOS_NOTARIZATION_USERNAME }}" \
--password "${{ secrets.MACOS_NOTARIZATION_PASSWORD }}" \
--asc-provider "${{ secrets.ASC_PROVIDER_SHORTNAME }}" \
--file "./release/${{ env.MACOS_FILENAME }}.zip")
rm ./release/${{ env.MACOS_FILENAME }}.zip
REQUEST_UUID=$(echo $UPLOAD_RESULT | awk -F ' = ' '/RequestUUID/ {print $2}')
# Pieces of code borrowed from rednoah/notarized-app
while sleep 30 && date; do
CHECK_RESULT=$(xcrun altool \
--notarization-info "$REQUEST_UUID" \
--username "${{ secrets.MACOS_NOTARIZATION_USERNAME }}" \
--password "${{ secrets.MACOS_NOTARIZATION_PASSWORD }}" \
--asc-provider "${{ secrets.ASC_PROVIDER_SHORTNAME }}")
if ! grep -q "Status: in progress" <<< "$CHECK_RESULT"; then
xcrun stapler staple ./release/${{ env.MACOS_FILENAME }}
break
fi
done
- name: 'Publish Packages'
if: success()
uses: actions/upload-artifact@v2-preview
with:
name: 'obs-websocket-${{ env.PACKAGE_VERSION }}-macOS'
path: '${{ github.workspace }}/obs-websocket/release/*.pkg'

6
.gitignore vendored
View File

@ -1,14 +1,12 @@
*~ *~
.DS_Store .DS_Store
.idea
.vscode
/build/ /build/
/build32/ /build32/
/build64/ /build64/
/release/ /release/
/package/ /package/
/installer/Output/ /installer/Output/
.idea
.vscode
/docs/node_modules/ /docs/node_modules/
/src/plugin-macros.generated.h
/installer/installer-windows.generated.iss
/cmake-build-debug/ /cmake-build-debug/

12
.gitmodules vendored
View File

@ -1,12 +0,0 @@
[submodule "deps/websocketpp"]
path = deps/websocketpp
url = https://github.com/zaphoyd/websocketpp.git
[submodule "deps/asio"]
path = deps/asio
url = https://github.com/chriskohlhoff/asio.git
[submodule "deps/json"]
path = deps/json
url = https://github.com/nlohmann/json.git
[submodule "deps/qr"]
path = deps/qr
url = https://github.com/nayuki/QR-Code-generator.git

View File

@ -1,726 +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/obs-websocket.so</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>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>obs-websocket</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>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>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>VERSION</key>
<integer>4</integer>
</dict>
<key>PACKAGE_SCRIPTS</key>
<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>IDENTIFIER</key>
<string>com.obsproject.obs-websocket</string>
<key>OVERWRITE_PERMISSIONS</key>
<false/>
<key>VERSION</key>
<string>5.0.0</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>../../release</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>obs-websocket</string>
</dict>
</dict>
<key>TYPE</key>
<integer>1</integer>
<key>VERSION</key>
<integer>2</integer>
</dict>
</plist>

View File

@ -1,340 +1,181 @@
cmake_minimum_required(VERSION 3.16...3.20) cmake_minimum_required(VERSION 3.16...3.25)
# Version variables legacy_check()
project(obs-websocket VERSION 5.0.0)
set(obs-websocket_VERSION 5.4.0)
set(OBS_WEBSOCKET_RPC_VERSION 1) set(OBS_WEBSOCKET_RPC_VERSION 1)
option(ENABLE_WEBSOCKET "Enable building OBS with websocket plugin" ON)
# Set correct version string if(NOT ENABLE_WEBSOCKET)
if(DEFINED OBS_WEBSOCKET_VERSION_SUFFIX AND NOT OBS_WEBSOCKET_VERSION_SUFFIX STREQUAL "") target_disable(obs-websocket)
set(OBS_WEBSOCKET_VERSION "${CMAKE_PROJECT_VERSION}${OBS_WEBSOCKET_VERSION_SUFFIX}") return()
message(WARNING "-----------------------------------\nVersion Suffix provided. OBS_WEBSOCKET_VERSION is now ${OBS_WEBSOCKET_VERSION}\n-----------------------------------")
else()
set(OBS_WEBSOCKET_VERSION "${CMAKE_PROJECT_VERSION}")
endif() endif()
# Find Qt
find_package(Qt6 REQUIRED Core Widgets Svg Network)
set(CMAKE_CXX_STANDARD 17) # Find nlohmann JSON
set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(nlohmann_json 3 REQUIRED)
# Find qrcodegencpp
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
find_package(qrcodegencpp REQUIRED)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF)
# Prohibit in-source builds # Find WebSocket++
file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" _LOC_PATH) find_package(Websocketpp 0.8 REQUIRED)
if(EXISTS "${LOC_PATH}")
message(FATAL_ERROR "obs-websocket: You cannot build in a source directory (or any directory with " # Find Asio
"CMakeLists.txt file). Please make a build subdirectory. Feel free to " find_package(Asio 1.12.1 REQUIRED)
"remove CMakeCache.txt and CMakeFiles.")
endif() add_library(obs-websocket MODULE)
unset(_LOC_PATH) add_library(OBS::websocket ALIAS obs-websocket)
target_sources(
# Allow selection of common build types via UI obs-websocket
if(NOT CMAKE_BUILD_TYPE) PRIVATE # cmake-format: sortable
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING lib/obs-websocket-api.h
"OBS build type [Release, RelWithDebInfo, Debug, MinSizeRel]" FORCE) src/Config.cpp
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Release RelWithDebInfo Debug MinSizeRel) src/Config.h
endif() src/forms/ConnectInfo.cpp
src/forms/ConnectInfo.h
src/forms/resources.qrc
# Plugin tests flag src/forms/SettingsDialog.cpp
option(PLUGIN_TESTS "Enable plugin runtime tests" OFF) src/forms/SettingsDialog.h
src/obs-websocket.cpp
src/obs-websocket.h
# Qt build stuff src/WebSocketApi.cpp
set(CMAKE_PREFIX_PATH "${QTDIR}") src/WebSocketApi.h)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON) target_sources(
set(CMAKE_AUTOUIC ON) obs-websocket
PRIVATE # cmake-format: sortable
set(CMAKE_AUTORCC ON) # For resources.qrc src/websocketserver/rpc/WebSocketSession.h
src/websocketserver/types/WebSocketCloseCode.h
# Tell websocketpp not to use system boost src/websocketserver/types/WebSocketOpCode.h
add_definitions(-DASIO_STANDALONE) src/websocketserver/WebSocketServer.cpp
src/websocketserver/WebSocketServer.h
src/websocketserver/WebSocketServer_Protocol.cpp)
# Arm build fixes
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") target_sources(
set(CMAKE_CXX_FLAGS "-mfpu=neon") obs-websocket
endif() PRIVATE # cmake-format: sortable
src/eventhandler/EventHandler.cpp
src/eventhandler/EventHandler.h
# Find libobs src/eventhandler/EventHandler_Config.cpp
if (WIN32 OR APPLE) src/eventhandler/EventHandler_Filters.cpp
include(cmake/FindLibObs.cmake) src/eventhandler/EventHandler_General.cpp
endif() src/eventhandler/EventHandler_Inputs.cpp
find_package(LibObs REQUIRED) src/eventhandler/EventHandler_MediaInputs.cpp
src/eventhandler/EventHandler_Outputs.cpp
src/eventhandler/EventHandler_SceneItems.cpp
# Find Qt5 src/eventhandler/EventHandler_Scenes.cpp
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Svg Network) src/eventhandler/EventHandler_Transitions.cpp
src/eventhandler/EventHandler_Ui.cpp
src/eventhandler/types/EventSubscription.h)
# Find nlohmann
set(JSON_BuildTests OFF CACHE INTERNAL "") target_sources(
add_subdirectory(deps/json) obs-websocket
PRIVATE # cmake-format: sortable
src/requesthandler/RequestBatchHandler.cpp
# Configure files src/requesthandler/RequestBatchHandler.h
configure_file( src/requesthandler/RequestHandler.cpp
src/plugin-macros.h.in src/requesthandler/RequestHandler.h
../src/plugin-macros.generated.h src/requesthandler/RequestHandler_Config.cpp
) src/requesthandler/RequestHandler_Filters.cpp
configure_file( src/requesthandler/RequestHandler_General.cpp
installer/installer-windows.iss.in src/requesthandler/RequestHandler_Inputs.cpp
../installer/installer-windows.generated.iss src/requesthandler/RequestHandler_MediaInputs.cpp
) src/requesthandler/RequestHandler_Outputs.cpp
src/requesthandler/RequestHandler_Record.cpp
src/requesthandler/RequestHandler_SceneItems.cpp
# Inlude sources src/requesthandler/RequestHandler_Scenes.cpp
set(obs-websocket_SOURCES src/requesthandler/RequestHandler_Sources.cpp
src/obs-websocket.cpp src/requesthandler/RequestHandler_Stream.cpp
src/Config.cpp src/requesthandler/RequestHandler_Transitions.cpp
src/WebSocketApi.cpp src/requesthandler/RequestHandler_Ui.cpp
src/websocketserver/WebSocketServer.cpp src/requesthandler/rpc/Request.cpp
src/websocketserver/WebSocketServer_Protocol.cpp src/requesthandler/rpc/Request.h
src/websocketserver/rpc/WebSocketSession.cpp src/requesthandler/rpc/RequestBatchRequest.cpp
src/eventhandler/EventHandler.cpp src/requesthandler/rpc/RequestBatchRequest.h
src/eventhandler/EventHandler_General.cpp src/requesthandler/rpc/RequestResult.cpp
src/eventhandler/EventHandler_Config.cpp src/requesthandler/rpc/RequestResult.h
src/eventhandler/EventHandler_Scenes.cpp src/requesthandler/types/RequestBatchExecutionType.h
src/eventhandler/EventHandler_Inputs.cpp src/requesthandler/types/RequestStatus.h)
src/eventhandler/EventHandler_Transitions.cpp
src/eventhandler/EventHandler_Filters.cpp target_sources(
src/eventhandler/EventHandler_Outputs.cpp obs-websocket
src/eventhandler/EventHandler_SceneItems.cpp PRIVATE # cmake-format: sortable
src/eventhandler/EventHandler_MediaInputs.cpp src/utils/Compat.cpp
src/eventhandler/EventHandler_Ui.cpp src/utils/Compat.h
src/requesthandler/RequestHandler.cpp src/utils/Crypto.cpp
src/requesthandler/RequestBatchHandler.cpp src/utils/Crypto.h
src/requesthandler/RequestHandler_General.cpp src/utils/Json.cpp
src/requesthandler/RequestHandler_Config.cpp src/utils/Json.h
src/requesthandler/RequestHandler_Sources.cpp src/utils/Obs.cpp
src/requesthandler/RequestHandler_Scenes.cpp src/utils/Obs.h
src/requesthandler/RequestHandler_Inputs.cpp src/utils/Obs_ActionHelper.cpp
src/requesthandler/RequestHandler_Transitions.cpp src/utils/Obs_ArrayHelper.cpp
src/requesthandler/RequestHandler_Filters.cpp src/utils/Obs_NumberHelper.cpp
src/requesthandler/RequestHandler_SceneItems.cpp src/utils/Obs_ObjectHelper.cpp
src/requesthandler/RequestHandler_Outputs.cpp src/utils/Obs_SearchHelper.cpp
src/requesthandler/RequestHandler_Stream.cpp src/utils/Obs_StringHelper.cpp
src/requesthandler/RequestHandler_Record.cpp src/utils/Obs_VolumeMeter.cpp
src/requesthandler/RequestHandler_MediaInputs.cpp src/utils/Obs_VolumeMeter.h
src/requesthandler/RequestHandler_Ui.cpp src/utils/Obs_VolumeMeter_Helpers.h
src/requesthandler/rpc/Request.cpp src/utils/Platform.cpp
src/requesthandler/rpc/RequestBatchRequest.cpp src/utils/Platform.h
src/requesthandler/rpc/RequestResult.cpp src/utils/Utils.h)
src/forms/SettingsDialog.cpp
src/forms/ConnectInfo.cpp configure_file(src/plugin-macros.h.in plugin-macros.generated.h)
src/forms/resources.qrc target_sources(obs-websocket PRIVATE plugin-macros.generated.h)
src/utils/Crypto.cpp
src/utils/Json.cpp target_compile_definitions(
src/utils/Obs.cpp obs-websocket PRIVATE ASIO_STANDALONE $<$<BOOL:${PLUGIN_TESTS}>:PLUGIN_TESTS>
src/utils/Obs_StringHelper.cpp $<$<PLATFORM_ID:Windows>:_WEBSOCKETPP_CPP11_STL_> $<$<PLATFORM_ID:Windows>:_WIN32_WINNT=0x0603>)
src/utils/Obs_EnumHelper.cpp
src/utils/Obs_NumberHelper.cpp target_compile_options(
src/utils/Obs_ArrayHelper.cpp obs-websocket
src/utils/Obs_ObjectHelper.cpp PRIVATE $<$<PLATFORM_ID:Windows>:/wd4267>
src/utils/Obs_SearchHelper.cpp $<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-Wall>
src/utils/Obs_ActionHelper.cpp $<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-Wno-error=float-conversion>
src/utils/Obs_VolumeMeter.cpp $<$<COMPILE_LANG_AND_ID:CXX,GNU,AppleClang,Clang>:-Wno-error=shadow>
src/utils/Platform.cpp $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-error=format-overflow>
src/utils/Compat.cpp $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-error=int-conversion>
deps/qr/cpp/QrCode.cpp) $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-error=comment>
$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=null-pointer-subtraction>
set(obs-websocket_HEADERS $<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=deprecated-declarations>
src/obs-websocket.h $<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=implicit-int-conversion>
src/Config.h $<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=shorten-64-to-32>
src/WebSocketApi.h $<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-comma>
src/websocketserver/WebSocketServer.h $<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-quoted-include-in-framework-header>)
src/websocketserver/types/WebSocketCloseCode.h
src/websocketserver/types/WebSocketOpCode.h target_link_libraries(
src/websocketserver/rpc/WebSocketSession.h obs-websocket
src/eventhandler/EventHandler.h PRIVATE OBS::libobs
src/eventhandler/types/EventSubscription.h OBS::frontend-api
src/requesthandler/RequestHandler.h Qt::Core
src/requesthandler/RequestBatchHandler.h Qt::Widgets
src/requesthandler/types/RequestStatus.h Qt::Svg
src/requesthandler/types/RequestBatchExecutionType.h Qt::Network
src/requesthandler/rpc/Request.h nlohmann_json::nlohmann_json
src/requesthandler/rpc/RequestBatchRequest.h Websocketpp::Websocketpp
src/requesthandler/rpc/RequestResult.h Asio::Asio
src/forms/SettingsDialog.h qrcodegencpp::qrcodegencpp)
src/forms/ConnectInfo.h
src/utils/Crypto.h target_link_options(obs-websocket PRIVATE $<$<PLATFORM_ID:Windows>:/IGNORE:4099>)
src/utils/Json.h
src/utils/Obs.h set_target_properties_obs(
src/utils/Obs_VolumeMeter.h obs-websocket
src/utils/Obs_VolumeMeter_Helpers.h PROPERTIES FOLDER plugins
src/utils/Platform.h PREFIX ""
src/utils/Compat.h AUTOMOC ON
src/utils/Utils.h AUTOUIC ON
lib/obs-websocket-api.h AUTORCC ON)
deps/qr/cpp/QrCode.hpp)
if(OS_WINDOWS)
set_property(
# Platform-independent build settings TARGET obs-websocket
add_library(obs-websocket MODULE APPEND
${obs-websocket_SOURCES} PROPERTY AUTORCC_OPTIONS --format-version 1)
${obs-websocket_HEADERS})
include_directories(
"${LIBOBS_INCLUDE_DIR}/../UI/obs-frontend-api"
${Qt5Core_INCLUDES}
${Qt5Widgets_INCLUDES}
${Qt5Svg_INCLUDES}
${Qt5Network_INCLUDES}
"${CMAKE_SOURCE_DIR}/deps/asio/asio/include"
"${CMAKE_SOURCE_DIR}/deps/websocketpp")
target_link_libraries(obs-websocket
libobs
Qt5::Core
Qt5::Widgets
Qt5::Svg
Qt5::Network
nlohmann_json::nlohmann_json)
if(PLUGIN_TESTS)
target_compile_definitions(obs-websocket PRIVATE PLUGIN_TESTS)
endif()
# Windows-specific build settings and tasks
if(WIN32)
if(NOT DEFINED OBS_FRONTEND_LIB)
set(OBS_FRONTEND_LIB "OBS_FRONTEND_LIB-NOTFOUND" CACHE FILEPATH "OBS frontend library")
message(FATAL_ERROR "Could not find OBS Frontend API's library!")
endif()
if(MSVC)
# Enable Multicore Builds and disable FH4 (to not depend on VCRUNTIME140_1.DLL)
add_definitions(/MP /d2FH4-)
endif()
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ARCH_NAME "64bit")
set(OBS_BUILDDIR_ARCH "build64")
else()
set(ARCH_NAME "32bit")
set(OBS_BUILDDIR_ARCH "build32")
endif()
include_directories(
"${LIBOBS_INCLUDE_DIR}/../${OBS_BUILDDIR_ARCH}/UI"
)
target_link_libraries(obs-websocket
"${OBS_FRONTEND_LIB}")
# Release package helper
# The "release" folder has a structure similar OBS' one on Windows
set(RELEASE_DIR "${PROJECT_SOURCE_DIR}/release")
add_custom_command(TARGET obs-websocket POST_BUILD
# If config is Release or RelWithDebInfo, package release files
COMMAND if $<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>==1 (
"${CMAKE_COMMAND}" -E make_directory
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}"
)
COMMAND if $<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>==1 (
"${CMAKE_COMMAND}" -E copy_directory
"${PROJECT_SOURCE_DIR}/data"
"${RELEASE_DIR}/data/obs-plugins/obs-websocket"
)
COMMAND if $<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>==1 (
"${CMAKE_COMMAND}" -E copy
"$<TARGET_FILE:obs-websocket>"
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}"
)
# In Release or RelWithDebInfo mode, copy Qt image format plugins
COMMAND if $<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>==1 (
"${CMAKE_COMMAND}" -E make_directory
"${RELEASE_DIR}/bin/${ARCH_NAME}/imageformats"
)
COMMAND if $<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>==1 (
"${CMAKE_COMMAND}" -E copy
"${QTDIR}/plugins/imageformats/qicns.dll"
"${QTDIR}/plugins/imageformats/qico.dll"
"${QTDIR}/plugins/imageformats/qjpeg.dll"
"${QTDIR}/plugins/imageformats/qtiff.dll"
"${QTDIR}/plugins/imageformats/qwbmp.dll"
"${QTDIR}/plugins/imageformats/qwebp.dll"
"${RELEASE_DIR}/bin/${ARCH_NAME}/imageformats"
)
# If config is RelWithDebInfo, package PDB file for target
COMMAND if $<CONFIG:RelWithDebInfo>==1 (
"${CMAKE_COMMAND}" -E copy
"$<TARGET_PDB_FILE:obs-websocket>"
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}"
)
# In the Debug configuration, copy to obs-studio dev environment for immediate testing
COMMAND if $<CONFIG:Debug>==1 (
"${CMAKE_COMMAND}" -E copy
"$<TARGET_FILE:obs-websocket>"
"${LIBOBS_INCLUDE_DIR}/../${OBS_BUILDDIR_ARCH}/rundir/$<CONFIG>/obs-plugins/${ARCH_NAME}"
)
COMMAND if $<CONFIG:Debug>==1 (
"${CMAKE_COMMAND}" -E copy
"$<TARGET_PDB_FILE:obs-websocket>"
"${LIBOBS_INCLUDE_DIR}/../${OBS_BUILDDIR_ARCH}/rundir/$<CONFIG>/obs-plugins/${ARCH_NAME}"
)
COMMAND if $<CONFIG:Debug>==1 (
"${CMAKE_COMMAND}" -E make_directory
"${LIBOBS_INCLUDE_DIR}/../${OBS_BUILDDIR_ARCH}/rundir/$<CONFIG>/data/obs-plugins/obs-websocket"
)
COMMAND if $<CONFIG:Debug>==1 (
"${CMAKE_COMMAND}" -E copy_directory
"${PROJECT_SOURCE_DIR}/data"
"${LIBOBS_INCLUDE_DIR}/../${OBS_BUILDDIR_ARCH}/rundir/$<CONFIG>/data/obs-plugins/obs-websocket"
)
)
endif()
# Linux-specific build settings and tasks
if(UNIX AND NOT APPLE)
include(GNUInstallDirs)
target_compile_options(obs-websocket PRIVATE -Wall -Wextra -Wpedantic -Werror -Wno-missing-field-initializers)
set_target_properties(obs-websocket PROPERTIES PREFIX "")
target_link_libraries(obs-websocket obs-frontend-api)
# Manually set permissions for locales
file(GLOB locale_files data/locale/*.ini)
set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
# Manually set file permissions for binary
install(TARGETS obs-websocket LIBRARY
DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/obs-plugins"
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# OBS on Ubuntu installs into a different directory than most linux distros
if(${USE_UBUNTU_FIX})
install(TARGETS obs-websocket LIBRARY
DESTINATION "/usr/lib/obs-plugins"
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
endif()
install(FILES ${locale_files}
DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/obs/obs-plugins/obs-websocket/locale")
endif()
# MacOS-specific build settings and tasks
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fvisibility=default")
set(CMAKE_SKIP_RPATH TRUE)
set_target_properties(obs-websocket PROPERTIES PREFIX "")
target_link_libraries(obs-websocket "${OBS_FRONTEND_LIB}")
endif() endif()

View File

@ -8,17 +8,18 @@
WebSocket API for OBS Studio. WebSocket API for OBS Studio.
[![CI Multiplatform Build](https://github.com/obsproject/obs-websocket/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/obsproject/obs-websocket/actions/workflows/main.yml)
[![Discord](https://img.shields.io/discord/715691013825364120.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/WBaSQ3A) [![Discord](https://img.shields.io/discord/715691013825364120.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/WBaSQ3A)
[![Financial Contributors on Open Collective](https://opencollective.com/obs-websocket-dev/all/badge.svg?label=financial+contributors)](https://opencollective.com/obs-websocket-dev) [![Financial Contributors on Open Collective](https://opencollective.com/obs-websocket-dev/all/badge.svg?label=financial+contributors)](https://opencollective.com/obs-websocket-dev)
## Downloads ## Downloads
Binaries for Windows, MacOS, and Linux are available in the [Releases](https://github.com/obsproject/obs-websocket/releases) section. **obs-websocket is now included by default with OBS Studio 28.0.0 and above. As such, there should be no need to download obs-websocket if you have OBS Studio > 28.0.0.**
Binaries **for OBS Studio < 28.0.0** on Windows, MacOS, and Linux are available in the [Releases](https://github.com/obsproject/obs-websocket/releases) section.
## Using obs-websocket ## Using obs-websocket
It is **highly recommended** to protect obs-websocket with a password against unauthorized control. To do this, open the "Websocket server settings" dialog under OBS' "Tools" menu. In the settings dialogs, you can enable or disable authentication and set a password for it. It is **highly recommended** to keep obs-websocket protected with a password against unauthorized control. obs-websocket generates a password for you automatically when you load it for the first time. To change this, open the "obs-websocket Settings" dialog under OBS' "Tools" menu. In the settings dialog, you can enable or disable authentication and set a password for it.
(Psst. You can use `--websocket_port`(value), `--websocket_password`(value), `--websocket_debug`(flag) and `--websocket_ipv4_only`(flag) on the command line to override the configured values.) (Psst. You can use `--websocket_port`(value), `--websocket_password`(value), `--websocket_debug`(flag) and `--websocket_ipv4_only`(flag) on the command line to override the configured values.)
@ -30,16 +31,32 @@ It is **highly recommended** to protect obs-websocket with a password against un
### Client software ### Client software
- (No known clients supporting 5.0.0 at the moment. Ping us in the Discord if you have one!) - [Macro Deck](https://macrodeck.org/)
- [Touch Portal](https://www.touch-portal.com/)
- [Twitchat](https://twitchat.fr/)
- [OBS-web](https://github.com/Niek/obs-web) - hosted client at [obs-web.niek.tv/](http://obs-web.niek.tv/)
- [Streamer.bot](https://streamer.bot/)
- [Deckboard](https://deckboard.app/)
- [OBS Blade](https://github.com/Kounex/obs_blade)
- [Aitum](https://aitum.tv/)
- [Kruiz Control](https://github.com/Kruiser8/Kruiz-Control)
- [Bitfocus Companion Module](https://bitfocus.io/companion/)
- [MacroGraph](https://github.com/Brendonovich/macrograph) - hosted client [here](https://macrograph.brendonovich.dev/)
- [MATRIC](https://matricapp.com/)
### Client libraries (for developers) ### Client libraries (for developers)
Here's a list of available language APIs for obs-websocket: Here's a list of available language APIs for obs-websocket:
- Python 3.7+ (Asyncio): [simpleobsws](https://github.com/IRLToolkit/simpleobsws/tree/master) by IRLToolkit - Python 3.7+ (Asyncio): [simpleobsws](https://github.com/IRLToolkit/simpleobsws/tree/master) by IRLToolkit
- Rust: [obws](https://github.com/dnaka91/obws/tree/v5-api) by dnaka91 - Python 3.10+ (Non-Asyncio): [obsws-python](https://pypi.org/project/obsws-python) by aatikturk and onyx-and-iris
- Godot 3.4.x: [obs-websocket-gd](https://github.com/you-win/obs-websocket-gd) by you-win - Rust: [obws](https://github.com/dnaka91/obws) by dnaka91
- Godot 4.0.x: [obs-websocket-gd](https://github.com/you-win/obs-websocket-gd) by you-win
- Javascript (Node and web): [obs-websocket-js](https://github.com/obs-websocket-community-projects/obs-websocket-js) by OBS Websocket Community - Javascript (Node and web): [obs-websocket-js](https://github.com/obs-websocket-community-projects/obs-websocket-js) by OBS Websocket Community
- C (uses obs-websocket-js): [v8-libwebsocket-obs-websocket](https://github.com/dgatwood/v8-libwebsocket-obs-websocket)
- Go: [goobs](https://github.com/andreykaipov/goobs) by andreykaipov
- Dart/Flutter (can target all supported platforms): [obs_websocket](https://github.com/faithoflifedev/obs_websocket) by faithoflifedev
- Java: [obs-websocket-java](https://github.com/obs-websocket-community-projects/obs-websocket-java) by OBS Websocket Community
The 5.x server is a typical WebSocket server running by default on port 4455 (the port number can be changed in the Settings dialog under `Tools`). The 5.x server is a typical WebSocket server running by default on port 4455 (the port number can be changed in the Settings dialog under `Tools`).
The protocol we use is documented in [PROTOCOL.md](docs/generated/protocol.md). The protocol we use is documented in [PROTOCOL.md](docs/generated/protocol.md).
@ -50,12 +67,11 @@ We'd like to know what you're building with obs-websocket! If you do something i
### Code Contributors ### Code Contributors
This project exists thanks to [all the people](graphs/contributors) who contribute. [Contribute](wiki/Contributing-Guidelines). This project exists thanks to [all the people](https://github.com/obsproject/obs-websocket/graphs/contributors) who contribute. [Contribute Code](https://github.com/obsproject/obs-websocket/wiki/Contributing-Guidelines).
<a href="https://github.com/obsproject/obs-websocket/graphs/contributors"><img src="https://opencollective.com/obs-websocket-dev/contributors.svg?width=890&button=false" /></a>
### Financial Contributors ### Financial Contributors
Become a financial contributor and help us sustain our community. [Contribute](https://opencollective.com/obs-websocket-dev/contribute) Become a financial contributor and help us sustain our community. [Contribute Financially](https://opencollective.com/obs-websocket-dev/contribute)
#### Individuals #### Individuals

View File

@ -1,107 +0,0 @@
# This module can be copied and used by external plugins for OBS
#
# Once done these will be defined:
#
# LIBOBS_FOUND
# LIBOBS_INCLUDE_DIRS
# LIBOBS_LIBRARIES
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_OBS QUIET obs libobs)
endif()
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_lib_suffix 64)
else()
set(_lib_suffix 32)
endif()
if(DEFINED CMAKE_BUILD_TYPE)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(_build_type_base "debug")
else()
set(_build_type_base "release")
endif()
endif()
find_path(LIBOBS_INCLUDE_DIR
NAMES obs.h
HINTS
ENV obsPath${_lib_suffix}
ENV obsPath
${obsPath}
PATHS
/usr/include /usr/local/include /opt/local/include /sw/include
PATH_SUFFIXES
libobs
)
function(find_obs_lib base_name repo_build_path lib_name)
string(TOUPPER "${base_name}" base_name_u)
if(DEFINED _build_type_base)
set(_build_type_${repo_build_path} "${_build_type_base}/${repo_build_path}")
set(_build_type_${repo_build_path}${_lib_suffix} "${_build_type_base}${_lib_suffix}/${repo_build_path}")
endif()
find_library(${base_name_u}_LIB
NAMES ${_${base_name_u}_LIBRARIES} ${lib_name} lib${lib_name}
HINTS
ENV obsPath${_lib_suffix}
ENV obsPath
${obsPath}
${_${base_name_u}_LIBRARY_DIRS}
PATHS
/usr/lib /usr/local/lib /opt/local/lib /sw/lib
PATH_SUFFIXES
lib${_lib_suffix} lib
libs${_lib_suffix} libs
bin${_lib_suffix} bin
../lib${_lib_suffix} ../lib
../libs${_lib_suffix} ../libs
../bin${_lib_suffix} ../bin
# base repo non-msvc-specific search paths
${_build_type_${repo_build_path}}
${_build_type_${repo_build_path}${_lib_suffix}}
build/${repo_build_path}
build${_lib_suffix}/${repo_build_path}
# base repo msvc-specific search paths on windows
build${_lib_suffix}/${repo_build_path}/Debug
build${_lib_suffix}/${repo_build_path}/RelWithDebInfo
build/${repo_build_path}/Debug
build/${repo_build_path}/RelWithDebInfo
)
endfunction()
find_obs_lib(LIBOBS libobs obs)
if(MSVC)
find_obs_lib(W32_PTHREADS deps/w32-pthreads w32-pthreads)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libobs DEFAULT_MSG LIBOBS_LIB LIBOBS_INCLUDE_DIR)
mark_as_advanced(LIBOBS_INCLUDE_DIR LIBOBS_LIB)
if(LIBOBS_FOUND)
if(MSVC)
if (NOT DEFINED W32_PTHREADS_LIB)
message(FATAL_ERROR "Could not find the w32-pthreads library" )
endif()
set(W32_PTHREADS_INCLUDE_DIR ${LIBOBS_INCLUDE_DIR}/../deps/w32-pthreads)
endif()
set(LIBOBS_INCLUDE_DIRS ${LIBOBS_INCLUDE_DIR} ${W32_PTHREADS_INCLUDE_DIR})
set(LIBOBS_LIBRARIES ${LIBOBS_LIB} ${W32_PTHREADS_LIB})
include(${LIBOBS_INCLUDE_DIR}/../cmake/external/ObsPluginHelpers.cmake)
# allows external plugins to easily use/share common dependencies that are often included with libobs (such as FFmpeg)
if(NOT DEFINED INCLUDED_LIBOBS_CMAKE_MODULES)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LIBOBS_INCLUDE_DIR}/../cmake/Modules/")
set(INCLUDED_LIBOBS_CMAKE_MODULES true)
endif()
else()
message(FATAL_ERROR "Could not find the libobs library" )
endif()

173
cmake/legacy.cmake Normal file
View File

@ -0,0 +1,173 @@
project(obs-websocket VERSION 5.4.1)
set(OBS_WEBSOCKET_RPC_VERSION 1)
option(ENABLE_WEBSOCKET "Enable building OBS with websocket plugin" ON)
if(NOT ENABLE_WEBSOCKET OR NOT ENABLE_UI)
message(STATUS "OBS: DISABLED obs-websocket")
return()
endif()
# Plugin tests flag
option(PLUGIN_TESTS "Enable plugin runtime tests" OFF)
# Find Qt
find_qt(COMPONENTS Core Widgets Svg Network)
# Find nlohmann JSON
find_package(nlohmann_json 3 REQUIRED)
# Find qrcodegencpp
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
find_package(qrcodegencpp REQUIRED)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF)
# Find WebSocket++
find_package(Websocketpp 0.8 REQUIRED)
# Find Asio
find_package(Asio 1.12.1 REQUIRED)
# Tell websocketpp not to use system boost
add_definitions(-DASIO_STANDALONE)
# Configure files
configure_file(src/plugin-macros.h.in plugin-macros.generated.h)
# Setup target
add_library(obs-websocket MODULE)
add_library(OBS::websocket ALIAS obs-websocket)
set_target_properties(
obs-websocket
PROPERTIES AUTOMOC ON
AUTOUIC ON
AUTORCC ON)
if(_QT_VERSION EQUAL 6 AND OS_WINDOWS)
set_target_properties(obs-websocket PROPERTIES AUTORCC_OPTIONS "--format-version;1")
endif()
target_include_directories(obs-websocket PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_sources(
obs-websocket
PRIVATE src/obs-websocket.cpp
src/obs-websocket.h
src/Config.cpp
src/Config.h
lib/obs-websocket-api.h
src/forms/SettingsDialog.cpp
src/forms/SettingsDialog.h
src/forms/ConnectInfo.cpp
src/forms/ConnectInfo.h
src/forms/resources.qrc
src/WebSocketApi.cpp
src/WebSocketApi.h
src/websocketserver/WebSocketServer.cpp
src/websocketserver/WebSocketServer_Protocol.cpp
src/websocketserver/WebSocketServer.h
src/websocketserver/rpc/WebSocketSession.h
src/websocketserver/types/WebSocketCloseCode.h
src/websocketserver/types/WebSocketOpCode.h
src/eventhandler/EventHandler.cpp
src/eventhandler/EventHandler_General.cpp
src/eventhandler/EventHandler_Config.cpp
src/eventhandler/EventHandler_Scenes.cpp
src/eventhandler/EventHandler_Inputs.cpp
src/eventhandler/EventHandler_Transitions.cpp
src/eventhandler/EventHandler_Filters.cpp
src/eventhandler/EventHandler_Outputs.cpp
src/eventhandler/EventHandler_SceneItems.cpp
src/eventhandler/EventHandler_MediaInputs.cpp
src/eventhandler/EventHandler_Ui.cpp
src/eventhandler/EventHandler.h
src/eventhandler/types/EventSubscription.h
src/requesthandler/RequestHandler.cpp
src/requesthandler/RequestHandler_General.cpp
src/requesthandler/RequestHandler_Config.cpp
src/requesthandler/RequestHandler_Sources.cpp
src/requesthandler/RequestHandler_Scenes.cpp
src/requesthandler/RequestHandler_Inputs.cpp
src/requesthandler/RequestHandler_Transitions.cpp
src/requesthandler/RequestHandler_Filters.cpp
src/requesthandler/RequestHandler_SceneItems.cpp
src/requesthandler/RequestHandler_Outputs.cpp
src/requesthandler/RequestHandler_Stream.cpp
src/requesthandler/RequestHandler_Record.cpp
src/requesthandler/RequestHandler_MediaInputs.cpp
src/requesthandler/RequestHandler_Ui.cpp
src/requesthandler/RequestHandler.h
src/requesthandler/RequestBatchHandler.cpp
src/requesthandler/RequestBatchHandler.h
src/requesthandler/rpc/Request.cpp
src/requesthandler/rpc/Request.h
src/requesthandler/rpc/RequestBatchRequest.cpp
src/requesthandler/rpc/RequestBatchRequest.h
src/requesthandler/rpc/RequestResult.cpp
src/requesthandler/rpc/RequestResult.h
src/requesthandler/types/RequestStatus.h
src/requesthandler/types/RequestBatchExecutionType.h
src/utils/Crypto.cpp
src/utils/Crypto.h
src/utils/Json.cpp
src/utils/Json.h
src/utils/Obs.cpp
src/utils/Obs_StringHelper.cpp
src/utils/Obs_NumberHelper.cpp
src/utils/Obs_ArrayHelper.cpp
src/utils/Obs_ObjectHelper.cpp
src/utils/Obs_SearchHelper.cpp
src/utils/Obs_ActionHelper.cpp
src/utils/Obs.h
src/utils/Obs_VolumeMeter.cpp
src/utils/Obs_VolumeMeter.h
src/utils/Obs_VolumeMeter_Helpers.h
src/utils/Platform.cpp
src/utils/Platform.h
src/utils/Compat.cpp
src/utils/Compat.h
src/utils/Utils.h)
target_link_libraries(
obs-websocket
PRIVATE OBS::libobs
OBS::frontend-api
Qt::Core
Qt::Widgets
Qt::Svg
Qt::Network
nlohmann_json::nlohmann_json
Websocketpp::Websocketpp
Asio::Asio
qrcodegencpp::qrcodegencpp)
target_compile_features(obs-websocket PRIVATE cxx_std_17)
set_target_properties(obs-websocket PROPERTIES FOLDER "plugins/obs-websocket")
if(PLUGIN_TESTS)
target_compile_definitions(obs-websocket PRIVATE PLUGIN_TESTS)
endif()
# Random other things
if(WIN32)
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
endif()
if(MSVC)
target_compile_options(obs-websocket PRIVATE /wd4267 /wd4996)
target_link_options(obs-websocket PRIVATE "LINKER:/IGNORE:4099")
else()
target_compile_options(
obs-websocket
PRIVATE
-Wall
"$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-error=format-overflow>"
"$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=null-pointer-subtraction;-Wno-error=deprecated-declarations>"
)
endif()
# Final CMake helpers
setup_plugin_target(obs-websocket)
setup_target_resources(obs-websocket "obs-plugins/obs-websocket")

28
cmake/macos/Info.plist.in Normal file
View File

@ -0,0 +1,28 @@
<?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>obs-websocket</string>
<key>CFBundleIdentifier</key>
<string>com.obsproject.obs-websocket</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleExecutable</key>
<string>obs-websocket</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>LSMinimumSystemVersion</key>
<string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>(c) 2016-${CURRENT_YEAR} Stéphane Lepin, Kyle Manning</string>
</dict>
</plist>

35
data/locale/af-ZA.ini Normal file
View File

@ -0,0 +1,35 @@
OBSWebSocket.Plugin.Description="Afstandbeheer van OBS deur WebSocket"
OBSWebSocket.Settings.DialogTitle="WebSocket-bedienerinstellings"
OBSWebSocket.Settings.PluginSettingsTitle="Inpropinstellings"
OBSWebSocket.Settings.ServerEnable="Aktiveer WebSocket-diens"
OBSWebSocket.Settings.ServerSettingsTitle="Bedienerinstellings"
OBSWebSocket.Settings.Password="Bedienerwagwoord"
OBSWebSocket.Settings.GeneratePassword="Genereer wagwoord"
OBSWebSocket.Settings.ServerPort="Bedienerpoort"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Waarskuwing: Tans regstreeks"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Dit lyk of n afvoer (stroom, opname, ens.) tans aktief is."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Is u seker u wil u verbindingsinligting laat sien?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Waarskuwing: potensiële beveiligingsprobleem"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websok bewaar die bedienerwagwoord as platteks. Dit word ten sterkste aanbeveel om n wagwoord wat deur obs-websok geskep is te gebruik."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Is u seker u wil u eie wagwoord gebruik?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Fout: Ongeldige opstalling"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="U moet n wagwoord van meet as 6 karakters gebruik."
OBSWebSocket.SessionTable.Title="Gekoppelde WebSocket-sessies"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Afstandsadres"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Sessieduur"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Boodskappe In/Uit"
OBSWebSocket.SessionTable.IdentifiedTitle="Geïdentifiseer"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Verwyder?"
OBSWebSocket.SessionTable.KickButtonText="Verwyder"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-verbindingsinligting"
OBSWebSocket.ConnectInfo.CopyText="Kopieer"
OBSWebSocket.ConnectInfo.ServerIp="Bediener-IP (beste skatting)"
OBSWebSocket.ConnectInfo.ServerPort="Bedienerpoort"
OBSWebSocket.ConnectInfo.ServerPassword="Bedienerwagwoord"
OBSWebSocket.ConnectInfo.QrTitle="Koppel QR"
OBSWebSocket.TrayNotification.Identified.Title="Nuwe WebSocket-koppeling"
OBSWebSocket.TrayNotification.Identified.Body="Kliënt %1 geïdentifiseer."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket-waarmerkfout"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Kliënt %1 kon nie waarmerk nie."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket-kliënt is ontkoppel"
OBSWebSocket.TrayNotification.Disconnected.Body="Kliënt %1 is ontkoppel."

41
data/locale/ar-SA.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="التحكم عن بعد في استوديو OBS من خلال WebSocket"
OBSWebSocket.Settings.DialogTitle="إعدادات خادم WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="إعدادات الإضافات"
OBSWebSocket.Settings.ServerEnable="تمكين خادم WebSocket"
OBSWebSocket.Settings.AlertsEnable="تمكين تنبيهات شريط النظام"
OBSWebSocket.Settings.DebugEnable="تمكين سجلات التصحيح"
OBSWebSocket.Settings.DebugEnableHoverText="تمكين تسجيل التصحيح للجلسة الحالية لـ OBS. لا تستمر عند اعادة الفتح.\nاستخدم --websocket_debug للتفعيل عند فتح البرنامج."
OBSWebSocket.Settings.ServerSettingsTitle="إعدادات الخادم"
OBSWebSocket.Settings.AuthRequired="تمكين المصادقة"
OBSWebSocket.Settings.Password="كلمة مرور الخادم"
OBSWebSocket.Settings.GeneratePassword="إنشاء كلمة مرور"
OBSWebSocket.Settings.ServerPort="منفذ الخادم"
OBSWebSocket.Settings.ShowConnectInfo="إظهار معلومات الاتصال"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="تحذير: البث المباشر جاري"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="يبدو أن المخرجات (البث والتسجيل الخ) نشطة حاليا."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="هل أنت متأكد من أنك تريد إظهار معلومات الاتصال الخاصة بك؟"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="تحذير: مشكلة أمان محتملة"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="يخزن obs-websocket كلمة مرور الخادم كنص عادي. يوصى بشدة استخدام كلمة المرور التي تم إنشاؤها من قبل obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="هل أنت متأكد من أنك تريد استخدام كلمة المرور الخاصة بك؟"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="خطأ:إعدادات غير صالحة"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="يجب عليك استخدام كلمة مرور تتكون من 6 أحرف أو أكثر."
OBSWebSocket.SessionTable.Title="جلسات WebSocket متصلة"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="العنوان البعيد"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="مدة الجلسة"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="الرسائل الداخلة/الخارجة"
OBSWebSocket.SessionTable.IdentifiedTitle="المعرِّف"
OBSWebSocket.SessionTable.KickButtonColumnTitle="طرد؟"
OBSWebSocket.SessionTable.KickButtonText="طرد"
OBSWebSocket.ConnectInfo.DialogTitle="معلومات اتصال WebSocket"
OBSWebSocket.ConnectInfo.CopyText="نسخ"
OBSWebSocket.ConnectInfo.ServerIp="عنوان IP الخادم (أفضل تخمين)"
OBSWebSocket.ConnectInfo.ServerPort="منفذ الخادم"
OBSWebSocket.ConnectInfo.ServerPassword="كلمة مرور الخادم"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[تم تعطيل المصادقة]"
OBSWebSocket.ConnectInfo.QrTitle="QR الاتصال"
OBSWebSocket.TrayNotification.Identified.Title="اتصال WebSocket جديد"
OBSWebSocket.TrayNotification.Identified.Body="تم تحديد العميل %1."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="فشل مصادقة WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="فشل العميل %1 في المصادقة."
OBSWebSocket.TrayNotification.Disconnected.Title="تم قطع اتصال عميل WebSocket"
OBSWebSocket.TrayNotification.Disconnected.Body="العميل %1 قطع الاتصال."

41
data/locale/ca-ES.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Control remot de l'OBS Studio mitjançant WebSocket"
OBSWebSocket.Settings.DialogTitle="Configuració del servidor WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Configuració del complement"
OBSWebSocket.Settings.ServerEnable="Habilita el servidor WebSocket"
OBSWebSocket.Settings.AlertsEnable="Habilita les notificacions a la barra de tasques"
OBSWebSocket.Settings.DebugEnable="Habilita l'informe de depuració"
OBSWebSocket.Settings.DebugEnableHoverText="Habilita l'informe de depuració només per a la instància actual de l'OBS. No persisteix en inicis posteriors.\nUtilitzeu --websocket_debug si us cal que el canvi sigui persistent."
OBSWebSocket.Settings.ServerSettingsTitle="Configuració del servidor"
OBSWebSocket.Settings.AuthRequired="Habilita l'autenticació"
OBSWebSocket.Settings.Password="Contrasenya del servidor"
OBSWebSocket.Settings.GeneratePassword="Genera una contrasenya"
OBSWebSocket.Settings.ServerPort="Port del servidor"
OBSWebSocket.Settings.ShowConnectInfo="Mostra la informació de connexió"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Atenció: Actualment en directe"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Sembla que una sortida (retransmissió, gravació, etc.) està actualment activa."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Segur que voleu mostrar la vostra informació de connexió?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Atenció: Risc potencial de seguretat"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket emmagatzema la contrasenya del servidor com a text pla. És altament recomanable l'ús d'una contrasenya generada automàticament."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Segur que voleu utilitzar la vostra contrasenya?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Error: Configuració no vàlida"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Utilitzeu una contrasenya de 6 o més caràcters."
OBSWebSocket.SessionTable.Title="Sessions de WebSocket connectades"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adreça remota"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Durada de la sessió"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Missatges d'entrada/sortida"
OBSWebSocket.SessionTable.IdentifiedTitle="Identificat"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Expulsar?"
OBSWebSocket.SessionTable.KickButtonText="Expulsa"
OBSWebSocket.ConnectInfo.DialogTitle="Informació de connexió del servidor WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Copia"
OBSWebSocket.ConnectInfo.ServerIp="Adreça IP (més acurada)"
OBSWebSocket.ConnectInfo.ServerPort="Port"
OBSWebSocket.ConnectInfo.ServerPassword="Contrasenya"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autenticació inhabilitada]"
OBSWebSocket.ConnectInfo.QrTitle="QR de la connexió"
OBSWebSocket.TrayNotification.Identified.Title="Connexió nova de WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Client %1 identificat."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Ha fallat l'autenticació del servidor WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Ha fallat l'autenticació del client %1."
OBSWebSocket.TrayNotification.Disconnected.Title="Client desconnectat del servidor WebSocket"
OBSWebSocket.TrayNotification.Disconnected.Body="Client %1 desconnectat."

41
data/locale/cs-CZ.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Vzdálené ovládání OBS Studia přes WebSocket"
OBSWebSocket.Settings.DialogTitle="Nastavení WebSocket serveru"
OBSWebSocket.Settings.PluginSettingsTitle="Nastavení pluginu"
OBSWebSocket.Settings.ServerEnable="Povolit WebSocketový server"
OBSWebSocket.Settings.AlertsEnable="Povolit upozornění v systémové liště"
OBSWebSocket.Settings.DebugEnable="Povolit podrobné protokolování"
OBSWebSocket.Settings.DebugEnableHoverText="Zapne podrobné protokolování pro aktuální instanci OBS. Nastavení není zachováno mezi spuštěními.\nPoužijte --websocket_debug pro povlení při spuštění."
OBSWebSocket.Settings.ServerSettingsTitle="Nastavení serveru"
OBSWebSocket.Settings.AuthRequired="Povolit přihlašování"
OBSWebSocket.Settings.Password="Heslo serveru"
OBSWebSocket.Settings.GeneratePassword="Vygenerovat heslo"
OBSWebSocket.Settings.ServerPort="Port serveru"
OBSWebSocket.Settings.ShowConnectInfo="Zobrazit info o připojení"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Varování: Aktuálně vysíláte"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Vypadá to, že výstup (vysílání, nahrávání etc.) je právě aktivní."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Opravdu si přejete zobrazit údaje k připojení?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Varování: Potencionální bezpečnostní problém"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket ukládá heslo jako prostý text. Důrazně doporučujeme použití hesla generovaného pomocí obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Opravdu si přejete použít vaše vlastní heslo?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Chyba: Neplatná konfigurace"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Musíte použít heslo o délce nejméně 6 znaků."
OBSWebSocket.SessionTable.Title="Připojené relace WebSocketu"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Vzdálená adresa"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Délka relace"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Zprávy do/z"
OBSWebSocket.SessionTable.IdentifiedTitle="Identifikované"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Vykopnout?"
OBSWebSocket.SessionTable.KickButtonText="Vykopnout"
OBSWebSocket.ConnectInfo.DialogTitle="Připojení k WebSocket serveru"
OBSWebSocket.ConnectInfo.CopyText="Kopírovat"
OBSWebSocket.ConnectInfo.ServerIp="IP adresa serveru (nejlepší odhad)"
OBSWebSocket.ConnectInfo.ServerPort="Port serveru"
OBSWebSocket.ConnectInfo.ServerPassword="Heslo serveru"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Přihlášení zakázáno]"
OBSWebSocket.ConnectInfo.QrTitle="QR pro připojení"
OBSWebSocket.TrayNotification.Identified.Title="Nové WebSocket připojení"
OBSWebSocket.TrayNotification.Identified.Body="Klient %1 identifikován."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Chyba přihlášení k WebSocketu"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Klient %1 nebyl přihlášen"
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket klient se odpojil"
OBSWebSocket.TrayNotification.Disconnected.Body="Klient %1 se odpojil."

41
data/locale/da-DK.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Fjernstyring af OBS Studio via WebSocket"
OBSWebSocket.Settings.DialogTitle="WebSocket-serverindstillinger"
OBSWebSocket.Settings.PluginSettingsTitle="Plugin-indstillinger"
OBSWebSocket.Settings.ServerEnable="Aktivér WebSocket-server"
OBSWebSocket.Settings.AlertsEnable="Aktivér Systembakke Alarmer"
OBSWebSocket.Settings.DebugEnable="Aktivér Fejlfindingslogning"
OBSWebSocket.Settings.DebugEnableHoverText="Aktivér fejlfindingslogning for den aktuelle forekomst af OBS. Vedvarer ikke ved indlæsning.\nBrug --websocket_debug til at aktivere ved indlæsning."
OBSWebSocket.Settings.ServerSettingsTitle="Serverindstillinger"
OBSWebSocket.Settings.AuthRequired="Aktivér godkendelse"
OBSWebSocket.Settings.Password="Serveradgangskode"
OBSWebSocket.Settings.GeneratePassword="Generér adgangskode"
OBSWebSocket.Settings.ServerPort="Serverport"
OBSWebSocket.Settings.ShowConnectInfo="Vis forbindelsesinfo"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Advarsel: Live i øjeblikket"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Det ser ud til, at et output (stream, optagelse mv.) pt. er aktiv."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Sikker på, at din forbindelsesinfo skal vises?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Advarsel: Potentielt sikkerhedsproblem"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket gemmer serverens adgangskode som alm. tekst. Det anbefales kraftigt at bruge en adgangskode genereret af obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Sikker på, at din egen adgangskoder skal bruges?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Fejl: Ugyldig opsætning"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="En adgangskode på mindst 6 tegn skal bruges."
OBSWebSocket.SessionTable.Title="Forbundne WebSocket-sessioner"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Fjernadresse"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Sessionsvarighed"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Beskeder Ind/Ud"
OBSWebSocket.SessionTable.IdentifiedTitle="Identificeret"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Fjern?"
OBSWebSocket.SessionTable.KickButtonText="Fjern"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-forbindelsesinfo"
OBSWebSocket.ConnectInfo.CopyText="Kopiér"
OBSWebSocket.ConnectInfo.ServerIp="Server-IP (bedste gæt)"
OBSWebSocket.ConnectInfo.ServerPort="Serverport"
OBSWebSocket.ConnectInfo.ServerPassword="Serveradgangskode"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Godk. deaktiveret]"
OBSWebSocket.ConnectInfo.QrTitle="Forbindelses-QR"
OBSWebSocket.TrayNotification.Identified.Title="Ny WebSocket-forbindelse"
OBSWebSocket.TrayNotification.Identified.Body="Klient %1 identificeret."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket godkendelsesfejl"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Klienten %1 kunne ikke godkendes."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket-klient frakoblet"
OBSWebSocket.TrayNotification.Disconnected.Body="Klient %1 frakoblet."

41
data/locale/de-DE.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="OBS Studio per WebSocket fernsteuern"
OBSWebSocket.Settings.DialogTitle="WebSocket-Servereinstellungen"
OBSWebSocket.Settings.PluginSettingsTitle="Plugineinstellungen"
OBSWebSocket.Settings.ServerEnable="WebSocket-Server aktivieren"
OBSWebSocket.Settings.AlertsEnable="Warnungen im Infobereich aktivieren"
OBSWebSocket.Settings.DebugEnable="Debug-Logging aktivieren"
OBSWebSocket.Settings.DebugEnableHoverText="Aktiviert Debug-Logging für die aktuelle OBS-Instanz.\nVerwenden Sie „--websocket_debug“, damit die Option beim Starten aktiviert wird."
OBSWebSocket.Settings.ServerSettingsTitle="Servereinstellungen"
OBSWebSocket.Settings.AuthRequired="Authentifizierung aktivieren"
OBSWebSocket.Settings.Password="Serverpasswort"
OBSWebSocket.Settings.GeneratePassword="Passwort generieren"
OBSWebSocket.Settings.ServerPort="Serverport"
OBSWebSocket.Settings.ShowConnectInfo="Verbindungsinformationen anzeigen"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Achtung: Zurzeit live"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Derzeit ist eine Ausgabe (Stream, Aufnahme, etc.) aktiv."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Möchten Sie wirklich Ihre Verbindungsinformationen anzeigen?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Achtung: Mögliches Sicherheitsproblem"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket speichert das Serverpasswort unverschlüsselt, daher ist ein von obs-websocket generiertes Passwort sehr zu empfehlen."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Möchten Sie wirklich ein eigenes Passwort verwenden?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Fehler: Ungültige Konfiguration"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Sie müssen ein Passwort mit mindestens 6 Zeichen verwenden."
OBSWebSocket.SessionTable.Title="Verbundene WebSocket-Sitzungen"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Remote-Adresse"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Sitzungsdauer"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Nachrichten rein/raus"
OBSWebSocket.SessionTable.IdentifiedTitle="Identifiziert"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Entfernen?"
OBSWebSocket.SessionTable.KickButtonText="Entfernen"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-Verbindungsinformationen"
OBSWebSocket.ConnectInfo.CopyText="Kopieren"
OBSWebSocket.ConnectInfo.ServerIp="Server-IP (Geschätzt)"
OBSWebSocket.ConnectInfo.ServerPort="Serverport"
OBSWebSocket.ConnectInfo.ServerPassword="Serverpasswort"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="Authentifizierung deaktiviert"
OBSWebSocket.ConnectInfo.QrTitle="QR-Code zum Verbinden"
OBSWebSocket.TrayNotification.Identified.Title="Neue WebSocket-Verbindung"
OBSWebSocket.TrayNotification.Identified.Body="Client %1 identifiziert."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket-Authentifizierungsfehler"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Client %1 konnte sich nicht authentifizieren."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket-Client getrennt"
OBSWebSocket.TrayNotification.Disconnected.Body="Client %1 getrennt."

41
data/locale/el-GR.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Απομακρυσμένος έλεγχος του OBS Studio μέσω WebSocket"
OBSWebSocket.Settings.DialogTitle="Ρυθμίσεις Διακομιστή WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Ρυθμίσεις Προσθέτων"
OBSWebSocket.Settings.ServerEnable="Ενεργοποίηση διακομιστή WebSocket"
OBSWebSocket.Settings.AlertsEnable="Ενεργοποίηση Ειδοποιήσεων στο System Tray"
OBSWebSocket.Settings.DebugEnable="Ενεργοποίηση καταγραφής σφαλμάτων"
OBSWebSocket.Settings.DebugEnableHoverText="Ενεργοποιεί την καταγραφή σφαλμάτων για την τρέχουσα εικόνα του OBS. Δεν επιμένει κατά τη φόρτωση.\nΧρησιμοποίησε το --websocket_debug για να ενεργοποιηθεί κατά τη φόρτωση."
OBSWebSocket.Settings.ServerSettingsTitle="Ρυθμίσεις Διακομιστή"
OBSWebSocket.Settings.AuthRequired="Ενεργοποίηση Επαλήθευσης Στοιχείων"
OBSWebSocket.Settings.Password="Κωδικός Διακομιστή"
OBSWebSocket.Settings.GeneratePassword="Δημιουργία Κωδικού"
OBSWebSocket.Settings.ServerPort="Θύρα Διακομιστή"
OBSWebSocket.Settings.ShowConnectInfo="Εμφάνιση Πληροφοριών Σύνδεσης"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Προειδοποίηση: Ενεργό επί του Παρόντος"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Φαίνεται ότι μια έξοδος (ροή, εγγραφή, κλπ.) είναι ενεργή αυτή τη στιγμή."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Είστε βέβαιοι ότι θέλετε να εμφανιστούν οι πληροφορίες σύνδεσης σας?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Προειδοποίηση: Πιθανό Πρόβλημα Ασφαλείας"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="Το obs-websocket αποθηκεύει τον κωδικό πρόσβασης του διακομιστή ως απλό κείμενο. Χρησιμοποιώντας έναν κωδικό πρόσβασης που δημιουργείται από το obs-websocket συνιστάται ιδιαίτερα."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Είστε βέβαιοι ότι θέλετε να χρησιμοποιήσετε το δικό σας κωδικό πρόσβασης?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Σφάλμα: Μη Έγκυρη Ρύθμιση"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Πρέπει να χρησιμοποιήσετε έναν κωδικό πρόσβασης με 6 ή περισσότερους χαρακτήρες."
OBSWebSocket.SessionTable.Title="Συνδεδεμένες Συνεδρίες WebSocket"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Απομακρυσμένη Διεύθυνση"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Διάρκεια Συνεδρίας"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Εισερχόμενα/Εξερχόμενα Μηνύματα"
OBSWebSocket.SessionTable.IdentifiedTitle="Ταυτοποιήθηκε"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Διακοπή?"
OBSWebSocket.SessionTable.KickButtonText="Διακοπή"
OBSWebSocket.ConnectInfo.DialogTitle="Πληροφορίες Σύνδεσης WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Αντιγραφή"
OBSWebSocket.ConnectInfo.ServerIp="IP Διακομιστή (Βέλτιστη Εκτίμηση)"
OBSWebSocket.ConnectInfo.ServerPort="Θύρα Διακομιστή"
OBSWebSocket.ConnectInfo.ServerPassword="Κωδικός Διακομιστή"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Ταυτοποίηση Απενεργοποιημένη]"
OBSWebSocket.ConnectInfo.QrTitle="Σύνδεση με QR"
OBSWebSocket.TrayNotification.Identified.Title="Νέα Σύνδεση WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Ο πελάτης %1 ταυτοποιήθηκε."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Αποτυχία Ταυτοποίησης WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Αποτυχία ταυτοποίησης του πελάτη %1."
OBSWebSocket.TrayNotification.Disconnected.Title="Αποσυνδέθηκε ο Πελάτης του WebSocket"
OBSWebSocket.TrayNotification.Disconnected.Body="Ο πελάτης %1 αποσυνδέθηκε."

1
data/locale/en-GB.ini Normal file
View File

@ -0,0 +1 @@
#

View File

@ -1,6 +1,6 @@
OBSWebSocket.Plugin.Description="Remote-control of OBS Studio through WebSocket" OBSWebSocket.Plugin.Description="Remote-control of OBS Studio through WebSocket"
OBSWebSocket.Settings.DialogTitle="obs-websocket Settings" OBSWebSocket.Settings.DialogTitle="WebSocket Server Settings"
OBSWebSocket.Settings.PluginSettingsTitle="Plugin Settings" OBSWebSocket.Settings.PluginSettingsTitle="Plugin Settings"
OBSWebSocket.Settings.ServerEnable="Enable WebSocket server" OBSWebSocket.Settings.ServerEnable="Enable WebSocket server"
@ -9,14 +9,11 @@ OBSWebSocket.Settings.DebugEnable="Enable Debug Logging"
OBSWebSocket.Settings.DebugEnableHoverText="Enables debug logging for the current instance of OBS. Does not persist on load.\nUse --websocket_debug to enable on load." OBSWebSocket.Settings.DebugEnableHoverText="Enables debug logging for the current instance of OBS. Does not persist on load.\nUse --websocket_debug to enable on load."
OBSWebSocket.Settings.ServerSettingsTitle="Server Settings" OBSWebSocket.Settings.ServerSettingsTitle="Server Settings"
OBSWebSocket.Settings.ServerPort="Server Port"
OBSWebSocket.Settings.AllowExternal="Allow External Access"
OBSWebSocket.Settings.AllowExternalHoverText="Allows clients from outside this computer to connect to obs-websocket."
OBSWebSocket.Settings.AuthRequired="Enable Authentication" OBSWebSocket.Settings.AuthRequired="Enable Authentication"
OBSWebSocket.Settings.Password="Server Password" OBSWebSocket.Settings.Password="Server Password"
OBSWebSocket.Settings.GeneratePassword="Generate Password" OBSWebSocket.Settings.GeneratePassword="Generate Password"
OBSWebSocket.Settings.ServerPort="Server Port"
OBSWebSocket.Settings.ShowConnectInfo="Show Connect Info" OBSWebSocket.Settings.ShowConnectInfo="Show Connect Info"
OBSWebSocket.Settings.ShowConnectInfoHoverText="Connect Info is not available if external connections are disabled."
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Warning: Currently Live" OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Warning: Currently Live"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="It appears that an output (stream, recording, etc.) is currently active." OBSWebSocket.Settings.ShowConnectInfoWarningMessage="It appears that an output (stream, recording, etc.) is currently active."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Are you sure that you want to show your connect info?" OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Are you sure that you want to show your connect info?"
@ -48,6 +45,3 @@ OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket Authenticati
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Client %1 failed to authenticate." OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Client %1 failed to authenticate."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket Client Disconnected" OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket Client Disconnected"
OBSWebSocket.TrayNotification.Disconnected.Body="Client %1 disconnected." OBSWebSocket.TrayNotification.Disconnected.Body="Client %1 disconnected."
OBSWebSocket.Server.StartFailed.Title="WebSocket Server Failure"
OBSWebSocket.Server.StartFailed.Message="The WebSocket server failed to start. TCP port %1 may already be in use elsewhere on this system by another application. Try setting a different TCP port in the WebSocket server settings, or stop any application that could be using this port.\n Error message: %2"

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

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Control remoto de OBS Studio a través de WebSocket"
OBSWebSocket.Settings.DialogTitle="Ajustes del servidor WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Ajustes del plugin"
OBSWebSocket.Settings.ServerEnable="Habilitar servidor WebSocket"
OBSWebSocket.Settings.AlertsEnable="Habilitar alertas en la bandeja del sistema"
OBSWebSocket.Settings.DebugEnable="Habilitar registro de depuración"
OBSWebSocket.Settings.DebugEnableHoverText="Habilita el registro de depuración para la instancia actual de OBS. No persiste al cargar.\nUse --websocket_debug para activar al cargar."
OBSWebSocket.Settings.ServerSettingsTitle="Ajustes del servidor"
OBSWebSocket.Settings.AuthRequired="Habilitar autenticación"
OBSWebSocket.Settings.Password="Contraseña del servidor"
OBSWebSocket.Settings.GeneratePassword="Generar contraseña"
OBSWebSocket.Settings.ServerPort="Puerto del servidor"
OBSWebSocket.Settings.ShowConnectInfo="Mostrar información de conexión"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Advertencia: Actualmente en directo"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Parece que una salida (emisión, grabación, etc.) está activa."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="¿Estás seguro de que quieres mostrar tu información de conexión?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Advertencia: Problema potencial de seguridad"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket almacena la contraseña del servidor como texto plano. El uso de una contraseña generada por obs-websocket es altamente recomendable."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="¿Está seguro de que desea utilizar su propia contraseña?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Error: Configuración no válida"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Debe utilizar una contraseña de 6 o más caracteres."
OBSWebSocket.SessionTable.Title="Sesiones conectadas de WebSocket"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Dirección remota"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Duración de la sesión"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Entrada/Salida de mensajes"
OBSWebSocket.SessionTable.IdentifiedTitle="Identificado"
OBSWebSocket.SessionTable.KickButtonColumnTitle="¿Expulsar?"
OBSWebSocket.SessionTable.KickButtonText="Expulsar"
OBSWebSocket.ConnectInfo.DialogTitle="Información de conexión de WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Copiar"
OBSWebSocket.ConnectInfo.ServerIp="IP del servidor (mejor propuesta)"
OBSWebSocket.ConnectInfo.ServerPort="Puerto del servidor"
OBSWebSocket.ConnectInfo.ServerPassword="Contraseña del servidor"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autenticación desactivada]"
OBSWebSocket.ConnectInfo.QrTitle="QR de conexión"
OBSWebSocket.TrayNotification.Identified.Title="Nueva conexión WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Cliente %1 identificado."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Fallo de autenticación WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="El cliente %1 no se pudo autenticar."
OBSWebSocket.TrayNotification.Disconnected.Title="Cliente WebSocket desconectado"
OBSWebSocket.TrayNotification.Disconnected.Body="Cliente %1 desconectado."

41
data/locale/et-EE.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="OBS Studio kaugjuhtimine WebSocketi kaudu"
OBSWebSocket.Settings.DialogTitle="WebSocket serveri seaded"
OBSWebSocket.Settings.PluginSettingsTitle="Plugina seaded"
OBSWebSocket.Settings.ServerEnable="Luba WebSocket server"
OBSWebSocket.Settings.AlertsEnable="Luba hoiatused tegumireal"
OBSWebSocket.Settings.DebugEnable="Luba silumislogimine"
OBSWebSocket.Settings.DebugEnableHoverText="Lubab OBS-i praeguse eksemplari silumislogimise. Ei püsi laadimisel.\nLaadimisel lubamiseks kasutage --websocket_debug."
OBSWebSocket.Settings.ServerSettingsTitle="Serveri seaded"
OBSWebSocket.Settings.AuthRequired="Luba autentimine"
OBSWebSocket.Settings.Password="Serveri salasõna"
OBSWebSocket.Settings.GeneratePassword="Loo salasõna"
OBSWebSocket.Settings.ServerPort="Serveri port"
OBSWebSocket.Settings.ShowConnectInfo="Näita ühenduse infot"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Hoiatus: hetkel otseülekandes"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Näib, et väljund (voogedastus, salvestus jne) on hetkel aktiivne."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Kas oled kindel, et soovid oma ühenduse teavet näidata?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Hoiatus: võimalik turvaprobleem"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket salvestab serveri salasõna lihtsa tekstina. obs-websocket'i poolt loodud salasõna kasutamine on väga soovitatav."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Kas oled kindel, et soovid kasutada oma salasõna?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Viga: vigane konfiguratsioon"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Pead kasutama salasõna, mis koosneb 6 või enamast tähemärgist."
OBSWebSocket.SessionTable.Title="Ühendatud WebSocket'i seansid"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Kaugjuhtimise aadress"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Seansi kestvus"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Sõnumid sisse/välja"
OBSWebSocket.SessionTable.IdentifiedTitle="Tuvastatud"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Eemalda?"
OBSWebSocket.SessionTable.KickButtonText="Eemalda"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket'i ühenduse info"
OBSWebSocket.ConnectInfo.CopyText="Kopeeri"
OBSWebSocket.ConnectInfo.ServerIp="Serveri IP (parim oletus)"
OBSWebSocket.ConnectInfo.ServerPort="Sreveri port"
OBSWebSocket.ConnectInfo.ServerPassword="Serveri salasõna"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autentimine keelatud]"
OBSWebSocket.ConnectInfo.QrTitle="Ühenda QR"
OBSWebSocket.TrayNotification.Identified.Title="Uus WebSocket'i ühendus"
OBSWebSocket.TrayNotification.Identified.Body="Klient %1 tuvastatud."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket autentimise tõrge"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Kliendi %1 autentimine ebaõnnestus."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket kliendi ühendus katkenud"
OBSWebSocket.TrayNotification.Disconnected.Body="Kliendi %1 ühendus katkenud."

40
data/locale/eu-ES.ini Normal file
View File

@ -0,0 +1,40 @@
OBSWebSocket.Plugin.Description="OBS Studioren urruneko kontrolatzailea WebSocket-en bidez"
OBSWebSocket.Settings.PluginSettingsTitle="Plugin Ezarpenak"
OBSWebSocket.Settings.ServerEnable="WebSocket zerbitzaria gaitu"
OBSWebSocket.Settings.AlertsEnable="Aktibatu sistema-erretiluko alertak"
OBSWebSocket.Settings.DebugEnable="Gaitu arazketa erregistroa"
OBSWebSocket.Settings.DebugEnableHoverText="OBSren uneko instantzian arazketa erregistroa gaitzen du. Berriro irekitzerakoan ez da mantenduko . \nErabili --websocket_debug kargatzerakoan gaitzeko."
OBSWebSocket.Settings.ServerSettingsTitle="Zerbitzariaren Ezarpenak"
OBSWebSocket.Settings.AuthRequired="Autentifikazioa aktibatu"
OBSWebSocket.Settings.Password="Zerbitzari pasahitza"
OBSWebSocket.Settings.GeneratePassword="Pasahitza sortu"
OBSWebSocket.Settings.ServerPort="Zerbitzari portua"
OBSWebSocket.Settings.ShowConnectInfo="Konexio-informazioa erakutsi"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Adi: Zuzenean zaude"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Irteera bat (stream, grabazioa, etab.) aktibo dagoela badirudi."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Ziur zaude konexio-informazioa erakutsi nahi duzula?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Adi: Segurtasun arazo potentziala"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket-ek zerbitzariaren pasahitza testu sinple gisa gordetzen du. obs-websocket bidez sortutako pasahitza erabiltzea gomendatzen da."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Ziur zaude zure pasahitza erabili nahi duzula?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Errorea: konfigurazio baliogabea"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="6 karaktere edo gehiagoko pasahitza erabili behar duzu."
OBSWebSocket.SessionTable.Title="Konektatutako WebSocket saioak"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Urruneko helbidea"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Saioaren iraupena"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Sarrera-/irteera-mezuak"
OBSWebSocket.SessionTable.IdentifiedTitle="Identifikatuta"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Kanporatu?"
OBSWebSocket.SessionTable.KickButtonText="Kanporatu"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket konexio-informazioa"
OBSWebSocket.ConnectInfo.CopyText="Kopiatu"
OBSWebSocket.ConnectInfo.ServerIp="Zerbitzariaren IP-a (proposamen hoberena)"
OBSWebSocket.ConnectInfo.ServerPort="Zerbitzari portua"
OBSWebSocket.ConnectInfo.ServerPassword="Zerbitzari pasahitza"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autorizazioa desgaituta]"
OBSWebSocket.ConnectInfo.QrTitle="Konexioaren QR kodea"
OBSWebSocket.TrayNotification.Identified.Title="WebSocket konexio berria"
OBSWebSocket.TrayNotification.Identified.Body="%1 bezeroa identifikatuta."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket Autentikazioan hutsegitea"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="%1 bezeroak autentifikatzen huts egin du."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket Bezeroa deskonektatu da"
OBSWebSocket.TrayNotification.Disconnected.Body="%1 bezeroa deskonektatu da."

41
data/locale/fa-IR.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="کنترل از راه دور OBS Studio از طریق WebSocket"
OBSWebSocket.Settings.DialogTitle="تنظیمات سرور سوکت وب"
OBSWebSocket.Settings.PluginSettingsTitle="تنظیمات پلاگین"
OBSWebSocket.Settings.ServerEnable="سرور سوکت وب را فعال کنید"
OBSWebSocket.Settings.AlertsEnable="هشدارهای سینی سیستم را فعال کنید"
OBSWebSocket.Settings.DebugEnable="فعال کردن گزارش اشکال زدایی"
OBSWebSocket.Settings.DebugEnableHoverText="ثبت اشکال زدایی را برای نمونه فعلی OBS فعال می کند. در بارگذاری ادامه نمی‌یابد.\n برای فعال کردن در بارگذاری از --websocket_debug استفاده کنید."
OBSWebSocket.Settings.ServerSettingsTitle="تنظیمات سرور"
OBSWebSocket.Settings.AuthRequired="فعال کردن احراز هویت"
OBSWebSocket.Settings.Password="رمز سرور"
OBSWebSocket.Settings.GeneratePassword="ایجاد رمز عبور"
OBSWebSocket.Settings.ServerPort="پورت سرور"
OBSWebSocket.Settings.ShowConnectInfo="نمایش اطلاعات اتصال"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="هشدار: در حال حاضر زنده است"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="به نظر می رسد که یک خروجی (جریان، ضبط و غیره) در حال حاضر فعال است."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="آیا مطمئن هستید که می خواهید اطلاعات اتصال خود را نشان دهید؟"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="هشدار: مشکل امنیتی احتمالی"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket رمز عبور سرور را به صورت متن ساده ذخیره می کند. استفاده از رمز عبور تولید شده توسط obs-websocket بسیار توصیه می شود."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="آیا مطمئن هستید که می خواهید از رمز عبور خود استفاده کنید؟"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="خطا: پیکربندی نامعتبر است"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="باید از رمز عبور 6 کاراکتر یا بیشتر استفاده کنید."
OBSWebSocket.SessionTable.Title="جلسات سوکت وب متصل"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="آدرس از راه دور"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="مدت زمان جلسه"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="پیام های ورودی/خارجی"
OBSWebSocket.SessionTable.IdentifiedTitle="تایید هویت شده"
OBSWebSocket.SessionTable.KickButtonColumnTitle="لگد زدن؟"
OBSWebSocket.SessionTable.KickButtonText="اخراج"
OBSWebSocket.ConnectInfo.DialogTitle="اطلاعات اتصال سوکت وب"
OBSWebSocket.ConnectInfo.CopyText="رونوشت‌"
OBSWebSocket.ConnectInfo.ServerIp="IP سرور (بهترین حدس)"
OBSWebSocket.ConnectInfo.ServerPort="پورت سرور"
OBSWebSocket.ConnectInfo.ServerPassword="رمز سرور"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[احراز غیر فعال]"
OBSWebSocket.ConnectInfo.QrTitle="QR را وصل کنید"
OBSWebSocket.TrayNotification.Identified.Title="اتصال سوکت وب جدید"
OBSWebSocket.TrayNotification.Identified.Body="سرویس گیرنده %1 شناسایی شد."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="خرابی تأیید اعتبار سوکت وب"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="سرویس گیرنده %1 احراز هویت نشد."
OBSWebSocket.TrayNotification.Disconnected.Title="سرویس گیرنده سوکت وب قطع شد"
OBSWebSocket.TrayNotification.Disconnected.Body="سرویس گیرنده %1 قطع شد."

41
data/locale/fi-FI.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="OBS Studion etähallinta WebSocketin kautta"
OBSWebSocket.Settings.DialogTitle="WebSocket-palvelimen asetukset"
OBSWebSocket.Settings.PluginSettingsTitle="Liitännäisen asetukset"
OBSWebSocket.Settings.ServerEnable="Ota WebSocket-palvelin käyttöön"
OBSWebSocket.Settings.AlertsEnable="Ota ilmoitusalueen ilmoitukset käyttöön"
OBSWebSocket.Settings.DebugEnable="Ota vianjäljityslokitus käyttöön"
OBSWebSocket.Settings.DebugEnableHoverText="Ottaa käyttöön OBS:n virheenkorjauksen lokin. Ei kuormituksen aikana.\nKäytä --websocket_debug ottaaksesi latauksen käyttöön."
OBSWebSocket.Settings.ServerSettingsTitle="Palvelimen asetukset"
OBSWebSocket.Settings.AuthRequired="Ota tunnistautuminen käyttöön"
OBSWebSocket.Settings.Password="Palvelimen salasana"
OBSWebSocket.Settings.GeneratePassword="Luo salasana"
OBSWebSocket.Settings.ServerPort="Palvelimen portti"
OBSWebSocket.Settings.ShowConnectInfo="Näytä yhteyden tiedot"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Varoitus: Suora lähetys"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Näyttää siltä, että jokin lähetys (suoratoisto, tallennus jne.) on tällä hetkellä aktiivinen."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Oletko varma, että haluat näyttää sinun yhteyden tiedot?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Varoitus: Mahdollinen tietoturvaongelma"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket tallentaa palvelimen salasanan pelkkänä tekstinä. Obs-websocketin luoman salasanan käyttäminen on erittäin suositeltavaa."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Haluatko varmasti käyttää omaa salasanaasi?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Virhe: Virheellinen määritys"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Sinun täytyy käyttää salasanaa, jossa on vähintään 6 merkkiä."
OBSWebSocket.SessionTable.Title="Yhdistetyt WebSocket-istunnot"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Etäosoite"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Istunnon kesto"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Viestejä sisään/ulos"
OBSWebSocket.SessionTable.IdentifiedTitle="Tunnistettu"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Potki?"
OBSWebSocket.SessionTable.KickButtonText="Potki"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-yhteystiedot"
OBSWebSocket.ConnectInfo.CopyText="Kopioi"
OBSWebSocket.ConnectInfo.ServerIp="Palvelimen IP (paras arvaus)"
OBSWebSocket.ConnectInfo.ServerPort="Palvelimen portti"
OBSWebSocket.ConnectInfo.ServerPassword="Palvelimen salasana"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Todennus poistettu]"
OBSWebSocket.ConnectInfo.QrTitle="Yhdistä QR"
OBSWebSocket.TrayNotification.Identified.Title="Uusi WebSocket-yhteys"
OBSWebSocket.TrayNotification.Identified.Body="Asiakas %1 tunnistettu."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket-tunnistusvirhe"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Asiakas %1 todennus epäonnistui."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket-asiakas katkaisi yhteyden"
OBSWebSocket.TrayNotification.Disconnected.Body="Asiakas %1 on katkaistu."

37
data/locale/fil-PH.ini Normal file
View File

@ -0,0 +1,37 @@
OBSWebSocket.Plugin.Description="Remote-control ng OBS Studio sa pamamagitan ng WebSocket"
OBSWebSocket.Settings.DialogTitle="Mga Setting Ng WebSocket Server"
OBSWebSocket.Settings.PluginSettingsTitle="Mga Setting ng Plugin"
OBSWebSocket.Settings.ServerEnable="Paganahin ang WebSocket server"
OBSWebSocket.Settings.AlertsEnable="Paganahin ang System Tray Alerto"
OBSWebSocket.Settings.DebugEnable="Paganahin ang Debug Log"
OBSWebSocket.Settings.DebugEnableHoverText="Paganahin ang debug log para sa kasalukuyang instance ng OBS. Hindi nagpapatuloy sa pag-load.\nGumamit ng --websocket_debug upang paganahin ang pag-load."
OBSWebSocket.Settings.ServerSettingsTitle="Mga setting ng Server"
OBSWebSocket.Settings.AuthRequired="Paggamit ng Pagpapatunay"
OBSWebSocket.Settings.Password="Password ng server"
OBSWebSocket.Settings.GeneratePassword="Mag-Generate ng Password"
OBSWebSocket.Settings.ShowConnectInfo="Ipakita ang Impormasyon sa Pagkonekta"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Babala: Kasalukuyang nakalive"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Lumalabas na kasalukuyang aktibo ang isang output (stream, recording, atbp.)."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Sigurado ka bang gusto mong ipakita ang iyong impormasyon sa pagkonekta?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Babala: Potensyal na Isyu sa Seguridad"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="Iniimbak ng obs-websocket ang password ng server bilang plain text. Ang paggamit ng password na nabuo ng obs-websocket ay lubos na inirerekomenda."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Sigurado ka bang gusto mong gamitin ang iyong sariling password?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Error: Di-wastong Configuration"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Dapat kang gumamit ng password na 6 o higit pang mga character."
OBSWebSocket.SessionTable.Title="Nakakonektang WebSocket Session"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Tagal ng Session"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Mga Mensahe In/Out"
OBSWebSocket.SessionTable.IdentifiedTitle="Kilalanin."
OBSWebSocket.SessionTable.KickButtonColumnTitle="Sipa?"
OBSWebSocket.SessionTable.KickButtonText="Sipa"
OBSWebSocket.ConnectInfo.DialogTitle="Impormasyon ng WebSocket Connect"
OBSWebSocket.ConnectInfo.CopyText="Kopyahin"
OBSWebSocket.ConnectInfo.ServerPassword="Password ng server"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Naka-disable ang Auth]"
OBSWebSocket.ConnectInfo.QrTitle="Ikonekta ang QR"
OBSWebSocket.TrayNotification.Identified.Title="Bagong Koneksyon sa WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Natukoy ang %1 ng kliyente."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Nabigo sa Pagpapatunay ang WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Nabigo ang kliyenteng %1 na patotohanan."
OBSWebSocket.TrayNotification.Disconnected.Title="Nadiskonekta ang WebSocket Client"
OBSWebSocket.TrayNotification.Disconnected.Body="Nadiskonekta ang kliyenteng %1."

41
data/locale/fr-FR.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Contrôle à distance d'OBS Studio via WebSocket"
OBSWebSocket.Settings.DialogTitle="Paramètres du serveur WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Paramètres du plugin"
OBSWebSocket.Settings.ServerEnable="Activer le serveur WebSocket"
OBSWebSocket.Settings.AlertsEnable="Activer les alertes de la zone de notification"
OBSWebSocket.Settings.DebugEnable="Activer les journaux de débogage"
OBSWebSocket.Settings.DebugEnableHoverText="Active la journalisation du débogage pour l'instance actuelle d'OBS. Ne persiste pas au chargement.\nUtilisez --websocket_debug pour l'activer lors du chargement."
OBSWebSocket.Settings.ServerSettingsTitle="Paramètres du serveur"
OBSWebSocket.Settings.AuthRequired="Utiliser l'authentification"
OBSWebSocket.Settings.Password="Mot de passe du serveur"
OBSWebSocket.Settings.GeneratePassword="Générer un mot de passe"
OBSWebSocket.Settings.ServerPort="Port du serveur"
OBSWebSocket.Settings.ShowConnectInfo="Afficher les informations de connexion"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Avertissement : Actuellement en direct"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Il semble qu'une sortie (stream, enregistrement, etc.) soit actuellement active."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Êtes-vous sûr de vouloir afficher vos informations de connexion ?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Avertissement : Problème potentiel de sécurité"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket enregistre le mot de passe du serveur en texte brut. L'utilisation d'un mot de passe généré par obs-websocket est fortement recommandée."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Êtes-vous sûr(e) de vouloir utiliser votre propre mot de passe ?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Erreur : Configuration invalide"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Vous devez utiliser un mot de passe de 6 caractères ou plus."
OBSWebSocket.SessionTable.Title="Sessions WebSocket connectées"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adresse distante"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Durée de session"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Messages entrant/sortant"
OBSWebSocket.SessionTable.IdentifiedTitle="Identifié"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Expulser?"
OBSWebSocket.SessionTable.KickButtonText="Expulser"
OBSWebSocket.ConnectInfo.DialogTitle="Informations de connexion WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Copier"
OBSWebSocket.ConnectInfo.ServerIp="IP du serveur (meilleure estimation)"
OBSWebSocket.ConnectInfo.ServerPort="Port serveur"
OBSWebSocket.ConnectInfo.ServerPassword="Mot de passe du serveur"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Authentification désactivée]"
OBSWebSocket.ConnectInfo.QrTitle="QR code de connexion"
OBSWebSocket.TrayNotification.Identified.Title="Nouvelle connexion WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Client %1 identifié."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Échec de l'authentification WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Échec d'authentification du client %1."
OBSWebSocket.TrayNotification.Disconnected.Title="Client WebSocket déconnecté"
OBSWebSocket.TrayNotification.Disconnected.Body="Client %1 déconnecté."

6
data/locale/gl-ES.ini Normal file
View File

@ -0,0 +1,6 @@
OBSWebSocket.Settings.ServerSettingsTitle="Configuración do servidor"
OBSWebSocket.ConnectInfo.CopyText="Copiar"
OBSWebSocket.ConnectInfo.ServerPort="Porto do Servidor"
OBSWebSocket.ConnectInfo.ServerPassword="Contrasinal do Servidor"
OBSWebSocket.TrayNotification.Identified.Body="Cliente %1 identificado."
OBSWebSocket.TrayNotification.Disconnected.Body="Cliente %1 desconectado."

41
data/locale/he-IL.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="שליטה מרחוק על OBS Studio באמצעות WebSocket"
OBSWebSocket.Settings.DialogTitle="הגדרות שרת WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="הגדרות תוסף"
OBSWebSocket.Settings.ServerEnable="הפעלת שרת WebSocket"
OBSWebSocket.Settings.AlertsEnable="הפעלת התראות במגש המערכת"
OBSWebSocket.Settings.DebugEnable="הפעלת לוג איתור באגים"
OBSWebSocket.Settings.DebugEnableHoverText="מאפשר לוג איתור באגים עבור ההפעלה הנוכחית של OBS. לא ממשיך לפעול בעת הפעלה.\nיש להשתמש ב --websocket_debug בכדי לאפשר בעת ההפעלה."
OBSWebSocket.Settings.ServerSettingsTitle="הגדרות שרת"
OBSWebSocket.Settings.AuthRequired="שימוש באימות"
OBSWebSocket.Settings.Password="סיסמת שרת"
OBSWebSocket.Settings.GeneratePassword="יצירת סיסמה"
OBSWebSocket.Settings.ServerPort="פורט שרת"
OBSWebSocket.Settings.ShowConnectInfo="הצגת מידע חיבור"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="אזהרה: שידור חי פעיל"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="נראה כי פלט (שידור חי, הקלטה וכו') פעיל כרגע."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="האם ברצונך להציג את המידע על החיבור שלך?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="אזהרה: בעיית אבטחה אפשרית"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket שומר את סיסמת השרת שלך כטקסט רגיל. מומלץ להשתמש בסיסמה שנוצרה ע\"י obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="האם ברצונך להשתמש בסיסמה שלך?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="שגיאה: תצורה לא חוקית"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="חובה להשתמש בסיסמה עם 6 תווים או יותר."
OBSWebSocket.SessionTable.Title="הפעלות WebSocket מחוברות"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="כתובת מרוחקת"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="משך זמן הפעלה"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="הודעות פנים/חוץ"
OBSWebSocket.SessionTable.IdentifiedTitle="מזוהים"
OBSWebSocket.SessionTable.KickButtonColumnTitle="בעט?"
OBSWebSocket.SessionTable.KickButtonText="בעט"
OBSWebSocket.ConnectInfo.DialogTitle="מידע חיבור WebSocket"
OBSWebSocket.ConnectInfo.CopyText="העתקה"
OBSWebSocket.ConnectInfo.ServerIp="כתובת IP שרת (הניחוש המוצלח ביותר)"
OBSWebSocket.ConnectInfo.ServerPort="פורט שרת"
OBSWebSocket.ConnectInfo.ServerPassword="סיסמת שרת"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[אימות מושבת]"
OBSWebSocket.ConnectInfo.QrTitle="חיבור QR"
OBSWebSocket.TrayNotification.Identified.Title="חיבור WebSocket חדש"
OBSWebSocket.TrayNotification.Identified.Body="לקוח %1 זוהה."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="אימות WebSocket נכשל"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="לקוח %1 נכשל באימות"
OBSWebSocket.TrayNotification.Disconnected.Title="לקוח WebSocket התנתק"
OBSWebSocket.TrayNotification.Disconnected.Body="לקוח %1 התנתק."

41
data/locale/hi-IN.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="WebSocket के माध्यम से OBS स्टूडियो का रिमोट-कंट्रोल"
OBSWebSocket.Settings.DialogTitle="वेबसॉकेट सर्वर सेटिंग्स"
OBSWebSocket.Settings.PluginSettingsTitle="प्लगइन सेटिंग्स"
OBSWebSocket.Settings.ServerEnable="WebSocket सर्वर सक्षम करें"
OBSWebSocket.Settings.AlertsEnable="सिस्टम ट्रे अलर्ट सक्षम करें"
OBSWebSocket.Settings.DebugEnable="डिबग लॉगिंग सक्रिय करें"
OBSWebSocket.Settings.DebugEnableHoverText="OBS के वर्तमान इंसटैन्स के लिए डीबग लॉगिंग सक्षम करता है. लोड होने पर कायम नहीं रहता है.\n लोड होने पर सक्षम करने के लिए --websocket_debug का उपयोग करें."
OBSWebSocket.Settings.ServerSettingsTitle="सर्वर सेटिंग"
OBSWebSocket.Settings.AuthRequired="प्रमाणीकरण सक्षम करें"
OBSWebSocket.Settings.Password="सर्वर का पासवर्ड"
OBSWebSocket.Settings.GeneratePassword="पासवर्ड बनाएं"
OBSWebSocket.Settings.ServerPort="सर्वर पोर्ट"
OBSWebSocket.Settings.ShowConnectInfo="कनेक्ट जानकारी दिखाएं"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="चेतावनी: वर्तमान में लाइव"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="ऐसा प्रतीत होता है कि कोई एक आउटपुट (स्ट्रीम, रिकॉर्डिंग, आदि) वर्तमान में सक्रिय है."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="क्या आप वाकई अपनी कनेक्ट जानकारी दिखाना चाहते हैं?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="चेतावनी : संभावित सुरक्षा समस्या"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket सर्वर पासवर्ड को प्लेन टेक्स्ट के रूप में स्टोर करता है. obs-websocket द्वारा उत्पन्न पासवर्ड का उपयोग करने की अत्यधिक अनुशंसा की जाती है."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="क्या आप वाकई स्वयं का पासवर्ड प्रयोग करना चाहते हैं?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="त्रुटि : अमान्य कॉन्फ़िगरेशन"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="आपको 6 या अधिक वर्णों वाले पासवर्ड का उपयोग करना चाहिए."
OBSWebSocket.SessionTable.Title="कनेक्टेड वेबसॉकेट सत्र"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="रिमोट ऐड्रेस"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="सत्र अवधि"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="संदेश इन/आउट"
OBSWebSocket.SessionTable.IdentifiedTitle="पहचाना हुआ"
OBSWebSocket.SessionTable.KickButtonColumnTitle="निकालें?"
OBSWebSocket.SessionTable.KickButtonText="निकालें"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket कनेक्ट जानकारी दिखाएं"
OBSWebSocket.ConnectInfo.CopyText="प्रतिलिपि"
OBSWebSocket.ConnectInfo.ServerIp="सर्वर IP (सर्वश्रेष्ठ अनुमान)"
OBSWebSocket.ConnectInfo.ServerPort="सर्वर पोर्ट"
OBSWebSocket.ConnectInfo.ServerPassword="सर्वर का पासवर्ड"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[पहुँच अक्षम]"
OBSWebSocket.ConnectInfo.QrTitle="QR से जुड़ें"
OBSWebSocket.TrayNotification.Identified.Title="नया WebSocket कनेक्शन"
OBSWebSocket.TrayNotification.Identified.Body="क्लाइंट %1 की पहचान की गई."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket सत्यापन विफलता"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="क्लाइंट %1प्रमाणित करने में विफल रहा."
OBSWebSocket.TrayNotification.Disconnected.Title="वेबसॉकेट क्लाइंट डिस्कनेक्ट हो गया"
OBSWebSocket.TrayNotification.Disconnected.Body="क्लाइंट %1 डिस्कनेक्ट हो गया."

10
data/locale/hr-HR.ini Normal file
View File

@ -0,0 +1,10 @@
OBSWebSocket.Settings.DialogTitle="Postavke servera WebSocket"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Pogreška: Neispravna konfiguracija"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Lozinka mora sadržavati barem 6 znakova."
OBSWebSocket.SessionTable.Title="Spojene sesije WebSocketa"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Udaljena adresa"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Trajanje sesije"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Ulaz/izlaz poruka"
OBSWebSocket.ConnectInfo.CopyText="Kopiraj"
OBSWebSocket.ConnectInfo.ServerPort="Vrata servera"
OBSWebSocket.ConnectInfo.ServerPassword="Lozinka servera"

41
data/locale/hu-HU.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Az OBS Studio távvezérlése WebSocketen keresztül"
OBSWebSocket.Settings.DialogTitle="WebSocket-kiszolgáló beállításai"
OBSWebSocket.Settings.PluginSettingsTitle="Bővítménybeállítások"
OBSWebSocket.Settings.ServerEnable="WebSocket-kiszolgáló engedélyezése"
OBSWebSocket.Settings.AlertsEnable="Rendszertálca-riasztások bekapcsolása"
OBSWebSocket.Settings.DebugEnable="Hibakeresési naplózás bekapcsolása"
OBSWebSocket.Settings.DebugEnableHoverText="Bekapcsolja a hibakeresési naplózást a jelenlegi OBS-példánynál. Betöltéskor nem marad meg.\nA betöltéskor történő bekapcsoláshoz használja a --websocket_debug kapcsolót."
OBSWebSocket.Settings.ServerSettingsTitle="Kiszolgálóbeállítások"
OBSWebSocket.Settings.AuthRequired="Hitelesítés bekapcsolása"
OBSWebSocket.Settings.Password="Kiszolgáló jelszava"
OBSWebSocket.Settings.GeneratePassword="Jelszó előállítása"
OBSWebSocket.Settings.ServerPort="Kiszolgáló portja"
OBSWebSocket.Settings.ShowConnectInfo="Kapcsolódási információ megjelenítése"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Figyelmeztetés: Élő adásban van"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Úgy néz ki, hogy egy kimenet (közvetítés, felvétel, stb.) jelenleg aktív."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Biztos, hogy megjeleníti a kapcsolódási információkat?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Figyelmeztetés: lehetséges biztonsági probléma"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="Az obs-websocket titkosítatlan szövegként tárolja a kiszolgáló jelszavát. Ajánlatos egy az obs-websocket általelőállított jelsztó használni."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Biztos, hogy a saját jelszavát használja?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Hiba: Érvénytelen konfiguráció"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Legalább 6 karakterből álló jelszót kell használnia."
OBSWebSocket.SessionTable.Title="Kapcsolódott WebSocket munkamenetek"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Távoli cím"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Munkamenet hossza"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Bejövő és kimenő üzenetek"
OBSWebSocket.SessionTable.IdentifiedTitle="Azonosított"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Kirúgás?"
OBSWebSocket.SessionTable.KickButtonText="Kirúgás"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket kapcsolati információk"
OBSWebSocket.ConnectInfo.CopyText="Másolás"
OBSWebSocket.ConnectInfo.ServerIp="Kiszolgáló IP (legjobb tipp)"
OBSWebSocket.ConnectInfo.ServerPort="Kiszolgáló portja"
OBSWebSocket.ConnectInfo.ServerPassword="Kiszolgáló jelszava"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Hitelesítés kikapcsolva]"
OBSWebSocket.ConnectInfo.QrTitle="Kapcsolódási QR-kód"
OBSWebSocket.TrayNotification.Identified.Title="Új WebSocket-kapcsolat"
OBSWebSocket.TrayNotification.Identified.Body="A(z) %1 kliens azonosítva."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket hitelesítési hiba"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="A(z) %1 kliens hitelesítése sikertelen."
OBSWebSocket.TrayNotification.Disconnected.Title="A WebSocket-kliens bontotta a kapcsolatot"
OBSWebSocket.TrayNotification.Disconnected.Body="A(z) %1 kliens bontotta a kapcsolatot"

41
data/locale/hy-AM.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="OBS Studio-ի հեռակառավարումը WebSocket-ի միջոցով"
OBSWebSocket.Settings.DialogTitle="WebSocket Սպասարկչի Կարգավորումները"
OBSWebSocket.Settings.PluginSettingsTitle="Միացնիչի կարգավորումներ"
OBSWebSocket.Settings.ServerEnable="Միացնել WebSocket սերվերը"
OBSWebSocket.Settings.AlertsEnable="Միացնել սկուտեղի ծանուցումները"
OBSWebSocket.Settings.DebugEnable="Միացնել վրիպազերծման գրանցումը"
OBSWebSocket.Settings.DebugEnableHoverText="Միացնում է վրիպազերծման գրանցումը ընթացիկ OBS օրինակի համար: Չի պահպանվում գործարկման ժամանակ:\nՕգտագործեք --websocket_debug՝ գործարկման ժամանակ միացնելու համար:"
OBSWebSocket.Settings.ServerSettingsTitle="Սերվերի կարգավորումներ"
OBSWebSocket.Settings.AuthRequired="Միացնել նույնականացումը"
OBSWebSocket.Settings.Password="Սերվերի գաղտնաբառը"
OBSWebSocket.Settings.GeneratePassword="Ստեղծել գաղտնաբառը"
OBSWebSocket.Settings.ServerPort="Սերվերի պորտ"
OBSWebSocket.Settings.ShowConnectInfo="Ցույց տալ կապի մանրամասները"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Զգուշացում։ Հիմա ուղիղ եթեր"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Կարծես թե ելքը (հոսք, գրել և այլն) ներկայումս ակտիվ է:"
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Իսկապե՞ս ուզում եք ցույց տալ ձեր կապի մանրամասները:"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Զգուշացում։ Հնարավոր անվտանգության խնդիր"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket-ը պահպանում է սերվերի գաղտնաբառը պարզ տեքստով: Խիստ խորհուրդ է տրվում օգտագործել obs-websock-ի կողմից ստեղծված գաղտնաբառը:"
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Վստա՞հ եք, որ ցանկանում եք օգտագործել ձեր սեփական գաղտնաբառը:"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Սխալ։ Անվավեր կոնֆիգուրացիա"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Դուք պետք է օգտագործեք 6 կամ ավելի նիշից բաղկացած գաղտնաբառ:"
OBSWebSocket.SessionTable.Title="Միացված WebSocket նիստեր"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Ջնջված հասցե"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Նիստի տևողությունը"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Ներս/Դուրս հաղորդագրություններ"
OBSWebSocket.SessionTable.IdentifiedTitle="Ճանաչված"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Վտարե՞լ:"
OBSWebSocket.SessionTable.KickButtonText="Վտարել"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket կապի մանրամասները"
OBSWebSocket.ConnectInfo.CopyText="Պատճենել"
OBSWebSocket.ConnectInfo.ServerIp="Սերվերի ԻԱ (լավագույն ենթադրություն)"
OBSWebSocket.ConnectInfo.ServerPort="Սերվերի պորտ"
OBSWebSocket.ConnectInfo.ServerPassword="Սերվերի գաղտնաբառը"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Թույլտվությունն անջատված է]"
OBSWebSocket.ConnectInfo.QrTitle="Միացման ԱԱ կոդը"
OBSWebSocket.TrayNotification.Identified.Title="Նոր WebSocket կապ"
OBSWebSocket.TrayNotification.Identified.Body="Հաճախորդը ճանաչվեց %1:"
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket վավերացման սխալ"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="%1 հաճախորդը չհաջողվեց նույնականացնել:"
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket հաճախորդն անջատված է"
OBSWebSocket.TrayNotification.Disconnected.Body="%1 հաճախորդն անջատվել է:"

41
data/locale/id-ID.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Kendali jarak jauh OBS Studio melalui WebSocket"
OBSWebSocket.Settings.DialogTitle="Pengaturan Server WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Pengaturan Plugin"
OBSWebSocket.Settings.ServerEnable="Aktifkan server WebSocket"
OBSWebSocket.Settings.AlertsEnable="Aktifkan Peringatan Baki Sistem"
OBSWebSocket.Settings.DebugEnable="Aktifkan Pencatatan Awakutu"
OBSWebSocket.Settings.DebugEnableHoverText="Aktifkan pencatatan awakutu untuk permintaan OBS saat ini. Tidak terus aktif saat memuat.\nGunakan --websocket_debug agar diaktifkan saat memuat."
OBSWebSocket.Settings.ServerSettingsTitle="Pengaturan Server"
OBSWebSocket.Settings.AuthRequired="Aktifkan Autentikasi"
OBSWebSocket.Settings.Password="Kata Sandi Server"
OBSWebSocket.Settings.GeneratePassword="Buat Kata Sandi"
OBSWebSocket.Settings.ServerPort="Port Server"
OBSWebSocket.Settings.ShowConnectInfo="Tampilkan Informasi Koneksi"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Peringatan: Saat Ini Siaran Langsung"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Sepertinya sebuah output (stream, rekaman, dll.) sedang aktif."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Anda yakin ingin melihat informasi koneksi Anda?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Peringatan: Potensi Masalah Keamanan"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket menyimpan kata sandi server sebagai teks biasa. Sangat disarankan untuk menggunakan kata sandi yang diciptakan oleh obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Apakah Anda yakin ingin menggunakan kata sandi sendiri?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Galat: Konfigurasi Tidak Berlaku"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Anda harus menggunakan kata sandi yang minimal 6 karakter atau lebih."
OBSWebSocket.SessionTable.Title="Sesi WebSocket yang Terhubung"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Alamat Kendali"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Durasi Sesi"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Pesan Masuk/Keluar"
OBSWebSocket.SessionTable.IdentifiedTitle="Teridentifikasi"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Putuskan?"
OBSWebSocket.SessionTable.KickButtonText="Putuskan"
OBSWebSocket.ConnectInfo.DialogTitle="Informasi Koneksi WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Salin"
OBSWebSocket.ConnectInfo.ServerIp="IP Server (Tebakan Terbaik)"
OBSWebSocket.ConnectInfo.ServerPort="Port Server"
OBSWebSocket.ConnectInfo.ServerPassword="Kata Sandi Server"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autentikasi Dinonaktifkan]"
OBSWebSocket.ConnectInfo.QrTitle="Hubungkan QR"
OBSWebSocket.TrayNotification.Identified.Title="Koneksi WebSocket Baru"
OBSWebSocket.TrayNotification.Identified.Body="Klien %1 teridentifikasi."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Autentikasi WebSocket Gagal"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Klien %1 gagal mengautentikasi."
OBSWebSocket.TrayNotification.Disconnected.Title="Klien WebSocket Terputus"
OBSWebSocket.TrayNotification.Disconnected.Body="Klien %1 terputus."

41
data/locale/it-IT.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Controllo remoto di OBS Studio tramite WebSocket"
OBSWebSocket.Settings.DialogTitle="Impostazioni server WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Impostazioni del plugin"
OBSWebSocket.Settings.ServerEnable="Abilita il server WebSocket"
OBSWebSocket.Settings.AlertsEnable="Abilita avvisi sulla barra delle applicazioni"
OBSWebSocket.Settings.DebugEnable="Abilita registrazione debug"
OBSWebSocket.Settings.DebugEnableHoverText="Abilita la registrazione debug per l'istanza attuale di OBS.\nNon rimane attiva per il prossimo caricamento.\nUsa --websocket_debug per abilitarla al caricamento."
OBSWebSocket.Settings.ServerSettingsTitle="Impostazioni server"
OBSWebSocket.Settings.AuthRequired="Abilita autenticazione"
OBSWebSocket.Settings.Password="Password server"
OBSWebSocket.Settings.GeneratePassword="Genera password"
OBSWebSocket.Settings.ServerPort="Porta server"
OBSWebSocket.Settings.ShowConnectInfo="Visualizza informazioni di connessione"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Attenzione: attualmente in diretta"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Sembra che sia attualmente attivo un output (stream, registrazione, ecc.)."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Sei sicuro di voler visualizzare le tue informazioni di connessione?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Avvertimento: potenziale problema di sicurezza"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket memorizza la password del server come testo normale.\nTi consigliamo vivamente di usare una password generata da obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Sei sicuro di voler usare la tua password?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Errore: configurazione non valida"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="È necessario usare una password di 6 o più caratteri."
OBSWebSocket.SessionTable.Title="Sessioni WebSocket connesse"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Indirizzo remoto"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Durata sessione"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Messaggi in entrata/uscita"
OBSWebSocket.SessionTable.IdentifiedTitle="Identificato"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Chiudere?"
OBSWebSocket.SessionTable.KickButtonText="Chiudi"
OBSWebSocket.ConnectInfo.DialogTitle="Informazioni sulla connessione WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Copia"
OBSWebSocket.ConnectInfo.ServerIp="IP server (miglior ipotesi)"
OBSWebSocket.ConnectInfo.ServerPort="Porta server"
OBSWebSocket.ConnectInfo.ServerPassword="Password server"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autorizzazione disabilitata]"
OBSWebSocket.ConnectInfo.QrTitle="QR connessione"
OBSWebSocket.TrayNotification.Identified.Title="Nuova connessione WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Identificato client %1."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Errore di autenticazione WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Il client %1 non è riuscito ad autenticarsi."
OBSWebSocket.TrayNotification.Disconnected.Title="Client WebSocket disconnesso"
OBSWebSocket.TrayNotification.Disconnected.Body="Client %1 disconnesso."

41
data/locale/ja-JP.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="WebSocketを介したOBS Studioのリモートコントロール"
OBSWebSocket.Settings.DialogTitle="WebSocket サーバー設定"
OBSWebSocket.Settings.PluginSettingsTitle="プラグイン設定"
OBSWebSocket.Settings.ServerEnable="WebSocketサーバーを有効にする"
OBSWebSocket.Settings.AlertsEnable="システムトレイアラートを有効にする"
OBSWebSocket.Settings.DebugEnable="デバッグログを有効にする"
OBSWebSocket.Settings.DebugEnableHoverText="現在のOBSインスタンスに対してデバッグログを有効にします。ロード時には持続しません。\nロード時に有効にするには --websocket_debug を使用します。"
OBSWebSocket.Settings.ServerSettingsTitle="サーバー設定"
OBSWebSocket.Settings.AuthRequired="認証を有効にする"
OBSWebSocket.Settings.Password="サーバーパスワード"
OBSWebSocket.Settings.GeneratePassword="パスワードを生成"
OBSWebSocket.Settings.ServerPort="サーバーポート"
OBSWebSocket.Settings.ShowConnectInfo="接続情報を表示"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="警告: 現在出力中"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="出力 (配信、録画など) が現在アクティブになっているようです。"
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="接続情報を表示してもよろしいですか?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="警告: 潜在的なセキュリティの問題"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocketはサーバーのパスワードをプレーンテキストとして保存します。 obs-websocketによって生成されたパスワードを使用することを強くお勧めします。"
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="自分が設定したパスワードを使用してもよろしいですか?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="エラー: 無効な設定です"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="6文字以上のパスワードを使用する必要があります。"
OBSWebSocket.SessionTable.Title="接続されているWebSocketセッション"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="リモートアドレス"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="セッション時間"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="メッセージ In/Out"
OBSWebSocket.SessionTable.IdentifiedTitle="識別"
OBSWebSocket.SessionTable.KickButtonColumnTitle="キック?"
OBSWebSocket.SessionTable.KickButtonText="キック"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket接続情報"
OBSWebSocket.ConnectInfo.CopyText="コピー"
OBSWebSocket.ConnectInfo.ServerIp="サーバーIP (推測)"
OBSWebSocket.ConnectInfo.ServerPort="サーバーポート"
OBSWebSocket.ConnectInfo.ServerPassword="サーバーパスワード"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[認証無効]"
OBSWebSocket.ConnectInfo.QrTitle="接続用QRコード"
OBSWebSocket.TrayNotification.Identified.Title="新しいWebSocket接続"
OBSWebSocket.TrayNotification.Identified.Body="クライアント %1 が識別されました。"
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket認証失敗"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="クライアント %1 の認証に失敗しました。"
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocketクライアントが切断されました"
OBSWebSocket.TrayNotification.Disconnected.Body="クライアント %1 が切断されました。"

41
data/locale/ka-GE.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="OBS Studio-ს დაშორებულად მართვა WebSocket-ით"
OBSWebSocket.Settings.DialogTitle="WebSocket-სერვერის პარამეტრები"
OBSWebSocket.Settings.PluginSettingsTitle="მოდულის პარამეტრები"
OBSWebSocket.Settings.ServerEnable="WebSocket-სერვერის ჩართვა"
OBSWebSocket.Settings.AlertsEnable="სისტემური არეში ცნობების ჩართვა"
OBSWebSocket.Settings.DebugEnable="გამართვის აღრიცხვის ჩართვა"
OBSWebSocket.Settings.DebugEnableHoverText="აღირიცხება ამ გაშვებული OBS-ის ჩანაწერები გაუმართაობის მოსაგვარებლად. გაშვებისას არ ნარჩუნდება.\nგამოიენეთ --websocket_debug გაშვებისას ჩასართავად."
OBSWebSocket.Settings.ServerSettingsTitle="სერვერის პარამეტრები"
OBSWebSocket.Settings.AuthRequired="ანგარიშზე შესვლით"
OBSWebSocket.Settings.Password="სერვერის პაროლი"
OBSWebSocket.Settings.GeneratePassword="პაროლის შედგენა"
OBSWebSocket.Settings.ServerPort="სერვერის პორტი"
OBSWebSocket.Settings.ShowConnectInfo="კავშირის შესახებ"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="გაფრთხილება: პირდაპირ ეთერშია"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="როგორც ჩანს, გამოტანა (ნაკადის, ჩანაწერის და სხვ.) ეთერში გადის."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="ნამდვილად გსურთ კავშირის მონაცემების გამოჩენა?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="ყურადღება: სავარაუდო საფრთხე"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket სერვერის პაროლს ტექსტის სახით. დაჟინებით გირჩევთ, გამოიყენოთ obs-websocket-ით შედგენილი პაროლი."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="ნამდვილად გსურთ საკუთარი პაროლის გამოყენება?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="შეცდომა: არასწორი გამართვა"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="პაროლი უნდა შეიცავდეს 6 ან მეტ სიმბოლოს."
OBSWebSocket.SessionTable.Title="დაკავშირებული WebSocket-სეანსები"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="დაშორებული მისამართი"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="სეანსის ხანგრძლივობა"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="მიღებ./გაგზ. შეტყობინებები"
OBSWebSocket.SessionTable.IdentifiedTitle="ამოცნობილი"
OBSWebSocket.SessionTable.KickButtonColumnTitle="გაითიშოს?"
OBSWebSocket.SessionTable.KickButtonText="გათიშვა"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-კავშირის შესახებ"
OBSWebSocket.ConnectInfo.CopyText="ასლი"
OBSWebSocket.ConnectInfo.ServerIp="სერვერის-IP (თვითდადგენით)"
OBSWebSocket.ConnectInfo.ServerPort="სერვერის პორტი"
OBSWebSocket.ConnectInfo.ServerPassword="სერვერის პაროლი"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[ანგარიშზე შეუსვლელად]"
OBSWebSocket.ConnectInfo.QrTitle="კავშირის QR"
OBSWebSocket.TrayNotification.Identified.Title="ახალი WebSocket-კავშირი"
OBSWebSocket.TrayNotification.Identified.Body="კლიენტი %1 აღმოშენილია."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket-შესვლის დამოწმება ვერ მოხერხდა"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="კლიენტი %1 ვერ დამოწმდა."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket-კლიენტი გამოითიშა"
OBSWebSocket.TrayNotification.Disconnected.Body="კლიენტი %1 გამოთიშეულია."

41
data/locale/kmr-TR.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Rêveberina ji dûr ve ya OBS Studio bi riya WebSocket"
OBSWebSocket.Settings.DialogTitle="Sazkariyên rajekar a WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Sazkariyên pêvekê"
OBSWebSocket.Settings.ServerEnable="Rajekarê WebSocket çalak bike"
OBSWebSocket.Settings.AlertsEnable="Hişyariyên darika pergalê çalak bike"
OBSWebSocket.Settings.DebugEnable="Têketinê serrastkirinê çalak bike"
OBSWebSocket.Settings.DebugEnableHoverText="Têketinê serrastkirinê çalak bike ji bo danişîna heyî ya OBS. Li ser barkirinê nadomîne.\nBikaranîna --websocket_debug rê dide bo çalakkirina barkirinê."
OBSWebSocket.Settings.ServerSettingsTitle="Sazkariyên rajekar"
OBSWebSocket.Settings.AuthRequired="Rastandinê çalak bike"
OBSWebSocket.Settings.Password="Borînpeyva rajekar"
OBSWebSocket.Settings.GeneratePassword="Borînpeyvê çê bike"
OBSWebSocket.Settings.ServerPort="Dergeha rajekar"
OBSWebSocket.Settings.ShowConnectInfo="Zanyariyên girêdanê nîşan bide"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Hişyarî: Weşan zindî ye"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Xuye dike ku deraneke (weşan, tomarkirin, hwd.) niha çalak e."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Ma tu bi rastî dixwazî zanyariya girêdana xwe nîşan bidî?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Hişyarî: Pirsgirêka ewlekariya potansiyel"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket borînpeyva rajekarê wekî nivîsek sade hiltîne. Bikaranîna borînpeyva ku ji hêla obs-websocket ve hatî çêkirin pir tê pêşniyar kirin."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Ma tu dixwazî ku borînpeyva xwe bi kar bînî?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Çewtî: Pevsazkirin ne derbasdar e"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Divê tu borînpeyvekê bi kar bînî ku ji 6 an jî bêtir tîpan be."
OBSWebSocket.SessionTable.Title="Danişînên WebSocket ên girêdayî"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Navnîşana ji dûr ve"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Dirêjahiya danişînê"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Peyamên Çûyî/Hatî"
OBSWebSocket.SessionTable.IdentifiedTitle="Naskirî"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Derxîne?"
OBSWebSocket.SessionTable.KickButtonText="Derxîne"
OBSWebSocket.ConnectInfo.DialogTitle="Zanyariyên girêdanê WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Jê bigire"
OBSWebSocket.ConnectInfo.ServerIp="IP ya rajekar (Çêtirîn texmîn)"
OBSWebSocket.ConnectInfo.ServerPort="Dergeha rajekar"
OBSWebSocket.ConnectInfo.ServerPassword="Borînpeyva rajekar"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Rastandin neçalak e]"
OBSWebSocket.ConnectInfo.QrTitle="QR girê bide"
OBSWebSocket.TrayNotification.Identified.Title="Girêdana bû ya WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Rajegir %1 hate naskirin."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Rastandina WebSocket têk çû"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Rastandina rajegir %1 têk çû."
OBSWebSocket.TrayNotification.Disconnected.Title="Girêdana rajegira WebSocket qut bû"
OBSWebSocket.TrayNotification.Disconnected.Body="Girêdana rajegir %1 qut bû."

41
data/locale/ko-KR.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="WebSocket으로 OBS Studio를 원격 제어"
OBSWebSocket.Settings.DialogTitle="WebSocket 서버 설정"
OBSWebSocket.Settings.PluginSettingsTitle="플러그인 설정"
OBSWebSocket.Settings.ServerEnable="WebSocket 서버 사용"
OBSWebSocket.Settings.AlertsEnable="시스템 트레이 알림 사용"
OBSWebSocket.Settings.DebugEnable="디버그 기록 사용"
OBSWebSocket.Settings.DebugEnableHoverText="OBS의 현재 인스턴스에 대해 디버그 기록을 활성화합니다. 불러오는 중에는 기록이 중단됩니다.\n불러오는 중에도 활성화하려면 --websocket_debug 인자를 이용하십시오."
OBSWebSocket.Settings.ServerSettingsTitle="서버 설정"
OBSWebSocket.Settings.AuthRequired="인증 기능 사용"
OBSWebSocket.Settings.Password="서버 비밀번호"
OBSWebSocket.Settings.GeneratePassword="비밀번호 생성"
OBSWebSocket.Settings.ServerPort="서버 포트"
OBSWebSocket.Settings.ShowConnectInfo="서버 정보 표시"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="경고: 현재 활성화 중"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="현재 출력(스트림, 녹화 등)이 활성화된 것으로 보입니다."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="정말로 연결 정보를 표시하시겠습니까?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="경고: 잠재적 보안 문제"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket은 서버 비밀번호를 평문으로 저장합니다. obs-websocket에서 생성한 비밀번호를 사용하는 것을 적극 권장합니다."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="정말로 직접 설정한 비밀번호를 사용하시겠습니까?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="오류: 설정이 유효하지 않음"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="6자 이상의 비밀번호를 사용해야 합니다."
OBSWebSocket.SessionTable.Title="WebSocket 세션에 연결됨"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="원격 주소"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="세션 지속 시간"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="메시지 입출력"
OBSWebSocket.SessionTable.IdentifiedTitle="식별 기록"
OBSWebSocket.SessionTable.KickButtonColumnTitle="퇴장?"
OBSWebSocket.SessionTable.KickButtonText="퇴장"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket 연결 정보"
OBSWebSocket.ConnectInfo.CopyText="복사"
OBSWebSocket.ConnectInfo.ServerIp="서버 IP (추정)"
OBSWebSocket.ConnectInfo.ServerPort="서버 포트"
OBSWebSocket.ConnectInfo.ServerPassword="서버 비밀번호"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[인증 사용 안 함]"
OBSWebSocket.ConnectInfo.QrTitle="연결 QR코드"
OBSWebSocket.TrayNotification.Identified.Title="새 WebSocket 연결"
OBSWebSocket.TrayNotification.Identified.Body="클라이언트 %1 식별 성공."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket 인증 실패"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="클라이언트 %1 인증 실패."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket 클라이언트 연결 해제됨"
OBSWebSocket.TrayNotification.Disconnected.Body="클라이언트 %1 연결 해제됨."

41
data/locale/ms-MY.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Kawalan-jauh OBS Studio melalui WebSocket"
OBSWebSocket.Settings.DialogTitle="Tetapan Pelayan WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Tetapan Pemalam"
OBSWebSocket.Settings.ServerEnable="Benarkan pelayan WebSocket"
OBSWebSocket.Settings.AlertsEnable="Benarkan Amaran Talam Sistem"
OBSWebSocket.Settings.DebugEnable="Benarkan Pegelogan Nyahpepijat"
OBSWebSocket.Settings.DebugEnableHoverText="Membenarkan pengelogan nyahpepijat bagi kejadian OBS semasa. Tidak ditetapkan ketika muat.\nGuna --websocket_debug untuk didayakan ketika muat."
OBSWebSocket.Settings.ServerSettingsTitle="Tetapan Pelayan"
OBSWebSocket.Settings.AuthRequired="Benarkan Pengesahihan"
OBSWebSocket.Settings.Password="Kata Laluan Pelayan"
OBSWebSocket.Settings.GeneratePassword="Jana Kata Lauan"
OBSWebSocket.Settings.ServerPort="Port Pelayan"
OBSWebSocket.Settings.ShowConnectInfo="Tunjuk Maklumat Sambungan"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Amaran: Sedang Berlangsung"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Nampaknya ada output (strim, rakaman, dll.) masih aktif."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Anda pasti mahu menunjukkan maklumat sambungan anda?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Amaran: Isu Keselamatan Mungkin Ada"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket menyimpan kata laluan pelayan dalam bentuk teks biasa. Menggunakan kata laluan yang dijana oleh obs-websocket iadalah sangat disarankan."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Adakah anda pasti mahu menggunakan kata laluan anda sendiri?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Ralat: Konfigurasi Tidak Sah"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Anda mesti guna satu kata laluan yang terdiri daripada 6 atau lebih aksara."
OBSWebSocket.SessionTable.Title="Sesi WebSocket Bersambung"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Alamat Jauh"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Tempoh Sesi"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Mesej Masuk/Keluar"
OBSWebSocket.SessionTable.IdentifiedTitle="Dikenal Pasti"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Tendang?"
OBSWebSocket.SessionTable.KickButtonText="Tendang"
OBSWebSocket.ConnectInfo.DialogTitle="Maklumat Sambungan WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Salin"
OBSWebSocket.ConnectInfo.ServerIp="IP Pelayan (Tekaan Terbaik)"
OBSWebSocket.ConnectInfo.ServerPort="Port Pelayan"
OBSWebSocket.ConnectInfo.ServerPassword="Kata Laluan Pelayan"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Izin Dilumpuh]"
OBSWebSocket.ConnectInfo.QrTitle="QR Sambungan"
OBSWebSocket.TrayNotification.Identified.Title="Sambungan WebSocket Baharu"
OBSWebSocket.TrayNotification.Identified.Body="Klien %1 dikenal past."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Kegagalan Pengesahihan WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Klien %1 gagal disahihkan."
OBSWebSocket.TrayNotification.Disconnected.Title="Klien WebSocket Terputus"
OBSWebSocket.TrayNotification.Disconnected.Body="Klien %1 terputus."

25
data/locale/nb-NO.ini Normal file
View File

@ -0,0 +1,25 @@
OBSWebSocket.Settings.DialogTitle="WebSocket-tjenerinnstillinger"
OBSWebSocket.Settings.PluginSettingsTitle="Utvidelsesinnstillinger"
OBSWebSocket.Settings.ServerSettingsTitle="Tjenerinnstillinger"
OBSWebSocket.Settings.AuthRequired="Skru på autentisering"
OBSWebSocket.Settings.Password="Server Passord"
OBSWebSocket.Settings.GeneratePassword="Generer Passord"
OBSWebSocket.Settings.ShowConnectInfo="Vis tilkoblingsinfo"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Advarsel: For øyeblikket på direktesending"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Advarsel: Potensielt sikkerhetsproblem"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Feil: Ugyldig konfigurasjon"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Du må bruke et passord på minst 6 tegn."
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Ekstern adresse"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Øktens varighet"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Innboks/Utboks"
OBSWebSocket.SessionTable.IdentifiedTitle="Identifisert"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket-tilkoblingsinfo"
OBSWebSocket.ConnectInfo.CopyText="Kopier"
OBSWebSocket.ConnectInfo.ServerIp="Tjenerens IP (beste gjetning)"
OBSWebSocket.ConnectInfo.ServerPort="Tjenerport"
OBSWebSocket.ConnectInfo.ServerPassword="Tjenerpassord"
OBSWebSocket.ConnectInfo.QrTitle="QR-tilkobling"
OBSWebSocket.TrayNotification.Identified.Title="Ny WebSocket-tilkobling"
OBSWebSocket.TrayNotification.Identified.Body="Klient %1 er identifisert."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket-klient koblet fra"
OBSWebSocket.TrayNotification.Disconnected.Body="Klient %1 koblet fra."

41
data/locale/nl-NL.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Op afstand bediening van OBS Studio via WebSocket"
OBSWebSocket.Settings.DialogTitle="WebSocket Server Instellingen"
OBSWebSocket.Settings.PluginSettingsTitle="Plugin instellingen"
OBSWebSocket.Settings.ServerEnable="WebSocket server inschakelen"
OBSWebSocket.Settings.AlertsEnable="Systeemtray meldingen inschakelen"
OBSWebSocket.Settings.DebugEnable="Activeer debug logging"
OBSWebSocket.Settings.DebugEnableHoverText="Schakelt debug logboekregistratie in voor de huidige instantie van OBS. Blijft niet meer te laden.\nGebruik --websocket_debug om bij laden in te schakelen."
OBSWebSocket.Settings.ServerSettingsTitle="Serverinstellingen"
OBSWebSocket.Settings.AuthRequired="Authenticatie inschakelen"
OBSWebSocket.Settings.Password="Server wachtwoord"
OBSWebSocket.Settings.GeneratePassword="Wachtwoord genereren"
OBSWebSocket.Settings.ServerPort="Serverpoort"
OBSWebSocket.Settings.ShowConnectInfo="Toon verbindingsinformatie"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Waarschuwing: Op dit moment live"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Het lijkt erop dat een output (stream, opname, etc.) momenteel actief is."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Weet je zeker dat je je verbindingsinformatie wilt laten zien?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Waarschuwing: potentieel beveiligingsprobleem"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket slaat het serverwachtwoord op als platte tekst. Het gebruik van een wachtwoord dat wordt gegenereerd door een obs-websocket wordt sterk aanbevolen."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Weet u zeker dat u uw eigen wachtwoord wilt gebruiken?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Fout: ongeldige configuratie"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="U moet een wachtwoord gebruiken van 6 of meer tekens."
OBSWebSocket.SessionTable.Title="Verbonden WebSocket Sessies"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Extern adres"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Sessie duur"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Berichten In/Uit"
OBSWebSocket.SessionTable.IdentifiedTitle="Geïdentificeerd"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Verwijderen?"
OBSWebSocket.SessionTable.KickButtonText="Verwijderen"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket verbindingsinformatie"
OBSWebSocket.ConnectInfo.CopyText="Kopiëren"
OBSWebSocket.ConnectInfo.ServerIp="Server IP (Beste inschatting)"
OBSWebSocket.ConnectInfo.ServerPort="Serverpoort"
OBSWebSocket.ConnectInfo.ServerPassword="Serverwachtwoord"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Authenticatie Uitgeschakeld]"
OBSWebSocket.ConnectInfo.QrTitle="QR koppelen"
OBSWebSocket.TrayNotification.Identified.Title="Nieuwe WebSocket verbinding"
OBSWebSocket.TrayNotification.Identified.Body="Client %1 geïdentificeerd."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket Authenticatie Fout"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Authenticatie van client %1 mislukt."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket Client losgekoppeld"
OBSWebSocket.TrayNotification.Disconnected.Body="Client %1 ontkoppeld."

41
data/locale/pl-PL.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Zdalna kontrola OBS Studio przez WebSocket"
OBSWebSocket.Settings.DialogTitle="Ustawienia serwera WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Ustawienia wtyczki"
OBSWebSocket.Settings.ServerEnable="Włącz serwer WebSocket"
OBSWebSocket.Settings.AlertsEnable="Włącz powiadomienia w zasobniku systemowym"
OBSWebSocket.Settings.DebugEnable="Włącz logowanie debugowania"
OBSWebSocket.Settings.DebugEnableHoverText="Włącza logowanie debugowania dla bieżącej instancji OBS. Opcja nie jest włączana przy ładowaniu aplikacji.\nUżyj --websocket_debug, aby włączyć logowanie debugowania przy ładowaniu aplikacji."
OBSWebSocket.Settings.ServerSettingsTitle="Ustawienia serwera"
OBSWebSocket.Settings.AuthRequired="Włącz uwierzytelnianie"
OBSWebSocket.Settings.Password="Hasło serwera"
OBSWebSocket.Settings.GeneratePassword="Wygeneruj hasło"
OBSWebSocket.Settings.ServerPort="Port serwera"
OBSWebSocket.Settings.ShowConnectInfo="Pokaż informacje połączenia"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Ostrzeżenie: Trwa transmisja lub nagranie"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Wygląda na to, że trwa transmisja lub nagrywanie."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Czy na pewno chcesz pokazać informacje połączenia?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Ostrzeżenie: Potencjalny problem bezpieczeństwa"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket przechowuje hasło serwera jako zwykły tekst. Wysoce zalecane jest użycie hasła generowanego przez obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Czy na pewno chcesz użyć własnego hasła?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Błąd: Nieprawidłowa konfiguracja"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Musisz użyć hasła, które ma 6 lub więcej znaków."
OBSWebSocket.SessionTable.Title="Podłączone sesje WebSocket"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adres zdalny"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Czas trwania sesji"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Wiadomości przychodzące/wychodzące"
OBSWebSocket.SessionTable.IdentifiedTitle="Zidentyfikowany"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Odłączyć?"
OBSWebSocket.SessionTable.KickButtonText="Odłącz"
OBSWebSocket.ConnectInfo.DialogTitle="Informacje o połączeniu WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Kopiuj"
OBSWebSocket.ConnectInfo.ServerIp="IP serwera (ustalone w miarę możliwości)"
OBSWebSocket.ConnectInfo.ServerPort="Port serwera"
OBSWebSocket.ConnectInfo.ServerPassword="Hasło serwera"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autoryzacja wyłączona]"
OBSWebSocket.ConnectInfo.QrTitle="Kod QR połączenia"
OBSWebSocket.TrayNotification.Identified.Title="Nowe połączenie WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Klient %1 zidentyfikowany."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Błąd uwierzytelniania WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Klient %1 nie został uwierzytelniony."
OBSWebSocket.TrayNotification.Disconnected.Title="Klient WebSocket odłączony"
OBSWebSocket.TrayNotification.Disconnected.Body="Klient %1 odłączony."

41
data/locale/pt-BR.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Controle remoto do OBS Studio através de WebSocket"
OBSWebSocket.Settings.DialogTitle="Configurações do servidor WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Configurações de Plugin"
OBSWebSocket.Settings.ServerEnable="Ativar servidor WebSocket"
OBSWebSocket.Settings.AlertsEnable="Ativar Alertas da Bandeja do Sistema"
OBSWebSocket.Settings.DebugEnable="Habilitar log de depuração"
OBSWebSocket.Settings.DebugEnableHoverText="Ativa o registro de depuração para a instância atual do OBS. Não persiste ao carregar.\nUse --websocket_debug para ativar no carregamento."
OBSWebSocket.Settings.ServerSettingsTitle="Configurações de Servidor"
OBSWebSocket.Settings.AuthRequired="Habilitar Autenticação"
OBSWebSocket.Settings.Password="Senha de Servidor"
OBSWebSocket.Settings.GeneratePassword="Gerar Senha"
OBSWebSocket.Settings.ServerPort="Porta de Servidor"
OBSWebSocket.Settings.ShowConnectInfo="Mostrar Informações de Conexão"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Aviso: Atualmente Ao Vivo"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Parece que uma saída (stream, gravação, etc.) está atualmente ativa."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Tem certeza de que deseja mostrar suas informações de conexão?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Aviso: Problema de Segurança Potencial"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket armazena a senha do servidor como texto sem formatação. Usar uma senha gerada pela obs-websocket é altamente recomendada."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Tem certeza de que deseja usar a sua própria senha?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Erro: Configuração Inválida"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Você deve usar uma senha que tenha 6 ou mais caracteres."
OBSWebSocket.SessionTable.Title="Sessões WebSocket Conectadas"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Endereço Remoto"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Duração de Sessão"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Mensagens"
OBSWebSocket.SessionTable.IdentifiedTitle="Identificada"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Expulsar?"
OBSWebSocket.SessionTable.KickButtonText="Expulsar"
OBSWebSocket.ConnectInfo.DialogTitle="Informação de Conexão WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Copiar"
OBSWebSocket.ConnectInfo.ServerIp="IP do servidor (Melhor Chute)"
OBSWebSocket.ConnectInfo.ServerPort="Porta de Servidor"
OBSWebSocket.ConnectInfo.ServerPassword="Senha de Servidor"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autenticação Desativada]"
OBSWebSocket.ConnectInfo.QrTitle="QR da conexão"
OBSWebSocket.TrayNotification.Identified.Title="Nova Conexão de WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Cliente %1 identificado."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Falha na Autenticação de WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Cliente %1 falhou na autenticação."
OBSWebSocket.TrayNotification.Disconnected.Title="Cliente WebSocket Desconectado"
OBSWebSocket.TrayNotification.Disconnected.Body="Cliente %1 desconectado."

41
data/locale/pt-PT.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Controlo remoto do OBS Studio através de WebSocket"
OBSWebSocket.Settings.DialogTitle="Definições do servidor WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Configurações do plugin"
OBSWebSocket.Settings.ServerEnable="Ativar servidor WebSocket"
OBSWebSocket.Settings.AlertsEnable="Ativar alertas da bandeja do sistema"
OBSWebSocket.Settings.DebugEnable="Ativar registo de depuração"
OBSWebSocket.Settings.DebugEnableHoverText="Ativa o registro de depuração para a instância atual do OBS. Não persiste no arranque.\nUse --websocket_debug para ativar no arranque."
OBSWebSocket.Settings.ServerSettingsTitle="Configurações do servidor"
OBSWebSocket.Settings.AuthRequired="Ativar autenticação"
OBSWebSocket.Settings.Password="Senha do servidor"
OBSWebSocket.Settings.GeneratePassword="Gerar senha"
OBSWebSocket.Settings.ServerPort="Porta do servidor"
OBSWebSocket.Settings.ShowConnectInfo="Mostrar informações de conexão"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Aviso: Atualmente ao vivo"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Parece que uma saída (transmissão, gravação, etc.) está atualmente ativa."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Tem certeza de que deseja mostrar as suas informações de ligação?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Aviso: Possível problema de segurança"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="O obs-websocket armazena a senha do servidor como texto sem formatação. É altamente recomendado usar uma senha gerada pelo obs-websocket ."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Tem a certeza de que deseja usar as suas próprias senhas?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Erro: Configuração inválida"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Deve usar uma senha que tenha 6 ou mais caracteres."
OBSWebSocket.SessionTable.Title="Sessões WebSocket ligadas"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Endereço remoto"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Duração da sessão"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Entrada/Saída de mensagens"
OBSWebSocket.SessionTable.IdentifiedTitle="Identificado"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Expulsar?"
OBSWebSocket.SessionTable.KickButtonText="Expulsar"
OBSWebSocket.ConnectInfo.DialogTitle="Informação de ligação WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Copiar"
OBSWebSocket.ConnectInfo.ServerIp="IP do servidor (melhor cálculo)"
OBSWebSocket.ConnectInfo.ServerPort="Porta do servidor"
OBSWebSocket.ConnectInfo.ServerPassword="Senha do servidor"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autenticação desativada]"
OBSWebSocket.ConnectInfo.QrTitle="Código QR de ligação"
OBSWebSocket.TrayNotification.Identified.Title="Nova conexão de WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Cliente %1 identificado."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Falha na autenticação de WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Cliente %1 falhou na autenticação."
OBSWebSocket.TrayNotification.Disconnected.Title="Cliente WebSocket desligado"
OBSWebSocket.TrayNotification.Disconnected.Body="Cliente %1 desligado."

41
data/locale/ro-RO.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Control de la distanță pentru OBS Studio prin WebSocket"
OBSWebSocket.Settings.DialogTitle="Setări pentru serverul WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Setări pentru plugin"
OBSWebSocket.Settings.ServerEnable="Activează serverul WebSocket"
OBSWebSocket.Settings.AlertsEnable="Activează alertele din bara de sistem"
OBSWebSocket.Settings.DebugEnable="Activează jurnalizarea pentru depanare"
OBSWebSocket.Settings.DebugEnableHoverText="Activează jurnalizarea pentru depanare în cazul instanței actuale de OBS. Nu persistă la încărcare.\nFolosește --websocket_debug pentru a activa la încărcare."
OBSWebSocket.Settings.ServerSettingsTitle="Setări pentru server"
OBSWebSocket.Settings.AuthRequired="Activează autentificarea"
OBSWebSocket.Settings.Password="Parola serverului"
OBSWebSocket.Settings.GeneratePassword="Generează parola"
OBSWebSocket.Settings.ServerPort="Portul serverului"
OBSWebSocket.Settings.ShowConnectInfo="Afișează informațiile conexiunii"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Avertisment: În prezent în direct"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Se pare că un output (transmisiune, înregistrare etc.) este activ în prezent."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Sigur vrei să afișezi informațiile de conectare?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Avertisment: Potențială problemă de securitate"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket stochează parola serverului ca text simplu. Este foarte recomandat să folosiți o parolă generată de obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Sigur vrei să-ți folosești propria parolă?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Eroare: Configurație invalidă"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Trebuie să folosești o parolă care să aibă 6 sau mai multe caractere."
OBSWebSocket.SessionTable.Title="Sesiuni WebSocket conectate"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Adresă la distanță"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Durata sesiunii"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Mesaje de intrare/ieșire"
OBSWebSocket.SessionTable.IdentifiedTitle="Identificat"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Înlături?"
OBSWebSocket.SessionTable.KickButtonText="Înlătură"
OBSWebSocket.ConnectInfo.DialogTitle="Informațiile conexiunii WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Copiază"
OBSWebSocket.ConnectInfo.ServerIp="IP-ul serverului (cea mai bună presupunere)"
OBSWebSocket.ConnectInfo.ServerPort="Portul serverului"
OBSWebSocket.ConnectInfo.ServerPassword="Parola serverului"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autentificare dezactivată]"
OBSWebSocket.ConnectInfo.QrTitle="QR de conectare"
OBSWebSocket.TrayNotification.Identified.Title="O nouă conexiune WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Clientul %1 identificat."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Eroare de autentificare WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Client %1 nu a reușit să se autentifice."
OBSWebSocket.TrayNotification.Disconnected.Title="Client WebSocket deconectat"
OBSWebSocket.TrayNotification.Disconnected.Body="Clientul %1 s-a deconectat."

41
data/locale/ru-RU.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Удалённое управление OBS Studio по WebSocket"
OBSWebSocket.Settings.DialogTitle="Настройки сервера WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Настройки плагина"
OBSWebSocket.Settings.ServerEnable="Включить сервер WebSocket"
OBSWebSocket.Settings.AlertsEnable="Включить оповещения в трее"
OBSWebSocket.Settings.DebugEnable="Включить отладочный журнал"
OBSWebSocket.Settings.DebugEnableHoverText="Включает ведение журнала отладки для текущего экземпляра OBS. Не сохраняется при запуске.\nИспользуйте --websocket_debug для включения при запуске."
OBSWebSocket.Settings.ServerSettingsTitle="Настройки сервера"
OBSWebSocket.Settings.AuthRequired="Включить вход в аккаунт"
OBSWebSocket.Settings.Password="Пароль сервера"
OBSWebSocket.Settings.GeneratePassword="Создать пароль"
OBSWebSocket.Settings.ServerPort="Порт сервера"
OBSWebSocket.Settings.ShowConnectInfo="Показать сведения о подключении"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Предупреждение: Сейчас в эфире"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Похоже, что вывод (поток, запись и т. д.) в настоящее время уже выбран."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Уверены, что хотите показать ваши сведения о подключении?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Предупреждение: Потенциальная проблема безопасности"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket хранит пароль сервера в виде обычного текста. Настоятельно рекомендуется использовать пароль, сгенерированный obs-websock."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Уверены, что хотите использовать собственый пароль?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Ошибка: Неверная конфигурация"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Вы должны использовать пароль длиной 6 или более символов."
OBSWebSocket.SessionTable.Title="Подключённые сеансы WebSocket"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Удалённый адрес"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Длительность сеанса"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Вх./исх. сообщения"
OBSWebSocket.SessionTable.IdentifiedTitle="Распознано"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Выгнать?"
OBSWebSocket.SessionTable.KickButtonText="Выгнать"
OBSWebSocket.ConnectInfo.DialogTitle="Сведения о подключении WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Копировать"
OBSWebSocket.ConnectInfo.ServerIp="IP сервера (лучшая догадка)"
OBSWebSocket.ConnectInfo.ServerPort="Порт сервера"
OBSWebSocket.ConnectInfo.ServerPassword="Пароль сервера"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Вход отключён]"
OBSWebSocket.ConnectInfo.QrTitle="QR-код подключения"
OBSWebSocket.TrayNotification.Identified.Title="Новое подключение WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Клиент %1 распознан."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Ошибка входа WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Клиент %1 не смог войти."
OBSWebSocket.TrayNotification.Disconnected.Title="Клиент WebSocket отключился"
OBSWebSocket.TrayNotification.Disconnected.Body="Клиент %1 отключился."

22
data/locale/si-LK.ini Normal file
View File

@ -0,0 +1,22 @@
OBSWebSocket.Settings.PluginSettingsTitle="පේනුවේ සැකසුම්"
OBSWebSocket.Settings.DebugEnable="නිදොස්කරණ සටහන් තැබීම සබල කරන්න"
OBSWebSocket.Settings.ServerSettingsTitle="සේවාදායකයේ සැකසුම්"
OBSWebSocket.Settings.AuthRequired="සත්‍යාපනය සබල කරන්න"
OBSWebSocket.Settings.Password="සේවාදායකයේ මුරපදය"
OBSWebSocket.Settings.GeneratePassword="මුරපදය උත්පාදනය"
OBSWebSocket.Settings.ServerPort="සේවාදායකයේ තොට"
OBSWebSocket.Settings.ShowConnectInfo="සබඳතාවේ තොරතුරු පෙන්වන්න"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="අවවාදයයි: දැනට සජීවයි"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="දුරස්ථ ලිපිනය"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="වාරයේ පරාසය"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="පණිවිඩ එන/යන"
OBSWebSocket.SessionTable.IdentifiedTitle="හඳුනා ගැනිණි"
OBSWebSocket.ConnectInfo.CopyText="පිටපතක්"
OBSWebSocket.ConnectInfo.ServerIp="සේවාදායකයේ අ.ජා.කෙ. (අනුමානය)"
OBSWebSocket.ConnectInfo.ServerPort="සේවාදායකයේ තොට"
OBSWebSocket.ConnectInfo.ServerPassword="සේවාදායකයේ මුරපදය"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[සත්‍යාපනය අබලයි]"
OBSWebSocket.ConnectInfo.QrTitle="සබැඳුමට QR"
OBSWebSocket.TrayNotification.Identified.Body="දැන් %1 අනුග්‍රාහකය හඳුනයි."
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="%1 අනුග්‍රාහකය සත්‍යාපනයට අසමත්!"
OBSWebSocket.TrayNotification.Disconnected.Body="%1 අනුග්‍රාහකය විසන්ධියි."

41
data/locale/sk-SK.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Vzdialené ovládanie OBS Štúdia cez WebSocket"
OBSWebSocket.Settings.DialogTitle="Serverové nastavenia WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Nastavenia pluginu"
OBSWebSocket.Settings.ServerEnable="Zapnúť WebSocket server"
OBSWebSocket.Settings.AlertsEnable="Zapnúť notifikácie zo systémovej lišty"
OBSWebSocket.Settings.DebugEnable="Zapnúť debug logovanie"
OBSWebSocket.Settings.DebugEnableHoverText="Zapne debug logovanie pre momentálnu inštanciu OBS. Nezotrvá po načítaní.\nPoužite --websocket_debug pre zapnutie pri načítaní."
OBSWebSocket.Settings.ServerSettingsTitle="Nastavenia servera"
OBSWebSocket.Settings.AuthRequired="Zapnúť autentifikáciu"
OBSWebSocket.Settings.Password="Serverové heslo"
OBSWebSocket.Settings.GeneratePassword="Vygenerovať heslo"
OBSWebSocket.Settings.ServerPort="Serverový port"
OBSWebSocket.Settings.ShowConnectInfo="Zobraziť info pripojenia"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Varovanie: Momentálne naživo"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Zdá sa, že nejaký výstup (stream, nahrávanie, atď.) je momentálne aktívny."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Ste si istí, že chcete zobraziť info vašeho pripojenia?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Varovanie: Potenciálny bezpečnostný problém"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket ukladá serverové heslo ako obyčajný text. Použitie vygenerovaného hesla pre obs-websocket je vysoko odporúčané."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Ste si istí, že chcete použiť svoje vlastné heslo?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Chyba: Neplatná konfigurácia"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Musíte zadať heslo, ktoré má 6 alebo viac znakov."
OBSWebSocket.SessionTable.Title="Pripojené WebSocket relácie"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Vzdialená adresa"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Travnie relácie"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Správy dnu/von"
OBSWebSocket.SessionTable.IdentifiedTitle="Identifikovaný"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Vyhodiť?"
OBSWebSocket.SessionTable.KickButtonText="Vyhodiť"
OBSWebSocket.ConnectInfo.DialogTitle="Info WebSocket pripojenia"
OBSWebSocket.ConnectInfo.CopyText="Kopírovať"
OBSWebSocket.ConnectInfo.ServerIp="IP servera (najlepší odhad)"
OBSWebSocket.ConnectInfo.ServerPort="Serverový port"
OBSWebSocket.ConnectInfo.ServerPassword="Serverové heslo"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autentifikácia vypnutá]"
OBSWebSocket.ConnectInfo.QrTitle="QR kód pripojenia"
OBSWebSocket.TrayNotification.Identified.Title="Nové WebSocket pripojenie"
OBSWebSocket.TrayNotification.Identified.Body="Klient %1 identifikovaný."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Zlyhanie WebSocket autentifikácie"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Klientovi %1 sa nepodarilo autentifikovať."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket klient odpojený"
OBSWebSocket.TrayNotification.Disconnected.Body="Klient %1 odpojený."

41
data/locale/sl-SI.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Oddaljeni nadzor OBS Studia prek WebSocketa"
OBSWebSocket.Settings.DialogTitle="Nastavitve strežnika WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Nastavitve vtičnika"
OBSWebSocket.Settings.ServerEnable="Omogoči strežnik WebSocket"
OBSWebSocket.Settings.AlertsEnable="Omogoči opozorila v sistemskem pladnju"
OBSWebSocket.Settings.DebugEnable="Omogoči beleženje napak"
OBSWebSocket.Settings.DebugEnableHoverText="Omogoči beleženje dogodkov za potrebe razhroščevanja v trenutno zagnani inačici OBS. Ne vztraja ob nalaganju.\nUporabbite --websocket_debug, da to možnost omogočite ob nalaganju."
OBSWebSocket.Settings.ServerSettingsTitle="Nastavitve strežnika"
OBSWebSocket.Settings.AuthRequired="Omogoči overjanje"
OBSWebSocket.Settings.Password="Geslo strežnika"
OBSWebSocket.Settings.GeneratePassword="Tvori geslo"
OBSWebSocket.Settings.ServerPort="Vrata strežnika"
OBSWebSocket.Settings.ShowConnectInfo="Pokaži podatke o povezavi"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Opozorilo: trenutno v živo"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Kaže, da je izhod (tok, posnetek itn.) trenutno dejaven."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Ali ste prepričani, da želite pokazati svoje podatke za povezavo?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Opozorilo: potencialna varnostna težava"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket hrani geslo strežnika kot navadno besedilo. Uporaba gesla, ki ga ustvari obs-websocket je zato zelo priporočena."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Ali ste prepričani, da želite uporabiti lastno geslo?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Napaka: neveljavna prilagoditev"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Uporabiti morate geslo z vsaj 6 znaki."
OBSWebSocket.SessionTable.Title="Povezane seje WebSocket"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Oddaljen naslov"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Trajanje seje"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Sporočila V/I"
OBSWebSocket.SessionTable.IdentifiedTitle="Identificirano"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Odvrzi?"
OBSWebSocket.SessionTable.KickButtonText="Odvrzi"
OBSWebSocket.ConnectInfo.DialogTitle="Podatki o povezavi WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Kopiraj"
OBSWebSocket.ConnectInfo.ServerIp="IP strežnika (naj-domneva)"
OBSWebSocket.ConnectInfo.ServerPort="Vrata strežnika"
OBSWebSocket.ConnectInfo.ServerPassword="Geslo strežnika"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Overjanje onemog.]"
OBSWebSocket.ConnectInfo.QrTitle="Koda QR za povezavo"
OBSWebSocket.TrayNotification.Identified.Title="Nova povezava WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Odjemalec %1 identificiran."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Spodletelo ovetjanje WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Odjemalec %1 ni prestal overjanja."
OBSWebSocket.TrayNotification.Disconnected.Title="Odjemalec WebSocket je prekinil povezavo"
OBSWebSocket.TrayNotification.Disconnected.Body="Odjemalec %1 ni več povezan."

41
data/locale/sv-SE.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Fjärrkontroll av OBS Studio via WebSocket"
OBSWebSocket.Settings.DialogTitle="WebSocket-serverinställningar"
OBSWebSocket.Settings.PluginSettingsTitle="Insticksmodulsinställningar"
OBSWebSocket.Settings.ServerEnable="Aktivera WebSocket-server"
OBSWebSocket.Settings.AlertsEnable="Aktivera systemfältsmeddelanden"
OBSWebSocket.Settings.DebugEnable="Aktivera felsökningsloggning"
OBSWebSocket.Settings.DebugEnableHoverText="Aktiverar felsökningsloggning för den aktuella instansen av OBS. Stannar inte igång vid inläsning.\nAnvänd --websocket_debug för att aktivera vid inläsning."
OBSWebSocket.Settings.ServerSettingsTitle="Serverinställningar"
OBSWebSocket.Settings.AuthRequired="Aktivera autentisering"
OBSWebSocket.Settings.Password="Serverlösenord"
OBSWebSocket.Settings.GeneratePassword="Generera lösenord"
OBSWebSocket.Settings.ServerPort="Serverport"
OBSWebSocket.Settings.ShowConnectInfo="Visa anslutningsinformation"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Varning: Sänder för närvarande"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Det verkar som om en utmatning (ström, inspelning, etc.) är för närvarande aktiv."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Är du säker på att du vill visa din anslutningsinformation?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Varning: Potentiellt säkerhetsproblem"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket lagrar serverns lösenord som vanlig text. Det kommenderas starkt att använda ett lösenord som genereras av obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Är du säker på att du vill använda ditt eget lösenord?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Fel: Ogiltig konfiguration"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Du måste använda ett lösenord som har 6 eller fler tecken."
OBSWebSocket.SessionTable.Title="Anslutna WebSocket-sessioner"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Fjärradress"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Sessionens varaktighet"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Meddelanden in/ut"
OBSWebSocket.SessionTable.IdentifiedTitle="Identifierad"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Sparka ut?"
OBSWebSocket.SessionTable.KickButtonText="Sparka ut"
OBSWebSocket.ConnectInfo.DialogTitle="Anslutningsinfo för WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Kopiera"
OBSWebSocket.ConnectInfo.ServerIp="Server-IP (uppskattad)"
OBSWebSocket.ConnectInfo.ServerPort="Serverport"
OBSWebSocket.ConnectInfo.ServerPassword="Serverlösenord"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Autentisering inaktiverad]"
OBSWebSocket.ConnectInfo.QrTitle="QR för anslutning"
OBSWebSocket.TrayNotification.Identified.Title="Ny WebSocket-anslutning"
OBSWebSocket.TrayNotification.Identified.Body="Klient %1 har identifierats."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Autentisering av WebSocket misslyckades"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Klient %1 misslyckades att autentiseras."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket-klient frånkopplades"
OBSWebSocket.TrayNotification.Disconnected.Body="Klient %1 frånkopplades."

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

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="WebSocket aracılığıyla uzaktan OBS Studio"
OBSWebSocket.Settings.DialogTitle="WebSocket Suncusu Ayarları"
OBSWebSocket.Settings.PluginSettingsTitle="Eklenti Ayarları"
OBSWebSocket.Settings.ServerEnable="WebSocket sunucuyu etkinleştir"
OBSWebSocket.Settings.AlertsEnable="Sistem Tepsi Uyarılarını Etkinleştir"
OBSWebSocket.Settings.DebugEnable="Hata Ayıklama Günlüğünü Etkinleştir"
OBSWebSocket.Settings.DebugEnableHoverText="OBS'in geçerli örneği için hata ayıklama günlüğünü etkinleştirir. Yüklemede kalıcı değildir.\nYüklemede etkinleştirmek için -- websocket_debug kullanın."
OBSWebSocket.Settings.ServerSettingsTitle="Sunucu Ayarları"
OBSWebSocket.Settings.AuthRequired="Kimlik Doğrulamasını Etkinleştir"
OBSWebSocket.Settings.Password="Sunucu Parolası"
OBSWebSocket.Settings.GeneratePassword="Parola oluştur"
OBSWebSocket.Settings.ServerPort="Sunucu Portu"
OBSWebSocket.Settings.ShowConnectInfo="Bağlanma Bilgilerini Göster"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Uyarı: Şu Anda Canlı"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Şu anda bir çıkış (yayın, kayıt, vb.) aktif görünüyor."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Bağlanma bilgilerinizi göstermek istediğinizden emin misiniz?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Uyarı: Olası Güvenlik Sorunu"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket sunucu parolasını düz metin olarak saklar. Obs-websocket tarafından oluşturulan bir parola kullanılması şiddetle tavsiye edilir."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Kendi parolanızı kullanmak istediğinizden emin misiniz?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Hata: Geçersiz Yapılandırma"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="6 veya daha fazla karakterden oluşan bir şifre kullanmalısınız."
OBSWebSocket.SessionTable.Title="Bağlı WebSocket Oturumları"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Uzaktaki Adres"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Oturum Süresi"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Gelen/Giden Mesajlar"
OBSWebSocket.SessionTable.IdentifiedTitle="Tanımlandı"
OBSWebSocket.SessionTable.KickButtonColumnTitle=ıkarılsın mı?"
OBSWebSocket.SessionTable.KickButtonText=ıkar"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket Bağlanma Bilgileri"
OBSWebSocket.ConnectInfo.CopyText="Kopyala"
OBSWebSocket.ConnectInfo.ServerIp="Sunucu IP (En İyi Tahmin)"
OBSWebSocket.ConnectInfo.ServerPort="Sunucu Portu"
OBSWebSocket.ConnectInfo.ServerPassword="Sunucu Parolası"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Doğrulama Devre Dışı]"
OBSWebSocket.ConnectInfo.QrTitle="Kare Kod ile Bağlan"
OBSWebSocket.TrayNotification.Identified.Title="Yeni WebSocket Bağlantısı"
OBSWebSocket.TrayNotification.Identified.Body="%1 istemcisi tanımlandı."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket Kimlik Doğrulama Hatası"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="%1 istemcisinin kimlik doğrulaması başarısız oldu."
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket İstemcisinin Bağlantısı Kesildi"
OBSWebSocket.TrayNotification.Disconnected.Body="%1 istemcisinin bağlantısı kesildi."

2
data/locale/ug-CN.ini Normal file
View File

@ -0,0 +1,2 @@
OBSWebSocket.Settings.GeneratePassword="ئىم ھاسىللا"
OBSWebSocket.ConnectInfo.CopyText="كۆچۈر"

41
data/locale/uk-UA.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="Віддалене керування OBS Studio через WebSocket"
OBSWebSocket.Settings.DialogTitle="Налаштування WebSocket сервера"
OBSWebSocket.Settings.PluginSettingsTitle="Налаштування плагіна"
OBSWebSocket.Settings.ServerEnable="Увімкнути сервер WebSocket"
OBSWebSocket.Settings.AlertsEnable="Увімкнути сповіщення у системному лотку"
OBSWebSocket.Settings.DebugEnable="Увімкнути журнал налагодження"
OBSWebSocket.Settings.DebugEnableHoverText="Вмикає журналювання налагодження для поточного екземпляра OBS. Не зберігається під час завантаження.\nВикористовуйте --websocket_debug для увімкнення під час завантаження."
OBSWebSocket.Settings.ServerSettingsTitle="Налаштування сервера"
OBSWebSocket.Settings.AuthRequired="Увімкнути автентифікацію"
OBSWebSocket.Settings.Password="Пароль сервера"
OBSWebSocket.Settings.GeneratePassword="Згенерувати пароль"
OBSWebSocket.Settings.ServerPort="Порт сервера"
OBSWebSocket.Settings.ShowConnectInfo="Показати відомості про з'єднання"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Попередження: Трансляція наживо"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Схоже, що вивід (потік, запис тощо) зараз активний."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Ви впевнені, що хочете показати ваші відомості про з'єднання?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Попередження: Імовірна проблема безпеки"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket зберігає пароль сервера у вигляді звичайного тексту. Радимо використовувати пароль, згенерований в obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Ви впевнені, що хочете використовувати власний пароль?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Помилка: неправильна конфігурація"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Ви повинні використовувати пароль, що складається з 6 або більше символів."
OBSWebSocket.SessionTable.Title="Під'єднані сеанси WebSocket"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Віддалена адреса"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Тривалість сеансу"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Повідомлення вводу/виводу"
OBSWebSocket.SessionTable.IdentifiedTitle="Визначені"
OBSWebSocket.SessionTable.KickButtonColumnTitle="Роз'єднати?"
OBSWebSocket.SessionTable.KickButtonText="Роз'єднати"
OBSWebSocket.ConnectInfo.DialogTitle="Відомості про з'єднання WebSocket"
OBSWebSocket.ConnectInfo.CopyText="Скопіювати"
OBSWebSocket.ConnectInfo.ServerIp="IP сервера (найкращий збіг)"
OBSWebSocket.ConnectInfo.ServerPort="Порт сервера"
OBSWebSocket.ConnectInfo.ServerPassword="Пароль сервера"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Автентифікацію вимкнено]"
OBSWebSocket.ConnectInfo.QrTitle="QR-код під'єднання"
OBSWebSocket.TrayNotification.Identified.Title="Нове з'єднання WebSocket"
OBSWebSocket.TrayNotification.Identified.Body="Ідентифікатор клієнта %1."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Помилка автентифікації WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Клієнт %1 не зміг автентифікуватися."
OBSWebSocket.TrayNotification.Disconnected.Title="Клієнт WebSocket від'єднаний"
OBSWebSocket.TrayNotification.Disconnected.Body="Клієнт %1 від'єднаний."

37
data/locale/vi-VN.ini Normal file
View File

@ -0,0 +1,37 @@
OBSWebSocket.Plugin.Description="Điều khiển từ xa OBS Studio thông qua WebSocket"
OBSWebSocket.Settings.DialogTitle="Cài đặt máy chủ WebSocket"
OBSWebSocket.Settings.PluginSettingsTitle="Thiết đặt trình cắm"
OBSWebSocket.Settings.ServerEnable="Bật máy chủ WebSocket"
OBSWebSocket.Settings.AlertsEnable="Bật cảnh báo khay hệ thống"
OBSWebSocket.Settings.DebugEnable="Bật ghi nhật ký gỡ lỗi"
OBSWebSocket.Settings.DebugEnableHoverText="Cho phép ghi nhật ký gỡ lỗi cho phiên bản OBS hiện tại. Không tồn tại khi tải.\nUde --websocket gỡ lỗi để bật khi tải."
OBSWebSocket.Settings.ServerSettingsTitle="Thiết đặt máy chủ"
OBSWebSocket.Settings.AuthRequired="Bật xác thực"
OBSWebSocket.Settings.Password="Mật khẩu máy chủ"
OBSWebSocket.Settings.GeneratePassword="Tạo mật khẩu"
OBSWebSocket.Settings.ServerPort="Cổng máy chủ"
OBSWebSocket.Settings.ShowConnectInfo="Hiện thông tin kết nối"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Cảnh báo: Hiện đang chạy"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Có vẻ như một đầu ra (luồng, bản ghi, v.v.) hiện đang hoạt động."
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Bạn có chắc chắn muốn hiển thị thông tin kết nối của mình không?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Cảnh báo: Vấn đề bảo mật tiềm ẩn"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket lưu trữ mật khẩu máy chủ dưới dạng văn bản thuần túy. Bạn nên sử dụng mật khẩu được tạo bởi obs-websocket."
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Bạn có chắc bạn muốn sử dụng mật khẩu của mình?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Lỗi: Thiết lập không hợp lệ"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Bạn phải sử dụng mật khẩu có 6 ký tự trở lên."
OBSWebSocket.SessionTable.Title="Các phiên WebSocket được kết nối"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="Địa chỉ từ xa"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="Thời lượng phiên"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="Tin nhắn vào/ra"
OBSWebSocket.SessionTable.IdentifiedTitle="Định dạng"
OBSWebSocket.ConnectInfo.DialogTitle="Thông tin kết nối WebSocket"
OBSWebSocket.ConnectInfo.ServerIp="IP Máy chủ (Gợi ý tốt nhất)"
OBSWebSocket.ConnectInfo.ServerPort="Cổng máy chủ"
OBSWebSocket.ConnectInfo.ServerPassword="Mật khẩu máy chủ"
OBSWebSocket.ConnectInfo.QrTitle="Kết nối bằng mã QR"
OBSWebSocket.TrayNotification.Identified.Title="Tạo cổng kết nối WebSocket mới"
OBSWebSocket.TrayNotification.Identified.Body="Máy khách %1 được xác định."
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="Lỗi xác thực WebSocket"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="Máy khách %1 không xác thực được."
OBSWebSocket.TrayNotification.Disconnected.Title="Máy khách WebSocket bị ngắt kết nối"
OBSWebSocket.TrayNotification.Disconnected.Body="Máy khách %1 bị ngắt kết nối."

41
data/locale/zh-CN.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="通过 WebSocket 远程控制 OBS Studio"
OBSWebSocket.Settings.DialogTitle="WebSocket 服务器设置"
OBSWebSocket.Settings.PluginSettingsTitle="插件设置"
OBSWebSocket.Settings.ServerEnable="开启 WebSocket 服务器"
OBSWebSocket.Settings.AlertsEnable="开启系统托盘提醒"
OBSWebSocket.Settings.DebugEnable="开启调试日志"
OBSWebSocket.Settings.DebugEnableHoverText="开启当前 OBS 实例的调试日志。下次启动时需重新设置。\n使用 --websocket_debug 在启动 OBS 时开启日志。"
OBSWebSocket.Settings.ServerSettingsTitle="服务器设置"
OBSWebSocket.Settings.AuthRequired="开启身份认证"
OBSWebSocket.Settings.Password="服务器密码"
OBSWebSocket.Settings.GeneratePassword="生成密码"
OBSWebSocket.Settings.ServerPort="服务器端口"
OBSWebSocket.Settings.ShowConnectInfo="显示连接信息"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="警告:正在直播"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="似乎输出(串流、录像等)正在进行。"
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="您确定要显示您的连接信息吗?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="警告:潜在安全问题"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket 会以明文形式储存服务器密码。强烈建议使用 obs-websocket 生成的密码。"
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="您确定要使用自定义密码吗?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="错误:无效的配置"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="您的密码必须包含 6 个或以上的字符。"
OBSWebSocket.SessionTable.Title="已连接的 WebSocket 会话"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="远程地址"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="会话持续时间"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="消息传入/传出"
OBSWebSocket.SessionTable.IdentifiedTitle="已识别"
OBSWebSocket.SessionTable.KickButtonColumnTitle="踢出?"
OBSWebSocket.SessionTable.KickButtonText="踢出"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket 连接信息"
OBSWebSocket.ConnectInfo.CopyText="复制"
OBSWebSocket.ConnectInfo.ServerIp="服务器 IP最佳猜测"
OBSWebSocket.ConnectInfo.ServerPort="服务器端口"
OBSWebSocket.ConnectInfo.ServerPassword="服务器密码"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[身份认证已停用]"
OBSWebSocket.ConnectInfo.QrTitle="连接 QR 码"
OBSWebSocket.TrayNotification.Identified.Title="新 WebSocket 连接"
OBSWebSocket.TrayNotification.Identified.Body="客户端%1已识别 。"
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket 认证失败"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="%1 客户端认证失败。"
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket 客户端已断开"
OBSWebSocket.TrayNotification.Disconnected.Body="%1 客户端已断开。"

41
data/locale/zh-TW.ini Normal file
View File

@ -0,0 +1,41 @@
OBSWebSocket.Plugin.Description="透過 WebSocket 遠端控制 OBS Studio"
OBSWebSocket.Settings.DialogTitle="WebSocket 伺服器設定"
OBSWebSocket.Settings.PluginSettingsTitle="外掛程式設定"
OBSWebSocket.Settings.ServerEnable="啟用 WebSocket 伺服器"
OBSWebSocket.Settings.AlertsEnable="啟用系統匣通知"
OBSWebSocket.Settings.DebugEnable="啟用除錯日誌"
OBSWebSocket.Settings.DebugEnableHoverText="啟用目前 OBS 實體的除錯日誌。下次啟動時需重新設定。\n使用 --websocket_debug 在啟動 OBS 時啟用日誌。"
OBSWebSocket.Settings.ServerSettingsTitle="伺服器設定"
OBSWebSocket.Settings.AuthRequired="啟用認證"
OBSWebSocket.Settings.Password="伺服器密碼"
OBSWebSocket.Settings.GeneratePassword="產生密碼"
OBSWebSocket.Settings.ServerPort="伺服器連線埠"
OBSWebSocket.Settings.ShowConnectInfo="顯示連線資訊"
OBSWebSocket.Settings.ShowConnectInfoWarningTitle="警告:目前正在直播"
OBSWebSocket.Settings.ShowConnectInfoWarningMessage="似乎正在進行輸出(串流、錄影等等)。"
OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="您確定要顯示連線資訊嗎?"
OBSWebSocket.Settings.Save.UserPasswordWarningTitle="警告:潛在安全問題"
OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket 會以明文方式儲存伺服器密碼。強烈建議使用 obs-websocket 產生的密碼。"
OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="您確定要使用自己的密碼嗎?"
OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="錯誤:設定無效"
OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="您必須使用 6 個字元以上的密碼。"
OBSWebSocket.SessionTable.Title="連線的 WebSocket 工作階段"
OBSWebSocket.SessionTable.RemoteAddressColumnTitle="遠端地址"
OBSWebSocket.SessionTable.SessionDurationColumnTitle="工作階段時長"
OBSWebSocket.SessionTable.MessagesInOutColumnTitle="訊息進出"
OBSWebSocket.SessionTable.IdentifiedTitle="已辨認階段"
OBSWebSocket.SessionTable.KickButtonColumnTitle="驅逐?"
OBSWebSocket.SessionTable.KickButtonText="驅逐"
OBSWebSocket.ConnectInfo.DialogTitle="WebSocket 連線資訊"
OBSWebSocket.ConnectInfo.CopyText="複製"
OBSWebSocket.ConnectInfo.ServerIp="(最可能的)伺服器 IP"
OBSWebSocket.ConnectInfo.ServerPort="伺服器連線埠"
OBSWebSocket.ConnectInfo.ServerPassword="伺服器密碼"
OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[已停用認證]"
OBSWebSocket.ConnectInfo.QrTitle="連線 QR 碼"
OBSWebSocket.TrayNotification.Identified.Title="新的 WebSocket 工作階段"
OBSWebSocket.TrayNotification.Identified.Body="已辨認 %1 用戶端。"
OBSWebSocket.TrayNotification.AuthenticationFailed.Title="WebSocket 認證失敗"
OBSWebSocket.TrayNotification.AuthenticationFailed.Body="%1 用戶端無法進行認證。"
OBSWebSocket.TrayNotification.Disconnected.Title="WebSocket 用戶端已斷線"
OBSWebSocket.TrayNotification.Disconnected.Body="%1 用戶端已斷線。"

1
deps/asio vendored

Submodule deps/asio deleted from b73dc1d2c0

1
deps/json vendored

Submodule deps/json deleted from a34e011e24

1
deps/qr vendored

Submodule deps/qr deleted from 8518684c0f

1
deps/websocketpp vendored

Submodule deps/websocketpp deleted from 56123c8759

View File

@ -1,5 +1,7 @@
# obs-websocket documentation # obs-websocket documentation
## If you're looking for the documentation page, it's [here](generated/protocol.md)
This is the documentation for obs-websocket. Run `build_docs.sh` to auto generate the latest docs from the `src` directory. There are 3 components to the docs generation: This is the documentation for obs-websocket. Run `build_docs.sh` to auto generate the latest docs from the `src` directory. There are 3 components to the docs generation:
- `comments/comments.js`: Generates the `work/comments.json` file from the code comments in the src directory. - `comments/comments.js`: Generates the `work/comments.json` file from the code comments in the src directory.

View File

@ -9,7 +9,9 @@ enumTypeOrder = [
'WebSocketCloseCode', 'WebSocketCloseCode',
'RequestBatchExecutionType', 'RequestBatchExecutionType',
'RequestStatus', 'RequestStatus',
'EventSubscription' 'EventSubscription',
'ObsMediaInputAction',
'ObsOutputState'
] ]
categoryOrder = [ categoryOrder = [

View File

@ -1,5 +1,5 @@
# obs-websocket 5.0.0 Protocol # obs-websocket 5.x.x Protocol
## Main Table of Contents ## Main Table of Contents
@ -19,6 +19,9 @@
- [RequestResponse (OpCode 7)](#requestresponse-opcode-7) - [RequestResponse (OpCode 7)](#requestresponse-opcode-7)
- [RequestBatch (OpCode 8)](#requestbatch-opcode-8) - [RequestBatch (OpCode 8)](#requestbatch-opcode-8)
- [RequestBatchResponse (OpCode 9)](#requestbatchresponse-opcode-9) - [RequestBatchResponse (OpCode 9)](#requestbatchresponse-opcode-9)
- [Enumerations](#enums)
- [Events](#events)
- [Requests](#requests)
## General Intro ## General Intro
@ -58,7 +61,7 @@ These steps should be followed precisely. Failure to connect to the server as in
- The server receives and processes the `Identify` sent by the client. - The server receives and processes the `Identify` sent by the client.
- If authentication is required and the `Identify` message data does not contain an `authentication` string, or the string is not correct, the connection is closed with `WebSocketCloseCode::AuthenticationFailed` - If authentication is required and the `Identify` message data does not contain an `authentication` string, or the string is not correct, the connection is closed with `WebSocketCloseCode::AuthenticationFailed`
- If the client has requested an `rpcVersion` which the server cannot use, the connection is closed with `WebSocketCloseCode::UnsupportedRpcVersion`. This system allows both the server and client to have seamless backwards compatability. - If the client has requested an `rpcVersion` which the server cannot use, the connection is closed with `WebSocketCloseCode::UnsupportedRpcVersion`. This system allows both the server and client to have seamless backwards compatibility.
- If any other parameters are malformed (invalid type, etc), the connection is closed with an appropriate close code. - If any other parameters are malformed (invalid type, etc), the connection is closed with an appropriate close code.
- Once identification is processed on the server, the server responds to the client with an [OpCode 2 `Identified`](#identified-opcode-2). - Once identification is processed on the server, the server responds to the client with an [OpCode 2 `Identified`](#identified-opcode-2).
@ -143,7 +146,7 @@ Authentication is required
{ {
"op": 0, "op": 0,
"d": { "d": {
"obsWebSocketVersion": "5.0.0", "obsWebSocketVersion": "5.1.0",
"rpcVersion": 1, "rpcVersion": 1,
"authentication": { "authentication": {
"challenge": "+IxH4CnCiqpX1rM9scsNynZzbOe4KhDeYcTNS3PDaeY=", "challenge": "+IxH4CnCiqpX1rM9scsNynZzbOe4KhDeYcTNS3PDaeY=",
@ -159,7 +162,7 @@ Authentication is not required
{ {
"op": 0, "op": 0,
"d": { "d": {
"obsWebSocketVersion": "5.0.0", "obsWebSocketVersion": "5.1.0",
"rpcVersion": 1 "rpcVersion": 1
} }
} }
@ -306,7 +309,7 @@ Authentication is not required
{ {
"op": 6, "op": 6,
"d": { "d": {
"requestType": "SetCurrentScene", "requestType": "SetCurrentProgramScene",
"requestId": "f819dcf0-89cc-11eb-8f0e-382c4ac93b9c", "requestId": "f819dcf0-89cc-11eb-8f0e-382c4ac93b9c",
"requestData": { "requestData": {
"sceneName": "Scene 12" "sceneName": "Scene 12"
@ -357,7 +360,7 @@ Successful Response
{ {
"op": 7, "op": 7,
"d": { "d": {
"requestType": "SetCurrentScene", "requestType": "SetCurrentProgramScene",
"requestId": "f819dcf0-89cc-11eb-8f0e-382c4ac93b9c", "requestId": "f819dcf0-89cc-11eb-8f0e-382c4ac93b9c",
"requestStatus": { "requestStatus": {
"result": true, "result": true,
@ -373,7 +376,7 @@ Failure Response
{ {
"op": 7, "op": 7,
"d": { "d": {
"requestType": "SetCurrentScene", "requestType": "SetCurrentProgramScene",
"requestId": "f819dcf0-89cc-11eb-8f0e-382c4ac93b9c", "requestId": "f819dcf0-89cc-11eb-8f0e-382c4ac93b9c",
"requestStatus": { "requestStatus": {
"result": false, "result": false,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +0,0 @@
#define MyAppName "obs-websocket"
#define MyAppVersion "@OBS_WEBSOCKET_VERSION@"
#define MyAppPublisher "obs-websocket"
#define MyAppURL "http://github.com/obsproject/obs-websocket"
[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={{117EE44F-48E1-49E5-A381-CC8D9195CF35}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={code:GetDirName}
DefaultGroupName={#MyAppName}
OutputBaseFilename=obs-websocket-{#MyAppVersion}-Windows-Installer
Compression=lzma
SolidCompression=yes
DirExistsWarning=no
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "..\release\*"; 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 obs-websocket',
'Press Page Down to see the rest of the agreement. Once you are aware of your rights, click Next to continue.',
String(GPLText)
);
end;
// Validate that obs-studio is installed before installing the plugin
function PrepareToInstall(var NeedsRestart: Boolean): String;
begin
Result := '';
if not DirExists(ExpandConstant('{app}\obs-plugins')) then
begin
Result := 'The selected install directory does not appear to be valid. Please install OBS Studio before installing {#MyAppName} or correct your install path.';
end;
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 := '{commonpf}\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,78 +1,79 @@
/* /*
obs-websocket obs-websocket
Copyright (C) 2020-2021 Kyle Manning <tt2468@gmail.com> Copyright (C) 2020-2021 Kyle Manning <tt2468@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program. If not, see <https://www.gnu.org/licenses/> with this program. If not, see <https://www.gnu.org/licenses/>
*/ */
// Similar example code can be found in ../../src/obs-websocket.cpp // Similar example code can be found in ../../src/obs-websocket.cpp
// You can test that sample code by specifying -DPLUGIN_TESTS=TRUE // You can test that sample code by specifying -DPLUGIN_TESTS=TRUE
#include <obs-module.h> #include <obs-module.h>
#include "../obs-websocket-api.h" #include "../obs-websocket-api.h"
OBS_DECLARE_MODULE() OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE(PLUGIN_NAME, "en-US") OBS_MODULE_USE_DEFAULT_LOCALE(PLUGIN_NAME, "en-US")
obs_websocket_vendor vendor; obs_websocket_vendor vendor;
bool obs_module_load(void) bool obs_module_load(void)
{ {
blog(LOG_INFO, "Example obs-websocket-api plugin loaded!"); blog(LOG_INFO, "Example obs-websocket-api plugin loaded!");
return true; return true;
} }
void example_request_cb(obs_data_t *request_data, obs_data_t *response_data, void *priv_data); void example_request_cb(obs_data_t *request_data, obs_data_t *response_data, void *priv_data);
void obs_module_post_load(void) void obs_module_post_load(void)
{ {
vendor = obs_websocket_register_vendor("api_example_plugin"); vendor = obs_websocket_register_vendor("api_example_plugin");
if (!vendor) { if (!vendor) {
blog(LOG_ERROR, "Vendor registration failed! (obs-websocket should have logged something if installed properly.)"); blog(LOG_ERROR, "Vendor registration failed! (obs-websocket should have logged something if installed properly.)");
return; return;
} }
if (!obs_websocket_vendor_register_request(vendor, "example_request", example_request_cb, NULL)) if (!obs_websocket_vendor_register_request(vendor, "example_request", example_request_cb, NULL))
blog(LOG_ERROR, "Failed to register `example_request` request with obs-websocket."); blog(LOG_ERROR, "Failed to register `example_request` request with obs-websocket.");
uint api_version = obs_websocket_get_api_version(); uint api_version = obs_websocket_get_api_version();
if (api_version == 0) { if (api_version == 0) {
blog(LOG_ERROR, "Unable to fetch obs-websocket plugin API version."); blog(LOG_ERROR, "Unable to fetch obs-websocket plugin API version.");
return; return;
} else if (api_version == 1) { } else if (api_version == 1) {
blog(LOG_WARNING, "Unsupported obs-websocket plugin API version for calling requests."); blog(LOG_WARNING, "Unsupported obs-websocket plugin API version for calling requests.");
return; return;
} }
struct obs_websocket_request_response *response = obs_websocket_call_request("GetVersion"); struct obs_websocket_request_response *response = obs_websocket_call_request("GetVersion");
if (!response) { if (!response) {
blog(LOG_ERROR, "Failed to call GetVersion due to obs-websocket not being installed."); blog(LOG_ERROR, "Failed to call GetVersion due to obs-websocket not being installed.");
return; return;
} }
blog(LOG_INFO, "[obs_module_post_load] Called GetVersion. Status Code: %u | Comment: %s | Response Data: %s", response->status_code, response->comment, response->response_data); blog(LOG_INFO, "[obs_module_post_load] Called GetVersion. Status Code: %u | Comment: %s | Response Data: %s",
obs_websocket_request_response_free(response); response->status_code, response->comment, response->response_data);
} obs_websocket_request_response_free(response);
}
void obs_module_unload(void)
{ void obs_module_unload(void)
blog(LOG_INFO, "Example obs-websocket-api plugin unloaded!"); {
} blog(LOG_INFO, "Example obs-websocket-api plugin unloaded!");
}
void example_request_cb(obs_data_t *request_data, obs_data_t *response_data, void *priv_data)
{ void example_request_cb(obs_data_t *request_data, obs_data_t *response_data, void *priv_data)
if (obs_data_has_user_value(request_data, "ping")) {
obs_data_set_bool(response_data, "pong", true); if (obs_data_has_user_value(request_data, "ping"))
obs_data_set_bool(response_data, "pong", true);
UNUSED_PARAMETER(priv_data);
} UNUSED_PARAMETER(priv_data);
}

View File

@ -1,215 +1,218 @@
/* /*
obs-websocket obs-websocket
Copyright (C) 2016-2021 Stephane Lepin <stephane.lepin@gmail.com> Copyright (C) 2016-2021 Stephane Lepin <stephane.lepin@gmail.com>
Copyright (C) 2020-2022 Kyle Manning <tt2468@gmail.com> Copyright (C) 2020-2022 Kyle Manning <tt2468@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program. If not, see <https://www.gnu.org/licenses/> with this program. If not, see <https://www.gnu.org/licenses/>
*/ */
#ifndef _OBS_WEBSOCKET_API_H #ifndef _OBS_WEBSOCKET_API_H
#define _OBS_WEBSOCKET_API_H #define _OBS_WEBSOCKET_API_H
#include <obs.h> #include <obs.h>
#define OBS_WEBSOCKET_API_VERSION 2 #define OBS_WEBSOCKET_API_VERSION 2
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef void* obs_websocket_vendor; typedef void *obs_websocket_vendor;
typedef void (*obs_websocket_request_callback_function)(obs_data_t*, obs_data_t*, void*); typedef void (*obs_websocket_request_callback_function)(obs_data_t *, obs_data_t *, void *);
struct obs_websocket_request_response { struct obs_websocket_request_response {
unsigned int status_code; unsigned int status_code;
char *comment; char *comment;
char *response_data; // JSON string, because obs_data_t* only supports array<object>, so conversions would break API. char *response_data; // JSON string, because obs_data_t* only supports array<object>, so conversions would break API.
}; };
/* ==================== INTERNAL DEFINITIONS ==================== */ /* ==================== INTERNAL DEFINITIONS ==================== */
struct obs_websocket_request_callback { struct obs_websocket_request_callback {
obs_websocket_request_callback_function callback; obs_websocket_request_callback_function callback;
void *priv_data; void *priv_data;
}; };
inline proc_handler_t *_ph; static proc_handler_t *_ph;
/* ==================== INTERNAL API FUNCTIONS ==================== */ /* ==================== INTERNAL API FUNCTIONS ==================== */
static inline proc_handler_t *obs_websocket_get_ph(void) static inline proc_handler_t *obs_websocket_get_ph(void)
{ {
proc_handler_t *global_ph = obs_get_proc_handler(); proc_handler_t *global_ph = obs_get_proc_handler();
assert(global_ph != NULL); assert(global_ph != NULL);
calldata_t cd = {0}; calldata_t cd = {0, 0, 0, 0};
if (!proc_handler_call(global_ph, "obs_websocket_api_get_ph", &cd)) if (!proc_handler_call(global_ph, "obs_websocket_api_get_ph", &cd))
blog(LOG_DEBUG, "Unable to fetch obs-websocket proc handler object. obs-websocket not installed?"); blog(LOG_DEBUG, "Unable to fetch obs-websocket proc handler object. obs-websocket not installed?");
proc_handler_t *ret = (proc_handler_t*)calldata_ptr(&cd, "ph"); proc_handler_t *ret = (proc_handler_t *)calldata_ptr(&cd, "ph");
calldata_free(&cd); calldata_free(&cd);
return ret; return ret;
} }
static inline bool obs_websocket_ensure_ph(void) static inline bool obs_websocket_ensure_ph(void)
{ {
if (!_ph) if (!_ph)
_ph = obs_websocket_get_ph(); _ph = obs_websocket_get_ph();
return _ph != NULL; return _ph != NULL;
} }
static inline bool obs_websocket_vendor_run_simple_proc(obs_websocket_vendor vendor, const char *proc_name, calldata_t *cd) static inline bool obs_websocket_vendor_run_simple_proc(obs_websocket_vendor vendor, const char *proc_name, calldata_t *cd)
{ {
if (!obs_websocket_ensure_ph()) if (!obs_websocket_ensure_ph())
return false; return false;
if (!vendor || !proc_name || !strlen(proc_name) || !cd) if (!vendor || !proc_name || !strlen(proc_name) || !cd)
return false; return false;
calldata_set_ptr(cd, "vendor", vendor); calldata_set_ptr(cd, "vendor", vendor);
proc_handler_call(_ph, proc_name, cd); proc_handler_call(_ph, proc_name, cd);
return calldata_bool(cd, "success"); return calldata_bool(cd, "success");
} }
/* ==================== GENERAL API FUNCTIONS ==================== */ /* ==================== GENERAL API FUNCTIONS ==================== */
// Gets the API version built with the obs-websocket plugin // Gets the API version built with the obs-websocket plugin
static inline unsigned int obs_websocket_get_api_version(void) static inline unsigned int obs_websocket_get_api_version(void)
{ {
if (!obs_websocket_ensure_ph()) if (!obs_websocket_ensure_ph())
return 0; return 0;
calldata_t cd = {0}; calldata_t cd = {0, 0, 0, 0};
if (!proc_handler_call(_ph, "get_api_version", &cd)) if (!proc_handler_call(_ph, "get_api_version", &cd))
return 1; // API v1 does not include get_api_version return 1; // API v1 does not include get_api_version
unsigned int ret = calldata_int(&cd, "version"); unsigned int ret = (unsigned int)calldata_int(&cd, "version");
calldata_free(&cd); calldata_free(&cd);
return ret; return ret;
} }
// Calls an obs-websocket request. Free response with `obs_websocket_request_response_free()` // Calls an obs-websocket request. Free response with `obs_websocket_request_response_free()`
static inline obs_websocket_request_response *obs_websocket_call_request(const char *request_type, obs_data_t *request_data = NULL) static inline struct obs_websocket_request_response *obs_websocket_call_request(const char *request_type, obs_data_t *request_data
{ #ifdef __cplusplus
if (!obs_websocket_ensure_ph()) = NULL
return NULL; #endif
)
const char *request_data_string = NULL; {
if (request_data) if (!obs_websocket_ensure_ph())
request_data_string = obs_data_get_json(request_data); return NULL;
calldata_t cd = {0}; const char *request_data_string = NULL;
if (request_data)
calldata_set_string(&cd, "request_type", request_type); request_data_string = obs_data_get_json(request_data);
calldata_set_string(&cd, "request_data", request_data_string);
calldata_t cd = {0, 0, 0, 0};
proc_handler_call(_ph, "call_request", &cd);
calldata_set_string(&cd, "request_type", request_type);
auto ret = (struct obs_websocket_request_response*)calldata_ptr(&cd, "response"); calldata_set_string(&cd, "request_data", request_data_string);
calldata_free(&cd); proc_handler_call(_ph, "call_request", &cd);
return ret; struct obs_websocket_request_response *ret = (struct obs_websocket_request_response *)calldata_ptr(&cd, "response");
}
calldata_free(&cd);
// Free a request response object returned by `obs_websocket_call_request()`
static inline void obs_websocket_request_response_free(struct obs_websocket_request_response *response) return ret;
{ }
if (!response)
return; // Free a request response object returned by `obs_websocket_call_request()`
static inline void obs_websocket_request_response_free(struct obs_websocket_request_response *response)
if (response->comment) {
bfree(response->comment); if (!response)
if (response->response_data) return;
bfree(response->response_data);
bfree(response); if (response->comment)
} bfree(response->comment);
if (response->response_data)
/* ==================== VENDOR API FUNCTIONS ==================== */ bfree(response->response_data);
bfree(response);
// ALWAYS CALL ONLY VIA `obs_module_post_load()` CALLBACK! }
// Registers a new "vendor" (Example: obs-ndi)
static inline obs_websocket_vendor obs_websocket_register_vendor(const char *vendor_name) /* ==================== VENDOR API FUNCTIONS ==================== */
{
if (!obs_websocket_ensure_ph()) // ALWAYS CALL ONLY VIA `obs_module_post_load()` CALLBACK!
return NULL; // Registers a new "vendor" (Example: obs-ndi)
static inline obs_websocket_vendor obs_websocket_register_vendor(const char *vendor_name)
calldata_t cd = {0}; {
if (!obs_websocket_ensure_ph())
calldata_set_string(&cd, "name", vendor_name); return NULL;
proc_handler_call(_ph, "vendor_register", &cd); calldata_t cd = {0, 0, 0, 0};
obs_websocket_vendor ret = calldata_ptr(&cd, "vendor");
calldata_free(&cd); calldata_set_string(&cd, "name", vendor_name);
return ret; proc_handler_call(_ph, "vendor_register", &cd);
} obs_websocket_vendor ret = calldata_ptr(&cd, "vendor");
calldata_free(&cd);
// Registers a new request for a vendor
static inline bool obs_websocket_vendor_register_request(obs_websocket_vendor vendor, const char *request_type, obs_websocket_request_callback_function request_callback, void* priv_data) return ret;
{ }
calldata_t cd = {0};
// Registers a new request for a vendor
struct obs_websocket_request_callback cb = {}; static inline bool obs_websocket_vendor_register_request(obs_websocket_vendor vendor, const char *request_type,
cb.callback = request_callback; obs_websocket_request_callback_function request_callback, void *priv_data)
cb.priv_data = priv_data; {
calldata_t cd = {0, 0, 0, 0};
calldata_set_string(&cd, "type", request_type);
calldata_set_ptr(&cd, "callback", &cb); struct obs_websocket_request_callback cb = {request_callback, priv_data};
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_register", &cd); calldata_set_string(&cd, "type", request_type);
calldata_free(&cd); calldata_set_ptr(&cd, "callback", &cb);
return success; bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_register", &cd);
} calldata_free(&cd);
// Unregisters an existing vendor request return success;
static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor vendor, const char *request_type) }
{
calldata_t cd = {0}; // Unregisters an existing vendor request
static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor vendor, const char *request_type)
calldata_set_string(&cd, "type", request_type); {
calldata_t cd = {0, 0, 0, 0};
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_unregister", &cd);
calldata_free(&cd); calldata_set_string(&cd, "type", request_type);
return success; bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_unregister", &cd);
} calldata_free(&cd);
// Does not affect event_data refcount. return success;
// Emits an event under the vendor's name }
static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor, const char *event_name, obs_data_t *event_data)
{ // Does not affect event_data refcount.
calldata_t cd = {0}; // Emits an event under the vendor's name
static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor, const char *event_name, obs_data_t *event_data)
calldata_set_string(&cd, "type", event_name); {
calldata_set_ptr(&cd, "data", (void*)event_data); calldata_t cd = {0, 0, 0, 0};
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_event_emit", &cd); calldata_set_string(&cd, "type", event_name);
calldata_free(&cd); calldata_set_ptr(&cd, "data", (void *)event_data);
return success; bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_event_emit", &cd);
} calldata_free(&cd);
/* ==================== END API FUNCTIONS ==================== */ return success;
}
#ifdef __cplusplus
} /* ==================== END API FUNCTIONS ==================== */
#endif
#ifdef __cplusplus
#endif }
#endif
#endif

View File

@ -28,7 +28,6 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#define PARAM_FIRSTLOAD "FirstLoad" #define PARAM_FIRSTLOAD "FirstLoad"
#define PARAM_ENABLED "ServerEnabled" #define PARAM_ENABLED "ServerEnabled"
#define PARAM_PORT "ServerPort" #define PARAM_PORT "ServerPort"
#define PARAM_BINDLOOPBACK "BindLoopback"
#define PARAM_ALERTS "AlertsEnabled" #define PARAM_ALERTS "AlertsEnabled"
#define PARAM_AUTHREQUIRED "AuthRequired" #define PARAM_AUTHREQUIRED "AuthRequired"
#define PARAM_PASSWORD "ServerPassword" #define PARAM_PASSWORD "ServerPassword"
@ -38,25 +37,14 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#define CMDLINE_WEBSOCKET_PASSWORD "websocket_password" #define CMDLINE_WEBSOCKET_PASSWORD "websocket_password"
#define CMDLINE_WEBSOCKET_DEBUG "websocket_debug" #define CMDLINE_WEBSOCKET_DEBUG "websocket_debug"
Config::Config() : Config::Config()
PortOverridden(false),
PasswordOverridden(false),
FirstLoad(true),
ServerEnabled(true),
ServerPort(4455),
BindLoopback(true),
Ipv4Only(false),
DebugEnabled(false),
AlertsEnabled(false),
AuthRequired(true),
ServerPassword("")
{ {
SetDefaultsToGlobalStore(); SetDefaultsToGlobalStore();
} }
void Config::Load() void Config::Load()
{ {
config_t* obsConfig = GetConfigStore(); config_t *obsConfig = GetConfigStore();
if (!obsConfig) { if (!obsConfig) {
blog(LOG_ERROR, "[Config::Load] Unable to fetch OBS config!"); blog(LOG_ERROR, "[Config::Load] Unable to fetch OBS config!");
return; return;
@ -66,7 +54,6 @@ void Config::Load()
ServerEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED); ServerEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED);
AlertsEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS); AlertsEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS);
ServerPort = config_get_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT); ServerPort = config_get_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT);
BindLoopback = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_BINDLOOPBACK);
AuthRequired = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED); AuthRequired = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED);
ServerPassword = config_get_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD); ServerPassword = config_get_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD);
@ -123,7 +110,7 @@ void Config::Load()
void Config::Save() void Config::Save()
{ {
config_t* obsConfig = GetConfigStore(); config_t *obsConfig = GetConfigStore();
if (!obsConfig) { if (!obsConfig) {
blog(LOG_ERROR, "[Config::Save] Unable to fetch OBS config!"); blog(LOG_ERROR, "[Config::Save] Unable to fetch OBS config!");
return; return;
@ -134,7 +121,6 @@ void Config::Save()
if (!PortOverridden) { if (!PortOverridden) {
config_set_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort); config_set_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort);
} }
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_BINDLOOPBACK, BindLoopback);
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled); config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled);
if (!PasswordOverridden) { if (!PasswordOverridden) {
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired); config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired);
@ -146,7 +132,7 @@ void Config::Save()
void Config::SetDefaultsToGlobalStore() void Config::SetDefaultsToGlobalStore()
{ {
config_t* obsConfig = GetConfigStore(); config_t *obsConfig = GetConfigStore();
if (!obsConfig) { if (!obsConfig) {
blog(LOG_ERROR, "[Config::SetDefaultsToGlobalStore] Unable to fetch OBS config!"); blog(LOG_ERROR, "[Config::SetDefaultsToGlobalStore] Unable to fetch OBS config!");
return; return;
@ -155,13 +141,12 @@ void Config::SetDefaultsToGlobalStore()
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, FirstLoad); config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, FirstLoad);
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, ServerEnabled); config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, ServerEnabled);
config_set_default_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort); config_set_default_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort);
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_BINDLOOPBACK, BindLoopback);
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled); config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled);
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired); config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired);
config_set_default_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD, QT_TO_UTF8(ServerPassword)); config_set_default_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD, QT_TO_UTF8(ServerPassword));
} }
config_t* Config::GetConfigStore() config_t *Config::GetConfigStore()
{ {
return obs_frontend_get_global_config(); return obs_frontend_get_global_config();
} }

View File

@ -30,18 +30,17 @@ struct Config {
void Load(); void Load();
void Save(); void Save();
void SetDefaultsToGlobalStore(); void SetDefaultsToGlobalStore();
config_t* GetConfigStore(); static config_t *GetConfigStore();
std::atomic<bool> PortOverridden; std::atomic<bool> PortOverridden = false;
std::atomic<bool> PasswordOverridden; std::atomic<bool> PasswordOverridden = false;
std::atomic<bool> FirstLoad; std::atomic<bool> FirstLoad = true;
std::atomic<bool> ServerEnabled; std::atomic<bool> ServerEnabled = false;
std::atomic<uint16_t> ServerPort; std::atomic<uint16_t> ServerPort = 4455;
std::atomic<bool> BindLoopback; std::atomic<bool> Ipv4Only = false;
std::atomic<bool> Ipv4Only; std::atomic<bool> DebugEnabled = false;
std::atomic<bool> DebugEnabled; std::atomic<bool> AlertsEnabled = false;
std::atomic<bool> AlertsEnabled; std::atomic<bool> AuthRequired = true;
std::atomic<bool> AuthRequired;
QString ServerPassword; QString ServerPassword;
}; };

View File

@ -1,9 +1,31 @@
/*
obs-websocket
Copyright (C) 2020-2023 Kyle Manning <tt2468@gmail.com>
This program 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; either version 2 of the License, or
(at your option) any later version.
This program 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/>
*/
#include "WebSocketApi.h" #include "WebSocketApi.h"
#include "requesthandler/RequestHandler.h" #include "requesthandler/RequestHandler.h"
#include "obs-websocket.h" #include "obs-websocket.h"
#include "utils/Json.h" #include "utils/Json.h"
#define RETURN_STATUS(status) { calldata_set_bool(cd, "success", status); return; } #define RETURN_STATUS(status) \
{ \
calldata_set_bool(cd, "success", status); \
return; \
}
#define RETURN_SUCCESS() RETURN_STATUS(true); #define RETURN_SUCCESS() RETURN_STATUS(true);
#define RETURN_FAILURE() RETURN_STATUS(false); #define RETURN_FAILURE() RETURN_STATUS(false);
@ -15,7 +37,7 @@ WebSocketApi::Vendor *get_vendor(calldata_t *cd)
return nullptr; return nullptr;
} }
return static_cast<WebSocketApi::Vendor*>(voidVendor); return static_cast<WebSocketApi::Vendor *>(voidVendor);
} }
WebSocketApi::WebSocketApi() WebSocketApi::WebSocketApi()
@ -25,11 +47,15 @@ WebSocketApi::WebSocketApi()
_procHandler = proc_handler_create(); _procHandler = proc_handler_create();
proc_handler_add(_procHandler, "bool get_api_version(out int version)", &get_api_version, nullptr); proc_handler_add(_procHandler, "bool get_api_version(out int version)", &get_api_version, nullptr);
proc_handler_add(_procHandler, "bool call_request(in string request_type, in string request_data, out ptr response)", &call_request, nullptr); proc_handler_add(_procHandler, "bool call_request(in string request_type, in string request_data, out ptr response)",
&call_request, nullptr);
proc_handler_add(_procHandler, "bool vendor_register(in string name, out ptr vendor)", &vendor_register_cb, this); proc_handler_add(_procHandler, "bool vendor_register(in string name, out ptr vendor)", &vendor_register_cb, this);
proc_handler_add(_procHandler, "bool vendor_request_register(in ptr vendor, in string type, in ptr callback)", &vendor_request_register_cb, this); proc_handler_add(_procHandler, "bool vendor_request_register(in ptr vendor, in string type, in ptr callback)",
proc_handler_add(_procHandler, "bool vendor_request_unregister(in ptr vendor, in string type)", &vendor_request_unregister_cb, this); &vendor_request_register_cb, this);
proc_handler_add(_procHandler, "bool vendor_event_emit(in ptr vendor, in string type, in ptr data)", &vendor_event_emit_cb, this); proc_handler_add(_procHandler, "bool vendor_request_unregister(in ptr vendor, in string type)",
&vendor_request_unregister_cb, this);
proc_handler_add(_procHandler, "bool vendor_event_emit(in ptr vendor, in string type, in ptr data)", &vendor_event_emit_cb,
this);
proc_handler_t *ph = obs_get_proc_handler(); proc_handler_t *ph = obs_get_proc_handler();
assert(ph != NULL); assert(ph != NULL);
@ -58,7 +84,8 @@ void WebSocketApi::SetEventCallback(EventCallback cb)
_eventCallback = cb; _eventCallback = cb;
} }
enum WebSocketApi::RequestReturnCode WebSocketApi::PerformVendorRequest(std::string vendorName, std::string requestType, obs_data_t *requestData, obs_data_t *responseData) enum WebSocketApi::RequestReturnCode WebSocketApi::PerformVendorRequest(std::string vendorName, std::string requestType,
obs_data_t *requestData, obs_data_t *responseData)
{ {
std::shared_lock l(_mutex); std::shared_lock l(_mutex);
@ -85,9 +112,9 @@ enum WebSocketApi::RequestReturnCode WebSocketApi::PerformVendorRequest(std::str
void WebSocketApi::get_ph_cb(void *priv_data, calldata_t *cd) void WebSocketApi::get_ph_cb(void *priv_data, calldata_t *cd)
{ {
auto c = static_cast<WebSocketApi*>(priv_data); auto c = static_cast<WebSocketApi *>(priv_data);
calldata_set_ptr(cd, "ph", (void*)c->_procHandler); calldata_set_ptr(cd, "ph", (void *)c->_procHandler);
RETURN_SUCCESS(); RETURN_SUCCESS();
} }
@ -107,7 +134,7 @@ void WebSocketApi::call_request(void *, calldata_t *cd)
if (!request_type) if (!request_type)
RETURN_FAILURE(); RETURN_FAILURE();
auto response = static_cast<obs_websocket_request_response*>(bzalloc(sizeof(struct obs_websocket_request_response))); auto response = static_cast<obs_websocket_request_response *>(bzalloc(sizeof(struct obs_websocket_request_response)));
if (!response) if (!response)
RETURN_FAILURE(); RETURN_FAILURE();
@ -119,7 +146,7 @@ void WebSocketApi::call_request(void *, calldata_t *cd)
Request request(request_type, requestData); Request request(request_type, requestData);
RequestResult requestResult = requestHandler.ProcessRequest(request); RequestResult requestResult = requestHandler.ProcessRequest(request);
response->status_code = (uint)requestResult.StatusCode; response->status_code = (unsigned int)requestResult.StatusCode;
if (!requestResult.Comment.empty()) if (!requestResult.Comment.empty())
response->comment = bstrdup(requestResult.Comment.c_str()); response->comment = bstrdup(requestResult.Comment.c_str());
if (requestResult.ResponseData.is_object()) { if (requestResult.ResponseData.is_object()) {
@ -129,14 +156,15 @@ void WebSocketApi::call_request(void *, calldata_t *cd)
calldata_set_ptr(cd, "response", response); calldata_set_ptr(cd, "response", response);
blog_debug("[WebSocketApi::call_request] Request %s called, response status code is %u", request_type, response->status_code); blog_debug("[WebSocketApi::call_request] Request %s called, response status code is %u", request_type,
response->status_code);
RETURN_SUCCESS(); RETURN_SUCCESS();
} }
void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd) void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd)
{ {
auto c = static_cast<WebSocketApi*>(priv_data); auto c = static_cast<WebSocketApi *>(priv_data);
const char *vendorName; const char *vendorName;
if (!calldata_get_string(cd, "name", &vendorName) || strlen(vendorName) == 0) { if (!calldata_get_string(cd, "name", &vendorName) || strlen(vendorName) == 0) {
@ -148,18 +176,19 @@ void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd)
std::unique_lock l(c->_mutex); std::unique_lock l(c->_mutex);
if (c->_vendors.count(vendorName)) { if (c->_vendors.count(vendorName)) {
blog(LOG_WARNING, "[WebSocketApi::vendor_register_cb] Failed because `%s` is already a registered vendor.", vendorName); blog(LOG_WARNING, "[WebSocketApi::vendor_register_cb] Failed because `%s` is already a registered vendor.",
vendorName);
RETURN_FAILURE(); RETURN_FAILURE();
} }
Vendor* v = new Vendor(); Vendor *v = new Vendor();
v->_name = vendorName; v->_name = vendorName;
c->_vendors[vendorName] = v; c->_vendors[vendorName] = v;
blog_debug("[WebSocketApi::vendor_register_cb] [vendorName: %s] Registered new vendor.", v->_name.c_str()); blog_debug("[WebSocketApi::vendor_register_cb] [vendorName: %s] Registered new vendor.", v->_name.c_str());
calldata_set_ptr(cd, "vendor", static_cast<void*>(v)); calldata_set_ptr(cd, "vendor", static_cast<void *>(v));
RETURN_SUCCESS(); RETURN_SUCCESS();
} }
@ -172,28 +201,35 @@ void WebSocketApi::vendor_request_register_cb(void *, calldata_t *cd)
const char *requestType; const char *requestType;
if (!calldata_get_string(cd, "type", &requestType) || strlen(requestType) == 0) { if (!calldata_get_string(cd, "type", &requestType) || strlen(requestType) == 0) {
blog(LOG_WARNING, "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed due to missing or empty `type` string.", v->_name.c_str()); blog(LOG_WARNING,
"[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed due to missing or empty `type` string.",
v->_name.c_str());
RETURN_FAILURE(); RETURN_FAILURE();
} }
void *voidCallback; void *voidCallback;
if (!calldata_get_ptr(cd, "callback", &voidCallback) || !voidCallback) { if (!calldata_get_ptr(cd, "callback", &voidCallback) || !voidCallback) {
blog(LOG_WARNING, "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed due to missing `callback` pointer.", v->_name.c_str()); blog(LOG_WARNING,
"[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed due to missing `callback` pointer.",
v->_name.c_str());
RETURN_FAILURE(); RETURN_FAILURE();
} }
auto cb = static_cast<obs_websocket_request_callback*>(voidCallback); auto cb = static_cast<obs_websocket_request_callback *>(voidCallback);
std::unique_lock l(v->_mutex); std::unique_lock l(v->_mutex);
if (v->_requests.count(requestType)) { if (v->_requests.count(requestType)) {
blog(LOG_WARNING, "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed because `%s` is already a registered request.", v->_name.c_str(), requestType); blog(LOG_WARNING,
"[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed because `%s` is already a registered request.",
v->_name.c_str(), requestType);
RETURN_FAILURE(); RETURN_FAILURE();
} }
v->_requests[requestType] = *cb; v->_requests[requestType] = *cb;
blog_debug("[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Registered new vendor request: %s", v->_name.c_str(), requestType); blog_debug("[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Registered new vendor request: %s",
v->_name.c_str(), requestType);
RETURN_SUCCESS(); RETURN_SUCCESS();
} }
@ -206,27 +242,32 @@ void WebSocketApi::vendor_request_unregister_cb(void *, calldata_t *cd)
const char *requestType; const char *requestType;
if (!calldata_get_string(cd, "type", &requestType) || strlen(requestType) == 0) { if (!calldata_get_string(cd, "type", &requestType) || strlen(requestType) == 0) {
blog(LOG_WARNING, "[WebSocketApi::vendor_request_unregister_cb] [vendorName: %s] Failed due to missing `type` string.", v->_name.c_str()); blog(LOG_WARNING,
"[WebSocketApi::vendor_request_unregister_cb] [vendorName: %s] Failed due to missing `type` string.",
v->_name.c_str());
RETURN_FAILURE(); RETURN_FAILURE();
} }
std::unique_lock l(v->_mutex); std::unique_lock l(v->_mutex);
if (!v->_requests.count(requestType)) { if (!v->_requests.count(requestType)) {
blog(LOG_WARNING, "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed because `%s` is not a registered request.", v->_name.c_str(), requestType); blog(LOG_WARNING,
"[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed because `%s` is not a registered request.",
v->_name.c_str(), requestType);
RETURN_FAILURE(); RETURN_FAILURE();
} }
v->_requests.erase(requestType); v->_requests.erase(requestType);
blog_debug("[WebSocketApi::vendor_request_unregister_cb] [vendorName: %s] Unregistered vendor request: %s", v->_name.c_str(), requestType); blog_debug("[WebSocketApi::vendor_request_unregister_cb] [vendorName: %s] Unregistered vendor request: %s",
v->_name.c_str(), requestType);
RETURN_SUCCESS(); RETURN_SUCCESS();
} }
void WebSocketApi::vendor_event_emit_cb(void *priv_data, calldata_t *cd) void WebSocketApi::vendor_event_emit_cb(void *priv_data, calldata_t *cd)
{ {
auto c = static_cast<WebSocketApi*>(priv_data); auto c = static_cast<WebSocketApi *>(priv_data);
Vendor *v = get_vendor(cd); Vendor *v = get_vendor(cd);
if (!v) if (!v)
@ -234,17 +275,19 @@ void WebSocketApi::vendor_event_emit_cb(void *priv_data, calldata_t *cd)
const char *eventType; const char *eventType;
if (!calldata_get_string(cd, "type", &eventType) || strlen(eventType) == 0) { if (!calldata_get_string(cd, "type", &eventType) || strlen(eventType) == 0) {
blog(LOG_WARNING, "[WebSocketApi::vendor_event_emit_cb] [vendorName: %s] Failed due to missing `type` string.", v->_name.c_str()); blog(LOG_WARNING, "[WebSocketApi::vendor_event_emit_cb] [vendorName: %s] Failed due to missing `type` string.",
v->_name.c_str());
RETURN_FAILURE(); RETURN_FAILURE();
} }
void *voidEventData; void *voidEventData;
if (!calldata_get_ptr(cd, "data", &voidEventData)) { if (!calldata_get_ptr(cd, "data", &voidEventData)) {
blog(LOG_WARNING, "[WebSocketApi::vendor_event_emit_cb] [vendorName: %s] Failed due to missing `data` pointer.", v->_name.c_str()); blog(LOG_WARNING, "[WebSocketApi::vendor_event_emit_cb] [vendorName: %s] Failed due to missing `data` pointer.",
v->_name.c_str());
RETURN_FAILURE(); RETURN_FAILURE();
} }
auto eventData = static_cast<obs_data_t*>(voidEventData); auto eventData = static_cast<obs_data_t *>(voidEventData);
if (!c->_eventCallback) if (!c->_eventCallback)
RETURN_FAILURE(); RETURN_FAILURE();

View File

@ -1,3 +1,21 @@
/*
obs-websocket
Copyright (C) 2020-2023 Kyle Manning <tt2468@gmail.com>
This program 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; either version 2 of the License, or
(at your option) any later version.
This program 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/>
*/
#pragma once #pragma once
#include <functional> #include <functional>
@ -10,39 +28,40 @@
#include "../lib/obs-websocket-api.h" #include "../lib/obs-websocket-api.h"
class WebSocketApi { class WebSocketApi {
public: public:
enum RequestReturnCode { enum RequestReturnCode {
Normal, Normal,
NoVendor, NoVendor,
NoVendorRequest, NoVendorRequest,
}; };
typedef std::function<void(std::string, std::string, obs_data_t*)> EventCallback; typedef std::function<void(std::string, std::string, obs_data_t *)> EventCallback;
struct Vendor { struct Vendor {
std::shared_mutex _mutex;
std::string _name;
std::map<std::string, obs_websocket_request_callback> _requests;
};
WebSocketApi();
~WebSocketApi();
void SetEventCallback(EventCallback cb);
enum RequestReturnCode PerformVendorRequest(std::string vendorName, std::string requestName, obs_data_t *requestData, obs_data_t *responseData);
static void get_ph_cb(void *priv_data, calldata_t *cd);
static void get_api_version(void *, calldata_t *cd);
static void call_request(void *, calldata_t *cd);
static void vendor_register_cb(void *priv_data, calldata_t *cd);
static void vendor_request_register_cb(void *priv_data, calldata_t *cd);
static void vendor_request_unregister_cb(void *priv_data, calldata_t *cd);
static void vendor_event_emit_cb(void *priv_data, calldata_t *cd);
private:
std::shared_mutex _mutex; std::shared_mutex _mutex;
EventCallback _eventCallback; std::string _name;
proc_handler_t *_procHandler; std::map<std::string, obs_websocket_request_callback> _requests;
std::map<std::string, Vendor*> _vendors; };
WebSocketApi();
~WebSocketApi();
void SetEventCallback(EventCallback cb);
enum RequestReturnCode PerformVendorRequest(std::string vendorName, std::string requestName, obs_data_t *requestData,
obs_data_t *responseData);
static void get_ph_cb(void *priv_data, calldata_t *cd);
static void get_api_version(void *, calldata_t *cd);
static void call_request(void *, calldata_t *cd);
static void vendor_register_cb(void *priv_data, calldata_t *cd);
static void vendor_request_register_cb(void *priv_data, calldata_t *cd);
static void vendor_request_unregister_cb(void *priv_data, calldata_t *cd);
static void vendor_event_emit_cb(void *priv_data, calldata_t *cd);
private:
std::shared_mutex _mutex;
EventCallback _eventCallback;
proc_handler_t *_procHandler;
std::map<std::string, Vendor *> _vendors;
}; };

View File

@ -19,23 +19,19 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "EventHandler.h" #include "EventHandler.h"
EventHandler::EventHandler() : EventHandler::EventHandler()
_obsLoaded(false),
_inputVolumeMetersRef(0),
_inputActiveStateChangedRef(0),
_inputShowStateChangedRef(0),
_sceneItemTransformChangedRef(0)
{ {
blog_debug("[EventHandler::EventHandler] Setting up..."); blog_debug("[EventHandler::EventHandler] Setting up...");
obs_frontend_add_event_callback(OnFrontendEvent, this); obs_frontend_add_event_callback(OnFrontendEvent, this);
signal_handler_t* coreSignalHandler = obs_get_signal_handler(); signal_handler_t *coreSignalHandler = obs_get_signal_handler();
if (coreSignalHandler) { if (coreSignalHandler) {
signal_handler_connect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this); signal_handler_connect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this);
signal_handler_connect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this); signal_handler_connect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this);
signal_handler_connect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this); signal_handler_connect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
signal_handler_connect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this); signal_handler_connect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this);
signal_handler_connect(coreSignalHandler, "source_update", SourceUpdatedMultiHandler, this);
} else { } else {
blog(LOG_ERROR, "[EventHandler::EventHandler] Unable to get libobs signal handler!"); blog(LOG_ERROR, "[EventHandler::EventHandler] Unable to get libobs signal handler!");
} }
@ -49,16 +45,31 @@ EventHandler::~EventHandler()
obs_frontend_remove_event_callback(OnFrontendEvent, this); obs_frontend_remove_event_callback(OnFrontendEvent, this);
signal_handler_t* coreSignalHandler = obs_get_signal_handler(); signal_handler_t *coreSignalHandler = obs_get_signal_handler();
if (coreSignalHandler) { if (coreSignalHandler) {
signal_handler_disconnect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this); signal_handler_disconnect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this);
signal_handler_disconnect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this); signal_handler_disconnect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this);
signal_handler_disconnect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this); signal_handler_disconnect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
signal_handler_disconnect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this); signal_handler_disconnect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this);
signal_handler_disconnect(coreSignalHandler, "source_update", SourceUpdatedMultiHandler, this);
} else { } else {
blog(LOG_ERROR, "[EventHandler::~EventHandler] Unable to get libobs signal handler!"); blog(LOG_ERROR, "[EventHandler::~EventHandler] Unable to get libobs signal handler!");
} }
// Revoke callbacks of all inputs and scenes, in case some still have our callbacks attached
auto enumInputs = [](void *param, obs_source_t *source) {
auto eventHandler = static_cast<EventHandler *>(param);
eventHandler->DisconnectSourceSignals(source);
return true;
};
obs_enum_sources(enumInputs, this);
auto enumScenes = [](void *param, obs_source_t *source) {
auto eventHandler = static_cast<EventHandler *>(param);
eventHandler->DisconnectSourceSignals(source);
return true;
};
obs_enum_scenes(enumScenes, this);
blog_debug("[EventHandler::~EventHandler] Finished."); blog_debug("[EventHandler::~EventHandler] Finished.");
} }
@ -67,9 +78,9 @@ void EventHandler::SetBroadcastCallback(EventHandler::BroadcastCallback cb)
_broadcastCallback = cb; _broadcastCallback = cb;
} }
void EventHandler::SetObsLoadedCallback(EventHandler::ObsLoadedCallback cb) void EventHandler::SetObsReadyCallback(EventHandler::ObsReadyCallback cb)
{ {
_obsLoadedCallback = cb; _obsReadyCallback = cb;
} }
// Function to increment refcounts for high volume event subscriptions // Function to increment refcounts for high volume event subscriptions
@ -80,7 +91,8 @@ void EventHandler::ProcessSubscription(uint64_t eventSubscriptions)
if (_inputVolumeMetersHandler) if (_inputVolumeMetersHandler)
blog(LOG_WARNING, "[EventHandler::ProcessSubscription] Input volume meter handler already exists!"); blog(LOG_WARNING, "[EventHandler::ProcessSubscription] Input volume meter handler already exists!");
else else
_inputVolumeMetersHandler = std::make_unique<Utils::Obs::VolumeMeter::Handler>(std::bind(&EventHandler::HandleInputVolumeMeters, this, std::placeholders::_1)); _inputVolumeMetersHandler = std::make_unique<Utils::Obs::VolumeMeter::Handler>(
std::bind(&EventHandler::HandleInputVolumeMeters, this, std::placeholders::_1));
} }
} }
if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) != 0) if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) != 0)
@ -124,7 +136,7 @@ void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inpu
// Disconnect all existing signals from the source to prevent multiple connections // Disconnect all existing signals from the source to prevent multiple connections
DisconnectSourceSignals(source); DisconnectSourceSignals(source);
signal_handler_t* sh = obs_source_get_signal_handler(source); signal_handler_t *sh = obs_source_get_signal_handler(source);
obs_source_type sourceType = obs_source_get_type(source); obs_source_type sourceType = obs_source_get_type(source);
@ -166,8 +178,8 @@ void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inpu
signal_handler_connect(sh, "reorder_filters", HandleSourceFilterListReindexed, this); signal_handler_connect(sh, "reorder_filters", HandleSourceFilterListReindexed, this);
signal_handler_connect(sh, "filter_add", FilterAddMultiHandler, this); signal_handler_connect(sh, "filter_add", FilterAddMultiHandler, this);
signal_handler_connect(sh, "filter_remove", FilterRemoveMultiHandler, this); signal_handler_connect(sh, "filter_remove", FilterRemoveMultiHandler, this);
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){ auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param) {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
eventHandler->ConnectSourceSignals(filter); eventHandler->ConnectSourceSignals(filter);
}; };
obs_source_enum_filters(source, enumFilters, this); obs_source_enum_filters(source, enumFilters, this);
@ -193,7 +205,7 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *source)
if (!source) if (!source)
return; return;
signal_handler_t* sh = obs_source_get_signal_handler(source); signal_handler_t *sh = obs_source_get_signal_handler(source);
obs_source_type sourceType = obs_source_get_type(source); obs_source_type sourceType = obs_source_get_type(source);
@ -235,8 +247,8 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *source)
signal_handler_disconnect(sh, "reorder_filters", HandleSourceFilterListReindexed, this); signal_handler_disconnect(sh, "reorder_filters", HandleSourceFilterListReindexed, this);
signal_handler_disconnect(sh, "filter_add", FilterAddMultiHandler, this); signal_handler_disconnect(sh, "filter_add", FilterAddMultiHandler, this);
signal_handler_disconnect(sh, "filter_remove", FilterRemoveMultiHandler, this); signal_handler_disconnect(sh, "filter_remove", FilterRemoveMultiHandler, this);
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){ auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param) {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
eventHandler->DisconnectSourceSignals(filter); eventHandler->DisconnectSourceSignals(filter);
}; };
obs_source_enum_filters(source, enumFilters, this); obs_source_enum_filters(source, enumFilters, this);
@ -258,240 +270,228 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *source)
void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_data) void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_data)
{ {
auto eventHandler = static_cast<EventHandler*>(private_data); auto eventHandler = static_cast<EventHandler *>(private_data);
if (!eventHandler->_obsLoaded.load() && event != OBS_FRONTEND_EVENT_FINISHED_LOADING)
return;
switch (event) { switch (event) {
// General // General
case OBS_FRONTEND_EVENT_FINISHED_LOADING: case OBS_FRONTEND_EVENT_FINISHED_LOADING:
blog_debug("[EventHandler::OnFrontendEvent] OBS has finished loading. Connecting final handlers and enabling events..."); eventHandler->FrontendFinishedLoadingMultiHandler();
break;
case OBS_FRONTEND_EVENT_SCRIPTING_SHUTDOWN:
eventHandler->FrontendExitMultiHandler();
break;
// Connect source signals and enable events only after OBS has fully loaded (to reduce extra logging). // Config
eventHandler->_obsLoaded.store(true); case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING: {
obs_frontend_source_list transitions = {};
// In the case that plugins become hotloadable, this will have to go back into `EventHandler::EventHandler()` obs_frontend_get_transitions(&transitions);
// Enumerate inputs and connect each one for (size_t i = 0; i < transitions.sources.num; i++) {
{ obs_source_t *transition = transitions.sources.array[i];
auto enumInputs = [](void *param, obs_source_t *source) { eventHandler->DisconnectSourceSignals(transition);
auto eventHandler = static_cast<EventHandler*>(param); }
eventHandler->ConnectSourceSignals(source); obs_frontend_source_list_free(&transitions);
return true;
};
obs_enum_sources(enumInputs, private_data);
}
// Enumerate scenes and connect each one
{
auto enumScenes = [](void *param, obs_source_t *source) {
auto eventHandler = static_cast<EventHandler*>(param);
eventHandler->ConnectSourceSignals(source);
return true;
};
obs_enum_scenes(enumScenes, private_data);
}
// Enumerate all scene transitions and connect each one
{
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t* transition = transitions.sources.array[i];
eventHandler->ConnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
}
blog_debug("[EventHandler::OnFrontendEvent] Finished.");
if (eventHandler->_obsLoadedCallback)
eventHandler->_obsLoadedCallback();
break;
case OBS_FRONTEND_EVENT_EXIT:
eventHandler->HandleExitStarted();
blog_debug("[EventHandler::OnFrontendEvent] OBS is unloading. Disabling events...");
// Disconnect source signals and disable events when OBS starts unloading (to reduce extra logging).
eventHandler->_obsLoaded.store(false);
// In the case that plugins become hotloadable, this will have to go back into `EventHandler::~EventHandler()`
// Enumerate inputs and disconnect each one
{
auto enumInputs = [](void *param, obs_source_t *source) {
auto eventHandler = static_cast<EventHandler*>(param);
eventHandler->DisconnectSourceSignals(source);
return true;
};
obs_enum_sources(enumInputs, private_data);
}
// Enumerate scenes and disconnect each one
{
auto enumScenes = [](void *param, obs_source_t *source) {
auto eventHandler = static_cast<EventHandler*>(param);
eventHandler->DisconnectSourceSignals(source);
return true;
};
obs_enum_scenes(enumScenes, private_data);
}
// Enumerate all scene transitions and disconnect each one
{
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t* transition = transitions.sources.array[i];
eventHandler->DisconnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
}
blog_debug("[EventHandler::OnFrontendEvent] Finished.");
break;
case OBS_FRONTEND_EVENT_STUDIO_MODE_ENABLED:
eventHandler->HandleStudioModeStateChanged(true);
break;
case OBS_FRONTEND_EVENT_STUDIO_MODE_DISABLED:
eventHandler->HandleStudioModeStateChanged(false);
break;
// Config
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING:
{
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t* transition = transitions.sources.array[i];
eventHandler->DisconnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
}
eventHandler->HandleCurrentSceneCollectionChanging();
break;
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED:
{
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t* transition = transitions.sources.array[i];
eventHandler->ConnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
}
eventHandler->HandleCurrentSceneCollectionChanged();
break;
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED:
eventHandler->HandleSceneCollectionListChanged();
break;
case OBS_FRONTEND_EVENT_PROFILE_CHANGING:
eventHandler->HandleCurrentProfileChanging();
break;
case OBS_FRONTEND_EVENT_PROFILE_CHANGED:
eventHandler->HandleCurrentProfileChanged();
break;
case OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED:
eventHandler->HandleProfileListChanged();
break;
// Scenes
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
eventHandler->HandleCurrentProgramSceneChanged();
break;
case OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED:
eventHandler->HandleCurrentPreviewSceneChanged();
break;
case OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED:
eventHandler->HandleSceneListChanged();
break;
// Transitions
case OBS_FRONTEND_EVENT_TRANSITION_CHANGED:
eventHandler->HandleCurrentSceneTransitionChanged();
break;
case OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED:
{
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t* transition = transitions.sources.array[i];
eventHandler->ConnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
}
break;
case OBS_FRONTEND_EVENT_TRANSITION_DURATION_CHANGED:
eventHandler->HandleCurrentSceneTransitionDurationChanged();
break;
// Outputs
case OBS_FRONTEND_EVENT_STREAMING_STARTING:
eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STARTING);
break;
case OBS_FRONTEND_EVENT_STREAMING_STARTED:
eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_STREAMING_STOPPING:
eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING);
break;
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_RECORDING_STARTING:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STARTING);
break;
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_RECORDING_STOPPING:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING);
break;
case OBS_FRONTEND_EVENT_RECORDING_STOPPED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_RECORDING_PAUSED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_PAUSED);
break;
case OBS_FRONTEND_EVENT_RECORDING_UNPAUSED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_RESUMED);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING:
eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STARTING);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED:
eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPING:
eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED:
eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_VIRTUALCAM_STARTED:
eventHandler->HandleVirtualcamStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_VIRTUALCAM_STOPPED:
eventHandler->HandleVirtualcamStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
eventHandler->HandleReplayBufferSaved();
break;
default:
break;
} }
// Before ready update to allow event to broadcast
eventHandler->HandleCurrentSceneCollectionChanging();
eventHandler->_obsReady = false;
if (eventHandler->_obsReadyCallback)
eventHandler->_obsReadyCallback(false);
break;
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED: {
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t *transition = transitions.sources.array[i];
eventHandler->ConnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
}
eventHandler->_obsReady = true;
if (eventHandler->_obsReadyCallback)
eventHandler->_obsReadyCallback(true);
eventHandler->HandleCurrentSceneCollectionChanged();
break;
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED:
eventHandler->HandleSceneCollectionListChanged();
break;
case OBS_FRONTEND_EVENT_PROFILE_CHANGING:
eventHandler->HandleCurrentProfileChanging();
break;
case OBS_FRONTEND_EVENT_PROFILE_CHANGED:
eventHandler->HandleCurrentProfileChanged();
break;
case OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED:
eventHandler->HandleProfileListChanged();
break;
// Scenes
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
eventHandler->HandleCurrentProgramSceneChanged();
break;
case OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED:
eventHandler->HandleCurrentPreviewSceneChanged();
break;
case OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED:
eventHandler->HandleSceneListChanged();
break;
// Transitions
case OBS_FRONTEND_EVENT_TRANSITION_CHANGED:
eventHandler->HandleCurrentSceneTransitionChanged();
break;
case OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED: {
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t *transition = transitions.sources.array[i];
eventHandler->ConnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
} break;
case OBS_FRONTEND_EVENT_TRANSITION_DURATION_CHANGED:
eventHandler->HandleCurrentSceneTransitionDurationChanged();
break;
// Outputs
case OBS_FRONTEND_EVENT_STREAMING_STARTING:
eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STARTING);
{
// Connect signals for stream output reconnects (hacky)
OBSOutputAutoRelease streamOutput = obs_frontend_get_streaming_output();
if (streamOutput) {
signal_handler_t *sh = obs_output_get_signal_handler(streamOutput);
signal_handler_connect(sh, "reconnect", StreamOutputReconnectHandler, private_data);
signal_handler_connect(sh, "reconnect_success", StreamOutputReconnectSuccessHandler, private_data);
}
}
break;
case OBS_FRONTEND_EVENT_STREAMING_STARTED:
eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_STREAMING_STOPPING:
eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING);
{
// Disconnect signals for stream output reconnects
OBSOutputAutoRelease streamOutput = obs_frontend_get_streaming_output();
if (streamOutput) {
signal_handler_t *sh = obs_output_get_signal_handler(streamOutput);
signal_handler_disconnect(sh, "reconnect", StreamOutputReconnectHandler, private_data);
signal_handler_disconnect(sh, "reconnect_success", StreamOutputReconnectSuccessHandler,
private_data);
}
}
break;
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_RECORDING_STARTING:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STARTING);
break;
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_RECORDING_STOPPING:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING);
break;
case OBS_FRONTEND_EVENT_RECORDING_STOPPED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_RECORDING_PAUSED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_PAUSED);
break;
case OBS_FRONTEND_EVENT_RECORDING_UNPAUSED:
eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_RESUMED);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING:
eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STARTING);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED:
eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPING:
eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED:
eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_VIRTUALCAM_STARTED:
eventHandler->HandleVirtualcamStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_VIRTUALCAM_STOPPED:
eventHandler->HandleVirtualcamStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
eventHandler->HandleReplayBufferSaved();
break;
// Ui
case OBS_FRONTEND_EVENT_STUDIO_MODE_ENABLED:
eventHandler->HandleStudioModeStateChanged(true);
break;
case OBS_FRONTEND_EVENT_STUDIO_MODE_DISABLED:
eventHandler->HandleStudioModeStateChanged(false);
break;
case OBS_FRONTEND_EVENT_SCREENSHOT_TAKEN:
eventHandler->HandleScreenshotSaved();
break;
default:
break;
}
}
void EventHandler::FrontendFinishedLoadingMultiHandler()
{
blog_debug(
"[EventHandler::FrontendFinishedLoadingMultiHandler] OBS has finished loading. Connecting final handlers and enabling events...");
// Enumerate all scene transitions and connect each one
{
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t *transition = transitions.sources.array[i];
ConnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
}
_obsReady = true;
if (_obsReadyCallback)
_obsReadyCallback(true);
blog_debug("[EventHandler::FrontendFinishedLoadingMultiHandler] Finished.");
}
void EventHandler::FrontendExitMultiHandler()
{
blog_debug("[EventHandler::FrontendExitMultiHandler] OBS is unloading. Disabling events...");
HandleExitStarted();
// Disconnect source signals and disable events when OBS starts unloading (to reduce extra logging).
_obsReady = false;
if (_obsReadyCallback)
_obsReadyCallback(false);
// Enumerate all scene transitions and disconnect each one
{
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t *transition = transitions.sources.array[i];
DisconnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
}
blog_debug("[EventHandler::FrontendExitMultiHandler] Finished.");
} }
// Only called for creation of a public source // Only called for creation of a public source
void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data) void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
// Don't react to signals until OBS has finished loading
if (!eventHandler->_obsLoaded.load())
return;
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -500,14 +500,14 @@ void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data)
eventHandler->ConnectSourceSignals(source); eventHandler->ConnectSourceSignals(source);
switch (obs_source_get_type(source)) { switch (obs_source_get_type(source)) {
case OBS_SOURCE_TYPE_INPUT: case OBS_SOURCE_TYPE_INPUT:
eventHandler->HandleInputCreated(source); eventHandler->HandleInputCreated(source);
break; break;
case OBS_SOURCE_TYPE_SCENE: case OBS_SOURCE_TYPE_SCENE:
eventHandler->HandleSceneCreated(source); eventHandler->HandleSceneCreated(source);
break; break;
default: default:
break; break;
} }
} }
@ -515,7 +515,7 @@ void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data)
// Used as a fallback if an input/scene is not explicitly removed // Used as a fallback if an input/scene is not explicitly removed
void EventHandler::SourceDestroyedMultiHandler(void *param, calldata_t *data) void EventHandler::SourceDestroyedMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
// We can't use any smart types here because releasing the source will cause infinite recursion // We can't use any smart types here because releasing the source will cause infinite recursion
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
@ -525,23 +525,19 @@ void EventHandler::SourceDestroyedMultiHandler(void *param, calldata_t *data)
// Disconnect all signals from the source // Disconnect all signals from the source
eventHandler->DisconnectSourceSignals(source); eventHandler->DisconnectSourceSignals(source);
// Don't react to signals if OBS is unloading
if (!eventHandler->_obsLoaded.load())
return;
switch (obs_source_get_type(source)) { switch (obs_source_get_type(source)) {
case OBS_SOURCE_TYPE_INPUT: case OBS_SOURCE_TYPE_INPUT:
// Only emit removed if the input has not already been removed. This is the case when removing the last scene item of an input. // Only emit removed if the input has not already been removed. This is the case when removing the last scene item of an input.
if (!obs_source_removed(source)) if (!obs_source_removed(source))
eventHandler->HandleInputRemoved(source); eventHandler->HandleInputRemoved(source);
break; break;
case OBS_SOURCE_TYPE_SCENE: case OBS_SOURCE_TYPE_SCENE:
// Only emit removed if the scene has not already been removed. // Only emit removed if the scene has not already been removed.
if (!obs_source_removed(source)) if (!obs_source_removed(source))
eventHandler->HandleSceneRemoved(source); eventHandler->HandleSceneRemoved(source);
break; break;
default: default:
break; break;
} }
} }
@ -549,33 +545,27 @@ void EventHandler::SourceDestroyedMultiHandler(void *param, calldata_t *data)
// For example, if an input is "removed" but there is a dangling ref, you still want to know that it shouldn't exist, but it's not guaranteed to be destroyed. // For example, if an input is "removed" but there is a dangling ref, you still want to know that it shouldn't exist, but it's not guaranteed to be destroyed.
void EventHandler::SourceRemovedMultiHandler(void *param, calldata_t *data) void EventHandler::SourceRemovedMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
if (!eventHandler->_obsLoaded.load())
return;
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
return; return;
switch (obs_source_get_type(source)) { switch (obs_source_get_type(source)) {
case OBS_SOURCE_TYPE_INPUT: case OBS_SOURCE_TYPE_INPUT:
eventHandler->HandleInputRemoved(source); eventHandler->HandleInputRemoved(source);
break; break;
case OBS_SOURCE_TYPE_SCENE: case OBS_SOURCE_TYPE_SCENE:
eventHandler->HandleSceneRemoved(source); eventHandler->HandleSceneRemoved(source);
break; break;
default: default:
break; break;
} }
} }
void EventHandler::SourceRenamedMultiHandler(void *param, calldata_t *data) void EventHandler::SourceRenamedMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
if (!eventHandler->_obsLoaded.load())
return;
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -587,15 +577,49 @@ void EventHandler::SourceRenamedMultiHandler(void *param, calldata_t *data)
return; return;
switch (obs_source_get_type(source)) { switch (obs_source_get_type(source)) {
case OBS_SOURCE_TYPE_INPUT: case OBS_SOURCE_TYPE_INPUT:
eventHandler->HandleInputNameChanged(source, oldSourceName, sourceName); eventHandler->HandleInputNameChanged(source, oldSourceName, sourceName);
break; break;
case OBS_SOURCE_TYPE_TRANSITION: case OBS_SOURCE_TYPE_TRANSITION:
break; break;
case OBS_SOURCE_TYPE_SCENE: case OBS_SOURCE_TYPE_SCENE:
eventHandler->HandleSceneNameChanged(source, oldSourceName, sourceName); eventHandler->HandleSceneNameChanged(source, oldSourceName, sourceName);
break; break;
default: default:
break; break;
} }
} }
void EventHandler::SourceUpdatedMultiHandler(void *param, calldata_t *data)
{
auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source)
return;
switch (obs_source_get_type(source)) {
case OBS_SOURCE_TYPE_INPUT:
eventHandler->HandleInputSettingsChanged(source);
break;
case OBS_SOURCE_TYPE_FILTER:
eventHandler->HandleSourceFilterSettingsChanged(source);
break;
default:
break;
}
}
void EventHandler::StreamOutputReconnectHandler(void *param, calldata_t *)
{
auto eventHandler = static_cast<EventHandler *>(param);
eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_RECONNECTING);
}
void EventHandler::StreamOutputReconnectSuccessHandler(void *param, calldata_t *)
{
auto eventHandler = static_cast<EventHandler *>(param);
eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_RECONNECTED);
}

View File

@ -27,125 +27,160 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "../obs-websocket.h" #include "../obs-websocket.h"
#include "../utils/Obs.h" #include "../utils/Obs.h"
#include "../utils/Obs_VolumeMeter.h" #include "../utils/Obs_VolumeMeter.h"
#include "../plugin-macros.generated.h" #include "plugin-macros.generated.h"
class EventHandler class EventHandler {
{ public:
public: EventHandler();
EventHandler(); ~EventHandler();
~EventHandler();
typedef std::function<void(uint64_t, std::string, json, uint8_t)> BroadcastCallback; typedef std::function<void(uint64_t, std::string, json, uint8_t)>
void SetBroadcastCallback(BroadcastCallback cb); BroadcastCallback; // uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion
typedef std::function<void()> ObsLoadedCallback; void SetBroadcastCallback(BroadcastCallback cb);
void SetObsLoadedCallback(ObsLoadedCallback cb); typedef std::function<void(bool)> ObsReadyCallback; // bool ready
void SetObsReadyCallback(ObsReadyCallback cb);
void ProcessSubscription(uint64_t eventSubscriptions); void ProcessSubscription(uint64_t eventSubscriptions);
void ProcessUnsubscription(uint64_t eventSubscriptions); void ProcessUnsubscription(uint64_t eventSubscriptions);
private: private:
BroadcastCallback _broadcastCallback; BroadcastCallback _broadcastCallback;
ObsLoadedCallback _obsLoadedCallback; ObsReadyCallback _obsReadyCallback;
std::atomic<bool> _obsLoaded; std::atomic<bool> _obsReady = false;
std::unique_ptr<Utils::Obs::VolumeMeter::Handler> _inputVolumeMetersHandler; std::unique_ptr<Utils::Obs::VolumeMeter::Handler> _inputVolumeMetersHandler;
std::atomic<uint64_t> _inputVolumeMetersRef; std::atomic<uint64_t> _inputVolumeMetersRef = 0;
std::atomic<uint64_t> _inputActiveStateChangedRef; std::atomic<uint64_t> _inputActiveStateChangedRef = 0;
std::atomic<uint64_t> _inputShowStateChangedRef; std::atomic<uint64_t> _inputShowStateChangedRef = 0;
std::atomic<uint64_t> _sceneItemTransformChangedRef; std::atomic<uint64_t> _sceneItemTransformChangedRef = 0;
void ConnectSourceSignals(obs_source_t *source); void ConnectSourceSignals(obs_source_t *source);
void DisconnectSourceSignals(obs_source_t *source); void DisconnectSourceSignals(obs_source_t *source);
void BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData = nullptr, uint8_t rpcVersion = 0); void BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData = nullptr, uint8_t rpcVersion = 0);
// Signal handler: frontend // Signal handler: frontend
static void OnFrontendEvent(enum obs_frontend_event event, void *private_data); static void OnFrontendEvent(enum obs_frontend_event event, void *private_data);
void FrontendFinishedLoadingMultiHandler();
void FrontendExitMultiHandler();
// Signal handler: libobs // Signal handler: libobs
static void SourceCreatedMultiHandler(void *param, calldata_t *data); static void SourceCreatedMultiHandler(void *param, calldata_t *data);
static void SourceDestroyedMultiHandler(void *param, calldata_t *data); static void SourceDestroyedMultiHandler(void *param, calldata_t *data);
static void SourceRemovedMultiHandler(void *param, calldata_t *data); static void SourceRemovedMultiHandler(void *param, calldata_t *data);
static void SourceRenamedMultiHandler(void *param, calldata_t *data);
static void SourceUpdatedMultiHandler(void *param, calldata_t *data);
// Signal handler: source // Signal handler: media sources
static void SourceRenamedMultiHandler(void *param, calldata_t *data); static void SourceMediaPauseMultiHandler(void *param, calldata_t *data);
static void SourceMediaPauseMultiHandler(void *param, calldata_t *data); static void SourceMediaPlayMultiHandler(void *param, calldata_t *data);
static void SourceMediaPlayMultiHandler(void *param, calldata_t *data); static void SourceMediaRestartMultiHandler(void *param, calldata_t *data);
static void SourceMediaRestartMultiHandler(void *param, calldata_t *data); static void SourceMediaStopMultiHandler(void *param, calldata_t *data);
static void SourceMediaStopMultiHandler(void *param, calldata_t *data); static void SourceMediaNextMultiHandler(void *param, calldata_t *data);
static void SourceMediaNextMultiHandler(void *param, calldata_t *data); static void SourceMediaPreviousMultiHandler(void *param, calldata_t *data);
static void SourceMediaPreviousMultiHandler(void *param, calldata_t *data);
// Signal handler: output
static void StreamOutputReconnectHandler(void *param, calldata_t *data);
static void StreamOutputReconnectSuccessHandler(void *param, calldata_t *data);
// General // General
void HandleExitStarted(); void HandleExitStarted();
void HandleStudioModeStateChanged(bool enabled);
// Config // Config
void HandleCurrentSceneCollectionChanging(); void HandleCurrentSceneCollectionChanging();
void HandleCurrentSceneCollectionChanged(); void HandleCurrentSceneCollectionChanged();
void HandleSceneCollectionListChanged(); void HandleSceneCollectionListChanged();
void HandleCurrentProfileChanging(); void HandleCurrentProfileChanging();
void HandleCurrentProfileChanged(); void HandleCurrentProfileChanged();
void HandleProfileListChanged(); void HandleProfileListChanged();
// Scenes // Scenes
void HandleSceneCreated(obs_source_t *source); void HandleSceneCreated(obs_source_t *source);
void HandleSceneRemoved(obs_source_t *source); void HandleSceneRemoved(obs_source_t *source);
void HandleSceneNameChanged(obs_source_t *source, std::string oldSceneName, std::string sceneName); void HandleSceneNameChanged(obs_source_t *source, std::string oldSceneName, std::string sceneName);
void HandleCurrentProgramSceneChanged(); void HandleCurrentProgramSceneChanged();
void HandleCurrentPreviewSceneChanged(); void HandleCurrentPreviewSceneChanged();
void HandleSceneListChanged(); void HandleSceneListChanged();
// Inputs // Inputs
void HandleInputCreated(obs_source_t *source); void HandleInputCreated(obs_source_t *source);
void HandleInputRemoved(obs_source_t *source); void HandleInputRemoved(obs_source_t *source);
void HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName); void HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName);
void HandleInputVolumeMeters(std::vector<json> inputs); // AudioMeter::Handler callback void HandleInputSettingsChanged(obs_source_t *source);
static void HandleInputActiveStateChanged(void *param, calldata_t *data); // Direct callback static void HandleInputActiveStateChanged(void *param,
static void HandleInputShowStateChanged(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleInputMuteStateChanged(void *param, calldata_t *data); // Direct callback static void HandleInputShowStateChanged(void *param,
static void HandleInputVolumeChanged(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleInputAudioBalanceChanged(void *param, calldata_t *data); // Direct callback static void HandleInputMuteStateChanged(void *param,
static void HandleInputAudioSyncOffsetChanged(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleInputAudioTracksChanged(void *param, calldata_t *data); // Direct callback static void HandleInputVolumeChanged(void *param,
static void HandleInputAudioMonitorTypeChanged(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleInputAudioBalanceChanged(void *param,
calldata_t *data); // Direct callback
static void HandleInputAudioSyncOffsetChanged(void *param,
calldata_t *data); // Direct callback
static void HandleInputAudioTracksChanged(void *param,
calldata_t *data); // Direct callback
static void HandleInputAudioMonitorTypeChanged(void *param,
calldata_t *data); // Direct callback
void HandleInputVolumeMeters(std::vector<json> inputs); // AudioMeter::Handler callback
// Transitions // Transitions
void HandleCurrentSceneTransitionChanged(); void HandleCurrentSceneTransitionChanged();
void HandleCurrentSceneTransitionDurationChanged(); void HandleCurrentSceneTransitionDurationChanged();
static void HandleSceneTransitionStarted(void *param, calldata_t *data); // Direct callback static void HandleSceneTransitionStarted(void *param,
static void HandleSceneTransitionEnded(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleSceneTransitionVideoEnded(void *param, calldata_t *data); // Direct callback static void HandleSceneTransitionEnded(void *param,
calldata_t *data); // Direct callback
static void HandleSceneTransitionVideoEnded(void *param,
calldata_t *data); // Direct callback
// Filters // Filters
static void FilterAddMultiHandler(void *param, calldata_t *data); // Direct callback static void FilterAddMultiHandler(void *param,
static void FilterRemoveMultiHandler(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleSourceFilterListReindexed(void *param, calldata_t *data); // Direct callback static void FilterRemoveMultiHandler(void *param,
void HandleSourceFilterCreated(obs_source_t *source, obs_source_t *filter); calldata_t *data); // Direct callback
void HandleSourceFilterRemoved(obs_source_t *source, obs_source_t *filter); static void HandleSourceFilterListReindexed(void *param,
static void HandleSourceFilterNameChanged(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleSourceFilterEnableStateChanged(void *param, calldata_t *data); // Direct callback void HandleSourceFilterCreated(obs_source_t *source, obs_source_t *filter);
void HandleSourceFilterRemoved(obs_source_t *source, obs_source_t *filter);
static void HandleSourceFilterNameChanged(void *param,
calldata_t *data); // Direct callback
void HandleSourceFilterSettingsChanged(obs_source_t *source);
static void HandleSourceFilterEnableStateChanged(void *param, calldata_t *data); // Direct callback
// Outputs // Outputs
void HandleStreamStateChanged(ObsOutputState state); void HandleStreamStateChanged(ObsOutputState state);
void HandleRecordStateChanged(ObsOutputState state); void HandleRecordStateChanged(ObsOutputState state);
void HandleReplayBufferStateChanged(ObsOutputState state); void HandleReplayBufferStateChanged(ObsOutputState state);
void HandleVirtualcamStateChanged(ObsOutputState state); void HandleVirtualcamStateChanged(ObsOutputState state);
void HandleReplayBufferSaved(); void HandleReplayBufferSaved();
// Scene Items // Scene Items
static void HandleSceneItemCreated(void *param, calldata_t *data); // Direct callback static void HandleSceneItemCreated(void *param,
static void HandleSceneItemRemoved(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleSceneItemListReindexed(void *param, calldata_t *data); // Direct callback static void HandleSceneItemRemoved(void *param,
static void HandleSceneItemEnableStateChanged(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleSceneItemLockStateChanged(void *param, calldata_t *data); // Direct callback static void HandleSceneItemListReindexed(void *param,
static void HandleSceneItemSelected(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
static void HandleSceneItemTransformChanged(void *param, calldata_t *data); // Direct callback static void HandleSceneItemEnableStateChanged(void *param,
calldata_t *data); // Direct callback
static void HandleSceneItemLockStateChanged(void *param,
calldata_t *data); // Direct callback
static void HandleSceneItemSelected(void *param,
calldata_t *data); // Direct callback
static void HandleSceneItemTransformChanged(void *param,
calldata_t *data); // Direct callback
// Media Inputs // Media Inputs
static void HandleMediaInputPlaybackStarted(void *param, calldata_t *data); // Direct callback static void HandleMediaInputPlaybackStarted(void *param,
static void HandleMediaInputPlaybackEnded(void *param, calldata_t *data); // Direct callback calldata_t *data); // Direct callback
void HandleMediaInputActionTriggered(obs_source_t *source, ObsMediaInputAction action); static void HandleMediaInputPlaybackEnded(void *param,
calldata_t *data); // Direct callback
void HandleMediaInputActionTriggered(obs_source_t *source, ObsMediaInputAction action);
// Ui
void HandleStudioModeStateChanged(bool enabled);
void HandleScreenshotSaved();
}; };

View File

@ -21,7 +21,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
void EventHandler::FilterAddMultiHandler(void *param, calldata_t *data) void EventHandler::FilterAddMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "filter"); obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "filter");
@ -36,7 +36,7 @@ void EventHandler::FilterAddMultiHandler(void *param, calldata_t *data)
void EventHandler::FilterRemoveMultiHandler(void *param, calldata_t *data) void EventHandler::FilterRemoveMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "filter"); obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "filter");
@ -65,7 +65,7 @@ void EventHandler::FilterRemoveMultiHandler(void *param, calldata_t *data)
*/ */
void EventHandler::HandleSourceFilterListReindexed(void *param, calldata_t *data) void EventHandler::HandleSourceFilterListReindexed(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -150,7 +150,7 @@ void EventHandler::HandleSourceFilterRemoved(obs_source_t *source, obs_source_t
*/ */
void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data) void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "source");
if (!filter) if (!filter)
@ -163,6 +163,32 @@ void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data)
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterNameChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterNameChanged", eventData);
} }
/**
* An source filter's settings have changed (been updated).
*
* @dataField sourceName | String | Name of the source the filter is on
* @dataField filterName | String | Name of the filter
* @dataField filterSettings | Object | New settings object of the filter
*
* @eventType SourceFilterSettingsChanged
* @eventSubscription Filters
* @complexity 3
* @rpcVersion -1
* @initialVersion 5.4.0
* @api events
* @category filters
*/
void EventHandler::HandleSourceFilterSettingsChanged(obs_source_t *source)
{
OBSDataAutoRelease filterSettings = obs_source_get_settings(source);
json eventData;
eventData["sourceName"] = obs_source_get_name(obs_filter_get_parent(source));
eventData["filterName"] = obs_source_get_name(source);
eventData["filterSettings"] = Utils::Json::ObsDataToJson(filterSettings);
BroadcastEvent(EventSubscription::Filters, "SourceFilterSettingsChanged", eventData);
}
/** /**
* A source filter's enable state has changed. * A source filter's enable state has changed.
* *
@ -180,7 +206,7 @@ void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data)
*/ */
void EventHandler::HandleSourceFilterEnableStateChanged(void *param, calldata_t *data) void EventHandler::HandleSourceFilterEnableStateChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "source");
if (!filter) if (!filter)

View File

@ -23,6 +23,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
* An input has been created. * An input has been created.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField inputKind | String | The kind of the input * @dataField inputKind | String | The kind of the input
* @dataField unversionedInputKind | String | The unversioned kind of input (aka no `_v2` stuff) * @dataField unversionedInputKind | String | The unversioned kind of input (aka no `_v2` stuff)
* @dataField inputSettings | Object | The settings configured to the input when it was created * @dataField inputSettings | Object | The settings configured to the input when it was created
@ -44,6 +45,7 @@ void EventHandler::HandleInputCreated(obs_source_t *source)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputKind"] = inputKind; eventData["inputKind"] = inputKind;
eventData["unversionedInputKind"] = obs_source_get_unversioned_id(source); eventData["unversionedInputKind"] = obs_source_get_unversioned_id(source);
eventData["inputSettings"] = Utils::Json::ObsDataToJson(inputSettings); eventData["inputSettings"] = Utils::Json::ObsDataToJson(inputSettings);
@ -55,6 +57,7 @@ void EventHandler::HandleInputCreated(obs_source_t *source)
* An input has been removed. * An input has been removed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* *
* @eventType InputRemoved * @eventType InputRemoved
* @eventSubscription Inputs * @eventSubscription Inputs
@ -68,12 +71,14 @@ void EventHandler::HandleInputRemoved(obs_source_t *source)
{ {
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
BroadcastEvent(EventSubscription::Inputs, "InputRemoved", eventData); BroadcastEvent(EventSubscription::Inputs, "InputRemoved", eventData);
} }
/** /**
* The name of an input has changed. * The name of an input has changed.
* *
* @dataField inputUuid | String | UUID of the input
* @dataField oldInputName | String | Old name of the input * @dataField oldInputName | String | Old name of the input
* @dataField inputName | String | New name of the input * @dataField inputName | String | New name of the input
* *
@ -85,20 +90,50 @@ void EventHandler::HandleInputRemoved(obs_source_t *source)
* @api events * @api events
* @category inputs * @category inputs
*/ */
void EventHandler::HandleInputNameChanged(obs_source_t *, std::string oldInputName, std::string inputName) void EventHandler::HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName)
{ {
json eventData; json eventData;
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["oldInputName"] = oldInputName; eventData["oldInputName"] = oldInputName;
eventData["inputName"] = inputName; eventData["inputName"] = inputName;
BroadcastEvent(EventSubscription::Inputs, "InputNameChanged", eventData); BroadcastEvent(EventSubscription::Inputs, "InputNameChanged", eventData);
} }
/**
* An input's settings have changed (been updated).
*
* Note: On some inputs, changing values in the properties dialog will cause an immediate update. Pressing the "Cancel" button will revert the settings, resulting in another event being fired.
*
* @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField inputSettings | Object | New settings object of the input
*
* @eventType InputSettingsChanged
* @eventSubscription Inputs
* @complexity 3
* @rpcVersion -1
* @initialVersion 5.4.0
* @api events
* @category inputs
*/
void EventHandler::HandleInputSettingsChanged(obs_source_t *source)
{
OBSDataAutoRelease inputSettings = obs_source_get_settings(source);
json eventData;
eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputSettings"] = Utils::Json::ObsDataToJson(inputSettings);
BroadcastEvent(EventSubscription::Inputs, "InputSettingsChanged", eventData);
}
/** /**
* An input's active state has changed. * An input's active state has changed.
* *
* When an input is active, it means it's being shown by the program feed. * When an input is active, it means it's being shown by the program feed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField videoActive | Boolean | Whether the input is active * @dataField videoActive | Boolean | Whether the input is active
* *
* @eventType InputActiveStateChanged * @eventType InputActiveStateChanged
@ -111,7 +146,7 @@ void EventHandler::HandleInputNameChanged(obs_source_t *, std::string oldInputNa
*/ */
void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data) void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
if (!eventHandler->_inputActiveStateChangedRef.load()) if (!eventHandler->_inputActiveStateChangedRef.load())
return; return;
@ -125,6 +160,7 @@ void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["videoActive"] = obs_source_active(source); eventData["videoActive"] = obs_source_active(source);
eventHandler->BroadcastEvent(EventSubscription::InputActiveStateChanged, "InputActiveStateChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::InputActiveStateChanged, "InputActiveStateChanged", eventData);
} }
@ -135,6 +171,7 @@ void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data)
* When an input is showing, it means it's being shown by the preview or a dialog. * When an input is showing, it means it's being shown by the preview or a dialog.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField videoShowing | Boolean | Whether the input is showing * @dataField videoShowing | Boolean | Whether the input is showing
* *
* @eventType InputShowStateChanged * @eventType InputShowStateChanged
@ -147,7 +184,7 @@ void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data)
*/ */
void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data) void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
if (!eventHandler->_inputShowStateChangedRef.load()) if (!eventHandler->_inputShowStateChangedRef.load())
return; return;
@ -161,6 +198,7 @@ void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["videoShowing"] = obs_source_showing(source); eventData["videoShowing"] = obs_source_showing(source);
eventHandler->BroadcastEvent(EventSubscription::InputShowStateChanged, "InputShowStateChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::InputShowStateChanged, "InputShowStateChanged", eventData);
} }
@ -169,6 +207,7 @@ void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data)
* An input's mute state has changed. * An input's mute state has changed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField inputMuted | Boolean | Whether the input is muted * @dataField inputMuted | Boolean | Whether the input is muted
* *
* @eventType InputMuteStateChanged * @eventType InputMuteStateChanged
@ -181,7 +220,7 @@ void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data)
*/ */
void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data) void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -192,6 +231,7 @@ void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputMuted"] = obs_source_muted(source); eventData["inputMuted"] = obs_source_muted(source);
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputMuteStateChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputMuteStateChanged", eventData);
} }
@ -200,7 +240,8 @@ void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data)
* An input's volume level has changed. * An input's volume level has changed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputVolumeMul | Number | New volume level in multimap * @dataField inputUuid | String | UUID of the input
* @dataField inputVolumeMul | Number | New volume level multiplier
* @dataField inputVolumeDb | Number | New volume level in dB * @dataField inputVolumeDb | Number | New volume level in dB
* *
* @eventType InputVolumeChanged * @eventType InputVolumeChanged
@ -213,7 +254,7 @@ void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data)
*/ */
void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data) void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -225,12 +266,13 @@ void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data)
// Volume must be grabbed from the calldata. Running obs_source_get_volume() will return the previous value. // Volume must be grabbed from the calldata. Running obs_source_get_volume() will return the previous value.
double inputVolumeMul = calldata_float(data, "volume"); double inputVolumeMul = calldata_float(data, "volume");
double inputVolumeDb = obs_mul_to_db(inputVolumeMul); double inputVolumeDb = obs_mul_to_db((float)inputVolumeMul);
if (inputVolumeDb == -INFINITY) if (inputVolumeDb == -INFINITY)
inputVolumeDb = -100; inputVolumeDb = -100;
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputVolumeMul"] = inputVolumeMul; eventData["inputVolumeMul"] = inputVolumeMul;
eventData["inputVolumeDb"] = inputVolumeDb; eventData["inputVolumeDb"] = inputVolumeDb;
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputVolumeChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputVolumeChanged", eventData);
@ -239,7 +281,8 @@ void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data)
/** /**
* The audio balance value of an input has changed. * The audio balance value of an input has changed.
* *
* @dataField inputName | String | Name of the affected input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField inputAudioBalance | Number | New audio balance value of the input * @dataField inputAudioBalance | Number | New audio balance value of the input
* *
* @eventType InputAudioBalanceChanged * @eventType InputAudioBalanceChanged
@ -252,7 +295,7 @@ void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data)
*/ */
void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data) void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -265,6 +308,7 @@ void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputAudioBalance"] = inputAudioBalance; eventData["inputAudioBalance"] = inputAudioBalance;
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioBalanceChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioBalanceChanged", eventData);
} }
@ -273,6 +317,7 @@ void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data)
* The sync offset of an input has changed. * The sync offset of an input has changed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField inputAudioSyncOffset | Number | New sync offset in milliseconds * @dataField inputAudioSyncOffset | Number | New sync offset in milliseconds
* *
* @eventType InputAudioSyncOffsetChanged * @eventType InputAudioSyncOffsetChanged
@ -285,7 +330,7 @@ void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data)
*/ */
void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *data) void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -298,6 +343,7 @@ void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *da
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputAudioSyncOffset"] = inputAudioSyncOffset / 1000000; eventData["inputAudioSyncOffset"] = inputAudioSyncOffset / 1000000;
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioSyncOffsetChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioSyncOffsetChanged", eventData);
} }
@ -306,6 +352,7 @@ void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *da
* The audio tracks of an input have changed. * The audio tracks of an input have changed.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField inputAudioTracks | Object | Object of audio tracks along with their associated enable states * @dataField inputAudioTracks | Object | Object of audio tracks along with their associated enable states
* *
* @eventType InputAudioTracksChanged * @eventType InputAudioTracksChanged
@ -318,7 +365,7 @@ void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *da
*/ */
void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data) void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -336,6 +383,7 @@ void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["inputAudioTracks"] = inputAudioTracks; eventData["inputAudioTracks"] = inputAudioTracks;
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioTracksChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioTracksChanged", eventData);
} }
@ -350,6 +398,7 @@ void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data)
* - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT` * - `OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT`
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField monitorType | String | New monitor type of the input * @dataField monitorType | String | New monitor type of the input
* *
* @eventType InputAudioMonitorTypeChanged * @eventType InputAudioMonitorTypeChanged
@ -362,7 +411,7 @@ void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data)
*/ */
void EventHandler::HandleInputAudioMonitorTypeChanged(void *param, calldata_t *data) void EventHandler::HandleInputAudioMonitorTypeChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -373,11 +422,10 @@ void EventHandler::HandleInputAudioMonitorTypeChanged(void *param, calldata_t *d
enum obs_monitoring_type monitorType = (obs_monitoring_type)calldata_int(data, "type"); enum obs_monitoring_type monitorType = (obs_monitoring_type)calldata_int(data, "type");
std::string monitorTypeString = Utils::Obs::StringHelper::GetInputMonitorType(monitorType);
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["monitorType"] = monitorTypeString; eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["monitorType"] = monitorType;
eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioMonitorTypeChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioMonitorTypeChanged", eventData);
} }

View File

@ -19,11 +19,14 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "EventHandler.h" #include "EventHandler.h"
#define CASE(x) case x: return #x; #define CASE(x) \
case x: \
return #x;
std::string GetMediaInputActionString(ObsMediaInputAction action) { std::string GetMediaInputActionString(ObsMediaInputAction action)
{
switch (action) { switch (action) {
default: default:
CASE(OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE) CASE(OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE)
CASE(OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY) CASE(OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY)
CASE(OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART) CASE(OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART)
@ -35,7 +38,7 @@ std::string GetMediaInputActionString(ObsMediaInputAction action) {
void EventHandler::SourceMediaPauseMultiHandler(void *param, calldata_t *data) void EventHandler::SourceMediaPauseMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -49,7 +52,7 @@ void EventHandler::SourceMediaPauseMultiHandler(void *param, calldata_t *data)
void EventHandler::SourceMediaPlayMultiHandler(void *param, calldata_t *data) void EventHandler::SourceMediaPlayMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -63,7 +66,7 @@ void EventHandler::SourceMediaPlayMultiHandler(void *param, calldata_t *data)
void EventHandler::SourceMediaRestartMultiHandler(void *param, calldata_t *data) void EventHandler::SourceMediaRestartMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -77,7 +80,7 @@ void EventHandler::SourceMediaRestartMultiHandler(void *param, calldata_t *data)
void EventHandler::SourceMediaStopMultiHandler(void *param, calldata_t *data) void EventHandler::SourceMediaStopMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -91,7 +94,7 @@ void EventHandler::SourceMediaStopMultiHandler(void *param, calldata_t *data)
void EventHandler::SourceMediaNextMultiHandler(void *param, calldata_t *data) void EventHandler::SourceMediaNextMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -105,7 +108,7 @@ void EventHandler::SourceMediaNextMultiHandler(void *param, calldata_t *data)
void EventHandler::SourceMediaPreviousMultiHandler(void *param, calldata_t *data) void EventHandler::SourceMediaPreviousMultiHandler(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -121,6 +124,7 @@ void EventHandler::SourceMediaPreviousMultiHandler(void *param, calldata_t *data
* A media input has started playing. * A media input has started playing.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* *
* @eventType MediaInputPlaybackStarted * @eventType MediaInputPlaybackStarted
* @eventSubscription MediaInputs * @eventSubscription MediaInputs
@ -132,7 +136,7 @@ void EventHandler::SourceMediaPreviousMultiHandler(void *param, calldata_t *data
*/ */
void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data) void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -143,6 +147,7 @@ void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackStarted", eventData); eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackStarted", eventData);
} }
@ -150,6 +155,7 @@ void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data
* A media input has finished playing. * A media input has finished playing.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* *
* @eventType MediaInputPlaybackEnded * @eventType MediaInputPlaybackEnded
* @eventSubscription MediaInputs * @eventSubscription MediaInputs
@ -161,7 +167,7 @@ void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data
*/ */
void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data) void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -172,6 +178,7 @@ void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data)
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackEnded", eventData); eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackEnded", eventData);
} }
@ -179,6 +186,7 @@ void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data)
* An action has been performed on an input. * An action has been performed on an input.
* *
* @dataField inputName | String | Name of the input * @dataField inputName | String | Name of the input
* @dataField inputUuid | String | UUID of the input
* @dataField mediaAction | String | Action performed on the input. See `ObsMediaInputAction` enum * @dataField mediaAction | String | Action performed on the input. See `ObsMediaInputAction` enum
* *
* @eventType MediaInputActionTriggered * @eventType MediaInputActionTriggered
@ -193,6 +201,7 @@ void EventHandler::HandleMediaInputActionTriggered(obs_source_t *source, ObsMedi
{ {
json eventData; json eventData;
eventData["inputName"] = obs_source_get_name(source); eventData["inputName"] = obs_source_get_name(source);
eventData["inputUuid"] = obs_source_get_uuid(source);
eventData["mediaAction"] = GetMediaInputActionString(action); eventData["mediaAction"] = GetMediaInputActionString(action);
BroadcastEvent(EventSubscription::MediaInputs, "MediaInputActionTriggered", eventData); BroadcastEvent(EventSubscription::MediaInputs, "MediaInputActionTriggered", eventData);
} }

View File

@ -19,18 +19,21 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "EventHandler.h" #include "EventHandler.h"
static bool GetOutputStateActive(ObsOutputState state) { static bool GetOutputStateActive(ObsOutputState state)
switch(state) { {
case OBS_WEBSOCKET_OUTPUT_STARTED: switch (state) {
case OBS_WEBSOCKET_OUTPUT_RESUMED: case OBS_WEBSOCKET_OUTPUT_STARTED:
return true; case OBS_WEBSOCKET_OUTPUT_RESUMED:
case OBS_WEBSOCKET_OUTPUT_STARTING: case OBS_WEBSOCKET_OUTPUT_RECONNECTED:
case OBS_WEBSOCKET_OUTPUT_STOPPING: return true;
case OBS_WEBSOCKET_OUTPUT_STOPPED: case OBS_WEBSOCKET_OUTPUT_STARTING:
case OBS_WEBSOCKET_OUTPUT_PAUSED: case OBS_WEBSOCKET_OUTPUT_STOPPING:
return false; case OBS_WEBSOCKET_OUTPUT_STOPPED:
default: case OBS_WEBSOCKET_OUTPUT_RECONNECTING:
return false; case OBS_WEBSOCKET_OUTPUT_PAUSED:
return false;
default:
return false;
} }
} }
@ -52,7 +55,7 @@ void EventHandler::HandleStreamStateChanged(ObsOutputState state)
{ {
json eventData; json eventData;
eventData["outputActive"] = GetOutputStateActive(state); eventData["outputActive"] = GetOutputStateActive(state);
eventData["outputState"] = Utils::Obs::StringHelper::GetOutputState(state); eventData["outputState"] = state;
BroadcastEvent(EventSubscription::Outputs, "StreamStateChanged", eventData); BroadcastEvent(EventSubscription::Outputs, "StreamStateChanged", eventData);
} }
@ -61,6 +64,7 @@ void EventHandler::HandleStreamStateChanged(ObsOutputState state)
* *
* @dataField outputActive | Boolean | Whether the output is active * @dataField outputActive | Boolean | Whether the output is active
* @dataField outputState | String | The specific state of the output * @dataField outputState | String | The specific state of the output
* @dataField outputPath | String | File name for the saved recording, if record stopped. `null` otherwise
* *
* @eventType RecordStateChanged * @eventType RecordStateChanged
* @eventSubscription Outputs * @eventSubscription Outputs
@ -74,7 +78,12 @@ void EventHandler::HandleRecordStateChanged(ObsOutputState state)
{ {
json eventData; json eventData;
eventData["outputActive"] = GetOutputStateActive(state); eventData["outputActive"] = GetOutputStateActive(state);
eventData["outputState"] = Utils::Obs::StringHelper::GetOutputState(state); eventData["outputState"] = state;
if (state == OBS_WEBSOCKET_OUTPUT_STOPPED || state == OBS_WEBSOCKET_OUTPUT_STARTED) {
eventData["outputPath"] = Utils::Obs::StringHelper::GetLastRecordFileName();
} else {
eventData["outputPath"] = nullptr;
}
BroadcastEvent(EventSubscription::Outputs, "RecordStateChanged", eventData); BroadcastEvent(EventSubscription::Outputs, "RecordStateChanged", eventData);
} }
@ -96,7 +105,7 @@ void EventHandler::HandleReplayBufferStateChanged(ObsOutputState state)
{ {
json eventData; json eventData;
eventData["outputActive"] = GetOutputStateActive(state); eventData["outputActive"] = GetOutputStateActive(state);
eventData["outputState"] = Utils::Obs::StringHelper::GetOutputState(state); eventData["outputState"] = state;
BroadcastEvent(EventSubscription::Outputs, "ReplayBufferStateChanged", eventData); BroadcastEvent(EventSubscription::Outputs, "ReplayBufferStateChanged", eventData);
} }
@ -118,7 +127,7 @@ void EventHandler::HandleVirtualcamStateChanged(ObsOutputState state)
{ {
json eventData; json eventData;
eventData["outputActive"] = GetOutputStateActive(state); eventData["outputActive"] = GetOutputStateActive(state);
eventData["outputState"] = Utils::Obs::StringHelper::GetOutputState(state); eventData["outputState"] = state;
BroadcastEvent(EventSubscription::Outputs, "VirtualcamStateChanged", eventData); BroadcastEvent(EventSubscription::Outputs, "VirtualcamStateChanged", eventData);
} }
@ -138,6 +147,6 @@ void EventHandler::HandleVirtualcamStateChanged(ObsOutputState state)
void EventHandler::HandleReplayBufferSaved() void EventHandler::HandleReplayBufferSaved()
{ {
json eventData; json eventData;
eventData["savedReplayPath"] = Utils::Obs::StringHelper::GetLastReplayBufferFilePath(); eventData["savedReplayPath"] = Utils::Obs::StringHelper::GetLastReplayBufferFileName();
BroadcastEvent(EventSubscription::Outputs, "ReplayBufferSaved", eventData); BroadcastEvent(EventSubscription::Outputs, "ReplayBufferSaved", eventData);
} }

View File

@ -23,7 +23,9 @@ with this program. If not, see <https://www.gnu.org/licenses/>
* A scene item has been created. * A scene item has been created.
* *
* @dataField sceneName | String | Name of the scene the item was added to * @dataField sceneName | String | Name of the scene the item was added to
* @dataField sceneUuid | String | UUID of the scene the item was added to
* @dataField sourceName | String | Name of the underlying source (input/scene) * @dataField sourceName | String | Name of the underlying source (input/scene)
* @dataField sourceUuid | String | UUID of the underlying source (input/scene)
* @dataField sceneItemId | Number | Numeric ID of the scene item * @dataField sceneItemId | Number | Numeric ID of the scene item
* @dataField sceneItemIndex | Number | Index position of the item * @dataField sceneItemIndex | Number | Index position of the item
* *
@ -37,7 +39,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
*/ */
void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data) void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene"); obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene");
if (!scene) if (!scene)
@ -49,7 +51,9 @@ void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data)
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
eventData["sourceName"] = obs_source_get_name(obs_sceneitem_get_source(sceneItem)); eventData["sourceName"] = obs_source_get_name(obs_sceneitem_get_source(sceneItem));
eventData["sourceUuid"] = obs_source_get_uuid(obs_sceneitem_get_source(sceneItem));
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventData["sceneItemIndex"] = obs_sceneitem_get_order_position(sceneItem); eventData["sceneItemIndex"] = obs_sceneitem_get_order_position(sceneItem);
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemCreated", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemCreated", eventData);
@ -61,7 +65,9 @@ void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data)
* This event is not emitted when the scene the item is in is removed. * This event is not emitted when the scene the item is in is removed.
* *
* @dataField sceneName | String | Name of the scene the item was removed from * @dataField sceneName | String | Name of the scene the item was removed from
* @dataField sceneUuid | String | UUID of the scene the item was removed from
* @dataField sourceName | String | Name of the underlying source (input/scene) * @dataField sourceName | String | Name of the underlying source (input/scene)
* @dataField sourceUuid | String | UUID of the underlying source (input/scene)
* @dataField sceneItemId | Number | Numeric ID of the scene item * @dataField sceneItemId | Number | Numeric ID of the scene item
* *
* @eventType SceneItemRemoved * @eventType SceneItemRemoved
@ -74,7 +80,7 @@ void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data)
*/ */
void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data) void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene"); obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene");
if (!scene) if (!scene)
@ -86,7 +92,9 @@ void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data)
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
eventData["sourceName"] = obs_source_get_name(obs_sceneitem_get_source(sceneItem)); eventData["sourceName"] = obs_source_get_name(obs_sceneitem_get_source(sceneItem));
eventData["sourceUuid"] = obs_source_get_uuid(obs_sceneitem_get_source(sceneItem));
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemRemoved", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemRemoved", eventData);
} }
@ -95,6 +103,7 @@ void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data)
* A scene's item list has been reindexed. * A scene's item list has been reindexed.
* *
* @dataField sceneName | String | Name of the scene * @dataField sceneName | String | Name of the scene
* @dataField sceneUuid | String | UUID of the scene
* @dataField sceneItems | Array<Object> | Array of scene item objects * @dataField sceneItems | Array<Object> | Array of scene item objects
* *
* @eventType SceneItemListReindexed * @eventType SceneItemListReindexed
@ -107,7 +116,7 @@ void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data)
*/ */
void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data) void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene"); obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene");
if (!scene) if (!scene)
@ -115,6 +124,7 @@ void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data)
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
eventData["sceneItems"] = Utils::Obs::ArrayHelper::GetSceneItemList(scene, true); eventData["sceneItems"] = Utils::Obs::ArrayHelper::GetSceneItemList(scene, true);
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemListReindexed", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemListReindexed", eventData);
} }
@ -123,6 +133,7 @@ void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data)
* A scene item's enable state has changed. * A scene item's enable state has changed.
* *
* @dataField sceneName | String | Name of the scene the item is in * @dataField sceneName | String | Name of the scene the item is in
* @dataField sceneUuid | String | UUID of the scene the item is in
* @dataField sceneItemId | Number | Numeric ID of the scene item * @dataField sceneItemId | Number | Numeric ID of the scene item
* @dataField sceneItemEnabled | Boolean | Whether the scene item is enabled (visible) * @dataField sceneItemEnabled | Boolean | Whether the scene item is enabled (visible)
* *
@ -136,7 +147,7 @@ void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data)
*/ */
void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *data) void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene"); obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene");
if (!scene) if (!scene)
@ -150,6 +161,7 @@ void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *da
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventData["sceneItemEnabled"] = sceneItemEnabled; eventData["sceneItemEnabled"] = sceneItemEnabled;
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemEnableStateChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemEnableStateChanged", eventData);
@ -159,6 +171,7 @@ void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *da
* A scene item's lock state has changed. * A scene item's lock state has changed.
* *
* @dataField sceneName | String | Name of the scene the item is in * @dataField sceneName | String | Name of the scene the item is in
* @dataField sceneUuid | String | UUID of the scene the item is in
* @dataField sceneItemId | Number | Numeric ID of the scene item * @dataField sceneItemId | Number | Numeric ID of the scene item
* @dataField sceneItemLocked | Boolean | Whether the scene item is locked * @dataField sceneItemLocked | Boolean | Whether the scene item is locked
* *
@ -172,7 +185,7 @@ void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *da
*/ */
void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data) void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene"); obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene");
if (!scene) if (!scene)
@ -186,6 +199,7 @@ void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventData["sceneItemLocked"] = sceneItemLocked; eventData["sceneItemLocked"] = sceneItemLocked;
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemLockStateChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemLockStateChanged", eventData);
@ -195,6 +209,7 @@ void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data
* A scene item has been selected in the Ui. * A scene item has been selected in the Ui.
* *
* @dataField sceneName | String | Name of the scene the item is in * @dataField sceneName | String | Name of the scene the item is in
* @dataField sceneUuid | String | UUID of the scene the item is in
* @dataField sceneItemId | Number | Numeric ID of the scene item * @dataField sceneItemId | Number | Numeric ID of the scene item
* *
* @eventType SceneItemSelected * @eventType SceneItemSelected
@ -207,7 +222,7 @@ void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data
*/ */
void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data) void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene"); obs_scene_t *scene = GetCalldataPointer<obs_scene_t>(data, "scene");
if (!scene) if (!scene)
@ -219,6 +234,7 @@ void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data)
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemSelected", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemSelected", eventData);
} }
@ -227,6 +243,7 @@ void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data)
* The transform/crop of a scene item has changed. * The transform/crop of a scene item has changed.
* *
* @dataField sceneName | String | The name of the scene the item is in * @dataField sceneName | String | The name of the scene the item is in
* @dataField sceneUuid | String | The UUID of the scene the item is in
* @dataField sceneItemId | Number | Numeric ID of the scene item * @dataField sceneItemId | Number | Numeric ID of the scene item
* @dataField sceneItemTransform | Object | New transform/crop info of the scene item * @dataField sceneItemTransform | Object | New transform/crop info of the scene item
* *
@ -240,7 +257,7 @@ void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data)
*/ */
void EventHandler::HandleSceneItemTransformChanged(void *param, calldata_t *data) void EventHandler::HandleSceneItemTransformChanged(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
if (!eventHandler->_sceneItemTransformChangedRef.load()) if (!eventHandler->_sceneItemTransformChangedRef.load())
return; return;
@ -255,6 +272,7 @@ void EventHandler::HandleSceneItemTransformChanged(void *param, calldata_t *data
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene));
eventData["sceneUuid"] = obs_source_get_uuid(obs_scene_get_source(scene));
eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem);
eventData["sceneItemTransform"] = Utils::Obs::ObjectHelper::GetSceneItemTransform(sceneItem); eventData["sceneItemTransform"] = Utils::Obs::ObjectHelper::GetSceneItemTransform(sceneItem);
eventHandler->BroadcastEvent(EventSubscription::SceneItemTransformChanged, "SceneItemTransformChanged", eventData); eventHandler->BroadcastEvent(EventSubscription::SceneItemTransformChanged, "SceneItemTransformChanged", eventData);

View File

@ -23,6 +23,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
* A new scene has been created. * A new scene has been created.
* *
* @dataField sceneName | String | Name of the new scene * @dataField sceneName | String | Name of the new scene
* @dataField sceneUuid | String | UUID of the new scene
* @dataField isGroup | Boolean | Whether the new scene is a group * @dataField isGroup | Boolean | Whether the new scene is a group
* *
* @eventType SceneCreated * @eventType SceneCreated
@ -37,6 +38,7 @@ void EventHandler::HandleSceneCreated(obs_source_t *source)
{ {
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(source); eventData["sceneName"] = obs_source_get_name(source);
eventData["sceneUuid"] = obs_source_get_uuid(source);
eventData["isGroup"] = obs_source_is_group(source); eventData["isGroup"] = obs_source_is_group(source);
BroadcastEvent(EventSubscription::Scenes, "SceneCreated", eventData); BroadcastEvent(EventSubscription::Scenes, "SceneCreated", eventData);
} }
@ -45,6 +47,7 @@ void EventHandler::HandleSceneCreated(obs_source_t *source)
* A scene has been removed. * A scene has been removed.
* *
* @dataField sceneName | String | Name of the removed scene * @dataField sceneName | String | Name of the removed scene
* @dataField sceneUuid | String | UUID of the removed scene
* @dataField isGroup | Boolean | Whether the scene was a group * @dataField isGroup | Boolean | Whether the scene was a group
* *
* @eventType SceneRemoved * @eventType SceneRemoved
@ -59,6 +62,7 @@ void EventHandler::HandleSceneRemoved(obs_source_t *source)
{ {
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(source); eventData["sceneName"] = obs_source_get_name(source);
eventData["sceneUuid"] = obs_source_get_uuid(source);
eventData["isGroup"] = obs_source_is_group(source); eventData["isGroup"] = obs_source_is_group(source);
BroadcastEvent(EventSubscription::Scenes, "SceneRemoved", eventData); BroadcastEvent(EventSubscription::Scenes, "SceneRemoved", eventData);
} }
@ -66,6 +70,7 @@ void EventHandler::HandleSceneRemoved(obs_source_t *source)
/** /**
* The name of a scene has changed. * The name of a scene has changed.
* *
* @dataField sceneUuid | String | UUID of the scene
* @dataField oldSceneName | String | Old name of the scene * @dataField oldSceneName | String | Old name of the scene
* @dataField sceneName | String | New name of the scene * @dataField sceneName | String | New name of the scene
* *
@ -77,9 +82,10 @@ void EventHandler::HandleSceneRemoved(obs_source_t *source)
* @api events * @api events
* @category scenes * @category scenes
*/ */
void EventHandler::HandleSceneNameChanged(obs_source_t *, std::string oldSceneName, std::string sceneName) void EventHandler::HandleSceneNameChanged(obs_source_t *source, std::string oldSceneName, std::string sceneName)
{ {
json eventData; json eventData;
eventData["sceneUuid"] = obs_source_get_uuid(source);
eventData["oldSceneName"] = oldSceneName; eventData["oldSceneName"] = oldSceneName;
eventData["sceneName"] = sceneName; eventData["sceneName"] = sceneName;
BroadcastEvent(EventSubscription::Scenes, "SceneNameChanged", eventData); BroadcastEvent(EventSubscription::Scenes, "SceneNameChanged", eventData);
@ -89,6 +95,7 @@ void EventHandler::HandleSceneNameChanged(obs_source_t *, std::string oldSceneNa
* The current program scene has changed. * The current program scene has changed.
* *
* @dataField sceneName | String | Name of the scene that was switched to * @dataField sceneName | String | Name of the scene that was switched to
* @dataField sceneUuid | String | UUID of the scene that was switched to
* *
* @eventType CurrentProgramSceneChanged * @eventType CurrentProgramSceneChanged
* @eventSubscription Scenes * @eventSubscription Scenes
@ -104,6 +111,7 @@ void EventHandler::HandleCurrentProgramSceneChanged()
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(currentScene); eventData["sceneName"] = obs_source_get_name(currentScene);
eventData["sceneUuid"] = obs_source_get_uuid(currentScene);
BroadcastEvent(EventSubscription::Scenes, "CurrentProgramSceneChanged", eventData); BroadcastEvent(EventSubscription::Scenes, "CurrentProgramSceneChanged", eventData);
} }
@ -111,6 +119,7 @@ void EventHandler::HandleCurrentProgramSceneChanged()
* The current preview scene has changed. * The current preview scene has changed.
* *
* @dataField sceneName | String | Name of the scene that was switched to * @dataField sceneName | String | Name of the scene that was switched to
* @dataField sceneUuid | String | UUID of the scene that was switched to
* *
* @eventType CurrentPreviewSceneChanged * @eventType CurrentPreviewSceneChanged
* @eventSubscription Scenes * @eventSubscription Scenes
@ -124,12 +133,13 @@ void EventHandler::HandleCurrentPreviewSceneChanged()
{ {
OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene(); OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene();
// This event may be called when OBS is not in studio mode, however retreiving the source while not in studio mode will return null. // This event may be called when OBS is not in studio mode, however retreiving the source while not in studio mode will return null.
if (!currentPreviewScene) if (!currentPreviewScene)
return; return;
json eventData; json eventData;
eventData["sceneName"] = obs_source_get_name(currentPreviewScene); eventData["sceneName"] = obs_source_get_name(currentPreviewScene);
eventData["sceneUuid"] = obs_source_get_uuid(currentPreviewScene);
BroadcastEvent(EventSubscription::Scenes, "CurrentPreviewSceneChanged", eventData); BroadcastEvent(EventSubscription::Scenes, "CurrentPreviewSceneChanged", eventData);
} }

View File

@ -23,6 +23,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
* The current scene transition has changed. * The current scene transition has changed.
* *
* @dataField transitionName | String | Name of the new transition * @dataField transitionName | String | Name of the new transition
* @dataField transitionUuid | String | UUID of the new transition
* *
* @eventType CurrentSceneTransitionChanged * @eventType CurrentSceneTransitionChanged
* @eventSubscription Transitions * @eventSubscription Transitions
@ -38,6 +39,7 @@ void EventHandler::HandleCurrentSceneTransitionChanged()
json eventData; json eventData;
eventData["transitionName"] = obs_source_get_name(transition); eventData["transitionName"] = obs_source_get_name(transition);
eventData["transitionUuid"] = obs_source_get_uuid(transition);
BroadcastEvent(EventSubscription::Transitions, "CurrentSceneTransitionChanged", eventData); BroadcastEvent(EventSubscription::Transitions, "CurrentSceneTransitionChanged", eventData);
} }
@ -65,6 +67,7 @@ void EventHandler::HandleCurrentSceneTransitionDurationChanged()
* A scene transition has started. * A scene transition has started.
* *
* @dataField transitionName | String | Scene transition name * @dataField transitionName | String | Scene transition name
* @dataField transitionUuid | String | Scene transition UUID
* *
* @eventType SceneTransitionStarted * @eventType SceneTransitionStarted
* @eventSubscription Transitions * @eventSubscription Transitions
@ -76,7 +79,7 @@ void EventHandler::HandleCurrentSceneTransitionDurationChanged()
*/ */
void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data) void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -84,6 +87,7 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data)
json eventData; json eventData;
eventData["transitionName"] = obs_source_get_name(source); eventData["transitionName"] = obs_source_get_name(source);
eventData["transitionUuid"] = obs_source_get_uuid(source);
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionStarted", eventData); eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionStarted", eventData);
} }
@ -93,6 +97,7 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data)
* Note: Does not appear to trigger when the transition is interrupted by the user. * Note: Does not appear to trigger when the transition is interrupted by the user.
* *
* @dataField transitionName | String | Scene transition name * @dataField transitionName | String | Scene transition name
* @dataField transitionUuid | String | Scene transition UUID
* *
* @eventType SceneTransitionEnded * @eventType SceneTransitionEnded
* @eventSubscription Transitions * @eventSubscription Transitions
@ -104,7 +109,7 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data)
*/ */
void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data) void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -112,6 +117,7 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data)
json eventData; json eventData;
eventData["transitionName"] = obs_source_get_name(source); eventData["transitionName"] = obs_source_get_name(source);
eventData["transitionUuid"] = obs_source_get_uuid(source);
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionEnded", eventData); eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionEnded", eventData);
} }
@ -124,6 +130,7 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data)
* Note: Appears to be called by every transition, regardless of relevance. * Note: Appears to be called by every transition, regardless of relevance.
* *
* @dataField transitionName | String | Scene transition name * @dataField transitionName | String | Scene transition name
* @dataField transitionUuid | String | Scene transition UUID
* *
* @eventType SceneTransitionVideoEnded * @eventType SceneTransitionVideoEnded
* @eventSubscription Transitions * @eventSubscription Transitions
@ -135,7 +142,7 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data)
*/ */
void EventHandler::HandleSceneTransitionVideoEnded(void *param, calldata_t *data) void EventHandler::HandleSceneTransitionVideoEnded(void *param, calldata_t *data)
{ {
auto eventHandler = static_cast<EventHandler*>(param); auto eventHandler = static_cast<EventHandler *>(param);
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source"); obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
if (!source) if (!source)
@ -143,5 +150,6 @@ void EventHandler::HandleSceneTransitionVideoEnded(void *param, calldata_t *data
json eventData; json eventData;
eventData["transitionName"] = obs_source_get_name(source); eventData["transitionName"] = obs_source_get_name(source);
eventData["transitionUuid"] = obs_source_get_uuid(source);
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionVideoEnded", eventData); eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionVideoEnded", eventData);
} }

View File

@ -38,3 +38,27 @@ void EventHandler::HandleStudioModeStateChanged(bool enabled)
eventData["studioModeEnabled"] = enabled; eventData["studioModeEnabled"] = enabled;
BroadcastEvent(EventSubscription::Ui, "StudioModeStateChanged", eventData); BroadcastEvent(EventSubscription::Ui, "StudioModeStateChanged", eventData);
} }
/**
* A screenshot has been saved.
*
* Note: Triggered for the screenshot feature available in `Settings -> Hotkeys -> Screenshot Output` ONLY.
* Applications using `Get/SaveSourceScreenshot` should implement a `CustomEvent` if this kind of inter-client
* communication is desired.
*
* @dataField savedScreenshotPath | String | Path of the saved image file
*
* @eventType ScreenshotSaved
* @eventSubscription Ui
* @complexity 2
* @rpcVersion -1
* @initialVersion 5.1.0
* @api events
* @category ui
*/
void EventHandler::HandleScreenshotSaved()
{
json eventData;
eventData["savedScreenshotPath"] = Utils::Obs::StringHelper::GetLastScreenshotFileName();
BroadcastEvent(EventSubscription::Ui, "ScreenshotSaved", eventData);
}

View File

@ -157,13 +157,14 @@ namespace EventSubscription {
* Helper to receive all non-high-volume events. * Helper to receive all non-high-volume events.
* *
* @enumIdentifier All * @enumIdentifier All
* @enumValue (General | Config | Scenes | Inputs | Transitions | Filters | Outputs | SceneItems | MediaInputs | Vendors) * @enumValue (General | Config | Scenes | Inputs | Transitions | Filters | Outputs | SceneItems | MediaInputs | Vendors | Ui)
* @enumType EventSubscription * @enumType EventSubscription
* @rpcVersion -1 * @rpcVersion -1
* @initialVersion 5.0.0 * @initialVersion 5.0.0
* @api enums * @api enums
*/ */
All = (General | Config | Scenes | Inputs | Transitions | Filters | Outputs | SceneItems | MediaInputs | Ui | Vendors), All = (General | Config | Scenes | Inputs | Transitions | Filters | Outputs | SceneItems | MediaInputs | Vendors |
Ui),
/** /**
* Subscription value to receive the `InputVolumeMeters` high-volume event. * Subscription value to receive the `InputVolumeMeters` high-volume event.
* *

View File

@ -21,25 +21,20 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <QPainter> #include <QPainter>
#include <QUrl> #include <QUrl>
#include <obs-module.h> #include <obs-module.h>
#include <qrcodegen.hpp>
#include "ConnectInfo.h" #include "ConnectInfo.h"
#include "../../deps/qr/cpp/QrCode.hpp"
#include "../obs-websocket.h" #include "../obs-websocket.h"
#include "../Config.h" #include "../Config.h"
#include "../utils/Platform.h" #include "../utils/Platform.h"
ConnectInfo::ConnectInfo(QWidget* parent) : ConnectInfo::ConnectInfo(QWidget *parent) : QDialog(parent, Qt::Dialog), ui(new Ui::ConnectInfo)
QDialog(parent, Qt::Dialog),
ui(new Ui::ConnectInfo)
{ {
ui->setupUi(this); ui->setupUi(this);
connect(ui->copyServerIpButton, &QPushButton::clicked, connect(ui->copyServerIpButton, &QPushButton::clicked, this, &ConnectInfo::CopyServerIpButtonClicked);
this, &ConnectInfo::CopyServerIpButtonClicked); connect(ui->copyServerPortButton, &QPushButton::clicked, this, &ConnectInfo::CopyServerPortButtonClicked);
connect(ui->copyServerPortButton, &QPushButton::clicked, connect(ui->copyServerPasswordButton, &QPushButton::clicked, this, &ConnectInfo::CopyServerPasswordButtonClicked);
this, &ConnectInfo::CopyServerPortButtonClicked);
connect(ui->copyServerPasswordButton, &QPushButton::clicked,
this, &ConnectInfo::CopyServerPasswordButtonClicked);
} }
ConnectInfo::~ConnectInfo() ConnectInfo::~ConnectInfo()
@ -110,17 +105,17 @@ void ConnectInfo::SetClipboardText(QString text)
void ConnectInfo::DrawQr(QString qrText) void ConnectInfo::DrawQr(QString qrText)
{ {
QPixmap map(230, 230); QPixmap map(236, 236);
map.fill(Qt::white); map.fill(Qt::white);
QPainter painter(&map); QPainter painter(&map);
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(QT_TO_UTF8(qrText), qrcodegen::QrCode::Ecc::MEDIUM); qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(QT_TO_UTF8(qrText), qrcodegen::QrCode::Ecc::MEDIUM);
const int s = qr.getSize() > 0 ? qr.getSize() : 1; const int s = qr.getSize() > 0 ? qr.getSize() : 1;
const double w = map.width(); const double w = map.width();
const double h = map.height(); const double h = map.height();
const double aspect = w/h; const double aspect = w / h;
const double size = ((aspect > 1.0) ? h : w); const double size = ((aspect > 1.0) ? h : w);
const double scale = size / (s+2); const double scale = size / (s + 2);
painter.setPen(Qt::NoPen); painter.setPen(Qt::NoPen);
painter.setBrush(Qt::black); painter.setBrush(Qt::black);

View File

@ -21,16 +21,15 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <QtWidgets/QDialog> #include <QtWidgets/QDialog>
#include "../plugin-macros.generated.h" #include "plugin-macros.generated.h"
#include "ui_ConnectInfo.h" #include "ui_ConnectInfo.h"
class ConnectInfo : public QDialog class ConnectInfo : public QDialog {
{
Q_OBJECT Q_OBJECT
public: public:
explicit ConnectInfo(QWidget* parent = 0); explicit ConnectInfo(QWidget *parent = 0);
~ConnectInfo(); ~ConnectInfo();
void showEvent(QShowEvent *event); void showEvent(QShowEvent *event);
void RefreshData(); void RefreshData();

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>451</width> <width>451</width>
<height>412</height> <height>432</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
@ -19,7 +19,7 @@
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>451</width> <width>451</width>
<height>412</height> <height>432</height>
</size> </size>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -31,12 +31,21 @@
<x>10</x> <x>10</x>
<y>10</y> <y>10</y>
<width>431</width> <width>431</width>
<height>101</height> <height>121</height>
</rect> </rect>
</property> </property>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<property name="formAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="serverIpLabel"> <widget class="QLabel" name="serverIpLabel">
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text"> <property name="text">
<string>OBSWebSocket.ConnectInfo.ServerIp</string> <string>OBSWebSocket.ConnectInfo.ServerIp</string>
</property> </property>
@ -46,6 +55,12 @@
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QLineEdit" name="serverIpLineEdit"> <widget class="QLineEdit" name="serverIpLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="readOnly"> <property name="readOnly">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -53,6 +68,12 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="copyServerIpButton"> <widget class="QPushButton" name="copyServerIpButton">
<property name="maximumSize">
<size>
<width>75</width>
<height>16777215</height>
</size>
</property>
<property name="text"> <property name="text">
<string>OBSWebSocket.ConnectInfo.CopyText</string> <string>OBSWebSocket.ConnectInfo.CopyText</string>
</property> </property>
@ -62,6 +83,12 @@
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="serverPortLabel"> <widget class="QLabel" name="serverPortLabel">
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text"> <property name="text">
<string>OBSWebSocket.ConnectInfo.ServerPort</string> <string>OBSWebSocket.ConnectInfo.ServerPort</string>
</property> </property>
@ -71,6 +98,12 @@
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<widget class="QLineEdit" name="serverPortLineEdit"> <widget class="QLineEdit" name="serverPortLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="readOnly"> <property name="readOnly">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -78,6 +111,12 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="copyServerPortButton"> <widget class="QPushButton" name="copyServerPortButton">
<property name="maximumSize">
<size>
<width>75</width>
<height>16777215</height>
</size>
</property>
<property name="text"> <property name="text">
<string>OBSWebSocket.ConnectInfo.CopyText</string> <string>OBSWebSocket.ConnectInfo.CopyText</string>
</property> </property>
@ -87,6 +126,12 @@
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="serverPasswordLabel"> <widget class="QLabel" name="serverPasswordLabel">
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text"> <property name="text">
<string>OBSWebSocket.ConnectInfo.ServerPassword</string> <string>OBSWebSocket.ConnectInfo.ServerPassword</string>
</property> </property>
@ -96,9 +141,15 @@
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item> <item>
<widget class="QLineEdit" name="serverPasswordLineEdit"> <widget class="QLineEdit" name="serverPasswordLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text"> <property name="text">
<string>OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText</string> <string>OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText</string>
</property> </property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="readOnly"> <property name="readOnly">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -106,6 +157,12 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="copyServerPasswordButton"> <widget class="QPushButton" name="copyServerPasswordButton">
<property name="maximumSize">
<size>
<width>75</width>
<height>16777215</height>
</size>
</property>
<property name="text"> <property name="text">
<string>OBSWebSocket.ConnectInfo.CopyText</string> <string>OBSWebSocket.ConnectInfo.CopyText</string>
</property> </property>
@ -119,7 +176,7 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>10</x>
<y>120</y> <y>140</y>
<width>431</width> <width>431</width>
<height>281</height> <height>281</height>
</rect> </rect>
@ -131,9 +188,9 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>100</x> <x>100</x>
<y>40</y> <y>30</y>
<width>230</width> <width>236</width>
<height>230</height> <height>236</height>
</rect> </rect>
</property> </property>
<property name="text"> <property name="text">

View File

@ -37,12 +37,12 @@ QString GetToolTipIconHtml()
return iconTemplate.arg(iconFile); return iconTemplate.arg(iconFile);
} }
SettingsDialog::SettingsDialog(QWidget* parent) : SettingsDialog::SettingsDialog(QWidget *parent)
QDialog(parent, Qt::Dialog), : QDialog(parent, Qt::Dialog),
ui(new Ui::SettingsDialog), ui(new Ui::SettingsDialog),
connectInfo(new ConnectInfo), connectInfo(new ConnectInfo),
sessionTableTimer(new QTimer), sessionTableTimer(new QTimer),
passwordManuallyEdited(false) passwordManuallyEdited(false)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->websocketSessionTable->horizontalHeader()->resizeSection(3, 100); // Resize Session Table column widths ui->websocketSessionTable->horizontalHeader()->resizeSection(3, 100); // Resize Session Table column widths
@ -52,22 +52,15 @@ SettingsDialog::SettingsDialog(QWidget* parent) :
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
// Set the appropriate tooltip icon for the theme // Set the appropriate tooltip icon for the theme
QString toolTipHtml = GetToolTipIconHtml(); ui->enableDebugLoggingToolTipLabel->setText(GetToolTipIconHtml());
ui->enableDebugLoggingToolTipLabel->setText(toolTipHtml);
ui->allowExternalToolTipLabel->setText(toolTipHtml);
connect(sessionTableTimer, &QTimer::timeout, connect(sessionTableTimer, &QTimer::timeout, this, &SettingsDialog::FillSessionTable);
this, &SettingsDialog::FillSessionTable); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &SettingsDialog::DialogButtonClicked);
connect(ui->buttonBox, &QDialogButtonBox::clicked, connect(ui->enableAuthenticationCheckBox, &QCheckBox::stateChanged, this,
this, &SettingsDialog::DialogButtonClicked); &SettingsDialog::EnableAuthenticationCheckBoxChanged);
connect(ui->enableAuthenticationCheckBox, &QCheckBox::stateChanged, connect(ui->generatePasswordButton, &QPushButton::clicked, this, &SettingsDialog::GeneratePasswordButtonClicked);
this, &SettingsDialog::EnableAuthenticationCheckBoxChanged); connect(ui->showConnectInfoButton, &QPushButton::clicked, this, &SettingsDialog::ShowConnectInfoButtonClicked);
connect(ui->generatePasswordButton, &QPushButton::clicked, connect(ui->serverPasswordLineEdit, &QLineEdit::textEdited, this, &SettingsDialog::PasswordEdited);
this, &SettingsDialog::GeneratePasswordButtonClicked);
connect(ui->showConnectInfoButton, &QPushButton::clicked,
this, &SettingsDialog::ShowConnectInfoButtonClicked);
connect(ui->serverPasswordLineEdit, &QLineEdit::textEdited,
this, &SettingsDialog::PasswordEdited);
} }
SettingsDialog::~SettingsDialog() SettingsDialog::~SettingsDialog()
@ -129,16 +122,12 @@ void SettingsDialog::RefreshData()
ui->enableSystemTrayAlertsCheckBox->setChecked(conf->AlertsEnabled); ui->enableSystemTrayAlertsCheckBox->setChecked(conf->AlertsEnabled);
ui->enableDebugLoggingCheckBox->setChecked(conf->DebugEnabled); ui->enableDebugLoggingCheckBox->setChecked(conf->DebugEnabled);
ui->serverPortSpinBox->setValue(conf->ServerPort); ui->serverPortSpinBox->setValue(conf->ServerPort);
ui->allowExternalCheckBox->setChecked(!conf->BindLoopback);
ui->enableAuthenticationCheckBox->setChecked(conf->AuthRequired); ui->enableAuthenticationCheckBox->setChecked(conf->AuthRequired);
ui->serverPasswordLineEdit->setText(conf->ServerPassword); ui->serverPasswordLineEdit->setText(conf->ServerPassword);
ui->showConnectInfoButton->setEnabled(!conf->BindLoopback);
ui->serverPasswordLineEdit->setEnabled(conf->AuthRequired); ui->serverPasswordLineEdit->setEnabled(conf->AuthRequired);
ui->generatePasswordButton->setEnabled(conf->AuthRequired); ui->generatePasswordButton->setEnabled(conf->AuthRequired);
ui->showConnectInfoButton->setToolTip(ui->allowExternalCheckBox->isChecked() ? "" : obs_module_text("OBSWebSocket.Settings.ShowConnectInfoHoverText"));
FillSessionTable(); FillSessionTable();
} }
@ -179,25 +168,24 @@ void SettingsDialog::SaveFormData()
int ret = msgBox.exec(); int ret = msgBox.exec();
switch (ret) { switch (ret) {
case QMessageBox::Yes: case QMessageBox::Yes:
break; break;
case QMessageBox::No: case QMessageBox::No:
default: default:
ui->serverPasswordLineEdit->setText(conf->ServerPassword); ui->serverPasswordLineEdit->setText(conf->ServerPassword);
return; return;
} }
} }
bool needsRestart = (conf->ServerEnabled != ui->enableWebSocketServerCheckBox->isChecked()) || bool needsRestart =
(ui->enableAuthenticationCheckBox->isChecked() && conf->ServerPassword != ui->serverPasswordLineEdit->text()) || (conf->ServerEnabled != ui->enableWebSocketServerCheckBox->isChecked()) ||
(conf->BindLoopback == ui->allowExternalCheckBox->isChecked()) || (conf->ServerPort != ui->serverPortSpinBox->value()) ||
(conf->ServerPort != ui->serverPortSpinBox->value()); (ui->enableAuthenticationCheckBox->isChecked() && conf->ServerPassword != ui->serverPasswordLineEdit->text());
conf->ServerEnabled = ui->enableWebSocketServerCheckBox->isChecked(); conf->ServerEnabled = ui->enableWebSocketServerCheckBox->isChecked();
conf->AlertsEnabled = ui->enableSystemTrayAlertsCheckBox->isChecked(); conf->AlertsEnabled = ui->enableSystemTrayAlertsCheckBox->isChecked();
conf->DebugEnabled = ui->enableDebugLoggingCheckBox->isChecked(); conf->DebugEnabled = ui->enableDebugLoggingCheckBox->isChecked();
conf->ServerPort = ui->serverPortSpinBox->value(); conf->ServerPort = ui->serverPortSpinBox->value();
conf->BindLoopback = !ui->allowExternalCheckBox->isChecked();
conf->AuthRequired = ui->enableAuthenticationCheckBox->isChecked(); conf->AuthRequired = ui->enableAuthenticationCheckBox->isChecked();
conf->ServerPassword = ui->serverPasswordLineEdit->text(); conf->ServerPassword = ui->serverPasswordLineEdit->text();
@ -246,7 +234,8 @@ void SettingsDialog::FillSessionTable()
QTableWidgetItem *durationItem = new QTableWidgetItem(QTime(0, 0, sessionDuration).toString("hh:mm:ss")); QTableWidgetItem *durationItem = new QTableWidgetItem(QTime(0, 0, sessionDuration).toString("hh:mm:ss"));
ui->websocketSessionTable->setItem(i, 1, durationItem); ui->websocketSessionTable->setItem(i, 1, durationItem);
QTableWidgetItem *statsItem = new QTableWidgetItem(QString("%1/%2").arg(session.incomingMessages).arg(session.outgoingMessages)); QTableWidgetItem *statsItem =
new QTableWidgetItem(QString("%1/%2").arg(session.incomingMessages).arg(session.outgoingMessages));
ui->websocketSessionTable->setItem(i, 2, statsItem); ui->websocketSessionTable->setItem(i, 2, statsItem);
QLabel *identifiedLabel = new QLabel(); QLabel *identifiedLabel = new QLabel();
@ -266,9 +255,7 @@ void SettingsDialog::FillSessionTable()
invalidateButtonLayout->setContentsMargins(0, 0, 0, 0); invalidateButtonLayout->setContentsMargins(0, 0, 0, 0);
invalidateButtonWidget->setLayout(invalidateButtonLayout); invalidateButtonWidget->setLayout(invalidateButtonLayout);
ui->websocketSessionTable->setCellWidget(i, 4, invalidateButtonWidget); ui->websocketSessionTable->setCellWidget(i, 4, invalidateButtonWidget);
connect(invalidateButton, &QPushButton::clicked, [=]() { connect(invalidateButton, &QPushButton::clicked, [=]() { webSocketServer->InvalidateSession(session.hdl); });
webSocketServer->InvalidateSession(session.hdl);
});
i++; i++;
} }
@ -305,11 +292,11 @@ void SettingsDialog::ShowConnectInfoButtonClicked()
int ret = msgBox.exec(); int ret = msgBox.exec();
switch (ret) { switch (ret) {
case QMessageBox::Yes: case QMessageBox::Yes:
break; break;
case QMessageBox::No: case QMessageBox::No:
default: default:
return; return;
} }
} }

View File

@ -23,16 +23,15 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <QTimer> #include <QTimer>
#include "ConnectInfo.h" #include "ConnectInfo.h"
#include "../plugin-macros.generated.h" #include "plugin-macros.generated.h"
#include "ui_SettingsDialog.h" #include "ui_SettingsDialog.h"
class SettingsDialog : public QDialog class SettingsDialog : public QDialog {
{
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsDialog(QWidget* parent = 0); explicit SettingsDialog(QWidget *parent = 0);
~SettingsDialog(); ~SettingsDialog();
void showEvent(QShowEvent *event); void showEvent(QShowEvent *event);
void hideEvent(QHideEvent *event); void hideEvent(QHideEvent *event);

View File

@ -80,7 +80,7 @@
<item row="3" column="1"> <item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>2</number>
</property> </property>
<item> <item>
<widget class="QCheckBox" name="enableDebugLoggingCheckBox"> <widget class="QCheckBox" name="enableDebugLoggingCheckBox">
@ -97,6 +97,12 @@
<property name="toolTip"> <property name="toolTip">
<string>OBSWebSocket.Settings.DebugEnableHoverText</string> <string>OBSWebSocket.Settings.DebugEnableHoverText</string>
</property> </property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -155,21 +161,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="1" column="1">
<widget class="QCheckBox" name="enableAuthenticationCheckBox"> <widget class="QCheckBox" name="enableAuthenticationCheckBox">
<property name="text"> <property name="text">
<string>OBSWebSocket.Settings.AuthRequired</string> <string>OBSWebSocket.Settings.AuthRequired</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="2" column="0">
<widget class="QLabel" name="serverPasswordLabel"> <widget class="QLabel" name="serverPasswordLabel">
<property name="text"> <property name="text">
<string>OBSWebSocket.Settings.Password</string> <string>OBSWebSocket.Settings.Password</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QLineEdit" name="serverPasswordLineEdit"> <widget class="QLineEdit" name="serverPasswordLineEdit">
@ -187,7 +193,7 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="5" column="0"> <item row="3" column="0">
<spacer name="horizontalSpacer_2"> <spacer name="horizontalSpacer_2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -203,47 +209,13 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="5" column="1"> <item row="3" column="1">
<widget class="QPushButton" name="showConnectInfoButton"> <widget class="QPushButton" name="showConnectInfoButton">
<property name="text"> <property name="text">
<string>OBSWebSocket.Settings.ShowConnectInfo</string> <string>OBSWebSocket.Settings.ShowConnectInfo</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="allowExternalCheckBox">
<property name="text">
<string>OBSWebSocket.Settings.AllowExternal</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="allowExternalToolTipLabel">
<property name="toolTip">
<string>OBSWebSocket.Settings.AllowExternalHoverText</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -32,10 +32,16 @@ with this program. If not, see <https://www.gnu.org/licenses/>
OBS_DECLARE_MODULE() OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE("obs-websocket", "en-US") OBS_MODULE_USE_DEFAULT_LOCALE("obs-websocket", "en-US")
OBS_MODULE_AUTHOR("OBSProject") OBS_MODULE_AUTHOR("OBSProject")
const char *obs_module_name(void) { return "obs-websocket"; } const char *obs_module_name(void)
const char *obs_module_description(void) { return obs_module_text("OBSWebSocket.Plugin.Description"); } {
return "obs-websocket";
}
const char *obs_module_description(void)
{
return obs_module_text("OBSWebSocket.Plugin.Description");
}
os_cpu_usage_info_t* _cpuUsageInfo; os_cpu_usage_info_t *_cpuUsageInfo;
ConfigPtr _config; ConfigPtr _config;
EventHandlerPtr _eventHandler; EventHandlerPtr _eventHandler;
WebSocketApiPtr _webSocketApi; WebSocketApiPtr _webSocketApi;
@ -46,7 +52,8 @@ void WebSocketApiEventCallback(std::string vendorName, std::string eventType, ob
bool obs_module_load(void) bool obs_module_load(void)
{ {
blog(LOG_INFO, "[obs_module_load] you can haz websockets (Version: %s | RPC Version: %d)", OBS_WEBSOCKET_VERSION, OBS_WEBSOCKET_RPC_VERSION); blog(LOG_INFO, "[obs_module_load] you can haz websockets (Version: %s | RPC Version: %d)", OBS_WEBSOCKET_VERSION,
OBS_WEBSOCKET_RPC_VERSION);
blog(LOG_INFO, "[obs_module_load] Qt version (compile-time): %s | Qt version (run-time): %s", QT_VERSION_STR, qVersion()); blog(LOG_INFO, "[obs_module_load] Qt version (compile-time): %s | Qt version (run-time): %s", QT_VERSION_STR, qVersion());
blog(LOG_INFO, "[obs_module_load] Linked ASIO Version: %d", ASIO_VERSION); blog(LOG_INFO, "[obs_module_load] Linked ASIO Version: %d", ASIO_VERSION);
@ -69,20 +76,37 @@ bool obs_module_load(void)
// Initialize the settings dialog // Initialize the settings dialog
obs_frontend_push_ui_translation(obs_module_get_string); obs_frontend_push_ui_translation(obs_module_get_string);
QMainWindow* mainWindow = static_cast<QMainWindow*>(obs_frontend_get_main_window()); QMainWindow *mainWindow = static_cast<QMainWindow *>(obs_frontend_get_main_window());
_settingsDialog = new SettingsDialog(mainWindow); _settingsDialog = new SettingsDialog(mainWindow);
obs_frontend_pop_ui_translation(); obs_frontend_pop_ui_translation();
// Add the settings dialog to the tools menu // Add the settings dialog to the tools menu
const char* menuActionText = obs_module_text("OBSWebSocket.Settings.DialogTitle"); const char *menuActionText = obs_module_text("OBSWebSocket.Settings.DialogTitle");
QAction* menuAction = (QAction*)obs_frontend_add_tools_menu_qaction(menuActionText); QAction *menuAction = (QAction *)obs_frontend_add_tools_menu_qaction(menuActionText);
QObject::connect(menuAction, &QAction::triggered, [] { _settingsDialog->ToggleShowHide(); }); QObject::connect(menuAction, &QAction::triggered, [] { _settingsDialog->ToggleShowHide(); });
blog(LOG_INFO, "[obs_module_load] Module loaded."); blog(LOG_INFO, "[obs_module_load] Module loaded.");
return true; return true;
} }
void obs_module_unload() #ifdef PLUGIN_TESTS
void test_register_vendor();
#endif
void obs_module_post_load(void)
{
#ifdef PLUGIN_TESTS
test_register_vendor();
#endif
// Server will accept clients, but requests and events will not be served until FINISHED_LOADING occurs
if (_config->ServerEnabled) {
blog(LOG_INFO, "[obs_module_post_load] WebSocket server is enabled, starting...");
_webSocketServer->Start();
}
}
void obs_module_unload(void)
{ {
blog(LOG_INFO, "[obs_module_unload] Shutting down..."); blog(LOG_INFO, "[obs_module_unload] Shutting down...");
@ -101,8 +125,7 @@ void obs_module_unload()
// Destroy the event handler // Destroy the event handler
_eventHandler.reset(); _eventHandler.reset();
// Save and destroy the config manager // Destroy the config manager
_config->Save();
_config.reset(); _config.reset();
// Destroy the cpu stats // Destroy the cpu stats
@ -111,7 +134,7 @@ void obs_module_unload()
blog(LOG_INFO, "[obs_module_unload] Finished shutting down."); blog(LOG_INFO, "[obs_module_unload] Finished shutting down.");
} }
os_cpu_usage_info_t* GetCpuUsageInfo() os_cpu_usage_info_t *GetCpuUsageInfo()
{ {
return _cpuUsageInfo; return _cpuUsageInfo;
} }
@ -186,35 +209,36 @@ static void test_vendor_request_cb(obs_data_t *requestData, obs_data_t *response
obs_websocket_vendor_emit_event(priv_data, "TestEvent", requestData); obs_websocket_vendor_emit_event(priv_data, "TestEvent", requestData);
} }
void obs_module_post_load() void test_register_vendor()
{ {
blog(LOG_INFO, "[obs_module_post_load] Post load started."); blog(LOG_INFO, "[test_register_vendor] Registering test vendor...");
// Test plugin API version fetch // Test plugin API version fetch
uint apiVersion = obs_websocket_get_api_version(); uint apiVersion = obs_websocket_get_api_version();
blog(LOG_INFO, "[obs_module_post_load] obs-websocket plugin API version: %u", apiVersion); blog(LOG_INFO, "[test_register_vendor] obs-websocket plugin API version: %u", apiVersion);
// Test calling obs-websocket requests // Test calling obs-websocket requests
struct obs_websocket_request_response *response = obs_websocket_call_request("GetVersion"); struct obs_websocket_request_response *response = obs_websocket_call_request("GetVersion");
if (response) { if (response) {
blog(LOG_INFO, "[obs_module_post_load] Called GetVersion. Status Code: %u | Comment: %s | Response Data: %s", response->status_code, response->comment, response->response_data); blog(LOG_INFO, "[test_register_vendor] Called GetVersion. Status Code: %u | Comment: %s | Response Data: %s",
response->status_code, response->comment, response->response_data);
obs_websocket_request_response_free(response); obs_websocket_request_response_free(response);
} }
// Test vendor creation // Test vendor creation
auto vendor = obs_websocket_register_vendor("obs-websocket-test"); auto vendor = obs_websocket_register_vendor("obs-websocket-test");
if (!vendor) { if (!vendor) {
blog(LOG_WARNING, "[obs_module_post_load] Failed to create vendor!"); blog(LOG_WARNING, "[test_register_vendor] Failed to create vendor!");
return; return;
} }
// Test vendor request registration // Test vendor request registration
if (!obs_websocket_vendor_register_request(vendor, "TestRequest", test_vendor_request_cb, vendor)) { if (!obs_websocket_vendor_register_request(vendor, "TestRequest", test_vendor_request_cb, vendor)) {
blog(LOG_WARNING, "[obs_module_post_load] Failed to register vendor request!"); blog(LOG_WARNING, "[test_register_vendor] Failed to register vendor request!");
return; return;
} }
blog(LOG_INFO, "[obs_module_post_load] Post load completed."); blog(LOG_INFO, "[test_register_vendor] Post load completed.");
} }
#endif #endif

View File

@ -26,7 +26,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "utils/Obs.h" #include "utils/Obs.h"
#include "plugin-macros.generated.h" #include "plugin-macros.generated.h"
class Config; struct Config;
typedef std::shared_ptr<Config> ConfigPtr; typedef std::shared_ptr<Config> ConfigPtr;
class EventHandler; class EventHandler;
@ -38,7 +38,7 @@ typedef std::shared_ptr<WebSocketApi> WebSocketApiPtr;
class WebSocketServer; class WebSocketServer;
typedef std::shared_ptr<WebSocketServer> WebSocketServerPtr; typedef std::shared_ptr<WebSocketServer> WebSocketServerPtr;
os_cpu_usage_info_t* GetCpuUsageInfo(); os_cpu_usage_info_t *GetCpuUsageInfo();
ConfigPtr GetConfig(); ConfigPtr GetConfig();

View File

@ -24,7 +24,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#define blog_debug(msg, ...) if (IsDebugEnabled()) blog(LOG_INFO, "[debug] " msg, ##__VA_ARGS__) #define blog_debug(msg, ...) if (IsDebugEnabled()) blog(LOG_INFO, "[debug] " msg, ##__VA_ARGS__)
#define OBS_WEBSOCKET_VERSION "@OBS_WEBSOCKET_VERSION@" #define OBS_WEBSOCKET_VERSION "@obs-websocket_VERSION@"
#define OBS_WEBSOCKET_RPC_VERSION @OBS_WEBSOCKET_RPC_VERSION@ #define OBS_WEBSOCKET_RPC_VERSION @OBS_WEBSOCKET_RPC_VERSION@

View File

@ -24,56 +24,54 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "../utils/Compat.h" #include "../utils/Compat.h"
#include "../obs-websocket.h" #include "../obs-websocket.h"
struct SerialFrameBatch struct SerialFrameBatch {
{
RequestHandler &requestHandler; RequestHandler &requestHandler;
std::queue<RequestBatchRequest> requests; std::queue<RequestBatchRequest> requests;
std::vector<RequestResult> results; std::vector<RequestResult> results;
json &variables; json &variables;
bool haltOnFailure; bool haltOnFailure;
size_t frameCount; size_t frameCount = 0;
size_t sleepUntilFrame; size_t sleepUntilFrame = 0;
std::mutex conditionMutex; std::mutex conditionMutex;
std::condition_variable condition; std::condition_variable condition;
SerialFrameBatch(RequestHandler &requestHandler, json &variables, bool haltOnFailure) : SerialFrameBatch(RequestHandler &requestHandler, json &variables, bool haltOnFailure)
requestHandler(requestHandler), : requestHandler(requestHandler), variables(variables), haltOnFailure(haltOnFailure)
variables(variables), {
haltOnFailure(haltOnFailure), }
frameCount(0),
sleepUntilFrame(0)
{}
}; };
struct ParallelBatchResults struct ParallelBatchResults {
{
RequestHandler &requestHandler; RequestHandler &requestHandler;
std::vector<RequestResult> results; std::vector<RequestResult> results;
std::mutex conditionMutex; std::mutex conditionMutex;
std::condition_variable condition; std::condition_variable condition;
ParallelBatchResults(RequestHandler &requestHandler) : ParallelBatchResults(RequestHandler &requestHandler) : requestHandler(requestHandler) {}
requestHandler(requestHandler)
{}
}; };
// `{"inputName": "inputNameVariable"}` is essentially `inputName = inputNameVariable` // `{"inputName": "inputNameVariable"}` is essentially `inputName = inputNameVariable`
static void PreProcessVariables(const json &variables, RequestBatchRequest &request) static void PreProcessVariables(const json &variables, RequestBatchRequest &request)
{ {
if (variables.empty() || !request.InputVariables.is_object() || request.InputVariables.empty() || !request.RequestData.is_object()) if (variables.empty() || !request.InputVariables.is_object() || request.InputVariables.empty() ||
!request.RequestData.is_object())
return; return;
for (auto& [key, value] : request.InputVariables.items()) { for (auto &[key, value] : request.InputVariables.items()) {
if (!value.is_string()) { if (!value.is_string()) {
blog_debug("[WebSocketServer::ProcessRequestBatch] Value of field `%s` in `inputVariables `is not a string. Skipping!", key.c_str()); blog_debug(
"[WebSocketServer::ProcessRequestBatch] Value of field `%s` in `inputVariables `is not a string. Skipping!",
key.c_str());
continue; continue;
} }
std::string valueString = value; std::string valueString = value;
if (!variables.contains(valueString)) { if (!variables.contains(valueString)) {
blog_debug("[WebSocketServer::ProcessRequestBatch] `inputVariables` requested variable `%s`, but it does not exist. Skipping!", valueString.c_str()); blog_debug(
"[WebSocketServer::ProcessRequestBatch] `inputVariables` requested variable `%s`, but it does not exist. Skipping!",
valueString.c_str());
continue; continue;
} }
@ -89,15 +87,19 @@ static void PostProcessVariables(json &variables, const RequestBatchRequest &req
if (!request.OutputVariables.is_object() || request.OutputVariables.empty() || requestResult.ResponseData.empty()) if (!request.OutputVariables.is_object() || request.OutputVariables.empty() || requestResult.ResponseData.empty())
return; return;
for (auto& [key, value] : request.OutputVariables.items()) { for (auto &[key, value] : request.OutputVariables.items()) {
if (!value.is_string()) { if (!value.is_string()) {
blog_debug("[WebSocketServer::ProcessRequestBatch] Value of field `%s` in `outputVariables` is not a string. Skipping!", key.c_str()); blog_debug(
"[WebSocketServer::ProcessRequestBatch] Value of field `%s` in `outputVariables` is not a string. Skipping!",
key.c_str());
continue; continue;
} }
std::string valueString = value; std::string valueString = value;
if (!requestResult.ResponseData.contains(valueString)) { if (!requestResult.ResponseData.contains(valueString)) {
blog_debug("[WebSocketServer::ProcessRequestBatch] `outputVariables` requested responseData field `%s`, but it does not exist. Skipping!", valueString.c_str()); blog_debug(
"[WebSocketServer::ProcessRequestBatch] `outputVariables` requested responseData field `%s`, but it does not exist. Skipping!",
valueString.c_str());
continue; continue;
} }
@ -109,7 +111,7 @@ static void ObsTickCallback(void *param, float)
{ {
ScopeProfiler prof{"obs_websocket_request_batch_frame_tick"}; ScopeProfiler prof{"obs_websocket_request_batch_frame_tick"};
auto serialFrameBatch = static_cast<SerialFrameBatch*>(param); auto serialFrameBatch = static_cast<SerialFrameBatch *>(param);
// Increment frame count // Increment frame count
serialFrameBatch->frameCount++; serialFrameBatch->frameCount++;
@ -156,7 +158,10 @@ static void ObsTickCallback(void *param, float)
serialFrameBatch->condition.notify_one(); serialFrameBatch->condition.notify_one();
} }
std::vector<RequestResult> RequestBatchHandler::ProcessRequestBatch(QThreadPool &threadPool, SessionPtr session, RequestBatchExecutionType::RequestBatchExecutionType executionType, std::vector<RequestBatchRequest> &requests, json &variables, bool haltOnFailure) std::vector<RequestResult>
RequestBatchHandler::ProcessRequestBatch(QThreadPool &threadPool, SessionPtr session,
RequestBatchExecutionType::RequestBatchExecutionType executionType,
std::vector<RequestBatchRequest> &requests, json &variables, bool haltOnFailure)
{ {
RequestHandler requestHandler(session); RequestHandler requestHandler(session);
if (executionType == RequestBatchExecutionType::SerialRealtime) { if (executionType == RequestBatchExecutionType::SerialRealtime) {
@ -189,7 +194,7 @@ std::vector<RequestResult> RequestBatchHandler::ProcessRequestBatch(QThreadPool
// Wait until the graphics thread processes the last request in the queue // Wait until the graphics thread processes the last request in the queue
std::unique_lock<std::mutex> lock(serialFrameBatch.conditionMutex); std::unique_lock<std::mutex> lock(serialFrameBatch.conditionMutex);
serialFrameBatch.condition.wait(lock, [&serialFrameBatch]{return serialFrameBatch.requests.empty();}); serialFrameBatch.condition.wait(lock, [&serialFrameBatch] { return serialFrameBatch.requests.empty(); });
// Remove the created callback entry since we don't need it anymore // Remove the created callback entry since we don't need it anymore
obs_remove_tick_callback(ObsTickCallback, &serialFrameBatch); obs_remove_tick_callback(ObsTickCallback, &serialFrameBatch);
@ -215,7 +220,9 @@ std::vector<RequestResult> RequestBatchHandler::ProcessRequestBatch(QThreadPool
// Wait for the last request to finish processing // Wait for the last request to finish processing
size_t requestCount = requests.size(); size_t requestCount = requests.size();
parallelResults.condition.wait(lock, [&parallelResults, requestCount]{return parallelResults.results.size() == requestCount;}); parallelResults.condition.wait(lock, [&parallelResults, requestCount] {
return parallelResults.results.size() == requestCount;
});
return parallelResults.results; return parallelResults.results;
} }

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