CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/UWP/PPSSPP_UWPMain.cpp
Views: 1401
1
#include "pch.h"
2
#include "PPSSPP_UWPMain.h"
3
4
#include <mutex>
5
#include <list>
6
#include <memory>
7
8
#include "Common/File/FileUtil.h"
9
#include "Common/Net/HTTPClient.h"
10
#include "Common/Net/Resolve.h"
11
#include "Common/GPU/thin3d_create.h"
12
13
#include "Common/Common.h"
14
#include "Common/Input/InputState.h"
15
#include "Common/File/VFS/VFS.h"
16
#include "Common/Thread/ThreadUtil.h"
17
#include "Common/Data/Encoding/Utf8.h"
18
#include "Common/DirectXHelper.h"
19
#include "Common/File/FileUtil.h"
20
#include "Common/Log.h"
21
#include "Common/Log/LogManager.h"
22
#include "Common/TimeUtil.h"
23
#include "Common/StringUtils.h"
24
#include "Common/System/Display.h"
25
#include "Common/System/NativeApp.h"
26
#include "Common/System/Request.h"
27
28
#include "Core/System.h"
29
#include "Core/Loaders.h"
30
#include "Core/Config.h"
31
32
#include "Windows/InputDevice.h"
33
#include "Windows/XinputDevice.h"
34
#include "NKCodeFromWindowsSystem.h"
35
#include "XAudioSoundStream.h"
36
#include "UWPUtil.h"
37
#include "App.h"
38
39
// UWP Helpers includes
40
#include "UWPHelpers/StorageManager.h"
41
#include "UWPHelpers/StorageAsync.h"
42
#include "UWPHelpers/LaunchItem.h"
43
#include "UWPHelpers/InputHelpers.h"
44
45
using namespace UWP;
46
using namespace Windows::Foundation;
47
using namespace Windows::Storage;
48
using namespace Windows::Storage::Streams;
49
using namespace Windows::System::Threading;
50
using namespace Windows::ApplicationModel::DataTransfer;
51
using namespace Windows::Devices::Enumeration;
52
using namespace Concurrency;
53
54
// UGLY!
55
extern WindowsAudioBackend *winAudioBackend;
56
std::list<std::unique_ptr<InputDevice>> g_input;
57
58
// TODO: Use Microsoft::WRL::ComPtr<> for D3D11 objects?
59
// TODO: See https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/WindowsAudioSession for WASAPI with UWP
60
// TODO: Low latency input: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/LowLatencyInput/cpp
61
62
// Loads and initializes application assets when the application is loaded.
63
PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptr<DX::DeviceResources>& deviceResources) :
64
app_(app),
65
m_deviceResources(deviceResources)
66
{
67
TimeInit();
68
69
// Register to be notified if the Device is lost or recreated
70
m_deviceResources->RegisterDeviceNotify(this);
71
72
ctx_.reset(new UWPGraphicsContext(deviceResources));
73
74
#if _DEBUG
75
LogManager::GetInstance()->SetAllLogLevels(LogLevel::LDEBUG);
76
77
if (g_Config.bEnableLogging) {
78
LogManager::GetInstance()->ChangeFileLog(GetLogFile().c_str());
79
}
80
#endif
81
82
// At this point we have main requirements initialized (Log, Config, NativeInit, Device)
83
NativeInitGraphics(ctx_.get());
84
NativeResized();
85
86
int width = m_deviceResources->GetScreenViewport().Width;
87
int height = m_deviceResources->GetScreenViewport().Height;
88
89
ctx_->GetDrawContext()->HandleEvent(Draw::Event::GOT_BACKBUFFER, width, height, m_deviceResources->GetBackBufferRenderTargetView());
90
91
// add first XInput device to respond
92
g_input.push_back(std::make_unique<XinputDevice>());
93
94
InputDevice::BeginPolling();
95
96
// Prepare input pane (for Xbox & touch devices)
97
PrepareInputPane();
98
}
99
100
PPSSPP_UWPMain::~PPSSPP_UWPMain() {
101
InputDevice::StopPolling();
102
ctx_->GetDrawContext()->HandleEvent(Draw::Event::LOST_BACKBUFFER, 0, 0, nullptr);
103
NativeShutdownGraphics();
104
NativeShutdown();
105
g_VFS.Clear();
106
107
// Deregister device notification
108
m_deviceResources->RegisterDeviceNotify(nullptr);
109
net::Shutdown();
110
}
111
112
// Updates application state when the window size changes (e.g. device orientation change)
113
void PPSSPP_UWPMain::CreateWindowSizeDependentResources() {
114
ctx_->GetDrawContext()->HandleEvent(Draw::Event::LOST_BACKBUFFER, 0, 0, nullptr);
115
116
NativeResized();
117
118
int width = m_deviceResources->GetScreenViewport().Width;
119
int height = m_deviceResources->GetScreenViewport().Height;
120
ctx_->GetDrawContext()->HandleEvent(Draw::Event::GOT_BACKBUFFER, width, height, m_deviceResources->GetBackBufferRenderTargetView());
121
}
122
123
void PPSSPP_UWPMain::UpdateScreenState() {
124
// This code was included into the render loop directly
125
// based on my test I don't understand why it should be called each loop
126
// is it better to call it on demand only, like when screen state changed?
127
auto context = m_deviceResources->GetD3DDeviceContext();
128
129
switch (m_deviceResources->ComputeDisplayRotation()) {
130
case DXGI_MODE_ROTATION_IDENTITY: g_display.rotation = DisplayRotation::ROTATE_0; break;
131
case DXGI_MODE_ROTATION_ROTATE90: g_display.rotation = DisplayRotation::ROTATE_90; break;
132
case DXGI_MODE_ROTATION_ROTATE180: g_display.rotation = DisplayRotation::ROTATE_180; break;
133
case DXGI_MODE_ROTATION_ROTATE270: g_display.rotation = DisplayRotation::ROTATE_270; break;
134
}
135
// Not super elegant but hey.
136
memcpy(&g_display.rot_matrix, &m_deviceResources->GetOrientationTransform3D(), sizeof(float) * 16);
137
138
// Reset the viewport to target the whole screen.
139
auto viewport = m_deviceResources->GetScreenViewport();
140
141
g_display.pixel_xres = viewport.Width;
142
g_display.pixel_yres = viewport.Height;
143
144
if (g_display.rotation == DisplayRotation::ROTATE_90 || g_display.rotation == DisplayRotation::ROTATE_270) {
145
// We need to swap our width/height.
146
std::swap(g_display.pixel_xres, g_display.pixel_yres);
147
}
148
149
g_display.dpi = m_deviceResources->GetActualDpi();
150
151
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) {
152
// Boost DPI a bit to look better.
153
g_display.dpi *= 96.0f / 136.0f;
154
}
155
g_display.dpi_scale_x = 96.0f / g_display.dpi;
156
g_display.dpi_scale_y = 96.0f / g_display.dpi;
157
158
g_display.pixel_in_dps_x = 1.0f / g_display.dpi_scale_x;
159
g_display.pixel_in_dps_y = 1.0f / g_display.dpi_scale_y;
160
161
g_display.dp_xres = g_display.pixel_xres * g_display.dpi_scale_x;
162
g_display.dp_yres = g_display.pixel_yres * g_display.dpi_scale_y;
163
164
context->RSSetViewports(1, &viewport);
165
}
166
167
// Renders the current frame according to the current application state.
168
// Returns true if the frame was rendered and is ready to be displayed.
169
bool PPSSPP_UWPMain::Render() {
170
static bool hasSetThreadName = false;
171
if (!hasSetThreadName) {
172
SetCurrentThreadName("UWPRenderThread");
173
hasSetThreadName = true;
174
}
175
176
UpdateScreenState();
177
178
NativeFrame(ctx_.get());
179
return true;
180
}
181
182
// Notifies renderers that device resources need to be released.
183
void PPSSPP_UWPMain::OnDeviceLost() {
184
ctx_->GetDrawContext()->HandleEvent(Draw::Event::LOST_DEVICE, 0, 0, nullptr);
185
}
186
187
// Notifies renderers that device resources may now be recreated.
188
void PPSSPP_UWPMain::OnDeviceRestored() {
189
CreateWindowSizeDependentResources();
190
191
ctx_->GetDrawContext()->HandleEvent(Draw::Event::GOT_DEVICE, 0, 0, nullptr);
192
}
193
194
void PPSSPP_UWPMain::OnKeyDown(int scanCode, Windows::System::VirtualKey virtualKey, int repeatCount) {
195
// TODO: Look like (Ctrl, Alt, Shift) don't trigger this event
196
bool isDPad = (int)virtualKey >= 195 && (int)virtualKey <= 218; // DPad buttons range
197
DPadInputState(isDPad);
198
199
auto iter = virtualKeyCodeToNKCode.find(virtualKey);
200
if (iter != virtualKeyCodeToNKCode.end()) {
201
KeyInput key{};
202
key.deviceId = DEVICE_ID_KEYBOARD;
203
key.keyCode = iter->second;
204
key.flags = KEY_DOWN | (repeatCount > 1 ? KEY_IS_REPEAT : 0);
205
NativeKey(key);
206
}
207
}
208
209
void PPSSPP_UWPMain::OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKey) {
210
auto iter = virtualKeyCodeToNKCode.find(virtualKey);
211
if (iter != virtualKeyCodeToNKCode.end()) {
212
KeyInput key{};
213
key.deviceId = DEVICE_ID_KEYBOARD;
214
key.keyCode = iter->second;
215
key.flags = KEY_UP;
216
NativeKey(key);
217
}
218
}
219
220
void PPSSPP_UWPMain::OnCharacterReceived(int scanCode, unsigned int keyCode) {
221
// This event triggered only in chars case, (Arrows, Delete..etc don't call it)
222
// TODO: Add ` && !IsCtrlOnHold()` once it's ready and implemented
223
if (isTextEditActive()) {
224
KeyInput key{};
225
key.deviceId = DEVICE_ID_KEYBOARD;
226
key.keyCode = (InputKeyCode)keyCode;
227
// After many tests turns out for char just add `KEY_CHAR` for the flags
228
// any other flag like `KEY_DOWN` will cause conflict and trigger something else
229
key.flags = KEY_CHAR;
230
NativeKey(key);
231
}
232
}
233
234
void PPSSPP_UWPMain::OnMouseWheel(float delta) {
235
InputKeyCode key = NKCODE_EXT_MOUSEWHEEL_UP;
236
if (delta < 0) {
237
key = NKCODE_EXT_MOUSEWHEEL_DOWN;
238
} else if (delta == 0) {
239
return;
240
}
241
242
KeyInput keyInput{};
243
keyInput.keyCode = key;
244
keyInput.deviceId = DEVICE_ID_MOUSE;
245
keyInput.flags = KEY_DOWN;
246
NativeKey(keyInput);
247
248
// KEY_UP is now sent automatically afterwards for mouse wheel events, see NativeKey.
249
}
250
251
bool PPSSPP_UWPMain::OnHardwareButton(HardwareButton button) {
252
KeyInput keyInput{};
253
keyInput.deviceId = DEVICE_ID_KEYBOARD;
254
keyInput.flags = KEY_DOWN | KEY_UP;
255
switch (button) {
256
case HardwareButton::BACK:
257
keyInput.keyCode = NKCODE_BACK;
258
return NativeKey(keyInput);
259
default:
260
return false;
261
}
262
}
263
264
void PPSSPP_UWPMain::OnTouchEvent(int touchEvent, int touchId, float x, float y, double timestamp) {
265
// We get the coordinate in Windows' device independent pixels already. So let's undo that,
266
// and then apply our own "dpi".
267
float dpiFactor_x = m_deviceResources->GetActualDpi() / 96.0f;
268
float dpiFactor_y = dpiFactor_x;
269
dpiFactor_x /= g_display.pixel_in_dps_x;
270
dpiFactor_y /= g_display.pixel_in_dps_y;
271
272
TouchInput input{};
273
input.id = touchId;
274
input.x = x * dpiFactor_x;
275
input.y = y * dpiFactor_y;
276
input.flags = touchEvent;
277
input.timestamp = timestamp;
278
NativeTouch(input);
279
280
KeyInput key{};
281
key.deviceId = DEVICE_ID_MOUSE;
282
if (touchEvent & TOUCH_DOWN) {
283
key.keyCode = NKCODE_EXT_MOUSEBUTTON_1;
284
key.flags = KEY_DOWN;
285
NativeKey(key);
286
}
287
if (touchEvent & TOUCH_UP) {
288
key.keyCode = NKCODE_EXT_MOUSEBUTTON_1;
289
key.flags = KEY_UP;
290
NativeKey(key);
291
}
292
}
293
294
void PPSSPP_UWPMain::OnSuspend() {
295
// TODO
296
}
297
298
299
UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr<DX::DeviceResources> resources) {
300
std::vector<std::string> adapterNames = resources->GetAdapters();
301
302
draw_ = Draw::T3DCreateD3D11Context(
303
resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetSwapChain(), resources->GetDeviceFeatureLevel(), 0, adapterNames, g_Config.iInflightFrames);
304
bool success = draw_->CreatePresets();
305
_assert_(success);
306
}
307
308
void UWPGraphicsContext::Shutdown() {
309
delete draw_;
310
}
311
312
std::string System_GetProperty(SystemProperty prop) {
313
static bool hasCheckedGPUDriverVersion = false;
314
switch (prop) {
315
case SYSPROP_NAME:
316
return GetSystemName();
317
case SYSPROP_SYSTEMBUILD:
318
return GetWindowsBuild();
319
case SYSPROP_LANGREGION:
320
return GetLangRegion();
321
case SYSPROP_CLIPBOARD_TEXT:
322
/* TODO: Need to either change this API or do this on a thread in an ugly fashion.
323
DataPackageView ^view = Clipboard::GetContent();
324
if (view) {
325
string text = await view->GetTextAsync();
326
}
327
*/
328
return "";
329
case SYSPROP_GPUDRIVER_VERSION:
330
return "";
331
case SYSPROP_BUILD_VERSION:
332
return PPSSPP_GIT_VERSION;
333
default:
334
return "";
335
}
336
}
337
338
std::vector<std::string> System_GetPropertyStringVec(SystemProperty prop) {
339
std::vector<std::string> result;
340
switch (prop) {
341
case SYSPROP_TEMP_DIRS:
342
{
343
std::wstring tempPath(MAX_PATH, '\0');
344
size_t sz = GetTempPath((DWORD)tempPath.size(), &tempPath[0]);
345
if (sz >= tempPath.size()) {
346
tempPath.resize(sz);
347
sz = GetTempPath((DWORD)tempPath.size(), &tempPath[0]);
348
}
349
// Need to resize off the null terminator either way.
350
tempPath.resize(sz);
351
result.push_back(ConvertWStringToUTF8(tempPath));
352
return result;
353
}
354
355
default:
356
return result;
357
}
358
}
359
360
int64_t System_GetPropertyInt(SystemProperty prop) {
361
switch (prop) {
362
case SYSPROP_AUDIO_SAMPLE_RATE:
363
return winAudioBackend ? winAudioBackend->GetSampleRate() : -1;
364
365
case SYSPROP_DEVICE_TYPE:
366
{
367
if (IsMobile()) {
368
return DEVICE_TYPE_MOBILE;
369
} else if (IsXBox()) {
370
return DEVICE_TYPE_TV;
371
} else {
372
return DEVICE_TYPE_DESKTOP;
373
}
374
}
375
case SYSPROP_DISPLAY_XRES:
376
{
377
CoreWindow^ corewindow = CoreWindow::GetForCurrentThread();
378
if (corewindow) {
379
return (int)corewindow->Bounds.Width;
380
}
381
}
382
case SYSPROP_DISPLAY_YRES:
383
{
384
CoreWindow^ corewindow = CoreWindow::GetForCurrentThread();
385
if (corewindow) {
386
return (int)corewindow->Bounds.Height;
387
}
388
}
389
default:
390
return -1;
391
}
392
}
393
394
float System_GetPropertyFloat(SystemProperty prop) {
395
switch (prop) {
396
case SYSPROP_DISPLAY_REFRESH_RATE:
397
return 60.f;
398
case SYSPROP_DISPLAY_SAFE_INSET_LEFT:
399
case SYSPROP_DISPLAY_SAFE_INSET_RIGHT:
400
case SYSPROP_DISPLAY_SAFE_INSET_TOP:
401
case SYSPROP_DISPLAY_SAFE_INSET_BOTTOM:
402
return 0.0f;
403
default:
404
return -1;
405
}
406
}
407
408
void System_Toast(std::string_view str) {}
409
410
bool System_GetPropertyBool(SystemProperty prop) {
411
switch (prop) {
412
case SYSPROP_HAS_TEXT_CLIPBOARD:
413
case SYSPROP_HAS_OPEN_DIRECTORY:
414
{
415
return !IsXBox();
416
}
417
case SYSPROP_HAS_FILE_BROWSER:
418
return true;
419
case SYSPROP_HAS_FOLDER_BROWSER:
420
return true;
421
case SYSPROP_HAS_IMAGE_BROWSER:
422
return true; // we just use the file browser
423
case SYSPROP_HAS_BACK_BUTTON:
424
return true;
425
case SYSPROP_HAS_ACCELEROMETER:
426
return IsMobile();
427
case SYSPROP_APP_GOLD:
428
#ifdef GOLD
429
return true;
430
#else
431
return false;
432
#endif
433
case SYSPROP_CAN_JIT:
434
return true;
435
case SYSPROP_HAS_KEYBOARD:
436
{
437
// Do actual check
438
// touch devices has input pane, we need to depend on it
439
// I don't know any possible way to display input dialog in non-xaml apps
440
return isKeyboardAvailable() || isTouchAvailable();
441
}
442
case SYSPROP_DEBUGGER_PRESENT:
443
return IsDebuggerPresent();
444
case SYSPROP_OK_BUTTON_LEFT:
445
return true;
446
default:
447
return false;
448
}
449
}
450
451
void System_Notify(SystemNotification notification) {
452
switch (notification) {
453
case SystemNotification::POLL_CONTROLLERS:
454
{
455
for (const auto &device : g_input)
456
{
457
if (device->UpdateState() == InputDevice::UPDATESTATE_SKIP_PAD)
458
break;
459
}
460
break;
461
}
462
default:
463
break;
464
}
465
}
466
467
bool System_MakeRequest(SystemRequestType type, int requestId, const std::string &param1, const std::string &param2, int64_t param3, int64_t param4) {
468
switch (type) {
469
470
case SystemRequestType::EXIT_APP:
471
{
472
bool state = false;
473
ExecuteTask(state, Windows::UI::ViewManagement::ApplicationView::GetForCurrentView()->TryConsolidateAsync());
474
if (!state) {
475
// Notify the user?
476
}
477
return true;
478
}
479
case SystemRequestType::RESTART_APP:
480
{
481
Windows::ApplicationModel::Core::AppRestartFailureReason error;
482
ExecuteTask(error, Windows::ApplicationModel::Core::CoreApplication::RequestRestartAsync(nullptr));
483
if (error != Windows::ApplicationModel::Core::AppRestartFailureReason::RestartPending) {
484
// Shutdown
485
System_MakeRequest(SystemRequestType::EXIT_APP, requestId, param1, param2, param3, param4);
486
}
487
return true;
488
}
489
case SystemRequestType::BROWSE_FOR_IMAGE:
490
{
491
std::vector<std::string> supportedExtensions = { ".jpg", ".png" };
492
493
//Call file picker
494
ChooseFile(supportedExtensions).then([requestId](std::string filePath) {
495
if (filePath.size() > 1) {
496
g_requestManager.PostSystemSuccess(requestId, filePath.c_str());
497
}
498
else {
499
g_requestManager.PostSystemFailure(requestId);
500
}
501
});
502
return true;
503
}
504
case SystemRequestType::BROWSE_FOR_FILE:
505
{
506
std::vector<std::string> supportedExtensions = {};
507
switch ((BrowseFileType)param3) {
508
case BrowseFileType::BOOTABLE:
509
supportedExtensions = { ".cso", ".iso", ".chd", ".elf", ".pbp", ".zip", ".prx", ".bin" }; // should .bin even be here?
510
break;
511
case BrowseFileType::INI:
512
supportedExtensions = { ".ini" };
513
break;
514
case BrowseFileType::ZIP:
515
supportedExtensions = { ".zip" };
516
break;
517
case BrowseFileType::DB:
518
supportedExtensions = { ".db" };
519
break;
520
case BrowseFileType::SOUND_EFFECT:
521
supportedExtensions = { ".wav", ".mp3" };
522
break;
523
case BrowseFileType::ANY:
524
// 'ChooseFile' will added '*' by default when there are no extensions assigned
525
break;
526
default:
527
ERROR_LOG(Log::FileSystem, "Unexpected BrowseFileType: %d", param3);
528
return false;
529
}
530
531
//Call file picker
532
ChooseFile(supportedExtensions).then([requestId](std::string filePath) {
533
if (filePath.size() > 1) {
534
g_requestManager.PostSystemSuccess(requestId, filePath.c_str());
535
}
536
else {
537
g_requestManager.PostSystemFailure(requestId);
538
}
539
});
540
541
return true;
542
}
543
case SystemRequestType::BROWSE_FOR_FOLDER:
544
{
545
ChooseFolder().then([requestId](std::string folderPath) {
546
if (folderPath.size() > 1) {
547
g_requestManager.PostSystemSuccess(requestId, folderPath.c_str());
548
}
549
else {
550
g_requestManager.PostSystemFailure(requestId);
551
}
552
});
553
return true;
554
}
555
case SystemRequestType::NOTIFY_UI_EVENT:
556
{
557
switch ((UIEventNotification)param3) {
558
case UIEventNotification::MENU_RETURN:
559
CloseLaunchItem();
560
break;
561
case UIEventNotification::POPUP_CLOSED:
562
DeactivateTextEditInput();
563
break;
564
case UIEventNotification::TEXT_GOTFOCUS:
565
ActivateTextEditInput(true);
566
break;
567
case UIEventNotification::TEXT_LOSTFOCUS:
568
DeactivateTextEditInput(true);
569
break;
570
default:
571
break;
572
}
573
return true;
574
}
575
case SystemRequestType::COPY_TO_CLIPBOARD:
576
{
577
auto dataPackage = ref new DataPackage();
578
dataPackage->RequestedOperation = DataPackageOperation::Copy;
579
dataPackage->SetText(ToPlatformString(param1));
580
Clipboard::SetContent(dataPackage);
581
return true;
582
}
583
case SystemRequestType::TOGGLE_FULLSCREEN_STATE:
584
{
585
auto view = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
586
bool flag = !view->IsFullScreenMode;
587
if (param1 == "0") {
588
flag = false;
589
} else if (param1 == "1"){
590
flag = true;
591
}
592
if (flag) {
593
view->TryEnterFullScreenMode();
594
} else {
595
view->ExitFullScreenMode();
596
}
597
return true;
598
}
599
case SystemRequestType::SHOW_FILE_IN_FOLDER:
600
OpenFolder(param1);
601
return true;
602
default:
603
return false;
604
}
605
}
606
607
void System_LaunchUrl(LaunchUrlType urlType, const char *url) {
608
auto uri = ref new Windows::Foundation::Uri(ToPlatformString(url));
609
610
create_task(Windows::System::Launcher::LaunchUriAsync(uri)).then([](bool b) {});
611
}
612
613
void System_Vibrate(int length_ms) {
614
#if _M_ARM
615
if (length_ms == -1 || length_ms == -3)
616
length_ms = 50;
617
else if (length_ms == -2)
618
length_ms = 25;
619
else
620
return;
621
622
auto timeSpan = Windows::Foundation::TimeSpan();
623
timeSpan.Duration = length_ms * 10000;
624
// TODO: Can't use this?
625
// Windows::Phone::Devices::Notification::VibrationDevice::GetDefault()->Vibrate(timeSpan);
626
#endif
627
}
628
629
void System_AskForPermission(SystemPermission permission) {
630
// Do nothing
631
}
632
633
PermissionStatus System_GetPermissionStatus(SystemPermission permission) {
634
return PERMISSION_STATUS_GRANTED;
635
}
636
637
std::string GetCPUBrandString() {
638
Platform::String^ cpu_id = nullptr;
639
Platform::String^ cpu_name = nullptr;
640
641
// GUID_DEVICE_PROCESSOR: {97FADB10-4E33-40AE-359C-8BEF029DBDD0}
642
Platform::String^ if_filter = L"System.Devices.InterfaceClassGuid:=\"{97FADB10-4E33-40AE-359C-8BEF029DBDD0}\"";
643
644
// Enumerate all CPU DeviceInterfaces, and get DeviceInstanceID of the first one.
645
auto if_task = create_task(
646
DeviceInformation::FindAllAsync(if_filter)).then([&](DeviceInformationCollection ^ collection) {
647
if (collection->Size > 0) {
648
auto cpu = collection->GetAt(0);
649
auto id = cpu->Properties->Lookup(L"System.Devices.DeviceInstanceID");
650
cpu_id = dynamic_cast<Platform::String^>(id);
651
}
652
});
653
654
try {
655
if_task.wait();
656
}
657
catch (const std::exception & e) {
658
const char* what = e.what();
659
INFO_LOG(Log::System, "%s", what);
660
}
661
662
if (cpu_id != nullptr) {
663
// Get the Device with the same ID as the DeviceInterface
664
// Then get the name (description) of that Device
665
// We have to do this because the DeviceInterface we get doesn't have a proper description.
666
Platform::String^ dev_filter = L"System.Devices.DeviceInstanceID:=\"" + cpu_id + L"\"";
667
668
auto dev_task = create_task(
669
DeviceInformation::FindAllAsync(dev_filter, {}, DeviceInformationKind::Device)).then(
670
[&](DeviceInformationCollection ^ collection) {
671
if (collection->Size > 0) {
672
cpu_name = collection->GetAt(0)->Name;
673
}
674
});
675
676
try {
677
dev_task.wait();
678
}
679
catch (const std::exception & e) {
680
const char* what = e.what();
681
INFO_LOG(Log::System, "%s", what);
682
}
683
}
684
685
if (cpu_name != nullptr) {
686
return FromPlatformString(cpu_name);
687
} else {
688
return "Unknown";
689
}
690
}
691
692