--- /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 <ecom/implementationproxy.h>
+#include <aiutility.h>
+
+#include <AknUtils.h>
+#include <StringLoader.h>
+#include <bautils.h>
+#include <avkon.rsg>
+
+#include <data_caging_path_literals.hrh> // KDC_APP_BITMAP_DIR
+#include <apgcli.h> // RApaLsSession
+#include <apacmdln.h> // CApaCommandLine
+#include <apgtask.h>
+
+#include <mpxlog.h>
+#include <mpxconstants.h> // KAppUidMusicPlayer
+#include <mpxparameter.h>
+#include <mpxmusicplayerviewplugin.hrh>
+#include <aiplayerpluginresource.rsg>
+
+#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<MAiPropertyExtension*>(this);
+ }
+ else if (aUid == KExtensionUidEventHandler)
+ {
+ return static_cast<MAiEventHandlerExtension*>(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<MAiContentItemIterator*>(iContent);
+
+ case EAiPublisherResources:
+ return static_cast<MAiContentItemIterator*>(iResources);
+
+ case EAiPublisherEvents:
+ return static_cast<MAiContentItemIterator*>(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<const TAiPublisherInfo*>(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<CAiPlayerPlugin*> (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<TInt32>(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<TInt32>(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<TInt32>(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<TInt32>(this));
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CAiPlayerPlugin::PlaybackPositionChanged
+// -----------------------------------------------------------------------------
+//
+void CAiPlayerPlugin::PlaybackPositionChanged( TInt aPosition )
+ {
+ MPX_DEBUG1("CAiPlayerPlugin::PlaybackPositionChanged");
+
+ TBuf<KMPXTimeIndicatorLength> elapsed;
+ TBuf<KMPXTimeIndicatorLength> 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<KMPXTimeIndicatorLength> 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<TInt32>(this));
+
+ //for (Classic view)
+ observer->Publish(*this,
+ EAiPlplContentElapsedTime,
+ iElapsedTime,
+ 1);
+
+ //for (Navibar view)
+ observer->Publish(*this,
+ EAiPlplContentDurationCaption,
+ iDuration,
+ 1);
+
+ observer->Commit(reinterpret_cast<TInt32>(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<TInt32>(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<TInt32>(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;
+}
+