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

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. #if defined (HELIX_CONFIG_CALYPSO_AUDIO_PREF)
  36. #include <calypso/audiopreference.h>
  37. #endif
  38. #include <mda/common/audio.h>
  39. #include "hxcom.h"
  40. #include "hxslist.h"
  41. #include "hxausvc.h"
  42. #include "hxbuffer.h"
  43. #include "audio_session-mda.h"
  44. #include "hxtick.h"
  45. static const TInt KClientPriority = 69; //EMdaPriorityNormal;
  46. #if defined(HELIX_CONFIG_CALYPSO_AUDIO_PREF)
  47. static const TMdaPriorityPreference KPriorityPref = (TMdaPriorityPreference)KAudioPrefComposer; 
  48. #else
  49. static const TMdaPriorityPreference KPriorityPref = EMdaPriorityPreferenceTime;
  50. #endif // SERIES60_PLAYER
  51. const INT32 WriteBufferDepth = 10; // Number of buffers we allow in the queue before blocking the caller
  52. ////////////////////////////////////////////////////
  53. //
  54. static TInt FlagToNumber(TMdaAudioDataSettings::TAudioCaps flag)
  55. {
  56.     switch( flag )
  57.     {
  58.     case TMdaAudioDataSettings::ESampleRate8000Hz:
  59.         return 8000;
  60.     case TMdaAudioDataSettings::ESampleRate11025Hz:
  61.         return 11025;
  62.     case TMdaAudioDataSettings::ESampleRate16000Hz:
  63.         return 16000;
  64.     case TMdaAudioDataSettings::ESampleRate22050Hz:
  65.         return 22050;
  66.     case TMdaAudioDataSettings::ESampleRate32000Hz:
  67.         return 32000;
  68.     case TMdaAudioDataSettings::ESampleRate44100Hz:
  69.         return 44100;
  70.     case TMdaAudioDataSettings::ESampleRate48000Hz:
  71.         return 48000;
  72.     case TMdaAudioDataSettings::EChannelsMono:
  73.         return 1;
  74.     case TMdaAudioDataSettings::EChannelsStereo:
  75.         return 2;
  76.     default:
  77.         return 0;
  78.         break;
  79.     }
  80.     return 0;
  81. }
  82. static TMdaAudioDataSettings::TAudioCaps NumberToFlag(TInt num)
  83. {
  84.     switch(num)
  85.     {
  86.     case 1:
  87.         return  TMdaAudioDataSettings::EChannelsMono;
  88.     case 2:
  89.         return  TMdaAudioDataSettings::EChannelsStereo;
  90.     case 8000:
  91.         return  TMdaAudioDataSettings::ESampleRate8000Hz;
  92.     case 11025:
  93.         return  TMdaAudioDataSettings::ESampleRate11025Hz;
  94.     case 16000:
  95.         return  TMdaAudioDataSettings::ESampleRate16000Hz;
  96.     case 22050:
  97.         return  TMdaAudioDataSettings::ESampleRate22050Hz;
  98.     case 32000:
  99.         return  TMdaAudioDataSettings::ESampleRate32000Hz;
  100.     case 44100:
  101.         return  TMdaAudioDataSettings::ESampleRate44100Hz;
  102.     case 48000:
  103.         return  TMdaAudioDataSettings::ESampleRate48000Hz;
  104.     default:
  105.         return (TMdaAudioDataSettings::TAudioCaps)0;
  106.         break;
  107.     }
  108.     return (TMdaAudioDataSettings::TAudioCaps)0;
  109. }
  110. HXSymbianAudioTimeline::HXSymbianAudioTimeline()
  111. {
  112.     Reset(0);
  113. }
  114. HXSymbianAudioTimeline::~HXSymbianAudioTimeline()
  115. {}
  116. void HXSymbianAudioTimeline::Reset(UINT32 ulByteRate)
  117. {
  118.     m_ulByteRate = ulByteRate;
  119.     ClearWritten();
  120.     m_ulBaseSec = 0;
  121.     m_ulBaseSubSecBytes = 0;
  122.     m_ulLastGetTime = 0;
  123. }
  124. void HXSymbianAudioTimeline::OnWrite(UINT32 ulBytes)
  125. {
  126.     UINT32 ulSum = m_ulSubSecBytes + ulBytes;
  127.     UINT32 ulSec = ulSum / m_ulByteRate;
  128.     m_ulSecWritten += ulSec;
  129.     m_ulSubSecBytes = ulSum - (ulSec * m_ulByteRate);
  130. }
  131. UINT32 HXSymbianAudioTimeline::GetPlaybackTime()
  132. {
  133.     UINT32 ulBaseMs = GetMs(m_ulBaseSec, m_ulBaseSubSecBytes);
  134.     UINT32 ulWrittenMs = GetWrittenTime();
  135.     UINT32 ulRet = ulBaseMs;
  136.     UINT32 ulDeviceTimeMs = GetWallclockTime();
  137.     
  138.     // Only use the device time if it
  139.     // is less than the amount of data
  140.     // written
  141.     if (ulWrittenMs > ulDeviceTimeMs)
  142.     {
  143.         ulRet += ulDeviceTimeMs;
  144.     }
  145.     else
  146.     {
  147.         ulRet += ulWrittenMs;
  148.     }
  149.     // Enforce monotonically increasing return values
  150.     if (ulRet >= m_ulLastGetTime)
  151.     {
  152.         m_ulLastGetTime = ulRet;
  153.     }
  154.     else
  155.     {
  156.         ulRet = m_ulLastGetTime;
  157.     }
  158.     return ulRet;
  159. }
  160. UINT32 HXSymbianAudioTimeline::GetWrittenTime() const
  161. {
  162.     return GetMs(m_ulSecWritten, m_ulSubSecBytes);
  163. }
  164. UINT32 HXSymbianAudioTimeline::GetWallclockTime() const
  165. {
  166.     UINT32 ulRet = m_ulDevTimeMs;
  167.     if (m_ulDevTimeMs)
  168.     {
  169.         ulRet += HX_GET_TICKCOUNT() - m_ulWallclockTime;
  170.     }
  171.     return ulRet;
  172. }
  173. void HXSymbianAudioTimeline::OnPlay()
  174. {
  175.     ClearWritten();
  176. }
  177. void HXSymbianAudioTimeline::OnPauseOrUnderflow()
  178. {
  179.     // Add the written time to the base time
  180.     m_ulBaseSec += m_ulSecWritten;
  181.     m_ulBaseSubSecBytes += m_ulSubSecBytes;
  182.     // Normalize the base time values
  183.     while (m_ulBaseSubSecBytes >= m_ulByteRate)
  184.     {
  185.         m_ulBaseSec++;
  186.         m_ulBaseSubSecBytes -= m_ulByteRate;
  187.     }
  188.     
  189.     // Clear the bytes written state
  190.     ClearWritten();
  191. }
  192. BOOL HXSymbianAudioTimeline::NeedDeviceTime() const
  193. {
  194.     // We only want a device time if we don't haven't
  195.     // received a non-zero device time.
  196.     return (m_ulDevTimeMs == 0);
  197. }
  198. void HXSymbianAudioTimeline::SetDeviceTime(UINT32 ulDeviceTimeMs)
  199. {
  200.     if (NeedDeviceTime())
  201.     {
  202.         m_ulDevTimeMs = ulDeviceTimeMs;
  203.         m_ulWallclockTime = HX_GET_TICKCOUNT();
  204.     }
  205. }
  206. UINT32 HXSymbianAudioTimeline::GetMs(UINT32 ulSec, UINT32 ulSubSec) const
  207. {
  208.     UINT32 ulRet = ulSec * 1000;
  209.     if (m_ulByteRate)
  210.     {
  211.         ulRet += (ulSubSec * 1000) / m_ulByteRate;
  212.     }
  213.     return ulRet;
  214. }
  215. void HXSymbianAudioTimeline::ClearWritten()
  216. {
  217.     m_ulSecWritten = 0;
  218.     m_ulSubSecBytes = 0;
  219.     m_ulDevTimeMs = 0;
  220.     m_ulWallclockTime = 0;
  221. }
  222. //
  223. // class HXSymbianAudioSession:
  224. //
  225. //
  226. // HXSymbianAudioSession::ctor:
  227. //
  228. // add the session to the server
  229. //
  230. HXSymbianAudioSession::HXSymbianAudioSession(RThread& client,
  231.                                              HXSymbianAudioServer* pServer)
  232.     : CSession(client),
  233.       m_pServer(pServer),
  234.       m_pStream(0),
  235.       m_sampleRate(TMdaAudioDataSettings::ESampleRate8000Hz),
  236.       m_channels(TMdaAudioDataSettings::EChannelsMono),
  237.       m_pData(0, 0),
  238.       m_wantsNotify(false),
  239.       m_reason(KErrNone),
  240.       m_open(false),
  241.       m_writeComplete(true),
  242.       m_bPaused(TRUE),
  243.       m_bWritePending(FALSE)
  244. {
  245.     // add the session to the server
  246.     m_pServer->AddSession();
  247. }
  248. //
  249. // HXSymbianAudioSession::dtor
  250. //
  251. HXSymbianAudioSession::~HXSymbianAudioSession()
  252. {
  253.     DoCleanup();
  254. }
  255. //
  256. // HXSymbianAudioSession::NewL
  257. //
  258. // creates a new session
  259. //
  260. HXSymbianAudioSession* HXSymbianAudioSession::NewL(RThread& client,
  261.                                                    HXSymbianAudioServer* pServer)
  262. {
  263.     HXSymbianAudioSession* pSession =
  264.         new (ELeave) HXSymbianAudioSession(client, pServer);
  265.     return pSession;
  266. }
  267. //
  268. // HXSymbianAudioSession::ServiceL
  269. //
  270. // services a client message
  271. //
  272. void HXSymbianAudioSession::ServiceL(const RMessage& mesg)
  273. {
  274.     switch (mesg.Function()) 
  275.     {
  276.     case HXSymbianAudioServer::EAS_Init:
  277.         Init();
  278.         break;
  279.     case HXSymbianAudioServer::EAS_Play:
  280.         Play();
  281.         break;
  282.     case HXSymbianAudioServer::EAS_Pause:
  283.         Pause();
  284.         break;
  285.     case HXSymbianAudioServer::EAS_Write:
  286.         Write();
  287.         break;
  288.     case HXSymbianAudioServer::EAS_CancelWrite:
  289.         if (!m_writeComplete)
  290.         {
  291.             m_writeComplete = true;
  292.             m_writeMessage.Complete(KErrCancel);
  293.         }
  294.         mesg.Complete(KErrNone);
  295.         break;
  296.     case HXSymbianAudioServer::EAS_GetTime:
  297.         GetTime();
  298.         break;
  299.     case HXSymbianAudioServer::EAS_GetBlocksBuffered:
  300.         GetBlocksBuffered();
  301.         break;
  302.     case HXSymbianAudioServer::EAS_SetVolume:
  303.         SetVolume();
  304.         break;
  305.     case HXSymbianAudioServer::EAS_GetVolume:
  306.         GetVolume();
  307.         break;
  308.     case HXSymbianAudioServer::EAS_GetMaxVolume:
  309.         GetMaxVolume();
  310.         break;
  311.     case HXSymbianAudioServer::EAS_GetMinVolume:
  312.         GetMinVolume();
  313.         break;
  314.     case HXSymbianAudioServer::EAS_Stop:
  315.         Stop();
  316.         break;
  317.     case HXSymbianAudioServer::EAS_RequestDeviceTakenNotification:
  318.         RequestDeviceTakenNotification();
  319.         break;
  320.     case HXSymbianAudioServer::EAS_CancelDeviceTakenNotification:
  321.         CancelDeviceTakenNotification();
  322.         break;
  323.     default:
  324.         mesg.Complete(KErrNotSupported);
  325.         break;
  326.     }
  327. }
  328. //
  329. // HXSymbianAudioSession::Init
  330. //
  331. // 1. Matches input sample rate to output sample rate
  332. //    by building a sample rate converter, if necessary.
  333. // 2. Opens and initializes the audio device.
  334. //
  335. void HXSymbianAudioSession::Init()
  336. {
  337.     TInt err = KErrNone;
  338.     // translate the audio props to flags needed by interface
  339.     m_sampleRate = NumberToFlag(Message().Int0());
  340.     m_channels   = NumberToFlag(Message().Int1());
  341.     m_timeline.Reset(GetByteRate());
  342.     m_bPaused = TRUE;
  343.     if (m_open)
  344.     {
  345.         TRAP(err, m_pStream->SetAudioPropertiesL(m_sampleRate,
  346.                                                  m_channels));
  347.         Message().Complete(err);
  348.     }
  349.     else 
  350.     {
  351.         TRAP(err, (m_pStream = CMdaAudioOutputStream::NewL(*this)));
  352.         if(KErrNone == err)
  353.         {
  354.             // open the audio device
  355.             m_settings.iSampleRate = m_sampleRate;
  356.             m_settings.iChannels = m_channels;
  357.             m_settings.iVolume = m_pStream->MaxVolume()/2;
  358.             m_settings.iFlags = 0;
  359.             m_pStream->Open(&m_settings);
  360.         }
  361.         else
  362.         {
  363.             Message().Complete(err);
  364.         }
  365.     }
  366. }
  367. void HXSymbianAudioSession::DoCleanup()
  368. {
  369.     while(!m_bufferList.IsEmpty())
  370.     {
  371.         IHXBuffer* pBuf = (IHXBuffer*)m_bufferList.RemoveHead();
  372.         HX_RELEASE(pBuf);
  373.     }
  374.     if (m_wantsNotify)
  375.     {
  376.         m_notifyRequest.Complete(KErrCancel);
  377.         m_wantsNotify = false;
  378.     }
  379.     if (m_pStream)
  380.     {
  381.         m_pStream->Stop();
  382.         delete m_pStream;
  383.         m_pStream = 0;
  384.         m_open = false;
  385.     }
  386.     // remove session from server
  387.     if( m_pServer)
  388.     {
  389.         m_pServer->DelSession();
  390.         m_pServer = 0;
  391.     }
  392. }
  393. //
  394. // HXSymbianAudioSession::Play
  395. //
  396. void HXSymbianAudioSession::Play()
  397. {
  398.     if (m_reason != KErrNone)
  399.         m_reason = KErrNone;
  400.     // reset audio properties in case they changed on us
  401.     TRAPD(error, m_pStream->SetAudioPropertiesL(m_sampleRate,
  402.                                                 m_channels));
  403.     m_pStream->SetPriority(KClientPriority, KPriorityPref);
  404.     m_timeline.OnPlay();
  405.     m_bPaused = FALSE;
  406.     if (ReadyToWrite())
  407.     {
  408.         error = WriteNextBuffer();
  409.     }
  410.     Message().Complete(error);
  411. }
  412. //
  413. // HXSymbianAudioSession::Pause
  414. //
  415. void HXSymbianAudioSession::Pause()
  416. {
  417.     m_timeline.OnPauseOrUnderflow();
  418.     m_bPaused = TRUE;
  419.     if (m_pStream)
  420.     {
  421.         m_pStream->Stop();
  422.     }
  423.     Message().Complete(KErrNone);
  424. }
  425. //
  426. // HXSymbianAudioSession::Write
  427. //
  428. //
  429. void HXSymbianAudioSession::Write()
  430. {
  431.     TInt result = KErrArgument;
  432.     IHXBuffer* pAudioBuf = (IHXBuffer*)Message().Ptr0();
  433.     if (pAudioBuf)
  434.     {
  435.         if (m_bufferList.AddTail(pAudioBuf))
  436.         {
  437.             pAudioBuf->AddRef();
  438.             if (ReadyToWrite())
  439.             {
  440.                 result = WriteNextBuffer();
  441.                 if (KErrNone != result)
  442.                 {
  443.                     // Remove the buffer we just appended
  444.                     // to the list
  445.                     m_bufferList.RemoveTail();
  446.                     // Release our reference to the buffer
  447.                     HX_RELEASE(pAudioBuf);
  448.                 }
  449.             }
  450.             else
  451.             {
  452.                 result = KErrNone;
  453.             }
  454.         }
  455.         else
  456.         {
  457.             result = KErrNoMemory;
  458.         }
  459.         
  460.     }
  461.     if( m_bufferList.GetCount() < WriteBufferDepth ||
  462.         KErrNone != result )
  463.     {
  464.         //We have slots free and no errors so we can complete the
  465.         //message.
  466.         m_writeComplete = true;
  467.         Message().Complete(result);
  468.     }
  469.     else
  470.     {
  471.         // We need to delay notifying the caller until the current
  472.         // write completes
  473.         m_writeComplete = false;
  474.         m_writeMessage = Message();
  475.     }
  476.     
  477. }
  478. //
  479. // HXSymbianAudioSession::GetTime
  480. //
  481. // Return the current playback position -- converts from
  482. // microseconds to milliseconds
  483. //
  484. void HXSymbianAudioSession::GetTime()
  485. {
  486.     Message().Complete(m_timeline.GetPlaybackTime());
  487. }
  488. //
  489. // HXSymbianAudioSession::GetBlocksBuffered
  490. //
  491. // Return the number of blocks buffered by this object.
  492. //
  493. void HXSymbianAudioSession::GetBlocksBuffered()
  494. {
  495.     Message().Complete(m_bufferList.GetCount());
  496. }
  497. //
  498. // HXSymbianAudioSession::SetVolume
  499. //
  500. // set the volume -- convert from 0-100 to 0-max range
  501. //
  502. void HXSymbianAudioSession::SetVolume()
  503. {
  504.     if (m_pStream)
  505.     {
  506.         m_pStream->SetVolume(Message().Int0());
  507.     }
  508.     Message().Complete(0);
  509. }
  510. //
  511. // HXSymbianAudioSession::GetVolume
  512. //
  513. // get the current volume normalized to 0-100 range
  514. //
  515. void HXSymbianAudioSession::GetVolume()
  516. {
  517.     TInt vol = 0;
  518.     if (m_pStream)
  519.     {
  520.         vol = m_pStream->Volume();
  521.     }
  522.     Message().Complete(vol);
  523. }
  524. //
  525. // HXSymbianAudioSession::GetMaxVolume
  526. //
  527. // get the maxium device volume
  528. //
  529. void HXSymbianAudioSession::GetMaxVolume()
  530. {
  531.     TInt maxVol = 0;
  532.     if (m_pStream)
  533.     {
  534.         maxVol = m_pStream->MaxVolume();
  535.     }
  536.     Message().Complete(maxVol);
  537. }
  538. //
  539. // HXSymbianAudioSession::GetMinVolume
  540. //
  541. // get the minimum device volume
  542. //
  543. void HXSymbianAudioSession::GetMinVolume()
  544. {
  545.     Message().Complete(0);
  546. }
  547. //
  548. // HXSymbianAudioSession::Stop
  549. //
  550. // stop playback
  551. //
  552. void HXSymbianAudioSession::Stop()
  553. {
  554.     m_bPaused = TRUE;
  555.     if(m_pStream)
  556.     {
  557.         m_pStream->Stop();
  558.     }
  559.     
  560.     // Cleanup any remaining buffers
  561.     while(!m_bufferList.IsEmpty())
  562.     {
  563.         IHXBuffer* pBuf = (IHXBuffer*)m_bufferList.RemoveHead();
  564.         HX_RELEASE(pBuf);
  565.     }
  566.     m_timeline.Reset(GetByteRate());
  567.     Message().Complete(KErrNone);
  568. }
  569. void
  570. HXSymbianAudioSession::RequestDeviceTakenNotification()
  571. {
  572.     m_wantsNotify = true;
  573.     m_notifyRequest = Message();
  574. }
  575. void
  576. HXSymbianAudioSession::CancelDeviceTakenNotification()
  577. {
  578.     if (m_wantsNotify)
  579.     {
  580.         m_notifyRequest.Complete(KErrCancel);
  581.         m_wantsNotify = false;
  582.     }
  583. }
  584. //
  585. // HXSymbianAudioSession::NotifyDeviceTaken
  586. //
  587. // notify the client that the audio device has been taken if a
  588. // notification requrest has been made 
  589. //
  590. void HXSymbianAudioSession::NotifyDeviceTaken()
  591. {
  592.     if (m_wantsNotify)
  593.     {
  594.         m_notifyRequest.Complete(m_reason);
  595.         m_wantsNotify = false;
  596.     }
  597. }
  598. //
  599. // callbacks
  600. //
  601. void HXSymbianAudioSession::MaoscOpenComplete(TInt error)
  602. {
  603.     if (error == KErrNone)
  604.     {
  605.         m_open = true;
  606.         TRAP(error, m_pStream->SetAudioPropertiesL(m_sampleRate,
  607.                                                    m_channels));
  608.         m_pStream->SetPriority(KClientPriority, KPriorityPref);
  609.     }
  610.     Message().Complete(error);
  611. }
  612. void HXSymbianAudioSession::MaoscBufferCopied(TInt error, const TDesC8& buf)
  613. {
  614.     m_bWritePending = FALSE;
  615.     // Check to see if we need a device time
  616.     if (m_timeline.NeedDeviceTime())
  617.     {
  618.         m_timeline.SetDeviceTime(GetDeviceMs());
  619.     }
  620.     if (!m_bufferList.IsEmpty())
  621.     {
  622.         // We should always enter here because the
  623.         // last buffer written is at the head of the list.
  624.         // We want to remove this buffer from the list since
  625.         // this call is the completion of last WriteL() call.
  626.         IHXBuffer* pBuf = (IHXBuffer*)m_bufferList.RemoveHead();
  627.         HX_RELEASE(pBuf);
  628.     }
  629.     if (ReadyToWrite())
  630.     {
  631.         error = WriteNextBuffer();
  632.     }
  633.     if( !m_writeComplete &&
  634.         (m_bufferList.GetCount() < WriteBufferDepth))
  635.     {
  636.         m_writeComplete = true;
  637.         m_writeMessage.Complete(error);
  638.     }
  639.     
  640. }
  641. void HXSymbianAudioSession::MaoscPlayComplete(TInt error)
  642. {
  643.     if (KErrUnderflow == error)
  644.     {
  645.         m_timeline.OnPauseOrUnderflow();
  646.     }
  647.     //If the media server is stopping for any reason make sure we
  648.     //honor any outstanding completes.
  649.     if( !m_writeComplete )
  650.     {
  651.         m_writeComplete = true;
  652.         m_writeMessage.Complete(error);
  653.     }
  654.     int resetErr;
  655.     TRAP(resetErr, m_pStream->SetAudioPropertiesL(m_sampleRate,
  656.                                                   m_channels));
  657.     m_pStream->SetPriority(KClientPriority, KPriorityPref);
  658.     if (error == KErrAbort)
  659.     {
  660.         m_reason = error;
  661.         m_pServer->NotifyDeviceTaken();
  662.     }
  663. }
  664. UINT32 HXSymbianAudioSession::GetByteRate() const
  665. {
  666.     return 2 * FlagToNumber(m_sampleRate) * FlagToNumber(m_channels);
  667. }
  668. UINT32 HXSymbianAudioSession::GetDeviceMs()
  669. {
  670.     UINT32 ulRet = 0;
  671.     if (m_pStream)
  672.     {
  673.         TTimeIntervalMicroSeconds pos = m_pStream->Position();
  674.         TInt64 millisecs = pos.Int64() / 1000;
  675.    
  676.         ulRet = millisecs.Low();
  677.     }
  678.     return ulRet;
  679. }
  680. BOOL HXSymbianAudioSession::ReadyToWrite() const
  681. {
  682.     return !m_bWritePending && !m_bPaused && !m_bufferList.IsEmpty();
  683. }
  684. TInt HXSymbianAudioSession::WriteNextBuffer()
  685. {
  686.     // Write the next buffer in the list
  687.     IHXBuffer* pBuffer = (IHXBuffer*)m_bufferList.GetHead();
  688.     TInt result = KErrNone;
  689.     if (pBuffer)
  690.     {
  691.         if( m_pStream )
  692.         {
  693.             int len = pBuffer->GetSize();
  694.             m_pData.Set((TUint8*)pBuffer->GetBuffer(), len, len);
  695.             TRAP(result, m_pStream->WriteL(m_pData));
  696.         }
  697.         else
  698.         {
  699.             // oom earlier?
  700.             result = KErrNotReady;
  701.         }
  702.     }
  703.     if (KErrNone == result)
  704.     {
  705.         m_timeline.OnWrite(pBuffer->GetSize());
  706.         m_bWritePending = TRUE;
  707.     }
  708.     else
  709.     {
  710.         m_bWritePending = FALSE;
  711.     }
  712.     return result;
  713. }