mtpdataproviders/mtpimagedp/src/cmtpimagedp.cpp
changeset 0 d0791faffa3f
child 2 4843bb5893b6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mtpdataproviders/mtpimagedp/src/cmtpimagedp.cpp	Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,658 @@
+// 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:
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#include <e32cmn.h>
+#include <centralrepository.h>
+#include <mtp/tmtptyperequest.h>
+#include <mtp/cmtpstoragemetadata.h>
+#include <mtp/cmtpobjectmetadata.h>
+#include <mtp/mmtpconnection.h>
+#include <mtp/mmtpdataproviderframework.h>
+#include <mtp/mtpdataproviderapitypes.h>
+#include <mtp/mtpprotocolconstants.h>
+#include <mtp/mmtpobjectmgr.h>
+#include <mtp/mmtpstoragemgr.h>
+#include <mtp/tmtptypeevent.h>
+
+#include "cmtpimagedp.h"
+#include "mtpimagedpconst.h"
+#include "mtpimagedppanic.h"
+#include "cmtprequestprocessor.h"
+#include "mtpimagedprequestprocessor.h"
+#include "cmtpimagedpthumbnailcreator.h"
+#include "mtpimagedputilits.h"
+#include "cmtpimagedpmdeobserver.h"
+#include "cmtpimagedprenameobject.h"
+
+__FLOG_STMT(_LIT8(KComponent,"CMTPImageDataProvider");)
+
+static const TInt KArrayGranularity = 3;
+static const TInt KDeleteObjectGranularity = 2;
+
+//used by hashmap & hashset class
+LOCAL_C TUint32 TBuf16Hash(const TBuf<KMaxExtNameLength>& aPtr)
+    {
+    return DefaultHash::Des16(aPtr);
+    }
+
+LOCAL_C TBool TBuf16Ident(const TBuf<KMaxExtNameLength>& aL, const TBuf<KMaxExtNameLength>& aR)
+    {
+    return DefaultIdentity::Des16(aL, aR);
+    }
+
+/**
+ Image data provider factory method.
+ @return A pointer to a Image data provider object. Ownership is transfered.
+ @leave One of the system wide error codes, if a processing failure occurs.
+*/
+TAny* CMTPImageDataProvider::NewL(TAny* aParams)
+    {
+    CMTPImageDataProvider* self = new (ELeave) CMTPImageDataProvider(aParams);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+/**
+ Standard C++ constructor
+ 
+ @param aParams  pointer to MMTPDataProviderFramework
+*/
+CMTPImageDataProvider::CMTPImageDataProvider(TAny* aParams) :
+    CMTPDataProviderPlugin(aParams),
+    iActiveProcessors(KArrayGranularity),
+    iFormatMappings(&TBuf16Hash, &TBuf16Ident),
+    iActiveProcessor(-1),
+    iEnumerated(EFalse),
+	iDeleteObjectsArray(KDeleteObjectGranularity)
+    {
+    }
+
+/**
+Second-phase construction
+*/
+void CMTPImageDataProvider::ConstructL()
+    {
+    __FLOG_OPEN(KMTPSubsystem, KComponent);
+    __FLOG(_L8(">> CMTPImageDataProvider::ConstructL"));
+    
+    iPropertyMgr = CMTPImageDpObjectPropertyMgr::NewL(Framework());
+    iThumbnailManager = CMTPImageDpThumbnailCreator::NewL();
+    iMdeObserver = CMTPImageDpMdeObserver::NewL(Framework(), *this);
+    iMdeObserver->SubscribeForChangeNotificationL();
+    
+    //Setup central repository connection
+    const TUint32 KUidMTPImageRepositoryValue(0x2001FCA2);
+    const TUid KUidMTPImageRepository = {KUidMTPImageRepositoryValue};
+    iRepository = CRepository::NewL(KUidMTPImageRepository);    
+    
+    //Initialize hash map of extention to format code
+    TInt count(sizeof(KMTPValidCodeExtensionMappings) / sizeof(KMTPValidCodeExtensionMappings[0]));
+    for(TInt i(0); i<count; i++)
+        {
+        iFormatMappings.Insert(KMTPValidCodeExtensionMappings[i].iExtension, KMTPValidCodeExtensionMappings[i].iFormatCode);
+        }    
+    
+    //Define RProperty of new pictures for status data provider
+    _LIT_SECURITY_POLICY_PASS(KAllowReadAll);
+    TInt error = RProperty::Define(TUid::Uid(KMTPServerUID), KMTPNewPicKey, RProperty::EInt, KAllowReadAll, KAllowReadAll);
+    if (error != KErrNone && error != KErrAlreadyExists)
+        {
+        __FLOG_1(_L8("CMTPImageDataProvider::ConstructL - RProperty define error:%d"), error);
+        User::LeaveIfError(error);
+        }    
+    
+    __FLOG(_L8("<< CMTPImageDataProvider::ConstructL"));
+    }
+
+/**
+ Destructor
+*/
+CMTPImageDataProvider::~CMTPImageDataProvider()
+    {
+    __FLOG(_L8(">> ~CMTPImageDataProvider"));      
+    
+    // delete all processor instances
+    TUint count(iActiveProcessors.Count());
+    while (count--)
+        {
+        iActiveProcessors[count]->Release();
+        }
+    iActiveProcessors.Close();
+     
+    // image dp unsubscribe from MDS
+    if(iMdeObserver)
+        {
+        TRAP_IGNORE(iMdeObserver->UnsubscribeForChangeNotificationL());
+        delete iMdeObserver;
+        }        
+    delete iThumbnailManager;
+    delete iPropertyMgr;       
+    delete iRepository;   
+    delete iRenameObject;
+    
+    iFormatMappings.Close();
+    
+    //Try to delete objects in array
+    HandleDeleteObjectsArray();
+    iDeleteObjectsArray.ResetAndDestroy();
+    
+    __FLOG(_L8("<< ~CMTPImageDataProvider"));
+    __FLOG_CLOSE;
+    }
+
+void CMTPImageDataProvider::Cancel()
+    {
+    __FLOG(_L8(">> Cancel"));
+    __FLOG(_L8("<< Cancel"));
+    }
+
+/**
+ Process the event from initiator
+ 
+ @param aEvent       The event to be processed
+ @param aConnection  The connection from which the event comes
+*/
+void CMTPImageDataProvider::ProcessEventL(const TMTPTypeEvent& aEvent, MMTPConnection& aConnection)
+    {
+    __FLOG(_L8(">> ProcessEventL"));
+    
+    //Try to delete objects in array
+    HandleDeleteObjectsArray();
+    
+    TInt idx(LocateRequestProcessorL(aEvent, aConnection));
+    
+    if (idx != KErrNotFound)
+        {
+        iActiveProcessors[idx]->HandleEventL(aEvent);
+        }
+
+    __FLOG(_L8("<< ProcessEventL"));
+    }
+
+/**
+Process the notification from framework
+@param aNotification  The notification to be processed
+@param aParams        Notification parmenter
+*/
+void CMTPImageDataProvider::ProcessNotificationL(TMTPNotification aNotification, const TAny* aParams)
+    {
+    __FLOG(_L8(">> ProcessNotificationL"));
+
+    switch (aNotification)
+        {
+    case EMTPSessionClosed:
+        SessionClosedL(*reinterpret_cast<const TMTPNotificationParamsSessionChange*>(aParams));
+        break;
+        
+    case EMTPSessionOpened:
+        SessionOpenedL(*reinterpret_cast<const TMTPNotificationParamsSessionChange*>(aParams));
+        break;
+        
+    case EMTPRenameObject:
+        RenameObjectL(*reinterpret_cast<const TMTPNotificationParamsHandle*>(aParams));
+        break;
+        
+    default:
+        // Ignore all other notifications.
+        break;
+        }
+ 
+    __FLOG(_L8("<< ProcessNotificationL"));
+    }
+
+/**
+ Process the request from initiator
+ 
+ @param aPhase       The request transaction phase
+ @param aRequest     The request to be processed
+ @param aConnection  The connection from which the request comes
+*/   
+void CMTPImageDataProvider::ProcessRequestPhaseL(TMTPTransactionPhase aPhase, const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
+    {    
+    __FLOG(_L8(">> ProcessRequestPhaseL"));    
+    
+    //Try to handle objects which need to be deleted
+    HandleDeleteObjectsArray();
+    
+    TInt idx(LocateRequestProcessorL(aRequest, aConnection));
+    __ASSERT_DEBUG((idx != KErrNotFound), Panic(EMTPImageDpNoMatchingProcessor));
+    MMTPRequestProcessor* processor(iActiveProcessors[idx]);
+    iActiveProcessor = idx;
+    iActiveProcessorRemoved = EFalse;    
+    TBool result(processor->HandleRequestL(aRequest, aPhase));
+    if (iActiveProcessorRemoved)
+        {
+        processor->Release(); // destroy the processor
+        }    
+    else if (result)    //destroy the processor
+        {
+        processor->Release();
+        iActiveProcessors.Remove(idx);
+        }
+ 
+    iActiveProcessor = -1;
+    __FLOG(_L8("<< ProcessRequestPhaseL"));
+    }
+
+/**
+ Starts the enumeration of the image dp
+*/
+void CMTPImageDataProvider::StartObjectEnumerationL(TUint32 aStorageId, TBool /*aPersistentFullEnumeration*/)
+    {
+    __FLOG(_L8(">> StartObjectEnumerationL"));
+    
+    if (aStorageId == KMTPStorageAll)
+        {
+        /*
+         * Query previous image object count for calculation of new pictures when MTP startup
+         * 
+         */
+        iPrePictures = QueryImageObjectCountL();
+        iEnumerated = ETrue;
+        __FLOG_1(_L16("CMTPImageDpEnumerator::CompleteEnumeration - Previous Pics: %d"), iPrePictures);
+        }
+
+    NotifyEnumerationCompleteL(aStorageId, KErrNone);
+    
+    __FLOG(_L8("<< StartObjectEnumerationL"));
+    }
+
+
+/**
+Starts enumerate imagedp storage, just declare complete
+*/
+void CMTPImageDataProvider::StartStorageEnumerationL()
+    {
+    __FLOG(_L8(">> StartStorageEnumerationL"));   
+    NotifyStorageEnumerationCompleteL();
+    __FLOG(_L8("<< StartStorageEnumerationL"));        
+    }
+
+/**
+Defines the supported operations and formats of the data provider
+
+@param aCategory Defines what MTP is quering the DP about
+@param aArray Supported() edits array to append supported features
+*/
+void CMTPImageDataProvider::Supported(TMTPSupportCategory aCategory, RArray<TUint>& aArray) const
+    {
+    __FLOG(_L8(">> Supported"));
+
+    switch (aCategory) 
+        {        
+    case EEvents:
+        {
+        TInt count(sizeof(KMTPImageDpSupportedEvents) / sizeof(KMTPImageDpSupportedEvents[0]));
+        for (TInt i(0); (i < count); i++)
+            {
+            aArray.Append(KMTPImageDpSupportedEvents[i]);
+            __FLOG_VA((_L("   CMTPImageDataProvider::Supported Events %d added"), KMTPImageDpSupportedEvents[i]));
+            }  
+        }
+        break;
+    case EObjectPlaybackFormats: // formats that can be placed on the device
+	/*intentional fall through*/ 
+    case EObjectCaptureFormats: // formats the device generates
+        {
+        TInt count(sizeof(KMTPValidCodeExtensionMappings) / sizeof(KMTPValidCodeExtensionMappings[0]));
+        for(TInt i(0); (i < count); i++)
+            {
+            __FLOG_VA((_L("   CMTPImageDataProvider::Supported we have formatCode %d"), KMTPValidCodeExtensionMappings[i].iFormatCode ));
+            if(aArray.Find(KMTPValidCodeExtensionMappings[i].iFormatCode)==KErrNotFound) // KMTPValidCodeExtensionMappings may contain format code more than once
+                {
+                aArray.Append(KMTPValidCodeExtensionMappings[i].iFormatCode);
+                __FLOG_VA((_L("   CMTPImageDataProvider::Supported formatCode %d added"), KMTPValidCodeExtensionMappings[i].iFormatCode));
+                }
+            }
+        }
+        break;
+    case EObjectProperties:
+        {
+        TInt count(sizeof(KMTPImageDpSupportedProperties) / sizeof(KMTPImageDpSupportedProperties[0]));
+        for (TInt i(0); (i < count); i++)
+            {
+            aArray.Append(KMTPImageDpSupportedProperties[i]);
+            __FLOG_VA((_L("   CMTPImageDataProvider::Supported property %d added"), KMTPImageDpSupportedProperties[i]));
+            }   
+        }
+        break; 
+
+    case EOperations:
+        {
+        TInt count(sizeof(KMTPImageDpSupportedOperations) / sizeof(KMTPImageDpSupportedOperations[0]));
+        for (TInt i(0); (i < count); i++)
+            {
+            aArray.Append(KMTPImageDpSupportedOperations[i]);
+            __FLOG_VA((_L("   CMTPImageDataProvider::Supported operation %d added"), KMTPImageDpSupportedOperations[i]));
+            }   
+        }
+        break;  
+
+    case EStorageSystemTypes:
+        aArray.Append(CMTPStorageMetaData::ESystemTypeDefaultFileSystem);
+        break; 
+
+    default:    
+        // Unrecognised category, leave aArray unmodified.
+        break;
+        }
+
+    __FLOG(_L8("<< Supported"));
+    }
+
+/**
+Defines the supported vendor extension info of the data provider
+
+@param aCategory Defines what MTP is quering the DP about
+@param aStrings Supported() edits array to append supported vendor info
+*/
+void CMTPImageDataProvider::SupportedL(TMTPSupportCategory aCategory, CDesCArray& aStrings) const
+    {
+    switch (aCategory) 
+        {
+    case EFolderExclusionSets:
+        {
+        //do nothing
+        }
+        break;
+        
+    case EFormatExtensionSets:
+        {
+        _LIT(KFormatExtensionJpg, "0x3801:jpg::3");//3 means file dp will enumerate all image files instead of image dp.
+        aStrings.AppendL(KFormatExtensionJpg);
+        _LIT(KFormatExtensionJpe, "0x3801:jpe::3");
+        aStrings.AppendL(KFormatExtensionJpe);
+        _LIT(KFormatExtensionJpeg, "0x3801:jpeg::3");
+        aStrings.AppendL(KFormatExtensionJpeg);   
+        }
+        break;
+        
+    default:
+        // Unrecognised category, leave aArray unmodified.
+        break;
+        }
+    }
+
+/**
+Notify framework the image dp has completed enumeration
+*/
+void CMTPImageDataProvider::NotifyStorageEnumerationCompleteL()
+    {
+    __FLOG(_L8(">> NotifyStorageEnumerationCompleteL"));    
+    Framework().StorageEnumerationCompleteL();    
+    __FLOG(_L8("<< NotifyStorageEnumerationCompleteL"));        
+    }
+
+CMTPImageDpThumbnailCreator& CMTPImageDataProvider::ThumbnailManager() const
+	{
+    __ASSERT_DEBUG(iThumbnailManager, User::Invariant());
+	return *iThumbnailManager;
+	}
+
+CMTPImageDpObjectPropertyMgr& CMTPImageDataProvider::PropertyMgr()const
+	{
+	__ASSERT_DEBUG(iPropertyMgr, User::Invariant());
+	return *iPropertyMgr;	
+	}
+
+CRepository& CMTPImageDataProvider::Repository() const
+    {
+    __ASSERT_DEBUG(iRepository, User::Invariant());
+    return *iRepository;
+    }
+
+// --------------------------------------------------------------------------
+// 
+// --------------------------------------------------------------------------
+//
+#ifdef __FLOG_ACTIVE  
+void CMTPImageDataProvider::NotifyEnumerationCompleteL(TUint32 aStorageId, TInt aError)
+#else
+void CMTPImageDataProvider::NotifyEnumerationCompleteL(TUint32 aStorageId, TInt /*aError*/)
+#endif // __FLOG_ACTIVE
+    {
+    __FLOG(_L8(">> NotifyEnumerationCompletedL"));
+    __FLOG_VA((_L8("Enumeration of storage 0x%08X completed with error status %d"), aStorageId, aError));
+        
+    Framework().ObjectEnumerationCompleteL(aStorageId);
+    
+    __FLOG(_L8("<< HandleEnumerationCompletedL"));
+    }
+
+/**
+Find or create a request processor that can process the request
+
+@param aRequest    The request to be processed
+@param aConnection The connection from which the request comes
+
+@return the index of the found/created request processor
+*/
+TInt CMTPImageDataProvider::LocateRequestProcessorL(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
+    {
+    __FLOG(_L8(">> LocateRequestProcessorL"));        
+    
+    TInt idx(KErrNotFound);
+    TInt count(iActiveProcessors.Count());
+    for (TInt i(0); (i < count); i++)
+        {
+        if (iActiveProcessors[i]->Match(aRequest, aConnection))
+            {
+            idx = i;
+            break;
+            }
+        }
+        
+    if (idx == KErrNotFound)
+        {
+        MMTPRequestProcessor* processor = MTPImageDpProcessor::CreateL(Framework(), aRequest, aConnection,*this);
+        CleanupReleasePushL(*processor);
+        iActiveProcessors.AppendL(processor);
+        CleanupStack::Pop();
+        idx = count;
+        }
+ 
+    __FLOG(_L8("<< LocateRequestProcessorL"));
+    return idx;
+    }
+
+/**
+Find or create a request processor that can process the event
+
+@param aEvent    The event to be processed
+@param aConnection The connection from which the request comes
+
+@return the index of the found/created request processor
+*/
+TInt CMTPImageDataProvider::LocateRequestProcessorL(const TMTPTypeEvent& aEvent, MMTPConnection& aConnection)
+    {
+    __FLOG(_L8(">> LocateRequestProcessorL"));
+        
+    TInt idx(KErrNotFound);
+    TInt count(iActiveProcessors.Count());
+    for (TInt i(0); (i < count); i++)
+        {
+        if (iActiveProcessors[i]->Match(aEvent, aConnection))
+            {
+            idx = i;
+            break;
+            }
+        }    
+
+    __FLOG(_L8("<< LocateRequestProcessorL"));
+    return idx;
+    }
+
+/**
+ Notify the data provider that the session has been closed
+
+ @param aSessionId    The session Id closed
+ @param aConnection   The connection of the sesssion
+*/
+void CMTPImageDataProvider::SessionClosedL(const TMTPNotificationParamsSessionChange& aSession)
+    {
+    __FLOG_VA((_L8(">> SessionClosedL SessionID = %d"), aSession.iMTPId));
+    
+    TInt count = iActiveProcessors.Count();
+    while(count--)
+        {
+        MMTPRequestProcessor* processor = iActiveProcessors[count];
+        TUint32 sessionId = processor->SessionId();
+        if((sessionId == aSession.iMTPId) && (processor->Connection().ConnectionId() == aSession.iConnection.ConnectionId()))
+            {
+            iActiveProcessors.Remove(count);
+            if (count == iActiveProcessor)
+                {
+                iActiveProcessorRemoved = ETrue;
+                }
+            else
+                {
+                processor->Release();
+                }
+            }
+        }
+    
+    __FLOG(_L8("<< SessionClosedL"));
+    }
+
+/**
+ Notify the data provider that the session opened
+ 
+ @param aSessionId    The session Id opened
+ @param aConnection   The connection of the sesssion
+*/
+#ifdef __FLOG_ACTIVE
+void CMTPImageDataProvider::SessionOpenedL(const TMTPNotificationParamsSessionChange& aSession)
+#else
+void CMTPImageDataProvider::SessionOpenedL(const TMTPNotificationParamsSessionChange& /*aSession*/)
+#endif
+    {
+    __FLOG_VA((_L8(">> SessionOpenedL SessionID = %d"), aSession.iMTPId));
+    
+    if (iEnumerated)
+        {
+        /**
+         * Get image object count from framework and calculate the new pictures
+         */
+        TUint curPictures = QueryImageObjectCountL();
+        TInt  newPictures = curPictures - iPrePictures;
+        
+        __FLOG_2(_L16("CMTPImageDpEnumerator::CompleteEnumeration - Previous Pics:%d, New Pics: %d"), iPrePictures, newPictures);
+        if (newPictures >= 0)
+            {
+            MTPImageDpUtilits::UpdateNewPicturesValue(*this, newPictures, ETrue);  
+            }
+        else
+            {
+            MTPImageDpUtilits::UpdateNewPicturesValue(*this, 0, ETrue);  
+            }
+        
+        iEnumerated = EFalse;
+        }
+    
+    __FLOG(_L8("<< SessionOpenedL "));
+    }
+
+/**
+ Notify the data provider that the folder name has been changed
+ 
+ @param aParam   The Rename notification
+*/
+void CMTPImageDataProvider::RenameObjectL(const TMTPNotificationParamsHandle& aParam)
+    {
+    __FLOG_VA((_L16(">> RenameObjectL Handle: %u, Old name: %S"), aParam.iHandleId, &aParam.iFileName));
+    
+    if (!iRenameObject)
+        {
+        iRenameObject = CMTPImageDpRenameObject::NewL(Framework(), *this);
+        }
+
+    iRenameObject->StartL(aParam.iHandleId, aParam.iFileName);    
+    
+    __FLOG(_L8("<< RenameObjectL "));
+    }
+
+/**
+ Find format code according to its extension name 
+*/
+TMTPFormatCode CMTPImageDataProvider::FindFormatL(const TDesC& aExtension)
+    {
+    TMTPFormatCode* ret = iFormatMappings.Find(aExtension);
+    User::LeaveIfNull(ret);
+    
+    return *ret;
+    }
+
+/**
+ Query image object count from current framework 
+*/
+TUint CMTPImageDataProvider::QueryImageObjectCountL()
+    { 
+    TMTPObjectMgrQueryParams params(KMTPStorageAll, EMTPFormatCodeEXIFJPEG, KMTPHandleNone);    
+    return Framework().ObjectMgr().CountL(params);
+    }
+
+TBool CMTPImageDataProvider::GetCacheParentHandle(const TDesC& aParentPath, TUint32& aParentHandle)
+    {
+    TBool ret = EFalse;
+    
+    if (iParentCache.iPath.Compare(aParentPath) == 0)
+        {
+        aParentHandle = iParentCache.iHandle;
+        ret = ETrue;
+        }
+    else
+        {
+        aParentHandle = KMTPHandleNone;
+        }
+    
+    return ret;
+    }
+
+void CMTPImageDataProvider::SetCacheParentHandle(const TDesC& aParentPath, TUint32 aParentHandle)
+    {
+    iParentCache.iPath.Copy(aParentPath);
+    iParentCache.iHandle = aParentHandle;
+    }
+
+void CMTPImageDataProvider::AppendDeleteObjectsArrayL(const TDesC& aSuid)
+    {
+    iDeleteObjectsArray.AppendL(aSuid.AllocLC());
+    CleanupStack::Pop();
+    }
+
+void CMTPImageDataProvider::HandleDeleteObjectsArray()
+    {
+    for ( TInt i = 0; i < iDeleteObjectsArray.Count(); i++ )
+        {
+        HBufC* object = iDeleteObjectsArray[i];
+        TInt err = Framework().Fs().Delete(object->Des());
+        __FLOG_2(_L8("delete left objects %d error code is %d \n"), i, err );
+        
+        if ( err == KErrNone )
+            {
+            iDeleteObjectsArray.Remove(i);
+            --i;
+            delete object;
+            object = NULL;
+            }
+        }
+    }