imagehandlingutilities/thumbnailmanager/thumbnailserver/src/thumbnailserversession.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 26 Jan 2010 15:18:05 +0200
changeset 0 2014ca87e772
child 1 235a7fc86938
permissions -rw-r--r--
Revision: 201004

/*
* 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:  Server side session for Thumbnail Manager Server
 *
*/

#include <imageconversion.h> 

#include "thumbnailserversession.h"
#include "thumbnailserver.h"
#include "thumbnailtaskprocessor.h"
#include "thumbnailmanagerconstants.h"
#include "thumbnailgeneratetask.h"
#include "thumbnailscaletask.h"
#include "thumbnaildecodetask.h"
#ifdef RD_MDS_2_5
#include "thumbnailmdsquerytask.h"
#endif // RD_MDS_2_5
#include "thumbnaillog.h"
#include "thumbnailpanic.h"

#include "thumbnailcenrep.h"

// ======== MEMBER FUNCTIONS ========

// ---------------------------------------------------------------------------
// CThumbnailServerSession::CThumbnailServerSession()
// C++ default constructor can NOT contain any code, that might leave.
// ---------------------------------------------------------------------------
//
CThumbnailServerSession::CThumbnailServerSession(): CSession2()
    {
    iBitmapHandle = 0;
    }


// ---------------------------------------------------------------------------
// CThumbnailServerSession::~CThumbnailServerSession()
// Destructor.
// ---------------------------------------------------------------------------
//
CThumbnailServerSession::~CThumbnailServerSession()
    {
    Server()->DropSession(this);
    }


// -----------------------------------------------------------------------------
// CThumbnailServerSession::DispatchMessageL()
// Message dispatcher.
// -----------------------------------------------------------------------------
//
TInt CThumbnailServerSession::DispatchMessageL( const RMessage2& aMessage )
    {
    TInt err( KErrNone );

    switch ( aMessage.Function())
        {
        case ERequestThumbByFileHandleAsync:
                {
                RequestThumbByFileHandleAsyncL( aMessage );
                break;
                }
        case ERequestThumbByPathAsync:
                {
                RequestThumbByPathAsyncL( aMessage );
                break;
                }
        case ERequestSetThumbnailByBuffer:
                {
                RequestSetThumbnailByBufferL( aMessage );
                break;
                }
        case ERequestSetThumbnailByBitmap:
                {
                RequestSetThumbnailByBitmapL( aMessage );
                break;
                }                
        case EReleaseBitmap:
                {
                ReleaseBitmap( aMessage );
                break;
                }
        case ECancelRequest:
                {
                err = CancelRequest( aMessage );
                break;
                }
        case EChangePriority:
                {
                err = ChangePriority( aMessage );
                break;
                }
        case ECreateThumbnails:
                {
                CreateThumbnailsL( aMessage );
                break;
                }
        case EDeleteThumbnails:
                {
                DeleteThumbnailsL( aMessage );
                break;
                }
        case EDeleteThumbnailsById:
                {
                DeleteThumbnailsByIdL( aMessage );
                break;
                }                
        case EGetMimeTypeBufferSize:
                {
                GetMimeTypeBufferSizeL( aMessage );
                break;
                }
        case EGetMimeTypeList:
                {
                GetMimeTypeListL( aMessage );
                break;
                }
        case ERequestThumbByIdAsync:
                {
                RequestThumbByIdAsyncL( aMessage );
                break;
                }
        case EUpdateThumbnails:
                {
                UpdateThumbnailsL( aMessage );
                break;
                }                  
        default:
                {
                err = KErrUnknown;
                break;
                }
        }

    return err;
    }


// ---------------------------------------------------------------------------
// CThumbnailServerSession::CreateL()
// ---------------------------------------------------------------------------
//
void CThumbnailServerSession::CreateL()
    {
    Server()->AddSession();
    }


// -----------------------------------------------------------------------------
// CThumbnailServerSession::ServiceL()
// Handles service request messages from clients.
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::ServiceL( const RMessage2& aMessage )
    {
    __ASSERT_DEBUG( !iMessage.Handle(), ThumbnailPanic(
        EThumbnailMessageNotCompleted ));
    if ( iMessage.Handle())
        {
        iMessage.Complete( KErrUnknown );
        iMessage = RMessage2();
        }
    iMessage = aMessage;

    // clean up possible trash
    if (iBitmapHandle)
        {
        Server()->DeleteBitmapFromPool( iBitmapHandle );
        iBitmapHandle = 0;
        }
    delete iBitmap;
    iBitmap = NULL;
    delete iBuffer;
    iBuffer = NULL;
    iOriginalSize = TSize();
    
    TInt ret = KErrNone;

    TRAPD( err, 
        {
        ret = DispatchMessageL( aMessage ); 
        }
     );
    if ( iMessage.Handle())
        {
        iMessage.Complete( ConvertSqlErrToE32Err( err != KErrNone ? err : ret ));
        iMessage = RMessage2();
        }
    else
    	{
    	return;
    	}
    }


// -----------------------------------------------------------------------------
// CThumbnailServerSession::Server()
// Returns the server pointer.
// -----------------------------------------------------------------------------
//
CThumbnailServer* CThumbnailServerSession::Server()
    {
    return ( CThumbnailServer* )( CSession2::Server());
    }


// -----------------------------------------------------------------------------
// CThumbnailServerSession::Cancel()
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::Cancel()
    {
    }


// -----------------------------------------------------------------------------
// CThumbnailServerSession::UpdateThumbnailsL()
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::UpdateThumbnailsL( const RMessage2& aMessage )
    {
    TN_DEBUG1( "CThumbnailServerSession::UpdateThumbnailsL()" );
    
    if(aMessage.Int1() != KCheckValue)
       {
       TN_DEBUG1( "CThumbnailServerSession::UpdateThumbnailsL() - error in aMessage - leaving" );
       User::Leave(KErrArgument);
       }
    
    // read message params
    aMessage.ReadL( 0, iRequestParams );
    const TThumbnailRequestParams& params = iRequestParams();
    
    TBool finished = Server()->UpdateThumbnailsL( params.iThumbnailId, params.iFileName, params.iOrientation, params.iModified );
    
    if (finished)
        {
        TN_DEBUG1( "CThumbnailServerSession::UpdateThumbnailsL() - finished" );
        
        aMessage.Complete( KErrNone );
        }
    else
        {
        TN_DEBUG1( "CThumbnailServerSession::UpdateThumbnailsL() - need to recreate thumbs" );
        
        // need to create new thumbs
        aMessage.Complete( KThumbnailErrThumbnailNotFound );
        }
    
    iMessage = RMessage2();
    }

// -----------------------------------------------------------------------------
// CThumbnailServerSession::RequestThumbByIdAsyncL()
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::RequestThumbByIdAsyncL( const RMessage2&
    aMessage )
    {
#ifdef _DEBUG
    TTime aStart, aStop;
    aStart.UniversalTime();
#endif
    
    TN_DEBUG1( "CThumbnailServerSession::RequestThumbByIdAsyncL() - begin" );
    
    if(aMessage.Int1() != KCheckValue)
       {
       TN_DEBUG1( "CThumbnailServerSession::RequestThumbByIdAsync() - error in aMessage - leaving" );
       User::Leave(KErrArgument);
       }

    aMessage.ReadL( 0, iRequestParams );
    const TThumbnailRequestParams& params = iRequestParams();
    TRAPD( err, Server()->FetchThumbnailL( params.iThumbnailId, iBitmap, iBuffer,
                                           params.iThumbnailSize, iOriginalSize ));
    if ( !err && iBitmap )
        {
        TN_DEBUG1( 
            "CThumbnailServerSession::RequestThumbByIdAsyncL() - found existing thumbnail- bitmap" );

        ProcessBitmapL();
        }
    else if ( !err && iBuffer)
        {
        TN_DEBUG1( 
             "CThumbnailServerSession::RequestThumbByIdAsyncL() - found existing thumbnail- jpeg" );
        
        CThumbnailDecodeTask* task = new( ELeave )CThumbnailDecodeTask( Server()
                 ->Processor(), * Server(), iBuffer, params.iPriority, params.iDisplayMode );
        
        CleanupStack::PushL( task );
        task->SetMessageData( TThumbnailServerRequestId( this, params.iRequestId ), iMessage );
        Server()->QueueTaskL( task );
        CleanupStack::Pop( task ); // owned by processor now
        
        // Decode task is now responsible for completing the message
        iMessage = RMessage2();
        
        //CThumbnailDecodeTask is responsible freeing
        iBuffer = NULL;
        }
    else if( err == KErrCompletion )                
        {
        // If thumbnail of requested size is blacklisted, fetching is left with KErrCompletion
        TN_DEBUG1( 
            "CThumbnailServerSession::RequestThumbByIdAsyncL() - thumbnail blacklisted" );
        aMessage.Complete( err );
        iMessage = RMessage2();
        }
    else                
        {
        TN_DEBUG2( 
            "CThumbnailServerSession::RequestThumbByIdAsyncL() - thumbnail not found ( query path from MDS ), err=%d ", err );

#ifdef RD_MDS_2_5        
        // try to query path from MDS
        CThumbnailMDSQueryTask* task = new( ELeave )CThumbnailMDSQueryTask(
                Server()->Processor(), params.iPriority + 1, Server()->GetMdESession(), *Server());
        
        CleanupStack::PushL( task );
        task->QueryPathByIdL(params.iThumbnailId);
        task->SetMessageData( TThumbnailServerRequestId( this, params.iRequestId ), iMessage );
        Server()->QueueTaskL( task );
        CleanupStack::Pop( task ); // owned by processor now
        
        // query task is now responsible for completing the message
        iMessage = RMessage2();
#else
        User::Leave(KThumbnailErrThumbnailNotFound);
#endif // RD_MDS_2_5
        
        }   
    
#ifdef _DEBUG
    aStop.UniversalTime();
    TN_DEBUG2( "CThumbnailStore::RequestThumbByIdAsyncL() request took %d ms", (TInt)aStop.MicroSecondsFrom(aStart).Int64()/1000 );
#endif 
    
    TN_DEBUG1("CThumbnailServerSession::RequestThumbByIdAsyncL() - end" );
    }

// -----------------------------------------------------------------------------
// CThumbnailServerSession::RequestThumbByFileHandleAsync()
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::RequestThumbByFileHandleAsyncL( const RMessage2&
    aMessage )
    {
    TN_DEBUG1( "CThumbnailServerSession::RequestThumbByFileHandleAsyncL()" );
    
    if(aMessage.Int1() != KCheckValue)
       {
       TN_DEBUG1( "CThumbnailServerSession::RequestThumbByFileHandleAsync() - error in aMessage - leaving" );
       User::Leave(KErrArgument);
       }
    
    aMessage.ReadL( 0, iRequestParams );
    const TThumbnailRequestParams& params = iRequestParams();

    RFile64 file;
    User::LeaveIfError( file.AdoptFromClient( aMessage, 2, 3 ));
    
    ResolveMimeTypeL(&file);
    
    if(params.iThumbnailSize == EFullScreenThumbnailSize ||
       params.iThumbnailSize == EGridThumbnailSize ||
       params.iThumbnailSize == EListThumbnailSize )
        {
        TInt sourceType = TThumbnailPersistentSize::EUnknownSourceType;
        sourceType = Server()->SourceTypeFromMimeType( params.iMimeType );
        ModifyThumbnailSize(sourceType);
        }
    
    // CreateThumbnails
    if (params.iControlFlags == EThumbnailGeneratePersistentSizesOnly)
        {
        CleanupClosePushL( file );
        CreateGenerateTaskFromFileHandleL( &file );
        CleanupStack::Pop( &file );         
        }
    // single thumbnail request
    else
        {
        TRAPD( err, FetchThumbnailL());
        
        if ( !err && iBitmap )
            {
            TN_DEBUG1( "CThumbnailServerSession::RequestThumbByFileHandleAsyncL() - found existing thumbnail - bitmap " );

            // Thumbnail already stored
            file.Close();
            TN_DEBUG1("CThumbnailServerSession::RequestThumbByFileHandleAsyncL - file handle closed");

            ProcessBitmapL();
            }
        else if ( (err == KErrNotFound || err == KErrAccessDenied) && 
                 !(params.iFlags& CThumbnailManager::EDoNotCreate) )
            {
            CreateGenerateTaskFromFileHandleL( &file);
            }
        else if (!err && iBuffer)
            {
            TN_DEBUG1( 
                "CThumbnailServerSession::RequestThumbByFileHandleAsyncL() - found existing thumbnail - jpeg " );
            
            CThumbnailDecodeTask* task = new( ELeave )CThumbnailDecodeTask( Server()
                        ->Processor(), * Server(), iBuffer, params.iPriority, params.iDisplayMode );
            
            CleanupStack::PushL( task );
            task->SetMessageData( TThumbnailServerRequestId( this, params.iRequestId ), iMessage );
            Server()->QueueTaskL( task );
            CleanupStack::Pop( task ); // owned by processor now
            
            // Decode task is now responsible for completing the message
            iMessage = RMessage2();
            
            //CThumbnailDecodeTask is responsible freeing
            iBuffer = NULL;
            file.Close();
            TN_DEBUG1("CThumbnailServerSession::RequestThumbByFileHandleAsyncL - file handle closed");
            }
        else
            {
            TN_DEBUG2( 
                "CThumbnailServerSession::RequestThumbByFileHandleAsyncL() - thumbnail not found, err=%d", err );
            aMessage.Complete( ConvertSqlErrToE32Err( err ));
            iMessage = RMessage2();
            }     
        }
    }

// -----------------------------------------------------------------------------
// CThumbnailServerSession::RequestThumbByPathAsync()
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::RequestThumbByPathAsyncL( const RMessage2&
    aMessage )
    {
    TN_DEBUG1( "CThumbnailServerSession::RequestThumbByPathAsyncL()" );
    
#ifdef _DEBUG
    TTime aStart, aStop;
    aStart.UniversalTime();
#endif
    
    if(aMessage.Int1() != KCheckValue)
       {
       TN_DEBUG1( "CThumbnailServerSession::RequestThumbByPathAsync() - error in aMessage - leaving" );
       User::Leave(KErrArgument);
       }

    aMessage.ReadL( 0, iRequestParams );
    const TThumbnailRequestParams& params = iRequestParams();
    
    ResolveMimeTypeL(NULL);
    
    if(params.iThumbnailSize == EFullScreenThumbnailSize ||
       params.iThumbnailSize == EGridThumbnailSize ||
       params.iThumbnailSize == EListThumbnailSize )
        {
        TInt sourceType = TThumbnailPersistentSize::EUnknownSourceType;
        sourceType = Server()->SourceTypeFromMimeType( params.iMimeType );
        ModifyThumbnailSize(sourceType);
        }
    
    // should always be true
    if (params.iControlFlags != EThumbnailGeneratePersistentSizesOnly)
		{
	    TRAPD( err, FetchThumbnailL());
	    
	    if ( !err && iBitmap )
	        {
	        TN_DEBUG1( 
	            "CThumbnailServerSession::RequestThumbByPathAsyncL() - found existing thumbnail- bitmap" );

	        ProcessBitmapL();
	        }
	    else if ( !err && iBuffer)
	        {
	        TN_DEBUG1( 
	            "CThumbnailServerSession::RequestThumbByPathAsyncL() - found existing thumbnail- jpeg" );
	        
	        CThumbnailDecodeTask* task = new( ELeave )CThumbnailDecodeTask( Server()
	               ->Processor(), * Server(), iBuffer, params.iPriority, params.iDisplayMode );
	        
	        CleanupStack::PushL( task );
	        task->SetMessageData( TThumbnailServerRequestId( this, params.iRequestId ), iMessage );
	        Server()->QueueTaskL( task );
	        CleanupStack::Pop( task ); // owned by processor now
	        
	        // Decode task is now responsible for completing the message
	        iMessage = RMessage2();
	        
	        //CThumbnailDecodeTask is responsible freeing
	        iBuffer = NULL;
	        }
	    else if( err == KErrCompletion )
	        {
            // If thumbnail of requested size is blacklisted, fetching is left with KErrCompletion
            TN_DEBUG1( 
                "CThumbnailServerSession::RequestThumbByIdAsyncL() - thumbnail blacklisted" );
            aMessage.Complete( err );
            iMessage = RMessage2();
	        }
	    else 
	        {
	        TN_DEBUG2( 
	            "CThumbnailServerSession::RequestThumbByPathAsyncL() - thumbnail not found, err = %d", err );
	        
	        if ( (err == KErrNotFound || err == KErrAccessDenied) && 
	            !(params.iFlags& CThumbnailManager::EDoNotCreate) )
	            {
	            // Special error code so that the client side can open the file
	            // and retry the request using file handle
	            err = KThumbnailErrThumbnailNotFound;
	            }
	        else
	            {
                User::Leave(err);
                }

#ifdef RD_MDS_2_5	        
            // try to query ID from MDS
            CThumbnailMDSQueryTask* task = new( ELeave )CThumbnailMDSQueryTask(
                    Server()->Processor(), params.iPriority + 1, Server()->GetMdESession(), *Server());
            
            CleanupStack::PushL( task );
            task->SetUpdateToDb( EFalse );
            task->QueryIdByPathL( params.iFileName );
            task->SetMessageData( TThumbnailServerRequestId( this, params.iRequestId ), iMessage );
            Server()->QueueTaskL( task );
            CleanupStack::Pop( task ); // owned by processor now
            
            // query task is now responsible for completing the message
            iMessage = RMessage2();	            
#else
            User::Leave(err);
#endif // RD_MDS_2_5
	        
	        }   
	   }
    
#ifdef _DEBUG
    aStop.UniversalTime();
    TN_DEBUG2( "CThumbnailStore::RequestThumbByPathAsyncL() request took %d ms", (TInt)aStop.MicroSecondsFrom(aStart).Int64()/1000 );
#endif
    }   
    
void CThumbnailServerSession::RequestSetThumbnailByBufferL( const RMessage2& aMessage )
    {
    TN_DEBUG1( "CThumbnailServerSession::RequestSetThumbnailByBufferL()" );
    
    if(aMessage.Int3() != KCheckValue)
        {
        TN_DEBUG1( "CThumbnailServerSession::RequestSetThumbnailByBufferL() - error in aMessage - leaving" );
        User::Leave(KErrArgument);
        }
      
    aMessage.ReadL( 0, iRequestParams );
    const TThumbnailRequestParams& params = iRequestParams();
    
    if(params.iThumbnailSize != EUnknownThumbnailSize)
        {
        Server()->DeleteThumbnailsL( params.iTargetUri);
        }
    
    if(params.iThumbnailSize == EFullScreenThumbnailSize ||
       params.iThumbnailSize == EGridThumbnailSize ||
       params.iThumbnailSize == EListThumbnailSize )
       {
       TInt sourceType = TThumbnailPersistentSize::EUnknownSourceType;
       TDataType mimetype;
       Server()->MimeTypeFromFileExt( params.iTargetUri, mimetype );
       sourceType = Server()->SourceTypeFromMimeType( mimetype );   
       ModifyThumbnailSize(sourceType);
       }
    
    TInt bufferSize = aMessage.Int2();
    HBufC8* buffer = HBufC8::NewMaxLC( bufferSize );
    TPtr8 ptr = buffer->Des();
    aMessage.ReadL( 1 /* buffer pointer */, ptr );
    
    CreateGenerateTaskFromBufferL( buffer );
    CleanupStack::Pop( buffer );
    }

void CThumbnailServerSession::RequestSetThumbnailByBitmapL( const RMessage2& aMessage )
    {
    TN_DEBUG1( "CThumbnailServerSession::RequestSetThumbnailByBitmapL()" );

    if(aMessage.Int2() != KCheckValue)
        {
        TN_DEBUG1( "CThumbnailServerSession::RequestSetThumbnailByBitmapL() - error in aMessage - leaving" );
        User::Leave(KErrArgument);
        }
        
    aMessage.ReadL( 0, iRequestParams );
    const TThumbnailRequestParams& params = iRequestParams();
    
    TInt bitmapHandle = aMessage.Int1();
    TThumbnailServerRequestId &reqId = (TThumbnailServerRequestId&)params.iRequestId;
    
    // get bitmap
    CFbsBitmap* bitmap = new( ELeave )CFbsBitmap();
    CleanupStack::PushL( bitmap );
    User::LeaveIfError( bitmap->Duplicate( bitmapHandle ) );
    Server()->AddBitmapToPoolL( reqId.iSession, bitmap );
    CleanupStack::Pop( bitmap );
    iBitmapHandle = bitmap->Handle();
    
    RArray < TThumbnailPersistentSize >* missingSizes = NULL;
    
    // source type
    TDataType mimeType;
    TInt sourceType = 0;
    TInt err = Server()->MimeTypeFromFileExt( params.iTargetUri, mimeType );
    TBool missingIDs(EFalse);
    
    // get missing sizes
    if ( err == KErrNone && ( params.iControlFlags & EThumbnailGeneratePersistentSizesOnly ) != 0 )
        {
        sourceType = Server()->SourceTypeFromMimeType( mimeType );
        
        missingSizes = new (ELeave) RArray < TThumbnailPersistentSize >;
        CleanupClosePushL( *missingSizes );
    
        Server()->GetMissingSizesAndIDsL( params.iTargetUri, sourceType, *missingSizes, missingIDs);
            
        if ( missingSizes->Count() == 0)
            {
            // all thumbs already exist
            CleanupStack::PopAndDestroy( missingSizes );
            delete missingSizes;
            missingSizes = NULL;
            }            
        }
    
    // if missing sizes, create scale tasks
    if ( missingSizes )
        {
        const TInt count = missingSizes->Count();
        
        TSize bitmapSize = bitmap->SizeInPixels();
        
        for ( TInt i( 0 ); i < count; i++ )
            {           
            if( bitmapSize.iWidth < bitmapSize.iHeight )
               {
               TInt height = (*missingSizes)[i].iSize.iHeight;
               (*missingSizes)[i].iSize.iHeight = (*missingSizes)[i].iSize.iWidth;
               (*missingSizes)[i].iSize.iWidth = height;
               TN_DEBUG1( "CThumbnailServerSession::RequestSetThumbnailByBitmapL() - portrait");
               }
            
            CThumbnailScaleTask* scaleTask = CThumbnailScaleTask::NewL( Server()->Processor(),
                *Server(), params.iTargetUri, bitmap, bitmapSize,
                (*missingSizes)[i].iSize, (*missingSizes)[i].iCrop, params.iDisplayMode,
                KMaxPriority, KNullDesC, (*missingSizes)[i].iType, params.iThumbnailId, EFalse, EFalse );
            CleanupStack::PushL( scaleTask );
            scaleTask->SetDoStore( ETrue );
            //increase priority, scale needs to run before ID update below
            scaleTask->SetPriority( params.iPriority + 1 );
            Server()->Processor().AddTaskL( scaleTask );
            CleanupStack::Pop( scaleTask );
            
            if( i == count-1 )
                {
                // scaleTask is now responsible for completing the RMessage
                scaleTask->SetMessageData( reqId, iMessage );
                iMessage = RMessage2();
                }
            }
        
        TN_DEBUG3("CThumbnailServerSession::RequestSetThumbnailByBitmapL() ID = %d, missingIDs = %d", params.iThumbnailId, missingIDs);
        }
    else
        {
        // complete message
        aMessage.Complete( KErrNone );
        iMessage = RMessage2();
        }
    
    if ( missingSizes )
        {
        CleanupStack::PopAndDestroy( missingSizes );
        delete missingSizes;
        missingSizes = NULL;
        }
    
    Server()->DeleteBitmapFromPool( iBitmapHandle );
    iBitmapHandle = 0;
    bitmap = NULL;
    }

// -----------------------------------------------------------------------------
// CThumbnailServerSession::CreateThumbnailsL()
// Create thumbnails for given object file
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::CreateThumbnailsL( const RMessage2& aMessage )
    {
    RFile64 file;
    CleanupClosePushL( file );
	User::LeaveIfError( file.AdoptFromClient( aMessage, 1, 2 ));

	CreateGenerateTaskFromFileHandleL( &file);
        
	CleanupStack::Pop( &file );
    }      

 
// -----------------------------------------------------------------------------
// CThumbnailServerSession::CreateGenerateTaskL()
// Create a task to generate a new thumbnail
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::CreateGenerateTaskFromFileHandleL( RFile64* aFile)
    {
    const TThumbnailRequestParams& params = iRequestParams();

    TN_DEBUG2( 
        "CThumbnailServerSession::CreateGenerateTaskFromFileHandleL() -- create thumbnail generation task for %S", &params.iFileName );
      
    TBool missingIDs = EFalse;
    
    RArray < TThumbnailPersistentSize >* missingSizes = NULL;
    
    // get missing sizes
    if ( ( params.iControlFlags & EThumbnailGeneratePersistentSizesOnly ) != 0 )
        {
        TInt sourceType = TThumbnailPersistentSize::EUnknownSourceType;
        sourceType = Server()->SourceTypeFromMimeType( params.iMimeType );
        missingSizes = new (ELeave) RArray < TThumbnailPersistentSize >;
        CleanupClosePushL( *missingSizes );
        
        Server()->GetMissingSizesAndIDsL( params.iFileName, sourceType, *missingSizes, missingIDs );
#ifdef RD_MDS_2_5        
        if( missingIDs )
            {
            TN_DEBUG1("CThumbnailServerSession::CreateGenerateTaskFromFileHandleL() some IDs missing");
            
            if( params.iThumbnailId == KNoId)
                {
                TN_DEBUG1("CThumbnailServerSession::CreateGenerateTaskFromFileHandleL() query fro MDS");
                // try to query ID from MDS
                CThumbnailMDSQueryTask* task = new( ELeave )CThumbnailMDSQueryTask(
                        Server()->Processor(), params.iPriority + 1, Server()->GetMdESession(), *Server());
                
                CleanupStack::PushL( task );
                task->QueryIdByPathL( params.iFileName );
                
                task->SetMessageData( TThumbnailServerRequestId( this, params.iRequestId ) );
                Server()->QueueTaskL( task );
                CleanupStack::Pop( task ); // owned by processor now
                TN_DEBUG1("CThumbnailServerSession::CreateGenerateTaskFromFileHandleL() query from MDS queued" );
                }
            else
                {
                TN_DEBUG2("CThumbnailServerSession::CreateGenerateTaskFromFileHandleL() got ID %d from params", params.iThumbnailId);
                TRAP_IGNORE( Server()->UpdateIDL(params.iFileName, params.iThumbnailId ) );
                }
            }
#endif // RD_MDS_2_5
        
        if ( missingSizes->Count() == 0)
            {
            // all thumbs already exist
            CleanupStack::PopAndDestroy( missingSizes );
            delete missingSizes;
            if( aFile )
               {
               aFile->Close();
               }
            return;
            }            
        }
    
    // priority
    TInt priority = params.iPriority;
    if ( priority > KMaxGeneratePriority )
        {
        priority = KMaxGeneratePriority;
        }
    
    // create new task
    if( !aFile)
        {
        User::Leave( KErrArgument );
        }
    CleanupClosePushL( *aFile );
    CThumbnailGenerateTask* task = new( ELeave )CThumbnailGenerateTask( Server()
        ->Processor(), * Server(), aFile, NULL, &params.iMimeType, params.iFlags,
        params.iSize, params.iDisplayMode, priority, missingSizes, params.iTargetUri,
        params.iThumbnailSize, params.iThumbnailId, params.iQualityPreference );

    // do not store bitmaps to server pool when generating only
    if( params.iControlFlags & EThumbnailGeneratePersistentSizesOnly )
        {
        task->ScaledBitmapToPool( EFalse );
        }
        
    CleanupStack::Pop( aFile );
    
    CleanupStack::PushL( task );
    task->SetMessageData( TThumbnailServerRequestId( this, params.iRequestId ),
        iMessage );
    Server()->QueueTaskL( task );
    CleanupStack::Pop( task ); // owned by processor now
    
    if ( missingSizes )
        {
        CleanupStack::Pop( missingSizes );
        }

    // Generate task is now responsible for completing the message
    iMessage = RMessage2();
    } 
// -----------------------------------------------------------------------------
// CThumbnailServerSession::CreateGenerateTaskL()
// Create a task to generate a new thumbnail
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::CreateGenerateTaskFromBufferL( TDesC8* aBuffer )
    {
    const TThumbnailRequestParams& params = iRequestParams();

    TN_DEBUG2( 
        "CThumbnailServerSession::CreateGenerateTaskFromBufferL() -- create thumbnail generation task for %S", &params.iTargetUri );
  
    if(aBuffer && params.iMimeType.Des().Match( KVideoMime ) == 0 )
        {
        User::Leave( KErrNotSupported );
        }
    
    TInt sourceType = TThumbnailPersistentSize::EUnknownSourceType;
    
    TDataType mimetype;
    TInt ret = Server()->MimeTypeFromFileExt( params.iTargetUri, mimetype );
    if(ret == KErrNotFound)
        {
        Server()->Fs().ShareProtected();
        RFile64 file;
        CleanupClosePushL( file );
        
        User::LeaveIfError( file.Open( Server()->Fs(), params.iTargetUri, EFileShareReadersOrWriters )); 
        TN_DEBUG2( "CThumbnailServerSession::CreateGenerateTaskFromBufferL - file handle opened for %S", &params.iFileName );
                
        mimetype = Server()->ResolveMimeTypeL(file);
                
        file.Close();
        TN_DEBUG1("CThumbnailServerSession::CreateGenerateTaskFromBufferL - file handle closed");
        
        CleanupStack::Pop( &file );    
        }
        
    sourceType = Server()->SourceTypeFromMimeType( mimetype );    
    
    RArray < TThumbnailPersistentSize >* missingSizes = NULL;
    
    // get missing sizes
    if ( ( params.iControlFlags & EThumbnailGeneratePersistentSizesOnly ) != 0 )
        {
        missingSizes = new (ELeave) RArray < TThumbnailPersistentSize >;
        CleanupClosePushL( *missingSizes );
        
        TBool missingIDs;
        Server()->GetMissingSizesAndIDsL( params.iTargetUri, sourceType, *missingSizes, missingIDs );
            
        if ( missingSizes->Count() == 0)
            {
            // all thumbs already exist
            CleanupStack::PopAndDestroy( missingSizes );
            delete missingSizes;
            if ( aBuffer)
               {
               delete aBuffer;
               aBuffer = NULL; 
               }
            return;
            }            
        }
    
    // priority
    TInt priority = params.iPriority;
    if ( priority > KMaxGeneratePriority )
        {
        priority = KMaxGeneratePriority;
        }
    
    // create new task
    if( !aBuffer)
        {
        User::Leave( KErrArgument );
        }
    
    CThumbnailGenerateTask* task = new( ELeave )CThumbnailGenerateTask( Server()
        ->Processor(), * Server(), NULL, aBuffer, &params.iMimeType, params.iFlags,
        params.iSize, params.iDisplayMode, priority, missingSizes, params.iTargetUri,
        params.iThumbnailSize, params.iThumbnailId, params.iQualityPreference );

    // do not store bitmaps to server pool when generating only
    if( params.iControlFlags & EThumbnailGeneratePersistentSizesOnly )
        {
        task->ScaledBitmapToPool( EFalse );
        }  
    
    CleanupStack::PushL( task );
    task->SetMessageData( TThumbnailServerRequestId( this, params.iRequestId ),
        iMessage );
    Server()->QueueTaskL( task );
    CleanupStack::Pop( task ); // owned by processor now
    
    if ( missingSizes )
        {
        CleanupStack::Pop( missingSizes );
        }

    // Generate task is now responsible for completing the message
    iMessage = RMessage2();
    } 
// -----------------------------------------------------------------------------
// CThumbnailServerSession::FetchThumbnailL()
// Fetch thumbnail data from database
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::FetchThumbnailL()
    {
    TN_DEBUG1("CThumbnailServerSession::FetchThumbnailL()");
    __ASSERT_DEBUG( !iBitmap, ThumbnailPanic( EThumbnailBitmapNotReleased ));

    delete iBitmap;
    iBitmap = NULL;

    TThumbnailRequestParams& params = iRequestParams();
    
    if ( params.iThumbnailSize != EUnknownThumbnailSize &&
         params.iThumbnailSize != ECustomThumbnailSize )
        {
        TThumbnailPersistentSize & persistentSize = Server()->PersistentSizeL( params.iThumbnailSize );
        params.iSize = persistentSize.iSize;
        }
    
    if( params.iFileName != KNullDesC )
        {
        TN_DEBUG4( "CThumbnailServerSession::FetchThumbnailL( TNId==%d ThumbnailSize=%d ( Path=%S ))", 
                params.iThumbnailId, params.iThumbnailSize, &params.iFileName );
        Server()->FetchThumbnailL( params.iFileName, iBitmap, iBuffer, params.iThumbnailSize, iOriginalSize);
        }
    else
        {
        TN_DEBUG3( "CThumbnailServerSession::FetchThumbnailL(Path=%S ThumbnailSize=%d)", 
                        &params.iFileName, params.iThumbnailSize );
        Server()->FetchThumbnailL( params.iThumbnailId, iBitmap, iBuffer,  params.iThumbnailSize, iOriginalSize );
        }
#ifdef _DEBUG
    if( iBitmap)
        {
        TN_DEBUG4( "CThumbnailServerSession::FetchThumbnailL() size %d x %d displaymode %d", iBitmap->SizeInPixels().iWidth, iBitmap->SizeInPixels().iHeight, iBitmap->DisplayMode());
        }
#endif
    }

// -----------------------------------------------------------------------------
// CThumbnailServerSession::ProcessBitmapL()
// Process a fetched bitmap by creating scale tasks or by returning the
// bitmap as such.
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::ProcessBitmapL()
    {   
    TThumbnailRequestParams& params = iRequestParams();
    
    // in import case store bitmap
    if (params.iTargetUri != KNullDesC)
        {
        Server()->StoreThumbnailL( params.iTargetUri, iBitmap, iOriginalSize,
                                   params.iFlags& CThumbnailManager::ECropToAspectRatio, params.iThumbnailSize, params.iThumbnailId );
        }
    
    // No need to scale, return iBitmap directly
    Server()->AddBitmapToPoolL( this, iBitmap );
    CFbsBitmap* bitmap = iBitmap;
    iBitmap = NULL; // owned by server now
    
    params.iBitmapHandle = bitmap->Handle();
    const TSize bitmapSize = bitmap->SizeInPixels();

    if ( params.iQualityPreference == CThumbnailManager
        ::EOptimizeForQualityWithPreview && bitmapSize.iWidth <
        params.iSize.iWidth && bitmapSize.iHeight < params.iSize.iHeight &&
        bitmapSize.iWidth < iOriginalSize.iWidth && bitmapSize.iHeight <
        iOriginalSize.iHeight )
        {
        // This is a non-scaled preview bitmap
        params.iControlFlags = EThumbnailPreviewThumbnail;
        }

    if ( iMessage.Handle() )
        {
        iMessage.WriteL( 0, iRequestParams );
        iMessage.Complete( KErrNone );
        iMessage = RMessage2();
        }            
    }

// -----------------------------------------------------------------------------
// CThumbnailServerSession::ReleaseBitmap()
// Release bitmap from bitmap pool
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::ReleaseBitmap( const RMessage2& aMessage )
    {
    TN_DEBUG2( "CThumbnailServerSession::ReleaseBitmap(%d)", aMessage.Int0());
    Server()->DeleteBitmapFromPool( aMessage.Int0());
    }


// -----------------------------------------------------------------------------
// CThumbnailServerSession::CancelRequest()
// Cancel pending request.
// -----------------------------------------------------------------------------
//
TInt CThumbnailServerSession::CancelRequest( const RMessage2& aMessage )
    {
    const TThumbnailServerRequestId requestId( this, aMessage.Int0());
    const TInt err = Server()->DequeTask( requestId );
    TN_DEBUG4( 
        "CThumbnailServerSession::CancelRequest(0x%08x/%d) - returning %d",
        requestId.iSession, requestId.iRequestId, err );
    return err;
    }

// -----------------------------------------------------------------------------
// CThumbnailServerSession::ChangePriority()
// Change priority of pending request.
// -----------------------------------------------------------------------------
//
TInt CThumbnailServerSession::ChangePriority( const RMessage2& aMessage )
    {
    const TThumbnailServerRequestId requestId( this, aMessage.Int0());
    const TInt newPriority = aMessage.Int1();

    const TInt err = Server()->ChangeTaskPriority( requestId, newPriority );
    TN_DEBUG5( 
        "CThumbnailServerSession::ChangePriority(0x%08x/%d, %d) - returning %d",
        requestId.iSession, requestId.iRequestId, newPriority, err );
    return err;
    }

// -----------------------------------------------------------------------------
// CThumbnailServerSession::DeleteThumbnailsL()
// Delete thumbnails for given object file
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::DeleteThumbnailsL( const RMessage2& aMessage )
    {
    if(aMessage.Int2() != KCheckValue)
       {
       TN_DEBUG1( "CThumbnailServerSession::DeleteThumbnailsL() - error in aMessage - leaving" );
       User::Leave(KErrArgument);
       }
    
    HBufC* fileName = HBufC::NewLC( KMaxFileName );
    TPtr ptr = fileName->Des();
    aMessage.ReadL( 1, ptr );
    Server()->DeleteThumbnailsL( ptr );
    CleanupStack::PopAndDestroy( fileName );
    
    aMessage.Complete( KErrNone );
    iMessage = RMessage2();
    }

// -----------------------------------------------------------------------------
// CThumbnailServerSession::DeleteThumbnailsByIdL()
// Delete thumbnails by TThumbnailId.
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::DeleteThumbnailsByIdL( const RMessage2& aMessage )
    {
    if(aMessage.Int2() != KCheckValue)
       {
       TN_DEBUG1( "CThumbnailServerSession::DeleteThumbnailsByIdL() - error in aMessage - leaving" );
       User::Leave(KErrArgument);
       }
    
    // read message params
    aMessage.ReadL( 0, iRequestParams );
    const TThumbnailRequestParams& params = iRequestParams();
    
    TThumbnailId id = params.iThumbnailId;
    Server()->DeleteThumbnailsByIdL( id );
    
    aMessage.Complete( KErrNone );
    iMessage = RMessage2();
    }

// -----------------------------------------------------------------------------
// Get the required size (in characters) for a buffer that contains the
// list of supported MIME types
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::GetMimeTypeBufferSizeL( const RMessage2& aMessage
    )
    {
    TPckgBuf < TInt > buf;
    buf() = Server()->GetMimeTypeBufferSize();
    aMessage.WriteL( 0, buf );
    }

// -----------------------------------------------------------------------------
// Get the list of supported MIME types and store them in the buffer
// allocated by the client.
// -----------------------------------------------------------------------------
//
void CThumbnailServerSession::GetMimeTypeListL( const RMessage2& aMessage )
    {
    TInt len = aMessage.GetDesMaxLengthL( 0 );
    HBufC* buf = HBufC::NewLC( len );
    TPtr ptr = buf->Des();
    Server()->GetMimeTypeList( ptr );
    aMessage.WriteL( 0, * buf );
    CleanupStack::PopAndDestroy( buf );
    }

// ---------------------------------------------------------------------------
// CThumbnailServerSession::ModifyThumbnailSize
// ---------------------------------------------------------------------------
//
void CThumbnailServerSession::ModifyThumbnailSize( TInt aSourceType )   
    {
    TThumbnailRequestParams& params = iRequestParams();
    if(aSourceType == TThumbnailPersistentSize::EImage)
        {
        if(params.iThumbnailSize == EFullScreenThumbnailSize)
            {
            params.iThumbnailSize = EImageFullScreenThumbnailSize;
            }
        else if(params.iThumbnailSize == EGridThumbnailSize)
            {
            params.iThumbnailSize = EImageGridThumbnailSize;
            }
        else if(params.iThumbnailSize == EListThumbnailSize)
            {
            params.iThumbnailSize = EImageListThumbnailSize;
            }       
        }
    else if(aSourceType == TThumbnailPersistentSize::EVideo)
           {
           if(params.iThumbnailSize == EFullScreenThumbnailSize)
               {
               params.iThumbnailSize = EVideoFullScreenThumbnailSize;
               }
           else if(params.iThumbnailSize == EGridThumbnailSize)
               {
               params.iThumbnailSize = EVideoGridThumbnailSize;
               }
           else if(params.iThumbnailSize == EListThumbnailSize)
               {
               params.iThumbnailSize = EVideoListThumbnailSize;
               }       
           }
    else if(aSourceType == TThumbnailPersistentSize::EAudio)
           {
           if(params.iThumbnailSize == EFullScreenThumbnailSize)
               {
               params.iThumbnailSize = EAudioFullScreenThumbnailSize;
               }
           else if(params.iThumbnailSize == EGridThumbnailSize)
               {
               params.iThumbnailSize = EAudioGridThumbnailSize;
               }
           else if(params.iThumbnailSize == EListThumbnailSize)
               {
               params.iThumbnailSize = EAudioListThumbnailSize;
               }       
           }
    }

//------------------------------------------------------------------------
// CThumbnailServerSession::ModifyThumbnailSize
// ---------------------------------------------------------------------------
//
void CThumbnailServerSession::ResolveMimeTypeL( RFile64* aFile )
    { 
    TThumbnailRequestParams& params = iRequestParams();
    TInt res = 0;
        
    // mime type
    if ( params.iMimeType.Des8() == KNullDesC8 && !Server()->SupportedMimeType(params.iMimeType) )
       {
       // try parsing from file extension
       res = Server()->MimeTypeFromFileExt( params.iFileName, params.iMimeType );
       if ( res == KErrNotFound )
           {
          if( aFile )
             {
             // parsed type not in the list, resolve from file
             params.iMimeType = Server()->ResolveMimeTypeL(*aFile);
             }
          else
             {
             Server()->Fs().ShareProtected();
             RFile64 file;
             CleanupClosePushL( file );
             
             User::LeaveIfError( file.Open( Server()->Fs(), params.iFileName, EFileShareReadersOrWriters )); 
             TN_DEBUG2( "CThumbnailServerSession::ResolveMimeType - file handle opened for %S", &params.iFileName );
             
             params.iMimeType = Server()->ResolveMimeTypeL(file);
             
             file.Close();
             TN_DEBUG1("CThumbnailServerSession::ResolveMimeType - file handle closed");
             
             CleanupStack::Pop( &file );    
             }    
          }        
       }      
    }


// ---------------------------------------------------------------------------
// RThumbnailMessage::FilterSqlErr
// ---------------------------------------------------------------------------
//
TInt CThumbnailServerSession::ConvertSqlErrToE32Err( TInt aReason )
    {
    TInt e32Err;
    if ( aReason >=  - 144 )
    // magic: [-1..-144] is E32 error range 
        {
        // E32 error value or non-negative value
        e32Err = aReason;
        }
    else
        {
        switch ( aReason )
            {
            case KSqlErrGeneral:
                e32Err = KErrGeneral;
                break;
            case KSqlErrInternal:
                e32Err = KErrGeneral;
                break;
            case KSqlErrPermission:
                e32Err = KErrPermissionDenied;
                break;
            case KSqlErrAbort:
                e32Err = KErrAbort;
                break;
            case KSqlErrBusy:
                e32Err = KErrServerBusy;
                break;
            case KSqlErrLocked:
                e32Err = KErrLocked;
                break;
            case KSqlErrReadOnly:
                e32Err = KErrAccessDenied;
                break;
            case KSqlErrInterrupt:
                e32Err = KErrAbort;
                break;
            case KSqlErrIO:
                e32Err = KErrGeneral;
                break;
            case KSqlErrCorrupt:
                e32Err = KErrCorrupt;
                break;
            case KSqlErrNotFound:
                e32Err = KErrNotFound;
                break;
            case KSqlErrFull:
                e32Err = KErrOverflow;
                break;
            case KSqlErrCantOpen:
                e32Err = KErrCouldNotConnect;
                break;
            case KSqlErrProtocol:
                e32Err = KErrLocked;
                break;
            case KSqlErrEmpty:
                e32Err = KErrNotFound;
                break;
            case KSqlErrSchema:
                e32Err = KErrAbort;
                break;
            case KSqlErrTooBig:
                e32Err = KErrTooBig;
                break;
            case KSqlErrConstraint:
                e32Err = KErrGeneral;
                break;
            case KSqlErrMismatch:
                e32Err = KErrGeneral;
                break;
            case KSqlErrMisuse:
                e32Err = KErrGeneral;
                break;
            case KSqlErrRange:
                e32Err = KErrOverflow;
                break;
            case KSqlErrNotDb:
                e32Err = KErrCorrupt;
                break;
            case KSqlErrStmtExpired:
                e32Err = KErrAbort;
                break;
            default:
                e32Err = aReason;
            }
        }
    return e32Err;
    }

// End of file