Skip to content

Commit 0f7daf5

Browse files
committed
Add wake_sleep functionality to Windows
2 parents 14c84ce + 47973ae commit 0f7daf5

File tree

10 files changed

+175
-7
lines changed

10 files changed

+175
-7
lines changed

gui/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ if(APPLE)
7777
include/macWakeSleep.h
7878
src/macWakeSleep.cpp
7979
)
80+
elseif(WIN32)
81+
list(APPEND SOURCE_FILES
82+
include/windowsWakeSleep.h
83+
src/windowsWakeSleep.cpp
84+
)
8085
endif()
8186

8287
add_executable(chiaki WIN32

gui/include/qmlbackend.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
class SystemdInhibit;
2121
#ifdef Q_OS_MACOS
2222
class MacWakeSleep;
23+
#elif defined(Q_OS_WINDOWS)
24+
class WindowsWakeSleep;
2325
#endif
2426

2527
class QmlRegist : public QObject
@@ -290,6 +292,8 @@ class QmlBackend : public QObject
290292
SystemdInhibit *sleep_inhibit = {};
291293
#ifdef Q_OS_MACOS
292294
MacWakeSleep *mac_wake_sleep = {};
295+
#elif defined(Q_OS_WINDOWS)
296+
WindowsWakeSleep *windows_wake_sleep = {};
293297
#endif
294298
bool controller_mapping_default_mapping = false;
295299
bool controller_mapping_altered = false;

gui/include/windowsWakeSleep.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
3+
#include <QObject>
4+
#include <windows.h>
5+
6+
typedef enum windows_wake_state_t {
7+
Awake = 0,
8+
AboutToSleep = 1,
9+
Sleeping = 2
10+
} WindowsWakeState;
11+
12+
class WindowsWakeSleep : public QObject
13+
{
14+
Q_OBJECT
15+
16+
public:
17+
WindowsWakeSleep(QObject *parent = nullptr);
18+
~WindowsWakeSleep();
19+
void awake();
20+
void aboutToSleep();
21+
WindowsWakeState getWakeState();
22+
void setWakeState(WindowsWakeState state);
23+
24+
signals:
25+
void wokeUp();
26+
void sleeping();
27+
28+
private:
29+
HPOWERNOTIFY hPowerNotify = {};
30+
WindowsWakeState wake_state = WindowsWakeState::Awake;
31+
};

gui/src/qml/qtwebengine_import.qml

Lines changed: 0 additions & 1 deletion
This file was deleted.

gui/src/qmlbackend.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include "chiaki/remote/holepunch.h"
1010
#ifdef Q_OS_MACOS
1111
#include "macWakeSleep.h"
12+
#elif defined(Q_OS_WINDOWS)
13+
#include "windowsWakeSleep.h"
1214
#endif
1315
#if CHIAKI_GUI_ENABLE_STEAM_SHORTCUT
1416
#include "steamtools.h"
@@ -227,6 +229,10 @@ QmlBackend::QmlBackend(Settings *settings, QmlMainWindow *window)
227229
mac_wake_sleep = new MacWakeSleep(this);
228230
connect(mac_wake_sleep, &MacWakeSleep::wokeUp, this, &QmlBackend::resumeFromSleep);
229231
connect(ControllerManager::GetInstance(), &ControllerManager::ControllerMoved, mac_wake_sleep, &MacWakeSleep::simulateUserActivity);
232+
#elif defined(Q_OS_WINDOWS)
233+
windows_wake_sleep = new WindowsWakeSleep(this);
234+
connect(windows_wake_sleep, &WindowsWakeSleep::wokeUp, this, &QmlBackend::resumeFromSleep);
235+
connect(windows_wake_sleep, &WindowsWakeSleep::sleeping, this, &QmlBackend::goToSleep);
230236
#endif
231237
refreshPsnToken();
232238
}
@@ -287,7 +293,14 @@ void QmlBackend::goToSleep()
287293
}
288294
void QmlBackend::resumeFromSleep()
289295
{
290-
qCInfo(chiakiGui) << "Resumed from sleep";
296+
#ifdef Q_OS_WINDOWS
297+
if(windows_wake_sleep->getWakeState() == WindowsWakeState::AboutToSleep)
298+
{
299+
windows_wake_sleep->setWakeState(WindowsWakeState::Awake);
300+
return;
301+
}
302+
windows_wake_sleep->setWakeState(WindowsWakeState::Awake);
303+
#endif
291304
if (resume_session) {
292305
qCInfo(chiakiGui) << "Resuming session...";
293306
resume_session = false;
@@ -418,6 +431,11 @@ void QmlBackend::profileChanged()
418431
mac_wake_sleep = new MacWakeSleep(this);
419432
connect(mac_wake_sleep, &MacWakeSleep::wokeUp, this, &QmlBackend::resumeFromSleep);
420433
connect(ControllerManager::GetInstance(), &ControllerManager::ControllerMoved, mac_wake_sleep, &MacWakeSleep::simulateUserActivity);
434+
#elif defined(Q_OS_WINDOWS)
435+
windows_wake_sleep->deleteLater();
436+
windows_wake_sleep = new WindowsWakeSleep(this);
437+
connect(windows_wake_sleep, &WindowsWakeSleep::wokeUp, this, &QmlBackend::resumeFromSleep);
438+
connect(windows_wake_sleep, &WindowsWakeSleep::sleeping, this, &QmlBackend::goToSleep);
421439
#endif
422440
refreshPsnToken();
423441
emit hostsChanged();
@@ -791,6 +809,13 @@ void QmlBackend::createSession(const StreamSessionConnectInfo &connect_info)
791809

792810
sleep_inhibit->release();
793811
setDiscoveryEnabled(true);
812+
#ifdef Q_OS_WINDOWS
813+
qCInfo(chiakiGui) << "Checking sleep state: ";
814+
if(windows_wake_sleep->getWakeState() == WindowsWakeState::Awake)
815+
QTimer::singleShot(2000, this, &QmlBackend::resumeFromSleep);
816+
else
817+
windows_wake_sleep->setWakeState(WindowsWakeState::Sleeping);
818+
#endif
794819
});
795820

796821
connect(session, &StreamSession::LoginPINRequested, this, [this, connect_info](bool incorrect) {

gui/src/windowsWakeSleep.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#include "windowsWakeSleep.h"
2+
#include "qmlmainwindow.h"
3+
extern "C" {
4+
#include <powrprof.h>
5+
}
6+
#pragma comment(lib, "powrprof.lib")
7+
8+
static ULONG MySleepCallBack(PVOID windowsWakeSleep, ULONG messageType, PVOID Setting)
9+
{
10+
11+
WindowsWakeSleep *windows_wake_sleep = reinterpret_cast<WindowsWakeSleep *>(windowsWakeSleep);
12+
switch (messageType)
13+
{
14+
case PBT_APMSUSPEND:
15+
/* System is suspending
16+
Perform needed actions before system goes to sleep
17+
*/
18+
windows_wake_sleep->aboutToSleep();
19+
20+
case PBT_APMRESUMESUSPEND:
21+
22+
/* System is resuming from suspend
23+
Perform needed action after waking up
24+
*/
25+
windows_wake_sleep->awake();
26+
break;
27+
28+
case PBT_APMRESUMEAUTOMATIC:
29+
30+
/* System is resuming automatically (i.e., scheduled wake-up)
31+
Perform needed action after waking up
32+
*/
33+
windows_wake_sleep->awake();
34+
break;
35+
36+
default:
37+
38+
break;
39+
}
40+
return 0;
41+
}
42+
43+
WindowsWakeSleep::WindowsWakeSleep(QObject *parent)
44+
: QObject(parent)
45+
, wake_state(WindowsWakeState::Awake)
46+
{
47+
#ifndef DEVICE_NOTIFY_CALLBACK
48+
#define DEVICE_NOTIFY_CALLBACK 2
49+
#endif
50+
#ifndef DEVICE_NOTIFY_CALLBACK_ROUTINE
51+
typedef
52+
ULONG
53+
CALLBACK
54+
DEVICE_NOTIFY_CALLBACK_ROUTINE (
55+
_In_opt_ PVOID Context,
56+
_In_ ULONG Type,
57+
_In_ PVOID Setting
58+
);
59+
typedef DEVICE_NOTIFY_CALLBACK_ROUTINE* PDEVICE_NOTIFY_CALLBACK_ROUTINE;
60+
#endif
61+
#ifndef _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
62+
typedef struct _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS {
63+
PDEVICE_NOTIFY_CALLBACK_ROUTINE Callback;
64+
PVOID Context;
65+
} DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS, *PDEVICE_NOTIFY_SUBSCRIBE_PARAMETERS;
66+
#endif
67+
static DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS sleepCallback = {
68+
MySleepCallBack,
69+
this
70+
};
71+
// register to receive system sleep notifications
72+
hPowerNotify = RegisterSuspendResumeNotification(&sleepCallback, DEVICE_NOTIFY_CALLBACK);
73+
if (hPowerNotify == NULL)
74+
{
75+
qCCritical(chiakiGui) << "Failed to register for system sleep notifications with error:" << GetLastError();
76+
}
77+
}
78+
79+
WindowsWakeSleep::~WindowsWakeSleep()
80+
{
81+
// unregister for system sleep notifications
82+
UnregisterSuspendResumeNotification(hPowerNotify);
83+
}
84+
85+
void WindowsWakeSleep::setWakeState(WindowsWakeState state)
86+
{
87+
this->wake_state = state;
88+
}
89+
90+
WindowsWakeState WindowsWakeSleep::getWakeState()
91+
{
92+
return this->wake_state;
93+
}
94+
95+
void WindowsWakeSleep::awake()
96+
{
97+
emit wokeUp();
98+
}
99+
100+
void WindowsWakeSleep::aboutToSleep()
101+
{
102+
setWakeState(WindowsWakeState::AboutToSleep);
103+
emit sleeping();
104+
}

lib/include/chiaki/stoppipe.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto
4646
/**
4747
* Like connect(), but can be canceled by the stop pipe. Only makes sense with a non-blocking socket.
4848
*/
49-
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_connect(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, struct sockaddr *addr, size_t addrlen);
49+
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_connect(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, struct sockaddr *addr, size_t addrlen, uint64_t timeout_ms);
5050
static inline ChiakiErrorCode chiaki_stop_pipe_sleep(ChiakiStopPipe *stop_pipe, uint64_t timeout_ms) { return chiaki_stop_pipe_select_single(stop_pipe, CHIAKI_INVALID_SOCKET, false, timeout_ms); }
5151
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_reset(ChiakiStopPipe *stop_pipe);
5252

lib/src/ctrl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl)
11101110
CHIAKI_LOGE(session->log, "Failed to set ctrl socket to non-blocking: %s", chiaki_error_string(err));
11111111

11121112
chiaki_mutex_unlock(&ctrl->notif_mutex);
1113-
err = chiaki_stop_pipe_connect(&ctrl->notif_pipe, sock, sa, addr->ai_addrlen);
1113+
err = chiaki_stop_pipe_connect(&ctrl->notif_pipe, sock, sa, addr->ai_addrlen, 5000);
11141114
chiaki_mutex_lock(&ctrl->notif_mutex);
11151115
free(sa);
11161116
if(err != CHIAKI_ERR_SUCCESS)

lib/src/session.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ static ChiakiErrorCode session_thread_request_session(ChiakiSession *session, Ch
824824
CHIAKI_LOGE(session->log, "Failed to set session socket to non-blocking: %s", chiaki_error_string(err));
825825

826826
chiaki_mutex_unlock(&session->state_mutex);
827-
err = chiaki_stop_pipe_connect(&session->stop_pipe, session_sock, sa, ai->ai_addrlen);
827+
err = chiaki_stop_pipe_connect(&session->stop_pipe, session_sock, sa, ai->ai_addrlen, 5000);
828828
chiaki_mutex_lock(&session->state_mutex);
829829
if(err == CHIAKI_ERR_CANCELED)
830830
{

lib/src/stoppipe.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,15 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto
170170
#endif
171171
}
172172

173-
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_connect(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, struct sockaddr *addr, size_t addrlen)
173+
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_connect(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, struct sockaddr *addr, size_t addrlen, uint64_t timeout_ms)
174174
{
175175
int r = connect(fd, addr, (socklen_t)addrlen);
176176
if(r >= 0)
177177
return CHIAKI_ERR_SUCCESS;
178178

179179
if(CHIAKI_SOCKET_EINPROGRESS)
180180
{
181-
ChiakiErrorCode err = chiaki_stop_pipe_select_single(stop_pipe, fd, true, UINT64_MAX);
181+
ChiakiErrorCode err = chiaki_stop_pipe_select_single(stop_pipe, fd, true, timeout_ms);
182182
if(err != CHIAKI_ERR_SUCCESS)
183183
return err;
184184
}

0 commit comments

Comments
 (0)