Initial commit

This commit is contained in:
Stéphane Lepin 2016-10-10 00:33:56 +02:00
commit 61be350bef
6 changed files with 331 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/build/
/build32/
/build64/

33
CMakeLists.txt Normal file
View File

@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.5)
project(obs-websocket)
set(CMAKE_PREFIX_PATH "${QTDIR}")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
include(external/FindLibObs.cmake)
find_package(LibObs REQUIRED)
find_package(Qt5Core REQUIRED)
find_package(Qt5WebSockets REQUIRED)
set(obs-websocket_SOURCES
obs-websocket.cpp
WSServer.cpp)
set(obs-websocket_HEADERS
WSServer.h)
add_library(obs-websocket MODULE
${obs-websocket_SOURCES}
${obs-websocket_HEADERS})
qt5_use_modules(obs-websocket
Core WebSockets)
include_directories(
"${LIBOBS_INCLUDE_DIR}/../UI/obs-frontend-api"
${Qt5Core_INCLUDES}
${Qt5WebSockets_INCLUDES})
target_link_libraries(obs-websocket
libobs
${OBS_FRONTEND_LIB}
Qt5::Core
Qt5::WebSockets)

92
WSServer.cpp Normal file
View File

@ -0,0 +1,92 @@
#include "WSServer.h"
#include <QtWebSockets/QWebSocketServer>
#include <QtWebSockets/QWebSocket>
#include <QtCore/QDebug>
#include <obs-frontend-api.h>
QT_USE_NAMESPACE
WSServer::WSServer(quint16 port, QObject *parent) :
QObject(parent),
_wsServer(Q_NULLPTR),
_clients()
{
_wsServer = new QWebSocketServer(
QStringLiteral("OBS Websocket API"),
QWebSocketServer::NonSecureMode,
this);
bool serverStarted = _wsServer->listen(QHostAddress::Any, port);
if (serverStarted) {
connect(_wsServer, &QWebSocketServer::newConnection, this, &WSServer::onNewConnection);
}
}
WSServer::~WSServer()
{
_wsServer->close();
qDeleteAll(_clients.begin(), _clients.end());
}
void WSServer::broadcast(QString message)
{
Q_FOREACH(QWebSocket *pClient, _clients) {
pClient->sendTextMessage(message);
}
}
void WSServer::onNewConnection()
{
QWebSocket *pSocket = _wsServer->nextPendingConnection();
blog(LOG_INFO, "[obs-websockets] new client connected from %s:%d", pSocket->peerAddress().toString().toStdString(), pSocket->peerPort());
connect(pSocket, &QWebSocket::textMessageReceived, this, &WSServer::processTextMessage);
connect(pSocket, &QWebSocket::disconnected, this, &WSServer::socketDisconnected);
_clients << pSocket;
}
void WSServer::processTextMessage(QString textMessage) {
QWebSocket *pSender = qobject_cast<QWebSocket *>(sender());
if (pSender) {
const char *msg = textMessage.toLocal8Bit();
blog(LOG_INFO, "[obs-websockets] new message : %s", msg);
obs_data_t *request = obs_data_create_from_json(msg);
if (!request) {
blog(LOG_ERROR, "[obs-websockets] invalid JSON payload for '%s'", msg);
}
const char *requestType = obs_data_get_string(request, "request");
if (strcmp(requestType, "scene_change") == 0) {
const char *sceneName = obs_data_get_string(request, "switch_to");
blog(LOG_INFO, "[obs-websockets] processing scene change request to %s", sceneName);
obs_source_t *source = obs_get_source_by_name(sceneName);
if (source) {
obs_frontend_set_current_scene(source);
}
else {
blog(LOG_ERROR, "[obs-websockets] requested scene '%s' doesn't exist !", sceneName);
}
}
obs_data_release(request);
}
}
void WSServer::socketDisconnected()
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
blog(LOG_INFO, "[obs-websockets] client %s:%d disconnected", pClient->peerAddress().toString().toStdString(), pClient->peerPort());
if (pClient) {
_clients.removeAll(pClient);
pClient->deleteLater();
}
}

30
WSServer.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef WSSERVER_H
#define WSSERVER_H
#include <QtCore/QObject>
#include <QtCore/QList>
#include <QtCore/QByteArray>
QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
QT_FORWARD_DECLARE_CLASS(QWebSocket)
class WSServer : public QObject
{
Q_OBJECT
public:
explicit WSServer(quint16 port, QObject *parent = Q_NULLPTR);
virtual ~WSServer();
void broadcast(QString message);
private Q_SLOTS:
void onNewConnection();
void processTextMessage(QString textMessage);
void socketDisconnected();
private:
QWebSocketServer *_wsServer;
QList<QWebSocket *> _clients;
};
#endif // WSSERVER_H

107
external/FindLibObs.cmake vendored Normal file
View File

@ -0,0 +1,107 @@
# This module can be copied and used by external plugins for OBS
#
# Once done these will be defined:
#
# LIBOBS_FOUND
# LIBOBS_INCLUDE_DIRS
# LIBOBS_LIBRARIES
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_OBS QUIET obs libobs)
endif()
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_lib_suffix 64)
else()
set(_lib_suffix 32)
endif()
if(DEFINED CMAKE_BUILD_TYPE)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(_build_type_base "debug")
else()
set(_build_type_base "release")
endif()
endif()
find_path(LIBOBS_INCLUDE_DIR
NAMES obs.h
HINTS
ENV obsPath${_lib_suffix}
ENV obsPath
${obsPath}
PATHS
/usr/include /usr/local/include /opt/local/include /sw/include
PATH_SUFFIXES
libobs
)
function(find_obs_lib base_name repo_build_path lib_name)
string(TOUPPER "${base_name}" base_name_u)
if(DEFINED _build_type_base)
set(_build_type_${repo_build_path} "${_build_type_base}/${repo_build_path}")
set(_build_type_${repo_build_path}${_lib_suffix} "${_build_type_base}${_lib_suffix}/${repo_build_path}")
endif()
find_library(${base_name_u}_LIB
NAMES ${_${base_name_u}_LIBRARIES} ${lib_name} lib${lib_name}
HINTS
ENV obsPath${_lib_suffix}
ENV obsPath
${obsPath}
${_${base_name_u}_LIBRARY_DIRS}
PATHS
/usr/lib /usr/local/lib /opt/local/lib /sw/lib
PATH_SUFFIXES
lib${_lib_suffix} lib
libs${_lib_suffix} libs
bin${_lib_suffix} bin
../lib${_lib_suffix} ../lib
../libs${_lib_suffix} ../libs
../bin${_lib_suffix} ../bin
# base repo non-msvc-specific search paths
${_build_type_${repo_build_path}}
${_build_type_${repo_build_path}${_lib_suffix}}
build/${repo_build_path}
build${_lib_suffix}/${repo_build_path}
# base repo msvc-specific search paths on windows
build${_lib_suffix}/${repo_build_path}/Debug
build${_lib_suffix}/${repo_build_path}/RelWithDebInfo
build/${repo_build_path}/Debug
build/${repo_build_path}/RelWithDebInfo
)
endfunction()
find_obs_lib(LIBOBS libobs obs)
if(MSVC)
find_obs_lib(W32_PTHREADS deps/w32-pthreads w32-pthreads)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libobs DEFAULT_MSG LIBOBS_LIB LIBOBS_INCLUDE_DIR)
mark_as_advanced(LIBOBS_INCLUDE_DIR LIBOBS_LIB)
if(LIBOBS_FOUND)
if(MSVC)
if (NOT DEFINED W32_PTHREADS_LIB)
message(FATAL_ERROR "Could not find the w32-pthreads library" )
endif()
set(W32_PTHREADS_INCLUDE_DIR ${LIBOBS_INCLUDE_DIR}/../deps/w32-pthreads)
endif()
set(LIBOBS_INCLUDE_DIRS ${LIBOBS_INCLUDE_DIR} ${W32_PTHREADS_INCLUDE_DIR})
set(LIBOBS_LIBRARIES ${LIBOBS_LIB} ${W32_PTHREADS_LIB})
include(${LIBOBS_INCLUDE_DIR}/../cmake/external/ObsPluginHelpers.cmake)
# allows external plugins to easily use/share common dependencies that are often included with libobs (such as FFmpeg)
if(NOT DEFINED INCLUDED_LIBOBS_CMAKE_MODULES)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LIBOBS_INCLUDE_DIR}/../cmake/Modules/")
set(INCLUDED_LIBOBS_CMAKE_MODULES true)
endif()
else()
message(FATAL_ERROR "Could not find the libobs library" )
endif()

66
obs-websocket.cpp Normal file
View File

@ -0,0 +1,66 @@
#include <obs-module.h>
#include <obs-frontend-api.h>
#include "WSServer.h"
OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE("obs-websocket", "en-US")
WSServer *server;
void obs_frontend_callback(enum obs_frontend_event event, void *)
{
bool sendMessage = false;
obs_data_t *announce = obs_data_create();
if (event == OBS_FRONTEND_EVENT_SCENE_CHANGED) {
obs_source_t *source = obs_frontend_get_current_scene();
const char *name = obs_source_get_name(source);
obs_data_set_string(announce, "type", "scene_changed");
obs_data_set_string(announce, "name", name);
sendMessage = true;
}
else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTED) {
obs_data_set_string(announce, "type", "streaming_started");
sendMessage = true;
}
else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPED) {
obs_data_set_string(announce, "type", "streaming_stopped");
sendMessage = true;
}
else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTED) {
obs_data_set_string(announce, "type", "recording_started");
sendMessage = true;
}
else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPED) {
obs_data_set_string(announce, "type", "recording_stopped");
sendMessage = true;
}
else if (event == OBS_FRONTEND_EVENT_EXIT) {
obs_data_set_string(announce, "type", "exiting");
sendMessage = true;
}
if (sendMessage && server) {
const char *message = obs_data_get_json(announce);
server->broadcast(message);
}
obs_data_release(announce);
}
bool obs_module_load(void)
{
blog(LOG_INFO, "[obs-websockets] you can haz websockets");
server = new WSServer(8080);
obs_frontend_add_event_callback(obs_frontend_callback, nullptr);
return true;
}
void obs_module_unload()
{
}