Skip to content

Instantly share code, notes, and snippets.

@jonwis
Created July 28, 2020 05:30
Show Gist options
  • Save jonwis/52555462873fd66cfd5466ed9480cb5d to your computer and use it in GitHub Desktop.
Save jonwis/52555462873fd66cfd5466ed9480cb5d to your computer and use it in GitHub Desktop.
template<typename TDevice> winrt::IAsyncOperation<TDevice> GetFirstDeviceAsync(winrt::hstring selector)
{
// Create a watcher. Try converting all the discovered device information records
// into real device instances. When the enumeration is complete, stop everything.
auto watcher = winrt::DeviceInformation::CreateWatcher(selector);
// DeviceWatcher enumeration ensures that all devices are enumerated, then
// raises 'EnumerationCompleted'. We'll use coroutines to model this.
winrt::handle event{ ::CreateEvent(nullptr, true, false, nullptr) };
winrt::check_bool(static_cast<bool>(event));
// Collects all the pending conversions of device informations into things.
std::vector<winrt::IAsyncOperation<TDevice>> devices;
std::mutex lock;
auto addedHandler = [&](auto const&, winrt::DeviceInformation const& info)
{
std::lock_guard<std::mutex> locker{ lock };
devices.emplace_back(TDevice::FromIdAsync(info.Id()));
};
auto completedHandler = [&](auto&&...)
{
::SetEvent(event.get());
};
// Start watching, go until the enumeration is complete.
auto addedToken = watcher.Added(winrt::auto_revoke, addedHandler);
auto completedToken = watcher.EnumerationCompleted(winrt::auto_revoke, completedHandler);
auto updatedToken = watcher.Updated(winrt::auto_revoke, [](auto&&...) {});
auto removedToken = watcher.Removed(winrt::auto_revoke, [](auto&&...) {});
watcher.Start();
co_await winrt::resume_on_signal(event.get());
// Await all the in-flight conversions, but stop when the first one
// is ready. If none are found, return nothing.
for (auto& i : devices)
{
if (TDevice found = co_await i)
{
co_return found;
}
}
co_return nullptr;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment