2009-04-09 18 views
6

नहीं भेजा गया है, मैं विंडोज 7 के IAudioSessionManager2 COM इंटरफ़ेस (IAudioSessionNotification के साथ) के माध्यम से नए ऑडियो सत्रों की निगरानी करने की कोशिश कर रहा हूं। वर्तमान में, IAudioSessionNotification :: OnSessionCreated() को कभी नहीं कहा जाता है और मैं विचारों से बाहर क्यों चला गया हूं।IAudioSessionManager2 नोटिफिकेशन

कोड दर्ज की कस्टम 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 घोषणा:

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; जो कभी नहीं होता है। बस अगर मेरी धारणाएं पूरी तरह से आधार से बाहर हैं, तो मुझे एक अधिसूचना की उम्मीद है जब भी कोई एप्लिकेशन जो ऑडियो चलाने के लिए नहीं है, ऐसा करने के लिए शुरू होता है; इसलिए एक वीडियो फ़ाइल के साथ वीएलसी लॉन्च करना तुरंत एक नोटिस में होना चाहिए, जबकि एक वेब ब्राउज़र के माध्यम से पेंडोरा का दौरा करने से इस तरह की सूचना भी शुरू हो जाएगी।

डीबगिंग से पता चलता है कि सभी लौटाए गए मूल्य S_OK हैं।

मेरा COM अनुभव काफी सीमित है, इसलिए सामान्य "डब्ल्यूटीएफ" को इंगित करना? भी सराहना की जाएगी।

+0

क्या कस्टमऑडियो नोटिफिकेशन :: QueryInterface कहा जाता है? क्या यह एस_ओके वापस आता है? – sharptooth

+0

अपने कारखाने के माध्यम से वस्तु का निर्माण करने के बाहर; नहीं, QueryInterface नहीं कहा जाता है। कम से कम, ब्रेकपॉइंट कभी नहीं फिसल जाता है। –

उत्तर

15

यह आपके लिए एक टन अधिक काम है।

आपको केवल एक कक्षा लिखने की आवश्यकता है जो IAudioSessionNotifications से प्राप्त होता है - आपको वास्तव में एक संपूर्ण COM ऑब्जेक्ट लिखने और उसे पंजीकृत करने की आवश्यकता नहीं है।

आपको eMultimedia भूमिका के बजाय ईकोनसोल भूमिका का भी उपयोग करना चाहिए। यह प्रभावी रूप से महत्वपूर्ण नहीं है (यदि आपके पास केवल एक ऑडियो डिवाइस है) लेकिन यह अधिक सही है।

कस्टमऑडियो नॉटिफिकेशन क्लास के लिए विनाशक निजी होना चाहिए - इस तरह आप आकस्मिक विनाश को रोकते हैं। तो मैं लिखना चाहते हैं:

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

मैं भी यह सोचते हैं रहा हूँ कि आप अपने कोड स्निपेट के पहले कॉम प्रारंभ कर दिया है।

UPDATED: केविन मुझे अपने आवेदन भेज दिया है और वहाँ है कि और अधिक मौलिक हैं

(मैं एपीआई के लिए भविष्य में किसी भी भ्रम की स्थिति को रोकने के लिए में सुधार प्रलेखन प्राप्त करने के लिए काम कर रहा हूँ) अपने आवेदन के साथ अन्य मुद्दों के एक जोड़े हैं

पहला यह है कि उनके एप्लिकेशन ने सत्रों की वर्तमान सूची पुनर्प्राप्त नहीं की है। यह सत्र गणना एपीआई के बारे में वास्तव में सूक्ष्म चीजों में से एक है। सत्र एपीआई का उपयोग करते समय एक सत्र अधिसूचना तब होती है जब सत्र अधिसूचना तब होती है जब सत्र अधिसूचना एपीआई शुरू हो जाती है, सत्र गणना API नई सत्र अधिसूचनाओं को त्याग देता है जब तक कि एप्लिकेशन ने पहले सत्रों की सूची को पुनर्प्राप्त नहीं किया हो।

उपयोग की अपेक्षित पद्धति है:

आवेदन एक सत्र Manager2 सक्रिय करता है। सत्र अधिसूचनाओं के लिए आवेदन रजिस्टर। एप्लिकेशन एंडपॉइंट के लिए सत्रों की वर्तमान सूची पुनर्प्राप्त करता है और सत्र नियंत्रण ऑब्जेक्ट्स को एक सूची में संग्रहीत करता है (सत्र को जोड़ने के लिए मत भूलना)।

जब कोई नया सत्र बनाया जाता है, तो एप्लिकेशन नव निर्मित सत्र नियंत्रण ऑब्जेक्ट का संदर्भ लेता है और यदि यह पहले से मौजूद नहीं है तो उसे सूची में सम्मिलित करता है। ध्यान दें कि अधिसूचना में पारित सत्र नियंत्रण वस्तु नष्ट हो जाएगी जब सत्र अधिसूचना वापस आती है - यदि आप इस बिंदु पर GetSessionEnumerator को कॉल करते हैं तो शायद यह नव निर्मित सत्र नहीं रखेगा (यह हो सकता है, यह सब समय पर निर्भर करता है)।

एप्लिकेशन सत्र के जीवनकाल को अपने मानदंडों के आधार पर प्रबंधित करता है - जब तक कि एप्लिकेशन सत्र नियंत्रण का संदर्भ रखता है, सत्र नियंत्रण ऑब्जेक्ट मान्य होगा। ऑडियो सत्र नियंत्रण वस्तुओं के लिए कोई समाप्ति तंत्र नहीं है।

इसके अतिरिक्त, सत्र एपीआई की आवश्यकता है कि एमटीए शुरू किया जाए - यह दुर्भाग्यपूर्ण है, लेकिन क्योंकि हम एक कार्यकर्ता थ्रेड पर COM ऑब्जेक्ट्स (जो IAudioSessionControl को लागू करते हैं) बनाते हैं, इसलिए एपीआई को अधिसूचना प्राप्त होने से पहले एमटीए बनाया जाना चाहिए।

+0

@ केविन, शायद आपको तब कोई बेहतर जवाब नहीं मिल सकता है। लैरी उन लोगों में से एक है जिन्होंने विंडोज ऑडियो कोड लिखा था। :) –