1

I'm trying to write a mute.fm-like program in Rust, this is my first big project both using rust and winapi. I managed to get IAudioSessionControl, but it doesn't include process ID or name, so there is no way to know which application it is. IAudioSessionControl2 has a GetProcessID method, but I can't find any way to obtain this interface.

It looks like in C# you can get it by just doing IAudioSessionControl2 ctl2 = ctl as IAudioSessionControl2;, where ctl is IAudioSessionControl (found this snippet in this issue), but in Rust that's not as simple. IAudioSessionControl2 can be converted into IAudioSessionControl using From, but not the other way around

This is the code I use, if it helps:

use std::ptr;
use windows::Win32::{Media::Audio::*, System::Com::*};

fn main() {
    unsafe {
        CoInitialize(ptr::null()).unwrap();

        let enumerator: IMMDeviceEnumerator =
            CoCreateInstance(&MMDeviceEnumerator, None, CLSCTX_ALL).unwrap();
        let device = enumerator
            .GetDefaultAudioEndpoint(eRender, eMultimedia)
            .unwrap();
        let manager: IAudioSessionManager2 = device.Activate(CLSCTX_ALL, ptr::null()).unwrap();
        let sessions = manager.GetSessionEnumerator().unwrap();

        for n in 0..sessions.GetCount().unwrap() {
            let session_control = sessions.GetSession(n).unwrap();
        }

        CoUninitialize();
    }
}

IInspectable
  • 46,945
  • 8
  • 85
  • 181
Lolotronop
  • 21
  • 4
  • Do get IAudioSessionControl2 from IAudioSessionControl, you must use sessionControlRef->QueryInterface(...) (this is was C# does undercovers). Not sure how to do that in rust. – Simon Mourier Sep 03 '22 at 12:51
  • Unrelated note: You shouldn't really call `CoUninitialize`. Even though the [documentation](https://learn.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-coinitialize) insists that each successful call to `CoInitialize[Ex]` must be balanced with a call to `CoUninitialize`, the latter has preconditions that are hard to maintain in practice. Just let the thread die and have the system clean up the mess afterwards. – IInspectable Sep 03 '22 at 13:29
  • Also unrelated, but if you have your `main` return a [`Result`](https://microsoft.github.io/windows-docs-rs/doc/windows/core/type.Result.html) instead, all those `unwrap()`s turn into simple [`?`](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator)s. – IInspectable Sep 03 '22 at 13:33
  • Thanks! Yeah, i know about the Result, just forgot about it in the moment, this was just a quick and dirty way to test the idea. `CoUninitialize` info is really helpful tho, removed it. Can you point me somewhere to read about what could go wrong with it? Or is it all just in the microsoft docs on this function? @iinspectable – Lolotronop Sep 04 '22 at 15:02
  • I'll write up a full answer that covers this as well as how COM is exposed in the `windows` crate. As a cliffhanger: The call to `CoUninitialize` introduces a bug, not just in theory but in practice. I'll cover that as well. I'm assuming you aren't blocked by this issue anymore, so I'll take my fair time. – IInspectable Sep 04 '22 at 15:09
  • Thanks a lot! You can take as much time as you'd like. Also uni just started so I haven even less spare hours to work on this so you have all the time in the world – Lolotronop Sep 04 '22 at 15:11

1 Answers1

1

Turns out you need to use .cast() on the IAudioSessionControl like so, annotating the type explicitly

let session_control_2: IAudioSessionControl2 = session_control.cast().unwrap();

The documentation is not as clear as i would hope it to be. Thanks to the comment I decided to search for the QueryInterface on the IAudioSessionControl page and found the .cast() method

Lolotronop
  • 21
  • 4
  • The [FAQ](https://github.com/microsoft/windows-rs/blob/master/docs/FAQ.md) has the following entry, which describes this: [How do I query for a specific COM interface?](https://github.com/microsoft/windows-rs/blob/master/docs/FAQ.md#how-do-i-query-for-a-specific-com-interface). Basic familiarity with COM is assumed. – IInspectable Sep 03 '22 at 13:25
  • Oh, now I see. Well, I am only about 3 days in winapi and don't have anybody at hand to ask so stackoverflow it is. At least this way anyone struggling to do the same thing will have something to find on google later on – Lolotronop Sep 04 '22 at 14:59