javauis/mmapi_qt/baseline/src/cmmaaudioplayer.cpp
branchRCL_3
changeset 65 ae942d28ec0e
--- /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 <mmf/server/mmfdes.h>
+#include <mmf/server/mmffile.h>
+#include <AudioPreference.h>
+#include <logger.h>
+#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<KErrorMessageSize> 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