diff -r 6c158198356e -r ae942d28ec0e javauis/mmapi_qt/baseline/src/cmmaaudioplayer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/mmapi_qt/baseline/src/cmmaaudioplayer.cpp Tue Aug 31 15:09:22 2010 +0300 @@ -0,0 +1,326 @@ +/* +* Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: This class is used for playing sounds +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include "cmmaaudioplayer.h" + +const TInt KPlayerPriority = KAudioPriorityRecording; +const TInt KErrorMessageSize = 32; + +const TUid KSourceUid = { KMmfUidDescriptorSource }; +const TUid KFileSourceUid = { KMmfUidFileSource }; +_LIT(KErrDefaultError, "Symbian OS Error: %d"); + +const TInt KMinIntervalBeforePrime = 0; + +CPlaybackCompletedCallback* CPlaybackCompletedCallback::NewL(MPlaybackCompletedCallback& aObs) +{ + CPlaybackCompletedCallback* self = new(ELeave)CPlaybackCompletedCallback(aObs); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; +} + +CPlaybackCompletedCallback::~CPlaybackCompletedCallback() +{ + Cancel(); +} + +void CPlaybackCompletedCallback::RunL() +{ + iObs.HandlePlaybackCompleteL(); +} + +TInt CPlaybackCompletedCallback::RunError(TInt aError) +{ + iObs.ErrorPlaybackComplete(aError); + return KErrNone; +} + +CPlaybackCompletedCallback::CPlaybackCompletedCallback(MPlaybackCompletedCallback& aObs) + : CTimer(EPriorityStandard), iObs(aObs) +{ + CActiveScheduler::Add(this); +} + +void CPlaybackCompletedCallback::Callback() +{ + if (!IsActive()) + After(KMinIntervalBeforePrime); +} + +CMMAAudioPlayer* CMMAAudioPlayer::NewLC( + CMMAMMFResolver* aResolver) +{ + CMMAAudioPlayer* self = new(ELeave) CMMAAudioPlayer(aResolver); + CleanupStack::PushL(self); + self->ConstructL(); + return self; +} + + +CMMAAudioPlayer::~CMMAAudioPlayer() +{ + + delete iPlaybackCompleted; +} + + +CMMAAudioPlayer::CMMAAudioPlayer( + CMMAMMFResolver* aResolver): + CMMAMMFPlayerBase(aResolver) +{ +} + + +void CMMAAudioPlayer::ConstructL() +{ + CMMAMMFPlayerBase::ConstructL(); + + iPlaybackCompleted = CPlaybackCompletedCallback::NewL(*this); +} + + +EXPORT_C void CMMAAudioPlayer::PrefetchDataL(const TDesC8& aData) +{ + LOG1(EJavaMMAPI, EInfo, "MMA::CMMAAudioPlayer::PrefetchDataL aData size %d", + aData.Size()); + + // player priority settings + TMMFPrioritySettings prioritySettings; + prioritySettings.iPriority = KPlayerPriority; + prioritySettings.iPref = EMdaPriorityPreferenceTimeAndQuality; + prioritySettings.iState = EMMFStatePlaying; + + TMMFDescriptorConfig srcConfig; + srcConfig().iDes = (TAny*)&aData; // wants pointer to TPtr8 + srcConfig().iDesThreadId = RThread().Id(); + + User::LeaveIfError(DoOpen(KSourceUid, + srcConfig, + KUidMmfAudioOutput, + KNullDesC8, + prioritySettings)); + + User::LeaveIfError(iController.Prime()); +} + +EXPORT_C void CMMAAudioPlayer::PrefetchFileL() +{ + LOG(EJavaMMAPI, EInfo, "MMA::CMMAAudioPlayer::Prefetching from file"); + + // player priority settings + TMMFPrioritySettings prioritySettings; + prioritySettings.iPriority = KPlayerPriority; + prioritySettings.iPref = EMdaPriorityPreferenceTimeAndQuality; + prioritySettings.iState = EMMFStatePlaying; + + TMMFFileConfig srcConfig; + srcConfig().iPath = iFileName->Des(); + + User::LeaveIfError(DoOpen(KFileSourceUid, + srcConfig, + KUidMmfAudioOutput, + KNullDesC8, + prioritySettings)); + + User::LeaveIfError(iController.Prime()); +} + +EXPORT_C void CMMAAudioPlayer::PlayCompleteL(TInt aError) +{ + LOG(EJavaMMAPI, EInfo, "CMMAAudioPlayer::PlayCompleteL +"); + TInt64 time; + GetDuration(&time); + iMediaTime = time; + iStartedEventTime = 0; + + ChangeState(EPrefetched); // ready to play again + + // Send 'Stopped' only when stop() is called. + PostLongEvent(CMMAPlayerEvent::EEndOfMedia, time); + + if (aError == KErrNone) + { + iRepeatCount++; + + // priming again for allowing e.g. mediatime setting + User::LeaveIfError(iController.Prime()); + + if (iRepeatForever || iRepeatCount < iRepeatNumberOfTimes) + { + StartL(); + } + else + { + iRepeatCount = 0; + + TTimeIntervalMicroSeconds position(0); + User::LeaveIfError(iController.SetPosition(position)); + } + } + else + { + // error has occured, setting correct number of + // repeats for next start + SetLoopCount(iRepeatNumberOfTimes); + } + LOG(EJavaMMAPI, EInfo, "CMMAAudioPlayer::PlayCompleteL -"); +} + +void CMMAAudioPlayer::RealizeL() +{ + LOG(EJavaMMAPI, EInfo, "CMMAAudioPlayer::RealizeL"); + // DataSource must have at least 1 stream or + // we must have file to play + if ((iSourceStreams.Count() == 0) && !iFileName) + { + User::Leave(KErrNotEnoughStreams); + } + CMMAPlayer::RealizeL(); +} + + +void CMMAAudioPlayer::PrefetchL() +{ + LOG(EJavaMMAPI, EInfo, "CMMAAudioPlayer::PrefetchL"); + __ASSERT_DEBUG((iSourceStreams.Count() > 0) || iFileName, User::Invariant()); + + if (iFileName) + { + // prefetching the file + PrefetchFileL(); + // we can go to prefetched state immediately + PostActionCompletedFile(); + ChangeState(EPrefetched); + //PostActionCompleted(KErrNone); + } + else + { + // Using TDes -- load the whole sound + iSourceStreams[ 0 ]->ReadAllL(); + } + // CMMASourceStream will notify with ReadCompleted +} + +const TDesC& CMMAAudioPlayer::Type() +{ + return KMMAAudioPlayer; +} + +// +// CMMASourceStreamReader finished read operation +// This is called when ReadL is completed in Prefetch() +// +void CMMAAudioPlayer::ReadCompletedL(TInt aStatus, const TDesC8& aData) +{ + LOG1(EJavaMMAPI, EInfo, "CMMAAudioPlayer::ReadCompletedL: status = %d", aStatus); + if (aStatus < KErrNone) + { + PostActionCompleted(aStatus); + } + else + { + TRAPD(err, PrefetchDataL(aData)); + if (err == KErrNone) + { + ChangeState(EPrefetched); + } + PostActionCompleted(err); + } +} + + +void CMMAAudioPlayer::HandleEvent(const TMMFEvent& aEvent) +{ + LOG(EJavaMMAPI, EInfo, "MID::CMMAAudioPlayer::HandleEvent"); + TInt err = aEvent.iErrorCode; + if (iState == EStarted) + { + // normal situation; will loop in PlayCompleteL if looping is set + if ((err == KErrEof || err == KErrUnderflow || err == KErrNone) + && aEvent.iEventType == KMMFEventCategoryPlaybackComplete) + { + iPlaybackCompleted->Callback(); + } + } + + if (err == KErrDied && aEvent.iEventType == KMMFEventCategoryPlaybackComplete) + { + + // basically pausing the playback + //1. when the phone call is received/answered , the player will be pushed to pause state and phone call is given high priority. + //2. when the call ends the player will still be in pause state , In this case the user should resume the player. + err = iController.Pause(); + + if (iState == EStarted) + { + TInt64 time; + GetMediaTime(&time); + iStartedEventTime = time; + LOG(EJavaMMAPI, EInfo, "MID::CMMAAudioPlayer::Going to ChangeState( EPrefetched );"); + + PostLongEvent(CMMAPlayerEvent::EStopped, time); + ChangeState(EPrefetched); + } + } + + if (err != KErrNone && err != KErrDied) + { + ErrorPlaybackComplete(err); + } +} + +EXPORT_C void CMMAAudioPlayer::HandlePlaybackCompleteL() +{ + PlayCompleteL(KErrNone); +} + +EXPORT_C void CMMAAudioPlayer::ErrorPlaybackComplete(TInt aError) +{ + ELOG1(EJavaMMAPI, "MID::CMMAAudioPlayer::ErrorPlaybackComplete: aError = %d", aError); + TBuf errorMessage; + errorMessage.Format(KErrDefaultError, aError); + PostStringEvent(CMMAPlayerEvent::EError, errorMessage); + + // Preparing controller for next try + TInt err = iController.Prime(); + if (err != KErrNone) + { + // Prime failed + errorMessage.Format(KErrDefaultError, err); + PostStringEvent(CMMAPlayerEvent::EError, errorMessage); + // we cannot recover, going back to unrealized state + ChangeState(EUnrealized); + return; + } + + // If player was in started state, then error will change state to + // EPrefetched. In other cases the old state is retained. + if (iState == EStarted) + { + ChangeState(EPrefetched); + } +} + +// END OF FILE