IAudioSessionManager2通知未发送 [英] IAudioSessionManager2 notifications not sent

查看:191
本文介绍了IAudioSessionManager2通知未发送的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过Windows 7的IAudioSessionManager2 COM接口(与IAudioSessionNotification配合)监视新的音频会话。目前,IAudioSessionNotification :: OnSessionCreated()从未被调用,我已经用完了为什么。

I'm trying to monitor new audio sessions via Windows 7's IAudioSessionManager2 COM interface (coupled with IAudioSessionNotification). Currently, IAudioSessionNotification::OnSessionCreated() is never called and I've run out of ideas as to why.

代码注册自定义IAudioSessionNotification:

Code registering 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声明:

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只是在当前创建会话时向窗口发布消息;从不发生。为了防止我的假设完全偏离基准,我希望每当有尚未播放音频的应用程序开始这样做的通知;因此使用视频文件启动VLC应该立即导致通知,而通过网络浏览器访问Pandora也会触发这样的通知。

OnSessionCreated just posts a message to a window whenever a session is created for the time being; which never happens. Just in case my assumptions are totally off base, I'm expecting a notification whenever an application that has yet to play audio starts to do so; so launching VLC with a video file should immediately result in a notice, while visiting Pandora via a web browser would also trigger such a notice.

调试显示所有返回的值都是S_OK 。

Debugging shows all returned values are S_OK.

我的COM体验是相当有限的,所以指出一般的WTFs?

My COM experience is pretty limitted, so pointing out general "WTFs?" would also be appreciated.

推荐答案

这是一个TON比你需要做的更多的工作。

That's a TON more work than you need to do.

你只需要写一个派生自IAudioSessionNotifications的类 - 你不需要实际写一个整个COM对象并注册它。

You just need to write a class that derives from IAudioSessionNotifications - you don't need to actually write a whole COM object and register it.

你还应该使用eConsole角色而不是eMultimedia角色。

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

CustomAudioNotification类的析构函数应该是私有的 - 这样你就可以防止意外破坏。所以我写:

The destructor for the CustomAudioNotification class should be private - that way you prevent accidental destruction. So I'd write:


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

UPDATED:Kevin给了我他的应用程序,还有一些其他问题,他的应用程序更基础(我是努力获得API的文档改进以防止将来的任何混乱)

UPDATED: Kevin sent me his application and there are a couple of other issues with his application that are more fundamental (I'm working to get the documentation for the APIs improve to prevent any confusion in the future)

第一个是他的应用程序没有检索到当前的会话列表。这是会话枚举API的一个非常微妙的事情。为了防止在使用会话API的应用程序启动时会话通知到达时可能发生的竞争条件,会话枚举API丢弃新的会话通知,直到应用首先检索到现有会话的列表。

The first is that his application hasn't retrieved the current list of sessions. This is one of the really subtle things about the session enumeration APIs. In order to prevent a race condition that can occur when a session notification arrives while the application using the session APIs is starting up, the session enumeration API discards new session notifications until the application has first retrieved the list of existing sessions.

预期的使用模式是:

应用程序激活会话管理器2。
会话通知的应用程序注册。
应用程序检索端点的会话的当前列表,并将会话控制对象存储到列表中(不要忘记addref会话)。

Application activates a session manager2. Application registers for session notifications. Application retrieves the current list of sessions for the endpoint and stores the session control objects into a list (don't forget to addref the session).

当创建新会话,应用程序将引用新创建的会话控制对象,并将其插入列表(如果它尚未存在)。注意,传递给通知的会话控制对象将在会话通知返回时被销毁 - 如果你在这一点调用GetSessionEnumerator,它可能不会保存新创建的会话(可能,这一切都取决于时间)。

When a new session is created, the application takes a reference to the newly created session control object and inserts it into the list if it's not already present. Note that the session control object passed into the notification will be destroyed when the session notification returns - if you call GetSessionEnumerator at this point it will probably NOT hold the newly created session (it might, it all depends on timing).

应用程序基于其自己的标准来管理会话的生存期 - 只要应用程序具有对会话控制的引用,会话控制对象将是有效的。对于音频会话控制对象没有到期机制。

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

此外,会话API要求MTA被初始化 - 这是不幸的,但是因为我们创建COM对象在工作线程上实现IAudioSessionControl)API要求在接收通知之前创建MTA。

In addition, the session APIs require that the MTA be initialized - this is unfortunate but because we create COM objects (which implement IAudioSessionControl) on a worker thread the API requires that the MTA be created before the notification is received.

这篇关于IAudioSessionManager2通知未发送的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆