Skip to content

Commit 19a0a16

Browse files
authored
fix cef main loop on mac obs-browser (#49)
* update mac-obs-browser to not block main thread (CefRunMessageLoop) * call CefDoMessageLoopWork instead of CefRunMessageLoop which is a blocking call * QoL change for dev: update ExecuteTask/ExecuteSyncTask to check if invoked on main thread. When debugging slobs, we're on main thread. But when this code is invoked from SLD, we're running from an async thread. so this code enables the task to be executed with no thought or care where its been run from.
1 parent c404f38 commit 19a0a16

File tree

3 files changed

+49
-14
lines changed

3 files changed

+49
-14
lines changed

browser-mac.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ bool ExecuteNextBrowserTask();
4444
void ExecuteTask(MessageTask task);
4545
void ExecuteSyncTask(MessageTask task);
4646
void DoCefMessageLoop(int ms);
47+
void DoCefMessageLoopTimer(float ms);
48+
void StopCefMessageLoopTimer();
4749
void Process();
4850
#if 0 // REMOVE_DUPLICATE
4951
void QueueBrowserTask(CefRefPtr<CefBrowser> browser, BrowserFunc func);

browser-mac.mm

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
std::mutex browserTaskMutex;
2828
std::deque<Task> browserTasks;
29+
static NSTimer *cefTimer = nil;
2930

3031
bool ExecuteNextBrowserTask()
3132
{
@@ -45,16 +46,26 @@ bool ExecuteNextBrowserTask()
4546

4647
void ExecuteTask(MessageTask task)
4748
{
48-
dispatch_async(dispatch_get_main_queue(), ^{
49+
// Protect against exception if already on main thread
50+
if ([NSThread isMainThread]) {
4951
task();
50-
});
52+
} else {
53+
dispatch_async(dispatch_get_main_queue(), ^{
54+
task();
55+
});
56+
}
5157
}
5258

5359
void ExecuteSyncTask(MessageTask task)
5460
{
55-
dispatch_sync(dispatch_get_main_queue(), ^{
61+
// Protect against exception if already on main thread
62+
if ([NSThread isMainThread]) {
5663
task();
57-
});
64+
} else {
65+
dispatch_sync(dispatch_get_main_queue(), ^{
66+
task();
67+
});
68+
}
5869
}
5970

6071
void DoCefMessageLoop(int)
@@ -64,6 +75,22 @@ void DoCefMessageLoop(int)
6475
});
6576
}
6677

78+
void DoCefMessageLoopTimer(float ms)
79+
{
80+
cefTimer = [NSTimer
81+
scheduledTimerWithTimeInterval:ms
82+
repeats:YES
83+
block:^(NSTimer *) {
84+
CefDoMessageLoopWork();
85+
}];
86+
}
87+
88+
void StopCefMessageLoopTimer()
89+
{
90+
[cefTimer invalidate];
91+
cefTimer = nil;
92+
}
93+
6794
void Process()
6895
{
6996
dispatch_async(dispatch_get_main_queue(), ^{

obs-browser-plugin.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,8 @@ static obs_data_array_t *browser_source_get_messages(void *data)
333333
messages = obs_data_array_create();
334334
for (const auto &message : bs->messagesToApp) {
335335
obs_data_t *msg_data = obs_data_create();
336-
obs_data_set_string(msg_data, "message", message.c_str());
336+
obs_data_set_string(msg_data, "message",
337+
message.c_str());
337338
obs_data_array_push_back(messages, msg_data);
338339
obs_data_release(msg_data);
339340
}
@@ -529,15 +530,9 @@ static void BrowserShutdown(void)
529530
#ifndef ENABLE_BROWSER_QT_LOOP
530531
static void BrowserManagerThread(obs_data_t *settings)
531532
{
532-
#ifdef __APPLE__
533-
ExecuteSyncTask([&settings]() {
534-
#endif
535-
BrowserInit(settings);
536-
CefRunMessageLoop();
537-
BrowserShutdown();
538-
#ifdef __APPLE__
539-
});
540-
#endif
533+
BrowserInit(settings);
534+
CefRunMessageLoop();
535+
BrowserShutdown();
541536
}
542537
#endif
543538

@@ -546,6 +541,12 @@ extern "C" EXPORT void obs_browser_initialize(obs_data_t *settings)
546541
if (!os_atomic_set_bool(&manager_initialized, true)) {
547542
#ifdef ENABLE_BROWSER_QT_LOOP
548543
BrowserInit(settings);
544+
#elif __APPLE__
545+
546+
ExecuteTask([&settings]() {
547+
BrowserInit(settings);
548+
DoCefMessageLoopTimer(0.01f); // Do not block the main queue so we avoid calling CefRunMessageLoop()
549+
});
549550
#else
550551
auto binded_fn = bind(BrowserManagerThread, settings);
551552
manager_thread = thread(binded_fn);
@@ -956,6 +957,11 @@ void obs_module_unload(void)
956957
{
957958
#ifdef USE_UI_LOOP
958959
BrowserShutdown();
960+
#elif __APPLE__
961+
ExecuteSyncTask([]() {
962+
StopCefMessageLoopTimer();
963+
BrowserShutdown();
964+
});
959965
#else
960966
if (manager_thread.joinable()) {
961967
while (!QueueCEFTask([]() { CefQuitMessageLoop(); }))

0 commit comments

Comments
 (0)