summaryrefslogtreecommitdiff
path: root/general/WinHEC 2017 Lab/Toaster Support App/SharedContent/cpp/DeviceHelpers.h
blob: c2fa82b278449c90e02cf2e8b490ce05612e2bda (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

#pragma once

namespace SDKTemplate
{
    namespace DeviceHelpers
    {
        // We use a DeviceWatcher instead of DeviceInformation.FindAllAsync because
        // the DeviceWatcher will let us see the devices as they are discovered,
        // whereas FindAllAsync returns results only after discovery is complete.
        //
        // The convertAsync functional is passed a device ID (Platform::String^) and returns a
        // Concurrency::task<Something^>.
        template<typename Converter>
        auto GetFirstDeviceAsync(Platform::String^ selector, Converter convertAsync)
            -> decltype(convertAsync(nullptr))
        {
            using T = typename decltype(convertAsync(nullptr))::result_type;
            Concurrency::task_completion_event<T> completionEvent;
            auto pendingTasks = std::make_shared<std::vector<Concurrency::task<void>>>();
            Windows::Devices::Enumeration::DeviceWatcher^ watcher = Windows::Devices::Enumeration::DeviceInformation::CreateWatcher(selector);

            watcher->Added += ref new Windows::Foundation::TypedEventHandler<Windows::Devices::Enumeration::DeviceWatcher^, Windows::Devices::Enumeration::DeviceInformation^>(
                [completionEvent, pendingTasks, convertAsync](Windows::Devices::Enumeration::DeviceWatcher^ sender, Windows::Devices::Enumeration::DeviceInformation^ device)
            {
                auto task = convertAsync(device->Id).then([completionEvent](T t)
                {
                    if (t != nullptr)
                    {
                        completionEvent.set(t);
                    }
                });
                pendingTasks->push_back(task);
            });

            watcher->EnumerationCompleted += ref new Windows::Foundation::TypedEventHandler<Windows::Devices::Enumeration::DeviceWatcher^, Platform::Object^>(
                [completionEvent, pendingTasks](Windows::Devices::Enumeration::DeviceWatcher^ sender, Platform::Object^ args)
            {
                // Wait for completion of all the tasks we created in our "Added" event handler.
                Concurrency::when_all(pendingTasks->begin(), pendingTasks->end()).then([completionEvent]()
                {
                    // This sets the result to "nullptr" if no task was able to produce a device.
                    completionEvent.set(nullptr);
                });
            });

            watcher->Start();

            // Wait for enumeration to complete or for a device to be found, whichever comes first.
            return Concurrency::create_task(completionEvent).then([watcher](T result)
            {
                watcher->Stop();
                return result;
            });
        }
    }
}