diff -r 000000000000 -r 09774dfdd46b qtinternetradio/irqmediaplayer/src/irqmmfadapter.cpp --- /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 +#include +#include +#include +#include +#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(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 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(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(); + } +}