Com IAudioSessionManager2未发送通知

Com IAudioSessionManager2未发送通知,com,windows-7,audio,Com,Windows 7,Audio,我正试图通过Windows7的IAudioSessionManager2 COM接口(结合IAudioSessionNotification)监视新的音频会话。目前,从未调用IAudioSessionNotification::OnSessionCreated(),我也不知道为什么 注册自定义IAudioSessionNotification的代码: #define SAFE_RELEASE(comObj) \ if(comObj != NULL) \ { (comObj)->Re

我正试图通过Windows7的IAudioSessionManager2 COM接口(结合IAudioSessionNotification)监视新的音频会话。目前,从未调用IAudioSessionNotification::OnSessionCreated(),我也不知道为什么

注册自定义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);
}
海关声明:

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应该会立即引起通知,而通过网络浏览器访问潘多拉也会触发这样的通知

调试显示所有返回值都正常


我的COM经验非常有限,因此指出一般的“WTF?”也将不胜感激。

这比你需要做的工作多得多

您只需要编写一个从IAudioSessionNotifications派生的类,而不需要实际编写整个COM对象并注册它

您还应该使用eConsole角色而不是eMultimedia角色。这实际上并不重要(如果你只有一个音频设备),但它更正确

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

CustomAudioNotification
*customNotification=新的CustomAudioNotification();
会话->RegisterSessionNotification(自定义通知)

我还假设您在编写代码片段之前已经初始化了COM

更新:Kevin向我发送了他的应用程序,他的应用程序还有一些更基本的问题(我正在努力改进API文档,以防止将来出现任何混乱)

首先,他的应用程序没有检索到当前会话列表。这是会话枚举API中非常微妙的事情之一。为了防止在使用会话API的应用程序启动时会话通知到达时出现争用情况,会话枚举API将丢弃新会话通知,直到应用程序首先检索到现有会话的列表

预期的使用模式是:

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

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

应用程序根据自己的标准管理会话的生存期-只要应用程序引用了会话控制,会话控制对象就有效。音频会话控制对象没有过期机制


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

是否调用CustomAudioNotifications::QueryInterface?它是否返回S_OK?在通过其工厂构建对象之外;不,不调用QueryInterface。至少,断点从未被绊倒。@Kevin,你可能再也找不到更好的答案了。拉里是编写Windows音频代码的人之一@拉里·奥斯特曼:这也适用于服务吗?我制作了一个控制台32应用程序。但是,相同的代码似乎没有在服务中接收回调。一些音频专家也提到,它将不起作用。所以,我只是想再核实一下。