--- /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();
+ }
+}