audbeos.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:18k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. /*******************************************************************
  36.  * audbeos.cpp
  37.  *
  38.  * CLASS: CAudioOutBeOS
  39.  *
  40.  * DESCRIPTION: Class implementation for BeOS-specific audio devices 
  41.  *
  42.  *******************************************************************/
  43. #include "hxtypes.h"
  44. #include "hxresult.h"
  45. #include "hxcom.h"
  46. #include "ihxpckts.h"
  47. #include "hxausvc.h"
  48. #include "auderrs.h"
  49. #include "hxaudev.h"
  50. #include "hxtick.h"
  51. #include "hxthread.h"
  52. #include "hxbuffer.h"
  53. #include "hxslist.h"
  54. #include "hxengin.h"
  55. #include "timeval.h"
  56. #include "hxaudses.h"
  57. #include "audbeos.h"
  58. #include <PushGameSound.h>
  59. #include <MediaDefs.h>
  60. struct IHXCallback;  // forward declaration needed for callback.
  61. CAudioOutBeOS::CAudioOutBeOS()
  62.     : m_player(NULL)
  63.     , m_bFirstWrite(TRUE)
  64.     , m_pPendingBufferList(NULL)
  65.     , m_ulLastPlayCursor(0)
  66.     , m_ulCurrentPlayTime(0)
  67.     , m_ulLastTimeSync(0)
  68.     , m_bPlaying(FALSE)
  69. , m_ulBufferSize(0)
  70. , m_ulFrameSize(0)
  71. , m_ulNextWriteOffset(0)
  72. , m_ulOldBytesLeft(0)
  73. , m_ulBlockSize(0)
  74. , m_bGotAWrite(FALSE)
  75. #if _BEOS_AUDIODEV_CALLBACK
  76. , m_pPlaybackCountCBTime(NULL)
  77. , m_bCallbackPending(FALSE)
  78. , m_PendingCallbackID(0)
  79. #endif
  80. {
  81. #if _BEOS_AUDIODEV_CALLBACK
  82. m_pPlaybackCountCBTime = new Timeval;
  83. #endif
  84. }    
  85. CAudioOutBeOS::~CAudioOutBeOS()
  86. {
  87. _Imp_Close();
  88. #if _BEOS_AUDIODEV_CALLBACK
  89. delete m_pPlaybackCountCBTime;
  90. #endif
  91. }
  92. HX_RESULT 
  93. CAudioOutBeOS::_Imp_Open(const HXAudioFormat* pFormat)
  94. {
  95. size_t bufSize;
  96. void *basePtr;
  97.     SetFormat(pFormat);
  98. #if _BEOS_AUDIODEV_CALLBACK
  99. if (m_pOwner)
  100. {
  101. m_pOwner->GetScheduler(&m_pScheduler);
  102. m_pScheduler->AddRef();
  103. }
  104. #endif
  105. // set up the player with enough buffer space for about 4 seconds of audio
  106. // m_player = new BPushGameSound(m_gameSoundFormat.frame_rate, &m_gameSoundFormat, 4);
  107. // BPushGameSound->CurrentPosition is accurate to within a buffer
  108. // Therefore, to keep good synchronization between audio and video, a single
  109. // buffer should not have a longer duration than a frame of video. We don't
  110. // know here what the video framerate (if any) may be, but we can assume that it
  111. // isn't over 30fps. Thus, each audio buffer should be no longer than about 30 ms.
  112. // To store about 3 seconds of audio, we'll need 100 buffers.
  113. bufSize = (size_t)(m_gameSoundFormat.frame_rate * 0.03f);
  114. m_player = new BPushGameSound(bufSize, &m_gameSoundFormat, 100);
  115. if (m_player->InitCheck() != B_OK)
  116. {
  117. delete m_player;
  118. m_player = NULL;
  119. return RA_AOE_BADOPEN;
  120. }
  121. if (m_player->LockForCyclic(&basePtr, &bufSize) != BPushGameSound::lock_ok)
  122. m_player->UnlockCyclic();
  123. m_ulBufferSize = bufSize;
  124. m_ulBlockSize = m_ulBytesPerGran;
  125. return HXR_OK;
  126. }
  127. HX_RESULT 
  128. CAudioOutBeOS::_Imp_Close()
  129. {
  130. #if _BEOS_AUDIODEV_CALLBACK
  131. if (m_pScheduler)
  132. {
  133. // Remove callback from scheduler
  134. if (m_bCallbackPending)
  135. {
  136. m_pScheduler->Remove(m_PendingCallbackID);
  137. m_bCallbackPending = FALSE;
  138. }
  139. m_pScheduler->Release();
  140. m_pScheduler = NULL;
  141. }
  142. #endif
  143. if (m_pPendingBufferList)
  144. {
  145. while (!m_pPendingBufferList->IsEmpty())
  146. {
  147. IHXBuffer *pBuffer = (IHXBuffer *)m_pPendingBufferList->RemoveHead();
  148. pBuffer->Release();
  149. pBuffer = NULL;
  150. }
  151. delete m_pPendingBufferList;
  152. m_pPendingBufferList = NULL;
  153. }
  154. if (m_player)
  155. {
  156. m_player->StopPlaying();
  157. delete m_player;
  158. m_player = NULL;
  159. }
  160. m_bPlaying = FALSE;
  161.     return HXR_OK;
  162. }
  163. HX_RESULT 
  164. CAudioOutBeOS::_Imp_Seek(ULONG32 ulSeekTime)
  165. {
  166.     return HXR_OK;
  167. }
  168. HX_RESULT 
  169. CAudioOutBeOS::_Imp_Pause()
  170. {
  171. if (m_player)
  172. {
  173. size_t curPos = m_player->CurrentPosition() * m_ulFrameSize;
  174. uint8 *pAudioPtr;
  175. size_t i, ulAudioBytes;
  176. m_player->StopPlaying();
  177. if (m_player->LockForCyclic((void **)&pAudioPtr, &ulAudioBytes) == BPushGameSound::lock_ok && pAudioPtr)
  178. {
  179. // shift the audio data all back to the beginning of the buffer
  180. if (m_ulNextWriteOffset > curPos)
  181. {
  182. for (i = curPos; i < m_ulNextWriteOffset; i++)
  183. {
  184. pAudioPtr[i - curPos] = pAudioPtr[i];
  185. }
  186. m_ulNextWriteOffset = m_ulNextWriteOffset - curPos;
  187. }
  188. else
  189. { // wrap-around
  190. uint32 remaining = ulAudioBytes - curPos;
  191. uint8 *tempBuf = new uint8[m_ulNextWriteOffset];
  192. for (i = 0; i < m_ulNextWriteOffset; i++)
  193. {
  194. tempBuf[i] = pAudioPtr[i];
  195. }
  196. for (i = curPos; i < ulAudioBytes; i++)
  197. {
  198. pAudioPtr[i - curPos] = pAudioPtr[i];
  199. }
  200. for (i = 0; i < m_ulNextWriteOffset; i++)
  201. {
  202. pAudioPtr[i + remaining] = tempBuf[i];
  203. }
  204. delete [] tempBuf;
  205. m_ulNextWriteOffset = remaining + m_ulNextWriteOffset;
  206. }
  207. m_player->UnlockCyclic();
  208. m_bGotAWrite = TRUE;
  209. m_ulLastPlayCursor = 0;
  210. }
  211. }
  212. m_bPlaying = FALSE;
  213. return HXR_OK;
  214. }
  215. HX_RESULT 
  216. CAudioOutBeOS::_Imp_Resume()
  217. {
  218. if (m_player)
  219. m_player->StartPlaying();
  220. m_ulLastPlayCursor = 0;
  221. m_bPlaying = TRUE;
  222. m_ulLastTimeSync = HX_GET_TICKCOUNT();
  223. OnTimeSync();
  224. return HXR_OK;
  225. }
  226. HX_RESULT 
  227. CAudioOutBeOS::_Imp_Write(const HXAudioData* pAudioOutData)
  228. {
  229. HX_RESULT theErr = HXR_OK;
  230. IHXBuffer *pBuffer = NULL;
  231. #if _BEOS_AUDIODEV_CALLBACK
  232. if (m_bFirstWrite && pAudioOutData)
  233. {
  234. /*  Initialize the playback callback time. */
  235. HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime();
  236. m_pPlaybackCountCBTime->tv_sec = lTime.tv_sec;
  237. m_pPlaybackCountCBTime->tv_usec = lTime.tv_usec;
  238. m_bFirstWrite = FALSE;
  239. ReschedPlaybackCheck();
  240. }
  241. #endif
  242. if (pAudioOutData && pAudioOutData->pData)
  243. {
  244. pAudioOutData->pData->AddRef();
  245. }
  246. if (m_pPendingBufferList && m_pPendingBufferList->GetCount() > 0)
  247. {
  248. if (pAudioOutData && pAudioOutData->pData)
  249. m_pPendingBufferList->AddTail(pAudioOutData->pData);
  250. pBuffer = (IHXBuffer *)m_pPendingBufferList->RemoveHead();
  251. }
  252. else
  253. {
  254. if (pAudioOutData && pAudioOutData->pData)
  255. pBuffer = pAudioOutData->pData;
  256. }
  257.     BOOL    bCanContinue = TRUE;
  258. while (bCanContinue && pBuffer)
  259. {
  260. UINT32 ulBufferSize = pBuffer->GetSize();
  261. uint8* pAudioPtr1 = NULL;
  262. uint8* pAudioPtr2 = NULL;
  263. size_t curPos;
  264. size_t ulAudioBytes1 = 0;
  265. size_t ulAudioBytes2 = 0;
  266. size_t ulAudioBytesWritten1 = 0;
  267. size_t ulAudioBytesWritten2 = 0;
  268. if (m_player->LockForCyclic((void **)&pAudioPtr1, &ulAudioBytes1) == BPushGameSound::lock_ok && pAudioPtr1)
  269. {
  270. size_t ulSizeToWrite, curPos;
  271. if (m_player->IsPlaying())
  272. curPos = m_player->CurrentPosition() * m_ulFrameSize;
  273. else
  274. curPos = 0;
  275. if (m_ulNextWriteOffset >= curPos)
  276. {
  277. pAudioPtr2 = pAudioPtr1;
  278. ulAudioBytes1 -= m_ulNextWriteOffset;
  279. }
  280. else
  281. {
  282. pAudioPtr2 = NULL;
  283. ulAudioBytes1 = curPos - m_ulNextWriteOffset - 1;
  284. }
  285. pAudioPtr1 += m_ulNextWriteOffset;
  286. if (ulAudioBytes1 < 0)
  287. ulAudioBytes1 = 0;
  288. ulSizeToWrite = ulBufferSize;
  289. if (ulSizeToWrite > ulAudioBytes1)
  290. {
  291. ulSizeToWrite = ulAudioBytes1;
  292. }
  293. if (ulSizeToWrite > 0)
  294. {
  295. ::memcpy(pAudioPtr1, (void*) pBuffer->GetBuffer(), ulSizeToWrite); /* Flawfinder: ignore */
  296. }
  297. ulAudioBytesWritten1 = ulSizeToWrite;
  298. size_t ulRemainingToWrite = ulBufferSize - ulSizeToWrite;
  299. ulAudioBytes2 = curPos - 1;
  300. if (ulRemainingToWrite > 0 && pAudioPtr2 && ulAudioBytes2 > 0)
  301. {
  302. ulSizeToWrite = ulRemainingToWrite;
  303. if (ulSizeToWrite > ulAudioBytes2)
  304. {
  305. ulSizeToWrite = ulAudioBytes2;
  306. }
  307. ::memcpy(pAudioPtr2, (void*) (pBuffer->GetBuffer() + ulAudioBytesWritten1), ulSizeToWrite);
  308. ulAudioBytesWritten2 = ulSizeToWrite;
  309. ulRemainingToWrite -= ulSizeToWrite;
  310. }
  311. if (ulRemainingToWrite > 0)
  312. {
  313. IHXBuffer* pNewBuffer = (IHXBuffer*) new CHXBuffer;
  314. pNewBuffer->AddRef();
  315. pNewBuffer->Set(pBuffer->GetBuffer() + (ulBufferSize - ulRemainingToWrite), ulRemainingToWrite);
  316. if (!m_pPendingBufferList)
  317. {
  318. m_pPendingBufferList = new CHXSimpleList;
  319. }
  320. m_pPendingBufferList->AddHead((void*) pNewBuffer);
  321. // no more space in the secondary buffer
  322. bCanContinue = FALSE;
  323. }
  324. m_player->UnlockCyclic();
  325. m_ulNextWriteOffset += ulAudioBytesWritten1 + ulAudioBytesWritten2;
  326. if (pAudioOutData)
  327. m_bGotAWrite = TRUE;
  328. if (m_ulNextWriteOffset >= m_ulBufferSize)
  329. {
  330. m_ulNextWriteOffset -= m_ulBufferSize;
  331. }
  332. if (m_bFirstWrite)
  333. {
  334. m_bFirstWrite = FALSE;
  335. }
  336. } // lock
  337. else
  338. {
  339. bCanContinue = FALSE;
  340. if (!m_pPendingBufferList)
  341. {
  342. m_pPendingBufferList = new CHXSimpleList;
  343. }
  344. pBuffer->AddRef();
  345. m_pPendingBufferList->AddHead((void*) pBuffer);
  346. }
  347. pBuffer->Release();
  348. pBuffer = NULL;
  349. if (bCanContinue && m_pPendingBufferList && m_pPendingBufferList->GetCount() > 0)
  350. {
  351. pBuffer = (IHXBuffer*) m_pPendingBufferList->RemoveHead();
  352. }
  353. } // while
  354. if (m_bPlaying)
  355. {
  356. UINT32 ulCurrentTime = HX_GET_TICKCOUNT();
  357. if (CALCULATE_ELAPSED_TICKS(m_ulLastTimeSync, ulCurrentTime) > 100)
  358. {
  359. m_ulLastTimeSync = ulCurrentTime;
  360. OnTimeSync();
  361. }
  362. }
  363. //@ This is an ugly hack, but it seems to work very well.
  364. // Hopefully I can figure it out and fix it properly at some point.
  365. // (mclifton 10/5/99)
  366. /*if (pAudioOutData && m_bPlaying && m_pPendingBufferList && m_pPendingBufferList->GetCount() > 0)
  367. {
  368. snooze(50000);
  369. _Imp_Write(NULL);
  370. }
  371. if (pAudioOutData && m_bPlaying && m_pPendingBufferList && m_pPendingBufferList->GetCount() > 0)
  372. {
  373. snooze(50000);
  374. _Imp_Write(NULL);
  375. }*/
  376. return theErr;
  377. }
  378. HX_RESULT 
  379. CAudioOutBeOS::_Imp_Reset()
  380. {
  381.     m_ulCurrentPlayTime = 0;
  382.     m_bFirstWrite = TRUE;
  383. m_ulNextWriteOffset = 0;
  384. if (m_player)
  385. m_player->StopPlaying();
  386. m_bPlaying = FALSE;
  387.     return HXR_OK;
  388. }
  389. HX_RESULT 
  390. CAudioOutBeOS::_Imp_Drain()
  391. {
  392.     return HXR_OK;
  393. }
  394. BOOL 
  395. CAudioOutBeOS::_Imp_SupportsVolume()
  396. {
  397.     return TRUE;
  398. }
  399. UINT16 
  400. CAudioOutBeOS::_Imp_GetVolume()
  401. {
  402. float vol = 0.0f;
  403. if (m_player)
  404. vol = m_player->Gain();
  405. return (UINT16)(vol * 100.0f);
  406. }
  407. HX_RESULT 
  408. CAudioOutBeOS::_Imp_SetVolume(const UINT16 uVolume)
  409. {
  410. float vol = (float)uVolume / 100.0f;
  411. if (m_player)
  412. m_player->SetGain(vol);
  413.     return HXR_OK;
  414. }
  415. HX_RESULT 
  416. CAudioOutBeOS::_Imp_CheckFormat(const HXAudioFormat* pFormat)
  417. {
  418.     return HXR_OK;
  419. }
  420. HX_RESULT 
  421. CAudioOutBeOS::_Imp_GetCurrentTime(ULONG32& ulCurrentTime)
  422. {
  423. size_t curPos = 0;
  424. if (m_player)
  425. {
  426. if (m_player->IsPlaying())
  427. curPos = m_player->CurrentPosition() * m_ulFrameSize;
  428. // This method of calculating elapsed time was basically copied over from
  429. // the DirectSound code. The bad news is that it is error-prone. Converting
  430. // from bytes to milliseconds is prone to roundoff, leading to an accumulation
  431. // of error, causing a drift of synchronization between audio and video.
  432. // (That DirectSound code has caused me nothing but headaches...)
  433. //m_ulCurrentPlayTime +=
  434. // CalcMs(CalculateElapsedBytes(m_ulLastPlayCursor, curPos));
  435. // The more accurate way to do it is to accumulate elapsed bytes, then
  436. // convert the total to milliseconds. The elapsed bytes is accurate to
  437. // within a video frame or so. Even though it can't be absolutely accurate,
  438. // at least it won't drift over time.
  439. m_ulCurrentPlayTime +=
  440. CalculateElapsedBytes(m_ulLastPlayCursor, curPos);
  441. m_ulLastPlayCursor = curPos;
  442. }
  443. // old method
  444. //ulCurrentTime = m_ulCurrentPlayTime;
  445. // new method
  446. ulCurrentTime = CalcMs(m_ulCurrentPlayTime);
  447. return HXR_OK;
  448. }
  449. UINT16
  450. CAudioOutBeOS::_NumberOfBlocksRemainingToPlay(void)
  451. {
  452. UINT32 res = 0;
  453. size_t curPos = 0;
  454. // add up the number of audio bytes queued up
  455. if (m_pPendingBufferList)
  456. {
  457. LISTPOSITION i = m_pPendingBufferList->GetHeadPosition();
  458. while (i)
  459. {
  460. res += ((IHXBuffer *)m_pPendingBufferList->GetAt(i))->GetSize();
  461. m_pPendingBufferList->GetNext(i);
  462. }
  463. }
  464. // add in the bytes that are currently in the playback buffer
  465. if (m_player)
  466. {
  467. UINT32 playingBytes = 0;
  468. if (m_player->IsPlaying())
  469. curPos = m_player->CurrentPosition() * m_ulFrameSize;
  470. if (curPos < m_ulNextWriteOffset)
  471. playingBytes += m_ulNextWriteOffset - curPos;
  472. else
  473. playingBytes += (m_ulBufferSize - curPos) + m_ulNextWriteOffset;
  474. res += playingBytes;
  475. }
  476. if (m_bGotAWrite)
  477. m_ulOldBytesLeft = res;
  478. else if (res > m_ulOldBytesLeft)
  479. {
  480. fprintf(stderr, "Buffer overflow!n");
  481. // This is a bad situation - I wish this never happened.
  482. // But what should I do when it does happen?
  483. // I used to return 0, since I thought that would force more
  484. // audio buffers my way, but it also seems to introduce more glitches.
  485. //res = 0;
  486. }
  487. m_bGotAWrite = FALSE;
  488. res /= m_ulBlockSize;
  489. return res;
  490. }
  491. void
  492. CAudioOutBeOS::SetFormat(const HXAudioFormat* pFormat)
  493. {
  494.     ::memset(&m_gameSoundFormat, 0, sizeof(gs_audio_format));
  495. m_gameSoundFormat.frame_rate = pFormat->ulSamplesPerSec;
  496. m_gameSoundFormat.channel_count = pFormat->uChannels;
  497. switch (pFormat->uBitsPerSample)
  498. {
  499. case 8:
  500. m_gameSoundFormat.format = gs_audio_format::B_GS_U8;
  501. break;
  502. case 16:
  503. m_gameSoundFormat.format = gs_audio_format::B_GS_S16;
  504. break;
  505. }
  506. m_gameSoundFormat.byte_order = B_MEDIA_LITTLE_ENDIAN;
  507. m_gameSoundFormat.buffer_size = 2048;
  508. m_ulFrameSize = m_gameSoundFormat.channel_count * ((m_gameSoundFormat.format==gs_audio_format::B_GS_U8)?1:2);
  509. }
  510. inline UINT32 
  511. CAudioOutBeOS::CalcMs(ULONG32 ulNumBytes)
  512. {
  513.     return ( (ULONG32) (( 1000.0
  514. / (m_ulFrameSize
  515. *  m_gameSoundFormat.frame_rate) )
  516. *  ulNumBytes) );
  517. }
  518. inline UINT32
  519. CAudioOutBeOS::CalculateElapsedBytes(UINT32 ulLastBytePos, UINT32 ulCurrentBytePos)
  520. {
  521.  return ((ulCurrentBytePos >= ulLastBytePos) ? (ulCurrentBytePos - ulLastBytePos) : (ulCurrentBytePos + (m_ulBufferSize - ulLastBytePos)));
  522. }
  523. #if _BEOS_AUDIODEV_CALLBACK
  524. void
  525. CAudioOutBeOS::DoTimeSyncs(void)
  526. {
  527. ReschedPlaybackCheck();
  528. OnTimeSync();
  529. return;
  530. }
  531. HX_RESULT
  532. CAudioOutBeOS::ReschedPlaybackCheck()
  533. {
  534. HX_RESULT theErr = HXR_OK;
  535. if (m_bCallbackPending)
  536. return theErr;
  537. *m_pPlaybackCountCBTime += (int)(m_ulGranularity * 1000) / 2;
  538. // Put this back in the scheduler.
  539. HXPlaybackCountCb *pCallback = 0;
  540. pCallback = new HXPlaybackCountCb(TRUE);
  541. if (pCallback)
  542. {
  543. pCallback->m_pAudioDeviceObject = this;
  544. m_bCallbackPending = TRUE;
  545. m_PendingCallbackID = m_pScheduler->AbsoluteEnter(pCallback, *((HXTimeval *)m_pPlaybackCountCBTime));
  546. }
  547. else
  548. theErr = HXR_OUTOFMEMORY;  // but ignored, why?
  549. return theErr;
  550. }
  551. CAudioOutBeOS::HXPlaybackCountCb::HXPlaybackCountCb(BOOL timed) 
  552. : m_lRefCount(0)
  553. , m_pAudioDeviceObject(0)
  554. , m_timed(timed)
  555. {
  556. }
  557. CAudioOutBeOS::HXPlaybackCountCb::~HXPlaybackCountCb()
  558. {
  559. }
  560. /*
  561.  * IUnknown methods
  562.  */
  563. /////////////////////////////////////////////////////////////////////////
  564. //      Method:
  565. //              IUnknown::QueryInterface
  566. //      Purpose:
  567. //              Implement this to export the interfaces supported by your 
  568. //              object.
  569. //
  570. STDMETHODIMP CAudioOutBeOS::HXPlaybackCountCb::QueryInterface(REFIID riid, void** ppvObj)
  571. {
  572. if (IsEqualIID(riid, IID_IHXCallback))
  573. {
  574. AddRef();
  575. *ppvObj = (IHXCallback*)this;
  576. return HXR_OK;
  577. }
  578. else if (IsEqualIID(riid, IID_IUnknown))
  579. {
  580. AddRef();
  581. *ppvObj = this;
  582. return HXR_OK;
  583. }
  584. *ppvObj = NULL;
  585. return HXR_NOINTERFACE;
  586. }
  587. /////////////////////////////////////////////////////////////////////////
  588. //      Method:
  589. //              IUnknown::AddRef
  590. //      Purpose:
  591. //              Everyone usually implements this the same... feel free to use
  592. //              this implementation.
  593. //
  594. STDMETHODIMP_(ULONG32) CAudioOutBeOS::HXPlaybackCountCb::AddRef()
  595. {
  596. return InterlockedIncrement(&m_lRefCount);
  597. }
  598. /////////////////////////////////////////////////////////////////////////
  599. //      Method:
  600. //              IUnknown::Release
  601. //      Purpose:
  602. //              Everyone usually implements this the same... feel free to use
  603. //              this implementation.
  604. //
  605. STDMETHODIMP_(ULONG32) CAudioOutBeOS::HXPlaybackCountCb::Release()
  606. {
  607. if (InterlockedDecrement(&m_lRefCount) > 0)
  608. {
  609. return m_lRefCount;
  610. }
  611. delete this;
  612. return 0;
  613. }
  614. /*
  615.  *      IHXPlaybackCountCb methods
  616.  */
  617. STDMETHODIMP CAudioOutBeOS::HXPlaybackCountCb::Func(void)
  618. {
  619. if (m_pAudioDeviceObject)
  620. {
  621. if (!m_timed)
  622. {
  623. m_pAudioDeviceObject->_Imp_Write(NULL);
  624. }
  625. else
  626. {
  627. m_pAudioDeviceObject->_Imp_Write(NULL);
  628. m_pAudioDeviceObject->m_bCallbackPending = FALSE;
  629. m_pAudioDeviceObject->DoTimeSyncs();
  630. }
  631. }
  632. return HXR_OK;
  633. }
  634. #endif