Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 1 addition & 17 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ env:
SLGenerator: Visual Studio 17 2022
SLDistributeDirectory: distribute
SLFullDistributePath: "streamlabs-build.app/distribute" # The .app extension is required to run macOS tests correctly.
LibOBSVersion: 30.2.4sl51
LibOBSVersion: 31.1.2test4
PACKAGE_NAME: osn

jobs:
Expand Down Expand Up @@ -254,22 +254,6 @@ jobs:
steps:
- name: 'Add msbuild to PATH'
uses: microsoft/setup-msbuild@v1
- name: Install older build components
run: |
# For versions update see here: https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools?view=vs-2022
Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\"
$InstallPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise"
$componentsToInstall= @(
"Microsoft.VisualStudio.Component.VC.v141.x86.x64"
"Microsoft.VisualStudio.Component.VC.14.39.17.9.x86.x64"
"Microsoft.VisualStudio.Component.VC.14.39.17.9.ATL"
)
[string]$workloadArgs = $componentsToInstall | ForEach-Object {" --add " + $_}
$Arguments = ('/c', "vs_installer.exe", 'modify', '--installPath', "`"$InstallPath`"",$workloadArgs, '--quiet', '--norestart', '--nocache')
# should be run twice
$process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden
$process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden
shell: powershell
- name: 'Checkout'
uses: actions/checkout@v3
with:
Expand Down
1 change: 0 additions & 1 deletion js/module.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,6 @@ export interface IVolmeterFactory {
create(type: EFaderType): IVolmeter;
}
export interface IVolmeter {
updateInterval: number;
destroy(): void;
attach(source: IInput): void;
detach(): void;
Expand Down
11 changes: 3 additions & 8 deletions js/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,12 +581,12 @@ export interface IGlobal {
readonly version: number;

/**
* Percentage of CPU being used
* Percentage of CPU being used
*/
readonly cpuPercentage: number;

/**
* Current FPS
* Current FPS
*/
readonly currentFrameRate: number;

Expand All @@ -601,7 +601,7 @@ export interface IGlobal {
readonly diskSpaceAvailable: number;

/**
* Current memory usage
* Current memory usage
*/
readonly memoryUsage: number;
}
Expand Down Expand Up @@ -1381,11 +1381,6 @@ export interface IVolmeterFactory {
* Object representing a volmeter control corresponding to a source.
*/
export interface IVolmeter {
/**
* The interval at which the volmeter will call the callback.
*/
updateInterval: number;

/**
* Destroy the volmeter object object
*/
Expand Down
3 changes: 1 addition & 2 deletions obs-studio-client/source/volmeter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ Napi::Value osn::Volmeter::Create(const Napi::CallbackInfo &info)
if (!ValidateResponse(info, response))
return info.Env().Undefined();

auto instance = osn::Volmeter::constructor.New({Napi::Number::New(info.Env(), static_cast<double>(response[1].value_union.ui64)),
Napi::Number::New(info.Env(), static_cast<double>(response[2].value_union.ui32))});
auto instance = osn::Volmeter::constructor.New({Napi::Number::New(info.Env(), static_cast<double>(response[1].value_union.ui64))});

globalCallback::add_volmeter(response[1].value_union.ui64);

Expand Down
25 changes: 19 additions & 6 deletions obs-studio-server/source/nodeobs_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,18 @@ void OBS_API::OBS_API_initAPI(void *data, const int64_t id, const std::vector<ip
SetPrivilegeForGPUPriority();
#endif

// This code initializes the graphics susbsystem and hardware acceleration features
obs_video_info *ovi = obs_create_video_info();
const auto resetResult = obs_reset_video(ovi);
if (resetResult != OBS_VIDEO_SUCCESS) {
rval.push_back(ipc::value((uint64_t)ErrorCode::CriticalError));
rval.push_back(ipc::value(resetResult));
}
obs_remove_video_info(ovi);
if (resetResult != OBS_VIDEO_SUCCESS) {
return;
}

osn::Source::initialize_global_signals();

cpuUsageInfo = os_cpu_usage_info_start();
Expand Down Expand Up @@ -1032,17 +1044,18 @@ void OBS_API::OBS_API_initAPI(void *data, const int64_t id, const std::vector<ip

util::CrashManager::setAppState("idle");

blog(LOG_INFO, "---------------------------------");
obs_log_loaded_modules();
blog(LOG_INFO, "---------------------------------");
logEncoders();
blog(LOG_INFO, "---------------------------------");

// We are returning a video result here because the frontend needs to know if we sucessfully
// initialized the Dx11 API
rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
rval.push_back(ipc::value(OBS_VIDEO_SUCCESS));

#if defined(__APPLE__)
// Block until CEF has been initialized by the main thread.
g_util_osx->nextState();
while (!g_util_osx->hasInitCef()) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
#endif
AUTO_DEBUG;
}

Expand Down
1 change: 0 additions & 1 deletion obs-studio-server/source/osn-volmeter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ void osn::Volmeter::Create(void *data, const int64_t id, const std::vector<ipc::

rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
rval.push_back(ipc::value(meter->id));
rval.push_back(ipc::value(obs_volmeter_get_update_interval(meter->self)));
AUTO_DEBUG;
}

Expand Down
56 changes: 48 additions & 8 deletions obs-studio-server/source/util-osx-impl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
******************************************************************************/

#include "util-osx-impl.h"
#include "obs.h"
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
Expand All @@ -43,13 +44,13 @@
return;

while (true) {
if (!appRunning) {
if (state == UtilObjCInt::EState::Stop) {
break;
}
int ret = ::read(file_descriptor, buffer.data(), count);
if (ret > 0) {
bool appCrashed = *reinterpret_cast<bool *>(buffer.data());
if (appCrashed && appRunning)
if (appCrashed && state != UtilObjCInt::EState::Stop)
this->stopApplication();
break;
}
Expand Down Expand Up @@ -86,17 +87,33 @@ @implementation UtilImplObj

void UtilObjCInt::runApplication(void)
{
worker = new std::thread(&UtilObjCInt::wait_terminate, this);
// Wait for OBS_API_initAPI to be invoked
while (!hasInitApi() && isRunning()) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
if (isRunning()) {
// Create a dummy source to init obs-browser plugin. Must be init from main thread before [NSApplication run]
obs_source_t *source = obs_source_create("browser_source", "dummy", NULL, NULL);
obs_source_release(source);
nextState();

@autoreleasepool {
NSApplication *app = [NSApplication sharedApplication];
appRunning = true;
[app run];
worker = new std::thread(&UtilObjCInt::wait_terminate, this);

@autoreleasepool {
NSApplication *app = [NSApplication sharedApplication];
[app run];
}
}
}

void UtilObjCInt::stopApplication(void)
{
if (!hasInitCef()) {
state = UtilObjCInt::EState::Stop;
return;
} else {
state = UtilObjCInt::EState::Stop;
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSApplication sharedApplication] stop:nil];
NSEvent *event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
Expand All @@ -110,12 +127,17 @@ @implementation UtilImplObj
data2:0];
[NSApp postEvent:event atStart:TRUE];

appRunning = false;
state = UtilObjCInt::EState::Stop;
if (worker->joinable())
worker->join();
});
}

bool UtilObjCInt::isRunning(void)
{
return state != UtilObjCInt::EState::Stop;
}

unsigned long long UtilObjCInt::getTotalPhysicalMemory(void)
{
return [NSProcessInfo processInfo].physicalMemory;
Expand Down Expand Up @@ -191,4 +213,22 @@ @implementation UtilImplObj
return 0;
return physical_cores;
}

void UtilObjCInt::nextState(void)
{
if (state + 1 < UtilObjCInt::EState::Max) {
state = state + 1;
}
}

bool UtilObjCInt::hasInitApi(void)
{
return state == UtilObjCInt::EState::InitializedApi;
}

bool UtilObjCInt::hasInitCef(void)
{
return state == UtilObjCInt::EState::InitializedCEF;
}

@end
13 changes: 12 additions & 1 deletion obs-studio-server/source/util-osx-int.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class UtilObjCInt {
std::string getDefaultVideoSavePath(void);
void runApplication(void);
void stopApplication(void);
bool isRunning(void);
unsigned long long getTotalPhysicalMemory(void);
unsigned long long getAvailableMemory(void);
std::vector<std::pair<uint32_t, uint32_t>> getAvailableScreenResolutions(void);
Expand All @@ -40,10 +41,20 @@ class UtilObjCInt {
std::string getComputerName(void);
int getPhysicalCores(void);
void wait_terminate(void);
void nextState(void);
bool hasInitApi(void);
bool hasInitCef(void);

private:
enum EState {
Idle = 0,
InitializedApi, // Was initAPI invoked?
InitializedCEF, // Was CefInitialize() invoked?
Stop,
Max
};
void *self;
std::atomic<bool> appRunning;
std::atomic<int> state; // See EState enum. Tracks application state
std::thread *worker;
};

Expand Down
20 changes: 20 additions & 0 deletions obs-studio-server/source/util-osx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ void UtilInt::stopApplication(void)
_impl->stopApplication();
}

bool UtilInt::isRunning(void)
{
return _impl->isRunning();
}

unsigned long long UtilInt::getTotalPhysicalMemory(void)
{
return _impl->getTotalPhysicalMemory();
Expand Down Expand Up @@ -83,3 +88,18 @@ int UtilInt::getPhysicalCores(void)
{
return _impl->getPhysicalCores();
}

void UtilInt::nextState(void)
{
_impl->nextState();
}

bool UtilInt::hasInitApi(void)
{
return _impl->hasInitApi();
}

bool UtilInt::hasInitCef(void)
{
return _impl->hasInitCef();
}
4 changes: 4 additions & 0 deletions obs-studio-server/source/util-osx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,17 @@ class UtilInt {
std::string getDefaultVideoSavePath(void);
void runApplication(void);
void stopApplication(void);
bool isRunning(void);
unsigned long long getTotalPhysicalMemory(void);
unsigned long long getAvailableMemory(void);
std::vector<std::pair<uint32_t, uint32_t>> getAvailableScreenResolutions(void);
std::string getUserDataPath(void);
std::string getWorkingDirectory(void);
std::string getComputerName(void);
int getPhysicalCores(void);
void nextState(void);
bool hasInitApi(void);
bool hasInitCef(void);

private:
UtilObjCInt *_impl;
Expand Down
10 changes: 10 additions & 0 deletions tests/osn-tests/src/test_osn_input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ describe(testName, () => {
});
});

it('Create Browser source and verify Chromium Embedded Framework (CEF) functionality', () => {
const input = osn.InputFactory.create(EOBSInputTypes.BrowserSource, 'input');

// Checking if input source was created correctly
expect(input).to.not.equal(undefined, GetErrorMessage(ETestErrorMsg.CreateInput, EOBSInputTypes.BrowserSource));
expect(input.id).to.equal(EOBSInputTypes.BrowserSource, GetErrorMessage(ETestErrorMsg.InputId, EOBSInputTypes.BrowserSource));
expect(input.name).to.equal('input', GetErrorMessage(ETestErrorMsg.InputName, EOBSInputTypes.BrowserSource));
input.release();
});

it('Create all types of input with settings parameter', () => {
// Create all input sources available with settings parameter
obs.inputTypes.forEach(function(inputType) {
Expand Down