Skip to content

Commit 2c29ae4

Browse files
authored
Merge pull request #20 from jpflouret/main
Feature: Add connection status to RdpGamepadReceiver
2 parents 5fa868b + 20b9ddd commit 2c29ae4

File tree

6 files changed

+72
-9
lines changed

6 files changed

+72
-9
lines changed

RdpGamepadViGEm/RdpGamepadProcessor.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
#include "ViGEmInterface.h"
99
#include <RdpGamepadProtocol.h>
1010

11-
RdpGamepadProcessor::RdpGamepadProcessor()
12-
: mRdpGamepadChannel(new RdpGamepad::RdpGamepadVirtualChannel())
11+
RdpGamepadProcessor::RdpGamepadProcessor(std::function<void()> ConnectionStateCallback)
12+
: mConnectionStateCallback(std::move(ConnectionStateCallback))
13+
, mRdpGamepadChannel(new RdpGamepad::RdpGamepadVirtualChannel())
1314
, mViGEmClient(std::make_shared<ViGEmClient>())
1415
{}
1516

@@ -31,6 +32,12 @@ void RdpGamepadProcessor::Stop()
3132
mThread.join();
3233
}
3334

35+
bool RdpGamepadProcessor::IsConnected() const
36+
{
37+
std::unique_lock<std::mutex> lock{mMutex};
38+
return mRdpGamepadConnected;
39+
}
40+
3441
void RdpGamepadProcessor::Run()
3542
{
3643
static constexpr int PollFrequency = 16; // ms
@@ -40,12 +47,19 @@ void RdpGamepadProcessor::Run()
4047
DueTime.QuadPart = -1;
4148

4249
TimerEvent = CreateWaitableTimerEx(NULL, NULL, 0, TIMER_ALL_ACCESS);
50+
if (TimerEvent == nullptr)
51+
{
52+
RdpGamepadTidy();
53+
return;
54+
}
55+
4356
SetWaitableTimer(TimerEvent, &DueTime, PollFrequency, NULL, NULL, false);
4457

4558
std::unique_lock<std::mutex> lock{mMutex};
4659
while (mKeepRunning)
4760
{
4861
mMutex.unlock();
62+
TriggerConnectionStateCallback();
4963
const unsigned long WaitResult = WaitForSingleObject(TimerEvent, PollFrequency * 2);
5064
mMutex.lock();
5165

@@ -62,10 +76,15 @@ void RdpGamepadProcessor::Run()
6276

6377
void RdpGamepadProcessor::RdpGamepadTidy()
6478
{
79+
bool bWasConnected = mRdpGamepadConnected;
6580
mViGEmTarget360 = nullptr;
6681
mRdpGamepadChannel->Close();
6782
mRdpGamepadConnected = false;
6883
mRdpGamepadPollTicks = 0;
84+
if (bWasConnected)
85+
{
86+
mConnectionStateCallbackPending = true;
87+
}
6988
}
7089

7190
void RdpGamepadProcessor::RdpGamepadProcess()
@@ -101,6 +120,7 @@ void RdpGamepadProcessor::RdpGamepadProcess()
101120
//assert(mViGEmTarget360 == nullptr)
102121
mViGEmTarget360 = mViGEmClient->CreateController();
103122
mRdpGamepadConnected = true;
123+
mConnectionStateCallbackPending = true;
104124
}
105125

106126
// Request controller state and update vibration
@@ -154,3 +174,12 @@ void RdpGamepadProcessor::RdpGamepadProcess()
154174
RdpGamepadTidy();
155175
}
156176
}
177+
178+
void RdpGamepadProcessor::TriggerConnectionStateCallback()
179+
{
180+
if (mConnectionStateCallbackPending && mConnectionStateCallback)
181+
{
182+
mConnectionStateCallback();
183+
mConnectionStateCallbackPending = false;
184+
}
185+
}

RdpGamepadViGEm/RdpGamepadProcessor.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,29 @@ class ViGEmTarget360;
1414
class RdpGamepadProcessor
1515
{
1616
public:
17-
RdpGamepadProcessor();
17+
explicit RdpGamepadProcessor(std::function<void()> ConnectionStateCallback);
1818
~RdpGamepadProcessor();
1919

2020
void Start();
2121
void Stop();
22+
bool IsConnected() const;
2223

2324
private:
25+
std::function<void()> mConnectionStateCallback;
2426
std::unique_ptr<RdpGamepad::RdpGamepadVirtualChannel> mRdpGamepadChannel;
2527
std::shared_ptr<ViGEmClient> mViGEmClient;
2628
std::shared_ptr<ViGEmTarget360> mViGEmTarget360;
2729
std::thread mThread;
28-
std::mutex mMutex;
30+
mutable std::mutex mMutex;
2931
unsigned int mRdpGamepadOpenRetry = 0;
3032
unsigned int mRdpGamepadPollTicks = 0;
3133
unsigned int mLastGetStateResponseTicks = 0;
3234
bool mRdpGamepadConnected = false;
3335
bool mKeepRunning = false;
36+
bool mConnectionStateCallbackPending = false;
3437

3538
void Run();
3639
void RdpGamepadTidy();
3740
void RdpGamepadProcess();
41+
void TriggerConnectionStateCallback();
3842
};

RdpGamepadViGEm/RdpGamepadViGEmApp.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99
#include <shellapi.h>
1010

1111
static constexpr UINT RDPGAMEPAD_NOTIFY_MESSAGE = WM_APP + 100;
12+
static constexpr UINT RDPGAMEPAD_CONNECTION_UPDATE_MESSAGE = WM_APP + 101;
1213

1314
class RdpGamepadViGEmApp
1415
{
1516
public:
1617
RdpGamepadViGEmApp()
18+
: mRdpProcessor(std::bind(&RdpGamepadViGEmApp::ConnectionStateChanged, this))
1719
{
1820
mRdpProcessor.Start();
1921
}
@@ -41,6 +43,7 @@ class RdpGamepadViGEmApp
4143
HideNotifyIcon();
4244
ReleaseSingleAppMutex();
4345

46+
mWnd = nullptr;
4447
return ret;
4548
}
4649

@@ -73,6 +76,7 @@ class RdpGamepadViGEmApp
7376
{
7477
ReleaseMutex(mGlobalMutex);
7578
CloseHandle(mGlobalMutex);
79+
mGlobalMutex = nullptr;
7680
}
7781

7882
void RegisterWindowClass()
@@ -126,7 +130,15 @@ class RdpGamepadViGEmApp
126130
GetSystemMetrics(SM_CXSMICON),
127131
GetSystemMetrics(SM_CYSMICON),
128132
LR_DEFAULTCOLOR);
129-
StringCchCopy(mNotifyIconData.szTip, ARRAYSIZE(mNotifyIconData.szTip), L"Microsoft Remote Desktop Gamepad Receiver");
133+
134+
UpdateToolTip();
135+
}
136+
137+
void UpdateToolTip()
138+
{
139+
LPCWSTR szTip = mRdpProcessor.IsConnected() ? L"Microsoft Remote Desktop Gamepad Receiver - Connected"
140+
: L"Microsoft Remote Desktop Gamepad Receiver - Disconnected";
141+
StringCchCopy(mNotifyIconData.szTip, ARRAYSIZE(mNotifyIconData.szTip), szTip);
130142
}
131143

132144
void ShowNotifyIcon()
@@ -140,6 +152,19 @@ class RdpGamepadViGEmApp
140152
Shell_NotifyIcon(NIM_DELETE, &mNotifyIconData);
141153
}
142154

155+
void UpdateNotifyIcon()
156+
{
157+
Shell_NotifyIcon(NIM_MODIFY, &mNotifyIconData);
158+
}
159+
160+
void ConnectionStateChanged()
161+
{
162+
if (mWnd != nullptr)
163+
{
164+
PostMessage(mWnd, RDPGAMEPAD_CONNECTION_UPDATE_MESSAGE, 0, 0);
165+
}
166+
}
167+
143168
void ShowPopupMenu()
144169
{
145170
HMENU hMenu = LoadMenu(mInstance, MAKEINTRESOURCE(IDR_POPUPMENU));
@@ -198,6 +223,11 @@ class RdpGamepadViGEmApp
198223
}
199224
break;
200225

226+
case RDPGAMEPAD_CONNECTION_UPDATE_MESSAGE:
227+
UpdateToolTip();
228+
UpdateNotifyIcon();
229+
break;
230+
201231
case WM_DESTROY:
202232
HideNotifyIcon();
203233
PostQuitMessage(0);
@@ -220,7 +250,7 @@ class RdpGamepadViGEmApp
220250
}
221251
};
222252

223-
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
253+
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nShowCmd)
224254
{
225255
RdpGamepadViGEmApp TheApp;
226256
return TheApp.Run(hInstance);

Setup/RdpGamepadClientInstall.iss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#define MyAppPublisher "Microsoft Corporation"
88
#define MyAppPublisherURL "https://www.microsoft.com"
99
#define MyAppURL "https://github.com/Microsoft/RdpGamepad"
10-
#define MyAppVersion "1.0.1"
10+
#define MyAppVersion "1.0.2"
1111

1212
[Setup]
1313
; NOTE: The value of AppId uniquely identifies this application.

Setup/RdpGamepadReceiverInstall.iss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#define MyAppPublisher "Microsoft Corporation"
88
#define MyAppPublisherURL "https://www.microsoft.com"
99
#define MyAppURL "https://github.com/Microsoft/RdpGamepad"
10-
#define MyAppVersion "1.0.1"
10+
#define MyAppVersion "1.0.2"
1111

1212
[Setup]
1313
; NOTE: The value of AppId uniquely identifies this application.

ViGEmClient

0 commit comments

Comments
 (0)