style(sonar): fix cpp:S4962 (#4140)

This commit is contained in:
ReenigneArcher
2025-08-08 00:45:53 -04:00
committed by GitHub
parent dbe80d0f92
commit fc7b9e30c8
20 changed files with 119 additions and 119 deletions

View File

@@ -1421,7 +1421,7 @@ namespace config {
if (!service_ctrl::is_service_running()) {
// If the service isn't running, relaunch ourselves as admin to start it
WCHAR executable[MAX_PATH];
GetModuleFileNameW(NULL, executable, ARRAYSIZE(executable));
GetModuleFileNameW(nullptr, executable, ARRAYSIZE(executable));
SHELLEXECUTEINFOW shell_exec_info {};
shell_exec_info.cbSize = sizeof(shell_exec_info);

View File

@@ -191,8 +191,8 @@ namespace service_ctrl {
}
private:
SC_HANDLE scm_handle = NULL;
SC_HANDLE service_handle = NULL;
SC_HANDLE scm_handle = nullptr;
SC_HANDLE service_handle = nullptr;
};
bool is_service_running() {

View File

@@ -186,7 +186,7 @@ int main(int argc, char *argv[]) {
wnd_class.lpszClassName = "SunshineSessionMonitorClass";
wnd_class.lpfnWndProc = SessionMonitorWindowProc;
if (!RegisterClassA(&wnd_class)) {
session_monitor_hwnd_promise.set_value(NULL);
session_monitor_hwnd_promise.set_value(nullptr);
BOOST_LOG(error) << "Failed to register session monitor window class"sv << std::endl;
return;
}

View File

@@ -12,13 +12,13 @@ namespace nvenc {
nvenc_d3d11::nvenc_d3d11(NV_ENC_DEVICE_TYPE device_type):
nvenc_base(device_type) {
async_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
async_event_handle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
}
nvenc_d3d11::~nvenc_d3d11() {
if (dll) {
FreeLibrary(dll);
dll = NULL;
dll = nullptr;
}
if (async_event_handle) {
CloseHandle(async_event_handle);
@@ -36,7 +36,7 @@ namespace nvenc {
constexpr auto dll_name = "nvEncodeAPI.dll";
#endif
if ((dll = LoadLibraryEx(dll_name, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
if ((dll = LoadLibraryEx(dll_name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
if (auto create_instance = (decltype(NvEncodeAPICreateInstance) *) GetProcAddress(dll, "NvEncodeAPICreateInstance")) {
auto new_nvenc = std::make_unique<NV_ENCODE_API_FUNCTION_LIST>();
new_nvenc->version = min_struct_version(NV_ENCODE_API_FUNCTION_LIST_VER);
@@ -55,7 +55,7 @@ namespace nvenc {
if (dll) {
FreeLibrary(dll);
dll = NULL;
dll = nullptr;
}
return false;

View File

@@ -39,7 +39,7 @@ namespace nvenc {
bool wait_for_async_event(uint32_t timeout_ms) override;
private:
HMODULE dll = NULL;
HMODULE dll = nullptr;
};
} // namespace nvenc

View File

@@ -63,7 +63,7 @@ namespace nvenc {
constexpr auto dll_name = "nvcuda.dll";
if ((cuda_functions.dll = LoadLibraryEx(dll_name, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
if ((cuda_functions.dll = LoadLibraryEx(dll_name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
auto load_function = [&]<typename T>(T &location, auto symbol) -> bool {
location = (T) GetProcAddress(cuda_functions.dll, symbol);
return location != nullptr;

View File

@@ -56,7 +56,7 @@ namespace nvenc {
autopop_context push_context();
HMODULE dll = NULL;
HMODULE dll = nullptr;
const ID3D11DevicePtr d3d_device;
ID3D11Texture2DPtr d3d_input_texture;

View File

@@ -155,7 +155,7 @@ namespace nvhttp {
std::string get_arg(const args_t &args, const char *name, const char *default_value = nullptr) {
auto it = args.find(name);
if (it == std::end(args)) {
if (default_value != NULL) {
if (default_value != nullptr) {
return std::string(default_value);
}

View File

@@ -377,7 +377,7 @@ namespace platf::audio {
*ppvInterface = (IMMNotificationClient *) this;
return S_OK;
} else {
*ppvInterface = NULL;
*ppvInterface = nullptr;
return E_NOINTERFACE;
}
}
@@ -679,7 +679,7 @@ namespace platf::audio {
float *sample_buf_pos;
int channels;
HANDLE mmcss_task_handle = NULL;
HANDLE mmcss_task_handle = nullptr;
};
class audio_control_t: public ::platf::audio_control_t {

View File

@@ -601,12 +601,12 @@ namespace platf::dxgi {
LUID val;
if (OpenProcessToken(GetCurrentProcess(), flags, &token) &&
!!LookupPrivilegeValue(NULL, SE_INC_BASE_PRIORITY_NAME, &val)) {
!!LookupPrivilegeValue(nullptr, SE_INC_BASE_PRIORITY_NAME, &val)) {
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = val;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(token, false, &tp, sizeof(tp), NULL, NULL)) {
if (!AdjustTokenPrivileges(token, false, &tp, sizeof(tp), nullptr, nullptr)) {
BOOST_LOG(warning) << "Could not set privilege to increase GPU priority";
}
}
@@ -918,20 +918,20 @@ namespace platf::dxgi {
"DXGI_FORMAT_A8P8",
"DXGI_FORMAT_B4G4R4A4_UNORM",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
"DXGI_FORMAT_P208",
"DXGI_FORMAT_V208",

View File

@@ -1739,7 +1739,7 @@ namespace platf::dxgi {
img->data = nullptr;
if (img->encoder_texture_handle) {
CloseHandle(img->encoder_texture_handle);
img->encoder_texture_handle = NULL;
img->encoder_texture_handle = nullptr;
}
// Initialize format-dependent fields

View File

@@ -293,7 +293,7 @@ namespace platf {
if (gamepad.repeat_task) {
task_pool.cancel(gamepad.repeat_task);
gamepad.repeat_task = 0;
gamepad.repeat_task = nullptr;
}
if (gamepad.gp && vigem_target_is_attached(gamepad.gp.get())) {
@@ -1452,7 +1452,7 @@ namespace platf {
// Cancel any pending updates. We will requeue one here when we're finished.
if (gamepad.repeat_task) {
task_pool.cancel(gamepad.repeat_task);
gamepad.repeat_task = 0;
gamepad.repeat_task = nullptr;
}
if (gamepad.gp && vigem_target_is_attached(gamepad.gp.get())) {

View File

@@ -117,7 +117,7 @@ namespace platf {
std::filesystem::path appdata() {
WCHAR sunshine_path[MAX_PATH];
GetModuleFileNameW(NULL, sunshine_path, _countof(sunshine_path));
GetModuleFileNameW(nullptr, sunshine_path, _countof(sunshine_path));
return std::filesystem::path {sunshine_path}.remove_filename() / L"config"sv;
}
@@ -410,16 +410,16 @@ namespace platf {
LPPROC_THREAD_ATTRIBUTE_LIST allocate_proc_thread_attr_list(DWORD attribute_count) {
SIZE_T size;
InitializeProcThreadAttributeList(NULL, attribute_count, 0, &size);
InitializeProcThreadAttributeList(nullptr, attribute_count, 0, &size);
auto list = (LPPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc(GetProcessHeap(), 0, size);
if (list == NULL) {
return NULL;
if (list == nullptr) {
return nullptr;
}
if (!InitializeProcThreadAttributeList(list, attribute_count, 0, &size)) {
HeapFree(GetProcessHeap(), 0, list);
return NULL;
return nullptr;
}
return list;
@@ -518,7 +518,7 @@ namespace platf {
// Allocate a process attribute list with space for 2 elements
startup_info.lpAttributeList = allocate_proc_thread_attr_list(2);
if (startup_info.lpAttributeList == NULL) {
if (startup_info.lpAttributeList == nullptr) {
// If the allocation failed, set ec to an appropriate error code and return the structure
ec = std::make_error_code(std::errc::not_enough_memory);
return startup_info;
@@ -530,7 +530,7 @@ namespace platf {
// Populate std handles if the caller gave us a log file to use
startup_info.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
startup_info.StartupInfo.hStdInput = NULL;
startup_info.StartupInfo.hStdInput = nullptr;
startup_info.StartupInfo.hStdOutput = log_file_handle;
startup_info.StartupInfo.hStdError = log_file_handle;
@@ -539,7 +539,7 @@ namespace platf {
//
// Note: The value we point to here must be valid for the lifetime of the attribute list,
// so we need to point into the STARTUPINFO instead of our log_file_variable on the stack.
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &startup_info.StartupInfo.hStdOutput, sizeof(startup_info.StartupInfo.hStdOutput), NULL, NULL);
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &startup_info.StartupInfo.hStdOutput, sizeof(startup_info.StartupInfo.hStdOutput), nullptr, nullptr);
}
if (job) {
@@ -547,7 +547,7 @@ namespace platf {
//
// Note: The value we point to here must be valid for the lifetime of the attribute list,
// so we take a HANDLE* instead of just a HANDLE to use the caller's stack storage.
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, job, sizeof(*job), NULL, NULL);
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, job, sizeof(*job), nullptr, nullptr);
}
return startup_info;
@@ -555,11 +555,11 @@ namespace platf {
/**
* @brief This function overrides HKEY_CURRENT_USER and HKEY_CLASSES_ROOT using the provided token.
* @param token The primary token identifying the user to use, or `NULL` to restore original keys.
* @param token The primary token identifying the user to use, or `nullptr` to restore original keys.
* @return `true` if the override or restore operation was successful.
*/
bool override_per_user_predefined_keys(HANDLE token) {
HKEY user_classes_root = NULL;
HKEY user_classes_root = nullptr;
if (token) {
auto err = RegOpenUserClassesRoot(token, 0, GENERIC_ALL, &user_classes_root);
if (err != ERROR_SUCCESS) {
@@ -573,14 +573,14 @@ namespace platf {
}
});
HKEY user_key = NULL;
HKEY user_key = nullptr;
if (token) {
impersonate_current_user(token, [&]() {
// RegOpenCurrentUser() doesn't take a token. It assumes we're impersonating the desired user.
auto err = RegOpenCurrentUser(GENERIC_ALL, &user_key);
if (err != ERROR_SUCCESS) {
BOOST_LOG(error) << "Failed to open user key for target user: "sv << err;
user_key = NULL;
user_key = nullptr;
}
});
if (!user_key) {
@@ -602,7 +602,7 @@ namespace platf {
err = RegOverridePredefKey(HKEY_CURRENT_USER, user_key);
if (err != ERROR_SUCCESS) {
BOOST_LOG(error) << "Failed to override HKEY_CURRENT_USER: "sv << err;
RegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
RegOverridePredefKey(HKEY_CLASSES_ROOT, nullptr);
return false;
}
@@ -671,7 +671,7 @@ namespace platf {
* @details This converts URLs and non-executable file paths into a runnable command like ShellExecute().
* @param raw_cmd The raw command provided by the user.
* @param working_dir The working directory for the new process.
* @param token The user token currently being impersonated or `NULL` if running as ourselves.
* @param token The user token currently being impersonated or `nullptr` if running as ourselves.
* @param creation_flags The creation flags for CreateProcess(), which may be modified by this function.
* @return A command string suitable for use by CreateProcess().
*/
@@ -757,7 +757,7 @@ namespace platf {
}
// Reset per-user keys back to the original value
override_per_user_predefined_keys(NULL);
override_per_user_predefined_keys(nullptr);
}
if (res != S_OK) {
@@ -972,7 +972,7 @@ namespace platf {
ec = impersonate_current_user(user_token, [&]() {
std::wstring env_block = create_environment_block(cloned_env);
std::wstring wcmd = resolve_command_string(cmd, start_dir, user_token, creation_flags);
ret = CreateProcessAsUserW(user_token, NULL, (LPWSTR) wcmd.c_str(), NULL, NULL, !!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES), creation_flags, env_block.data(), start_dir.empty() ? NULL : start_dir.c_str(), (LPSTARTUPINFOW) &startup_info, &process_info);
ret = CreateProcessAsUserW(user_token, nullptr, (LPWSTR) wcmd.c_str(), nullptr, nullptr, !!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES), creation_flags, env_block.data(), start_dir.empty() ? nullptr : start_dir.c_str(), (LPSTARTUPINFOW) &startup_info, &process_info);
});
}
// Otherwise, launch the process using CreateProcessW()
@@ -995,8 +995,8 @@ namespace platf {
}
std::wstring env_block = create_environment_block(cloned_env);
std::wstring wcmd = resolve_command_string(cmd, start_dir, NULL, creation_flags);
ret = CreateProcessW(NULL, (LPWSTR) wcmd.c_str(), NULL, NULL, !!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES), creation_flags, env_block.data(), start_dir.empty() ? NULL : start_dir.c_str(), (LPSTARTUPINFOW) &startup_info, &process_info);
std::wstring wcmd = resolve_command_string(cmd, start_dir, nullptr, creation_flags);
ret = CreateProcessW(nullptr, (LPWSTR) wcmd.c_str(), nullptr, nullptr, !!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES), creation_flags, env_block.data(), start_dir.empty() ? nullptr : start_dir.c_str(), (LPSTARTUPINFOW) &startup_info, &process_info);
}
// Use the results of the launch to create a bp::child object
@@ -1052,7 +1052,7 @@ namespace platf {
static std::once_flag load_wlanapi_once_flag;
std::call_once(load_wlanapi_once_flag, []() {
// wlanapi.dll is not installed by default on Windows Server, so we load it dynamically
HMODULE wlanapi = LoadLibraryExA("wlanapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
HMODULE wlanapi = LoadLibraryExA("wlanapi.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!wlanapi) {
BOOST_LOG(debug) << "wlanapi.dll is not available on this OS"sv;
return;
@@ -1129,7 +1129,7 @@ namespace platf {
fn_WlanFreeMemory(wlan_interface_list);
} else {
fn_WlanCloseHandle(wlan_handle, nullptr);
wlan_handle = NULL;
wlan_handle = nullptr;
}
}
}
@@ -1200,7 +1200,7 @@ namespace platf {
startup_info.StartupInfo.cb = sizeof(startup_info);
WCHAR executable[MAX_PATH];
if (GetModuleFileNameW(NULL, executable, ARRAYSIZE(executable)) == 0) {
if (GetModuleFileNameW(nullptr, executable, ARRAYSIZE(executable)) == 0) {
auto winerr = GetLastError();
BOOST_LOG(fatal) << "Failed to get Sunshine path: "sv << winerr;
return;
@@ -1220,7 +1220,7 @@ namespace platf {
void restart() {
// If we're running standalone, we have to respawn ourselves via CreateProcess().
// If we're running from the service, we should just exit and let it respawn us.
if (GetConsoleWindow() != NULL) {
if (GetConsoleWindow() != nullptr) {
// Avoid racing with the new process by waiting until we're exiting to start it.
atexit(restart_on_exit);
}
@@ -1538,7 +1538,7 @@ namespace platf {
}
virtual ~qos_t() {
if (!fn_QOSRemoveSocketFromFlow(qos_handle, (SOCKET) NULL, flow_id, 0)) {
if (!fn_QOSRemoveSocketFromFlow(qos_handle, (SOCKET) nullptr, flow_id, 0)) {
auto winerr = GetLastError();
BOOST_LOG(warning) << "QOSRemoveSocketFromFlow() failed: "sv << winerr;
}
@@ -1570,7 +1570,7 @@ namespace platf {
static std::once_flag load_qwave_once_flag;
std::call_once(load_qwave_once_flag, []() {
// qWAVE is not installed by default on Windows Server, so we load it dynamically
HMODULE qwave = LoadLibraryExA("qwave.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
HMODULE qwave = LoadLibraryExA("qwave.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!qwave) {
BOOST_LOG(debug) << "qwave.dll is not available on this OS"sv;
return;
@@ -1788,11 +1788,11 @@ namespace platf {
}
operator bool() override {
return timer != NULL;
return timer != nullptr;
}
private:
HANDLE timer = NULL;
HANDLE timer = nullptr;
};
std::unique_ptr<high_precision_timer> create_high_precision_timer() {

View File

@@ -60,7 +60,7 @@ namespace nvprefs {
void driver_settings_t::destroy() {
if (session_handle) {
NvAPI_DRS_DestroySession(session_handle);
session_handle = 0;
session_handle = nullptr;
}
NvAPI_Unload();
}
@@ -105,7 +105,7 @@ namespace nvprefs {
if (swapchain_data) {
NvAPI_Status status;
NvDRSProfileHandle profile_handle = 0;
NvDRSProfileHandle profile_handle = nullptr;
status = NvAPI_DRS_GetBaseProfile(session_handle, &profile_handle);
if (status != NVAPI_OK) {
nvapi_error_message(status);
@@ -168,7 +168,7 @@ namespace nvprefs {
return true;
}
NvDRSProfileHandle profile_handle = 0;
NvDRSProfileHandle profile_handle = nullptr;
status = NvAPI_DRS_GetBaseProfile(session_handle, &profile_handle);
if (status != NVAPI_OK) {
nvapi_error_message(status);
@@ -224,7 +224,7 @@ namespace nvprefs {
NvAPI_UnicodeString profile_name = {};
fill_nvapi_string(profile_name, sunshine_application_profile_name);
NvDRSProfileHandle profile_handle = 0;
NvDRSProfileHandle profile_handle = nullptr;
status = NvAPI_DRS_FindProfileByName(session_handle, profile_name, &profile_handle);
if (status != NVAPI_OK) {

View File

@@ -36,7 +36,7 @@ namespace nvprefs {
bool check_and_modify_application_profile(bool &modified);
private:
NvDRSSessionHandle session_handle = 0;
NvDRSSessionHandle session_handle = nullptr;
};
} // namespace nvprefs

View File

@@ -15,7 +15,7 @@
namespace {
std::map<const char *, void *> interfaces;
HMODULE dll = NULL;
HMODULE dll = nullptr;
template<typename Func, typename... Args>
NvAPI_Status call_interface(const char *name, Args... args) {
@@ -47,7 +47,7 @@ NvAPI_Initialize() {
auto dll_name = "nvapi.dll";
#endif
if ((dll = LoadLibraryEx(dll_name, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
if ((dll = LoadLibraryEx(dll_name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
if (auto query_interface = (decltype(nvapi_QueryInterface) *) GetProcAddress(dll, "nvapi_QueryInterface")) {
for (const auto &item : nvapi_interface_table) {
interfaces[item.func] = query_interface(item.id);
@@ -64,7 +64,7 @@ NVAPI_INTERFACE NvAPI_Unload() {
if (dll) {
interfaces.clear();
FreeLibrary(dll);
dll = NULL;
dll = nullptr;
}
return NVAPI_OK;
}

View File

@@ -21,7 +21,7 @@ namespace nvprefs {
explicit operator bool() const {
auto handle = get();
return handle != NULL && handle != INVALID_HANDLE_VALUE;
return handle != nullptr && handle != INVALID_HANDLE_VALUE;
}
};

View File

@@ -51,7 +51,7 @@ namespace nvprefs {
std::optional<undo_file_t> undo_file_t::open_existing_file(std::filesystem::path file_path, bool &access_denied) {
undo_file_t file;
file.file_handle.reset(CreateFileW(file_path.c_str(), GENERIC_READ | DELETE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
file.file_handle.reset(CreateFileW(file_path.c_str(), GENERIC_READ | DELETE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
if (file.file_handle) {
access_denied = false;
return file;
@@ -64,7 +64,7 @@ namespace nvprefs {
std::optional<undo_file_t> undo_file_t::create_new_file(std::filesystem::path file_path) {
undo_file_t file;
file.file_handle.reset(CreateFileW(file_path.c_str(), GENERIC_WRITE | STANDARD_RIGHTS_ALL, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL));
file.file_handle.reset(CreateFileW(file_path.c_str(), GENERIC_WRITE | STANDARD_RIGHTS_ALL, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr));
if (file.file_handle) {
// give GENERIC_READ, GENERIC_WRITE and DELETE permissions to Users group

View File

@@ -84,7 +84,7 @@ namespace system_tray {
#ifdef _WIN32
// If we're running in a service, return a special status to
// tell it to terminate too, otherwise it will just respawn us.
if (GetConsoleWindow() == NULL) {
if (GetConsoleWindow() == nullptr) {
lifetime::exit_sunshine(ERROR_SHUTDOWN_IN_PROGRESS, true);
return;
}
@@ -230,10 +230,10 @@ namespace system_tray {
return;
}
tray.notification_title = NULL;
tray.notification_text = NULL;
tray.notification_cb = NULL;
tray.notification_icon = NULL;
tray.notification_title = nullptr;
tray.notification_text = nullptr;
tray.notification_cb = nullptr;
tray.notification_icon = nullptr;
tray.icon = TRAY_ICON_PLAYING;
tray_update(&tray);
tray.icon = TRAY_ICON_PLAYING;
@@ -251,10 +251,10 @@ namespace system_tray {
return;
}
tray.notification_title = NULL;
tray.notification_text = NULL;
tray.notification_cb = NULL;
tray.notification_icon = NULL;
tray.notification_title = nullptr;
tray.notification_text = nullptr;
tray.notification_cb = nullptr;
tray.notification_icon = nullptr;
tray.icon = TRAY_ICON_PAUSING;
tray_update(&tray);
char msg[256];
@@ -272,10 +272,10 @@ namespace system_tray {
return;
}
tray.notification_title = NULL;
tray.notification_text = NULL;
tray.notification_cb = NULL;
tray.notification_icon = NULL;
tray.notification_title = nullptr;
tray.notification_text = nullptr;
tray.notification_cb = nullptr;
tray.notification_icon = nullptr;
tray.icon = TRAY_ICON;
tray_update(&tray);
char msg[256];
@@ -293,10 +293,10 @@ namespace system_tray {
return;
}
tray.notification_title = NULL;
tray.notification_text = NULL;
tray.notification_cb = NULL;
tray.notification_icon = NULL;
tray.notification_title = nullptr;
tray.notification_text = nullptr;
tray.notification_cb = nullptr;
tray.notification_icon = nullptr;
tray.icon = TRAY_ICON;
tray_update(&tray);
tray.icon = TRAY_ICON;