diff -r 000000000000 -r ff3acec5bc43 mpxmusicplayer/activeidle/aiplayerplugin/src/aiplayerplugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpxmusicplayer/activeidle/aiplayerplugin/src/aiplayerplugin.cpp Thu Dec 17 08:45:05 2009 +0200 @@ -0,0 +1,632 @@ +/* +* Copyright (c) 2006-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: Active Idle player plug-in +* +*/ + + +#include +#include + +#include +#include +#include +#include + +#include // KDC_APP_BITMAP_DIR +#include // RApaLsSession +#include // CApaCommandLine +#include + +#include +#include // KAppUidMusicPlayer +#include +#include +#include + +#include "aiplayerplugin.h" +#include "aiplayerpluginuids.hrh" +#include "aiplayerplugincontentmodel.h" + +_LIT(KMPXZeroDurationMark, "--"); +const TInt KMPXMinSecSeparatorIndex = 2; +const TInt KMPXOneSecInMicroSecs = 1000000; +const TInt KMPXOneHourInSeconds = 60*60; +const TInt KMPXTimeIndicatorLength = 16; +const TInt KPlayerMusicPlayerParameterGranularity = 50; +_LIT( KMPXAiPlayerRscPath, "z:aiplayerpluginresource.rsc" ); + +const TInt KMPlayerResumeWaitTime = 1000000; // 1.0s + +// ======== MEMBER FUNCTIONS ======== + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::ConstructL +// ---------------------------------------------------------------------------- +// +void CAiPlayerPlugin::ConstructL() + { + MPX_DEBUG1("CAiPlayerPlugin::ConstructL() - begin"); + + iInfo.iUid = KUidMusicPlayerPlugin; + iInfo.iName.Copy(_L8("PlayerPlugin")); + + iContent = AiUtility::CreateContentItemArrayIteratorL(KAiPlplContent); + iResources = AiUtility::CreateContentItemArrayIteratorL(KAiPlplResources); + iEvents = AiUtility::CreateContentItemArrayIteratorL(KAiPlplEvents); + + // Read time format strings from AVKON resource + iLongFormatString = StringLoader::LoadL(R_QTN_TIME_DURAT_LONG_WITH_ZERO); + iShortFormatString = StringLoader::LoadL(R_QTN_TIME_DURAT_MIN_SEC_WITH_ZERO); + + iCoeEnv = CCoeEnv::Static(); + + TParse parse; + parse.Set(KMPXAiPlayerRscPath, &KDC_APP_RESOURCE_DIR, NULL); + TFileName resourceFile; + resourceFile.Append(parse.FullName()); + BaflUtils::NearestLanguageFile(iCoeEnv->FsSession(), resourceFile); + iResourceOffset = iCoeEnv->AddResourceFileL(resourceFile); + iUnknownArtistText = StringLoader::LoadL(R_MPX_QTN_AIPP_UNKNOWN_ARTIST); + + iPlayStarted = EFalse; + iCleanTimer = CPeriodic::NewL(CActive::EPriorityStandard); + + MPX_DEBUG1("CAiPlayerPlugin::ConstructL() - end"); + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::NewL +// ---------------------------------------------------------------------------- +// +CAiPlayerPlugin* CAiPlayerPlugin::NewL() + { + CAiPlayerPlugin* self = new (ELeave) CAiPlayerPlugin; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::CAiPlayerPlugin +// ---------------------------------------------------------------------------- +// +CAiPlayerPlugin::CAiPlayerPlugin() + : iEngine(NULL) + { + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::~CAiPlayerPlugin() +// ---------------------------------------------------------------------------- +// +CAiPlayerPlugin::~CAiPlayerPlugin() + { + iObservers.Close(); + + Release( iContent ); + Release( iResources ); + Release( iEvents ); + + if ( iResourceOffset ) + { + iCoeEnv->DeleteResourceFile(iResourceOffset); + } + + delete iEngine; + + delete iLongFormatString; + delete iShortFormatString; + delete iUnknownArtistText; + + iCoeEnv = NULL; + iCleanTimer->Cancel(); + delete iCleanTimer; + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::Resume +// ---------------------------------------------------------------------------- +// +void CAiPlayerPlugin::Resume( TAiTransitionReason aReason ) + { + MPX_DEBUG1("CAiPlayerPlugin::ResumeL"); + if ( !iEngine ) + { + TRAPD(err, iEngine = CAiPlayerPluginEngine::NewL(*this)); + if ( err == KErrNone ) + { + iState = iEngine->PlayerState(); + PlayerStateChanged( iState ); + if (iState == EMPlayerStatePlaying || iState == EMPlayerStatePaused ) + { + TrackInfoChanged( iEngine->Title(), iEngine->Artist() ); + VolumeChanged( iEngine->Volume() ); + PlaybackPositionChanged( iEngine->Position() ); + } + } + } + else if ( aReason == EAiGeneralThemeChanged ) + { + PlayerStateChanged( iEngine->PlayerState() ); + } + + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::Suspend +// ---------------------------------------------------------------------------- +// +void CAiPlayerPlugin::Suspend( TAiTransitionReason /*aReason*/ ) + { + MPX_DEBUG1("CAiPlayerPlugin::Suspend"); + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::Stop +// ---------------------------------------------------------------------------- +// +void CAiPlayerPlugin::Stop( TAiTransitionReason /*aReason*/ ) + { + MPX_DEBUG1("CAiPlayerPlugin::Stop"); + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::SubscribeL +// ---------------------------------------------------------------------------- +// +void CAiPlayerPlugin::SubscribeL( MAiContentObserver& aObserver ) + { + MPX_DEBUG1("CAiPlayerPlugin::SubscribeL"); + return iObservers.AppendL(&aObserver); + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::ConfigureL +// ---------------------------------------------------------------------------- +// +void CAiPlayerPlugin::ConfigureL( RAiSettingsItemArray& /*aSettings*/ ) + { + MPX_DEBUG1("CAiPlayerPlugin::ConfigureL"); + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::Extension +// ---------------------------------------------------------------------------- +// +TAny* CAiPlayerPlugin::Extension( TUid aUid ) + { + if (aUid == KExtensionUidProperty) + { + return static_cast(this); + } + else if (aUid == KExtensionUidEventHandler) + { + return static_cast(this); + } + return NULL; // Requested extension not supported + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::GetPropertyL +// ---------------------------------------------------------------------------- +// +TAny* CAiPlayerPlugin::GetPropertyL( TInt aProperty ) + { + switch (aProperty) + { + case EAiPublisherInfo: + return &iInfo; + + case EAiPublisherContent: + return static_cast(iContent); + + case EAiPublisherResources: + return static_cast(iResources); + + case EAiPublisherEvents: + return static_cast(iEvents); + } + + User::Leave(KErrNotSupported); + return NULL; + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::SetPropertyL +// ---------------------------------------------------------------------------- +// +void CAiPlayerPlugin::SetPropertyL( TInt aProperty, TAny* aValue ) + { + if (aValue) + { + switch (aProperty) + { + case EAiPublisherInfo: + { + const TAiPublisherInfo* info = + static_cast(aValue); + + iInfo.iUid.iUid = info->iUid.iUid; + iInfo.iName.Copy( info->iName ); + } + break; + } + } + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::HandleEvent +// ---------------------------------------------------------------------------- +// +void CAiPlayerPlugin::HandleEvent( TInt aEvent, const TDesC& aParam ) + { + MPX_DEBUG1("CAiPlayerPlugin::HandleEvent"); + TRAPD(err, DoHandleEventL( aEvent, aParam ) ); + if ( err != KErrNone ) + { + MPX_DEBUG2("CAiPlayerPlugin::HandleEvent err[%d]", err); + } + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::DoHandleEventL +// ---------------------------------------------------------------------------- +// +void CAiPlayerPlugin::DoHandleEventL( TInt aEvent, const TDesC& aParam ) + { + MPX_DEBUG2("CAiPlayerPlugin::DoHandleEventL %d", aEvent); + + TInt volume = iEngine->Volume(); + switch (aEvent) + { + case EAiPlplEventVolInc: + { + iEngine->SetVolumeL(++volume); + iLastSetVolume = volume; + } + break; + case EAiPlplEventVolDec: + { + iEngine->SetVolumeL(--volume); + iLastSetVolume = volume; + } + break; + case EAiPlplEventVolSet: + { + TLex lex; + lex.Assign(aParam); + if( lex.Val(volume) == KErrNone ) + { + iEngine->SetVolumeL(volume); + } + iLastSetVolume = volume; + } + break; + case EAiPlplEventVolMute: + { + iLastSetVolume = volume; + iEngine->SetVolumeL(0); + } + break; + case EAiPlplEventVolRestore: + { + if( iLastSetVolume == 0 ) + { + // So that "muting muted" don't function funky way. + iLastSetVolume = 1; + } + iEngine->SetVolumeL(iLastSetVolume); + } + break; + case EAiPlplEventLaunchLibrary: + { + MPX_DEBUG1("CAiPlayerPlugin::DoHandleEventL() EAiPlplEventLaunchLibrary"); + //Launch player + TApaTaskList tasList(iEikonEnv->WsSession()); + TApaTask task = tasList.FindApp(KAppUidMusicPlayerX); + if (task.Exists()) + { + MPX_DEBUG1("CAiPlayerPlugin::DoHandleEventL() Music app is already launched. Go to Now Playing view."); + RWsSession& wsSession( iCoeEnv->WsSession() ); + CMPXParameter* param = new ( ELeave ) CMPXParameter(); + CleanupStack::PushL( param ); + param->iType.iUid = KMPXPluginTypePlaybackUid; + param->iCmdForward = EMPXCmdFwdNowPlaying; + + MPX_DEBUG1( "CAiPlayerPlugin::DoHandleEventL start Externalize" ); + CBufBase* buffer = CBufFlat::NewL( KPlayerMusicPlayerParameterGranularity ); + CleanupStack::PushL( buffer ); + RBufWriteStream writeStream( *buffer ); + CleanupClosePushL( writeStream ); + param->ExternalizeL( writeStream ); + writeStream.CommitL(); + buffer->Compress(); + CleanupStack::PopAndDestroy( &writeStream ); + + MPX_DEBUG2( "CAiPlayerPlugin::DoHandleEventL start Send message, message size = %d", buffer->Size() ); + wsSession.SendMessageToWindowGroup( task.WgId(), KAppUidMusicPlayerX, buffer->Ptr( 0 )); + MPX_DEBUG1( "CAiPlayerPlugin::DoHandleEventL Send message complete" ); + CleanupStack::PopAndDestroy( buffer ); + CleanupStack::PopAndDestroy( param ); + } + else + { + // Launch Music Player Application + MPX_DEBUG1("CAiPlayerPlugin::DoHandleEventL() Launch Music app for the first time"); + RProcess process; + TApaAppInfo appInfo; + RApaLsSession session; + TInt res = session.Connect(); // Ignore error + CleanupClosePushL( session ); + TInt err = session.GetAppInfo( appInfo, KAppUidMusicPlayerX ); + if ( !err ) + { + process.Create( appInfo.iFullName, KNullDesC );// Ignore error + TRAP( err, + { + CApaCommandLine* commandLine = CApaCommandLine::NewLC(); + commandLine->SetDocumentNameL( KNullDesC ); + commandLine->SetExecutableNameL( appInfo.iFullName ); + commandLine->SetProcessEnvironmentL( process ); + session.StartApp( *commandLine ); // Ignore error + CleanupStack::PopAndDestroy(); // commandLine + }); + process.Resume(); + process.Close(); + } + CleanupStack::PopAndDestroy(); // Close RApaLsSession session + } + } + break; + default: + break; + } + } + +// ---------------------------------------------------------------------------- +// CAiPlayerPlugin::ClearL +// ---------------------------------------------------------------------------- +// +TInt CAiPlayerPlugin::ClearL(TAny* aPtr) + { + MPX_DEBUG1("CAiPlayerPlugin::ClearL"); + CAiPlayerPlugin* plugin = reinterpret_cast (aPtr); + for (TInt i = 0; i < plugin->iObservers.Count(); i++) + { + MAiContentObserver* observer = plugin->iObservers[i]; + observer->Clean((MAiPropertyExtension&) *plugin, EAiPlplContentArtistCaption, 1); + observer->Clean((MAiPropertyExtension&) *plugin, EAiPlplContentTitleCaption, 1); + observer->Clean((MAiPropertyExtension&) *plugin, EAiPlplContentDurationCaption, 1); + observer->Clean((MAiPropertyExtension&) *plugin, EAiPlplContentElapsedTime,1); + observer->Clean((MAiPropertyExtension&) *plugin, EAiPlplContentStatus, 1); + observer->Clean((MAiPropertyExtension&) *plugin, EAiPlplContentVolume,1); + observer->Commit(0); + } + plugin->iCleanTimer->Cancel(); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CAiPlayerPlugin::PlayerStateChanged +// ----------------------------------------------------------------------------- +// +void CAiPlayerPlugin::PlayerStateChanged( TMPlayerState aState ) + { + MPX_DEBUG2("CAiPlayerPlugin::PlayerStateChanged [%d]", aState); + iState = aState; + for (TInt i = 0; i < iObservers.Count(); i++) + { + MAiContentObserver* observer = iObservers[i]; + observer->StartTransaction(reinterpret_cast(this)); + switch(iState) + { + case EMPlayerStatePlaying: + { + iPlayStarted = ETrue; + iCleanTimer->Cancel(); + observer->Publish(*this, + EAiPlplContentStatus, + EAiPlplResourcePlayIcon, + 1); + } + break; + case EMPlayerStatePaused: + { + iPlayStarted = ETrue; + iCleanTimer->Cancel(); + observer->Publish(*this, + EAiPlplContentStatus, + EAiPlplResourcePauseIcon, + 1); + PlaybackPositionChanged(iEngine->Position()); + } + break; + case EMPlayerStateSeeking: + PlaybackPositionChanged(iEngine->Position()); + break; + default: // EMPlayerStateOther + if ( iPlayStarted ) + { + iCleanTimer->Start(KMPlayerResumeWaitTime, + KMPlayerResumeWaitTime, + TCallBack(ClearL,this)); + } + iPlayStarted = EFalse; + break; + } + observer->Commit(reinterpret_cast(this)); + } + } + +// ----------------------------------------------------------------------------- +// CAiPlayerPlugin::TrackInfoChanged +// ----------------------------------------------------------------------------- +// +void CAiPlayerPlugin::TrackInfoChanged( const TDesC& aTitle, const TDesC& aArtist ) + { + MPX_DEBUG1("CAiPlayerPlugin::TrackInfoChanged"); + for (TInt i = 0; i < iObservers.Count(); i++) + { + MAiContentObserver* observer = iObservers[i]; + observer->StartTransaction(reinterpret_cast(this)); + + if ( &aTitle && aTitle.Length() ) //Check if hte reference exists add if is not empty + { + observer->Publish(*this, EAiPlplContentTitleCaption, aTitle, 1); + } + if ( &aArtist && aArtist.Length() ) //Check if hte reference exists add if is not empty + { + observer->Publish(*this, EAiPlplContentArtistCaption, aArtist, 1); + } + else + { + observer->Publish(*this, EAiPlplContentArtistCaption, *iUnknownArtistText, 1); + } + observer->Commit(reinterpret_cast(this)); + } + } + +// ----------------------------------------------------------------------------- +// CAiPlayerPlugin::PlaybackPositionChanged +// ----------------------------------------------------------------------------- +// +void CAiPlayerPlugin::PlaybackPositionChanged( TInt aPosition ) + { + MPX_DEBUG1("CAiPlayerPlugin::PlaybackPositionChanged"); + + TBuf elapsed; + TBuf total; + + TInt64 playbackPosInSeconds; + TInt64 totalLengthInSeconds; + + playbackPosInSeconds = aPosition; + totalLengthInSeconds = iEngine->Duration(); + + TPtrC format = *iShortFormatString; + + if (totalLengthInSeconds >= KMPXOneHourInSeconds) + { + // For tracks longer than an hour we use different time format and a + // slightly different layout which has more space for the time labels. + format.Set(*iLongFormatString); + } + + TTime elapsedTime(playbackPosInSeconds * KMPXOneSecInMicroSecs); + TTime totalTime(totalLengthInSeconds * KMPXOneSecInMicroSecs); + + if (aPosition == 0) + { + totalLengthInSeconds = 0; + } + + // Convert total playing time to texts. + elapsedTime.FormatL(elapsed, format); + + if (totalLengthInSeconds) + { + // Time remaining + totalTime.FormatL(total, format); + } + else + { + // Time remaining: --:-- + TLocale locale; + TBuf pos; + TChar separator = locale.TimeSeparator(KMPXMinSecSeparatorIndex); + total = KMPXZeroDurationMark; + total.Append(separator); + total += KMPXZeroDurationMark; + } + + AknTextUtils::LanguageSpecificNumberConversion(elapsed); + AknTextUtils::LanguageSpecificNumberConversion(total); + + iElapsedTime.Copy(elapsed); + + iDuration.Copy(elapsed); + iDuration.Append(_L("/")); + iDuration.Append(total); + + if ( iState == EMPlayerStatePlaying || iState == EMPlayerStatePaused || iState == EMPlayerStateSeeking ) + { + for (TInt i = 0; i < iObservers.Count(); i++) + { + MAiContentObserver* observer = iObservers[i]; + observer->StartTransaction(reinterpret_cast(this)); + + //for (Classic view) + observer->Publish(*this, + EAiPlplContentElapsedTime, + iElapsedTime, + 1); + + //for (Navibar view) + observer->Publish(*this, + EAiPlplContentDurationCaption, + iDuration, + 1); + + observer->Commit(reinterpret_cast(this)); + } + } + } + +// ----------------------------------------------------------------------------- +// CAiPlayerPlugin::VolumeChanged +// ----------------------------------------------------------------------------- +// +void CAiPlayerPlugin::VolumeChanged( TInt aVolume ) + { + MPX_DEBUG1("CAiPlayerPlugin::VolumeChanged"); + + for (TInt i = 0; i < iObservers.Count(); i++) + { + MAiContentObserver* observer = iObservers[i]; + observer->StartTransaction(reinterpret_cast(this)); + + // Order of enum TAiPlplPluginResourceIds is important + // must stay EAiPlplResourceVol0= 0 ... EAiPlplResourceVol10 = 10 + // for this to work + if ( aVolume>=0 && aVolume<=10 ) + { + observer->Publish(*this, + EAiPlplContentVolume, + aVolume, + 1); + } + observer->Commit(reinterpret_cast(this)); + } + } + +// ======== GLOBAL FUNCTIONS ======== + +// Provide a key pair value table for ECOM. +// Used to identify the correct construction function for the requested interface. +const TImplementationProxy ImplementationTable[] = +{ + IMPLEMENTATION_PROXY_ENTRY( AI_UID_ECOM_IMPLEMENTATION_CONTENTPUBLISHER_PLAYERPLUGIN, + CAiPlayerPlugin::NewL ) +}; + + +// Return an instance of the proxy table. +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) +{ + aTableCount = sizeof( ImplementationTable ) / sizeof( TImplementationProxy ); + return ImplementationTable; +} +