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
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,14 @@ if(NOT libcurl_POPULATED)
set(USE_LIBIDN2 OFF CACHE BOOL "" FORCE)
set(USE_LIBPSL OFF CACHE BOOL "" FORCE)
set(CURL_ZLIB OFF CACHE BOOL "" FORCE)

if(APPLE)
# Enable Secure Transport on Apple platforms
set(CURL_USE_SECTRANSP ON CACHE BOOL "" FORCE)
set(CMAKE_USE_SCHANNEL OFF CACHE BOOL "" FORCE)
else()
set(CMAKE_USE_SCHANNEL ON CACHE BOOL "" FORCE)
endif()

FetchContent_Populate(libcurl)
add_subdirectory(${libcurl_SOURCE_DIR} ${libcurl_BINARY_DIR} EXCLUDE_FROM_ALL)
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
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Config DownloadGoLiveConfig(std::string url, const PostData &post_data)
5); // timeout in seconds

if (!encodeConfigDownloadedOk) {
blog(LOG_ERROR, "Go live error: %s", libraryError.c_str());
throw std::runtime_error("Failed to start stream. Config request failed");
}

Expand Down
64 changes: 62 additions & 2 deletions obs-studio-server/source/osn-multitrack-video-system-info-osx.mm
Original file line number Diff line number Diff line change
@@ -1,8 +1,68 @@
#include "osn-multitrack-video-system-info.hpp"
#include "shared.hpp"
#include "util/platform.h"

#import <Foundation/Foundation.h>
#import <Foundation/NSProcessInfo.h>

namespace osn {

// This feature is currently unused on Mac
void system_info(Capabilities &capabilities) {}
void fillSystemInfo(System &sysinfo)
{
NSProcessInfo *procInfo = [NSProcessInfo processInfo];
NSOperatingSystemVersion versionObj = [procInfo operatingSystemVersion];

sysinfo.name = "macOS";
sysinfo.bits = 64; // 32-bit macOS is long deprecated.
sysinfo.version = [[procInfo operatingSystemVersionString] UTF8String];

switch (versionObj.majorVersion) {
case 11:
sysinfo.release = "Big Sur";
break;
case 12:
sysinfo.release = "Monterey";
break;
case 13:
sysinfo.release = "Ventura";
break;
case 14:
sysinfo.release = "Sonoma";
break;
case 15:
sysinfo.release = "Sequoia";
break;
case 26:
sysinfo.release = "Tahoe";
break;
default:
sysinfo.release = "unknown";
}

sysinfo.arm = true;
sysinfo.armEmulation = false;
}

void system_info(Capabilities &capabilities)
{
capabilities.cpu.name = g_util_osx->getCpuName();
// Getting the frequency is not supported on Apple Silicon.
capabilities.cpu.physical_cores = os_get_physical_cores();
capabilities.cpu.logical_cores = os_get_logical_cores();

capabilities.memory.total = os_get_sys_total_size();
capabilities.memory.free = os_get_sys_free_size();

// Apple Silicon- there's only going to be gpu
Gpu gpu;
gpu.model = capabilities.cpu.name.value_or("Unknown");
gpu.vendor_id = 0x106b; // Always Apple
gpu.device_id = 0; // Always 0 for Apple Silicon

std::vector<Gpu> gpus;
gpus.push_back(std::move(gpu));
capabilities.gpu = gpus;
fillSystemInfo(capabilities.system);
}

} // namespace osn
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
71 changes: 63 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,37 @@ @implementation UtilImplObj
return 0;
return physical_cores;
}

std::string UtilObjCInt::getCpuName(void)
{
char buffer[256];
size_t size = sizeof(buffer);
std::string name;

if (sysctlbyname("machdep.cpu.brand_string", buffer, &size, nullptr, 0) == 0) {
name = std::string(buffer);
} else if (sysctlbyname("hw.model", buffer, &size, nullptr, 0) == 0) {
name = std::string(buffer);
}

return name;
}

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
14 changes: 13 additions & 1 deletion obs-studio-server/source/util-osx-int.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,30 @@ 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);
std::string getUserDataPath(void);
std::string getWorkingDirectory(void);
std::string getComputerName(void);
int getPhysicalCores(void);
std::string getCpuName(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
Loading
Loading