events: decouple events encoding from event emit

This commit is contained in:
Stéphane Lepin 2020-01-28 18:37:25 +01:00
parent 06c29b7810
commit 46068573c5
10 changed files with 169 additions and 46 deletions

View File

@ -48,6 +48,7 @@ set(obs-websocket_SOURCES
src/Utils.cpp
src/rpc/RpcRequest.cpp
src/rpc/RpcResponse.cpp
src/rpc/RpcEvent.cpp
src/protocol/OBSRemoteProtocol.cpp
src/forms/settings-dialog.cpp)
@ -61,6 +62,7 @@ set(obs-websocket_HEADERS
src/Utils.h
src/rpc/RpcRequest.h
src/rpc/RpcResponse.h
src/rpc/RpcEvent.h
src/protocol/OBSRemoteProtocol.h
src/forms/settings-dialog.h)
@ -180,8 +182,8 @@ if(UNIX AND NOT APPLE)
install(TARGETS obs-websocket
LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/obs-plugins")
# Dirty fix for Ubuntu
install(TARGETS obs-websocket
LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/${UNAME_MACHINE}-linux-gnu/obs-plugins")
install(TARGETS obs-websocket
LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/${UNAME_MACHINE}-linux-gnu/obs-plugins")
install(FILES ${locale_files}
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/obs/obs-plugins/obs-websocket/locale")

View File

@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see <https://www.gnu.org/licenses/>
*/
#include <inttypes.h>
#include <QtWidgets/QMainWindow>
#include <QtCore/QDir>
#include <QtCore/QUrl>
@ -822,3 +823,17 @@ void Utils::PauseRecording(bool pause)
pauseRecording(pause);
}
QString Utils::nsToTimestamp(uint64_t ns)
{
uint64_t ms = ns / 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 QString::asprintf("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64 ".%03" PRIu64, hoursPart, minutesPart, secsPart, msPart);
}

View File

@ -86,4 +86,6 @@ class Utils {
static bool RecordingPauseSupported();
static bool RecordingPaused();
static void PauseRecording(bool pause);
static QString nsToTimestamp(uint64_t ns);
};

View File

@ -23,27 +23,15 @@
#include <QtWidgets/QPushButton>
#include "Config.h"
#include "Utils.h"
#include "WSEvents.h"
#include "obs-websocket.h"
#include "Config.h"
#include "Utils.h"
#include "rpc/RpcEvent.h"
#define STATUS_INTERVAL 2000
QString nsToTimestamp(uint64_t ns) {
uint64_t ms = ns / 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 QString::asprintf("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64 ".%03" PRIu64, hoursPart, minutesPart, secsPart, msPart);
}
const char* sourceTypeToString(obs_source_type type) {
switch (type) {
case OBS_SOURCE_TYPE_INPUT:
@ -252,28 +240,11 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
void WSEvents::broadcastUpdate(const char* updateType,
obs_data_t* additionalFields = nullptr)
{
OBSDataAutoRelease update = obs_data_create();
obs_data_set_string(update, "update-type", updateType);
uint64_t streamTime = getStreamingTime();
uint64_t recordingTime = getStreamingTime();
RpcEvent event(QString(updateType), streamTime, recordingTime, additionalFields);
if (obs_frontend_streaming_active()) {
QString streamingTimecode = getStreamingTimecode();
obs_data_set_string(update, "stream-timecode", streamingTimecode.toUtf8().constData());
}
if (obs_frontend_recording_active()) {
QString recordingTimecode = getRecordingTimecode();
obs_data_set_string(update, "rec-timecode", recordingTimecode.toUtf8().constData());
}
if (additionalFields)
obs_data_apply(update, additionalFields);
QString json = obs_data_get_json(update);
_srv->broadcast(json.toStdString());
if (GetConfig()->DebugEnabled) {
blog(LOG_INFO, "Update << '%s'", json.toUtf8().constData());
}
_srv->broadcast(event);
}
void WSEvents::connectSourceSignals(obs_source_t* source) {
@ -410,11 +381,11 @@ uint64_t WSEvents::getRecordingTime() {
}
QString WSEvents::getStreamingTimecode() {
return nsToTimestamp(getStreamingTime());
return Utils::nsToTimestamp(getStreamingTime());
}
QString WSEvents::getRecordingTimecode() {
return nsToTimestamp(getRecordingTime());
return Utils::nsToTimestamp(getRecordingTime());
}
/**

View File

@ -125,8 +125,15 @@ void WSServer::stop()
blog(LOG_INFO, "server stopped successfully");
}
void WSServer::broadcast(std::string message)
void WSServer::broadcast(const RpcEvent& event)
{
OBSRemoteProtocol protocol;
std::string message = protocol.encodeEvent(event);
if (GetConfig()->DebugEnabled) {
blog(LOG_INFO, "Update << '%s'", message.c_str());
}
QMutexLocker locker(&_clMutex);
for (connection_hdl hdl : _connections) {
if (GetConfig()->AuthRequired) {

View File

@ -30,8 +30,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <websocketpp/server.hpp>
#include "ConnectionProperties.h"
#include "WSRequestHandler.h"
#include "rpc/RpcEvent.h"
using websocketpp::connection_hdl;
@ -46,7 +46,7 @@ public:
virtual ~WSServer();
void start(quint16 port);
void stop();
void broadcast(std::string message);
void broadcast(const RpcEvent& event);
QThreadPool* threadPool() {
return &_threadPool;
}

View File

@ -16,8 +16,12 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see <https://www.gnu.org/licenses/>
*/
#include <inttypes.h>
#include "OBSRemoteProtocol.h"
#include "../WSRequestHandler.h"
#include "../rpc/RpcEvent.h"
#include "../Utils.h"
std::string OBSRemoteProtocol::processMessage(WSRequestHandler& requestHandler, std::string message)
{
@ -56,7 +60,33 @@ std::string OBSRemoteProtocol::processMessage(WSRequestHandler& requestHandler,
return std::string();
}
std::string OBSRemoteProtocol::buildResponse(QString messageId, QString status, obs_data_t* fields) {
std::string OBSRemoteProtocol::encodeEvent(const RpcEvent& event)
{
OBSDataAutoRelease eventData = obs_data_create();
OBSData additionalFields = event.fields();
if (additionalFields) {
obs_data_apply(eventData, additionalFields);
}
QString updateType = event.updateType();
obs_data_set_string(eventData, "update-type", updateType.toUtf8().constData());
if (obs_frontend_streaming_active()) {
QString streamingTimecode = Utils::nsToTimestamp(event.streamTime());
obs_data_set_string(eventData, "stream-timecode", streamingTimecode.toUtf8().constData());
}
if (obs_frontend_recording_active()) {
QString recordingTimecode = Utils::nsToTimestamp(event.recordingTime());
obs_data_set_string(eventData, "rec-timecode", recordingTimecode.toUtf8().constData());
}
return std::string(obs_data_get_json(eventData));
}
std::string OBSRemoteProtocol::buildResponse(QString messageId, QString status, obs_data_t* fields)
{
OBSDataAutoRelease response = obs_data_create();
if (!messageId.isNull()) {
obs_data_set_string(response, "message-id", messageId.toUtf8().constData());
@ -71,11 +101,13 @@ std::string OBSRemoteProtocol::buildResponse(QString messageId, QString status,
return responseString;
}
std::string OBSRemoteProtocol::successResponse(QString messageId, obs_data_t* fields) {
std::string OBSRemoteProtocol::successResponse(QString messageId, obs_data_t* fields)
{
return buildResponse(messageId, "ok", fields);
}
std::string OBSRemoteProtocol::errorResponse(QString messageId, QString errorMessage, obs_data_t* additionalFields) {
std::string OBSRemoteProtocol::errorResponse(QString messageId, QString errorMessage, obs_data_t* additionalFields)
{
OBSDataAutoRelease fields = obs_data_create();
if (additionalFields) {
obs_data_apply(fields, additionalFields);

View File

@ -23,11 +23,13 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <QtCore/QString>
class WSRequestHandler;
class RpcEvent;
class OBSRemoteProtocol
{
public:
std::string processMessage(WSRequestHandler& requestHandler, std::string message);
std::string encodeEvent(const RpcEvent& event);
private:
std::string buildResponse(QString messageId, QString status, obs_data_t* fields = nullptr);

47
src/rpc/RpcEvent.cpp Normal file
View File

@ -0,0 +1,47 @@
/*
obs-websocket
Copyright (C) 2016-2020 Stéphane Lepin <stephane.lepin@gmail.com>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <https://www.gnu.org/licenses/>
*/
#include "RpcEvent.h"
RpcEvent::RpcEvent(const QString& updateType, uint64_t streamTime, uint64_t recordingTime, obs_data_t* fields) :
_updateType(updateType),
_streamTime(streamTime),
_recordingTime(recordingTime),
_fields(fields)
{
}
const QString& RpcEvent::updateType() const
{
return _updateType;
}
const uint64_t RpcEvent::streamTime() const
{
return _streamTime;
}
const uint64_t RpcEvent::recordingTime() const
{
return _recordingTime;
}
const OBSData RpcEvent::fields() const
{
return OBSData(_fields);
}

45
src/rpc/RpcEvent.h Normal file
View File

@ -0,0 +1,45 @@
/*
obs-websocket
Copyright (C) 2016-2020 Stéphane Lepin <stephane.lepin@gmail.com>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <https://www.gnu.org/licenses/>
*/
#pragma once
#include <obs-data.h>
#include <QtCore/QString>
#include "../obs-websocket.h"
class RpcEvent
{
public:
explicit RpcEvent(
const QString& updateType,
uint64_t streamTime, uint64_t recordingTime,
obs_data_t* fields = nullptr
);
const QString& updateType() const;
const uint64_t streamTime() const;
const uint64_t recordingTime() const;
const OBSData fields() const;
private:
QString _updateType;
uint64_t _streamTime;
uint64_t _recordingTime;
OBSDataAutoRelease _fields;
};