mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-06-02 04:35:29 -06:00
Fix several issues discussed in the PR comments. The macOS main thread issue is still open.
This commit is contained in:
parent
3a9de5736e
commit
0d52fb7834
@ -391,6 +391,7 @@ int CemuApp::OnExit()
|
|||||||
{
|
{
|
||||||
wxApp::OnExit();
|
wxApp::OnExit();
|
||||||
wxTheClipboard->Flush();
|
wxTheClipboard->Flush();
|
||||||
|
InputManager::instance().Shutdown();
|
||||||
#if BOOST_OS_WINDOWS
|
#if BOOST_OS_WINDOWS
|
||||||
ExitProcess(0);
|
ExitProcess(0);
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -53,8 +53,7 @@ InputManager::InputManager()
|
|||||||
|
|
||||||
InputManager::~InputManager()
|
InputManager::~InputManager()
|
||||||
{
|
{
|
||||||
m_update_thread_shutdown.store(true);
|
// destructors will not invoked forever, so we manually release resources in Shutdown().
|
||||||
m_update_thread.join();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::load() noexcept
|
void InputManager::load() noexcept
|
||||||
@ -952,3 +951,21 @@ void InputManager::update_thread()
|
|||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InputManager::Shutdown()
|
||||||
|
{
|
||||||
|
m_update_thread_shutdown = true;
|
||||||
|
|
||||||
|
if (m_update_thread.joinable())
|
||||||
|
{
|
||||||
|
m_update_thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& pad : m_vpad) pad.reset();
|
||||||
|
for (auto& pad : m_wpad) pad.reset();
|
||||||
|
|
||||||
|
for (auto& providers : m_api_available)
|
||||||
|
{
|
||||||
|
providers.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -46,6 +46,8 @@ public:
|
|||||||
|
|
||||||
bool is_gameprofile_set(size_t player_index) const;
|
bool is_gameprofile_set(size_t player_index) const;
|
||||||
|
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
EmulatedControllerPtr set_controller(EmulatedControllerPtr controller);
|
EmulatedControllerPtr set_controller(EmulatedControllerPtr controller);
|
||||||
EmulatedControllerPtr set_controller(size_t player_index, EmulatedController::Type type);
|
EmulatedControllerPtr set_controller(size_t player_index, EmulatedController::Type type);
|
||||||
EmulatedControllerPtr set_controller(size_t player_index, EmulatedController::Type type, const std::shared_ptr<ControllerBase>& controller);
|
EmulatedControllerPtr set_controller(size_t player_index, EmulatedController::Type type, const std::shared_ptr<ControllerBase>& controller);
|
||||||
|
|||||||
@ -42,8 +42,25 @@ DSUControllerProvider::~DSUControllerProvider()
|
|||||||
if (m_running)
|
if (m_running)
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_running = false;
|
||||||
m_writer_thread.join();
|
|
||||||
m_reader_thread.join();
|
boost::system::error_code ec;
|
||||||
|
m_socket.shutdown(boost::asio::ip::udp::socket::shutdown_both, ec);
|
||||||
|
m_socket.close(ec);
|
||||||
|
|
||||||
|
if (m_reader_thread.joinable())
|
||||||
|
{
|
||||||
|
m_reader_thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock lock(m_writer_mutex);
|
||||||
|
m_writer_cond.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_writer_thread.joinable())
|
||||||
|
{
|
||||||
|
m_writer_thread.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,6 +278,11 @@ void DSUControllerProvider::reader_thread()
|
|||||||
const size_t len = m_socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint, 0, ec);
|
const size_t len = m_socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint, 0, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
|
if (!m_running.load(std::memory_order_relaxed))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_DSU_CLIENT
|
#ifdef DEBUG_DSU_CLIENT
|
||||||
printf(" DSUControllerProvider::ReaderThread: exception %s\n", ec.what());
|
printf(" DSUControllerProvider::ReaderThread: exception %s\n", ec.what());
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -16,30 +16,6 @@ struct SDL_JoystickGUIDHash
|
|||||||
|
|
||||||
SDLControllerProvider::SDLControllerProvider()
|
SDLControllerProvider::SDLControllerProvider()
|
||||||
{
|
{
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1");
|
|
||||||
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, "1");
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1");
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH2, "1");
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STADIA, "1");
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1");
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_LUNA, "1");
|
|
||||||
|
|
||||||
if (!SDL_Init(SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC))
|
|
||||||
{
|
|
||||||
throw std::runtime_error(fmt::format("couldn't initialize SDL: {}", SDL_GetError()));
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetGamepadEventsEnabled(true);
|
|
||||||
if (!SDL_GamepadEventsEnabled())
|
|
||||||
{
|
|
||||||
cemuLog_log(LogType::Force, "Couldn't enable SDL gamecontroller event polling: {}", SDL_GetError());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_motion_states.reserve(8);
|
m_motion_states.reserve(8);
|
||||||
|
|
||||||
m_running = true;
|
m_running = true;
|
||||||
@ -53,13 +29,15 @@ SDLControllerProvider::~SDLControllerProvider()
|
|||||||
m_running = false;
|
m_running = false;
|
||||||
// wake the thread with a quit event if it's currently waiting for events
|
// wake the thread with a quit event if it's currently waiting for events
|
||||||
SDL_Event evt;
|
SDL_Event evt;
|
||||||
|
SDL_zero(evt);
|
||||||
evt.type = SDL_EVENT_QUIT;
|
evt.type = SDL_EVENT_QUIT;
|
||||||
SDL_PushEvent(&evt);
|
SDL_PushEvent(&evt);
|
||||||
// wait until thread exited
|
|
||||||
m_thread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_QuitSubSystem(SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC);
|
if (m_thread.joinable())
|
||||||
|
{
|
||||||
|
m_thread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<ControllerBase>> SDLControllerProvider::get_controllers()
|
std::vector<std::shared_ptr<ControllerBase>> SDLControllerProvider::get_controllers()
|
||||||
@ -143,6 +121,30 @@ MotionSample SDLControllerProvider::motion_sample(SDL_JoystickID diid)
|
|||||||
void SDLControllerProvider::event_thread()
|
void SDLControllerProvider::event_thread()
|
||||||
{
|
{
|
||||||
SetThreadName("SDL_events");
|
SetThreadName("SDL_events");
|
||||||
|
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH2, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STADIA, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_LUNA, "1");
|
||||||
|
|
||||||
|
if (!SDL_InitSubSystem(SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(fmt::format("couldn't initialize SDL: {}", SDL_GetError()));
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetGamepadEventsEnabled(true);
|
||||||
|
if (!SDL_GamepadEventsEnabled())
|
||||||
|
{
|
||||||
|
cemuLog_log(LogType::Force, "Couldn't enable SDL gamecontroller event polling: {}", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
while (m_running.load(std::memory_order_relaxed))
|
while (m_running.load(std::memory_order_relaxed))
|
||||||
{
|
{
|
||||||
SDL_Event event{};
|
SDL_Event event{};
|
||||||
@ -153,9 +155,8 @@ void SDLControllerProvider::event_thread()
|
|||||||
case SDL_EVENT_QUIT:
|
case SDL_EVENT_QUIT:
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_running = false;
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION: /**< Game controller axis motion */
|
case SDL_EVENT_GAMEPAD_AXIS_MOTION: /**< Game controller axis motion */
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -275,4 +276,5 @@ void SDLControllerProvider::event_thread()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,9 +25,31 @@ WiimoteControllerProvider::~WiimoteControllerProvider()
|
|||||||
if (m_running)
|
if (m_running)
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_running = false;
|
||||||
m_writer_thread.join();
|
|
||||||
m_reader_thread.join();
|
{
|
||||||
m_connectionThread.join();
|
std::scoped_lock lock(m_writer_mutex);
|
||||||
|
m_writer_cond.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock lock(m_connectionMutex);
|
||||||
|
m_connectionCond.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_writer_thread.joinable())
|
||||||
|
{
|
||||||
|
m_writer_thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_reader_thread.joinable())
|
||||||
|
{
|
||||||
|
m_reader_thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_connectionThread.joinable())
|
||||||
|
{
|
||||||
|
m_connectionThread.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +191,8 @@ void WiimoteControllerProvider::connectionThread()
|
|||||||
m_connectedDevices.clear();
|
m_connectedDevices.clear();
|
||||||
std::ranges::move(devices, std::back_inserter(m_connectedDevices));
|
std::ranges::move(devices, std::back_inserter(m_connectedDevices));
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
std::unique_lock<std::mutex> lock(m_connectionMutex);
|
||||||
|
m_connectionCond.wait_for(lock, std::chrono::seconds(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -80,6 +80,8 @@ private:
|
|||||||
std::shared_mutex m_device_mutex;
|
std::shared_mutex m_device_mutex;
|
||||||
|
|
||||||
std::thread m_connectionThread;
|
std::thread m_connectionThread;
|
||||||
|
std::mutex m_connectionMutex;
|
||||||
|
std::condition_variable m_connectionCond;
|
||||||
std::vector<WiimoteDevicePtr> m_connectedDevices;
|
std::vector<WiimoteDevicePtr> m_connectedDevices;
|
||||||
std::mutex m_connectedDeviceMutex;
|
std::mutex m_connectedDeviceMutex;
|
||||||
struct Wiimote
|
struct Wiimote
|
||||||
|
|||||||
@ -4,37 +4,62 @@
|
|||||||
class ScreenSaver
|
class ScreenSaver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void SetInhibit(bool inhibit)
|
static void SetInhibit(bool inhibit)
|
||||||
{
|
{
|
||||||
// temporary workaround because feature crashes on macOS
|
// temporary workaround because feature crashes on macOS
|
||||||
#if BOOST_OS_MACOS
|
#if BOOST_OS_MACOS
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
// Initialize video subsystem if necessary
|
bool* inhibitArg = new bool(inhibit);
|
||||||
if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
|
|
||||||
{
|
if (!SDL_RunOnMainThread(SetInhibitCallback, inhibitArg, false))
|
||||||
int initErr = SDL_InitSubSystem(SDL_INIT_VIDEO);
|
{
|
||||||
if (initErr)
|
delete inhibitArg;
|
||||||
{
|
cemuLog_log(LogType::Force, "Failed to schedule screen saver logic on main thread: {}", SDL_GetError());
|
||||||
cemuLog_log(LogType::Force, "Could not disable screen saver (SDL video subsystem initialization error)");
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Toggle SDL's screen saver inhibition
|
private:
|
||||||
if (inhibit)
|
static void SDLCALL SetInhibitCallback(void* userdata)
|
||||||
{
|
{
|
||||||
SDL_DisableScreenSaver();
|
if (!userdata)
|
||||||
if (SDL_ScreenSaverEnabled())
|
{
|
||||||
{
|
return;
|
||||||
cemuLog_log(LogType::Force, "Could not verify if screen saver was disabled (`SDL_IsScreenSaverEnabled()` returned SDL_TRUE)");
|
}
|
||||||
}
|
|
||||||
}
|
bool inhibit = *static_cast<bool*>(userdata);
|
||||||
else
|
SDL_free(userdata);
|
||||||
{
|
|
||||||
SDL_EnableScreenSaver();
|
if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
|
||||||
if (!SDL_ScreenSaverEnabled())
|
{
|
||||||
{
|
if (!SDL_InitSubSystem(SDL_INIT_VIDEO))
|
||||||
cemuLog_log(LogType::Force, "Could not verify if screen saver was re-enabled (`SDL_IsScreenSaverEnabled()` returned SDL_FALSE)");
|
{
|
||||||
}
|
cemuLog_log(LogType::Force, "Could not disable screen saver (SDL video subsystem initialization error: {})", SDL_GetError());
|
||||||
}
|
return;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inhibit)
|
||||||
|
{
|
||||||
|
if (!SDL_DisableScreenSaver())
|
||||||
|
{
|
||||||
|
cemuLog_log(LogType::Force, "Could not disable screen saver: {}", SDL_GetError());
|
||||||
|
}
|
||||||
|
else if (SDL_ScreenSaverEnabled())
|
||||||
|
{
|
||||||
|
cemuLog_log(LogType::Force, "Could not verify if screen saver was disabled (`SDL_IsScreenSaverEnabled()` returned true)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!SDL_EnableScreenSaver())
|
||||||
|
{
|
||||||
|
cemuLog_log(LogType::Force, "Could not enable screen saver: {}", SDL_GetError());
|
||||||
|
}
|
||||||
|
else if (!SDL_ScreenSaverEnabled())
|
||||||
|
{
|
||||||
|
cemuLog_log(LogType::Force, "Could not verify if screen saver was re-enabled (`SDL_IsScreenSaverEnabled()` returned false)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user