About the CoreAudio Wrapper

Apr 9, 2010 at 9:12 AM

Hi Mark,

I just wanted to use the callback for IMMNotificationClient to receive updates if a device was added or removed. So I created a class implementing the IMMNotificationClient interface and registered an instance of this class on the deviceenumerator. However, when I try this code I get one callback but then the vshost (or the exe if not debuging) crashes with an unkown error. 

I was wondering if you or someone else has ever tried to use the IMMNotificationClient callback. Do I have to mark the implenting class with some Com Attributes? I thought it should be similar to AudioEndpointVolumeCallback...



Apr 9, 2010 at 9:26 AM

hi Christoph

Writing managed wrappers for COM interfaces is an error prone process, so there is every chance there is a mistake in IMMNotificationClient or one of its dependencies. I haven't used it myself. Some of the CoreAudio wrappers I wrote myself, but a lot came from a guy called Ray Molenkamp, and seemed to be of good quality. However, it looks like IMMNotificationClient may have been one of mine and not fully tested yet, so it would be worth double-checking all the interop signatures. Have you got AudioEndpointVolumeCallback working?


Apr 9, 2010 at 10:08 AM

Hi Mark,

AudioEndpointVolumeCallback works fine. And we are doing it in the same way. Was also reading a lot about COM wrapping (same order of methods, etc) but nothing seems to fix the problem. I have also seen the source from this Molekamp guy on Codeproject.

I ran out of clues so I contacted you.


Apr 9, 2010 at 10:36 AM

Hi Mark,

I found the problem! It seems the return value (HRESULT) was causing the problem if you change that to return void it works.

thanks for you help!


Apr 9, 2010 at 10:39 AM

great! can you post the changes you made. I'll try to get them checked in



Apr 9, 2010 at 11:28 AM

Here is the changed code:

[Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMMNotificationClient
        void OnDeviceStateChanged([MarshalAs(UnmanagedType.LPWStr)] string deviceId, [MarshalAs(UnmanagedType.I4)] DeviceState newState);

        void OnDeviceAdded([MarshalAs(UnmanagedType.LPWStr)] string pwstrDeviceId);

        void OnDeviceRemoved([MarshalAs(UnmanagedType.LPWStr)] string deviceId);

        void OnDefaultDeviceChanged(DataFlow flow, Role role, [MarshalAs(UnmanagedType.LPWStr)]string defaultDeviceId);

        void OnPropertyValueChanged([MarshalAs(UnmanagedType.LPWStr)] string pwstrDeviceId, PropertyKey key);

note the return types have changed to void plus I added MarshalAs Attributes for the string values.



Apr 15, 2010 at 4:11 PM

thanks balistof,

I've checked in your changes