audio_session-mmf.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:16k
源码类别:
Symbian
开发平台:
Visual C++
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: audio_session-mmf.cpp,v 1.1.2.2 2004/07/09 02:01:33 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #if defined (HELIX_CONFIG_CALYPSO_AUDIO_PREF)
- #include <calypso/audiopreference.h>
- #endif
- #include "hxcom.h"
- #include "hxslist.h"
- #include "hxausvc.h"
- #include "hxbuffer.h"
- #include "audio_session-mmf.h"
- #include "hxtick.h"
- #include <e32std.h>
- static const TInt KClientPriority = 69;
- #if defined(HELIX_CONFIG_CALYPSO_AUDIO_PREF)
- static const TMdaPriorityPreference KPriorityPref = (TMdaPriorityPreference)KAudioPrefComposer;
- #else
- static const TMdaPriorityPreference KPriorityPref = (TMdaPriorityPreference)80; //EMdaPriorityPreferenceTime;
- #endif // SERIES60_PLAYER
- const INT32 WriteBufferDepth = 10; // Number of buffers we allow in the queue before blocking the caller
- static TInt FlagToNumber(TMMFSampleRate flag)
- {
- switch( flag )
- {
- case EMMFSampleRate8000Hz:
- return 8000;
- case EMMFSampleRate11025Hz:
- return 11025;
- case EMMFSampleRate16000Hz:
- return 16000;
- case EMMFSampleRate22050Hz:
- return 22050;
- case EMMFSampleRate32000Hz:
- return 32000;
- case EMMFSampleRate44100Hz:
- return 44100;
- case EMMFSampleRate48000Hz:
- return 48000;
- default:
- return 0;
- break;
- }
- return 0;
- }
- static TMMFSampleRate NumberToFlag(TInt num)
- {
- switch(num)
- {
- case 8000:
- return EMMFSampleRate8000Hz;
- case 11025:
- return EMMFSampleRate11025Hz;
- case 16000:
- return EMMFSampleRate16000Hz;
- case 22050:
- return EMMFSampleRate22050Hz;
- case 32000:
- return EMMFSampleRate32000Hz;
- case 44100:
- return EMMFSampleRate44100Hz;
- case 48000:
- return EMMFSampleRate48000Hz;
- default:
- HX_ASSERT(NULL=="Invalid sample rate flag");
- break;
- }
- return EMMFSampleRate16000Hz;
- }
- HXSymbianAudioSession::HXSymbianAudioSession(RThread& client,
- HXSymbianAudioServer* pServer)
- : CSession(client),
- m_pServer(pServer),
- m_wantsNotify(false),
- m_reason(KErrNone),
- m_open(false),
- m_bPaused(FALSE),
- m_pStream(NULL),
- m_pData(NULL),
- m_bBufferNeedsFilling(false),
- m_bPlayInited(FALSE),
- m_uSampleRate(0),
- m_ulPauseTime(0),
- m_ulStartTime(0),
- m_nLastSampleCount(0),
- m_nUnderflowSampleCount(0)
- {
- // add the session to the server
- m_pServer->AddSession();
- memset(&m_Settings, 0, sizeof( m_Settings) );
- }
- //
- // HXSymbianAudioSession::dtor
- //
- HXSymbianAudioSession::~HXSymbianAudioSession()
- {
- DoCleanup();
- }
- //
- // HXSymbianAudioSession::NewL
- //
- // creates a new session
- //
- HXSymbianAudioSession* HXSymbianAudioSession::NewL(RThread& client,
- HXSymbianAudioServer* pServer)
- {
- HXSymbianAudioSession* pSession =
- new (ELeave) HXSymbianAudioSession(client, pServer);
- return pSession;
- }
- //
- // HXSymbianAudioSession::ServiceL
- //
- // services a client message
- //
- void HXSymbianAudioSession::ServiceL(const RMessage& mesg)
- {
- switch (mesg.Function())
- {
- case HXSymbianAudioServer::EAS_Init:
- Init();
- break;
- case HXSymbianAudioServer::EAS_Play:
- Play();
- break;
- case HXSymbianAudioServer::EAS_Pause:
- Pause();
- break;
- case HXSymbianAudioServer::EAS_Write:
- Write();
- break;
- case HXSymbianAudioServer::EAS_CancelWrite:
- mesg.Complete(KErrNone);
- break;
- case HXSymbianAudioServer::EAS_GetTime:
- GetTime();
- break;
- case HXSymbianAudioServer::EAS_GetBlocksBuffered:
- GetBlocksBuffered();
- break;
- case HXSymbianAudioServer::EAS_SetVolume:
- SetVolume();
- break;
- case HXSymbianAudioServer::EAS_GetVolume:
- GetVolume();
- break;
- case HXSymbianAudioServer::EAS_GetMaxVolume:
- GetMaxVolume();
- break;
- case HXSymbianAudioServer::EAS_GetMinVolume:
- GetMinVolume();
- break;
- case HXSymbianAudioServer::EAS_Stop:
- Stop();
- break;
- case HXSymbianAudioServer::EAS_RequestDeviceTakenNotification:
- RequestDeviceTakenNotification();
- break;
- case HXSymbianAudioServer::EAS_CancelDeviceTakenNotification:
- CancelDeviceTakenNotification();
- break;
- default:
- mesg.Complete(KErrNotSupported);
- break;
- }
- }
- //
- // HXSymbianAudioSession::Init
- //
- // 1. Matches input sample rate to output sample rate
- // by building a sample rate converter, if necessary.
- // 2. Opens and initializes the audio device.
- //
- void HXSymbianAudioSession::Init()
- {
- TInt err = KErrNone;
- // translate the audio props to flags needed by interface
- m_Settings.iRate = NumberToFlag(Message().Int0());
- m_Settings.iChannels = Message().Int1();
- m_Settings.iEncoding = EMMFSoundEncoding16BitPCM; //We always do 16bit.
- m_uSampleRate = Message().Int0();
- if (m_open)
- {
- TRAP(err, (m_pStream->CMMFDevSound::SetConfigL(m_Settings)));
- Message().Complete(err);
- }
- else
- {
- TRAP(err, (m_pStream = CMMFDevSound::NewL()));
- if(KErrNone == err)
- {
- m_InitMessage = Message();
- TRAP(err, (m_pStream->InitializeL(*this, EMMFStatePlaying)));
- }
- if( KErrNone != err )
- {
- Message().Complete(err);
- }
- }
- m_bPlayInited = FALSE;
- }
- void HXSymbianAudioSession::DoCleanup()
- {
- while(!m_bufferList.IsEmpty())
- {
- IHXBuffer* pBuf = (IHXBuffer*)m_bufferList.RemoveHead();
- HX_RELEASE(pBuf);
- }
- if (m_wantsNotify)
- {
- m_notifyRequest.Complete(KErrCancel);
- m_wantsNotify = false;
- }
- if (m_pStream)
- {
- m_pStream->Stop();
- delete m_pStream;
- m_pStream = 0;
- m_open = false;
- m_pData= NULL;
- }
- // remove session from server
- if( m_pServer)
- {
- m_pServer->DelSession();
- m_pServer = 0;
- }
- }
- //
- // HXSymbianAudioSession::Play
- //
- void HXSymbianAudioSession::Play()
- {
- TInt err = KErrNone;
- m_reason = KErrNone;
- m_ulStartTime = HX_GET_TICKCOUNT();
- if( m_pData )
- {
- m_pStream->PlayData();
- }
- if(!m_bPlayInited)
- {
- //Set priority.
- TMMFPrioritySettings prioritySettings;
- prioritySettings.iPref = KPriorityPref;
- prioritySettings.iPriority = KClientPriority;
- m_pStream->SetPrioritySettings(prioritySettings);
- TRAP(err, m_pStream->PlayInitL());
- m_bPlayInited = TRUE;
- }
- m_bPaused = FALSE;
- Message().Complete(err);
- }
- //
- // HXSymbianAudioSession::Pause
- //
- void HXSymbianAudioSession::Pause()
- {
- m_bPaused = TRUE;
- if( m_ulStartTime )
- m_ulPauseTime += HX_GET_TICKCOUNT()-m_ulStartTime;
- m_ulStartTime = 0;
- //Only pause the stream if we have actually started to play.
- if (m_pStream && m_pData)
- {
- m_pStream->Pause();
- }
- Message().Complete(KErrNone);
- }
- //
- // HXSymbianAudioSession::Write
- //
- //
- void HXSymbianAudioSession::Write()
- {
- TInt result = KErrArgument;
- TInt err = KErrNone;
- IHXBuffer* pAudioBuf = (IHXBuffer*)Message().Ptr0();
- if (pAudioBuf)
- {
- if (m_bufferList.AddTail(pAudioBuf))
- {
- result = KErrNone;
- }
- else
- {
- result = KErrNoMemory;
- }
- }
- Message().Complete(result);
- if( m_bBufferNeedsFilling && m_pData )
- {
- BufferToBeFilled(m_pData);
- m_bBufferNeedsFilling = false;
- }
- }
- //
- // HXSymbianAudioSession::GetTime
- //
- // Return the current playback position -- converts from
- // microseconds to milliseconds
- //
- void HXSymbianAudioSession::GetTime()
- {
- TInt nMSTime = 0;
- TInt nSamples = m_pStream->SamplesPlayed();
- nMSTime = (nSamples+m_nUnderflowSampleCount)*1000/m_uSampleRate;
- // if(m_ulStartTime)
- // nMSTime = HX_GET_TICKCOUNT()-m_ulStartTime;
- // nMSTime += m_ulPauseTime;
- Message().Complete(nMSTime);
- }
- //
- // HXSymbianAudioSession::GetBlocksBuffered
- //
- // Return the number of blocks buffered by this object.
- //
- void HXSymbianAudioSession::GetBlocksBuffered()
- {
- TInt nTmp = m_bufferList.GetCount();
- Message().Complete(nTmp);
- }
- //
- // HXSymbianAudioSession::SetVolume
- //
- // set the volume -- convert from 0-100 to 0-max range
- //
- void HXSymbianAudioSession::SetVolume()
- {
- if (m_pStream)
- {
- m_pStream->SetVolume(Message().Int0());
- }
- Message().Complete(0);
- }
- //
- // HXSymbianAudioSession::GetVolume
- //
- // get the current volume normalized to 0-100 range
- //
- void HXSymbianAudioSession::GetVolume()
- {
- TInt vol = 0;
- if (m_pStream)
- {
- vol = m_pStream->Volume();
- }
- Message().Complete(vol);
- }
- //
- // HXSymbianAudioSession::GetMaxVolume
- //
- // get the maxium device volume
- //
- void HXSymbianAudioSession::GetMaxVolume()
- {
- TInt maxVol = 0;
- if (m_pStream)
- {
- maxVol = m_pStream->MaxVolume();
- }
- Message().Complete(maxVol);
- }
- //
- // HXSymbianAudioSession::GetMinVolume
- //
- // get the minimum device volume
- //
- void HXSymbianAudioSession::GetMinVolume()
- {
- Message().Complete(0);
- }
- //
- // HXSymbianAudioSession::Stop
- //
- // stop playback
- //
- void HXSymbianAudioSession::Stop()
- {
- m_bPlayInited = FALSE;
- m_ulStartTime = 0;
- m_ulPauseTime = 0;
- m_nUnderflowSampleCount = 0;
- m_nLastSampleCount = 0;
- if(m_pStream)
- {
- m_pStream->Stop();
- m_pData = NULL;
- }
- // Cleanup any remaining buffers
- while(!m_bufferList.IsEmpty())
- {
- IHXBuffer* pBuf = (IHXBuffer*)m_bufferList.RemoveHead();
- HX_RELEASE(pBuf);
- }
- Message().Complete(KErrNone);
- }
- void
- HXSymbianAudioSession::RequestDeviceTakenNotification()
- {
- m_wantsNotify = true;
- m_notifyRequest = Message();
- }
- void
- HXSymbianAudioSession::CancelDeviceTakenNotification()
- {
- if (m_wantsNotify)
- {
- m_notifyRequest.Complete(KErrCancel);
- m_wantsNotify = false;
- }
- }
- //
- // HXSymbianAudioSession::NotifyDeviceTaken
- //
- // notify the client that the audio device has been taken if a
- // notification requrest has been made
- //
- void HXSymbianAudioSession::NotifyDeviceTaken()
- {
- if (m_wantsNotify)
- {
- m_notifyRequest.Complete(m_reason);
- m_wantsNotify = false;
- }
- }
- //
- // callbacks
- //
- //MDevSoundObserver callbacks
- void HXSymbianAudioSession::InitializeComplete(TInt aError)
- {
- TInt err = KErrNone;
- TRAP(err, (m_pStream->CMMFDevSound::SetConfigL(m_Settings)));
- if( KErrNone == err )
- {
- m_open = true;
- }
- m_InitMessage.Complete(err);
- }
- void HXSymbianAudioSession::BufferToBeFilled(CMMFBuffer* aBuffer)
- {
- TInt err = KErrUnderflow;
- m_pData = aBuffer;
- m_nLastSampleCount = m_pStream->SamplesPlayed();
- if( aBuffer )
- {
- //Called whenever the media server needs more data to play.
- if( !m_bufferList.IsEmpty())
- {
- TDes8& dataDesc = ((CMMFDataBuffer*)aBuffer)->Data();
- int nRequestSize = aBuffer->RequestSize();
- int nTotalWritten = 0;
- //Clear out the descriptor.
- dataDesc = TPtrC8(NULL, 0 );
- while( !m_bufferList.IsEmpty() )
- {
- //Fill up as much as we can.
- IHXBuffer* pBuffer = (IHXBuffer*)m_bufferList.GetHead();
- int len = pBuffer->GetSize();
- if( nTotalWritten+len < nRequestSize )
- {
- TPtrC8 desc((TUint8*)pBuffer->GetBuffer(), len);
- dataDesc.Append(desc);
- IHXBuffer* pTmp = (IHXBuffer*)m_bufferList.RemoveHead();
- HX_RELEASE(pTmp);
- }
- else
- {
- break;
- }
- nTotalWritten += len;
- //XXXGfw break here is intentional. I don't want to do
- //combined writes right now.
- break;
- }
- m_pStream->PlayData();
- }
- else
- {
- m_bBufferNeedsFilling = true;
- }
- }
- }
- void HXSymbianAudioSession::PlayError(TInt aError)
- {
- TInt err = KErrNone;
- m_reason = aError;
- m_pData = NULL;
- switch(aError)
- {
- case KErrUnderflow:
- //HX_ASSERT(NULL=="Underflow.");
- TMMFPrioritySettings prioritySettings;
- prioritySettings.iPref = KPriorityPref;
- prioritySettings.iPriority = KClientPriority;
- m_pStream->SetPrioritySettings(prioritySettings);
- TRAP(err, m_pStream->PlayInitL());
- m_bPlayInited = TRUE;
- m_nUnderflowSampleCount += m_nLastSampleCount;
- break;
- case KErrAccessDenied:
- NotifyDeviceTaken();
- break;
- case KErrCancel:
- HX_ASSERT(NULL=="PlayError -- KErrCancel");
- break;
- case KErrInUse:
- NotifyDeviceTaken();
- break;
- default:
- HX_ASSERT(NULL=="unknown error");
- break;
- }
- }
- //These are never used in PCM playback, just recording or converting.
- void HXSymbianAudioSession::ToneFinished(TInt aError) {}
- void HXSymbianAudioSession::RecordError(TInt aError) {}
- void HXSymbianAudioSession::ConvertError(TInt aError) {}
- void HXSymbianAudioSession::BufferToBeEmptied(CMMFBuffer* aBuffer) {}
- void HXSymbianAudioSession::DeviceMessage(TUid aMessageType, const TDesC8& aMsg) {}
- void HXSymbianAudioSession::SendEventToClient(const TMMFEvent& aEvent) {}