diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 62ce5a59..5ad3fe5e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,6 +1,6 @@ - + ### Description @@ -27,7 +27,7 @@ Tested OS(s): ### Checklist: -- [ ] I have read the [**contributing** document](https://github.com/Palakis/obs-websocket/blob/4.x-current/CONTRIBUTING.md). +- [ ] I have read the [**contributing** document](https://github.com/obs-websocket/obs-websocket/blob/4.x-current/CONTRIBUTING.md). - [ ] My code is not on the master branch. - [ ] The code has been tested. - [ ] All commit messages are properly formatted and commits squashed where appropriate. diff --git a/BUILDING.md b/BUILDING.md index 9dda2fed..a7f25241 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -21,7 +21,7 @@ On Debian/Ubuntu : ```shell sudo apt-get install libboost-all-dev -git clone --recursive https://github.com/Palakis/obs-websocket.git +git clone --recursive https://github.com/obs-websocket/obs-websocket.git cd obs-websocket mkdir build && cd build cmake -DLIBOBS_INCLUDE_DIR="" -DCMAKE_INSTALL_PREFIX=/usr -DUSE_UBUNTU_FIX=true .. @@ -51,7 +51,7 @@ Of course, you're encouraged to dig through the contents of these scripts to look for issues or specificities. ```shell -git clone --recursive https://github.com/Palakis/obs-websocket.git +git clone --recursive https://github.com/obs-websocket/obs-websocket.git cd obs-websocket ./CI/install-dependencies-macos.sh ./CI/install-build-obs-macos.sh @@ -63,4 +63,4 @@ This will result in a ready-to-use `obs-websocket.pkg` installer in the `release ## Automated Builds -![Github Actions](https://github.com/Palakis/obs-websocket/actions/workflows/main.yml/badge.svg?branch=master) +![Github Actions](https://github.com/obs-websocket/obs-websocket/actions/workflows/main.yml/badge.svg?branch=master) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc1f5707..0ab45138 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,7 @@ set(obs-websocket_SOURCES src/requesthandler/RequestHandler_SceneItems.cpp src/requesthandler/RequestHandler_Stream.cpp src/requesthandler/RequestHandler_Record.cpp + src/requesthandler/RequestHandler_MediaInputs.cpp src/requesthandler/rpc/Request.cpp src/requesthandler/rpc/RequestResult.cpp src/forms/SettingsDialog.cpp diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 628b16ef..3c68be97 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,21 +29,20 @@ These are required to automatically generate the [protocol specification documen * Favor return-early code and avoid wrapping huge portions of code in conditionals. As an example, this: ```cpp -if (success) { +if (success) return RequestResult::Success(); -} else { +else return RequestResult::Error(RequestStatus::GenericError); -} ``` is better like this: ```cpp -if (!success) { +if (!success) return RequestResult::Error(RequestStatus::GenericError); -} + return RequestResult::Success(); ``` -* Try to use the [built-in](https://github.com/Palakis/obs-websocket/blob/master/src/requesthandler/rpc/Request.h) request checks when possible. +* Try to use the [built-in](https://github.com/obs-websocket/obs-websocket/blob/master/src/requesthandler/rpc/Request.h) request checks when possible. * Refer to existing requests for usage examples. * Some example common response/request property names are: @@ -54,12 +53,14 @@ return RequestResult::Success(); * Response parameters which have no attributed data due to an invalid state should be set to `null` (versus being left out) * For example, when `GetSceneList` is called and OBS is not in studio mode, `currentPreviewSceneName` will be `null` - * If a request's core response data depends on a state, an error should be thrown unless `ignoreNonFatalRequestChecks` is set. See `GetCurrentPreviewScene` as an example. + * If a request's core response data depends on a state, an error should be thrown. See `GetCurrentPreviewScene` as an example. + +* In general, try to match the style of existing code as best as possible. We try our best to keep a consistent code style, and may suggest nitpicks as necessary. ### Commit Guidelines * Commits follow the 50/72 standard: - * 50 characters max for the commit title (excluding scope name) + * 50 characters suggested max for the commit title (absolute maximum 72 including scope) * One empty line after the title * Description wrapped to 72 columns max width per line. diff --git a/README.md b/README.md index fc47efe6..a2cbe09e 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,13 @@ WebSockets API for OBS Studio. -[![CI Multiplatform Build](https://github.com/Palakis/obs-websocket/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/Palakis/obs-websocket/actions/workflows/main.yml) +[![CI Multiplatform Build](https://github.com/obs-websocket/obs-websocket/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/obs-websocket/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) [![Financial Contributors on Open Collective](https://opencollective.com/obs-websocket/all/badge.svg?label=financial+contributors)](https://opencollective.com/obs-websocket) ## Downloads -Binaries for Windows, MacOS, and Linux are available in the [Releases](https://github.com/Palakis/obs-websocket/releases) section. +Binaries for Windows, MacOS, and Linux are available in the [Releases](https://github.com/obs-websocket/obs-websocket/releases) section. ### Homebrew @@ -75,7 +75,7 @@ Please join the localization project on [Crowdin](https://crowdin.com/project/ob ### Code Contributors This project exists thanks to all the people who contribute. [Contribute](CONTRIBUTING.md). - + ### Financial Contributors diff --git a/installer/installer-windows.iss.in b/installer/installer-windows.iss.in index 2990ccdb..f27c99cf 100644 --- a/installer/installer-windows.iss.in +++ b/installer/installer-windows.iss.in @@ -1,7 +1,7 @@ #define MyAppName "obs-websocket" #define MyAppVersion "@OBS_WEBSOCKET_VERSION@" #define MyAppPublisher "Stephane Lepin" -#define MyAppURL "http://github.com/Palakis/obs-websocket" +#define MyAppURL "http://github.com/obs-websocket/obs-websocket" [Setup] ; NOTE: The value of AppId uniquely identifies this application. diff --git a/src/eventhandler/EventHandler.cpp b/src/eventhandler/EventHandler.cpp index 42d08b6c..c91b5597 100644 --- a/src/eventhandler/EventHandler.cpp +++ b/src/eventhandler/EventHandler.cpp @@ -237,18 +237,18 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_ break; // Config - //case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING: - // eventHandler->HandleCurrentSceneCollectionChanging(); - // break; + case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING: + eventHandler->HandleCurrentSceneCollectionChanging(); + break; case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED: 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_CHANGING: + eventHandler->HandleCurrentProfileChanging(); + break; case OBS_FRONTEND_EVENT_PROFILE_CHANGED: eventHandler->HandleCurrentProfileChanged(); break; diff --git a/src/requesthandler/RequestHandler.cpp b/src/requesthandler/RequestHandler.cpp index 168a7a2a..4def32ee 100644 --- a/src/requesthandler/RequestHandler.cpp +++ b/src/requesthandler/RequestHandler.cpp @@ -97,6 +97,12 @@ const std::map RequestHandler::_handlerMap {"PauseRecord", &RequestHandler::PauseRecord}, {"ResumeRecord", &RequestHandler::ResumeRecord}, //{"GetRecordDirectory", &RequestHandler::GetRecordDirectory}, + + // Media Inputs + {"GetMediaInputStatus", &RequestHandler::GetMediaInputStatus}, + {"SetMediaInputCursor", &RequestHandler::SetMediaInputCursor}, + {"OffsetMediaInputCursor", &RequestHandler::OffsetMediaInputCursor}, + {"TriggerMediaInputAction", &RequestHandler::TriggerMediaInputAction}, }; RequestHandler::RequestHandler(SessionPtr session) : diff --git a/src/requesthandler/RequestHandler.h b/src/requesthandler/RequestHandler.h index f426e3e4..4c057c15 100644 --- a/src/requesthandler/RequestHandler.h +++ b/src/requesthandler/RequestHandler.h @@ -119,6 +119,12 @@ class RequestHandler { RequestResult ResumeRecord(const Request&); RequestResult GetRecordDirectory(const Request&); + // Media Inputs + RequestResult GetMediaInputStatus(const Request&); + RequestResult SetMediaInputCursor(const Request&); + RequestResult OffsetMediaInputCursor(const Request&); + RequestResult TriggerMediaInputAction(const Request&); + SessionPtr _session; static const std::map _handlerMap; }; diff --git a/src/requesthandler/RequestHandler_Config.cpp b/src/requesthandler/RequestHandler_Config.cpp index cee2447c..10692cd3 100644 --- a/src/requesthandler/RequestHandler_Config.cpp +++ b/src/requesthandler/RequestHandler_Config.cpp @@ -23,10 +23,10 @@ RequestResult RequestHandler::GetPersistentData(const Request& request) json responseData; json persistentData; - if (!(Utils::Json::GetJsonFileContent(persistentDataPath, persistentData) && persistentData.contains(slotName))) - responseData["slotValue"] = nullptr; - else + if (Utils::Json::GetJsonFileContent(persistentDataPath, persistentData) && persistentData.contains(slotName)) responseData["slotValue"] = persistentData[slotName]; + else + responseData["slotValue"] = nullptr; return RequestResult::Success(responseData); } @@ -347,7 +347,7 @@ RequestResult RequestHandler::SetStreamServiceSettings(const Request& request) obs_service_update(currentStreamService, newStreamServiceSettings); } else { // TODO: This leaks memory. I have no idea why. - OBSService newStreamService = obs_service_create(requestedStreamServiceType.c_str(), "obs_websocket_custom_service", requestedStreamServiceSettings, NULL); + OBSService newStreamService = obs_service_create(requestedStreamServiceType.c_str(), "obs_websocket_custom_service", requestedStreamServiceSettings, nullptr); // TODO: Check service type here, instead of relying on service creation to fail. if (!newStreamService) return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the stream service with the requested streamServiceType. It may be an invalid type."); diff --git a/src/requesthandler/RequestHandler_General.cpp b/src/requesthandler/RequestHandler_General.cpp index e49d5110..bb631e38 100644 --- a/src/requesthandler/RequestHandler_General.cpp +++ b/src/requesthandler/RequestHandler_General.cpp @@ -8,7 +8,7 @@ RequestResult RequestHandler::GetVersion(const Request& request) { json responseData; - responseData["obsVersion"] = Utils::Obs::StringHelper::GetObsVersionString(); + responseData["obsVersion"] = Utils::Obs::StringHelper::GetObsVersion(); responseData["obsWebSocketVersion"] = OBS_WEBSOCKET_VERSION; responseData["rpcVersion"] = OBS_WEBSOCKET_RPC_VERSION; responseData["availableRequests"] = GetRequestList(); diff --git a/src/requesthandler/RequestHandler_Inputs.cpp b/src/requesthandler/RequestHandler_Inputs.cpp index d95b3daf..95c982c7 100644 --- a/src/requesthandler/RequestHandler_Inputs.cpp +++ b/src/requesthandler/RequestHandler_Inputs.cpp @@ -319,7 +319,7 @@ RequestResult RequestHandler::GetInputAudioMonitorType(const Request& request) return RequestResult::Error(statusCode, comment); json responseData; - responseData["monitorType"] = Utils::Obs::StringHelper::GetInputMonitorTypeString(input); + responseData["monitorType"] = Utils::Obs::StringHelper::GetInputMonitorType(input); return RequestResult::Success(responseData); } @@ -365,6 +365,8 @@ std::vector GetListPropertyItems(obs_property_t *property) itemData["itemValue"] = obs_property_list_item_float(property, i); } else if (itemFormat == OBS_COMBO_FORMAT_STRING) { itemData["itemValue"] = obs_property_list_item_string(property, i); + } else { + itemData["itemValue"] = nullptr; } ret.push_back(itemData); } diff --git a/src/requesthandler/RequestHandler_MediaInputs.cpp b/src/requesthandler/RequestHandler_MediaInputs.cpp new file mode 100644 index 00000000..3e1b83dd --- /dev/null +++ b/src/requesthandler/RequestHandler_MediaInputs.cpp @@ -0,0 +1,110 @@ +#include "RequestHandler.h" + +bool IsMediaTimeValid(obs_source_t *input) +{ + auto mediaState = obs_source_media_get_state(input); + return mediaState == OBS_MEDIA_STATE_PLAYING || mediaState == OBS_MEDIA_STATE_PAUSED; +} + +RequestResult RequestHandler::GetMediaInputStatus(const Request& request) +{ + RequestStatus::RequestStatus statusCode; + std::string comment; + OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + if (!input) + return RequestResult::Error(statusCode, comment); + + json responseData; + responseData["mediaState"] = Utils::Obs::StringHelper::GetMediaInputState(input); + + if (IsMediaTimeValid(input)) { + responseData["mediaDuration"] = obs_source_media_get_duration(input); + responseData["mediaCursor"] = obs_source_media_get_time(input); + } else { + responseData["mediaDuration"] = nullptr; + responseData["mediaCursor"] = nullptr; + } + + return RequestResult::Success(responseData); +} + +RequestResult RequestHandler::SetMediaInputCursor(const Request& request) +{ + RequestStatus::RequestStatus statusCode; + std::string comment; + OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + if (!(input && request.ValidateNumber("mediaCursor", statusCode, comment, 0))) + return RequestResult::Error(statusCode, comment); + + if (!IsMediaTimeValid(input)) + return RequestResult::Error(RequestStatus::InvalidResourceState, "The media input must be playing or paused in order to set the cursor position."); + + int64_t mediaCursor = request.RequestData["mediaCursor"]; + + // Yes, we're setting the time without checking if it's valid. Can't baby everything. + obs_source_media_set_time(input, mediaCursor); + + return RequestResult::Success(); +} + +RequestResult RequestHandler::OffsetMediaInputCursor(const Request& request) +{ + RequestStatus::RequestStatus statusCode; + std::string comment; + OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + if (!(input && request.ValidateNumber("mediaCursorOffset", statusCode, comment))) + return RequestResult::Error(statusCode, comment); + + if (!IsMediaTimeValid(input)) + return RequestResult::Error(RequestStatus::InvalidResourceState, "The media input must be playing or paused in order to set the cursor position."); + + int64_t mediaCursorOffset = request.RequestData["mediaCursorOffset"]; + int64_t mediaCursor = obs_source_media_get_time(input) + mediaCursorOffset; + + if (mediaCursor < 0) + mediaCursor = 0; + + obs_source_media_set_time(input, mediaCursor); + + return RequestResult::Success(); +} + +RequestResult RequestHandler::TriggerMediaInputAction(const Request& request) +{ + RequestStatus::RequestStatus statusCode; + std::string comment; + OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + if (!(input && request.ValidateString("mediaAction", statusCode, comment))) + return RequestResult::Error(statusCode, comment); + + std::string mediaActionString = request.RequestData["mediaAction"]; + auto mediaAction = Utils::Obs::EnumHelper::GetMediaInputAction(mediaActionString); + + switch (mediaAction) { + default: + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE: + return RequestResult::Error(RequestStatus::InvalidRequestParameter, "You have specified an invalid media input action."); + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY: + // Shoutout to whoever implemented this API call like this + obs_source_media_play_pause(input, false); + break; + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE: + obs_source_media_play_pause(input, true); + break; + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP: + obs_source_media_stop(input); + break; + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART: + // I'm only implementing this because I'm nice. I think its a really dumb action. + obs_source_media_restart(input); + break; + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT: + obs_source_media_next(input); + break; + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS: + obs_source_media_previous(input); + break; + } + + return RequestResult::Success(); +} diff --git a/src/requesthandler/RequestHandler_Record.cpp b/src/requesthandler/RequestHandler_Record.cpp index ef6699f1..db4ffa76 100644 --- a/src/requesthandler/RequestHandler_Record.cpp +++ b/src/requesthandler/RequestHandler_Record.cpp @@ -4,11 +4,13 @@ RequestResult RequestHandler::GetRecordStatus(const Request& request) { OBSOutputAutoRelease recordOutput = obs_frontend_get_streaming_output(); + uint64_t outputDuration = Utils::Obs::NumberHelper::GetOutputDuration(recordOutput); + json responseData; responseData["outputActive"] = obs_output_active(recordOutput); responseData["outputPaused"] = obs_output_paused(recordOutput); - responseData["outputTimecode"] = Utils::Obs::StringHelper::GetOutputTimecodeString(recordOutput); - responseData["outputDuration"] = Utils::Obs::NumberHelper::GetOutputDuration(recordOutput); + responseData["outputTimecode"] = Utils::Obs::StringHelper::DurationToTimecode(outputDuration); + responseData["outputDuration"] = outputDuration; responseData["outputBytes"] = (uint64_t)obs_output_get_total_bytes(recordOutput); return RequestResult::Success(responseData); diff --git a/src/requesthandler/RequestHandler_Stream.cpp b/src/requesthandler/RequestHandler_Stream.cpp index f151aa9f..50b844fe 100644 --- a/src/requesthandler/RequestHandler_Stream.cpp +++ b/src/requesthandler/RequestHandler_Stream.cpp @@ -4,11 +4,13 @@ RequestResult RequestHandler::GetStreamStatus(const Request& request) { OBSOutputAutoRelease streamOutput = obs_frontend_get_streaming_output(); + uint64_t outputDuration = Utils::Obs::NumberHelper::GetOutputDuration(streamOutput); + json responseData; responseData["outputActive"] = obs_output_active(streamOutput); responseData["outputReconnecting"] = obs_output_reconnecting(streamOutput); - responseData["outputTimecode"] = Utils::Obs::StringHelper::GetOutputTimecodeString(streamOutput); - responseData["outputDuration"] = Utils::Obs::NumberHelper::GetOutputDuration(streamOutput); + responseData["outputTimecode"] = Utils::Obs::StringHelper::DurationToTimecode(outputDuration); + responseData["outputDuration"] = outputDuration; responseData["outputBytes"] = (uint64_t)obs_output_get_total_bytes(streamOutput); responseData["outputSkippedFrames"] = obs_output_get_frames_dropped(streamOutput); responseData["outputTotalFrames"] = obs_output_get_total_frames(streamOutput); diff --git a/src/utils/Obs.cpp b/src/utils/Obs.cpp index a4f6c7d4..a5a5b7eb 100644 --- a/src/utils/Obs.cpp +++ b/src/utils/Obs.cpp @@ -30,7 +30,7 @@ std::vector ConvertStringArray(char **array) return ret; } -std::string Utils::Obs::StringHelper::GetObsVersionString() +std::string Utils::Obs::StringHelper::GetObsVersion() { uint32_t version = obs_get_version(); @@ -77,7 +77,7 @@ std::string Utils::Obs::StringHelper::GetCurrentRecordOutputPath() return ""; } -std::string Utils::Obs::StringHelper::GetSourceTypeString(obs_source_t *source) +std::string Utils::Obs::StringHelper::GetSourceType(obs_source_t *source) { obs_source_type sourceType = obs_source_get_type(source); @@ -90,7 +90,7 @@ std::string Utils::Obs::StringHelper::GetSourceTypeString(obs_source_t *source) } } -std::string Utils::Obs::StringHelper::GetInputMonitorTypeString(obs_source_t *input) +std::string Utils::Obs::StringHelper::GetInputMonitorType(obs_source_t *input) { obs_monitoring_type monitorType = obs_source_get_monitoring_type(input); @@ -102,7 +102,7 @@ std::string Utils::Obs::StringHelper::GetInputMonitorTypeString(obs_source_t *in } } -std::string Utils::Obs::StringHelper::GetMediaInputStateString(obs_source_t *input) +std::string Utils::Obs::StringHelper::GetMediaInputState(obs_source_t *input) { obs_media_state mediaState = obs_source_media_get_state(input); @@ -130,7 +130,7 @@ std::string Utils::Obs::StringHelper::GetLastReplayBufferFilePath() return ret; } -std::string Utils::Obs::StringHelper::GetSceneItemBoundsTypeString(enum obs_bounds_type type) +std::string Utils::Obs::StringHelper::GetSceneItemBoundsType(enum obs_bounds_type type) { switch (type) { default: @@ -144,16 +144,8 @@ std::string Utils::Obs::StringHelper::GetSceneItemBoundsTypeString(enum obs_boun } } -std::string Utils::Obs::StringHelper::GetOutputTimecodeString(obs_output_t *output) +std::string Utils::Obs::StringHelper::DurationToTimecode(uint64_t ms) { - if (!output || !obs_output_active(output)) - return "00:00:00.000"; - - video_t* video = obs_output_video(output); - uint64_t frameTimeNs = video_output_get_frame_time(video); - int totalFrames = obs_output_get_total_frames(output); - - uint64_t ms = util_mul_div64(totalFrames, frameTimeNs, 1000000ULL); uint64_t secs = ms / 1000ULL; uint64_t minutes = secs / 60ULL; @@ -179,6 +171,18 @@ enum obs_bounds_type Utils::Obs::EnumHelper::GetSceneItemBoundsType(std::string return OBS_BOUNDS_NONE; } +enum ObsMediaInputAction Utils::Obs::EnumHelper::GetMediaInputAction(std::string mediaAction) +{ + RET_COMPARE(mediaAction, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY); + RET_COMPARE(mediaAction, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE); + RET_COMPARE(mediaAction, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP); + RET_COMPARE(mediaAction, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART); + RET_COMPARE(mediaAction, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT); + RET_COMPARE(mediaAction, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS); + + return OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE; +} + uint64_t Utils::Obs::NumberHelper::GetOutputDuration(obs_output_t *output) { if (!output || !obs_output_active(output)) @@ -288,11 +292,15 @@ std::vector Utils::Obs::ListHelper::GetSceneItemList(obs_scene_t *scene, b if (!enumData->second) { OBSSource itemSource = obs_sceneitem_get_source(sceneItem); item["sourceName"] = obs_source_get_name(itemSource); - item["sourceType"] = StringHelper::GetSourceTypeString(itemSource); + item["sourceType"] = StringHelper::GetSourceType(itemSource); if (obs_source_get_type(itemSource) == OBS_SOURCE_TYPE_INPUT) item["inputKind"] = obs_source_get_id(itemSource); - else if (obs_source_get_type(itemSource) == OBS_SOURCE_TYPE_SCENE) + else + item["inputKind"] = nullptr; + if (obs_source_get_type(itemSource) == OBS_SOURCE_TYPE_SCENE) item["isGroup"] = obs_source_is_group(itemSource); + else + item["isGroup"] = nullptr; } enumData->first.push_back(item); @@ -433,7 +441,7 @@ json Utils::Obs::DataHelper::GetSceneItemTransform(obs_sceneitem_t *item) ret["alignment"] = osi.alignment; - ret["boundsType"] = StringHelper::GetSceneItemBoundsTypeString(osi.bounds_type); + ret["boundsType"] = StringHelper::GetSceneItemBoundsType(osi.bounds_type); ret["boundsAlignment"] = osi.bounds_alignment; ret["boundsWidth"] = osi.bounds.x; ret["boundsHeight"] = osi.bounds.y; diff --git a/src/utils/Obs.h b/src/utils/Obs.h index 8819003f..883c2160 100644 --- a/src/utils/Obs.h +++ b/src/utils/Obs.h @@ -16,10 +16,11 @@ enum ObsOutputState { }; enum ObsMediaInputAction { - OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE, + OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY, - OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART, + OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP, + OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS }; @@ -27,21 +28,22 @@ enum ObsMediaInputAction { namespace Utils { namespace Obs { namespace StringHelper { - std::string GetObsVersionString(); + std::string GetObsVersion(); std::string GetCurrentSceneCollection(); std::string GetCurrentProfile(); std::string GetCurrentProfilePath(); std::string GetCurrentRecordOutputPath(); - std::string GetSourceTypeString(obs_source_t *source); - std::string GetInputMonitorTypeString(obs_source_t *input); - std::string GetMediaInputStateString(obs_source_t *input); + std::string GetSourceType(obs_source_t *source); + std::string GetInputMonitorType(obs_source_t *input); + std::string GetMediaInputState(obs_source_t *input); std::string GetLastReplayBufferFilePath(); - std::string GetSceneItemBoundsTypeString(enum obs_bounds_type type); - std::string GetOutputTimecodeString(obs_output_t *output); + std::string GetSceneItemBoundsType(enum obs_bounds_type type); + std::string DurationToTimecode(uint64_t); } namespace EnumHelper { enum obs_bounds_type GetSceneItemBoundsType(std::string boundsType); + enum ObsMediaInputAction GetMediaInputAction(std::string mediaAction); } namespace NumberHelper {