audbeos.cpp
Upload User: dangjiwu
Upload Date: 2013-07-19
Package Size: 42019k
Code Size: 19k
Category:

Symbian

Development Platform:

Visual C++

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