audOpwave.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:19k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: audOpwave.cpp,v 1.3.8.1 2004/07/09 02:01:26 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxcom.h"
  50. #include "hxresult.h"
  51. #include "hxengin.h"
  52. #include "ihxpckts.h"   // for IHXBuffer 
  53. #include "hxslist.h"
  54. #include "timeval.h"
  55. #include "hxausvc.h"
  56. #include "auderrs.h"
  57. #include "hxaudev.h"
  58. #include "hxaudses.h"
  59. #include "hxtick.h"
  60. #include "chxpckts.h"
  61. #include "debug.h"
  62. #include "audOpwave.h"
  63. #include "hlxclib/errno.h"
  64. #include "hxtick.h"
  65. //-1 is usually considered to be no file descriptor.
  66. const int CAudioOutOpenwave::NO_FILE_DESCRIPTOR = -1;
  67. const int CAudioOutOpenwave::MAX_VOLUME = 100;
  68. static const unsigned long BLOCK_SIZE = 176400;   // ~ 1s of audio, size of the write buffer
  69. //**************************************************************************
  70. // Prototypes.
  71. //
  72. static void
  73. iodone_callback (
  74. op_sound_handle const *handle,
  75. S32 msg,
  76. op_sound_buffer const *sndbuf,
  77. void *data
  78. );
  79. static void
  80. iodone_callback (
  81. op_sound_handle const *handle,
  82. S32 msg,
  83. op_sound_buffer const *sndbuf,
  84. void *data
  85. )
  86. {
  87. CAudioOutOpenwave *app = (CAudioOutOpenwave *) data;
  88. app->iodone();
  89. }
  90. void
  91. CAudioOutOpenwave::iodone()
  92. {
  93. if (m_bWriteDone) // huh? double buffering out of sync, we should always be writing
  94. {
  95. //OpDPRINTF("iodone: double buffering ERROR!!!n");
  96. //_PushBits();
  97. }
  98. m_bWriteDone = true;
  99. _PushBits();
  100. }
  101.     
  102. //XXXgfw We need to clean up the return values. We need to return only PN result codes
  103. //XXXgfw and not RA_AOE codes from interface methods.
  104. CAudioOutOpenwave::CAudioOutOpenwave() :
  105.     m_pCallback(NULL),
  106.     m_wState( RA_AOS_CLOSED ),
  107.     m_wLastError( RA_AOE_NOERR ),
  108.     m_bMixerPresent(FALSE),
  109.     m_wBlockSize(0),
  110.     m_ulLastNumBytes (0),
  111.     m_ulTotalWritten(0),
  112.     m_bFirstWrite (TRUE),
  113.     m_bInitCallback (TRUE),
  114.     m_pPlaybackCountCBTime(0),
  115.     m_PendingCallbackID (0),
  116.     m_bCallbackPending(FALSE),
  117.     m_pWriteList(NULL),
  118.     m_ulDeviceBufferSize(0),
  119.     m_ulLastTick(0),
  120.     m_pSndDev(NULL),
  121.     m_bWriteDone(true)
  122. {
  123. //Alloc a Timeval for use with the timer callback.
  124.     m_pPlaybackCountCBTime = new Timeval;
  125.     m_pCallback = new HXPlaybackCountCB(this);
  126.     m_pCallback->AddRef();
  127.     // Initialize the Openwave write buf struct
  128.     for (int i=0; i<10; i++)
  129.     {
  130. m_SndBuf[i].fSampleBuffer = malloc(BLOCK_SIZE);
  131. m_SndBuf[i].fNSamples = 0;
  132. m_SndBuf[i].fUserData = NULL;
  133. m_SndBuf[i].fState = OP_SNDBUF_STATE_READY;
  134. m_SndBuf[i].fFlags = OP_SNDBUFF_CALLBACK_ON_IODONE;
  135.     }
  136.     m_nCurBuf = 0;
  137.     m_ulSampleBufSize = BLOCK_SIZE;
  138.     
  139.     //Alloc our write buffer list. Want to throw from here? You will, like
  140.     //it or not.
  141.     m_pWriteList = new CHXSimpleList();
  142.     
  143. }
  144. void CAudioOutOpenwave::_initAfterContext()
  145. {    
  146. }
  147. CAudioOutOpenwave::~CAudioOutOpenwave()
  148. {
  149.     //We must assume that _Imp_Close has already been called. If not, we are 
  150.     //in big trouble.
  151.     if ( m_wState != RA_AOS_CLOSED ) 
  152.     {
  153.         HX_ASSERT( "Device not closed in dtor." == NULL );
  154.     }
  155.     //Clean up the scheduler.
  156.     HX_RELEASE( m_pScheduler );
  157.     HX_DELETE(m_pPlaybackCountCBTime);
  158.     HX_RELEASE(m_pCallback);
  159.     //OpDPRINTF("dtor: Freeing sample buffer, expect an exceptionn");
  160.     for (int i=0; i<10; i++)
  161.      HX_DELETE(m_SndBuf[i].fSampleBuffer);
  162.     //OpDPRINTF("dtor: Done freeing sample buffers n");
  163.     if (m_pSndDev) 
  164.     {
  165.      //OpDPRINTF("dtor : before freeing the channeln");
  166. op_sound_unregister_callback(m_pSndDev, iodone_callback);
  167. op_sound_freechan(m_pSndDev);
  168.      //OpDPRINTF("dtor : freeing the channeln");
  169.     }
  170.     HX_DELETE(m_pWriteList); // Remove all elements in the list, if any
  171. }
  172. UINT16 CAudioOutOpenwave::_Imp_GetVolume()
  173. {
  174.  
  175.     return m_uCurVolume;
  176. }
  177. HX_RESULT CAudioOutOpenwave::_Imp_SetVolume( const UINT16 uVolume )
  178. {
  179.     HX_RESULT retCode = RA_AOE_NOERR;
  180.     
  181. m_uCurVolume = uVolume;
  182.     m_wLastError = retCode;
  183.     return m_wLastError;
  184. }
  185. BOOL CAudioOutOpenwave::_Imp_SupportsVolume()
  186. {
  187.     return TRUE;
  188. }
  189. HX_RESULT CAudioOutOpenwave::_Imp_Open( const HXAudioFormat* pFormat )
  190. {
  191.     HX_RESULT retCode = RA_AOE_NOERR;
  192.     m_ulLastTick = GetTickCount();
  193. m_ulCurrentTime = 0;
  194. m_wState = RA_AOS_OPENING;
  195. m_wLastError = retCode;
  196. //////////////////////////////
  197. // open the channel
  198. //////////////////////////////
  199. OpError retval;
  200. if (m_pSndDev) 
  201. {
  202. //_Imp_Close(); // Close last channel
  203. //op_sound_unregister_callback(m_pSndDev, iodone_callback);
  204. op_sound_freechan(m_pSndDev);
  205. }
  206. //  Procure channels.  
  207. if (!(m_pSndDev = op_sound_allocchan (pFormat->uChannels)))
  208. return HXR_FAIL;
  209. m_unNumChannels = pFormat->uChannels;
  210. m_unSampleRate = pFormat->ulSamplesPerSec;
  211. m_unBitsPerSample = pFormat->uBitsPerSample;
  212.      m_unBytesPerSec = (m_unNumChannels * (m_unBitsPerSample/8) * m_unSampleRate);
  213. // Convert params into Openwave enums
  214. op_sound_pcm_format pcmfmt = OP_PCM_FMT_INVALID;
  215. switch (pFormat->uBitsPerSample)
  216. {
  217. case 8 : pcmfmt = OP_PCM_FMT_U8; break;
  218. case 16: pcmfmt = OP_PCM_FMT_U16_LE; break;
  219. }
  220. op_sound_pcm_rate pcmrate = OP_PCM_RATE_44100;
  221. switch (pFormat->ulSamplesPerSec)
  222. {
  223. case 8000 : pcmrate = OP_PCM_RATE_8000; break;
  224. case 11025: pcmrate = OP_PCM_RATE_11025; break;
  225. case 16000: pcmrate = OP_PCM_RATE_16000; break;
  226. case 22050: pcmrate = OP_PCM_RATE_22050; break;
  227. case 32000: pcmrate = OP_PCM_RATE_32000; break;
  228. case 44100: pcmrate = OP_PCM_RATE_44100; break;
  229. case 48000: pcmrate = OP_PCM_RATE_48000; break;
  230. case 64000: pcmrate = OP_PCM_RATE_64000; break;
  231. }
  232. //  Configure channels for playback.  
  233. retval = op_sound_set_params_args
  234.           (m_pSndDev,
  235.            OP_AUDIOTAG_VOLUME, 0xFFFF, // m_uCurVolume ?
  236.            OP_AUDIOTAG_PCMFORMAT, pcmfmt,
  237.    OP_AUDIOTAG_PCMRATE, pcmrate,
  238.            OP_AUDIOTAG_INTERLEAVESAMPLES, true,
  239.            OP_AUDIOTAG_END);
  240. if (retval < 0)
  241. return HXR_FAIL;
  242. //  Register our callback.  
  243. retval = op_sound_register_callback
  244.           (m_pSndDev, iodone_callback, this);
  245. if (retval < 0)
  246. return HXR_FAIL;
  247. // Start the device
  248. retval = op_sound_start (m_pSndDev);
  249. if (retval < 0)
  250. return HXR_FAIL;
  251.     //Schedule the timer callback...
  252.     if(m_pContext && !m_pScheduler)
  253.     {
  254.         m_pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler );
  255.     }
  256.     return m_wLastError;
  257. }
  258. HX_RESULT CAudioOutOpenwave::_Imp_Close()
  259. {
  260.     HX_RESULT retCode = RA_AOE_NOERR;
  261. if (m_pSndDev != NULL)
  262. {
  263.     // Stop the callback
  264.     op_sound_unregister_callback(m_pSndDev, iodone_callback);
  265. // Openwave error, can't free a channel when it's busy. Just free it in the destructor
  266. //op_sound_freechan(m_pSndDev);
  267. //m_pSndDev = NULL;
  268. }
  269.     //Remove callback from scheduler
  270.     if (m_bCallbackPending)
  271.     {
  272.         m_pScheduler->Remove(m_PendingCallbackID);
  273.         m_bCallbackPending = FALSE;
  274.     }
  275.     m_wLastError = retCode;
  276.     return m_wLastError;
  277. }
  278. // no support this.
  279. HX_RESULT CAudioOutOpenwave::_Imp_Seek(ULONG32 ulSeekTime)
  280. {
  281.     m_wLastError = HXR_OK;
  282.     return m_wLastError;
  283. }
  284. HX_RESULT CAudioOutOpenwave::_Imp_Pause()
  285. {
  286.     m_wLastError = HXR_OK;
  287. m_wState = RA_AOS_OPEN_PAUSED;
  288. op_sound_unregister_callback(m_pSndDev, iodone_callback);
  289. op_sound_pause(m_pSndDev);
  290.     return m_wLastError;
  291. }
  292. HX_RESULT CAudioOutOpenwave::_Imp_Resume()
  293. {
  294.     //XXXgfw We really should be closing and re-opening the device to be nice to other procs.
  295.     m_wLastError = HXR_OK;
  296. m_wState = RA_AOS_OPEN_PLAYING;
  297. m_ulLastTick = GetTickCount();
  298. op_sound_register_callback(m_pSndDev, iodone_callback, this);
  299. if (!m_bFirstWrite)
  300. {
  301. // Start the double buffering again
  302. m_bWriteDone = TRUE;
  303. _PushBits(); 
  304. m_bWriteDone = TRUE;
  305. _PushBits(); 
  306. }
  307. op_sound_resume(m_pSndDev);
  308.     return m_wLastError;
  309. }
  310. HX_RESULT CAudioOutOpenwave::_Imp_Reset()
  311. {
  312.     HX_RESULT retCode = RA_AOE_NOERR;
  313.     m_ulCurrentTime = 0;
  314. m_ulLastTick = GetTickCount();
  315.     m_wLastError = retCode;
  316.     return m_wLastError;
  317. }
  318. HX_RESULT CAudioOutOpenwave::_Imp_Drain()
  319. {
  320.     HX_RESULT retCode = RA_AOE_NOERR;
  321.     m_wLastError = retCode;
  322.     return m_wLastError;
  323. }
  324. HX_RESULT CAudioOutOpenwave::_Imp_CheckFormat( const HXAudioFormat* pFormat )
  325. {
  326.     HX_RESULT retCode = RA_AOE_NOERR;
  327.     m_wLastError       = HXR_OK;
  328.     return m_wLastError;
  329. }
  330. HX_RESULT CAudioOutOpenwave::_Imp_GetCurrentTime( ULONG32& ulCurrentTime )
  331. {
  332.     ULONG32 ulTime   = 0;
  333.     INT64  ulBytes  = 0;
  334.     /*
  335.   
  336. if (RA_AOS_OPEN_PLAYING == m_wState)
  337. {
  338. ulTime = GetTickCount();
  339.     
  340. HX_ASSERT(ulTime >= m_ulLastTick);
  341. //Not used anywhere but belongs to CHXAudioDevice so we must set it.
  342. m_ulCurrentTime  += (ulTime - m_ulLastTick);
  343. m_ulLastTick = ulTime;
  344. }
  345. ulCurrentTime = m_ulCurrentTime;
  346. */
  347. //// New implementation
  348.     ulBytes = _GetBytesActualyPlayed();
  349.     ulTime = (ULONG32) ((ulBytes * 1000) / m_unBytesPerSec);
  350.     
  351. //    OpDPRINTF("cur %d, new %dn", m_ulCurrentTime, ulTime);
  352.     //Not used anywhere but belongs to CHXAudioDevice so we must set it.
  353.     m_ulCurrentTime  = ulTime;
  354.     //Set the answer.
  355.     ulCurrentTime = ulTime;
  356.     m_wLastError = HXR_OK;
  357.     return HXR_OK;
  358. }
  359. void CAudioOutOpenwave::DoTimeSyncs()
  360. {
  361.     ReschedPlaybackCheck();
  362.     OnTimeSync();
  363.     return;
  364. }
  365. HX_RESULT CAudioOutOpenwave::ReschedPlaybackCheck()
  366. {
  367.     HX_RESULT retCode = HXR_OK;
  368.     
  369.     if(!m_bCallbackPending)
  370.     {
  371.         HX_ASSERT( m_pCallback );
  372.         if(m_pCallback)
  373.         {
  374.             *m_pPlaybackCountCBTime += (int)(500*m_ulGranularity);
  375.             m_bCallbackPending = TRUE;
  376.             m_PendingCallbackID = m_pScheduler->AbsoluteEnter( m_pCallback,*((HXTimeval*)m_pPlaybackCountCBTime));
  377.         }
  378.         else
  379.         {
  380.             retCode = HXR_OUTOFMEMORY;
  381.         }
  382.     }
  383.     m_wLastError = retCode;
  384.     return m_wLastError;
  385. }
  386. UINT16 CAudioOutOpenwave::_NumberOfBlocksRemainingToPlay(void)
  387. {
  388.     //XXXctd total hack, to make sure there is always data to write
  389.     if (m_pWriteList && !m_bFirstWrite && m_pWriteList->GetCount() > 10)
  390.     {
  391.    return m_pWriteList->GetCount(); 
  392.     }
  393.     return 0;
  394. }
  395. CAudioOutOpenwave::HXPlaybackCountCB::~HXPlaybackCountCB()
  396. {
  397. }
  398. STDMETHODIMP CAudioOutOpenwave::HXPlaybackCountCB::QueryInterface( REFIID riid, void** ppvObj )
  399. {
  400.     HX_RESULT retCode = HXR_OK;
  401.     
  402.     if( IsEqualIID(riid, IID_IHXCallback) )
  403.     {
  404.         AddRef();
  405.         *ppvObj = (IHXCallback*)this;
  406.     }
  407.     else if (IsEqualIID(riid, IID_IUnknown))
  408.     {
  409.         AddRef();
  410.         *ppvObj = this;
  411.     }
  412.     else
  413.     {
  414.         *ppvObj = NULL;
  415.         retCode = HXR_NOINTERFACE;
  416.     }
  417.     return retCode;
  418. }
  419. STDMETHODIMP_(ULONG32) CAudioOutOpenwave::HXPlaybackCountCB::AddRef()
  420. {
  421.     return InterlockedIncrement(&m_lRefCount);
  422. }
  423. STDMETHODIMP_(ULONG32) CAudioOutOpenwave::HXPlaybackCountCB::Release()
  424. {
  425.     
  426.     if (InterlockedDecrement(&m_lRefCount) > 0)
  427.     {
  428.         return m_lRefCount;
  429.     }
  430.     
  431.     delete this;
  432.     return HXR_OK;
  433. }
  434. STDMETHODIMP CAudioOutOpenwave::HXPlaybackCountCB::Func(void)
  435. {
  436.     if (m_pAudioDeviceObject)
  437.     {
  438.         if(!m_timed)
  439.         {
  440.             //m_pAudioDeviceObject->_Imp_Write(NULL);
  441.         }
  442.         else
  443.         {
  444.             m_pAudioDeviceObject->m_bCallbackPending  = FALSE;
  445.             //m_pAudioDeviceObject->_Imp_Write(NULL);
  446.             m_pAudioDeviceObject->DoTimeSyncs();
  447.         }
  448.     }
  449.     return HXR_OK;
  450. }
  451. HX_RESULT CAudioOutOpenwave::_Pause()
  452. {
  453.     return RA_AOE_NOTSUPPORTED;
  454. }
  455. HX_RESULT CAudioOutOpenwave::_Resume()
  456. {
  457.     return RA_AOE_NOTSUPPORTED;
  458. }
  459. BOOL CAudioOutOpenwave::_IsSelectable() const
  460. {
  461.     return TRUE;
  462. }
  463. BOOL CAudioOutOpenwave::_HardwarePauseSupported() const
  464. {
  465.     return FALSE;
  466. }
  467. // Don't protect anything in this method with mutexes. It has 
  468. // already been done from where it is called from. But mostly
  469. // because we aren't using recursive mutexes yet.
  470. ULONG32 CAudioOutOpenwave::_PushBits()
  471. {
  472.     if (!m_bWriteDone)
  473.     {
  474.      //OpDPRINTF("_PushBits : ERROR Both buffers are writing?n");
  475. return 0;
  476.     }
  477.     if (m_pWriteList == NULL || m_pWriteList->GetCount() <= 0)  
  478.     {
  479.      //OpDPRINTF("_PushBits : ERROR Nothing to writen");
  480.      //OpDPRINTF("_PushBits : m_pWriteList(%d) %dn", m_pWriteList->GetCount(), m_nCurBuf);
  481. return 0;
  482.     }
  483.     if (m_SndBuf[m_nCurBuf].fState == OP_SNDBUF_STATE_NOWPLAYING ||
  484.      m_SndBuf[m_nCurBuf].fState == OP_SNDBUF_STATE_QUEUED)
  485.     {
  486.      //OpDPRINTF("_PushBits : buf playing %dn", m_nCurBuf);
  487. return 0;
  488.     }
  489.     //OpDPRINTF("_PushBits : m_pWriteList(%d)n", m_pWriteList->GetCount());
  490.     IHXBuffer* pBuffer  = NULL;
  491.     UCHAR*      pData    = 0;
  492.     ULONG32     nSize = 0;
  493.     op_sound_buffer* sndbuf;
  494.     sndbuf = &m_SndBuf[m_nCurBuf];
  495.     m_nCurBuf = !m_nCurBuf;
  496.     //m_nCurBuf = (m_nCurBuf + 1) % 10;  // use all ten buffers
  497.     //We are going to try and write. Grab the head and do it.
  498.     pBuffer = (IHXBuffer*)m_pWriteList->RemoveHead();
  499.     pData   = pBuffer->GetBuffer();
  500.     nSize   = pBuffer->GetSize();
  501.     memcpy( (unsigned char*)sndbuf->fSampleBuffer, pData, nSize );
  502.     HX_RELEASE( pBuffer );
  503.     sndbuf->fNSamples = (nSize) / (m_unNumChannels * (m_unBitsPerSample/8));
  504.     m_ulTotalWritten += nSize; //Keep track of how much we have written to the device.
  505.     op_sound_write (m_pSndDev, sndbuf);
  506.     m_bWriteDone = false;
  507.     return nSize;
  508. }
  509. HX_RESULT CAudioOutOpenwave::_Imp_Write( const HXAudioData* pAudioOutHdr )
  510. {
  511.     ULONG32     ulCount  = 0;
  512.     //Schedule callbacks.
  513.     if( m_bInitCallback && pAudioOutHdr )
  514.     {
  515.         m_bInitCallback = FALSE;
  516.         //  Initialize the playback callback time.
  517.         HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime();
  518.         m_pPlaybackCountCBTime->tv_sec = lTime.tv_sec;
  519.         m_pPlaybackCountCBTime->tv_usec = lTime.tv_usec;
  520.         //  Scheduler playback callback.
  521.         ReschedPlaybackCheck();
  522.     }
  523.     //Blindly add the incoming data to the tail of the writelist.
  524.     if( pAudioOutHdr != NULL)
  525.     {
  526.         IHXBuffer* pTmpBuff = pAudioOutHdr->pData;
  527.         m_pWriteList->AddTail(pTmpBuff);
  528.         pTmpBuff->AddRef();
  529.     }
  530.     //OpDPRINTF("_Imp_Write : m_pWriteList(%d) n", m_pWriteList->GetCount());
  531.     //Just return if there is nothing to do 
  532.     if( m_pWriteList->GetCount() <= 0 || m_wState==RA_AOS_OPEN_PAUSED )
  533.     {
  534.         return RA_AOE_NOERR;
  535.     }
  536.     m_wState = RA_AOS_OPEN_PLAYING;
  537.     if( m_bFirstWrite )
  538.     {
  539. if (m_pWriteList->GetCount() >= 10)
  540. {
  541.          m_bFirstWrite = FALSE;
  542. for (int i=0; i<2; i++)
  543. {
  544. m_bWriteDone = TRUE;
  545. ulCount = _PushBits(); // Start the double buffering
  546. }
  547. }
  548.     }
  549.     else
  550.     {
  551.      //ulCount = _PushBits();// causes two competing threads
  552.     }
  553.     
  554.     if ( m_bInitCallback )
  555.     {
  556.         m_bInitCallback = FALSE;
  557.             
  558.         //  Initialize the playback callback time. 
  559.         HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime();
  560.         m_pPlaybackCountCBTime->tv_sec = lTime.tv_sec;
  561.         m_pPlaybackCountCBTime->tv_usec = lTime.tv_usec;
  562.             
  563.         //  Scheduler playback callback. 
  564.         ReschedPlaybackCheck();
  565.     }
  566.     //make sure the device is kept full.
  567.     //if( m_pWriteList->GetCount()>0 && ulCount>0)
  568.         //_PushBits();
  569.     return m_wLastError;
  570.     
  571. }
  572. //-------------------------------------------------------
  573. // These Device Specific methods must be implemented 
  574. // by the platform specific sub-classes.
  575. //-------------------------------------------------------
  576. INT16 CAudioOutOpenwave::_Imp_GetAudioFd(void)
  577. {
  578.     return 0;
  579. }
  580. //Device specific method to set the audio device characteristics. Sample rate,
  581. //bits-per-sample, etc.
  582. //Method *must* set member vars. m_unSampleRate and m_unNumChannels.
  583. HX_RESULT CAudioOutOpenwave::_SetDeviceConfig( const HXAudioFormat* pFormat )
  584. {
  585.     return RA_AOE_NOERR;
  586. }
  587. //Device specific method to write bytes out to the audiodevice and return a
  588. //count of bytes written. 
  589. HX_RESULT CAudioOutOpenwave::_WriteBytes( UCHAR* buffer, ULONG32 ulBuffLength, LONG32& lCount )
  590. {
  591.     HX_RESULT retCode = RA_AOE_NOERR;
  592.     return retCode;
  593. }
  594. //Device specific methods to open/close the mixer and audio devices.
  595. HX_RESULT CAudioOutOpenwave::_OpenAudio()
  596. {
  597.     HX_RESULT retCode = RA_AOE_NOERR;
  598.     
  599.     m_wLastError = retCode;
  600.     return m_wLastError;
  601. }
  602. HX_RESULT CAudioOutOpenwave::_CloseAudio()
  603. {
  604.     HX_RESULT retCode = RA_AOE_NOERR;
  605.     
  606.     m_wLastError = retCode;
  607.     return m_wLastError;
  608. }
  609. HX_RESULT CAudioOutOpenwave::_OpenMixer()
  610. {
  611.     HX_RESULT retCode = RA_AOE_NOERR;
  612.     m_wLastError = retCode;
  613.     return m_wLastError;
  614. }
  615. HX_RESULT CAudioOutOpenwave::_CloseMixer()
  616. {
  617.     HX_RESULT retCode = RA_AOE_NOERR;
  618.     m_wLastError = retCode;
  619.     return m_wLastError;
  620. }
  621. UINT64 CAudioOutOpenwave::_GetBytesActualyPlayed(void) const
  622. {
  623.     /* Get current playback position in device DMA. */
  624.     return  m_ulTotalWritten;
  625. }
  626. HX_RESULT CAudioOutOpenwave::_CheckSampleRate( ULONG32 ulSampleRate )
  627. {
  628.     ULONG32 ulTmp = ulSampleRate;
  629.     m_wLastError = RA_AOE_NOERR;
  630.     
  631.     return m_wLastError;
  632. }