Requests: Add more requests

- GetStreamServiceSettings
- SetStreamServiceSettings
- CreateInput
- GetStreamStatus
- StartStream
- StopStream
This commit is contained in:
tt2468 2021-07-22 16:26:04 -07:00
parent 4d271da541
commit d0e05ae45c
8 changed files with 160 additions and 0 deletions

View File

@ -91,6 +91,7 @@ set(obs-websocket_SOURCES
src/requesthandler/RequestHandler_Sources.cpp
src/requesthandler/RequestHandler_Scenes.cpp
src/requesthandler/RequestHandler_Inputs.cpp
src/requesthandler/RequestHandler_Stream.cpp
src/requesthandler/rpc/Request.cpp
src/requesthandler/rpc/RequestResult.cpp
src/forms/SettingsDialog.cpp

View File

@ -22,6 +22,8 @@ const std::map<std::string, RequestMethodHandler> RequestHandler::_handlerMap
{"SetProfileParameter", &RequestHandler::SetProfileParameter},
{"GetVideoSettings", &RequestHandler::GetVideoSettings},
{"SetVideoSettings", &RequestHandler::SetVideoSettings},
{"GetStreamServiceSettings", &RequestHandler::GetStreamServiceSettings},
{"SetStreamServiceSettings", &RequestHandler::SetStreamServiceSettings},
// Sources
{"GetSourceActive", &RequestHandler::GetSourceActive},
@ -51,6 +53,11 @@ const std::map<std::string, RequestMethodHandler> RequestHandler::_handlerMap
{"SetInputVolume", &RequestHandler::SetInputVolume},
{"SetInputName", &RequestHandler::SetInputName},
{"CreateInput", &RequestHandler::CreateInput},
// Stream
{"GetStreamStatus", &RequestHandler::GetStreamStatus},
{"StartStream", &RequestHandler::StartStream},
{"StopStream", &RequestHandler::StopStream},
};
RequestResult RequestHandler::ProcessRequest(const Request& request)

View File

@ -37,6 +37,8 @@ class RequestHandler {
RequestResult SetProfileParameter(const Request&);
RequestResult GetVideoSettings(const Request&);
RequestResult SetVideoSettings(const Request&);
RequestResult GetStreamServiceSettings(const Request&);
RequestResult SetStreamServiceSettings(const Request&);
// Sources
RequestResult GetSourceActive(const Request&);
@ -67,5 +69,10 @@ class RequestHandler {
RequestResult SetInputName(const Request&);
RequestResult CreateInput(const Request&);
// Stream
RequestResult GetStreamStatus(const Request&);
RequestResult StartStream(const Request&);
RequestResult StopStream(const Request&);
static const std::map<std::string, RequestMethodHandler> _handlerMap;
};

View File

@ -175,3 +175,55 @@ RequestResult RequestHandler::SetVideoSettings(const Request& request)
return RequestResult::Error(RequestStatus::MissingRequestParameter, "You must specify at least one video-changing pair.");
}
RequestResult RequestHandler::GetStreamServiceSettings(const Request& request)
{
json responseData;
OBSService service = obs_frontend_get_streaming_service();
responseData["streamServiceType"] = obs_service_get_type(service);
OBSDataAutoRelease serviceSettings = obs_service_get_settings(service);
responseData["streamServiceSettings"] = Utils::Json::ObsDataToJson(serviceSettings, true);
return RequestResult::Success(responseData);
}
RequestResult RequestHandler::SetStreamServiceSettings(const Request& request)
{
if (obs_frontend_streaming_active())
return RequestResult::Error(RequestStatus::StreamRunning);
RequestStatus::RequestStatus statusCode;
std::string comment;
if (!(request.ValidateString("streamServiceType", statusCode, comment) && request.ValidateObject("streamServiceSettings", statusCode, comment)))
return RequestResult::Error(statusCode, comment);
OBSService currentStreamService = obs_frontend_get_streaming_service();
std::string streamServiceType = obs_service_get_type(currentStreamService);
std::string requestedStreamServiceType = request.RequestData["streamServiceType"];
OBSDataAutoRelease requestedStreamServiceSettings = Utils::Json::JsonToObsData(request.RequestData["streamServiceSettings"]);
// Don't create a new service if the current service is the same type.
if (streamServiceType == requestedStreamServiceType) {
OBSDataAutoRelease currentStreamServiceSettings = obs_service_get_settings(currentStreamService);
OBSDataAutoRelease newStreamServiceSettings = obs_data_create();
obs_data_apply(newStreamServiceSettings, currentStreamServiceSettings);
obs_data_apply(newStreamServiceSettings, requestedStreamServiceSettings);
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);
// TODO: Check service type here, instead of relying on service creation to fail.
if (!newStreamService)
return RequestResult::Error(RequestStatus::StreamServiceCreationFailed, "Creating the stream service with the requested streamServiceType failed. It may be an invalid type.");
obs_frontend_set_streaming_service(newStreamService);
}
obs_frontend_save_streaming_service();
return RequestResult::Success();
}

View File

@ -0,0 +1,36 @@
#include "RequestHandler.h"
#include "../plugin-macros.generated.h"
RequestResult RequestHandler::GetStreamStatus(const Request& request)
{
json responseData;
OBSOutputAutoRelease streamOutput = obs_frontend_get_streaming_output();
responseData["outputActive"] = obs_output_active(streamOutput);
responseData["outputTimecode"] = Utils::Obs::StringHelper::GetOutputTimecodeString(streamOutput);
responseData["outputDuration"] = Utils::Obs::NumberHelper::GetOutputDuration(streamOutput);
return RequestResult::Success(responseData);
}
RequestResult RequestHandler::StartStream(const Request& request)
{
if (obs_frontend_streaming_active())
return RequestResult::Error(RequestStatus::StreamRunning);
// TODO: Call signal directly to perform blocking wait
obs_frontend_streaming_start();
return RequestResult::Success();
}
RequestResult RequestHandler::StopStream(const Request& request)
{
if (!obs_frontend_streaming_active())
return RequestResult::Error(RequestStatus::StreamNotRunning);
// TODO: Call signal directly to perform blocking wait
obs_frontend_streaming_stop();
return RequestResult::Success();
}

View File

@ -118,5 +118,7 @@ namespace RequestStatus {
DirectoryCreationFailed = 706,
// The combination of request parameters cannot be used to perform an action
CannotAct = 707,
// Creation of a new stream service failed
StreamServiceCreationFailed = 708,
};
};

View File

@ -1,4 +1,9 @@
#include <inttypes.h>
#include <memory>
#include <string>
#include <stdexcept>
#include <obs-frontend-api.h>
#include <util/util_uint64.h>
#include "Utils.h"
#include "../obs-websocket.h"
@ -6,6 +11,17 @@
#define CASE(x) case x: return #x;
template<typename ... Args>
std::string string_format( const std::string& format, Args ... args )
{
int size_s = std::snprintf( nullptr, 0, format.c_str(), args ... ) + 1;
if( size_s <= 0 ){ throw std::runtime_error( "Error during formatting." ); }
auto size = static_cast<size_t>( size_s );
auto buf = std::make_unique<char[]>( size );
std::snprintf( buf.get(), size, format.c_str(), args ... );
return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
}
std::vector<std::string> ConvertStringArray(char **array)
{
std::vector<std::string> ret;
@ -107,6 +123,40 @@ std::string Utils::Obs::StringHelper::GetLastReplayBufferFilePath()
return ret;
}
std::string Utils::Obs::StringHelper::GetOutputTimecodeString(obs_output_t *output)
{
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 = (((uint64_t)totalFrames) * frameTimeNs) / 1000000ULL;
uint64_t secs = ms / 1000ULL;
uint64_t minutes = secs / 60ULL;
uint64_t hoursPart = minutes / 60ULL;
uint64_t minutesPart = minutes % 60ULL;
uint64_t secsPart = secs % 60ULL;
uint64_t msPart = ms % 1000ULL;
return string_format("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64 ".%03" PRIu64, hoursPart, minutesPart, secsPart, msPart);
}
uint64_t Utils::Obs::NumberHelper::GetOutputDuration(obs_output_t *output)
{
if (!output || !obs_output_active(output))
return 0;
video_t* video = obs_output_video(output);
uint64_t frameTimeNs = video_output_get_frame_time(video);
int totalFrames = obs_output_get_total_frames(output);
return util_mul_div64(totalFrames, frameTimeNs, 1000000ULL);
//return (((uint64_t)totalFrames) * frameTimeNs) / ;
}
std::vector<std::string> Utils::Obs::ListHelper::GetSceneCollectionList()
{
char** sceneCollections = obs_frontend_get_scene_collections();

View File

@ -38,6 +38,11 @@ namespace Utils {
std::string GetInputMonitorTypeString(obs_source_t *input);
std::string GetMediaInputStateString(obs_source_t *input);
std::string GetLastReplayBufferFilePath();
std::string GetOutputTimecodeString(obs_output_t *output);
}
namespace NumberHelper {
uint64_t GetOutputDuration(obs_output_t *output);
}
namespace ListHelper {