mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
Merge branch 'master' into docs-formatting
This commit is contained in:
commit
ac102de1e8
1
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@ -69,6 +69,7 @@ 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.0.0-alpha3
|
- 5.0.0-alpha3
|
||||||
- 5.0.0-alpha2
|
- 5.0.0-alpha2
|
||||||
- 4.9.1
|
- 4.9.1
|
||||||
|
3
.github/workflows/main.yml
vendored
3
.github/workflows/main.yml
vendored
@ -470,7 +470,8 @@ jobs:
|
|||||||
-DLIBOBS_LIB=${{ 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" \
|
-DOBS_FRONTEND_LIB="${{ github.workspace }}/obs-studio/build/UI/obs-frontend-api/libobs-frontend-api.dylib" \
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
-DCMAKE_INSTALL_PREFIX=/usr
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
|
-DOBS_WEBSOCKET_VERSION_SUFFIX="${{ env.CMAKE_VERSION_SUFFIX }}"
|
||||||
- name: 'Build obs-websocket'
|
- name: 'Build obs-websocket'
|
||||||
working-directory: ${{ github.workspace }}/obs-websocket/build
|
working-directory: ${{ github.workspace }}/obs-websocket/build
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -20,7 +20,7 @@ Binaries for Windows, MacOS, and Linux are available in the [Releases](https://g
|
|||||||
|
|
||||||
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 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.
|
||||||
|
|
||||||
(Psst. You can use `--websocket_port`(value), `--websocket_password`(value), and `--websocket_debug`(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.)
|
||||||
|
|
||||||
### Possible use cases
|
### Possible use cases
|
||||||
|
|
||||||
@ -38,6 +38,8 @@ 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
|
- Rust: [obws](https://github.com/dnaka91/obws/tree/v5-api) by dnaka91
|
||||||
|
- Godot 3.4.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
|
||||||
|
|
||||||
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).
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# obs-websocket documentation
|
# obs-websocket documentation
|
||||||
|
|
||||||
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.
|
||||||
- `docs/process_comments.py`: Processes `work/comments.json` to create `generated/protocol.json`, which is a machine-readable documentation format that can be used to create obs-websocket client libraries.
|
- `docs/process_comments.py`: Processes `work/comments.json` to create `generated/protocol.json`, which is a machine-readable documentation format that can be used to create obs-websocket client libraries.
|
||||||
|
@ -1443,6 +1443,42 @@
|
|||||||
],
|
],
|
||||||
"responseFields": []
|
"responseFields": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"description": "Sets the enable state of a source filter.",
|
||||||
|
"requestType": "SetSourceFilterEnabled",
|
||||||
|
"complexity": 3,
|
||||||
|
"rpcVersion": "1",
|
||||||
|
"deprecated": false,
|
||||||
|
"initialVersion": "5.0.0",
|
||||||
|
"category": "filters",
|
||||||
|
"requestFields": [
|
||||||
|
{
|
||||||
|
"valueName": "sourceName",
|
||||||
|
"valueType": "String",
|
||||||
|
"valueDescription": "Name of the source the filter is on",
|
||||||
|
"valueRestrictions": null,
|
||||||
|
"valueOptional": false,
|
||||||
|
"valueOptionalBehavior": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valueName": "filterName",
|
||||||
|
"valueType": "String",
|
||||||
|
"valueDescription": "Name of the filter",
|
||||||
|
"valueRestrictions": null,
|
||||||
|
"valueOptional": false,
|
||||||
|
"valueOptionalBehavior": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valueName": "filterEnabled",
|
||||||
|
"valueType": "Boolean",
|
||||||
|
"valueDescription": "New enable state of the filter",
|
||||||
|
"valueRestrictions": null,
|
||||||
|
"valueOptional": false,
|
||||||
|
"valueOptionalBehavior": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responseFields": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "Gets data about the current plugin and RPC version.",
|
"description": "Gets data about the current plugin and RPC version.",
|
||||||
"requestType": "GetVersion",
|
"requestType": "GetVersion",
|
||||||
@ -1477,6 +1513,16 @@
|
|||||||
"valueName": "supportedImageFormats",
|
"valueName": "supportedImageFormats",
|
||||||
"valueType": "Array<String>",
|
"valueType": "Array<String>",
|
||||||
"valueDescription": "Image formats available in `GetSourceScreenshot` and `SaveSourceScreenshot` requests."
|
"valueDescription": "Image formats available in `GetSourceScreenshot` and `SaveSourceScreenshot` requests."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valueName": "platform",
|
||||||
|
"valueType": "String",
|
||||||
|
"valueDescription": "Name of the platform. Usually `windows`, `macos`, or `ubuntu` (linux flavor). Not guaranteed to be any of those"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valueName": "platformDescription",
|
||||||
|
"valueType": "String",
|
||||||
|
"valueDescription": "Description of the platform, like `Windows 10 (10.0)`"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -2891,6 +2937,14 @@
|
|||||||
"valueRestrictions": null,
|
"valueRestrictions": null,
|
||||||
"valueOptional": false,
|
"valueOptional": false,
|
||||||
"valueOptionalBehavior": null
|
"valueOptionalBehavior": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valueName": "searchOffset",
|
||||||
|
"valueType": "Number",
|
||||||
|
"valueDescription": "Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item",
|
||||||
|
"valueRestrictions": ">= -1",
|
||||||
|
"valueOptional": true,
|
||||||
|
"valueOptionalBehavior": "0"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responseFields": [
|
"responseFields": [
|
||||||
@ -4183,6 +4237,23 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responseFields": []
|
"responseFields": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Gets a list of connected monitors and information about them.",
|
||||||
|
"requestType": "GetMonitorList",
|
||||||
|
"complexity": 2,
|
||||||
|
"rpcVersion": "1",
|
||||||
|
"deprecated": false,
|
||||||
|
"initialVersion": "5.0.0",
|
||||||
|
"category": "ui",
|
||||||
|
"requestFields": [],
|
||||||
|
"responseFields": [
|
||||||
|
{
|
||||||
|
"valueName": "monitors",
|
||||||
|
"valueType": "Array<Object>",
|
||||||
|
"valueDescription": "a list of detected monitors with some information"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": [
|
"events": [
|
||||||
@ -4288,6 +4359,28 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"description": "A source's filter list has been reindexed.",
|
||||||
|
"eventType": "SourceFilterListReindexed",
|
||||||
|
"eventSubscription": "Filters",
|
||||||
|
"complexity": 3,
|
||||||
|
"rpcVersion": "1",
|
||||||
|
"deprecated": false,
|
||||||
|
"initialVersion": "5.0.0",
|
||||||
|
"category": "filters",
|
||||||
|
"dataFields": [
|
||||||
|
{
|
||||||
|
"valueName": "sourceName",
|
||||||
|
"valueType": "String",
|
||||||
|
"valueDescription": "Name of the source"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valueName": "filters",
|
||||||
|
"valueType": "Array<Object>",
|
||||||
|
"valueDescription": "Array of filter objects"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "A filter has been added to a source.",
|
"description": "A filter has been added to a source.",
|
||||||
"eventType": "SourceFilterCreated",
|
"eventType": "SourceFilterCreated",
|
||||||
@ -4353,10 +4446,10 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "A source's filter list has been reindexed.",
|
"description": "The name of a source filter has changed.",
|
||||||
"eventType": "SourceFilterListReindexed",
|
"eventType": "SourceFilterNameChanged",
|
||||||
"eventSubscription": "Filters",
|
"eventSubscription": "Filters",
|
||||||
"complexity": 3,
|
"complexity": 2,
|
||||||
"rpcVersion": "1",
|
"rpcVersion": "1",
|
||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"initialVersion": "5.0.0",
|
"initialVersion": "5.0.0",
|
||||||
@ -4365,12 +4458,17 @@
|
|||||||
{
|
{
|
||||||
"valueName": "sourceName",
|
"valueName": "sourceName",
|
||||||
"valueType": "String",
|
"valueType": "String",
|
||||||
"valueDescription": "Name of the source"
|
"valueDescription": "The source the filter is on"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"valueName": "filters",
|
"valueName": "oldFilterName",
|
||||||
"valueType": "Array<Object>",
|
"valueType": "String",
|
||||||
"valueDescription": "Array of filter objects"
|
"valueDescription": "Old name of the filter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valueName": "filterName",
|
||||||
|
"valueType": "String",
|
||||||
|
"valueDescription": "New name of the filter"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -4401,33 +4499,6 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"description": "The name of a source filter has changed.",
|
|
||||||
"eventType": "SourceFilterNameChanged",
|
|
||||||
"eventSubscription": "Filters",
|
|
||||||
"complexity": 2,
|
|
||||||
"rpcVersion": "1",
|
|
||||||
"deprecated": false,
|
|
||||||
"initialVersion": "5.0.0",
|
|
||||||
"category": "filters",
|
|
||||||
"dataFields": [
|
|
||||||
{
|
|
||||||
"valueName": "sourceName",
|
|
||||||
"valueType": "String",
|
|
||||||
"valueDescription": "The source the filter is on"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"valueName": "oldFilterName",
|
|
||||||
"valueType": "String",
|
|
||||||
"valueDescription": "Old name of the filter"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"valueName": "filterName",
|
|
||||||
"valueType": "String",
|
|
||||||
"valueDescription": "New name of the filter"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"description": "OBS has begun the shutdown process.",
|
"description": "OBS has begun the shutdown process.",
|
||||||
"eventType": "ExitStarted",
|
"eventType": "ExitStarted",
|
||||||
@ -5179,7 +5250,7 @@
|
|||||||
"description": "The current scene transition has changed.",
|
"description": "The current scene transition has changed.",
|
||||||
"eventType": "CurrentSceneTransitionChanged",
|
"eventType": "CurrentSceneTransitionChanged",
|
||||||
"eventSubscription": "Transitions",
|
"eventSubscription": "Transitions",
|
||||||
"complexity": 3,
|
"complexity": 2,
|
||||||
"rpcVersion": "1",
|
"rpcVersion": "1",
|
||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"initialVersion": "5.0.0",
|
"initialVersion": "5.0.0",
|
||||||
@ -5209,6 +5280,57 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"description": "A scene transition has started.",
|
||||||
|
"eventType": "SceneTransitionStarted",
|
||||||
|
"eventSubscription": "Transitions",
|
||||||
|
"complexity": 2,
|
||||||
|
"rpcVersion": "1",
|
||||||
|
"deprecated": false,
|
||||||
|
"initialVersion": "5.0.0",
|
||||||
|
"category": "transitions",
|
||||||
|
"dataFields": [
|
||||||
|
{
|
||||||
|
"valueName": "transitionName",
|
||||||
|
"valueType": "String",
|
||||||
|
"valueDescription": "Scene transition name"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "A scene transition has completed fully.\n\nNote: Does not appear to trigger when the transition is interrupted by the user.",
|
||||||
|
"eventType": "SceneTransitionEnded",
|
||||||
|
"eventSubscription": "Transitions",
|
||||||
|
"complexity": 2,
|
||||||
|
"rpcVersion": "1",
|
||||||
|
"deprecated": false,
|
||||||
|
"initialVersion": "5.0.0",
|
||||||
|
"category": "transitions",
|
||||||
|
"dataFields": [
|
||||||
|
{
|
||||||
|
"valueName": "transitionName",
|
||||||
|
"valueType": "String",
|
||||||
|
"valueDescription": "Scene transition name"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "A scene transition's video has completed fully.\n\nUseful for stinger transitions to tell when the video *actually* ends.\n`SceneTransitionEnded` only signifies the cut point, not the completion of transition playback.\n\nNote: Appears to be called by every transition, regardless of relevance.",
|
||||||
|
"eventType": "SceneTransitionVideoEnded",
|
||||||
|
"eventSubscription": "Transitions",
|
||||||
|
"complexity": 2,
|
||||||
|
"rpcVersion": "1",
|
||||||
|
"deprecated": false,
|
||||||
|
"initialVersion": "5.0.0",
|
||||||
|
"category": "transitions",
|
||||||
|
"dataFields": [
|
||||||
|
{
|
||||||
|
"valueName": "transitionName",
|
||||||
|
"valueType": "String",
|
||||||
|
"valueDescription": "Scene transition name"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "Studio mode has been enabled or disabled.",
|
"description": "Studio mode has been enabled or disabled.",
|
||||||
"eventType": "StudioModeStateChanged",
|
"eventType": "StudioModeStateChanged",
|
||||||
|
@ -1282,12 +1282,15 @@ Subscription value to receive the `SceneItemTransformChanged` high-volume event.
|
|||||||
- [Transitions](#transitions)
|
- [Transitions](#transitions)
|
||||||
- [CurrentSceneTransitionChanged](#currentscenetransitionchanged)
|
- [CurrentSceneTransitionChanged](#currentscenetransitionchanged)
|
||||||
- [CurrentSceneTransitionDurationChanged](#currentscenetransitiondurationchanged)
|
- [CurrentSceneTransitionDurationChanged](#currentscenetransitiondurationchanged)
|
||||||
|
- [SceneTransitionStarted](#scenetransitionstarted)
|
||||||
|
- [SceneTransitionEnded](#scenetransitionended)
|
||||||
|
- [SceneTransitionVideoEnded](#scenetransitionvideoended)
|
||||||
- [Filters](#filters)
|
- [Filters](#filters)
|
||||||
|
- [SourceFilterListReindexed](#sourcefilterlistreindexed)
|
||||||
- [SourceFilterCreated](#sourcefiltercreated)
|
- [SourceFilterCreated](#sourcefiltercreated)
|
||||||
- [SourceFilterRemoved](#sourcefilterremoved)
|
- [SourceFilterRemoved](#sourcefilterremoved)
|
||||||
- [SourceFilterListReindexed](#sourcefilterlistreindexed)
|
|
||||||
- [SourceFilterEnableStateChanged](#sourcefilterenablestatechanged)
|
|
||||||
- [SourceFilterNameChanged](#sourcefilternamechanged)
|
- [SourceFilterNameChanged](#sourcefilternamechanged)
|
||||||
|
- [SourceFilterEnableStateChanged](#sourcefilterenablestatechanged)
|
||||||
- [Scene Items](#scene-items)
|
- [Scene Items](#scene-items)
|
||||||
- [SceneItemCreated](#sceneitemcreated)
|
- [SceneItemCreated](#sceneitemcreated)
|
||||||
- [SceneItemRemoved](#sceneitemremoved)
|
- [SceneItemRemoved](#sceneitemremoved)
|
||||||
@ -1785,7 +1788,7 @@ A high-volume event providing volume levels of all active inputs every 50 millis
|
|||||||
|
|
||||||
The current scene transition has changed.
|
The current scene transition has changed.
|
||||||
|
|
||||||
- Complexity Rating: `3/5`
|
- Complexity Rating: `2/5`
|
||||||
- Latest Supported RPC Version: `1`
|
- Latest Supported RPC Version: `1`
|
||||||
- Added in v5.0.0
|
- Added in v5.0.0
|
||||||
|
|
||||||
@ -1812,8 +1815,84 @@ The current scene transition duration has changed.
|
|||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ----------- |
|
| ---- | :---: | ----------- |
|
||||||
| transitionDuration | Number | Transition duration in milliseconds |
|
| transitionDuration | Number | Transition duration in milliseconds |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SceneTransitionStarted
|
||||||
|
|
||||||
|
A scene transition has started.
|
||||||
|
|
||||||
|
- Complexity Rating: `2/5`
|
||||||
|
- Latest Supported RPC Version: `1`
|
||||||
|
- Added in v5.0.0
|
||||||
|
|
||||||
|
|
||||||
|
**Data Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ----------- |
|
||||||
|
| transitionName | String | Scene transition name |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SceneTransitionEnded
|
||||||
|
|
||||||
|
A scene transition has completed fully.
|
||||||
|
|
||||||
|
Note: Does not appear to trigger when the transition is interrupted by the user.
|
||||||
|
|
||||||
|
- Complexity Rating: `2/5`
|
||||||
|
- Latest Supported RPC Version: `1`
|
||||||
|
- Added in v5.0.0
|
||||||
|
|
||||||
|
|
||||||
|
**Data Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ----------- |
|
||||||
|
| transitionName | String | Scene transition name |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SceneTransitionVideoEnded
|
||||||
|
|
||||||
|
A scene transition's video has completed fully.
|
||||||
|
|
||||||
|
Useful for stinger transitions to tell when the video *actually* ends.
|
||||||
|
`SceneTransitionEnded` only signifies the cut point, not the completion of transition playback.
|
||||||
|
|
||||||
|
Note: Appears to be called by every transition, regardless of relevance.
|
||||||
|
|
||||||
|
- Complexity Rating: `2/5`
|
||||||
|
- Latest Supported RPC Version: `1`
|
||||||
|
- Added in v5.0.0
|
||||||
|
|
||||||
|
|
||||||
|
**Data Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ----------- |
|
||||||
|
| transitionName | String | Scene transition name |
|
||||||
## Filters
|
## Filters
|
||||||
|
|
||||||
|
### SourceFilterListReindexed
|
||||||
|
|
||||||
|
A source's filter list has been reindexed.
|
||||||
|
|
||||||
|
- Complexity Rating: `3/5`
|
||||||
|
- Latest Supported RPC Version: `1`
|
||||||
|
- Added in v5.0.0
|
||||||
|
|
||||||
|
|
||||||
|
**Data Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ----------- |
|
||||||
|
| sourceName | String | Name of the source |
|
||||||
|
| filters | Array<Object> | Array of filter objects |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### SourceFilterCreated
|
### SourceFilterCreated
|
||||||
|
|
||||||
A filter has been added to a source.
|
A filter has been added to a source.
|
||||||
@ -1854,11 +1933,11 @@ A filter has been removed from a source.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### SourceFilterListReindexed
|
### SourceFilterNameChanged
|
||||||
|
|
||||||
A source's filter list has been reindexed.
|
The name of a source filter has changed.
|
||||||
|
|
||||||
- Complexity Rating: `3/5`
|
- Complexity Rating: `2/5`
|
||||||
- Latest Supported RPC Version: `1`
|
- Latest Supported RPC Version: `1`
|
||||||
- Added in v5.0.0
|
- Added in v5.0.0
|
||||||
|
|
||||||
@ -1867,8 +1946,9 @@ A source's filter list has been reindexed.
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | :---: | ----------- |
|
| ---- | :---: | ----------- |
|
||||||
| sourceName | String | Name of the source |
|
| sourceName | String | The source the filter is on |
|
||||||
| filters | Array<Object> | Array of filter objects |
|
| oldFilterName | String | Old name of the filter |
|
||||||
|
| filterName | String | New name of the filter |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -1888,25 +1968,6 @@ A source filter's enable state has changed.
|
|||||||
| sourceName | String | Name of the source the filter is on |
|
| sourceName | String | Name of the source the filter is on |
|
||||||
| filterName | String | Name of the filter |
|
| filterName | String | Name of the filter |
|
||||||
| filterEnabled | Boolean | Whether the filter is enabled |
|
| filterEnabled | Boolean | Whether the filter is enabled |
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### SourceFilterNameChanged
|
|
||||||
|
|
||||||
The name of a source filter has changed.
|
|
||||||
|
|
||||||
- Complexity Rating: `2/5`
|
|
||||||
- Latest Supported RPC Version: `1`
|
|
||||||
- Added in v5.0.0
|
|
||||||
|
|
||||||
|
|
||||||
**Data Fields:**
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| ---- | :---: | ----------- |
|
|
||||||
| sourceName | String | The source the filter is on |
|
|
||||||
| oldFilterName | String | Old name of the filter |
|
|
||||||
| filterName | String | New name of the filter |
|
|
||||||
## Scene Items
|
## Scene Items
|
||||||
|
|
||||||
### SceneItemCreated
|
### SceneItemCreated
|
||||||
@ -2285,6 +2346,7 @@ Studio mode has been enabled or disabled.
|
|||||||
- [GetSourceFilter](#getsourcefilter)
|
- [GetSourceFilter](#getsourcefilter)
|
||||||
- [SetSourceFilterIndex](#setsourcefilterindex)
|
- [SetSourceFilterIndex](#setsourcefilterindex)
|
||||||
- [SetSourceFilterSettings](#setsourcefiltersettings)
|
- [SetSourceFilterSettings](#setsourcefiltersettings)
|
||||||
|
- [SetSourceFilterEnabled](#setsourcefilterenabled)
|
||||||
- [Scene Items](#scene-items-1)
|
- [Scene Items](#scene-items-1)
|
||||||
- [GetSceneItemList](#getsceneitemlist)
|
- [GetSceneItemList](#getsceneitemlist)
|
||||||
- [GetGroupItemList](#getgroupitemlist)
|
- [GetGroupItemList](#getgroupitemlist)
|
||||||
@ -2338,6 +2400,7 @@ Studio mode has been enabled or disabled.
|
|||||||
- [OpenInputPropertiesDialog](#openinputpropertiesdialog)
|
- [OpenInputPropertiesDialog](#openinputpropertiesdialog)
|
||||||
- [OpenInputFiltersDialog](#openinputfiltersdialog)
|
- [OpenInputFiltersDialog](#openinputfiltersdialog)
|
||||||
- [OpenInputInteractDialog](#openinputinteractdialog)
|
- [OpenInputInteractDialog](#openinputinteractdialog)
|
||||||
|
- [GetMonitorList](#getmonitorlist)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -2362,6 +2425,8 @@ Gets data about the current plugin and RPC version.
|
|||||||
| rpcVersion | Number | Current latest obs-websocket RPC version |
|
| rpcVersion | Number | Current latest obs-websocket RPC version |
|
||||||
| availableRequests | Array<String> | Array of available RPC requests for the currently negotiated RPC version |
|
| availableRequests | Array<String> | Array of available RPC requests for the currently negotiated RPC version |
|
||||||
| supportedImageFormats | Array<String> | Image formats available in `GetSourceScreenshot` and `SaveSourceScreenshot` requests. |
|
| supportedImageFormats | Array<String> | Image formats available in `GetSourceScreenshot` and `SaveSourceScreenshot` requests. |
|
||||||
|
| platform | String | Name of the platform. Usually `windows`, `macos`, or `ubuntu` (linux flavor). Not guaranteed to be any of those |
|
||||||
|
| platformDescription | String | Description of the platform, like `Windows 10 (10.0)` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -3988,6 +4053,25 @@ Sets the settings of a source filter.
|
|||||||
| filterSettings | Object | Object of settings to apply | None | N/A |
|
| filterSettings | Object | Object of settings to apply | None | N/A |
|
||||||
| ?overlay | Boolean | True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. | None | true |
|
| ?overlay | Boolean | True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. | None | true |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SetSourceFilterEnabled
|
||||||
|
|
||||||
|
Sets the enable state of a source filter.
|
||||||
|
|
||||||
|
- Complexity Rating: `3/5`
|
||||||
|
- Latest Supported RPC Version: `1`
|
||||||
|
- Added in v5.0.0
|
||||||
|
|
||||||
|
|
||||||
|
**Request Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description | Value Restrictions | ?Default Behavior |
|
||||||
|
| ---- | :---: | ----------- | :----------------: | ----------------- |
|
||||||
|
| sourceName | String | Name of the source the filter is on | None | N/A |
|
||||||
|
| filterName | String | Name of the filter | None | N/A |
|
||||||
|
| filterEnabled | Boolean | New enable state of the filter | None | N/A |
|
||||||
|
|
||||||
|
|
||||||
## Scene Items
|
## Scene Items
|
||||||
|
|
||||||
@ -4062,6 +4146,7 @@ Scenes and Groups
|
|||||||
| ---- | :---: | ----------- | :----------------: | ----------------- |
|
| ---- | :---: | ----------- | :----------------: | ----------------- |
|
||||||
| sceneName | String | Name of the scene or group to search in | None | N/A |
|
| sceneName | String | Name of the scene or group to search in | None | N/A |
|
||||||
| sourceName | String | Name of the source to find | None | N/A |
|
| sourceName | String | Name of the source to find | None | N/A |
|
||||||
|
| ?searchOffset | Number | Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item | >= -1 | 0 |
|
||||||
|
|
||||||
|
|
||||||
**Response Fields:**
|
**Response Fields:**
|
||||||
@ -4873,4 +4958,21 @@ Opens the interact dialog of an input.
|
|||||||
| ---- | :---: | ----------- | :----------------: | ----------------- |
|
| ---- | :---: | ----------- | :----------------: | ----------------- |
|
||||||
| inputName | String | Name of the input to open the dialog of | None | N/A |
|
| inputName | String | Name of the input to open the dialog of | None | N/A |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### GetMonitorList
|
||||||
|
|
||||||
|
Gets a list of connected monitors and information about them.
|
||||||
|
|
||||||
|
- Complexity Rating: `2/5`
|
||||||
|
- Latest Supported RPC Version: `1`
|
||||||
|
- Added in v5.0.0
|
||||||
|
|
||||||
|
|
||||||
|
**Response Fields:**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | :---: | ----------- |
|
||||||
|
| monitors | Array<Object> | a list of detected monitors with some information |
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
#define PARAM_PASSWORD "ServerPassword"
|
#define PARAM_PASSWORD "ServerPassword"
|
||||||
|
|
||||||
#define CMDLINE_WEBSOCKET_PORT "websocket_port"
|
#define CMDLINE_WEBSOCKET_PORT "websocket_port"
|
||||||
|
#define CMDLINE_WEBSOCKET_IPV4_ONLY "websocket_ipv4_only"
|
||||||
#define CMDLINE_WEBSOCKET_PASSWORD "websocket_password"
|
#define CMDLINE_WEBSOCKET_PASSWORD "websocket_password"
|
||||||
#define CMDLINE_WEBSOCKET_DEBUG "websocket_debug"
|
#define CMDLINE_WEBSOCKET_DEBUG "websocket_debug"
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ Config::Config() :
|
|||||||
FirstLoad(true),
|
FirstLoad(true),
|
||||||
ServerEnabled(true),
|
ServerEnabled(true),
|
||||||
ServerPort(4455),
|
ServerPort(4455),
|
||||||
|
Ipv4Only(false),
|
||||||
DebugEnabled(false),
|
DebugEnabled(false),
|
||||||
AlertsEnabled(false),
|
AlertsEnabled(false),
|
||||||
AuthRequired(true),
|
AuthRequired(true),
|
||||||
@ -93,6 +95,12 @@ void Config::Load()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process `--websocket_ipv4_only` override
|
||||||
|
if (Utils::Platform::GetCommandLineFlagSet(CMDLINE_WEBSOCKET_IPV4_ONLY)) {
|
||||||
|
blog(LOG_INFO, "[Config::Load] --websocket_ipv4_only passed. Binding only to IPv4 interfaces.");
|
||||||
|
Ipv4Only = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Process `--websocket_password` override
|
// Process `--websocket_password` override
|
||||||
QString passwordArgument = Utils::Platform::GetCommandLineArgument(CMDLINE_WEBSOCKET_PASSWORD);
|
QString passwordArgument = Utils::Platform::GetCommandLineArgument(CMDLINE_WEBSOCKET_PASSWORD);
|
||||||
if (passwordArgument != "") {
|
if (passwordArgument != "") {
|
||||||
|
@ -38,6 +38,7 @@ struct Config {
|
|||||||
std::atomic<bool> FirstLoad;
|
std::atomic<bool> FirstLoad;
|
||||||
std::atomic<bool> ServerEnabled;
|
std::atomic<bool> ServerEnabled;
|
||||||
std::atomic<uint16_t> ServerPort;
|
std::atomic<uint16_t> ServerPort;
|
||||||
|
std::atomic<bool> Ipv4Only;
|
||||||
std::atomic<bool> DebugEnabled;
|
std::atomic<bool> DebugEnabled;
|
||||||
std::atomic<bool> AlertsEnabled;
|
std::atomic<bool> AlertsEnabled;
|
||||||
std::atomic<bool> AuthRequired;
|
std::atomic<bool> AuthRequired;
|
||||||
|
@ -115,6 +115,7 @@ void EventHandler::BroadcastEvent(uint64_t requiredIntent, std::string eventType
|
|||||||
_broadcastCallback(requiredIntent, eventType, eventData, rpcVersion);
|
_broadcastCallback(requiredIntent, eventType, eventData, rpcVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Connect source signals for Inputs, Scenes, and Transitions. Filters are automatically connected.
|
||||||
void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inputs and scenes
|
void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inputs and scenes
|
||||||
{
|
{
|
||||||
if (!source || obs_source_removed(source))
|
if (!source || obs_source_removed(source))
|
||||||
@ -128,6 +129,7 @@ void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inpu
|
|||||||
obs_source_type sourceType = obs_source_get_type(source);
|
obs_source_type sourceType = obs_source_get_type(source);
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
|
if (sourceType == OBS_SOURCE_TYPE_INPUT) {
|
||||||
signal_handler_connect(sh, "activate", HandleInputActiveStateChanged, this);
|
signal_handler_connect(sh, "activate", HandleInputActiveStateChanged, this);
|
||||||
signal_handler_connect(sh, "deactivate", HandleInputActiveStateChanged, this);
|
signal_handler_connect(sh, "deactivate", HandleInputActiveStateChanged, this);
|
||||||
signal_handler_connect(sh, "show", HandleInputShowStateChanged, this);
|
signal_handler_connect(sh, "show", HandleInputShowStateChanged, this);
|
||||||
@ -138,11 +140,6 @@ void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inpu
|
|||||||
signal_handler_connect(sh, "audio_sync", HandleInputAudioSyncOffsetChanged, this);
|
signal_handler_connect(sh, "audio_sync", HandleInputAudioSyncOffsetChanged, this);
|
||||||
signal_handler_connect(sh, "audio_mixers", HandleInputAudioTracksChanged, this);
|
signal_handler_connect(sh, "audio_mixers", HandleInputAudioTracksChanged, this);
|
||||||
signal_handler_connect(sh, "audio_monitoring", HandleInputAudioMonitorTypeChanged, this);
|
signal_handler_connect(sh, "audio_monitoring", HandleInputAudioMonitorTypeChanged, this);
|
||||||
signal_handler_connect(sh, "filter_add", HandleSourceFilterCreated, this);
|
|
||||||
signal_handler_connect(sh, "filter_remove", HandleSourceFilterRemoved, this);
|
|
||||||
signal_handler_connect(sh, "reorder_filters", HandleSourceFilterListReindexed, this);
|
|
||||||
|
|
||||||
if (sourceType == OBS_SOURCE_TYPE_INPUT) {
|
|
||||||
signal_handler_connect(sh, "media_started", HandleMediaInputPlaybackStarted, this);
|
signal_handler_connect(sh, "media_started", HandleMediaInputPlaybackStarted, this);
|
||||||
signal_handler_connect(sh, "media_ended", HandleMediaInputPlaybackEnded, this);
|
signal_handler_connect(sh, "media_ended", HandleMediaInputPlaybackEnded, this);
|
||||||
signal_handler_connect(sh, "media_pause", SourceMediaPauseMultiHandler, this);
|
signal_handler_connect(sh, "media_pause", SourceMediaPauseMultiHandler, this);
|
||||||
@ -163,8 +160,34 @@ void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inpu
|
|||||||
signal_handler_connect(sh, "item_select", HandleSceneItemSelected, this);
|
signal_handler_connect(sh, "item_select", HandleSceneItemSelected, this);
|
||||||
signal_handler_connect(sh, "item_transform", HandleSceneItemTransformChanged, this);
|
signal_handler_connect(sh, "item_transform", HandleSceneItemTransformChanged, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scenes and Inputs
|
||||||
|
if (sourceType == OBS_SOURCE_TYPE_INPUT || sourceType == OBS_SOURCE_TYPE_SCENE) {
|
||||||
|
signal_handler_connect(sh, "reorder_filters", HandleSourceFilterListReindexed, this);
|
||||||
|
signal_handler_connect(sh, "filter_add", FilterAddMultiHandler, this);
|
||||||
|
signal_handler_connect(sh, "filter_remove", FilterRemoveMultiHandler, this);
|
||||||
|
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){
|
||||||
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
|
eventHandler->ConnectSourceSignals(filter);
|
||||||
|
};
|
||||||
|
obs_source_enum_filters(source, enumFilters, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transitions
|
||||||
|
if (sourceType == OBS_SOURCE_TYPE_TRANSITION) {
|
||||||
|
signal_handler_connect(sh, "transition_start", HandleSceneTransitionStarted, this);
|
||||||
|
signal_handler_connect(sh, "transition_stop", HandleSceneTransitionEnded, this);
|
||||||
|
signal_handler_connect(sh, "transition_video_stop", HandleSceneTransitionVideoEnded, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filters
|
||||||
|
if (sourceType == OBS_SOURCE_TYPE_FILTER) {
|
||||||
|
signal_handler_connect(sh, "enable", HandleSourceFilterEnableStateChanged, this);
|
||||||
|
signal_handler_connect(sh, "rename", HandleSourceFilterNameChanged, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disconnect source signals for Inputs, Scenes, and Transitions. Filters are automatically disconnected.
|
||||||
void EventHandler::DisconnectSourceSignals(obs_source_t *source)
|
void EventHandler::DisconnectSourceSignals(obs_source_t *source)
|
||||||
{
|
{
|
||||||
if (!source)
|
if (!source)
|
||||||
@ -172,7 +195,10 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *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);
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
|
if (sourceType == OBS_SOURCE_TYPE_INPUT) {
|
||||||
signal_handler_disconnect(sh, "activate", HandleInputActiveStateChanged, this);
|
signal_handler_disconnect(sh, "activate", HandleInputActiveStateChanged, this);
|
||||||
signal_handler_disconnect(sh, "deactivate", HandleInputActiveStateChanged, this);
|
signal_handler_disconnect(sh, "deactivate", HandleInputActiveStateChanged, this);
|
||||||
signal_handler_disconnect(sh, "show", HandleInputShowStateChanged, this);
|
signal_handler_disconnect(sh, "show", HandleInputShowStateChanged, this);
|
||||||
@ -191,11 +217,10 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *source)
|
|||||||
signal_handler_disconnect(sh, "media_stopped", SourceMediaStopMultiHandler, this);
|
signal_handler_disconnect(sh, "media_stopped", SourceMediaStopMultiHandler, this);
|
||||||
signal_handler_disconnect(sh, "media_next", SourceMediaNextMultiHandler, this);
|
signal_handler_disconnect(sh, "media_next", SourceMediaNextMultiHandler, this);
|
||||||
signal_handler_disconnect(sh, "media_previous", SourceMediaPreviousMultiHandler, this);
|
signal_handler_disconnect(sh, "media_previous", SourceMediaPreviousMultiHandler, this);
|
||||||
signal_handler_disconnect(sh, "filter_add", HandleSourceFilterCreated, this);
|
}
|
||||||
signal_handler_disconnect(sh, "filter_remove", HandleSourceFilterRemoved, this);
|
|
||||||
signal_handler_disconnect(sh, "reorder_filters", HandleSourceFilterListReindexed, this);
|
|
||||||
|
|
||||||
// Scenes
|
// Scenes
|
||||||
|
if (sourceType == OBS_SOURCE_TYPE_SCENE) {
|
||||||
signal_handler_disconnect(sh, "item_add", HandleSceneItemCreated, this);
|
signal_handler_disconnect(sh, "item_add", HandleSceneItemCreated, this);
|
||||||
signal_handler_disconnect(sh, "item_remove", HandleSceneItemRemoved, this);
|
signal_handler_disconnect(sh, "item_remove", HandleSceneItemRemoved, this);
|
||||||
signal_handler_disconnect(sh, "reorder", HandleSceneItemListReindexed, this);
|
signal_handler_disconnect(sh, "reorder", HandleSceneItemListReindexed, this);
|
||||||
@ -205,37 +230,44 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *source)
|
|||||||
signal_handler_disconnect(sh, "item_transform", HandleSceneItemTransformChanged, this);
|
signal_handler_disconnect(sh, "item_transform", HandleSceneItemTransformChanged, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::ConnectFilterSignals(obs_source_t *filter)
|
// Inputs and Scenes
|
||||||
{
|
if (sourceType == OBS_SOURCE_TYPE_INPUT || sourceType == OBS_SOURCE_TYPE_SCENE) {
|
||||||
if (!filter || obs_source_removed(filter))
|
signal_handler_disconnect(sh, "reorder_filters", HandleSourceFilterListReindexed, this);
|
||||||
return;
|
signal_handler_disconnect(sh, "filter_add", FilterAddMultiHandler, this);
|
||||||
|
signal_handler_disconnect(sh, "filter_remove", FilterRemoveMultiHandler, this);
|
||||||
DisconnectFilterSignals(filter);
|
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){
|
||||||
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
signal_handler_t* sh = obs_source_get_signal_handler(filter);
|
eventHandler->DisconnectSourceSignals(filter);
|
||||||
|
};
|
||||||
signal_handler_connect(sh, "enable", HandleSourceFilterEnableStateChanged, this);
|
obs_source_enum_filters(source, enumFilters, this);
|
||||||
signal_handler_connect(sh, "rename", HandleSourceFilterNameChanged, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::DisconnectFilterSignals(obs_source_t *filter)
|
// Transitions
|
||||||
{
|
if (sourceType == OBS_SOURCE_TYPE_TRANSITION) {
|
||||||
if (!filter)
|
signal_handler_disconnect(sh, "transition_start", HandleSceneTransitionStarted, this);
|
||||||
return;
|
signal_handler_disconnect(sh, "transition_stop", HandleSceneTransitionEnded, this);
|
||||||
|
signal_handler_disconnect(sh, "transition_video_stop", HandleSceneTransitionVideoEnded, this);
|
||||||
signal_handler_t* sh = obs_source_get_signal_handler(filter);
|
}
|
||||||
|
|
||||||
|
// Filters
|
||||||
|
if (sourceType == OBS_SOURCE_TYPE_FILTER) {
|
||||||
signal_handler_disconnect(sh, "enable", HandleSourceFilterEnableStateChanged, this);
|
signal_handler_disconnect(sh, "enable", HandleSourceFilterEnableStateChanged, this);
|
||||||
signal_handler_disconnect(sh, "rename", HandleSourceFilterNameChanged, this);
|
signal_handler_disconnect(sh, "rename", HandleSourceFilterNameChanged, this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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()) {
|
if (!eventHandler->_obsLoaded.load() && event != OBS_FRONTEND_EVENT_FINISHED_LOADING)
|
||||||
if (event == OBS_FRONTEND_EVENT_FINISHED_LOADING) {
|
return;
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
// General
|
||||||
|
case OBS_FRONTEND_EVENT_FINISHED_LOADING:
|
||||||
blog_debug("[EventHandler::OnFrontendEvent] OBS has finished loading. Connecting final handlers and enabling events...");
|
blog_debug("[EventHandler::OnFrontendEvent] OBS has finished loading. Connecting final handlers and enabling events...");
|
||||||
|
|
||||||
// Connect source signals and enable events only after OBS has fully loaded (to reduce extra logging).
|
// Connect source signals and enable events only after OBS has fully loaded (to reduce extra logging).
|
||||||
eventHandler->_obsLoaded.store(true);
|
eventHandler->_obsLoaded.store(true);
|
||||||
|
|
||||||
@ -245,13 +277,6 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
|
|||||||
auto enumInputs = [](void *param, obs_source_t *source) {
|
auto enumInputs = [](void *param, obs_source_t *source) {
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
eventHandler->ConnectSourceSignals(source);
|
eventHandler->ConnectSourceSignals(source);
|
||||||
|
|
||||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){
|
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
|
||||||
eventHandler->ConnectFilterSignals(filter);
|
|
||||||
};
|
|
||||||
obs_source_enum_filters(source, enumFilters, param);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
obs_enum_sources(enumInputs, private_data);
|
obs_enum_sources(enumInputs, private_data);
|
||||||
@ -262,29 +287,28 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
|
|||||||
auto enumScenes = [](void *param, obs_source_t *source) {
|
auto enumScenes = [](void *param, obs_source_t *source) {
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
eventHandler->ConnectSourceSignals(source);
|
eventHandler->ConnectSourceSignals(source);
|
||||||
|
|
||||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){
|
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
|
||||||
eventHandler->ConnectFilterSignals(filter);
|
|
||||||
};
|
|
||||||
obs_source_enum_filters(source, enumFilters, param);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
obs_enum_scenes(enumScenes, private_data);
|
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.");
|
blog_debug("[EventHandler::OnFrontendEvent] Finished.");
|
||||||
|
|
||||||
if (eventHandler->_obsLoadedCallback)
|
if (eventHandler->_obsLoadedCallback)
|
||||||
eventHandler->_obsLoadedCallback();
|
eventHandler->_obsLoadedCallback();
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event) {
|
break;
|
||||||
// General
|
|
||||||
case OBS_FRONTEND_EVENT_EXIT:
|
case OBS_FRONTEND_EVENT_EXIT:
|
||||||
eventHandler->HandleExitStarted();
|
eventHandler->HandleExitStarted();
|
||||||
|
|
||||||
@ -298,13 +322,6 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
|
|||||||
auto enumInputs = [](void *param, obs_source_t *source) {
|
auto enumInputs = [](void *param, obs_source_t *source) {
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
eventHandler->DisconnectSourceSignals(source);
|
eventHandler->DisconnectSourceSignals(source);
|
||||||
|
|
||||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){
|
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
|
||||||
eventHandler->ConnectFilterSignals(filter);
|
|
||||||
};
|
|
||||||
obs_source_enum_filters(source, enumFilters, param);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
obs_enum_sources(enumInputs, private_data);
|
obs_enum_sources(enumInputs, private_data);
|
||||||
@ -315,18 +332,22 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
|
|||||||
auto enumScenes = [](void *param, obs_source_t *source) {
|
auto enumScenes = [](void *param, obs_source_t *source) {
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
eventHandler->DisconnectSourceSignals(source);
|
eventHandler->DisconnectSourceSignals(source);
|
||||||
|
|
||||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){
|
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
|
||||||
eventHandler->ConnectFilterSignals(filter);
|
|
||||||
};
|
|
||||||
obs_source_enum_filters(source, enumFilters, param);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
obs_enum_scenes(enumScenes, private_data);
|
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.");
|
blog_debug("[EventHandler::OnFrontendEvent] Finished.");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -339,9 +360,27 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
|
|||||||
|
|
||||||
// Config
|
// Config
|
||||||
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING:
|
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();
|
eventHandler->HandleCurrentSceneCollectionChanging();
|
||||||
break;
|
break;
|
||||||
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED:
|
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();
|
eventHandler->HandleCurrentSceneCollectionChanged();
|
||||||
break;
|
break;
|
||||||
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED:
|
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED:
|
||||||
@ -373,6 +412,15 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
|
|||||||
eventHandler->HandleCurrentSceneTransitionChanged();
|
eventHandler->HandleCurrentSceneTransitionChanged();
|
||||||
break;
|
break;
|
||||||
case OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED:
|
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;
|
break;
|
||||||
case OBS_FRONTEND_EVENT_TRANSITION_DURATION_CHANGED:
|
case OBS_FRONTEND_EVENT_TRANSITION_DURATION_CHANGED:
|
||||||
eventHandler->HandleCurrentSceneTransitionDurationChanged();
|
eventHandler->HandleCurrentSceneTransitionDurationChanged();
|
||||||
@ -463,7 +511,8 @@ void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only called for destruction of a public source
|
// Only called for destruction of a public sourcs
|
||||||
|
// 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);
|
||||||
@ -482,16 +531,22 @@ void EventHandler::SourceDestroyedMultiHandler(void *param, calldata_t *data)
|
|||||||
|
|
||||||
switch (obs_source_get_type(source)) {
|
switch (obs_source_get_type(source)) {
|
||||||
case OBS_SOURCE_TYPE_INPUT:
|
case OBS_SOURCE_TYPE_INPUT:
|
||||||
// We have to call `InputRemoved` with source_destroy because source_removed is not called when an input's last scene item is removed
|
// 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))
|
||||||
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.
|
||||||
|
if (!obs_source_removed(source))
|
||||||
|
eventHandler->HandleSceneRemoved(source);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We prefer remove signals over destroy signals because they are more time-accurate.
|
||||||
|
// 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);
|
||||||
@ -505,9 +560,9 @@ void EventHandler::SourceRemovedMultiHandler(void *param, calldata_t *data)
|
|||||||
|
|
||||||
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);
|
||||||
break;
|
break;
|
||||||
case OBS_SOURCE_TYPE_SCENE:
|
case OBS_SOURCE_TYPE_SCENE:
|
||||||
// Scenes emit the `removed` signal when they are removed from OBS, as expected
|
|
||||||
eventHandler->HandleSceneRemoved(source);
|
eventHandler->HandleSceneRemoved(source);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -58,9 +58,6 @@ class EventHandler
|
|||||||
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 ConnectFilterSignals(obs_source_t *filter);
|
|
||||||
void DisconnectFilterSignals(obs_source_t *filter);
|
|
||||||
|
|
||||||
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
|
||||||
@ -118,6 +115,18 @@ class EventHandler
|
|||||||
// Transitions
|
// Transitions
|
||||||
void HandleCurrentSceneTransitionChanged();
|
void HandleCurrentSceneTransitionChanged();
|
||||||
void HandleCurrentSceneTransitionDurationChanged();
|
void HandleCurrentSceneTransitionDurationChanged();
|
||||||
|
static void HandleSceneTransitionStarted(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
|
||||||
|
static void FilterAddMultiHandler(void *param, calldata_t *data); // Direct callback
|
||||||
|
static void FilterRemoveMultiHandler(void *param, calldata_t *data); // Direct callback
|
||||||
|
static void HandleSourceFilterListReindexed(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
|
||||||
|
static void HandleSourceFilterEnableStateChanged(void *param, calldata_t *data); // Direct callback
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
void HandleStreamStateChanged(ObsOutputState state);
|
void HandleStreamStateChanged(ObsOutputState state);
|
||||||
@ -139,11 +148,4 @@ class EventHandler
|
|||||||
static void HandleMediaInputPlaybackStarted(void *param, calldata_t *data); // Direct callback
|
static void HandleMediaInputPlaybackStarted(void *param, calldata_t *data); // Direct callback
|
||||||
static void HandleMediaInputPlaybackEnded(void *param, calldata_t *data); // Direct callback
|
static void HandleMediaInputPlaybackEnded(void *param, calldata_t *data); // Direct callback
|
||||||
void HandleMediaInputActionTriggered(obs_source_t *source, ObsMediaInputAction action);
|
void HandleMediaInputActionTriggered(obs_source_t *source, ObsMediaInputAction action);
|
||||||
|
|
||||||
// Filters
|
|
||||||
static void HandleSourceFilterNameChanged(void *param, calldata_t *data); // Direct callback
|
|
||||||
static void HandleSourceFilterCreated(void *param, calldata_t *data); // Direct callback
|
|
||||||
static void HandleSourceFilterRemoved(void *param, calldata_t *data); // Direct callback
|
|
||||||
static void HandleSourceFilterListReindexed(void *param, calldata_t *data); // Direct callback
|
|
||||||
static void HandleSourceFilterEnableStateChanged(void *param, calldata_t *data); // Direct callback
|
|
||||||
};
|
};
|
||||||
|
@ -19,25 +19,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
|
|
||||||
/**
|
void EventHandler::FilterAddMultiHandler(void *param, calldata_t *data)
|
||||||
* A filter has been added to a source.
|
|
||||||
*
|
|
||||||
* @dataField sourceName | String | Name of the source the filter was added to
|
|
||||||
* @dataField filterName | String | Name of the filter
|
|
||||||
* @dataField filterKind | String | The kind of the filter
|
|
||||||
* @dataField filterIndex | Number | Index position of the filter
|
|
||||||
* @dataField filterSettings | Object | The settings configured to the filter when it was created
|
|
||||||
* @dataField defaultFilterSettings | Object | The default settings for the filter
|
|
||||||
*
|
|
||||||
* @eventType SourceFilterCreated
|
|
||||||
* @eventSubscription Filters
|
|
||||||
* @complexity 2
|
|
||||||
* @rpcVersion -1
|
|
||||||
* @initialVersion 5.0.0
|
|
||||||
* @api events
|
|
||||||
* @category filters
|
|
||||||
*/
|
|
||||||
void EventHandler::HandleSourceFilterCreated(void *param, calldata_t *data)
|
|
||||||
{
|
{
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
|
|
||||||
@ -47,37 +29,12 @@ void EventHandler::HandleSourceFilterCreated(void *param, calldata_t *data)
|
|||||||
if (!(source && filter))
|
if (!(source && filter))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
eventHandler->ConnectFilterSignals(filter);
|
eventHandler->ConnectSourceSignals(filter);
|
||||||
|
|
||||||
std::string filterKind = obs_source_get_id(filter);
|
eventHandler->HandleSourceFilterCreated(source, filter);
|
||||||
OBSDataAutoRelease filterSettings = obs_source_get_settings(filter);
|
|
||||||
OBSDataAutoRelease defaultFilterSettings = obs_get_source_defaults(filterKind.c_str());
|
|
||||||
|
|
||||||
json eventData;
|
|
||||||
eventData["sourceName"] = obs_source_get_name(source);
|
|
||||||
eventData["filterName"] = obs_source_get_name(filter);
|
|
||||||
eventData["filterKind"] = filterKind;
|
|
||||||
eventData["filterIndex"] = Utils::Obs::NumberHelper::GetSourceFilterIndex(source, filter);
|
|
||||||
eventData["filterSettings"] = Utils::Json::ObsDataToJson(filterSettings);
|
|
||||||
eventData["defaultFilterSettings"] = Utils::Json::ObsDataToJson(defaultFilterSettings, true);
|
|
||||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterCreated", eventData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void EventHandler::FilterRemoveMultiHandler(void *param, calldata_t *data)
|
||||||
* A filter has been removed from a source.
|
|
||||||
*
|
|
||||||
* @dataField sourceName | String | Name of the source the filter was on
|
|
||||||
* @dataField filterName | String | Name of the filter
|
|
||||||
*
|
|
||||||
* @eventType SourceFilterRemoved
|
|
||||||
* @eventSubscription Filters
|
|
||||||
* @complexity 2
|
|
||||||
* @rpcVersion -1
|
|
||||||
* @initialVersion 5.0.0
|
|
||||||
* @api events
|
|
||||||
* @category filters
|
|
||||||
*/
|
|
||||||
void EventHandler::HandleSourceFilterRemoved(void *param, calldata_t *data)
|
|
||||||
{
|
{
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
|
|
||||||
@ -87,12 +44,9 @@ void EventHandler::HandleSourceFilterRemoved(void *param, calldata_t *data)
|
|||||||
if (!(source && filter))
|
if (!(source && filter))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
eventHandler->DisconnectFilterSignals(filter);
|
eventHandler->DisconnectSourceSignals(filter);
|
||||||
|
|
||||||
json eventData;
|
eventHandler->HandleSourceFilterRemoved(source, filter);
|
||||||
eventData["sourceName"] = obs_source_get_name(source);
|
|
||||||
eventData["filterName"] = obs_source_get_name(filter);
|
|
||||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterRemoved", eventData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,6 +77,92 @@ void EventHandler::HandleSourceFilterListReindexed(void *param, calldata_t *data
|
|||||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterListReindexed", eventData);
|
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterListReindexed", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A filter has been added to a source.
|
||||||
|
*
|
||||||
|
* @dataField sourceName | String | Name of the source the filter was added to
|
||||||
|
* @dataField filterName | String | Name of the filter
|
||||||
|
* @dataField filterKind | String | The kind of the filter
|
||||||
|
* @dataField filterIndex | Number | Index position of the filter
|
||||||
|
* @dataField filterSettings | Object | The settings configured to the filter when it was created
|
||||||
|
* @dataField defaultFilterSettings | Object | The default settings for the filter
|
||||||
|
*
|
||||||
|
* @eventType SourceFilterCreated
|
||||||
|
* @eventSubscription Filters
|
||||||
|
* @complexity 2
|
||||||
|
* @rpcVersion -1
|
||||||
|
* @initialVersion 5.0.0
|
||||||
|
* @api events
|
||||||
|
* @category filters
|
||||||
|
*/
|
||||||
|
void EventHandler::HandleSourceFilterCreated(obs_source_t *source, obs_source_t *filter)
|
||||||
|
{
|
||||||
|
std::string filterKind = obs_source_get_id(filter);
|
||||||
|
OBSDataAutoRelease filterSettings = obs_source_get_settings(filter);
|
||||||
|
OBSDataAutoRelease defaultFilterSettings = obs_get_source_defaults(filterKind.c_str());
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["sourceName"] = obs_source_get_name(source);
|
||||||
|
eventData["filterName"] = obs_source_get_name(filter);
|
||||||
|
eventData["filterKind"] = filterKind;
|
||||||
|
eventData["filterIndex"] = Utils::Obs::NumberHelper::GetSourceFilterIndex(source, filter);
|
||||||
|
eventData["filterSettings"] = Utils::Json::ObsDataToJson(filterSettings);
|
||||||
|
eventData["defaultFilterSettings"] = Utils::Json::ObsDataToJson(defaultFilterSettings, true);
|
||||||
|
BroadcastEvent(EventSubscription::Filters, "SourceFilterCreated", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A filter has been removed from a source.
|
||||||
|
*
|
||||||
|
* @dataField sourceName | String | Name of the source the filter was on
|
||||||
|
* @dataField filterName | String | Name of the filter
|
||||||
|
*
|
||||||
|
* @eventType SourceFilterRemoved
|
||||||
|
* @eventSubscription Filters
|
||||||
|
* @complexity 2
|
||||||
|
* @rpcVersion -1
|
||||||
|
* @initialVersion 5.0.0
|
||||||
|
* @api events
|
||||||
|
* @category filters
|
||||||
|
*/
|
||||||
|
void EventHandler::HandleSourceFilterRemoved(obs_source_t *source, obs_source_t *filter)
|
||||||
|
{
|
||||||
|
json eventData;
|
||||||
|
eventData["sourceName"] = obs_source_get_name(source);
|
||||||
|
eventData["filterName"] = obs_source_get_name(filter);
|
||||||
|
BroadcastEvent(EventSubscription::Filters, "SourceFilterRemoved", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of a source filter has changed.
|
||||||
|
*
|
||||||
|
* @dataField sourceName | String | The source the filter is on
|
||||||
|
* @dataField oldFilterName | String | Old name of the filter
|
||||||
|
* @dataField filterName | String | New name of the filter
|
||||||
|
*
|
||||||
|
* @eventType SourceFilterNameChanged
|
||||||
|
* @eventSubscription Filters
|
||||||
|
* @complexity 2
|
||||||
|
* @rpcVersion -1
|
||||||
|
* @initialVersion 5.0.0
|
||||||
|
* @api events
|
||||||
|
* @category filters
|
||||||
|
*/
|
||||||
|
void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!filter)
|
||||||
|
return;
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["sourceName"] = obs_source_get_name(obs_filter_get_parent(filter));
|
||||||
|
eventData["oldFilterName"] = calldata_string(data, "prev_name");
|
||||||
|
eventData["filterName"] = calldata_string(data, "new_name");
|
||||||
|
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterNameChanged", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A source filter's enable state has changed.
|
* A source filter's enable state has changed.
|
||||||
*
|
*
|
||||||
@ -159,33 +199,3 @@ void EventHandler::HandleSourceFilterEnableStateChanged(void *param, calldata_t
|
|||||||
eventData["filterEnabled"] = filterEnabled;
|
eventData["filterEnabled"] = filterEnabled;
|
||||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterEnableStateChanged", eventData);
|
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterEnableStateChanged", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of a source filter has changed.
|
|
||||||
*
|
|
||||||
* @dataField sourceName | String | The source the filter is on
|
|
||||||
* @dataField oldFilterName | String | Old name of the filter
|
|
||||||
* @dataField filterName | String | New name of the filter
|
|
||||||
*
|
|
||||||
* @eventType SourceFilterNameChanged
|
|
||||||
* @eventSubscription Filters
|
|
||||||
* @complexity 2
|
|
||||||
* @rpcVersion -1
|
|
||||||
* @initialVersion 5.0.0
|
|
||||||
* @api events
|
|
||||||
* @category filters
|
|
||||||
*/
|
|
||||||
void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data)
|
|
||||||
{
|
|
||||||
auto eventHandler = static_cast<EventHandler*>(param);
|
|
||||||
|
|
||||||
obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "source");
|
|
||||||
if (!filter)
|
|
||||||
return;
|
|
||||||
|
|
||||||
json eventData;
|
|
||||||
eventData["sourceName"] = obs_source_get_name(obs_filter_get_parent(filter));
|
|
||||||
eventData["oldFilterName"] = calldata_string(data, "prev_name");
|
|
||||||
eventData["filterName"] = calldata_string(data, "new_name");
|
|
||||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterNameChanged", eventData);
|
|
||||||
}
|
|
||||||
|
@ -26,7 +26,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
*
|
*
|
||||||
* @eventType CurrentSceneTransitionChanged
|
* @eventType CurrentSceneTransitionChanged
|
||||||
* @eventSubscription Transitions
|
* @eventSubscription Transitions
|
||||||
* @complexity 3
|
* @complexity 2
|
||||||
* @rpcVersion -1
|
* @rpcVersion -1
|
||||||
* @initialVersion 5.0.0
|
* @initialVersion 5.0.0
|
||||||
* @api events
|
* @api events
|
||||||
@ -60,3 +60,88 @@ void EventHandler::HandleCurrentSceneTransitionDurationChanged()
|
|||||||
eventData["transitionDuration"] = obs_frontend_get_transition_duration();
|
eventData["transitionDuration"] = obs_frontend_get_transition_duration();
|
||||||
BroadcastEvent(EventSubscription::Transitions, "CurrentSceneTransitionDurationChanged", eventData);
|
BroadcastEvent(EventSubscription::Transitions, "CurrentSceneTransitionDurationChanged", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A scene transition has started.
|
||||||
|
*
|
||||||
|
* @dataField transitionName | String | Scene transition name
|
||||||
|
*
|
||||||
|
* @eventType SceneTransitionStarted
|
||||||
|
* @eventSubscription Transitions
|
||||||
|
* @complexity 2
|
||||||
|
* @rpcVersion -1
|
||||||
|
* @initialVersion 5.0.0
|
||||||
|
* @api events
|
||||||
|
* @category transitions
|
||||||
|
*/
|
||||||
|
void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["transitionName"] = obs_source_get_name(source);
|
||||||
|
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionStarted", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A scene transition has completed fully.
|
||||||
|
*
|
||||||
|
* Note: Does not appear to trigger when the transition is interrupted by the user.
|
||||||
|
*
|
||||||
|
* @dataField transitionName | String | Scene transition name
|
||||||
|
*
|
||||||
|
* @eventType SceneTransitionEnded
|
||||||
|
* @eventSubscription Transitions
|
||||||
|
* @complexity 2
|
||||||
|
* @rpcVersion -1
|
||||||
|
* @initialVersion 5.0.0
|
||||||
|
* @api events
|
||||||
|
* @category transitions
|
||||||
|
*/
|
||||||
|
void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["transitionName"] = obs_source_get_name(source);
|
||||||
|
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionEnded", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A scene transition's video has completed fully.
|
||||||
|
*
|
||||||
|
* Useful for stinger transitions to tell when the video *actually* ends.
|
||||||
|
* `SceneTransitionEnded` only signifies the cut point, not the completion of transition playback.
|
||||||
|
*
|
||||||
|
* Note: Appears to be called by every transition, regardless of relevance.
|
||||||
|
*
|
||||||
|
* @dataField transitionName | String | Scene transition name
|
||||||
|
*
|
||||||
|
* @eventType SceneTransitionVideoEnded
|
||||||
|
* @eventSubscription Transitions
|
||||||
|
* @complexity 2
|
||||||
|
* @rpcVersion -1
|
||||||
|
* @initialVersion 5.0.0
|
||||||
|
* @api events
|
||||||
|
* @category transitions
|
||||||
|
*/
|
||||||
|
void EventHandler::HandleSceneTransitionVideoEnded(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = static_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["transitionName"] = obs_source_get_name(source);
|
||||||
|
eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionVideoEnded", eventData);
|
||||||
|
}
|
||||||
|
@ -138,6 +138,8 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
|
|||||||
{"SetSceneItemIndex", &RequestHandler::SetSceneItemIndex},
|
{"SetSceneItemIndex", &RequestHandler::SetSceneItemIndex},
|
||||||
{"GetSceneItemBlendMode", &RequestHandler::GetSceneItemBlendMode},
|
{"GetSceneItemBlendMode", &RequestHandler::GetSceneItemBlendMode},
|
||||||
{"SetSceneItemBlendMode", &RequestHandler::SetSceneItemBlendMode},
|
{"SetSceneItemBlendMode", &RequestHandler::SetSceneItemBlendMode},
|
||||||
|
{"GetSceneItemPrivateSettings", &RequestHandler::GetSceneItemPrivateSettings},
|
||||||
|
{"SetSceneItemPrivateSettings", &RequestHandler::SetSceneItemPrivateSettings},
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
{"GetVirtualCamStatus", &RequestHandler::GetVirtualCamStatus},
|
{"GetVirtualCamStatus", &RequestHandler::GetVirtualCamStatus},
|
||||||
@ -179,6 +181,7 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
|
|||||||
{"OpenInputPropertiesDialog", &RequestHandler::OpenInputPropertiesDialog},
|
{"OpenInputPropertiesDialog", &RequestHandler::OpenInputPropertiesDialog},
|
||||||
{"OpenInputFiltersDialog", &RequestHandler::OpenInputFiltersDialog},
|
{"OpenInputFiltersDialog", &RequestHandler::OpenInputFiltersDialog},
|
||||||
{"OpenInputInteractDialog", &RequestHandler::OpenInputInteractDialog},
|
{"OpenInputInteractDialog", &RequestHandler::OpenInputInteractDialog},
|
||||||
|
{"GetMonitorList", &RequestHandler::GetMonitorList},
|
||||||
};
|
};
|
||||||
|
|
||||||
RequestHandler::RequestHandler(SessionPtr session) :
|
RequestHandler::RequestHandler(SessionPtr session) :
|
||||||
|
@ -156,6 +156,8 @@ class RequestHandler {
|
|||||||
RequestResult SetSceneItemIndex(const Request&);
|
RequestResult SetSceneItemIndex(const Request&);
|
||||||
RequestResult GetSceneItemBlendMode(const Request&);
|
RequestResult GetSceneItemBlendMode(const Request&);
|
||||||
RequestResult SetSceneItemBlendMode(const Request&);
|
RequestResult SetSceneItemBlendMode(const Request&);
|
||||||
|
RequestResult GetSceneItemPrivateSettings(const Request&);
|
||||||
|
RequestResult SetSceneItemPrivateSettings(const Request&);
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
RequestResult GetVirtualCamStatus(const Request&);
|
RequestResult GetVirtualCamStatus(const Request&);
|
||||||
@ -197,6 +199,7 @@ class RequestHandler {
|
|||||||
RequestResult OpenInputPropertiesDialog(const Request&);
|
RequestResult OpenInputPropertiesDialog(const Request&);
|
||||||
RequestResult OpenInputFiltersDialog(const Request&);
|
RequestResult OpenInputFiltersDialog(const Request&);
|
||||||
RequestResult OpenInputInteractDialog(const Request&);
|
RequestResult OpenInputInteractDialog(const Request&);
|
||||||
|
RequestResult GetMonitorList(const Request&);
|
||||||
|
|
||||||
SessionPtr _session;
|
SessionPtr _session;
|
||||||
static const std::unordered_map<std::string, RequestMethodHandler> _handlerMap;
|
static const std::unordered_map<std::string, RequestMethodHandler> _handlerMap;
|
||||||
|
@ -18,6 +18,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QImageWriter>
|
#include <QImageWriter>
|
||||||
|
#include <QSysInfo>
|
||||||
|
|
||||||
#include "RequestHandler.h"
|
#include "RequestHandler.h"
|
||||||
#include "../websocketserver/WebSocketServer.h"
|
#include "../websocketserver/WebSocketServer.h"
|
||||||
@ -34,6 +35,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
* @responseField rpcVersion | Number | Current latest obs-websocket RPC version
|
* @responseField rpcVersion | Number | Current latest obs-websocket RPC version
|
||||||
* @responseField availableRequests | Array<String> | Array of available RPC requests for the currently negotiated RPC version
|
* @responseField availableRequests | Array<String> | Array of available RPC requests for the currently negotiated RPC version
|
||||||
* @responseField supportedImageFormats | Array<String> | Image formats available in `GetSourceScreenshot` and `SaveSourceScreenshot` requests.
|
* @responseField supportedImageFormats | Array<String> | Image formats available in `GetSourceScreenshot` and `SaveSourceScreenshot` requests.
|
||||||
|
* @responseField platform | String | Name of the platform. Usually `windows`, `macos`, or `ubuntu` (linux flavor). Not guaranteed to be any of those
|
||||||
|
* @responseField platformDescription | String | Description of the platform, like `Windows 10 (10.0)`
|
||||||
*
|
*
|
||||||
* @requestType GetVersion
|
* @requestType GetVersion
|
||||||
* @complexity 1
|
* @complexity 1
|
||||||
@ -57,6 +60,9 @@ RequestResult RequestHandler::GetVersion(const Request&)
|
|||||||
}
|
}
|
||||||
responseData["supportedImageFormats"] = supportedImageFormats;
|
responseData["supportedImageFormats"] = supportedImageFormats;
|
||||||
|
|
||||||
|
responseData["platform"] = QSysInfo::productType().toStdString();
|
||||||
|
responseData["platformDescription"] = QSysInfo::prettyProductName().toStdString();
|
||||||
|
|
||||||
return RequestResult::Success(responseData);
|
return RequestResult::Success(responseData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ RequestResult RequestHandler::GetGroupSceneItemList(const Request& request)
|
|||||||
*
|
*
|
||||||
* @requestField sceneName | String | Name of the scene or group to search in
|
* @requestField sceneName | String | Name of the scene or group to search in
|
||||||
* @requestField sourceName | String | Name of the source to find
|
* @requestField sourceName | String | Name of the source to find
|
||||||
|
* @requestField ?searchOffset | Number | Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item | >= -1 | 0
|
||||||
*
|
*
|
||||||
* @responseField sceneItemId | Number | Numeric ID of the scene item
|
* @responseField sceneItemId | Number | Numeric ID of the scene item
|
||||||
*
|
*
|
||||||
@ -108,9 +109,16 @@ RequestResult RequestHandler::GetSceneItemId(const Request& request)
|
|||||||
|
|
||||||
std::string sourceName = request.RequestData["sourceName"];
|
std::string sourceName = request.RequestData["sourceName"];
|
||||||
|
|
||||||
OBSSceneItemAutoRelease item = Utils::Obs::SearchHelper::GetSceneItemByName(scene, sourceName);
|
int offset = 0;
|
||||||
|
if (request.Contains("searchOffset")) {
|
||||||
|
if (!request.ValidateOptionalNumber("searchOffset", statusCode, comment, -1))
|
||||||
|
return RequestResult::Error(statusCode, comment);
|
||||||
|
offset = request.RequestData["searchOffset"];
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSSceneItemAutoRelease item = Utils::Obs::SearchHelper::GetSceneItemByName(scene, sourceName, offset);
|
||||||
if (!item)
|
if (!item)
|
||||||
return RequestResult::Error(RequestStatus::ResourceNotFound, "No scene items were found in the specified scene by that name.");
|
return RequestResult::Error(RequestStatus::ResourceNotFound, "No scene items were found in the specified scene by that name or offset.");
|
||||||
|
|
||||||
json responseData;
|
json responseData;
|
||||||
responseData["sceneItemId"] = obs_sceneitem_get_id(item);
|
responseData["sceneItemId"] = obs_sceneitem_get_id(item);
|
||||||
@ -710,3 +718,39 @@ RequestResult RequestHandler::SetSceneItemBlendMode(const Request& request)
|
|||||||
|
|
||||||
return RequestResult::Success();
|
return RequestResult::Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Intentionally undocumented
|
||||||
|
RequestResult RequestHandler::GetSceneItemPrivateSettings(const Request& request)
|
||||||
|
{
|
||||||
|
RequestStatus::RequestStatus statusCode;
|
||||||
|
std::string comment;
|
||||||
|
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||||
|
if (!sceneItem)
|
||||||
|
return RequestResult::Error(statusCode, comment);
|
||||||
|
|
||||||
|
OBSDataAutoRelease privateSettings = obs_sceneitem_get_private_settings(sceneItem);
|
||||||
|
|
||||||
|
json responseData;
|
||||||
|
responseData["sceneItemSettings"] = Utils::Json::ObsDataToJson(privateSettings);
|
||||||
|
|
||||||
|
return RequestResult::Success(responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intentionally undocumented
|
||||||
|
RequestResult RequestHandler::SetSceneItemPrivateSettings(const Request& request)
|
||||||
|
{
|
||||||
|
RequestStatus::RequestStatus statusCode;
|
||||||
|
std::string comment;
|
||||||
|
OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP);
|
||||||
|
if (!sceneItem || !request.ValidateObject("sceneItemSettings", statusCode, comment))
|
||||||
|
return RequestResult::Error(statusCode, comment);
|
||||||
|
|
||||||
|
OBSDataAutoRelease privateSettings = obs_sceneitem_get_private_settings(sceneItem);
|
||||||
|
|
||||||
|
OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData(request.RequestData["sceneItemSettings"]);
|
||||||
|
|
||||||
|
// Always overlays to prevent destroying internal source unintentionally
|
||||||
|
obs_data_apply(privateSettings, newSettings);
|
||||||
|
|
||||||
|
return RequestResult::Success();
|
||||||
|
}
|
||||||
|
@ -17,6 +17,11 @@ 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/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QRect>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "RequestHandler.h"
|
#include "RequestHandler.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,3 +153,39 @@ RequestResult RequestHandler::OpenInputInteractDialog(const Request& request)
|
|||||||
|
|
||||||
return RequestResult::Success();
|
return RequestResult::Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of connected monitors and information about them.
|
||||||
|
*
|
||||||
|
* @responseField monitors | Array<Object> | a list of detected monitors with some information
|
||||||
|
*
|
||||||
|
* @requestType GetMonitorList
|
||||||
|
* @complexity 2
|
||||||
|
* @rpcVersion -1
|
||||||
|
* @initialVersion 5.0.0
|
||||||
|
* @category ui
|
||||||
|
* @api requests
|
||||||
|
*/
|
||||||
|
RequestResult RequestHandler::GetMonitorList(const Request&)
|
||||||
|
{
|
||||||
|
json responseData;
|
||||||
|
std::vector<json> monitorsData;
|
||||||
|
QList<QScreen *> screensList = QGuiApplication::screens();
|
||||||
|
for (int screenIndex = 0; screenIndex < screensList.size(); screenIndex++)
|
||||||
|
{
|
||||||
|
json screenData;
|
||||||
|
QScreen const* screen = screensList[screenIndex];
|
||||||
|
std::stringstream nameAndIndex;
|
||||||
|
nameAndIndex << screen->name().toStdString();
|
||||||
|
nameAndIndex << '(' << screenIndex << ')';
|
||||||
|
screenData["monitorName"] = nameAndIndex.str();
|
||||||
|
const QRect screenGeometry = screen->geometry();
|
||||||
|
screenData["monitorWidth"] = screenGeometry.width();
|
||||||
|
screenData["monitorHeight"] = screenGeometry.height();
|
||||||
|
screenData["monitorPositionX"] = screenGeometry.x();
|
||||||
|
screenData["monitorPositionY"] = screenGeometry.y();
|
||||||
|
monitorsData.push_back(screenData);
|
||||||
|
}
|
||||||
|
responseData["monitors"] = monitorsData;
|
||||||
|
return RequestResult::Success(responseData);
|
||||||
|
}
|
||||||
|
@ -205,7 +205,7 @@ namespace Utils {
|
|||||||
namespace SearchHelper {
|
namespace SearchHelper {
|
||||||
obs_hotkey_t *GetHotkeyByName(std::string name);
|
obs_hotkey_t *GetHotkeyByName(std::string name);
|
||||||
obs_source_t *GetSceneTransitionByName(std::string name); // Increments source ref. Use OBSSourceAutoRelease
|
obs_source_t *GetSceneTransitionByName(std::string name); // Increments source ref. Use OBSSourceAutoRelease
|
||||||
obs_sceneitem_t *GetSceneItemByName(obs_scene_t *scene, std::string name); // Increments ref. Use OBSSceneItemAutoRelease
|
obs_sceneitem_t *GetSceneItemByName(obs_scene_t *scene, std::string name, int offset = 0); // Increments ref. Use OBSSceneItemAutoRelease
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ActionHelper {
|
namespace ActionHelper {
|
||||||
|
@ -88,6 +88,7 @@ std::vector<json> Utils::Obs::ArrayHelper::GetSceneList()
|
|||||||
obs_frontend_get_scenes(&sceneList);
|
obs_frontend_get_scenes(&sceneList);
|
||||||
|
|
||||||
std::vector<json> ret;
|
std::vector<json> ret;
|
||||||
|
ret.reserve(sceneList.sources.num);
|
||||||
for (size_t i = 0; i < sceneList.sources.num; i++) {
|
for (size_t i = 0; i < sceneList.sources.num; i++) {
|
||||||
obs_source_t *scene = sceneList.sources.array[i];
|
obs_source_t *scene = sceneList.sources.array[i];
|
||||||
|
|
||||||
@ -225,6 +226,8 @@ std::vector<json> Utils::Obs::ArrayHelper::GetListPropertyItems(obs_property_t *
|
|||||||
enum obs_combo_format itemFormat = obs_property_list_format(property);
|
enum obs_combo_format itemFormat = obs_property_list_format(property);
|
||||||
size_t itemCount = obs_property_list_item_count(property);
|
size_t itemCount = obs_property_list_item_count(property);
|
||||||
|
|
||||||
|
ret.reserve(itemCount);
|
||||||
|
|
||||||
for (size_t i = 0; i < itemCount; i++) {
|
for (size_t i = 0; i < itemCount; i++) {
|
||||||
json itemData;
|
json itemData;
|
||||||
itemData["itemName"] = obs_property_list_item_name(property, i);
|
itemData["itemName"] = obs_property_list_item_name(property, i);
|
||||||
@ -262,6 +265,7 @@ std::vector<json> Utils::Obs::ArrayHelper::GetSceneTransitionList()
|
|||||||
obs_frontend_get_transitions(&transitionList);
|
obs_frontend_get_transitions(&transitionList);
|
||||||
|
|
||||||
std::vector<json> ret;
|
std::vector<json> ret;
|
||||||
|
ret.reserve(transitionList.sources.num);
|
||||||
for (size_t i = 0; i < transitionList.sources.num; i++) {
|
for (size_t i = 0; i < transitionList.sources.num; i++) {
|
||||||
obs_source_t *transition = transitionList.sources.array[i];
|
obs_source_t *transition = transitionList.sources.array[i];
|
||||||
json transitionJson;
|
json transitionJson;
|
||||||
|
@ -54,15 +54,42 @@ obs_source_t *Utils::Obs::SearchHelper::GetSceneTransitionByName(std::string nam
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SceneItemSearchData {
|
||||||
|
std::string name;
|
||||||
|
int offset;
|
||||||
|
obs_sceneitem_t *ret = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
// Increments item ref. Use OBSSceneItemAutoRelease
|
// Increments item ref. Use OBSSceneItemAutoRelease
|
||||||
obs_sceneitem_t *Utils::Obs::SearchHelper::GetSceneItemByName(obs_scene_t *scene, std::string name)
|
obs_sceneitem_t *Utils::Obs::SearchHelper::GetSceneItemByName(obs_scene_t *scene, std::string name, int offset)
|
||||||
{
|
{
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Finds first matching scene item in scene, search starts at index 0
|
SceneItemSearchData enumData;
|
||||||
OBSSceneItem ret = obs_scene_find_source(scene, name.c_str());
|
enumData.name = name;
|
||||||
obs_sceneitem_addref(ret);
|
enumData.offset = offset;
|
||||||
|
|
||||||
return ret;
|
obs_scene_enum_items(scene, [](obs_scene_t*, obs_sceneitem_t* sceneItem, void* param) {
|
||||||
|
auto enumData = static_cast<SceneItemSearchData*>(param);
|
||||||
|
|
||||||
|
OBSSource itemSource = obs_sceneitem_get_source(sceneItem);
|
||||||
|
std::string sourceName = obs_source_get_name(itemSource);
|
||||||
|
if (sourceName == enumData->name) {
|
||||||
|
if (enumData->offset > 0) {
|
||||||
|
enumData->offset--;
|
||||||
|
} else {
|
||||||
|
if (enumData->ret) // Release existing selection in the case of last match selection
|
||||||
|
obs_sceneitem_release(enumData->ret);
|
||||||
|
obs_sceneitem_addref(sceneItem);
|
||||||
|
enumData->ret = sceneItem;
|
||||||
|
if (enumData->offset == 0) // Only break if in normal selection mode (not offset == -1)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}, &enumData);
|
||||||
|
|
||||||
|
return enumData.ret;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,13 @@ void WebSocketServer::Start()
|
|||||||
_server.reset();
|
_server.reset();
|
||||||
|
|
||||||
websocketpp::lib::error_code errorCode;
|
websocketpp::lib::error_code errorCode;
|
||||||
|
if (conf->Ipv4Only) {
|
||||||
|
blog(LOG_INFO, "[WebSocketServer::Start] Locked to IPv4 bindings");
|
||||||
_server.listen(websocketpp::lib::asio::ip::tcp::v4(), conf->ServerPort, errorCode);
|
_server.listen(websocketpp::lib::asio::ip::tcp::v4(), conf->ServerPort, errorCode);
|
||||||
|
} else {
|
||||||
|
blog(LOG_INFO, "[WebSocketServer::Start] Not locked to IPv4 bindings");
|
||||||
|
_server.listen(conf->ServerPort, errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
if (errorCode) {
|
if (errorCode) {
|
||||||
std::string errorCodeMessage = errorCode.message();
|
std::string errorCodeMessage = errorCode.message();
|
||||||
|
Loading…
Reference in New Issue
Block a user