mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
Initial commit
This commit is contained in:
commit
61be350bef
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/build/
|
||||
/build32/
|
||||
/build64/
|
33
CMakeLists.txt
Normal file
33
CMakeLists.txt
Normal 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
92
WSServer.cpp
Normal 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
30
WSServer.h
Normal 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
107
external/FindLibObs.cmake
vendored
Normal 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
66
obs-websocket.cpp
Normal 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()
|
||||
{
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user