taskswitcher/contextengine/tsfswpreviewprovider/wsplugin/src/previewprovidercrp.cpp
/*
* Copyright (c) 2008 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: Preview provider ECOM plugin
*
*/
#include <bldvariant.hrh>
#ifdef SYMBIAN_BUILD_GCE
#define NGA
#endif
#include "previewprovidercrp.h"
#include "previewmsg.h"
#include "previewprovidercrplogging.h"
#include <ecom/implementationproxy.h>
#include <s32mem.h> //RDesReadStream
#ifdef NGA
#include <graphics/wsscreendevice.h>
#endif
// CONSTANTS
const TInt KImpId( 0x20016BEC );
const TInt KMinTimeForOrientationSwitch = 1; // 1 second
// --------------------------------------------------------------------------
// CPreviewProviderCRP::CreateL
// --------------------------------------------------------------------------
//
CWsGraphicDrawer* CPreviewProviderCRP::CreateL()
{
CPreviewProviderCRP* crp = new (ELeave) CPreviewProviderCRP();
CleanupStack::PushL( crp );
crp->ConstructL();
CleanupStack::Pop( crp );
return crp;
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::ConstructL
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::ConstructL()
{
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::~CPreviewProviderCRP
// --------------------------------------------------------------------------
//
CPreviewProviderCRP::~CPreviewProviderCRP()
{
Env().UnregisterEventHandler( this );
iScreenshots.ResetAndDestroy();
iWgIds.Close();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::DoDraw
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::DoDraw( MWsGc& /*aGc*/, const TRect& /*aRect*/,
const TDesC8& /*aData*/) const
{
//draws nothing
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::HandleMessage
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::HandleMessage( const TDesC8& aData )
{
TRAP_IGNORE( DoHandleMessageL( aData ) );
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::DoHandleMessageL
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::DoHandleMessageL( const TDesC8& aData )
{
TSLOG_CONTEXT( DoHandleMessageL, TSLOG_LOCAL );
TSLOG_IN();
RDesReadStream in( aData );
switch( in.ReadInt32L() )
{
case NPreviewMsg::ERegister:
{
const TInt id = in.ReadInt32L();
Register( id );
}
break;
case NPreviewMsg::EUnregister:
{
const TInt id = in.ReadInt32L();
Unregister( id );
}
break;
case NPreviewMsg::EChangeScreen:
{
const TInt screen = in.ReadInt32L();
if ( Env().ScreenCount() )
{
iScreen = screen;
}
}
break;
case NPreviewMsg::ESetPreviewParam:
iScreenshotSize.iWidth = in.ReadInt32L();
iScreenshotSize.iHeight = in.ReadInt32L();
iScreenshotMode = static_cast<TDisplayMode>( in.ReadInt32L() );
break;
case NPreviewMsg::ETakePreview:
ScreenshotL();
break;
case NPreviewMsg::EAckPreviewReady:
RemoveScreenshot( in.ReadInt32L() );
break;
}
TSLOG_OUT();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::ConstructL
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::ConstructL( MWsGraphicDrawerEnvironment& aEnv,
const TGraphicDrawerId& aId, MWsClient& aOwner, const TDesC8& /*aData*/ )
{
TSLOG_CONTEXT( ConstructL, TSLOG_LOCAL );
TSLOG_IN();
BaseConstructL( aEnv, aId, aOwner );
aEnv.RegisterEventHandler( this, this, TWservCrEvent::EWindowGroupChanged |
TWservCrEvent::EDeviceOrientationChanged );
iScreenChangedTime = 0;
TSLOG_OUT();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::DoHandleEvent
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::DoHandleEvent( const TWservCrEvent& aEvent )
{
TSLOG_CONTEXT( DoHandleEvent, TSLOG_LOCAL );
TSLOG_IN();
if ( aEvent.Type() == TWservCrEvent::EWindowGroupChanged )
{
const TInt wgId = aEvent.WindowGroupIdentifier();
if ( iWgIds.FindInOrder( iPrevId ) >= 0 ||
( iPrevId == 0 && iPrevReg != 0 ) )
{
TTime currTime;
currTime.HomeTime();
TTimeIntervalSeconds secondsFrom;
TInt err = currTime.SecondsFrom( iScreenChangedTime, secondsFrom );
if ( err != KErrNone || secondsFrom.Int() > KMinTimeForOrientationSwitch )
{
TRAP_IGNORE( ScreenshotL() );
}
else
{
// Reset time to allow screenshot taking on next wg change
iScreenChangedTime = 0;
// Order screenshot rotation
BitmapRotationNeeded( iPrevId?iPrevId:iPrevReg, iClockwiseRot );
}
iPrevReg = 0;
}
iPrevId = wgId;
}
else if ( aEvent.Type() == TWservCrEvent::EDeviceOrientationChanged )
{
iScreenChangedTime.HomeTime();
TRAP_IGNORE( ScreenshotL() );
}
TSLOG_OUT();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::ScaleComplete
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::ScaleCompleteL( const CFbsBitmap& aBitmap )
{
TSLOG_CONTEXT( ScaleComplete, TSLOG_LOCAL );
TSLOG_IN();
const TInt msg[] = {
NPreviewMsg::EPreviewReady,
iPrevId?iPrevId:iPrevReg,
aBitmap.Handle()
};
TPckgC<TInt[sizeof(msg) / sizeof(TInt)]> buf(msg);
User::LeaveIfError( SendMessage( buf ) );
TSLOG3( TSLOG_INFO, "size = %dx%d handle = %d",
aBitmap.SizeInPixels().iWidth,
aBitmap.SizeInPixels().iHeight,
aBitmap.Handle() );
TSLOG_OUT();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::UnregisterComplete
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::UnregisterComplete( TInt aWgId )
{
TSLOG_CONTEXT( UnregisterComplete, TSLOG_LOCAL );
TSLOG_IN();
const TInt msg[] = {
NPreviewMsg::EUnregisterReady,
aWgId,
0
};
TPckgC<TInt[sizeof(msg) / sizeof(TInt)]> buf(msg);
SendMessage(buf);
TSLOG_OUT();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::BitmapRotationNeeded
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::BitmapRotationNeeded( TInt aWgId, TBool aClockwise )
{
TSLOG_CONTEXT( BitmapRotationNeeded, TSLOG_LOCAL );
TSLOG_IN();
const TInt msg[] = {
aClockwise ? NPreviewMsg::EBitmapRotationNeeded90 : NPreviewMsg::EBitmapRotationNeeded270,
aWgId,
0
};
TPckgC<TInt[sizeof(msg) / sizeof(TInt)]> buf(msg);
SendMessage(buf);
TSLOG_OUT();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::Register
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::Register( TInt aWgId )
{
TSLOG_CONTEXT( Register, TSLOG_LOCAL );
TSLOG_IN();
iPrevReg = aWgId;
iWgIds.InsertInOrder( aWgId );
TSLOG_OUT();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::Unregister
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::Unregister( TInt aWgId )
{
TSLOG_CONTEXT( Unregister, TSLOG_LOCAL );
TSLOG_IN();
const TInt index = iWgIds.FindInOrder( aWgId );
if ( index >= 0 )
{
iWgIds.Remove( index );
}
UnregisterComplete( aWgId );
TSLOG_OUT();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::ScreenShotL
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::ScreenshotL()
{
CFbsBitmap* screenshot = new (ELeave)CFbsBitmap();
CleanupStack::PushL( screenshot );
ScreenshotL( *screenshot );
ScaleCompleteL( *screenshot );
iScreenshots.InsertL( screenshot, iScreenshots.Count() );
CleanupStack::Pop( screenshot );
CheckOverflow();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::ScreenShotL
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::ScreenshotL(CFbsBitmap& aBitmap)
{
TSLOG_CONTEXT( ScreenShot, TSLOG_LOCAL );
TSLOG_IN();
if( 0 > iScreen || Env().ScreenCount() <= iScreen )
{
//screen offset out of range. skip request
User::Leave(KErrArgument);
}
// Find the screen resolution
MWsScreenConfig* screenConfig =
Env().Screen( iScreen )->ObjectInterface<MWsScreenConfig>();
const TSize sz = screenConfig->ScreenModeSizeInPixels();
// Get the screen buffer (containing screenshot data)
MWsFrontBuffer* screenFront =
Env().Screen( iScreen )->ObjectInterface<MWsFrontBuffer>();
// With NGA we do not support downscaling of the screenshots.
// So use the size of the screen if no screenshot size has been explicitly
// set or if the old method for taking screenshots is not available.
if ( iScreenshotSize.iWidth == 0 ||
iScreenshotSize.iHeight == 0 ||
!screenFront )
{
iScreenshotSize = sz;
}
// Mark direction for possible rotation
iClockwiseRot = iScreenshotSize.iWidth > iScreenshotSize.iHeight;
// Use the the same DisplayMode as for the source image
// so override the display mode, ignoring any requests.
iScreenshotMode = screenConfig->DisplayMode();
TSLOG3( TSLOG_INFO, "iShotSize: %dx%d mode: %d",
iScreenshotSize.iWidth, iScreenshotSize.iHeight, iScreenshotMode );
aBitmap.Reset();
User::LeaveIfError( aBitmap.Create( iScreenshotSize, iScreenshotMode ) );
// Check if front buffer is available.
// Will always be NULL with NGA.
if ( screenFront )
{
TSLOG0( TSLOG_INFO, "non-NGA, using front buffer" );
FrontBufferScreenShot( aBitmap, *screenFront, sz, screenConfig->Stride() );
}
#ifdef NGA
else
{
TSLOG0( TSLOG_INFO, "NGA, using CopyScreenToBitmapL" );
MWsScreenDevice* screenDevice = static_cast<MWsScreenDevice*>(
Env().Screen( iScreen )->ResolveObjectInterface(
MWsScreenDevice::EWsObjectInterfaceId ) );
User::LeaveIfNull( screenDevice );
screenDevice->CopyScreenToBitmapL( &aBitmap, iScreenshotSize );
}
#endif
TSLOG_OUT();
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::RemoveScreenshot
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::RemoveScreenshot( TInt aBitmapHandle )
{
for( int iter(0); iter < iScreenshots.Count(); ++iter )
{
if( iScreenshots[iter]->Handle() == aBitmapHandle )
{
delete iScreenshots[iter];
iScreenshots.Remove(iter);
break;
}
}
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::CheckOverflow
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::CheckOverflow()
{
TInt overflow( iScreenshots.Count() - KMaxShots);
while( 0 < overflow-- )
{
delete iScreenshots[0];
iScreenshots.Remove(0);
}
}
// --------------------------------------------------------------------------
// CPreviewProviderCRP::FrontBufferScreenShot
// --------------------------------------------------------------------------
//
void CPreviewProviderCRP::FrontBufferScreenShot( CFbsBitmap& aBitmap,
MWsFrontBuffer& aFront,
const TSize& aSrcSize,
TInt aSrcStride )
{
TSLOG_CONTEXT( CPreviewProviderCRP::FrontBufferScreenShot, TSLOG_LOCAL );
TSLOG_IN();
const TUint8* src = static_cast<const TUint8*> ( aFront.GetBits() );
TSLOG1( TSLOG_INFO, "src address = [%d]", src );
TInt srcstride( aSrcStride );
TInt srcwidth( aSrcSize.iWidth );
TInt srcheight( aSrcSize.iHeight );
TInt dststride( aBitmap.DataStride() );
TInt dstheight( iScreenshotSize.iHeight );
TInt dstwidth( iScreenshotSize.iWidth );
TInt stepdst( dststride / dstwidth );
TInt stepsrc( srcstride / srcwidth );
// scale must be TInt type
TInt scaleX( aSrcSize.iWidth / iScreenshotSize.iWidth );
TInt scaleY( aSrcSize.iHeight / iScreenshotSize.iHeight );
aBitmap.LockHeap();
TUint8* dst = ( TUint8* ) aBitmap.DataAddress();
TInt minWidth = Min( srcwidth, dstwidth );
TInt minHeight = Min( srcheight, dstheight );
TInt minStep = Min( stepsrc, stepdst );
for ( TInt y = minHeight; y > 0; y-- )
{
for ( TInt x = minWidth; x > 0; x-- )
{
Mem::Copy( dst, src, minStep );
dst += stepdst;
src += scaleX*stepdst;
}
src += srcstride - scaleX * stepdst * minWidth;
src += ( scaleY - 1 ) * srcstride;
}
aBitmap.UnlockHeap();
TSLOG_OUT();
}
// --------------------------------------------------------------------------
// KImplementationTable
// --------------------------------------------------------------------------
//
LOCAL_C const TImplementationProxy KImplementationTable[] =
{
IMPLEMENTATION_PROXY_ENTRY(KImpId, CPreviewProviderCRP::CreateL)
};
// --------------------------------------------------------------------------
// ImplementationGroupProxy
// --------------------------------------------------------------------------
//
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
{
aTableCount = (sizeof(KImplementationTable) / sizeof(TImplementationProxy));
return KImplementationTable;
}
// End of file