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

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2003 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. #include <e32base.h>
  36. #include <e32std.h>
  37. #include "hxassert.h"
  38. #include "hxresult.h"
  39. #include "hxslist.h"
  40. #include "hxcom.h"
  41. #include "hxausvc.h"
  42. #include "ihxpckts.h"   
  43. #include "audiosvr/audio_svr.h"
  44. #include "audiosvr/audio_svr_cntxt.h"
  45. #include "audsymbian.h"
  46. static UINT32 Scale(UINT32 v, UINT32 f0, UINT32 f1, UINT32 t0, UINT32 t1);
  47. CHXAudioDevice::CHXAudioDevice()
  48.     : CActive(EPriorityHigh),
  49.       m_lRefCount(0),
  50.       m_deviceOpen(false),
  51.       m_pWriteList(NULL),
  52.       m_pDeviceResponse(NULL),
  53.       m_pAudioStream(NULL),
  54.       m_pAudioServerContext(NULL),
  55.       m_paused(false),
  56.       m_uMinPlayerVolume(0),
  57.       m_uMaxPlayerVolume(100),
  58.       m_uMinDevVolume(0),
  59.       m_uMaxDevVolume(100)
  60. {
  61.     CActiveScheduler::Add(this);
  62. }
  63. CHXAudioDevice::~CHXAudioDevice()
  64. {
  65.     Close(TRUE); 
  66. }
  67. ULONG32 CHXAudioDevice::AddRef()
  68. {
  69.     return InterlockedIncrement(&m_lRefCount);
  70. }
  71. ULONG32 CHXAudioDevice::Release()
  72. {
  73.     if (InterlockedDecrement(&m_lRefCount) > 0)
  74.     {
  75.         return m_lRefCount;
  76.     }
  77.     delete this;
  78.     return 0;
  79. }
  80. HX_RESULT CHXAudioDevice::QueryInterface(REFIID riid, void** ppvObj)
  81. {
  82.     if (IsEqualIID(riid, IID_IHXAudioDevice))
  83.     {
  84.         AddRef();
  85.         *ppvObj = (IHXAudioDevice*)this;
  86.         return HXR_OK;
  87.     }
  88.     else if (IsEqualIID(riid, IID_IUnknown))
  89.     {
  90.         AddRef();
  91.         *ppvObj = this;
  92.         return HXR_OK;
  93.     }
  94.     *ppvObj = NULL;
  95.     return HXR_NOINTERFACE;
  96. }
  97. HX_RESULT CHXAudioDevice::Open(const HXAudioFormat* pFormat,
  98.        IHXAudioDeviceResponse* pDeviceResponse)
  99. {
  100.     HX_RESULT res = HXR_OK;
  101.     HX_ASSERT(!m_pDeviceResponse);
  102.     HX_RELEASE(m_pDeviceResponse);
  103.     if( pDeviceResponse )
  104.     {
  105.         m_pDeviceResponse = pDeviceResponse;
  106.         m_pDeviceResponse->AddRef();
  107.     }
  108.     if (NULL == (m_pWriteList = new CHXSimpleList))
  109.     {
  110. res = HXR_OUTOFMEMORY;
  111.     } 
  112.     else if (HXR_OK != OpenDevice() || HXR_OK != InitDevice(pFormat))
  113.     {
  114. res = HXR_FAIL;
  115.     }
  116.     return res;
  117. }
  118. HX_RESULT CHXAudioDevice::Close(const BOOL bFlush)
  119. {
  120.     Reset();
  121.     if (m_pAudioStream)
  122.     {
  123. m_pAudioStream->Close();
  124. m_pAudioServerContext->Stop();
  125. m_deviceOpen = false;
  126. HX_DELETE(m_pAudioStream);
  127. HX_DELETE(m_pAudioServerContext);
  128. HX_DELETE(m_pWriteList);
  129. HX_RELEASE(m_pDeviceResponse);
  130.     }
  131.     return HXR_OK;
  132. }
  133. HX_RESULT CHXAudioDevice::Write(const HXAudioData* pAudioData)
  134. {
  135.     HX_RESULT res = HXR_OK;
  136.     if (pAudioData)
  137.     {
  138. // add the buffer to the pending write list
  139. IHXBuffer* pAudioBuf = pAudioData->pData;
  140. pAudioBuf->AddRef();
  141. LISTPOSITION listRet = m_pWriteList->AddTail(pAudioBuf);
  142.         if( listRet == NULL )
  143.         {
  144.             HX_RELEASE(pAudioBuf);
  145.             res = HXR_OUTOFMEMORY;
  146.         }
  147. // if we are not waiting for a write to complete, 
  148. // write the next pending buffer
  149. if (!IsActive() && !m_paused && res == HXR_OK)
  150. {
  151.     IHXBuffer* pWriteBuf = (IHXBuffer*)m_pWriteList->GetHead();
  152.     if (pWriteBuf)
  153.     {
  154. res = WriteToDevice(pWriteBuf);
  155.     }
  156. }
  157.     }
  158.     return res;
  159. }
  160. HX_RESULT CHXAudioDevice::Reset()
  161. {
  162.     if (m_pAudioStream)
  163.     {
  164. if (!m_pAudioStream->Stopped())
  165. {
  166.     m_pAudioStream->Stop();
  167. }
  168.     }
  169.     
  170.     if (IsActive())
  171.     {
  172. Cancel();
  173.     }
  174.     if (m_pWriteList)
  175.     {
  176. while(!m_pWriteList->IsEmpty())
  177. {
  178.     IHXBuffer* pBuf = (IHXBuffer*)m_pWriteList->RemoveHead();
  179.     HX_RELEASE(pBuf);
  180. }
  181.     }
  182.     return HXR_OK;
  183. }
  184. HX_RESULT CHXAudioDevice::Drain()
  185. {
  186.     HX_ASSERT("Not implemented"==NULL);
  187.     return HXR_FAIL;
  188. }
  189. HX_RESULT CHXAudioDevice::SetVolume( const UINT16 uVolume )
  190. {
  191.     HX_RESULT res = HXR_FAIL;
  192.     
  193.     if( m_pAudioStream )
  194.     {
  195.         m_pAudioStream->SetVolume(TInt(Scale(UINT32(uVolume), 
  196.      m_uMinPlayerVolume, m_uMaxPlayerVolume,
  197.      m_uMinDevVolume, m_uMaxDevVolume)));
  198.         res = HXR_OK;
  199.     }
  200.     return res;
  201. }
  202. HX_RESULT CHXAudioDevice::GetCurrentAudioTime( ULONG32& ulCurrentTime )
  203. {
  204.     HX_RESULT res = HXR_FAIL;
  205.     
  206.     HX_ASSERT(m_pAudioStream);
  207.     if( m_pAudioStream )
  208.     {
  209. ulCurrentTime = m_pAudioStream->GetTime();
  210. res = HXR_OK;
  211.     }
  212.     
  213.     return res;
  214. }
  215. BOOL CHXAudioDevice::SupportsVolume()
  216. {
  217.     return TRUE;
  218. }
  219. UINT16 CHXAudioDevice::GetVolume()
  220. {
  221.     UINT16 vol = 0;
  222.     if (m_pAudioStream)
  223.     {
  224.         vol = UINT16(Scale(UINT32(m_pAudioStream->GetVolume()),
  225.    m_uMinDevVolume, m_uMaxDevVolume,
  226.    m_uMinPlayerVolume, m_uMaxPlayerVolume));
  227.     }
  228.     return vol;
  229. }
  230. short CHXAudioDevice::GetAudioFd( void )
  231. {
  232.     //We don't have file descriptors on symbian for the
  233.     //audio device.
  234.     return 0;
  235. }
  236. HX_RESULT CHXAudioDevice::Seek(ULONG32 ulSeekTime)
  237. {
  238.     HX_ASSERT( "Not implemented"==NULL);
  239.     return HXR_OK;
  240. }
  241. HX_RESULT CHXAudioDevice::Resume()
  242. {
  243.     m_paused = false;
  244.     if (m_pAudioStream)
  245.     {
  246. m_pAudioStream->Play();
  247.     }
  248.     // write the next buffer on the pending write list
  249.     if (!IsActive() && !m_pWriteList->IsEmpty())
  250.     {
  251. IHXBuffer* pWriteBuf = (IHXBuffer*)m_pWriteList->GetHead();
  252. if (pWriteBuf)
  253. {
  254.     WriteToDevice(pWriteBuf);
  255. }
  256.     }
  257.     
  258.     return HXR_OK;
  259. }
  260. HX_RESULT CHXAudioDevice::Pause()
  261. {
  262.     HX_RESULT res = HXR_OK;
  263.     m_paused = true;
  264.     if (m_pAudioStream)
  265.     {
  266. m_pAudioStream->Pause();
  267.     }
  268.     return res;
  269. }
  270. HX_RESULT CHXAudioDevice::CheckFormat(const HXAudioFormat* pFormat)
  271. {
  272.     HX_RESULT res = HXR_FAIL;
  273.     //Symbian only supports 16-bit PCM.
  274.     if (pFormat->uBitsPerSample == 16 &&
  275. HXR_OK == OpenDevice() &&
  276. HXR_OK == InitDevice(pFormat))
  277.     {
  278.         res = HXR_OK;
  279.     }
  280.     return res;
  281. }
  282. UINT16 CHXAudioDevice::NumberOfBlocksRemainingToPlay(void)
  283. {
  284.     return (UINT16)(m_pWriteList->GetCount() + 
  285.                     m_pAudioStream->GetBlocksBuffered());
  286. }
  287. BOOL CHXAudioDevice::InitVolume(const UINT16 uMinVolume,
  288. const UINT16 uMaxVolume )
  289. {
  290.     HX_ASSERT(m_uMaxPlayerVolume > m_uMinPlayerVolume);
  291.     
  292.     if (m_uMaxPlayerVolume > m_uMinPlayerVolume)
  293.     {
  294. m_uMinPlayerVolume = uMinVolume;
  295. m_uMaxPlayerVolume = uMaxVolume;
  296.     }
  297.     return (m_uMaxPlayerVolume > m_uMinPlayerVolume) && SupportsVolume();
  298. }
  299. //
  300. // CActive methods
  301. //
  302. void CHXAudioDevice::RunL()
  303. {
  304.     if (iStatus != KErrCancel)
  305.     {
  306. // the buffer at the head of the list is the one we just wrote
  307. // remove it from the list and release it
  308. if (!m_pWriteList->IsEmpty())
  309. {
  310.     IHXBuffer* m_pHeadBuf = (IHXBuffer*)m_pWriteList->RemoveHead();
  311.     HX_ASSERT(m_pHeadBuf);
  312.     HX_RELEASE(m_pHeadBuf);
  313. }
  314. // write the next buffer on the pending write list
  315. if (!m_paused && !m_pWriteList->IsEmpty())
  316. {
  317.     IHXBuffer* pWriteBuf = (IHXBuffer*)m_pWriteList->GetHead();
  318.     if (pWriteBuf)
  319.     {
  320. WriteToDevice(pWriteBuf);
  321.     }
  322. }
  323. // call back the response object to update time
  324.         if (m_pDeviceResponse)
  325.         {
  326.             ULONG32 ulAudioTime = 0;
  327.             GetCurrentAudioTime(ulAudioTime);
  328.             m_pDeviceResponse->OnTimeSync(ulAudioTime);
  329.         }
  330.     }
  331. }
  332. void CHXAudioDevice::DoCancel()
  333. {
  334.     if (m_pAudioStream)
  335.     {
  336. m_pAudioStream->CancelWrite();
  337.     }
  338. }
  339. //////////////////////////////////////////////////////////////////////
  340. // private methods ///////////////////////////////////////////////////
  341. //////////////////////////////////////////////////////////////////////
  342. HX_RESULT CHXAudioDevice::OpenDevice()
  343. {
  344.     HX_RESULT res = HXR_FAIL;
  345.     if (m_deviceOpen)
  346. return HXR_OK;
  347.     if(!m_pAudioStream)
  348.     {
  349. m_pAudioStream = new HXSymbianAudioClient;
  350.     }
  351.     if (m_pAudioStream)
  352.     {
  353. // create the thread context for the audio server to run 
  354. if (!m_pAudioServerContext)
  355. {
  356.     m_pAudioServerContext = new HXSymbianAudioServerContext;
  357. }
  358. // start the audio sevrver thread
  359. if (m_pAudioServerContext && !m_pAudioServerContext->Running())
  360. {
  361.     m_pAudioServerContext->Start();
  362. }
  363. // connect to the audio server and share the session
  364. if (m_pAudioServerContext->Running() &&
  365.     KErrNone == m_pAudioStream->Connect() &&
  366.     KErrNone == m_pAudioStream->Share(RSessionBase::EAutoAttach))
  367. {
  368.     m_deviceOpen = true;
  369.     res = HXR_OK;
  370. }
  371.     }
  372.     return res;
  373. }
  374. HX_RESULT CHXAudioDevice::InitDevice(const HXAudioFormat* pFormat)
  375. {
  376.     HX_RESULT res = HXR_FAIL;
  377.     // attempt to init device with given audio format
  378.     if (m_pAudioStream &&  
  379. (KErrNone == m_pAudioStream->Init(pFormat->ulSamplesPerSec,
  380.   pFormat->uChannels)))
  381.     {
  382. // grab device volume info (first opportunity)
  383. m_uMinDevVolume = m_pAudioStream->GetMinVolume();
  384. m_uMaxDevVolume = m_pAudioStream->GetMaxVolume();
  385. res = HXR_OK;
  386.     }
  387.     return res;
  388. }
  389. HX_RESULT CHXAudioDevice::WriteToDevice(IHXBuffer* pAudioBuf )
  390. {
  391.     HX_RESULT res = HXR_FAIL;
  392.     HX_ASSERT( m_pAudioStream!=NULL );
  393.  
  394.     if (m_pAudioStream)
  395.     {
  396. // async call -- called back in RunL() on completion
  397. m_pAudioStream->Write(pAudioBuf, iStatus);
  398. SetActive();
  399. res = HXR_OK;
  400.     }
  401.     return res;
  402. }
  403. //////////////////////////////////////////////////////////////////////
  404. // convenience methods ///////////////////////////////////////////////
  405. //////////////////////////////////////////////////////////////////////
  406. UINT32 Scale(UINT32 v, UINT32 f0, UINT32 f1, UINT32 t0, UINT32 t1)
  407. {
  408.     HX_ASSERT(f1 > f0);
  409.     HX_ASSERT(t1 >= t0);
  410.     HX_ASSERT(v >= f0);
  411.     if (f1 > f0 && v > f0)
  412.     {
  413. UINT64 tr = t1 - t0;
  414. UINT64 fr = f1 - f0;
  415. UINT64 n  = v - f0;
  416. UINT64 q  = n / fr;
  417. UINT64 r  = n % fr;
  418. return t0 + INT64_TO_UINT32((q * tr + (r * tr + (fr >> 1)) / fr));
  419.     }
  420.     return 0;
  421. }