This commit is contained in:
Palakis 2017-02-26 19:46:09 +01:00
parent 4141983ccd
commit d1c19382a1
6 changed files with 259 additions and 35 deletions

View File

@ -11,8 +11,12 @@ The protocol in general is based on the OBS Remote protocol created by Bill Hami
- [Event Types](#event-types)
- ["SwitchScenes"](#switchscenes)
- ["ScenesChanged"](#sceneschanged)
- ["SceneCollectionChanged"](#scenecollectionchanged)
- ["SceneCollectionListChanged"](#scenecollectionlistchanged)
- ["SwitchTransition"](#switchtransition)
- ["TransitionListChanged"](#transitionlistchanged)
- ["ProfileChanged"](#profilechanged)
- ["ProfileListChanged"](#profilelistchanged)
- ["StreamStarting"](#streamstarting)
- ["StreamStarted"](#streamstarted)
- ["StreamStopping"](#streamstopping)
@ -45,6 +49,12 @@ The protocol in general is based on the OBS Remote protocol created by Bill Hami
- ["ToggleMute"](#togglemute)
- ["SetSceneItemPosition"](#setsceneitemposition)
- ["SetSceneItemTransform"](#setsceneitemtransform)
- ["SetCurrentSceneCollection"](#setcurrentscenecollection)
- ["GetCurrentSceneCollection"](#getcurrentscenecollection)
- ["ListSceneCollections"](#listscenecollections)
- ["SetCurrentProfile"](#setcurrentprofile)
- ["GetCurrentProfile"](#getcurrentprofile)
- ["ListProfiles"](#listprofiles)
* [Authentication](#authentication)
## Events
@ -67,6 +77,16 @@ The scene list has been modified (Scenes have been added, removed, or renamed).
---
#### "SceneCollectionChanged"
Triggered when switching to another scene collection or when renaming the current scene collection.
---
#### "SceneCollectionListChanged"
Triggered when a scene collection is created, added, renamed or removed.
---
#### "SwitchTransition"
The active transition has been changed.
- **transition-name** (string) : The name of the active transition.
@ -78,6 +98,16 @@ The list of available transitions has been modified (Transitions have been added
---
#### "ProfileChanged"
Triggered when switching to another profile or when renaming the current profile.
---
#### "ProfileListChanged"
Triggered when a profile is created, added, renamed or removed.
---
#### "StreamStarting"
A request to start streaming has been issued.
- **preview-only** (bool) : Always false.
@ -390,6 +420,66 @@ __Response__ : OK if specified item exists, error otherwise.
---
#### "SetCurrentSceneCollection"
Change the current scene collection.
__Request fields__ :
- **"sc-name"** (string) : name of the desired scene collection
__Response__ : OK if scene collection exists, error otherwise.
---
#### "GetCurrentSceneCollection"
Get the name of the current scene collection.
__Request fields__ : none
__Response__ : OK with these additional fields :
- **"sc-name"** (string) : name of the current scene collection
---
#### "ListSceneCollections"
Get a list of available scene collections.
__Request fields__ : none
__Response__ : OK with these additional fields :
- **"scene-collections"** (array of objects) : names of available scene collections
---
#### "SetCurrentProfile"
Change the current profile.
__Request fields__ :
- **"profile-name"** (string) : name of the desired profile
__Response__ : OK if profile exists, error otherwise.
---
#### "GetCurrentProfile"
Get the name of the current profile.
__Request fields__ : none
__Response__ : OK with these additional fields :
- **"profile-name"** (string) : name of the current profile
---
#### "ListProfiles"
Get a list of available profiles.
__Request fields__ : none
__Response__ : OK with the additional fields :
- **"profiles"** (array of objects) : names of available profiles
---
### Authentication
A call to `GetAuthRequired` gives the client two elements :
- A challenge : a random string that will be used to generate the auth response

View File

@ -18,6 +18,31 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "Utils.h"
#include <obs-frontend-api.h>
#include "obs-websocket.h"
obs_data_array_t* string_list_to_array(char** strings, char* key)
{
if (!strings)
return obs_data_array_create();
obs_data_array_t *list = obs_data_array_create();
char* value = "";
for (int i = 0; value != nullptr; i++)
{
value = strings[i];
obs_data_t *item = obs_data_create();
obs_data_set_string(item, key, value);
if (value)
obs_data_array_push_back(list, item);
obs_data_release(item);
}
return list;
}
obs_data_array_t* Utils::GetSceneItems(obs_source_t *source) {
obs_data_array_t *items = obs_data_array_create();
@ -152,6 +177,24 @@ obs_data_t* Utils::GetSceneData(obs_source *source) {
return sceneData;
}
obs_data_array_t* Utils::GetSceneCollections()
{
char** scene_collections = obs_frontend_get_scene_collections();
obs_data_array_t *list = string_list_to_array(scene_collections, "sc-name");
bfree(scene_collections);
return list;
}
obs_data_array_t* Utils::GetProfiles()
{
char** profiles = obs_frontend_get_profiles();
obs_data_array_t *list = string_list_to_array(profiles, "profile-name");
bfree(profiles);
return list;
}
const char* Utils::OBSVersionString() {
uint32_t version = obs_get_version();

View File

@ -33,6 +33,9 @@ class Utils
static obs_data_array_t* GetScenes();
static obs_data_t* GetSceneData(obs_source *source);
static obs_data_array_t* GetSceneCollections();
static obs_data_array_t* GetProfiles();
static const char* OBSVersionString();
};

View File

@ -22,7 +22,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include "WSEvents.h"
WSEvents::WSEvents(WSServer *srv) {
WSEvents::WSEvents(WSServer *srv)
{
_srv = srv;
obs_frontend_add_event_callback(WSEvents::FrontendEventHandler, this);
@ -34,7 +35,8 @@ WSEvents::WSEvents(WSServer *srv) {
_rec_starttime = 0;
}
WSEvents::~WSEvents() {
WSEvents::~WSEvents()
{
obs_frontend_remove_event_callback(WSEvents::FrontendEventHandler, this);
}
@ -47,49 +49,78 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void *private
// TODO : implement SourceChanged, SourceOrderChanged and RepopulateSources
if (event == OBS_FRONTEND_EVENT_SCENE_CHANGED) {
if (event == OBS_FRONTEND_EVENT_SCENE_CHANGED)
{
owner->OnSceneChange();
}
else if (event == OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED) {
else if (event == OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED)
{
owner->OnSceneListChange();
}
else if (event == OBS_FRONTEND_EVENT_TRANSITION_CHANGED) {
else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED)
{
owner->OnSceneCollectionChange();
}
else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED)
{
owner->OnSceneCollectionListChange();
}
else if (event == OBS_FRONTEND_EVENT_TRANSITION_CHANGED)
{
owner->OnTransitionChange();
}
else if (event == OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED) {
else if (event == OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED)
{
owner->OnTransitionListChange();
}
else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTING) {
else if (event == OBS_FRONTEND_EVENT_PROFILE_CHANGED)
{
owner->OnProfileChange();
}
else if (event == OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED)
{
owner->OnProfileListChange();
}
else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTING)
{
owner->OnStreamStarting();
}
else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTED) {
else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTED)
{
owner->OnStreamStarted();
}
else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPING) {
else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPING)
{
owner->OnStreamStopping();
}
else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPED) {
else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPED)
{
owner->OnStreamStopped();
}
else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTING) {
else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTING)
{
owner->OnRecordingStarting();
}
else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTED) {
else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTED)
{
owner->OnRecordingStarted();
}
else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPING) {
else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPING)
{
owner->OnRecordingStopping();
}
else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPED) {
else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPED)
{
owner->OnRecordingStopped();
}
else if (event == OBS_FRONTEND_EVENT_EXIT) {
obs_frontend_save();
else if (event == OBS_FRONTEND_EVENT_EXIT)
{
owner->OnExit();
}
}
void WSEvents::broadcastUpdate(const char *updateType, obs_data_t *additionalFields = NULL) {
void WSEvents::broadcastUpdate(const char *updateType, obs_data_t *additionalFields = NULL)
{
obs_data_t *update = obs_data_create();
obs_data_set_string(update, "update-type", updateType);
@ -102,19 +133,22 @@ void WSEvents::broadcastUpdate(const char *updateType, obs_data_t *additionalFie
obs_data_release(update);
}
void WSEvents::OnSceneChange() {
void WSEvents::OnSceneChange()
{
// Implements an existing update type from bilhamil's OBS Remote
// Default behavior : get the new scene from the running transition
obs_source_t *transition = obs_frontend_get_current_transition();
obs_source_t *new_scene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_B);
if (!new_scene) {
if (!new_scene)
{
obs_source_release(transition);
return;
}
const char *scene_name = obs_source_get_name(new_scene);
if (!scene_name) {
if (!scene_name)
{
// Fallback behaviour : get the new scene straight from the API
obs_source_release(new_scene);
new_scene = obs_frontend_get_current_scene();
@ -134,11 +168,23 @@ void WSEvents::OnSceneChange() {
obs_source_release(transition);
}
void WSEvents::OnSceneListChange() {
void WSEvents::OnSceneListChange()
{
broadcastUpdate("ScenesChanged");
}
void WSEvents::OnTransitionChange() {
void WSEvents::OnSceneCollectionChange()
{
broadcastUpdate("SceneCollectionChanged");
}
void WSEvents::OnSceneCollectionListChange()
{
broadcastUpdate("SceneCollectionListChanged");
}
void WSEvents::OnTransitionChange()
{
obs_source_t *transition = obs_frontend_get_current_transition();
const char *transition_name = obs_source_get_name(transition);
@ -151,11 +197,23 @@ void WSEvents::OnTransitionChange() {
obs_source_release(transition);
}
void WSEvents::OnTransitionListChange() {
void WSEvents::OnTransitionListChange()
{
broadcastUpdate("TransitionListChanged");
}
void WSEvents::OnStreamStarting() {
void WSEvents::OnProfileChange()
{
broadcastUpdate("ProfileChanged");
}
void WSEvents::OnProfileListChange()
{
broadcastUpdate("ProfileListChanged");
}
void WSEvents::OnStreamStarting()
{
// Implements an existing update type from bilhamil's OBS Remote
obs_data_t *data = obs_data_create();
obs_data_set_bool(data, "preview-only", false);
@ -165,14 +223,16 @@ void WSEvents::OnStreamStarting() {
obs_data_release(data);
}
void WSEvents::OnStreamStarted() {
void WSEvents::OnStreamStarted()
{
// New update type specific to OBS Studio
_stream_starttime = os_gettime_ns();
_lastBytesSent = 0;
broadcastUpdate("StreamStarted");
}
void WSEvents::OnStreamStopping() {
void WSEvents::OnStreamStopping()
{
// Implements an existing update type from bilhamil's OBS Remote
obs_data_t *data = obs_data_create();
obs_data_set_bool(data, "preview-only", false);
@ -182,40 +242,47 @@ void WSEvents::OnStreamStopping() {
obs_data_release(data);
}
void WSEvents::OnStreamStopped() {
void WSEvents::OnStreamStopped()
{
// New update type specific to OBS Studio
_stream_starttime = 0;
broadcastUpdate("StreamStopped");
}
void WSEvents::OnRecordingStarting() {
void WSEvents::OnRecordingStarting()
{
// New update type specific to OBS Studio
broadcastUpdate("RecordingStarting");
}
void WSEvents::OnRecordingStarted() {
void WSEvents::OnRecordingStarted()
{
// New update type specific to OBS Studio
_rec_starttime = os_gettime_ns();
broadcastUpdate("RecordingStarted");
}
void WSEvents::OnRecordingStopping() {
void WSEvents::OnRecordingStopping()
{
// New update type specific to OBS Studio
broadcastUpdate("RecordingStopping");
}
void WSEvents::OnRecordingStopped() {
void WSEvents::OnRecordingStopped()
{
// New update type specific to OBS Studio
_rec_starttime = 0;
broadcastUpdate("RecordingStopped");
}
void WSEvents::OnExit() {
void WSEvents::OnExit()
{
// New update type specific to OBS Studio
broadcastUpdate("Exiting");
}
void WSEvents::StreamStatus() {
void WSEvents::StreamStatus()
{
bool streaming_active = obs_frontend_streaming_active();
bool recording_active = obs_frontend_recording_active();

View File

@ -46,10 +46,15 @@ class WSEvents : public QObject
void OnSceneChange();
void OnSceneListChange();
void OnSceneCollectionChange();
void OnSceneCollectionListChange();
void OnTransitionChange();
void OnTransitionListChange();
void OnProfileChange();
void OnProfileListChange();
void OnStreamStarting();
void OnStreamStarted();
void OnStreamStopping();

View File

@ -564,7 +564,15 @@ void WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandler *owner)
void WSRequestHandler::HandleListSceneCollections(WSRequestHandler *owner)
{
// TODO
obs_data_array_t *scene_collections = Utils::GetSceneCollections();
obs_data_t *response = obs_data_create();
obs_data_set_array(response, "scene-collections", scene_collections);
owner->SendOKResponse(response);
obs_data_release(response);
obs_data_array_release(scene_collections);
}
void WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler *owner)
@ -595,7 +603,15 @@ void WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler *owner)
void WSRequestHandler::HandleListProfiles(WSRequestHandler *owner)
{
// TODO
obs_data_array_t *profiles = Utils::GetProfiles();
obs_data_t *response = obs_data_create();
obs_data_set_array(response, "profiles", profiles);
owner->SendOKResponse(response);
obs_data_release(response);
obs_data_array_release(profiles);
}
void WSRequestHandler::ErrNotImplemented(WSRequestHandler *owner)