qtinternetradio/irqmediaplayer/src/irqmmfadapter.cpp
changeset 0 09774dfdd46b
child 5 0930554dc389
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qtinternetradio/irqmediaplayer/src/irqmmfadapter.cpp	Mon Apr 19 14:01:53 2010 +0300
@@ -0,0 +1,520 @@
+/*
+* Copyright (c) 2009 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:
+*
+*/
+#include <mmf/common/mmferrors.h>
+#include <NokiaAudioPreference.h>
+#include <coedef.h>
+#include <QStringList>
+#include <hxmetadatakeys.h>
+#include "irqmetadata.h"
+#include "irqenums.h"
+#include "irqmmfadapter.h"
+
+//Constants
+const TUid KUidController        = { 0x101F8514 }; // Helix Video controller UID
+const TInt KConnectingTime       = 30*1000000;     // 30 seconds
+const TInt KVolumeMinPercentage  = 0;              // Minimum volume percentage
+const TInt KVolumeMaxPercentage  = 100;            // Maximum volume percentage
+const TInt KLoadingCompletePercentage = 100;       // Loading Complete percentage
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::IRQMMFAdapter
+//  Constructor
+//  Initialize viriants
+// ---------------------------------------------------------------------------
+//
+IRQMMFAdapter::IRQMMFAdapter() :
+    iVideoPlayer(NULL)
+    ,iQMetaData(NULL)
+    ,iPrepareTimer(NULL)
+{
+    iPlayState = EStopped;
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::~IRQMMFAdapter
+//  Destructor
+//  Clean up resources
+// ---------------------------------------------------------------------------
+//
+IRQMMFAdapter::~IRQMMFAdapter()
+{
+    destroyPlayer();
+
+    delete iQMetaData;
+    iQMetaData = NULL;
+
+    if (iPrepareTimer)
+    {
+        if (iPrepareTimer->IsActive())
+        {
+            iPrepareTimer->Cancel();
+        }
+        delete iPrepareTimer;
+        iPrepareTimer = NULL;
+    }
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::playStation
+//  IRQPlayerAdapterInterface method
+//  Play url via specific access point id
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::playStation(const QString &aUrl, int aApId)
+{
+    TRAPD(error, playL(aUrl, aApId));
+    if (NULL == iQMetaData)
+    {
+        emit errorOccured(EIRQErrorOutOfMemory);
+    }
+
+    if (KErrNone != error)
+    {
+        emit errorOccured(EIRQPlayerErrorGeneral);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::playL
+//  Play url via specific access point id
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::playL(const QString &aUrl, int aApId)
+{
+    // Save stream Url
+    if (NULL == iQMetaData)
+    {
+        iQMetaData = new (ELeave) IRQMetaData();
+    }
+    else
+    {
+        // Clear MetaData
+        iQMetaData->clear();
+    }
+    iQMetaData->setStreamUrl(aUrl);
+
+    // Transfer url from QString to TDesC
+    TPtrC stationUrl(reinterpret_cast<const TUint16*>(aUrl.utf16()));
+
+    // Create player if it doesn't exist
+    if (NULL == iVideoPlayer)
+    {
+        createPlayerL();
+    }
+
+    // If the status is not stopped, clean up last playback resources
+    stop();
+
+    // Open url
+    iVideoPlayer->OpenUrlL(stationUrl, aApId, KNullDesC8, KUidController);
+    iPlayState = EOpenning;
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::stop
+//  IRQPlayerAdapterInterface method
+//  Stop playback, call Close() to clean up allocated resources
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::stop()
+{
+    if (iVideoPlayer && EStopped != iPlayState)
+    {
+        if (iPrepareTimer)
+        {
+            if (iPrepareTimer->IsActive())
+            {
+                iPrepareTimer->Cancel();
+            }
+        }
+
+        iVideoPlayer->Stop();
+        iVideoPlayer->Close();
+        iPlayState = EStopped;
+    }
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::setVolume
+//  IRQPlayerAdapterInterface method
+//  Set volume to player
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::setVolume(int aVolume)
+{
+    if (iVideoPlayer && iPlayState > EOpenning)
+    {
+        // aVolume is a percentage
+        if (aVolume < KVolumeMinPercentage)
+        {
+            aVolume = KVolumeMinPercentage;
+        }
+        else if (aVolume > KVolumeMaxPercentage)
+        {
+            aVolume = KVolumeMaxPercentage;
+        }
+        int volume = aVolume*iVideoPlayer->MaxVolume()/KVolumeMaxPercentage;
+
+        TRAPD(error, iVideoPlayer->SetVolumeL(volume));
+        if (KErrNone != error)
+        {
+            emit errorOccured(EIRQPlayerErrorGeneral);
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::getVolume
+//  IRQPlayerAdapterInterface method
+//  Get current volume value from player
+// ---------------------------------------------------------------------------
+//
+int IRQMMFAdapter::getVolume()
+{
+    int volume = KVolumeMinPercentage;
+
+    if (iVideoPlayer && iPlayState > EOpenning)
+    {
+        // Return a percentage
+        volume = iVideoPlayer->Volume()*KVolumeMaxPercentage/iVideoPlayer->MaxVolume();
+    }
+    return volume;
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::getPlayerInstance
+//  IRQPlayerAdapterInterface method
+//  Get audio player instance
+// ---------------------------------------------------------------------------
+//
+void* IRQMMFAdapter::getPlayerInstance()
+{
+    return (void*)iVideoPlayer;
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::MvpuoOpenComplete
+//  Callback function, MVideoPlayerUtilityObserver method
+//  Called after calling CVideoPlayerUtility::OpenUrlL()
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::MvpuoOpenComplete(TInt aError)
+{
+    if (KErrNone == aError)
+    {
+        if (NULL == iPrepareTimer)
+        {
+            TRAPD(error, iPrepareTimer = CPeriodic::NewL(CPeriodic::EPriorityStandard));
+            if (KErrNone != error)
+            {
+                emit errorOccured(EIRQErrorOutOfMemory);
+                return;
+             }
+        }
+
+        // Prepare to playback
+        iVideoPlayer->Prepare();
+        iPlayState = EConnecting;
+
+        // Start a timer to check preparation status
+        if (iPrepareTimer->IsActive())
+        {
+            // Cancel the previous request if pending
+            iPrepareTimer->Cancel();
+        }
+        TTimeIntervalMicroSeconds32 interval(KConnectingTime);
+        iPrepareTimer->Start(interval,interval,
+                             TCallBack(IRQMMFAdapter::isPrepareCompleted,this));
+    }
+    else
+    {
+        emit errorOccured(EIRQPlayerErrorConnectingFailed);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::MvpuoPrepareComplete
+//  Callback function, MVideoPlayerUtilityObserver method
+//  Called after calling CVideoPlayerUtility::Prepare. Since some audio types
+//  are not explicitly(hxmmffourccmap.cpp), they are not retrieved here.
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::MvpuoPrepareComplete(TInt aError)
+{
+    // Cancel the previous request if pending
+    if (iPrepareTimer->IsActive())
+    {
+        iPrepareTimer->Cancel();
+    }
+
+    if (KErrNone == aError)
+    {
+        // Get volume from preset
+        int volumeval = KVolumeMaxPercentage/2;
+        emit volumeExpected(volumeval);
+        setVolume(volumeval);
+
+        // Save bit rate
+        int bitrate = 0;
+        TRAPD(error, bitrate = iVideoPlayer->AudioBitRateL());
+        if (KErrNone == error)
+        {
+            iQMetaData->setBitrate(bitrate/1000);
+        }
+
+        // Send signal ConnectionEstablished
+        emit connectionEstablished(iQMetaData->getBitrate());
+
+        // Set specific event to get meta data from player
+        setMetadataEventConfig();
+
+        // Start playback
+        iVideoPlayer->Play();
+        iPlayState = EBuffering;
+    }
+    else if (KErrServerBusy == aError)
+    {
+        emit errorOccured(EIRQPlayerErrorServerFull);
+    }
+    else
+    {
+        emit errorOccured(EIRQPlayerErrorConnectingFailed);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::MvpuoPlayComplete
+//  Callback function, MVideoPlayerUtilityObserver method
+//  Notification that video playback has completed. This is not called if play
+//  back is explicitly stopped by calling Stop. Moreover, radio station stream
+//  has no end. So it should be NEVER called.
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::MvpuoPlayComplete(TInt aError)
+{
+    if (KErrNone != aError)
+    {
+        emit errorOccured(EIRQPlayerErrorGeneral);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::MvpuoEvent
+//  Callback function, MVideoPlayerUtilityObserver method
+//  Handle events from player.
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::MvpuoEvent(TMMFEvent const & aEvent)
+{
+    if (KMMFEventCategoryVideoPlayerGeneralError == aEvent.iEventType)
+    {
+        switch (aEvent.iErrorCode)
+        {
+            case KErrHardwareNotAvailable:
+            case KErrMMAudioDevice:
+                // Higher priority application has taken over the
+                // audio device. --> Do stop.
+                emit errorOccured(EIRQPlayerErrorAudioDeviceLost);
+                break;
+            case KErrDisconnected:
+                emit errorOccured(EIRQPlayerErrorConnectionLost);
+                break;
+            case KErrTimedOut:    
+                emit errorOccured(EIRQPlayerErrorTimeOut);
+                break;
+            case KErrServerBusy:    
+                emit errorOccured(EIRQPlayerErrorServerFull);
+                break;                                            
+            default:
+                emit errorOccured(EIRQPlayerErrorGeneral);			
+                break;
+        }
+    }
+    else if (KMMFRefreshMetaData == aEvent.iEventType)
+    {
+        // Get refreshed meta data
+        TRAPD(error, getRefreshedMetaDataL(aEvent.iErrorCode));
+        if (KErrNone != error)
+        {
+            emit errorOccured(EIRQPlayerErrorGeneral);
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::MvpuoFrameReady
+//  Callback function, MVideoPlayerUtilityObserver method
+//  For video stream only, never called
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::MvpuoFrameReady(CFbsBitmap& aFrame,TInt aError)
+{
+    Q_UNUSED(aFrame);
+    Q_UNUSED(aError);
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::MvloLoadingStarted
+//  Callback function, MVideoLoadingObserver method
+//  Start buffering after CVideoPlayerUtility::Play() is called
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::MvloLoadingStarted()
+{
+    // Get buffering progress and send it to application
+    int percentageComplete = 0;
+
+    TRAPD(error, iVideoPlayer->GetVideoLoadingProgressL(percentageComplete));
+
+    if (KErrNone == error)
+    {
+        // Send signal to UpdateProgress
+        emit percentageBuffered(percentageComplete);
+    }
+    else
+    {
+        emit errorOccured(EIRQPlayerErrorGeneral);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::MvloLoadingComplete
+//  Callback function, MVideoLoadingObserver method
+//  Send 100% buffering status out
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::MvloLoadingComplete()
+{
+    iPlayState = EPlaying;
+
+    // Send signal to update progress, 100%
+    emit percentageBuffered(KLoadingCompletePercentage);
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::getRefreshedMetaData
+//  Get refreshed meta data according to the index
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::getRefreshedMetaDataL(TInt index)
+{
+    if (iQMetaData)
+    {
+        CMMFMetaDataEntry* pMetadataEntry = iVideoPlayer->MetaDataEntryL(index);
+
+        QString entryName = QString::fromUtf16(pMetadataEntry->Name().Ptr(),
+                                               pMetadataEntry->Name().Length());
+
+        // If the meta data is the same as last, we don't need to report it.
+        if (iLastArtistSongName == entryName)
+        {
+            return;
+        }
+        else
+        {
+            iLastArtistSongName = entryName;
+        }
+
+        // Artist, song name
+        if (entryName == HXAuthor)
+        {
+            QString songArtist = QString::fromUtf16(pMetadataEntry->Value().Ptr(),
+                                                    pMetadataEntry->Value().Length());
+            iQMetaData->setArtistSongName(songArtist);
+
+            // Send signal HandleMetaDataReceived
+            emit metaDataReceived(*iQMetaData);
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::createPlayer
+//  Create player instance
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::createPlayerL()
+{
+    // Create player instance
+    iVideoPlayer = CVideoPlayerUtility2::NewL(*this,KAudioPriorityAudioPlaybackStreaming ,
+                                             (TMdaPriorityPreference)KAudioPrefRealOneStreaming);
+    // Register loading notification
+    iVideoPlayer->RegisterForVideoLoadingNotification(*this);
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::destroyPlayer
+//  Destroy player
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::destroyPlayer()
+{
+    delete iVideoPlayer;
+    iVideoPlayer = NULL;
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::SetMetadataEventConfig
+//  Enable meta data event
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::setMetadataEventConfig()
+{
+    TMMFMessageDestinationPckg  destinationPckg(KUidInterfaceMMFControllerMetadataEventMsg);
+    TPckgBuf<TBool>             metadataEventPckg(EMMFEnableMetadataEvent);
+
+    //  Enable meta data event.
+    iVideoPlayer->CustomCommandSync(destinationPckg,
+                                    EMMFSetMetadataEventConfig,
+                                    metadataEventPckg,
+                                    KNullDesC8);
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::isPrepareCompleted
+//  Static function for periodic call
+// ---------------------------------------------------------------------------
+//
+TInt IRQMMFAdapter::isPrepareCompleted(TAny* aPtr)
+{
+    IRQMMFAdapter* self = static_cast<IRQMMFAdapter*>(aPtr);
+    if (self)
+    {
+        self->checkPrepare();
+    }
+    return KErrNone;
+}
+
+// ---------------------------------------------------------------------------
+//  IRQMMFAdapter::checkPrepare
+//  Check if the preparation is complete
+// ---------------------------------------------------------------------------
+//
+void IRQMMFAdapter::checkPrepare()
+{
+    if (iPrepareTimer->IsActive())
+    {
+        // Cancel the previous request if pending
+        iPrepareTimer->Cancel();
+    }
+
+    if (EConnecting == iPlayState)
+    {
+        emit errorOccured(EIRQPlayerErrorConnectingFailed);
+        stop();
+    }
+}