IAudioSessionManager2 notifications not sent

I am trying to control new audio sessions through the Windows 7 IAudioSessionManager2 COM interface (in conjunction with IAudioSessionNotification). Currently, IAudioSessionNotification :: OnSessionCreated () is never called, and I'm running out of ideas as to why.

Code registration of custom IAudioSessionNotification:

#define SAFE_RELEASE(comObj) \ if(comObj != NULL) \ { (comObj)->Release(); comObj = NULL; } BOOL success = false; HRESULT res; IClassFactory* pFactory; IMMDevice* pDevice; IMMDeviceEnumerator* pEnumerator; SESSION_LISTENER = NULL; SESSION = NULL; res = CoInitialize(NULL); if(res != S_OK && res != S_FALSE) return false; res = CoGetClassObject(CLSID_CustomAudioFactory, CLSCTX_ALL, NULL, __uuidof(IClassFactory), (void**)&pFactory); if(res != S_OK) goto Exit; res = pFactory->CreateInstance(NULL, CLSID_CustomAudioNotifications, (void**)&SESSION_LISTENER); if(res != S_OK) goto Exit; res = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator); if(res != S_OK) goto Exit; res = pEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDevice); if(res != S_OK) goto Exit; res = pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**)&SESSION); if(res != S_OK) goto Exit; res = SESSION->RegisterSessionNotification(SESSION_LISTENER); if(res != S_OK) goto Exit; success = true; Exit: SAFE_RELEASE(pFactory); SAFE_RELEASE(pEnumerator); SAFE_RELEASE(pDevice); if(!success) { SAFE_RELEASE(SESSION_LISTENER); SAFE_RELEASE(SESSION); } 

CustomAudioNotifications declaration:

 class CustomAudioNotifications : public IAudioSessionNotification { public: //Constructors CustomAudioNotifications() { InterlockedIncrement(&g_notifyCount); m_listener = NULL; } ~CustomAudioNotifications() { InterlockedDecrement(&g_notifyCount); SAFE_RELEASE(m_listener); } //IUnknown interface HRESULT __stdcall QueryInterface( REFIID riid , void **ppObj); ULONG __stdcall AddRef(); ULONG __stdcall Release(); //Notification HRESULT __stdcall OnSessionCreated(IAudioSessionControl *NewSession); private: LONG m_nRefCount; }; 

OnSessionCreated simply posts a message in the window whenever a session is created; which never happens. Just in case, if my assumptions do not fully work, I expect a notification whenever an application that does not yet play audio starts to do so; therefore, launching a VLC with a video file should immediately result in a notification, while visiting Pandora via a web browser will also result in such a notification.

Debugging shows that all returned values ​​are S_OK.

My experience with COM is pretty limited, so indicating generic "WTFs"? will also be appreciated.

+6
windows-7 com audio
source share
1 answer

That ton is more work than you need.

You just need to write a class that derives from IAudioSessionNotifications - you do not need to write the entire COM object and register it.

You should also use the eConsole role instead of the eMultimedia role. It doesn't really matter (if you only have one audio device), but it is more correct.

The destructor of the CustomAudioNotification class must be closed - this way you will prevent accidental destruction. Therefore, I would write:

CustomAudioNotification *customNotification = new CustomAudioNotification(); SESSION->RegisterSessionNotification(customNotification);

I also assume that you initialized COM before your code snippet.

UPDATED: Kevin sent me his application, and there are several other problems related to its application that are more fundamental (I am working on improving the documentation for the API to prevent confusion in the future)

First, his application did not retrieve the current list of sessions. This is one of the very subtle features of the session APIs. To prevent a race condition that may occur when a session notification arrives when an application using the session APIs is started, the session listing API discards new session notifications until the application receives a list of existing sessions.

Expected usage pattern:

The application activates the session manager 2. Application registers for session notifications. The application retrieves the current session list for the endpoint and stores the session management objects in the list (do not forget to add a session to the session).

When a new session is created, the application accepts the link to the newly created session management object and inserts it into the list if it is not already present. Note that the session control object passed to the notification will be destroyed when the session notification returns - if you call GetSessionEnumerator at that moment, it will probably NOT have a newly created session (it may all depend on the time).

The application manages the session lifetime based on its own criteria - as long as the application has a link to the session management, the session management object will be valid. There is no expiration mechanism for audio connection objects.

In addition, the session APIs require the MTA to be initialized - this is unfortunate, but since we create COM objects (which implement the IAudioSessionControl) in the workflow, the API requires the MTA to be created before the notification is received.

+15
source share

All Articles