Skip to content

Commit

Permalink
Module (#132)
Browse files Browse the repository at this point in the history
* Add module load/init

* Look for modules inside slobs-plugin

* Few fixes on the module API

* Fixed initialize module

* Fix typo

* Clarify substr
  • Loading branch information
EddyGharbi committed Oct 30, 2018
1 parent adce1f0 commit 3c82fd0
Show file tree
Hide file tree
Showing 10 changed files with 577 additions and 9 deletions.
4 changes: 2 additions & 2 deletions js/module.d.ts
Expand Up @@ -660,8 +660,8 @@ export interface IAudioFactory {
reset(info: IAudioInfo): boolean;
getGlobal(): IAudio;
}
export interface IModuleFactory {
create(binPath: string, dataPath: string): IModule;
export interface IModuleFactory extends IFactoryTypes {
open(binPath: string, dataPath: string): IModule;
loadAll(): void;
addPath(path: string, dataPath: string): void;
logLoaded(): void;
Expand Down
4 changes: 2 additions & 2 deletions js/module.ts
Expand Up @@ -1493,8 +1493,8 @@ export interface IAudioFactory {
}


export interface IModuleFactory {
create(binPath: string, dataPath: string): IModule;
export interface IModuleFactory extends IFactoryTypes {
open(binPath: string, dataPath: string): IModule;
loadAll(): void;
addPath(path: string, dataPath: string): void;
logLoaded(): void;
Expand Down
1 change: 1 addition & 0 deletions obs-studio-client/CMakeLists.txt
Expand Up @@ -69,6 +69,7 @@ SET(PROJECT_SOURCE
"${PROJECT_SOURCE_DIR}/source/main.cpp"
"${PROJECT_SOURCE_DIR}/source/volmeter.cpp" "${PROJECT_SOURCE_DIR}/source/volmeter.hpp"
"${PROJECT_SOURCE_DIR}/source/video.cpp" "${PROJECT_SOURCE_DIR}/source/video.hpp"
"${PROJECT_SOURCE_DIR}/source/module.cpp" "${PROJECT_SOURCE_DIR}/source/module.hpp"
)
SET(PROJECT_LIBRARIES
${NODEJS_LIBRARIES}
Expand Down
2 changes: 2 additions & 0 deletions obs-studio-client/source/main.cpp
Expand Up @@ -29,6 +29,7 @@
#include "transition.hpp"
#include "video.hpp"
#include "volmeter.hpp"
#include "module.hpp"

extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 1;

Expand All @@ -47,6 +48,7 @@ void main(v8::Local<v8::Object> exports, v8::Local<v8::Value> module, void* priv
osn::Fader::Register(exports);
osn::VolMeter::Register(exports);
osn::Video::Register(exports);
osn::Module::Register(exports);

while (initializerFunctions.size() > 0) {
initializerFunctions.front()(exports);
Expand Down
216 changes: 216 additions & 0 deletions obs-studio-client/source/module.cpp
@@ -0,0 +1,216 @@
// Client module for the OBS Studio node module.
// Copyright(C) 2017 Streamlabs (General Workings Inc)
//
// 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, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA.

#include <condition_variable>
#include <mutex>
#include <string>
#include "controller.hpp"
#include "error.hpp"
#include "ipc-value.hpp"
#include "shared.hpp"
#include "utility.hpp"
#include "module.hpp"

osn::Module::Module(uint64_t id)
{
this->moduleId = id;
}

Nan::Persistent<v8::FunctionTemplate> osn::Module::prototype = Nan::Persistent<v8::FunctionTemplate>();

void osn::Module::Register(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target)
{
auto fnctemplate = Nan::New<v8::FunctionTemplate>();
fnctemplate->InstanceTemplate()->SetInternalFieldCount(1);
fnctemplate->SetClassName(Nan::New<v8::String>("Module").ToLocalChecked());

utilv8::SetTemplateField(fnctemplate, "open", Open);

v8::Local<v8::Template> objtemplate = fnctemplate->PrototypeTemplate();
utilv8::SetTemplateField(objtemplate, "initialize", Initialize);

utilv8::SetTemplateAccessorProperty(objtemplate, "name", Name);
utilv8::SetTemplateAccessorProperty(objtemplate, "fileName", FileName);
utilv8::SetTemplateAccessorProperty(objtemplate, "author", Author);
utilv8::SetTemplateAccessorProperty(objtemplate, "description", Description);
utilv8::SetTemplateAccessorProperty(objtemplate, "binaryPath", BinaryPath);
utilv8::SetTemplateAccessorProperty(objtemplate, "dataPath", DataPath);

utilv8::SetObjectField(target, "Module", fnctemplate->GetFunction());
prototype.Reset(fnctemplate);
}

Nan::NAN_METHOD_RETURN_TYPE osn::Module::Open(Nan::NAN_METHOD_ARGS_TYPE info)
{
std::string bin_path, data_path;

ASSERT_INFO_LENGTH(info, 2);
ASSERT_GET_VALUE(info[0], bin_path);
ASSERT_GET_VALUE(info[1], data_path);

auto conn = GetConnection();
if (!conn)
return;

std::vector<ipc::value> response = conn->call_synchronous_helper("Module", "Open", {ipc::value(bin_path), ipc::value(data_path)});

if (!ValidateResponse(response))
return;

osn::Module* obj = new osn::Module(response[1].value_union.ui64);
info.GetReturnValue().Set(osn::Module::Store(obj));
}

Nan::NAN_METHOD_RETURN_TYPE osn::Module::Initialize(Nan::NAN_METHOD_ARGS_TYPE info)
{
osn::Module* module;
if (!utilv8::SafeUnwrap(info, module)) {
return;
}

auto conn = GetConnection();
if (!conn)
return;

std::vector<ipc::value> response =
conn->call_synchronous_helper("Module", "Initialize", {ipc::value(module->moduleId)});

if (!ValidateResponse(response))
return;

info.GetReturnValue().Set(response[1].value_union.i32);
}

Nan::NAN_METHOD_RETURN_TYPE osn::Module::Name(Nan::NAN_METHOD_ARGS_TYPE info)
{
osn::Module* module;
if (!utilv8::SafeUnwrap(info, module)) {
return;
}

auto conn = GetConnection();
if (!conn)
return;

std::vector<ipc::value> response =
conn->call_synchronous_helper("Module", "GetName", {ipc::value(module->moduleId)});

if (!ValidateResponse(response))
return;

info.GetReturnValue().Set(utilv8::ToValue(response[1].value_str));
}

Nan::NAN_METHOD_RETURN_TYPE osn::Module::FileName(Nan::NAN_METHOD_ARGS_TYPE info)
{
osn::Module* module;
if (!utilv8::SafeUnwrap(info, module)) {
return;
}

auto conn = GetConnection();
if (!conn)
return;

std::vector<ipc::value> response =
conn->call_synchronous_helper("Module", "GetFileName", {ipc::value(module->moduleId)});

if (!ValidateResponse(response))
return;

info.GetReturnValue().Set(utilv8::ToValue(response[1].value_str));
}

Nan::NAN_METHOD_RETURN_TYPE osn::Module::Description(Nan::NAN_METHOD_ARGS_TYPE info)
{
osn::Module* module;
if (!utilv8::SafeUnwrap(info, module)) {
return;
}

auto conn = GetConnection();
if (!conn)
return;

std::vector<ipc::value> response =
conn->call_synchronous_helper("Module", "GetDescription", {ipc::value(module->moduleId)});

if (!ValidateResponse(response))
return;

info.GetReturnValue().Set(utilv8::ToValue(response[1].value_str));
}

Nan::NAN_METHOD_RETURN_TYPE osn::Module::Author(Nan::NAN_METHOD_ARGS_TYPE info)
{
osn::Module* module;
if (!utilv8::SafeUnwrap(info, module)) {
return;
}

auto conn = GetConnection();
if (!conn)
return;

std::vector<ipc::value> response =
conn->call_synchronous_helper("Module", "GetAuthor", {ipc::value(module->moduleId)});

if (!ValidateResponse(response))
return;

info.GetReturnValue().Set(utilv8::ToValue(response[1].value_str));
}

Nan::NAN_METHOD_RETURN_TYPE osn::Module::BinaryPath(Nan::NAN_METHOD_ARGS_TYPE info)
{
osn::Module* module;
if (!utilv8::SafeUnwrap(info, module)) {
return;
}

auto conn = GetConnection();
if (!conn)
return;

std::vector<ipc::value> response =
conn->call_synchronous_helper("Module", "GetBinaryPath", {ipc::value(module->moduleId)});

if (!ValidateResponse(response))
return;

info.GetReturnValue().Set(utilv8::ToValue(response[1].value_str));
}

Nan::NAN_METHOD_RETURN_TYPE osn::Module::DataPath(Nan::NAN_METHOD_ARGS_TYPE info)
{
osn::Module* module;
if (!utilv8::SafeUnwrap(info, module)) {
return;
}

auto conn = GetConnection();
if (!conn)
return;

std::vector<ipc::value> response =
conn->call_synchronous_helper("Module", "GetDataPath", {ipc::value(module->moduleId)});

if (!ValidateResponse(response))
return;

info.GetReturnValue().Set(utilv8::ToValue(response[1].value_str));
}
54 changes: 54 additions & 0 deletions obs-studio-client/source/module.hpp
@@ -0,0 +1,54 @@
// Client module for the OBS Studio node module.
// Copyright(C) 2017 Streamlabs (General Workings Inc)
//
// 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, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA.

#pragma once
#include <nan.h>
#include <node.h>
#include "utility-v8.hpp"

namespace osn
{
class Module : public utilv8::ManagedObject<osn::Module>, public Nan::ObjectWrap
{
friend class utilv8::ManagedObject<osn::Module>;

public:
uint64_t moduleId;
Module(uint64_t id);
virtual ~Module(){};

// JavaScript
public:
static Nan::Persistent<v8::FunctionTemplate> prototype;

static void Register(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);

//Functions
static Nan::NAN_METHOD_RETURN_TYPE Open(Nan::NAN_METHOD_ARGS_TYPE info);
static Nan::NAN_METHOD_RETURN_TYPE Initialize(Nan::NAN_METHOD_ARGS_TYPE info);

//Methods
static Nan::NAN_METHOD_RETURN_TYPE Name(Nan::NAN_METHOD_ARGS_TYPE info);
static Nan::NAN_METHOD_RETURN_TYPE FileName(Nan::NAN_METHOD_ARGS_TYPE info);
static Nan::NAN_METHOD_RETURN_TYPE Author(Nan::NAN_METHOD_ARGS_TYPE info);
static Nan::NAN_METHOD_RETURN_TYPE Description(Nan::NAN_METHOD_ARGS_TYPE info);
static Nan::NAN_METHOD_RETURN_TYPE BinaryPath(Nan::NAN_METHOD_ARGS_TYPE info);
static Nan::NAN_METHOD_RETURN_TYPE DataPath(Nan::NAN_METHOD_ARGS_TYPE info);


};
} // namespace osn
2 changes: 2 additions & 0 deletions obs-studio-server/source/main.cpp
Expand Up @@ -41,6 +41,7 @@
#include "osn-transition.hpp"
#include "osn-video.hpp"
#include "osn-volmeter.hpp"
#include "osn-module.hpp"

extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 1;

Expand Down Expand Up @@ -169,6 +170,7 @@ int main(int argc, char* argv[])
osn::VolMeter::Register(myServer);
osn::Properties::Register(myServer);
osn::Video::Register(myServer);
osn::Module::Register(myServer);
OBS_API::Register(myServer);
OBS_content::Register(myServer);
OBS_service::Register(myServer);
Expand Down
12 changes: 8 additions & 4 deletions obs-studio-server/source/nodeobs_api.cpp
Expand Up @@ -42,6 +42,7 @@ std::string OBS_currentSceneCollectio
bool useOBS_configFiles = false;
bool isOBS_installedValue;
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string slobs_plugin;

std::string g_moduleDirectory = "";

Expand Down Expand Up @@ -427,14 +428,16 @@ void OBS_API::OBS_API_initAPI(
}
pathConfigDirectory = args[0].value_str.c_str();
appdata_path = args[0].value_str.c_str();
appdata_path += "/node-obs/";

/* libobs will use three methods of finding data files:
* 1. ${CWD}/data/libobs <- This doesn't work for us
* 2. ${OBS_DATA_PATH}/libobs <- This works but is inflexible
* 3. getenv(OBS_DATA_PATH) + /libobs <- Can be set anywhere
* on the cli, in the frontend, or the backend. */
obs_add_data_path((g_moduleDirectory + "/libobs/data/libobs/").c_str());
slobs_plugin = appdata_path.substr(0, appdata_path.size() - strlen("/slobs-client"));
slobs_plugin.append("/slobs-plugins");
obs_add_data_path((slobs_plugin + "/data/").c_str());

std::vector<char> userData = std::vector<char>(1024);
os_get_config_path(userData.data(), userData.capacity() - 1, "slobs-client/plugin_config");
Expand All @@ -443,7 +446,7 @@ void OBS_API::OBS_API_initAPI(
/* Logging */
string filename = GenerateTimeDateFilename("txt");
string log_path = appdata_path;
log_path.append("/logs/");
log_path.append("/node-obs/logs/");

/* Make sure the path is created
before attempting to make a file there. */
Expand Down Expand Up @@ -818,9 +821,10 @@ void OBS_API::openAllModules(void)
{
OBS_service::resetVideoContext(NULL);

std::string plugins_paths[] = {g_moduleDirectory + "/obs-plugins/64bit", g_moduleDirectory + "/obs-plugins"};
std::string plugins_paths[] = {g_moduleDirectory + "/obs-plugins/64bit", g_moduleDirectory + "/obs-plugins", slobs_plugin + "/obs-plugins/64bit"};

std::string plugins_data_paths[] = {g_moduleDirectory + "/data/obs-plugins", plugins_data_paths[0]};
std::string plugins_data_paths[] = {
g_moduleDirectory + "/data/obs-plugins", plugins_data_paths[0], slobs_plugin + "/data/obs-plugins"};

size_t num_paths = sizeof(plugins_paths) / sizeof(plugins_paths[0]);

Expand Down

0 comments on commit 3c82fd0

Please sign in to comment.