mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-04-22 08:11:28 -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();
|
||||
wxTheClipboard->Flush();
|
||||
InputManager::instance().Shutdown();
|
||||
#if BOOST_OS_WINDOWS
|
||||
ExitProcess(0);
|
||||
#else
|
||||
|
||||
@ -53,8 +53,7 @@ InputManager::InputManager()
|
||||
|
||||
InputManager::~InputManager()
|
||||
{
|
||||
m_update_thread_shutdown.store(true);
|
||||
m_update_thread.join();
|
||||
// destructors will not invoked forever, so we manually release resources in Shutdown().
|
||||
}
|
||||
|
||||
void InputManager::load() noexcept
|
||||
@ -952,3 +951,21 @@ void InputManager::update_thread()
|
||||
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;
|
||||
|
||||
void Shutdown();
|
||||
|
||||
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, const std::shared_ptr<ControllerBase>& controller);
|
||||
|
||||
@ -42,8 +42,25 @@ DSUControllerProvider::~DSUControllerProvider()
|
||||
if (m_running)
|
||||
{
|
||||
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);
|
||||
if (ec)
|
||||
{
|
||||
if (!m_running.load(std::memory_order_relaxed))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DSU_CLIENT
|
||||
printf(" DSUControllerProvider::ReaderThread: exception %s\n", ec.what());
|
||||
#endif
|
||||
|
||||
@ -16,30 +16,6 @@ struct SDL_JoystickGUIDHash
|
||||
|
||||
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_running = true;
|
||||
@ -53,13 +29,15 @@ SDLControllerProvider::~SDLControllerProvider()
|
||||
m_running = false;
|
||||
// wake the thread with a quit event if it's currently waiting for events
|
||||
SDL_Event evt;
|
||||
SDL_zero(evt);
|
||||
evt.type = SDL_EVENT_QUIT;
|
||||
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()
|
||||
@ -143,6 +121,30 @@ MotionSample SDLControllerProvider::motion_sample(SDL_JoystickID diid)
|
||||
void SDLControllerProvider::event_thread()
|
||||
{
|
||||
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))
|
||||
{
|
||||
SDL_Event event{};
|
||||
@ -153,9 +155,8 @@ void SDLControllerProvider::event_thread()
|
||||
case SDL_EVENT_QUIT:
|
||||
{
|
||||
m_running = false;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION: /**< Game controller axis motion */
|
||||
{
|
||||
break;
|
||||
@ -275,4 +276,5 @@ void SDLControllerProvider::event_thread()
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC);
|
||||
}
|
||||
|
||||
@ -30,11 +30,11 @@ public:
|
||||
|
||||
private:
|
||||
void event_thread();
|
||||
|
||||
|
||||
std::atomic_bool m_running = false;
|
||||
std::thread m_thread;
|
||||
mutable std::shared_mutex m_mutex;
|
||||
|
||||
|
||||
struct MotionInfoTracking
|
||||
{
|
||||
uint64 lastTimestampGyro{};
|
||||
|
||||
@ -25,9 +25,31 @@ WiimoteControllerProvider::~WiimoteControllerProvider()
|
||||
if (m_running)
|
||||
{
|
||||
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();
|
||||
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::thread m_connectionThread;
|
||||
std::mutex m_connectionMutex;
|
||||
std::condition_variable m_connectionCond;
|
||||
std::vector<WiimoteDevicePtr> m_connectedDevices;
|
||||
std::mutex m_connectedDeviceMutex;
|
||||
struct Wiimote
|
||||
|
||||
@ -4,37 +4,62 @@
|
||||
class ScreenSaver
|
||||
{
|
||||
public:
|
||||
static void SetInhibit(bool inhibit)
|
||||
{
|
||||
// temporary workaround because feature crashes on macOS
|
||||
static void SetInhibit(bool inhibit)
|
||||
{
|
||||
// temporary workaround because feature crashes on macOS
|
||||
#if BOOST_OS_MACOS
|
||||
return;
|
||||
return;
|
||||
#endif
|
||||
// Initialize video subsystem if necessary
|
||||
if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
|
||||
{
|
||||
int initErr = SDL_InitSubSystem(SDL_INIT_VIDEO);
|
||||
if (initErr)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "Could not disable screen saver (SDL video subsystem initialization error)");
|
||||
}
|
||||
}
|
||||
// Toggle SDL's screen saver inhibition
|
||||
if (inhibit)
|
||||
{
|
||||
SDL_DisableScreenSaver();
|
||||
if (SDL_ScreenSaverEnabled())
|
||||
{
|
||||
cemuLog_log(LogType::Force, "Could not verify if screen saver was disabled (`SDL_IsScreenSaverEnabled()` returned SDL_TRUE)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_EnableScreenSaver();
|
||||
if (!SDL_ScreenSaverEnabled())
|
||||
{
|
||||
cemuLog_log(LogType::Force, "Could not verify if screen saver was re-enabled (`SDL_IsScreenSaverEnabled()` returned SDL_FALSE)");
|
||||
}
|
||||
}
|
||||
};
|
||||
bool* inhibitArg = new bool(inhibit);
|
||||
|
||||
if (!SDL_RunOnMainThread(SetInhibitCallback, inhibitArg, false))
|
||||
{
|
||||
delete inhibitArg;
|
||||
cemuLog_log(LogType::Force, "Failed to schedule screen saver logic on main thread: {}", SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void SDLCALL SetInhibitCallback(void* userdata)
|
||||
{
|
||||
if (!userdata)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool inhibit = *static_cast<bool*>(userdata);
|
||||
SDL_free(userdata);
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
|
||||
{
|
||||
if (!SDL_InitSubSystem(SDL_INIT_VIDEO))
|
||||
{
|
||||
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