Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Device enumeration/ WinRT eventing sample #2171

Closed
Paul-Dempsey opened this issue Nov 17, 2022 · 2 comments · Fixed by #2172
Closed

Feature request: Device enumeration/ WinRT eventing sample #2171

Paul-Dempsey opened this issue Nov 17, 2022 · 2 comments · Fixed by #2172
Labels
enhancement New feature or request

Comments

@Paul-Dempsey
Copy link

Motivation

None of the samples cover how to implement the event callbacks required to (for example) enumerate the available MIDI ports using Windows::Devices::Enumeration::DeviceInformation. Looking for the Rust equivalent of the MidiDeviceWatcher class in the UWP MIDI sample, but without the UWP UI. A console based example would be fine.

I'm just learning Rust, and attempting to decode usage from the projections of the types is daunting. This is where a working sample shines and adds tremendous value.

Drawbacks

I can't think of a drawback to educating users how to use this aspect of modern windows programming in rust.

Rationale and alternatives

I've looked for other crates using windows-rs that do device enumeration or implement WinRT events, but haven't found anything.

Additional context

No response

@Paul-Dempsey Paul-Dempsey added the enhancement New feature or request label Nov 17, 2022
@kennykerr
Copy link
Collaborator

Thanks for the reminder. Yes, there isn't a good example of working with WinRT events in the sample collection.

So here you go: #2172

Note that WinRT events are still a little clunky as Rust doesn't let us be generic over the handler. That's something I'd still like to address: #332

@Paul-Dempsey
Copy link
Author

Paul-Dempsey commented Nov 22, 2022

Thanks for that, Kenny! - it at least got me started. tho, "a little clunky" is an understatement (certainly for a rust newbie) :-). Attempting to do something more useful than printing to the console, such as maintaining a device collection immediately runs into #1110, #1465, .... After days of effort, I think I may have an exceedingly ugly hack using state behind a static mutex that allows me to move forward with my application. I'm looking forward to when these issues are resolved.

If you're interested, here's potentially more useful version of the sample that demos all the DeviceWatcher events and doesn't take 10 minutes to run (happy to open a PR). My hacky solution to the lifetime issues isn't worth sharing ;-).

use windows::{core::*, Devices::Enumeration::*, Foundation::*};

fn main() -> Result<()> {
    let watcher = DeviceInformation::CreateWatcher()?;
    watcher.Added(&TypedEventHandler::<DeviceWatcher, DeviceInformation>::new(
        |_, info| {
            let info = info.as_ref().expect("info");
            println!("Added {} ({})", info.Name()?, info.Id()?);
            Ok(())
        },
    ))?;
    watcher.Stopped(&TypedEventHandler::<DeviceWatcher, IInspectable>::new(
        |_, item| {
            let name  = item.as_ref().expect("inspectable").GetRuntimeClassName()?;
            println!("Stopped {}", name.to_string());
            Ok(())
        }
    ))?;
    watcher.Removed(&TypedEventHandler::<DeviceWatcher, DeviceInformationUpdate>::new(
        |_, update| {
            let info = update.as_ref().expect("update");
            println!("Removed {}", info.Id()?);
            Ok(())
        },
    ))?;
    watcher.Updated(&TypedEventHandler::<DeviceWatcher, DeviceInformationUpdate>::new(
        |_, update| {
            let info = update.as_ref().expect("update");
            println!("Updated {}", info.Id()?);
            Ok(())
        },
    ))?;
    watcher.EnumerationCompleted(&TypedEventHandler::new(|_, _| {
        println!("EnumerationCompleted");
        Ok(())
    }))?;

    let interval = std::time::Duration::new(1, 0);
    watcher.Start()?;
    while match watcher.Status()? {
        DeviceWatcherStatus::EnumerationCompleted => false,
        DeviceWatcherStatus::Aborted => false,
        DeviceWatcherStatus::Stopped => false,
        _ => true
    } {
        std::thread::sleep(interval);
    }
    Ok(())
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants