mpxmusicplayer/activeidle/aiplayerplugin/src/aiplayerplugin.cpp
changeset 0 ff3acec5bc43
--- /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;
+}
+