mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
base, lib: Add ability to call obs-websocket requests via plugin API
**Increments Plugin API Version** Adds functions: - `obs_websocket_get_api_version()` - Gets the current obs-websocket plugin API version - `obs_websocket_call_request()` - Calls an obs-websocket request via the plugin API Adds structs: - `obs_websocket_request_response`
This commit is contained in:
parent
3303acfcca
commit
d85c86e3a0
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
obs-websocket
|
obs-websocket
|
||||||
Copyright (C) 2016-2021 Stephane Lepin <stephane.lepin@gmail.com>
|
Copyright (C) 2016-2021 Stephane Lepin <stephane.lepin@gmail.com>
|
||||||
Copyright (C) 2020-2021 Kyle Manning <tt2468@gmail.com>
|
Copyright (C) 2020-2022 Kyle Manning <tt2468@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -22,7 +22,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include <obs.h>
|
#include <obs.h>
|
||||||
|
|
||||||
#define OBS_WEBSOCKET_API_VERSION 1
|
#define OBS_WEBSOCKET_API_VERSION 2
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -31,12 +31,22 @@ extern "C" {
|
|||||||
typedef void* obs_websocket_vendor;
|
typedef void* obs_websocket_vendor;
|
||||||
typedef void (*obs_websocket_request_callback_function)(obs_data_t*, obs_data_t*, void*);
|
typedef void (*obs_websocket_request_callback_function)(obs_data_t*, obs_data_t*, void*);
|
||||||
|
|
||||||
|
struct obs_websocket_request_response {
|
||||||
|
uint status_code;
|
||||||
|
char *comment;
|
||||||
|
char *response_data; // JSON string, because obs_data_t* only supports array<object>, so conversions would break API.
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ==================== INTERNAL DEFINITIONS ==================== */
|
||||||
|
|
||||||
struct obs_websocket_request_callback {
|
struct obs_websocket_request_callback {
|
||||||
obs_websocket_request_callback_function callback;
|
obs_websocket_request_callback_function callback;
|
||||||
void *priv_data;
|
void *priv_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline proc_handler_t *ph;
|
inline proc_handler_t *_ph;
|
||||||
|
|
||||||
|
/* ==================== INTERNAL API FUNCTIONS ==================== */
|
||||||
|
|
||||||
static inline proc_handler_t *obs_websocket_get_ph(void)
|
static inline proc_handler_t *obs_websocket_get_ph(void)
|
||||||
{
|
{
|
||||||
@ -52,30 +62,98 @@ static inline proc_handler_t *obs_websocket_get_ph(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool obs_websocket_run_simple_proc(obs_websocket_vendor vendor, const char *proc_name, calldata_t *cd)
|
static inline bool obs_websocket_ensure_ph(void)
|
||||||
{
|
{
|
||||||
if (!ph || !vendor || !proc_name || !strlen(proc_name) || !cd)
|
if (!_ph)
|
||||||
|
_ph = obs_websocket_get_ph();
|
||||||
|
return _ph != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool obs_websocket_vendor_run_simple_proc(obs_websocket_vendor vendor, const char *proc_name, calldata_t *cd)
|
||||||
|
{
|
||||||
|
if (!obs_websocket_ensure_ph())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!vendor || !proc_name || !strlen(proc_name) || !cd)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
calldata_set_ptr(cd, "vendor", vendor);
|
calldata_set_ptr(cd, "vendor", vendor);
|
||||||
|
|
||||||
proc_handler_call(ph, proc_name, cd);
|
proc_handler_call(_ph, proc_name, cd);
|
||||||
return calldata_bool(cd, "success");
|
return calldata_bool(cd, "success");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ALWAYS CALL VIA `obs_module_post_load()` CALLBACK!
|
/* ==================== GENERAL API FUNCTIONS ==================== */
|
||||||
|
|
||||||
|
// Gets the API version built with the obs-websocket plugin
|
||||||
|
static inline uint obs_websocket_get_api_version(void)
|
||||||
|
{
|
||||||
|
if (!obs_websocket_ensure_ph())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
calldata_t cd = {0};
|
||||||
|
|
||||||
|
if (!proc_handler_call(_ph, "get_api_version", &cd))
|
||||||
|
return 1; // API v1 does not include get_api_version
|
||||||
|
|
||||||
|
uint ret = calldata_int(&cd, "version");
|
||||||
|
|
||||||
|
calldata_free(&cd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calls an obs-websocket request. Free response with `obs_websocket_request_response_free()`
|
||||||
|
static inline obs_websocket_request_response *obs_websocket_call_request(const char *request_type, obs_data_t *request_data = NULL)
|
||||||
|
{
|
||||||
|
if (!obs_websocket_ensure_ph())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
const char *request_data_string = NULL;
|
||||||
|
if (request_data)
|
||||||
|
request_data_string = obs_data_get_json(request_data);
|
||||||
|
|
||||||
|
calldata_t cd = {0};
|
||||||
|
|
||||||
|
calldata_set_string(&cd, "request_type", request_type);
|
||||||
|
calldata_set_string(&cd, "request_data", request_data_string);
|
||||||
|
|
||||||
|
proc_handler_call(_ph, "call_request", &cd);
|
||||||
|
|
||||||
|
auto ret = (struct obs_websocket_request_response*)calldata_ptr(&cd, "response");
|
||||||
|
|
||||||
|
calldata_free(&cd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free a request response object returned by `obs_websocket_call_request()`
|
||||||
|
static inline void obs_websocket_request_response_free(struct obs_websocket_request_response *response)
|
||||||
|
{
|
||||||
|
if (!response)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (response->comment)
|
||||||
|
bfree(response->comment);
|
||||||
|
if (response->response_data)
|
||||||
|
bfree(response->response_data);
|
||||||
|
bfree(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================== VENDOR API FUNCTIONS ==================== */
|
||||||
|
|
||||||
|
// ALWAYS CALL ONLY VIA `obs_module_post_load()` CALLBACK!
|
||||||
// Registers a new "vendor" (Example: obs-ndi)
|
// Registers a new "vendor" (Example: obs-ndi)
|
||||||
static inline obs_websocket_vendor obs_websocket_register_vendor(const char *vendor_name)
|
static inline obs_websocket_vendor obs_websocket_register_vendor(const char *vendor_name)
|
||||||
{
|
{
|
||||||
ph = obs_websocket_get_ph();
|
if (!obs_websocket_ensure_ph())
|
||||||
if (!ph)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
calldata_t cd = {0};
|
calldata_t cd = {0};
|
||||||
|
|
||||||
calldata_set_string(&cd, "name", vendor_name);
|
calldata_set_string(&cd, "name", vendor_name);
|
||||||
|
|
||||||
proc_handler_call(ph, "vendor_register", &cd);
|
proc_handler_call(_ph, "vendor_register", &cd);
|
||||||
obs_websocket_vendor ret = calldata_ptr(&cd, "vendor");
|
obs_websocket_vendor ret = calldata_ptr(&cd, "vendor");
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
@ -94,7 +172,7 @@ static inline bool obs_websocket_vendor_register_request(obs_websocket_vendor ve
|
|||||||
calldata_set_string(&cd, "type", request_type);
|
calldata_set_string(&cd, "type", request_type);
|
||||||
calldata_set_ptr(&cd, "callback", &cb);
|
calldata_set_ptr(&cd, "callback", &cb);
|
||||||
|
|
||||||
bool success = obs_websocket_run_simple_proc(vendor, "vendor_request_register", &cd);
|
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_register", &cd);
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@ -107,7 +185,7 @@ static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor
|
|||||||
|
|
||||||
calldata_set_string(&cd, "type", request_type);
|
calldata_set_string(&cd, "type", request_type);
|
||||||
|
|
||||||
bool success = obs_websocket_run_simple_proc(vendor, "vendor_request_unregister", &cd);
|
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_unregister", &cd);
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@ -122,12 +200,14 @@ static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor,
|
|||||||
calldata_set_string(&cd, "type", event_name);
|
calldata_set_string(&cd, "type", event_name);
|
||||||
calldata_set_ptr(&cd, "data", (void*)event_data);
|
calldata_set_ptr(&cd, "data", (void*)event_data);
|
||||||
|
|
||||||
bool success = obs_websocket_run_simple_proc(vendor, "vendor_event_emit", &cd);
|
bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_event_emit", &cd);
|
||||||
calldata_free(&cd);
|
calldata_free(&cd);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==================== END API FUNCTIONS ==================== */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "WebSocketApi.h"
|
#include "WebSocketApi.h"
|
||||||
|
#include "requesthandler/RequestHandler.h"
|
||||||
#include "obs-websocket.h"
|
#include "obs-websocket.h"
|
||||||
|
#include "utils/Json.h"
|
||||||
|
|
||||||
#define RETURN_STATUS(status) { calldata_set_bool(cd, "success", status); return; }
|
#define RETURN_STATUS(status) { calldata_set_bool(cd, "success", status); return; }
|
||||||
#define RETURN_SUCCESS() RETURN_STATUS(true);
|
#define RETURN_SUCCESS() RETURN_STATUS(true);
|
||||||
@ -22,6 +24,8 @@ WebSocketApi::WebSocketApi()
|
|||||||
|
|
||||||
_procHandler = proc_handler_create();
|
_procHandler = proc_handler_create();
|
||||||
|
|
||||||
|
proc_handler_add(_procHandler, "bool get_api_version(out int version)", &get_api_version, nullptr);
|
||||||
|
proc_handler_add(_procHandler, "bool call_request(in string request_type, in string request_data, out ptr response)", &call_request, nullptr);
|
||||||
proc_handler_add(_procHandler, "bool vendor_register(in string name, out ptr vendor)", &vendor_register_cb, this);
|
proc_handler_add(_procHandler, "bool vendor_register(in string name, out ptr vendor)", &vendor_register_cb, this);
|
||||||
proc_handler_add(_procHandler, "bool vendor_request_register(in ptr vendor, in string type, in ptr callback)", &vendor_request_register_cb, this);
|
proc_handler_add(_procHandler, "bool vendor_request_register(in ptr vendor, in string type, in ptr callback)", &vendor_request_register_cb, this);
|
||||||
proc_handler_add(_procHandler, "bool vendor_request_unregister(in ptr vendor, in string type)", &vendor_request_unregister_cb, this);
|
proc_handler_add(_procHandler, "bool vendor_request_unregister(in ptr vendor, in string type)", &vendor_request_unregister_cb, this);
|
||||||
@ -88,6 +92,48 @@ void WebSocketApi::get_ph_cb(void *priv_data, calldata_t *cd)
|
|||||||
RETURN_SUCCESS();
|
RETURN_SUCCESS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebSocketApi::get_api_version(void *, calldata_t *cd)
|
||||||
|
{
|
||||||
|
calldata_set_int(cd, "version", OBS_WEBSOCKET_API_VERSION);
|
||||||
|
|
||||||
|
RETURN_SUCCESS();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketApi::call_request(void *, calldata_t *cd)
|
||||||
|
{
|
||||||
|
const char *request_type = calldata_string(cd, "request_type");
|
||||||
|
const char *request_data = calldata_string(cd, "request_data");
|
||||||
|
|
||||||
|
if (!request_type)
|
||||||
|
RETURN_FAILURE();
|
||||||
|
|
||||||
|
auto response = static_cast<obs_websocket_request_response*>(bzalloc(sizeof(struct obs_websocket_request_response)));
|
||||||
|
if (!response)
|
||||||
|
RETURN_FAILURE();
|
||||||
|
|
||||||
|
json requestData;
|
||||||
|
if (request_data)
|
||||||
|
requestData = json::parse(request_data);
|
||||||
|
|
||||||
|
RequestHandler requestHandler;
|
||||||
|
Request request(request_type, requestData);
|
||||||
|
RequestResult requestResult = requestHandler.ProcessRequest(request);
|
||||||
|
|
||||||
|
response->status_code = (uint)requestResult.StatusCode;
|
||||||
|
if (!requestResult.Comment.empty())
|
||||||
|
response->comment = bstrdup(requestResult.Comment.c_str());
|
||||||
|
if (requestResult.ResponseData.is_object()) {
|
||||||
|
std::string responseData = requestResult.ResponseData.dump();
|
||||||
|
response->response_data = bstrdup(responseData.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
calldata_set_ptr(cd, "response", response);
|
||||||
|
|
||||||
|
blog_debug("[WebSocketApi::call_request] Request %s called, response status code is %u", request_type, response->status_code);
|
||||||
|
|
||||||
|
RETURN_SUCCESS();
|
||||||
|
}
|
||||||
|
|
||||||
void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd)
|
void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd)
|
||||||
{
|
{
|
||||||
auto c = static_cast<WebSocketApi*>(priv_data);
|
auto c = static_cast<WebSocketApi*>(priv_data);
|
||||||
|
@ -33,6 +33,8 @@ class WebSocketApi {
|
|||||||
enum RequestReturnCode PerformVendorRequest(std::string vendorName, std::string requestName, obs_data_t *requestData, obs_data_t *responseData);
|
enum RequestReturnCode PerformVendorRequest(std::string vendorName, std::string requestName, obs_data_t *requestData, obs_data_t *responseData);
|
||||||
|
|
||||||
static void get_ph_cb(void *priv_data, calldata_t *cd);
|
static void get_ph_cb(void *priv_data, calldata_t *cd);
|
||||||
|
static void get_api_version(void *, calldata_t *cd);
|
||||||
|
static void call_request(void *, calldata_t *cd);
|
||||||
static void vendor_register_cb(void *priv_data, calldata_t *cd);
|
static void vendor_register_cb(void *priv_data, calldata_t *cd);
|
||||||
static void vendor_request_register_cb(void *priv_data, calldata_t *cd);
|
static void vendor_request_register_cb(void *priv_data, calldata_t *cd);
|
||||||
static void vendor_request_unregister_cb(void *priv_data, calldata_t *cd);
|
static void vendor_request_unregister_cb(void *priv_data, calldata_t *cd);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user