Skip to content

fix(tray): run tray in main event loop enabling support for macOS #3818

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
3 changes: 0 additions & 3 deletions cmake/compile_definitions/macos.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ list(APPEND SUNSHINE_EXTERNAL_LIBRARIES

set(APPLE_PLIST_FILE "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/Info.plist")

# todo - tray is not working on macos
set(SUNSHINE_TRAY 0)

set(PLATFORM_TARGET_FILES
"${CMAKE_SOURCE_DIR}/src/platform/macos/av_audio.h"
"${CMAKE_SOURCE_DIR}/src/platform/macos/av_audio.m"
Expand Down
2 changes: 1 addition & 1 deletion cmake/prep/options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ option(BUILD_WERROR "Enable -Werror flag." OFF)
# if this option is set, the build will exit after configuring special package configuration files
option(SUNSHINE_CONFIGURE_ONLY "Configure special files only, then exit." OFF)

option(SUNSHINE_ENABLE_TRAY "Enable system tray icon. This option will be ignored on macOS." ON)
option(SUNSHINE_ENABLE_TRAY "Enable system tray icon." ON)

option(SUNSHINE_SYSTEM_WAYLAND_PROTOCOLS "Use system installation of wayland-protocols rather than the submodule." OFF)

Expand Down
1 change: 0 additions & 1 deletion packaging/sunshine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ def install
end

args << "-DCUDA_FAIL_ON_MISSING=OFF" if OS.linux?
args << "-DSUNSHINE_ENABLE_TRAY=OFF" if OS.mac?

# Handle system tray on Linux
if OS.linux?
Expand Down
57 changes: 46 additions & 11 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,43 @@ WINAPI BOOL ConsoleCtrlHandler(DWORD type) {
}
#endif

#if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
constexpr bool tray_is_enabled = true;
#else
constexpr bool tray_is_enabled = false;
#endif

void mainThreadLoop(const std::shared_ptr<safe::event_t<bool>> &shutdown_event) {
bool run_loop = false;

// Conditions that would require the main thread event loop
run_loop = tray_is_enabled;

if (!run_loop) {
BOOST_LOG(info) << "No main thread features enabled, skipping event loop"sv;
return;
}

// Main thread event loop
BOOST_LOG(info) << "Starting main loop"sv;
while (true) {
if (shutdown_event->peek()) {
BOOST_LOG(info) << "Shutdown event detected, breaking main loop"sv;
if (tray_is_enabled) {
system_tray::end_tray();
}
break;
}

if (tray_is_enabled) {
system_tray::process_tray_events();
}

// Sleep to avoid busy waiting
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}

int main(int argc, char *argv[]) {
lifetime::argv = argv;

Expand Down Expand Up @@ -243,11 +280,6 @@ int main(int argc, char *argv[]) {

task_pool.start(1);

#if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
// create tray thread and detach it
system_tray::run_tray();
#endif

// Create signal handler after logging has been initialized
auto shutdown_event = mail::man->event<bool>(mail::shutdown);
on_signal(SIGINT, [&force_shutdown, &display_device_deinit_guard, shutdown_event]() {
Expand Down Expand Up @@ -346,19 +378,22 @@ int main(int argc, char *argv[]) {
}
#endif

rtsp_stream::rtpThread();
std::thread rtpThread {rtsp_stream::start};

if (tray_is_enabled) {
BOOST_LOG(info) << "Starting system tray"sv;
system_tray::init_tray();
}

mainThreadLoop(shutdown_event);

httpThread.join();
configThread.join();
rtpThread.join();

task_pool.stop();
task_pool.join();

// stop system tray
#if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
system_tray::end_tray();
#endif

#ifdef WIN32
// Restore global NVIDIA control panel settings
if (nvprefs_instance.owning_undo_file() && nvprefs_instance.load()) {
Expand Down
2 changes: 1 addition & 1 deletion src/rtsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@
respond(sock, session, &option, 200, "OK", req->sequenceNumber, {});
}

void rtpThread() {
void start() {

Check warning on line 1091 in src/rtsp.cpp

View check run for this annotation

Codecov / codecov/patch

src/rtsp.cpp#L1091

Added line #L1091 was not covered by tests
auto shutdown_event = mail::man->event<bool>(mail::shutdown);
auto broadcast_shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown);

Expand Down
2 changes: 1 addition & 1 deletion src/rtsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ namespace rtsp_stream {
*/
void terminate_sessions();

void rtpThread();
void start();

} // namespace rtsp_stream
34 changes: 13 additions & 21 deletions src/system_tray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
.allIconPaths = {TRAY_ICON, TRAY_ICON_LOCKED, TRAY_ICON_PLAYING, TRAY_ICON_PAUSING},
};

int system_tray() {
int init_tray() {

Check warning on line 127 in src/system_tray.cpp

View check run for this annotation

Codecov / codecov/patch

src/system_tray.cpp#L127

Added line #L127 was not covered by tests
#ifdef _WIN32
// If we're running as SYSTEM, Explorer.exe will not have permission to open our thread handle
// to monitor for thread termination. If Explorer fails to open our thread, our tray icon
Expand Down Expand Up @@ -195,29 +195,21 @@
}

tray_initialized = true;
while (tray_loop(1) == 0) {
BOOST_LOG(debug) << "System tray loop"sv;
}

return 0;
}

void run_tray() {
// create the system tray
#if defined(__APPLE__) || defined(__MACH__)
// macOS requires that UI elements be created on the main thread
// creating tray using dispatch queue does not work, although the code doesn't actually throw any (visible) errors

// dispatch_async(dispatch_get_main_queue(), ^{
// system_tray();
// });

BOOST_LOG(info) << "system_tray() is not yet implemented for this platform."sv;
#else // Windows, Linux
// create tray in separate thread
std::thread tray_thread(system_tray);
tray_thread.detach();
#endif
int process_tray_events() {

Check warning on line 201 in src/system_tray.cpp

View check run for this annotation

Codecov / codecov/patch

src/system_tray.cpp#L201

Added line #L201 was not covered by tests
if (!tray_initialized) {
return 1;
}

// Process one iteration of the tray loop with non-blocking mode (0)
if (const int result = tray_loop(0); result != 0) {
BOOST_LOG(warning) << "System tray loop failed"sv;
return result;

Check warning on line 209 in src/system_tray.cpp

View check run for this annotation

Codecov / codecov/patch

src/system_tray.cpp#L209

Added line #L209 was not covered by tests
}

return 0;
}

int end_tray() {
Expand Down
13 changes: 6 additions & 7 deletions src/system_tray.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,16 @@ namespace system_tray {
void tray_quit_cb(struct tray_menu *item);

/**
* @brief Create the system tray.
* @details This function has an endless loop, so it should be run in a separate thread.
* @return 1 if the system tray failed to create, otherwise 0 once the tray has been terminated.
* @brief Initializes the system tray without starting a loop.
* @return 0 if initialization was successful, non-zero otherwise.
*/
int system_tray();
int init_tray();

/**
* @brief Run the system tray with platform specific options.
* @todo macOS requires that UI elements be created on the main thread, so the system tray is not currently implemented for macOS.
* @brief Processes a single tray event iteration.
* @return 0 if processing was successful, non-zero otherwise.
*/
int run_tray();
int process_tray_events();

/**
* @brief Exit the system tray.
Expand Down
Loading