Synopsis:
Implement opaque streams, which will be used initially by Secure Audio Path.
 
Overview:
Secure Audio Path (SAP) is used by certain DRM content, in which the audio
data is fed to our application in an encrypted state, and is decrypted by
the audio driver.  Therefore, our app must not do anything to modify the
data during its journey through the core.
 
This is implemented by adding the concept of an opaque audio stream.  New
header values were added to the audio stream to signify this is an opaque
stream.  Audio services will see this header, and go into an "opaque mode".
This causes audio services to allow only one stream, and no modifications
may be done to it (no up/down mix, no pre- or post-mix hooks, etc).  Also,
the audio device will be opened in an opaque mode, passing to it any special
data needed for this type of opaque stream.  For SAP, this is a custom
WAVEFORMATEX header with which the audio device must be opened.

Files Modified:
client/audiosvc/hxaudses.cpp/.h:  Add flag for opaque mode, opens audio
device in opaque mode if needed, disables post-mix hooks in opaque mode
client/audiosvc/hxaudstr_new.cpp/.h: Read audio stream headers for opaque
mode, sets audio session to opaque mode if needed
client/audiosvc/mixengine.cpp/.h: Disables modifications to audio data if in
opaque mode
common/include/hxausvc.h and hxiids.h: Add new interface
IHXOpaqueAudioDevice
audio/device/hxaudev.cpp/.h: Implement IHXOpaqueAudioDevice interface.
Calls derived _Imp_OpaqueOpen in platform-specific audio device
audio/device/platform/win/hxaudevds.cpp/.h: Implemented opaque mode, uses
passed-in WAVEFORMATEX struct instead of building one when in opaque mode,
also disables real-time hooks.

Image Size and Heap Use impact:
Didn't measure, shouldn't add more than 1K total for image size and heap
use.

Platforms and Profiles Affected:
All

Distribution Libraries affected:
none
 
Distribution library impact and planned action:
none
 
-----------------------------------------------------------
 
Platforms and Profiles Build Verified:
win32-i386-vc7, helix-client-all-defines

Platforms and Profiles Functionality verified:
win32-i386-vc7, helix-client-all-defines

Branch:
neptune 116, 123, 150, and HEAD (I think that's all)

QA Instructions:
A seperate test plan has been written
Index: hxaudses.cpp
===================================================================
RCS file: /cvsroot/client/audiosvc/hxaudses.cpp,v
retrieving revision 1.28.4.9
diff -u -w -r1.28.4.9 hxaudses.cpp
--- hxaudses.cpp        13 Oct 2004 00:03:55 -0000      1.28.4.9
+++ hxaudses.cpp        3 May 2005 05:18:31 -0000
@@ -258,6 +258,8 @@
     , m_bSessionBufferDirty(FALSE)
     , m_bPostMixHooksUpdated(FALSE)
     , m_pMPPSupport(NULL)
+    , m_bOpaqueMode(FALSE)
+    , m_pOpaqueData(NULL)
 {
     m_pFakeAudioCBTime                  = new Timeval;
     m_pInDataPtr                        = new HXAudioData;
@@ -1714,7 +1716,7 @@
                     }
                 }
 
-                if (m_pHookList)
+                if (m_pHookList && !m_bOpaqueMode)
                 {
                     ProcessHooks(&audioData);
                 }
@@ -1985,6 +1987,16 @@
         {
             ((CHXAudioDevice*)m_pAudioDev)->SetGranularity( m_ulGranularity, 
m_ulBytesPerGran);
         }
+       if (m_bOpaqueMode)
+       {
+           IHXOpaqueAudioDevice* pOpaqueDevice = NULL;
+           m_pAudioDev->QueryInterface (IID_IHXOpaqueAudioDevice, (void 
**)&pOpaqueDevice);
+           if (!pOpaqueDevice)
+               return HXR_FAIL;
+           theErr = pOpaqueDevice->Open(&m_ActualDeviceFmt, this, 
m_strOpaqueType, m_pOpaqueData );
+           HX_RELEASE(pOpaqueDevice);
+       }
+       else
         theErr = m_pAudioDev->Open( &m_ActualDeviceFmt, this );
         bDeviceOpened = TRUE;
         m_ulBlocksWritten = 0;
@@ -2546,6 +2558,8 @@
     m_bDeferActualResume        = FALSE;
     m_pLastPausedPlayer         = NULL;
 
+    m_bOpaqueMode              = FALSE;
+    HX_RELEASE(m_pOpaqueData);
 
     HX_RELEASE(m_pMPPSupport);
 
@@ -4676,5 +4690,18 @@
 
 STDMETHODIMP_(BOOL) CHXAudioSession::HXDeviceSetupCallback::IsInterruptSafe()
 {
+    return TRUE;
+}
+
+BOOL CHXAudioSession::SetOpaqueMode( const char * pszOpaqueType, IHXBuffer * 
pOpaqueData )
+{
+    if( m_bOpaqueMode )
+       return FALSE;
+
+    m_bOpaqueMode = TRUE;
+    m_strOpaqueType = pszOpaqueType;
+    m_pOpaqueData = pOpaqueData;
+    m_pOpaqueData->AddRef();
+
     return TRUE;
 }
Index: hxaudstr_new.cpp
===================================================================
RCS file: /cvsroot/client/audiosvc/hxaudstr_new.cpp,v
retrieving revision 1.12.2.8
diff -u -w -r1.12.2.8 hxaudstr_new.cpp
--- hxaudstr_new.cpp    21 Sep 2004 20:08:15 -0000      1.12.2.8
+++ hxaudstr_new.cpp    2 May 2005 03:15:50 -0000
@@ -161,6 +161,7 @@
 ,      m_bMayNeedToRollbackTimestamp(FALSE)
 ,      m_piPendingAudioData(NULL)
 ,      m_nSoundLevelOffset(0)
+,      m_bIsOpaqueStream(FALSE)
 {
 /*
  *  Left around for future debugging
@@ -331,6 +332,26 @@
            SetAudioDeviceReflushHint(TRUE);
            m_Owner->m_Owner->CheckIfLastNMilliSecsToBeStored();
        }
+
+       ulVal = 0;
+       m_pValues->GetPropertyULONG32("IsOpaqueAudioStream", ulVal);
+       if (ulVal)
+       {
+           m_bIsOpaqueStream = TRUE;
+           IHXBuffer* pOpaqueType = NULL;
+           IHXBuffer* pOpaqueData = NULL;
+           if( FAILED(m_pValues->GetPropertyCString("OpaqueAudioStreamType", 
pOpaqueType)) ||
+               FAILED(m_pValues->GetPropertyBuffer("OpaqueAudioStreamData", 
pOpaqueData)) ||
+               !m_Owner->m_Owner->SetOpaqueMode( 
+                   (const char *)pOpaqueType->GetBuffer(), pOpaqueData))
+           {
+               HX_RELEASE(pOpaqueType);
+               HX_RELEASE(pOpaqueData);
+               return HXR_FAIL;
+           }
+           HX_RELEASE(pOpaqueType);
+           HX_RELEASE(pOpaqueData);
+       }
     }
 
     memcpy( &m_AudioFmt, pAudioFormat, sizeof(HXAudioFormat) );
@@ -1705,7 +1726,7 @@
 */
 
     // this call does all the mixing.
-    res = m_pMixEngine->MixIntoBuffer(pPlayerBuf, ulBufSize, 
bIsMixBufferDirty) ;
+    res = m_pMixEngine->MixIntoBuffer(pPlayerBuf, ulBufSize, 
bIsMixBufferDirty, m_bIsOpaqueStream) ;
     if (FAILED(res))
         return res ; 
 
@@ -1818,7 +1839,7 @@
          pInfo->llStartTimeInSamples,pInfo->llEndTimeInSamples,
          nn,
          nMixbufferOffset,nMixbufferOffset+nSamplesToUse,nSamplesToUse);
-     fprintf(f1,"  pastPacketStart = %I64d, nMixbufferOffset = %ld\n",
+     fprintf(f1,"  pastPacketStart = %ld, nMixbufferOffset = %ld\n",
                 pastPacketStart,nMixbufferOffset) ;
      fclose(f1);}
 */
Index: mixengine.cpp
===================================================================
RCS file: /cvsroot/client/audiosvc/mixengine.cpp,v
retrieving revision 1.8.4.2
diff -u -w -r1.8.4.2 mixengine.cpp
--- mixengine.cpp       21 Sep 2004 20:09:17 -0000      1.8.4.2
+++ mixengine.cpp       15 Apr 2005 22:15:01 -0000
@@ -322,7 +322,7 @@
 }
 #endif
 
-HX_RESULT HXAudioSvcMixEngine::MixIntoBuffer(void* pPlayerbuf0, UINT32 
ulBufSizeInBytes_4, BOOL &bIsMixBufferDirty)
+HX_RESULT HXAudioSvcMixEngine::MixIntoBuffer(void* pPlayerbuf0, UINT32 
ulBufSizeInBytes_4, BOOL &bIsMixBufferDirty, BOOL bOpaqueStream)
 {
     // our caller's sense of "dirty" is inverted
     bIsMixBufferDirty = !bIsMixBufferDirty ;
@@ -395,7 +395,7 @@
         //
 
         // downmix if necessary (creates nSamples_2 samples)
-        if (bHaveInput && m_nChannels_2_3 != m_nChannels_1)
+        if (bHaveInput && m_nChannels_2_3 != m_nChannels_1 && !bOpaqueStream)
             (*this.*m_pfDownmix)(m_pBuffer_1, nSamples_1) ;
 
         //
@@ -403,7 +403,7 @@
         //
 
 #ifdef HELIX_FEATURE_GAINTOOL
-        if (bHaveInput)
+        if (bHaveInput && !bOpaqueStream)
             gainFeed(m_pBuffer_1, nSamples_2, m_pGaintool) ;
 #endif
 
@@ -416,7 +416,7 @@
         // shifts other data. This needs to be worked out.
 
         tAudioSample *pResampOutput_3 ;
-        if (m_pResampler && bHaveInput)
+        if (m_pResampler && bHaveInput && !bOpaqueStream)
         {
 #ifdef HELIX_FEATURE_RESAMPLER
             // compiler should optimize one of these branches away.
@@ -477,7 +477,8 @@
         INT64 nSamplesInFade     = nSamples_3 - nSamplesBeforeFade ;
 
         if (nSamplesBeforeFade >= 0 // fade starts after this segment start
-            && nSamplesInFade > 0) // fade starts before this segment end
+            && nSamplesInFade > 0 // fade starts before this segment end
+           && !bOpaqueStream)
         {
             // time to start an XFade
             m_bPastXFade = TRUE ;
@@ -488,7 +489,7 @@
         // the XFader. Since it has a fast path when the XFade is done, this is
         // not a resource drain.
 
-        if (m_bPastXFade)
+        if (m_bPastXFade && !bOpaqueStream)
         {
             if (nSamplesBeforeFade < 0) // fade was started earlier
             {
@@ -507,7 +508,7 @@
         //
 
 #ifdef HELIX_FEATURE_LIMITER
-        if (m_pLimiter && NBITS_PER_AUDIOSAMPLE == 32)
+        if (m_pLimiter && NBITS_PER_AUDIOSAMPLE == 32 && !bOpaqueStream)
         {
             LimiterProcess((int*)pResampOutput_3, nSamples_3, m_pLimiter);
         }
@@ -536,10 +537,10 @@
             switch (m_ulBytesPerSample)
             {
             case 2:
-                upmix(pResampOutput_3, (INT16*)pPlayerbuf, m_upmixMachine, 
nSamples_3, bIsMixBufferDirty) ;
+               upmix(pResampOutput_3, (INT16*)pPlayerbuf, m_upmixMachine, 
nSamples_3, bOpaqueStream ? TRUE : bIsMixBufferDirty) ;
                 break ;
             case 4:
-                upmix(pResampOutput_3, (INT32*)pPlayerbuf, m_upmixMachine, 
nSamples_3, bIsMixBufferDirty) ;
+                upmix(pResampOutput_3, (INT32*)pPlayerbuf, m_upmixMachine, 
nSamples_3, bOpaqueStream ? TRUE : bIsMixBufferDirty) ;
                 break ;
             }
 
Index: pub/hxaudses.h
===================================================================
RCS file: /cvsroot/client/audiosvc/pub/hxaudses.h,v
retrieving revision 1.6.12.2
diff -u -w -r1.6.12.2 hxaudses.h
--- pub/hxaudses.h      2 Jul 2004 22:22:41 -0000       1.6.12.2
+++ pub/hxaudses.h      12 Apr 2005 02:03:30 -0000
@@ -438,6 +438,9 @@
 
     BOOL GetDisableMultiPlayPauseSupport();
 
+    BOOL SetOpaqueMode( const char * pszOpaqueType, IHXBuffer * 
pOpaqueStreamData );
+    BOOL IsOpaqueMode() { return m_bOpaqueMode; }
+
     /*  ************************************************************  */
     /*  Fake audio callback class.                                  */
     /*  ************************************************************  */
@@ -745,6 +748,9 @@
     BOOL                m_bPostMixHooksUpdated;
     IHXPreferences*     m_pPreferences;
     BOOL                m_bAudioDeviceSupportsVolume;
+    BOOL               m_bOpaqueMode;
+    IHXBuffer*         m_pOpaqueData;
+    CHXString          m_strOpaqueType;
 
     IHXMultiPlayPauseSupport* m_pMPPSupport;
 };
Index: pub/hxaudstr.h
===================================================================
RCS file: /cvsroot/client/audiosvc/pub/hxaudstr.h,v
retrieving revision 1.8.4.2
diff -u -w -r1.8.4.2 hxaudstr.h
--- pub/hxaudstr.h      21 Sep 2004 20:11:56 -0000      1.8.4.2
+++ pub/hxaudstr.h      14 Apr 2005 23:32:48 -0000
@@ -438,6 +438,7 @@
     INT16              m_nSoundLevelOffset;    // For audio level normalization
     BOOL               m_bMute;
     BOOL               m_bGotHooks;            // if TRUE if this stream has 
hooks
+    BOOL               m_bIsOpaqueStream;      // TRUE if this is an opaque 
audio stream
 
     INT64              m_llLastWriteTime;      // Time of last buffer written
     ULONG32            m_ulFudge;              // The fudge factor for 
detecting gaps
Index: pub/mixengine.h
===================================================================
RCS file: /cvsroot/client/audiosvc/pub/mixengine.h,v
retrieving revision 1.8.4.2
diff -u -w -r1.8.4.2 mixengine.h
--- pub/mixengine.h     21 Sep 2004 20:12:28 -0000      1.8.4.2
+++ pub/mixengine.h     15 Apr 2005 22:16:41 -0000
@@ -143,7 +143,8 @@
     HX_RESULT MixIntoBuffer(
         void* pPlayerBuf,
         UINT32 ulBufSizeInBytes,
-        BOOL&    bIsMixBufferDirty
+        BOOL&    bIsMixBufferDirty,
+       BOOL bOpaqueStream
     ) ;
 
     // guess what.
Index: hxausvc.h
===================================================================
RCS file: /cvsroot/common/include/hxausvc.h,v
retrieving revision 1.3.20.4
diff -u -w -r1.3.20.4 hxausvc.h
--- hxausvc.h   21 Sep 2004 20:26:24 -0000      1.3.20.4
+++ hxausvc.h   11 Apr 2005 21:45:08 -0000
@@ -50,6 +50,7 @@
 typedef _INTERFACE   IHXAudioStream2               IHXAudioStream2;
 typedef _INTERFACE   IHXAudioDevice                IHXAudioDevice;
 typedef _INTERFACE   IHXAudioDeviceResponse        IHXAudioDeviceResponse;
+typedef _INTERFACE   IHXOpaqueAudioDevice          IHXOpaqueAudioDevice;
 typedef _INTERFACE   IHXAudioHook                  IHXAudioHook;
 typedef _INTERFACE   IHXAudioDeviceHookManager     IHXAudioDeviceHookManager;
 typedef _INTERFACE   IHXAudioStreamInfoResponse    IHXAudioStreamInfoResponse;
@@ -618,6 +619,57 @@
      */
     STDMETHOD(OnTimeSync)         (THIS_
                                ULONG32                         /*IN*/ 
ulTimeEnd) PURE;
+};
+
+/****************************************************************************
+ * 
+ *  Interface:
+ * 
+ *     IHXOpaqueAudioDevice
+ * 
+ *  Purpose:
+ * 
+ * 
+ *  IID_IHXOpaqueAudioDevice:
+ * 
+ *     {00000717-0901-11d1-8B06-00A024406D59}
+ * 
+ */
+DEFINE_GUID(IID_IHXOpaqueAudioDevice, 0x00000717, 0x901, 0x11d1, 0x8b, 0x6, 
0x0, 
+            0xa0, 0x24, 0x40, 0x6d, 0x59);
+
+#undef  INTERFACE
+#define INTERFACE   IHXOpaqueAudioDevice
+
+DECLARE_INTERFACE_(IHXOpaqueAudioDevice, IUnknown)
+{
+    /*
+     *  IUnknown methods
+     */
+    STDMETHOD(QueryInterface)       (THIS_
+                    REFIID riid,
+                    void** ppvObj) PURE;
+
+    STDMETHOD_(ULONG32,AddRef)      (THIS) PURE;
+
+    STDMETHOD_(ULONG32,Release)     (THIS) PURE;
+
+    /*
+     *  IHXOpaqueAudioDevice methods
+     */
+
+    /************************************************************************
+    *  Method:
+    *      IHXOpaqueAudioDevice::Open
+    *  Purpose:
+    *      The caller calls this to open the audio device using the audio
+    *      format given.
+    */
+    STDMETHOD(Open)(THIS_
+                   const HXAudioFormat*    /*IN*/ pAudioFormat, 
+                   IHXAudioDeviceResponse* /*IN*/ pDeviceResponse, 
+                   const char*             /*IN*/ pszOpaqueType, 
+                   IHXBuffer*              /*IN*/ pOpaqueData) PURE;
 };
 
 /****************************************************************************
Index: hxiids.h
===================================================================
RCS file: /cvsroot/common/include/hxiids.h,v
retrieving revision 1.33.2.8
diff -u -w -r1.33.2.8 hxiids.h
--- hxiids.h    21 Sep 2004 20:26:24 -0000      1.33.2.8
+++ hxiids.h    9 Apr 2005 23:24:32 -0000
@@ -430,6 +430,7 @@
  *     IID_IHXAudioHookManager:         {0000070E-0901-11d1-8B06-00A024406D59}
  *     IID_IHXAudioDeviceHookManager:   {00000715-0901-11d1-8B06-00A024406D59}
  *     IID_IHXAudioLevelNormalization:  {00000716-0901-11d1-8B06-00A024406D59}
+ *     IID_IHXOpaqueAudioDevice:        {00000717-0901-11d1-8B06-00A024406D59}
 // $Private:
  *     IID_IHXMultiPlayPauseSupport:   {0000070F-0901-11d1-8B06-00A024406D59}
  *     IID_IHXAudioDeviceManager2:     {00000710-0901-11d1-8B06-00A024406D59}
@@ -456,6 +457,7 @@
 DEFINE_GUID_ENUM(IID_IHXAudioHookManager,           0x0000070E, 0x901, 0x11d1, 
0x8b, 0x6, 0x0, 0xa0, 0x24, 0x40, 0x6d, 0x59)
 DEFINE_GUID_ENUM(IID_IHXAudioDeviceHookManager,             0x00000715, 0x901, 
0x11d1, 0x8b, 0x6, 0x0, 0xa0, 0x24, 0x40, 0x6d, 0x59)
 DEFINE_GUID_ENUM(IID_IHXAudioLevelNormalization,     0x00000716, 0x901, 
0x11d1, 0x8b, 0x6, 0x0, 0xa0, 0x24, 0x40, 0x6d, 0x59)
+DEFINE_GUID_ENUM(IID_IHXOpaqueAudioDevice,          0x00000717, 0x901, 0x11d1, 
0x8b, 0x6, 0x0, 0xa0, 0x24, 0x40, 0x6d, 0x59)
 // $Private:
 DEFINE_GUID_ENUM(IID_IHXMultiPlayPauseSupport,   0x0000070F, 0x901, 0x11d1, 
0x8b, 0x6, 0x0, 0xa0, 0x24, 0x40, 0x6d, 0x59)
 DEFINE_GUID_ENUM(IID_IHXAudioDeviceManager2,     0x00000710, 0x901, 0x11d1, 
0x8b, 0x6, 0x0, 0xa0, 0x24, 0x40, 0x6d, 0x59)
Index: hxaudev.cpp
===================================================================
RCS file: /cvsroot/audio/device/hxaudev.cpp,v
retrieving revision 1.17.4.3
diff -u -w -r1.17.4.3 hxaudev.cpp
--- hxaudev.cpp 16 Dec 2004 00:48:27 -0000      1.17.4.3
+++ hxaudev.cpp 2 May 2005 03:17:32 -0000
@@ -153,6 +153,7 @@
     QInterfaceList qiList[] =
         {
             { GET_IIDHANDLE(IID_IHXAudioDevice), (IHXAudioDevice*)this },
+            { GET_IIDHANDLE(IID_IHXOpaqueAudioDevice), 
(IHXOpaqueAudioDevice*)this },
             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXAudioDevice*)this },
         };
     
@@ -338,6 +339,38 @@
 
     memcpy( &m_AudioFmt, pAudioFormat, sizeof(HXAudioFormat) ); /* Flawfinder: 
ignore */
     theErr = _Imp_Open( pAudioFormat );
+    
+    if (!theErr)
+    {
+        m_eState = E_DEV_OPENED;
+    }
+
+    return theErr;
+}
+
+/************************************************************************
+ *  Method:
+ *             IHXOpaqueAudioDevice::Open
+ *     Purpose:
+ *             Open the audio device using the given format in opaque mode
+ */
+HX_RESULT CHXAudioDevice::Open(
+    const HXAudioFormat*    /*IN*/ pAudioFormat, 
+    IHXAudioDeviceResponse* /*IN*/ pDeviceResponse, 
+    const char*                    /*IN*/ pszOpaqueType, 
+    IHXBuffer*             /*IN*/ pOpaqueData)
+{
+    HX_RESULT theErr = HXR_OK;
+
+    m_pDeviceResponse = pDeviceResponse;
+
+    if (m_pDeviceResponse)
+    {
+        m_pDeviceResponse->AddRef();
+    }
+
+    memcpy( &m_AudioFmt, pAudioFormat, sizeof(HXAudioFormat) ); /* Flawfinder: 
ignore */
+    theErr = _Imp_OpaqueOpen( pAudioFormat, pszOpaqueType, pOpaqueData );
     
     if (!theErr)
     {
Index: platform/win/hxaudevds.cpp
===================================================================
RCS file: /cvsroot/audio/device/platform/win/hxaudevds.cpp,v
retrieving revision 1.10.16.11
diff -u -w -r1.10.16.11 hxaudevds.cpp
--- platform/win/hxaudevds.cpp  17 Jan 2005 20:49:35 -0000      1.10.16.11
+++ platform/win/hxaudevds.cpp  2 May 2005 03:25:06 -0000
@@ -112,6 +112,8 @@
     ,  m_bExitThread(FALSE)
     ,  m_ulOriginalThreadId(0)
     ,  m_pAudioHookDMO(NULL)
+    ,  m_pWaveFormat(NULL)
+    ,  m_bOpaqueFormat(FALSE)
 {
     // Create a unique message for destroying the audio window
     if (!zm_uDestroyMessage)
@@ -144,6 +146,8 @@
 
 CHXAudioDeviceDS::~CHXAudioDeviceDS()
 {
+    HX_DELETE(m_pWaveFormat);
+
     if (m_hSoundDll)
     {
        FreeLibrary(m_hSoundDll);
@@ -197,25 +201,71 @@
     if (res == DS_OK)
     {
         res = !DS_OK ;
-        if (m_WaveFormat.Format.nChannels > 2)
+        if (m_pWaveFormat->nChannels > 2 || m_bOpaqueFormat)
         {
-            res = m_pPrimaryBuffer->SetFormat(&m_WaveFormat.Format) ;
+            res = m_pPrimaryBuffer->SetFormat(m_pWaveFormat) ;
         }
-        if (res != DS_OK)
+        if (res != DS_OK && !m_bOpaqueFormat)
         {
            /* if that fails, try to open with WAVE_FORMAT_PCM */
-           m_WaveFormat.Format.wFormatTag = WAVE_FORMAT_PCM ;
-           res = m_pPrimaryBuffer->SetFormat(&m_WaveFormat.Format) ;
+           m_pWaveFormat->wFormatTag = WAVE_FORMAT_PCM ;
+           res = m_pPrimaryBuffer->SetFormat(m_pWaveFormat) ;
         }
     }
     return res ;
 }
 
 /*
+ *  IHXOpaqueAudioDevice override methods
+ */
+HX_RESULT CHXAudioDeviceDS::_Imp_OpaqueOpen(
+    const HXAudioFormat*    /*IN*/ pAudioFormat, 
+    const char*                    /*IN*/ pszOpaqueType, 
+    IHXBuffer*             /*IN*/ pOpaqueData)
+{
+    if( !pszOpaqueType || !pOpaqueData || strcmp( pszOpaqueType, 
"audio/x-wma-sap" ) != 0  )
+       return HXR_FAIL;
+
+    HX_DELETE(m_pWaveFormat);
+
+    ULONG32 ulBufSize = pOpaqueData->GetSize();
+    m_pWaveFormat = (WAVEFORMATEX *) new BYTE[ ulBufSize ];
+    memcpy( m_pWaveFormat, pOpaqueData->GetBuffer(), ulBufSize );
+
+    m_bOpaqueFormat = TRUE;
+    return _DoOpen(pAudioFormat);
+}
+
+/*
  *  IHXAudioDevice override methods
  */
 HX_RESULT CHXAudioDeviceDS::_Imp_Open(const HXAudioFormat* pFormat)
 {
+    /* fill out the wave format structure */
+    WAVEFORMATEXTENSIBLE *pwfe = new WAVEFORMATEXTENSIBLE;
+
+    HX_DELETE(m_pWaveFormat);
+    m_pWaveFormat = (WAVEFORMATEX *) pwfe;
+
+    pwfe->Format.wFormatTag    = WAVE_FORMAT_EXTENSIBLE;
+    pwfe->Format.nChannels     = pFormat->uChannels;
+    pwfe->Format.nSamplesPerSec = pFormat->ulSamplesPerSec;    
+    pwfe->Format.wBitsPerSample = pFormat->uBitsPerSample;
+    pwfe->Format.nBlockAlign   = pFormat->uBitsPerSample/8 * 
pFormat->uChannels;
+    pwfe->Format.nAvgBytesPerSec= pwfe->Format.nBlockAlign * 
pFormat->ulSamplesPerSec;
+    pwfe->Format.cbSize                = 22;
+
+    pwfe->Samples.wValidBitsPerSample = pFormat->uBitsPerSample;
+    pwfe->SubFormat = KSDATAFORMAT_SUBTYPE_PCM ;
+
+    pwfe->dwChannelMask = defaultChannelMapping(pFormat->uChannels) ;
+
+    m_bOpaqueFormat = FALSE;
+    return _DoOpen(pFormat);
+}
+
+HX_RESULT CHXAudioDeviceDS::_DoOpen(const HXAudioFormat* pFormat)
+{
     HX_RESULT theErr = HXR_FAIL;
 
     if(!m_hwnd || !m_hSoundDll)
@@ -243,21 +293,6 @@
        primary buffer (16 bit, multichannel!), we need DSSCL_PRIORITY. */
     m_pDSDev->SetCooperativeLevel(m_hwnd, DSSCL_PRIORITY );
 
-    /* fill out the wave format structure */
-    ::memset(&m_WaveFormat, 0, sizeof(m_WaveFormat));
-    m_WaveFormat.Format.wFormatTag     = WAVE_FORMAT_EXTENSIBLE;
-    m_WaveFormat.Format.nChannels      = pFormat->uChannels;
-    m_WaveFormat.Format.nSamplesPerSec = pFormat->ulSamplesPerSec;     
-    m_WaveFormat.Format.wBitsPerSample = pFormat->uBitsPerSample;
-    m_WaveFormat.Format.nBlockAlign    = pFormat->uBitsPerSample/8 * 
pFormat->uChannels;
-    m_WaveFormat.Format.nAvgBytesPerSec = m_WaveFormat.Format.nBlockAlign * 
pFormat->ulSamplesPerSec ;
-    m_WaveFormat.Format.cbSize = 22;
-
-    m_WaveFormat.Samples.wValidBitsPerSample = pFormat->uBitsPerSample;
-    m_WaveFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM ;
-
-    m_WaveFormat.dwChannelMask = defaultChannelMapping(pFormat->uChannels) ;
-
     /* set the format of the primary buffer. This will fail on WDM systems 
(because
        the kernel mixer termines the primary buffer format), but is important 
on
        non-WDM systems.
@@ -275,14 +310,14 @@
     ::memset(&bufferDesc, 0, sizeof(DSBUFFERDESC));
 
     bufferDesc.dwSize     = sizeof(DSBUFFERDESC);
-    bufferDesc.lpwfxFormat = &m_WaveFormat.Format;
+    bufferDesc.lpwfxFormat = m_pWaveFormat;
 
     // Manipulate the buffer size so that is is an exact multiple of the block 
size.
     // This will ensure that our write positions on the buffer are the same in 
every loop.
     // We need to do this so that we have fixed playback notification 
positions marking the end each write block.
-    m_nBlocksPerBuffer = 
(m_WaveFormat.Format.nAvgBytesPerSec*BUFFER_TIME)/pFormat->uMaxBlockSize;
+    m_nBlocksPerBuffer = 
(m_pWaveFormat->nAvgBytesPerSec*BUFFER_TIME)/pFormat->uMaxBlockSize;
     m_ulTotalBuffer = pFormat->uMaxBlockSize*m_nBlocksPerBuffer;
-    m_ulLoopTime = (double)m_ulTotalBuffer / 
(double)m_WaveFormat.Format.nAvgBytesPerSec;
+    m_ulLoopTime = (double)m_ulTotalBuffer / 
(double)m_pWaveFormat->nAvgBytesPerSec;
 
     bufferDesc.dwBufferBytes = m_ulTotalBuffer ;
     bufferDesc.dwFlags =
@@ -291,25 +326,26 @@
                      DSBCAPS_CTRLPOSITIONNOTIFY | // have them reported here
                      DSBCAPS_GLOBALFOCUS | // take control!
                      DSBCAPS_STICKYFOCUS |
-#ifdef HELIX_FEATURE_AUDIO_DEVICE_HOOKS
-                     (bUsingDS8 && m_WaveFormat.Format.nChannels <= 2 ? 
DSBCAPS_CTRLFX : 0);
-#else
+//#ifdef HELIX_FEATURE_AUDIO_DEVICE_HOOKS
+                     (bUsingDS8 && m_pWaveFormat->nChannels <= 2 && 
!m_bOpaqueFormat ? DSBCAPS_CTRLFX : 0);
+//#else
                      0;
-#endif
+//#endif
 
     /* Again, try with WAVE_FORMAT_EXTENSIBLE first, but only if multichannel. 
*/
 
     theErr = !DS_OK ;
-    if (m_WaveFormat.Format.nChannels > 2)
+    if (m_pWaveFormat->nChannels > 2 || m_bOpaqueFormat)
     {
-        m_WaveFormat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+       if(!m_bOpaqueFormat)
+           m_pWaveFormat->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
         theErr = m_pDSDev->CreateSoundBuffer(&bufferDesc, &m_pSecondaryBuffer, 
NULL);
     }
 
-       if (theErr != DS_OK)
+    if (theErr != DS_OK && !m_bOpaqueFormat)
     {
        /* and if that fails, try WAVEFORMATEX */
-       m_WaveFormat.Format.wFormatTag  = WAVE_FORMAT_PCM;
+       m_pWaveFormat->wFormatTag = WAVE_FORMAT_PCM;
        theErr = m_pDSDev->CreateSoundBuffer(&bufferDesc, &m_pSecondaryBuffer, 
NULL);
     }
 
@@ -356,13 +392,14 @@
            delete[] aPositionNotify;
            DWORD dwWaitThreadID(0);
            m_hWaitThread = CreateThread(NULL, 0, EventThreadProc, 
(LPVOID)this, 0, &dwWaitThreadID);
+           SetThreadPriority( m_hWaitThread, THREAD_PRIORITY_HIGHEST );
        }
        HX_RELEASE(pNotify);
 
        m_pSecondaryBuffer->SetVolume(DSBVOLUME_MAX);
        m_pSecondaryBuffer->SetCurrentPosition(0);
 
-       if(bUsingDS8 && m_WaveFormat.Format.nChannels <= 2)
+       if(bUsingDS8 && m_pWaveFormat->nChannels <= 2 && !m_bOpaqueFormat)
        {
            LoadDirectSoundFilter();
        }
@@ -372,7 +409,7 @@
     m_ulCurrLoopTime = 0;
     m_ulLoops = 0;
     // Setup converter to convert from samples/sec to milliseconds
-    m_TSConverter.SetBase(m_WaveFormat.Format.nSamplesPerSec, 1000);
+    m_TSConverter.SetBase(m_pWaveFormat->nSamplesPerSec, 1000);
 
     return theErr;
 }
@@ -712,7 +749,7 @@
                if (dwCurrentPlayCursor > m_ulLastPlayCursor)
                {
                    ULONG32 ulSamplesPlayedThisLoop = 
-                       dwCurrentPlayCursor / m_WaveFormat.Format.nBlockAlign;
+                       dwCurrentPlayCursor / (m_pWaveFormat->wBitsPerSample/8 
* m_pWaveFormat->nChannels);
 
                    m_ulCurrPlayTime = m_ulCurrLoopTime + 
                        m_TSConverter.ConvertVector(ulSamplesPlayedThisLoop);
@@ -737,7 +774,7 @@
 inline UINT32 
 CHXAudioDeviceDS::CalcMs(UINT32 ulNumBytes)
 {
-    return (ulNumBytes * 1000UL) / m_WaveFormat.Format.nAvgBytesPerSec ;
+    return (ulNumBytes * 1000UL) / m_pWaveFormat->nAvgBytesPerSec ;
 }
 
 DWORD
Index: pub/hxaudev.h
===================================================================
RCS file: /cvsroot/audio/device/pub/hxaudev.h,v
retrieving revision 1.4.16.2
diff -u -w -r1.4.16.2 hxaudev.h
--- pub/hxaudev.h       2 Jul 2004 22:02:57 -0000       1.4.16.2
+++ pub/hxaudev.h       20 Apr 2005 00:18:40 -0000
@@ -65,7 +65,7 @@
  *      PN implementation of audio device object.
  *
  */
-class CHXAudioDevice: public IHXAudioDevice
+class CHXAudioDevice: public IHXAudioDevice, public IHXOpaqueAudioDevice
 {
 private:
 
@@ -93,6 +93,7 @@
        char*           m_pdevName;
 
        virtual         HX_RESULT       _Imp_Open(const HXAudioFormat* 
pAudioFormat ) = 0;
+       virtual         HX_RESULT       _Imp_OpaqueOpen(const HXAudioFormat* 
pAudioFormat, const char *pszOpaqueType, IHXBuffer *pOpaqueData ) { return 
HXR_FAIL; }
        virtual         HX_RESULT       _Imp_Close(void) = 0;
        virtual         HX_RESULT       _Imp_Seek(ULONG32 ulSeekTime) = 0;
        virtual         HX_RESULT       _Imp_Pause(void) = 0;
@@ -205,6 +206,16 @@
        STDMETHOD(Drain)                (THIS);
        STDMETHOD(CheckFormat)          (THIS_
                                         const HXAudioFormat* pAudioFormat);
+
+       /*
+       *  IHXOpaqueAudioDevice methods
+       */
+
+       STDMETHOD(Open)(THIS_
+                       const HXAudioFormat*    /*IN*/ pAudioFormat, 
+                       IHXAudioDeviceResponse* /*IN*/ pDeviceResponse, 
+                       const char*                 /*IN*/ pszOpaqueType, 
+                       IHXBuffer*                  /*IN*/ pOpaqueData);
 
        /* This function returns the most accurate audio playback time 
         * that can be ascertained from platform specific calls.
Index: pub/platform/win/hxaudevds.h
===================================================================
RCS file: /cvsroot/audio/device/pub/platform/win/hxaudevds.h,v
retrieving revision 1.4.16.6
diff -u -w -r1.4.16.6 hxaudevds.h
--- pub/platform/win/hxaudevds.h        26 Jul 2004 20:51:37 -0000      1.4.16.6
+++ pub/platform/win/hxaudevds.h        20 Apr 2005 00:18:40 -0000
@@ -71,7 +71,8 @@
        IDirectSoundBuffer *m_pPrimaryBuffer, *m_pSecondaryBuffer ;
        DWORD           defaultChannelMapping(UINT32 ulChannels) const ;
 
-       WAVEFORMATEXTENSIBLE    m_WaveFormat;
+       BOOL            m_bOpaqueFormat;
+       WAVEFORMATEX*   m_pWaveFormat;
        UINT32          m_ulLastPlayCursor;
        UINT32          m_ulLastWriteCursor;
        UINT32          m_ulCurrPlayTime;
@@ -110,7 +111,9 @@
 
     CHXAudioDeviceDS();
 
+    HX_RESULT              _DoOpen( const HXAudioFormat* pFormat );
     HX_RESULT              _Imp_Open( const HXAudioFormat* pFormat );
+    HX_RESULT              _Imp_OpaqueOpen( const HXAudioFormat* pFormat, 
const char *pszOpaqueType, IHXBuffer *pOpaqueData );
     HX_RESULT              _Imp_Close( void );
     HX_RESULT              _Imp_Seek(ULONG32 ulSeekTime) {     return HXR_OK; 
};
     HX_RESULT              _Imp_Pause( void );
_______________________________________________
Audio-dev mailing list
[email protected]
http://lists.helixcommunity.org/mailman/listinfo/audio-dev

Reply via email to