2009-04-09 23 views
6

私は、Windows 7のIAudioSessionManager2 COMインターフェイス(IAudioSessionNotificationと組み合わせて)を介して新しいオーディオセッションを監視しようとしています。現時点では、IAudioSessionNotification :: OnSessionCreated()は呼び出されません。理由についてはアイデアが不足しています。カスタムIAudioSessionNotificationを登録IAudioSessionManager2通知が送信されない

コード:

#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宣言:

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をビデオファイルで起動するとすぐに通知が表示され、Webブラウザ経由でPandoraを訪れるとそのような通知が行われます。

デバッグは、すべての戻り値がS_OKであることを示します。

私のCOMエクスペリエンスはかなり制限されているので、一般的な「WTF」を指摘しています。また評価されるだろう。

+0

CustomAudioNotifications :: QueryInterfaceが呼び出されていますか?それはS_OKを返しますか? – sharptooth

+0

そのファクトリを介してオブジェクトを構築することの外側。いいえ、QueryInterfaceは呼び出されません。少なくとも、ブレークポイントは決してトリップされません。 –

答えて

15

これは、必要以上に多くの作業です。

IAudioSessionNotificationsから派生したクラスを記述するだけで済みます。COMオブジェクト全体を実際に記述して登録する必要はありません。

eMultimediaロールの代わりにeConsoleロールも使用する必要があります。それは事実上問題ではありませんが(オーディオデバイスが1つだけの場合)、より正確です。

CustomAudioNotificationクラスのデストラクタはプライベートである必要があります。つまり、偶発的な破壊を防ぐためです。だから私は書きたい:私はまた、あなたのコードスニペットの前にCOMを初期化してきたことを仮定してい

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

UPDATED:ケビンは私に自分のアプリケーションを送信し、

(APIは将来の任意の混乱を防ぐために、改善のために、私はドキュメントを取得するために働いている)より基本的なもの、彼のアプリケーションと他の問題がいくつかあります

最初は、彼のアプリケーションが現在のセッションリストを取得していないことです。これは、セッション列挙APIに関する本当に微妙なものの1つです。セッションAPIを使用しているアプリケーションの起動中にセッション通知が到着したときに発生する可能性のある競合状態を防ぐため、セッション列挙APIは、アプリケーションが最初に既存のセッションのリストを取得するまで、新しいセッション通知を破棄します。

予想される使用パターンがある:

アプリケーションは、セッションマネージャ2を活性化します。 アプリケーションはセッション通知用に登録します。 アプリケーションは、エンドポイントのセッションの現在のリストを取得し、セッション制御オブジェクトをリストに格納します(セッションを追加するのを忘れないでください)。

新しいセッションが作成されると、アプリケーションは新しく作成されたセッションコントロールオブジェクトへの参照を取得し、まだ存在しない場合はリストに挿入します。通知に渡されたセッションコントロールオブジェクトは、セッション通知が返ってきたときに破棄されます。この時点でGetSessionEnumeratorを呼び出すと、新しく作成されたセッションが保持されない可能性があります。

アプリケーションは、独自の基準に基づいてセッションの有効期間を管理します。アプリケーションがセッション制御への参照を持つ限り、セッション制御オブジェクトは有効です。オーディオセッションコントロールオブジェクトの有効期限のメカニズムはありません。

さらに、セッションAPIでは、MTAを初期化する必要があります。これは残念ですが、ワーカースレッドでCOMオブジェクト(IAudioSessionControlを実装する)を作成するため、APIは通知を受け取る前にMTAを作成する必要があります。

+0

@ケビン、あなたはおそらくもっと良い答えを得ることはできません。 LarryはWindows Audioコードを書いた人の一人です。 :) –

関連する問題