/*
* Copyright (c) 2002-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: This class takes snapshot and resizes bitmap if needed.
*
*/
// INCLUDE FILES
#include <jdebug.h>
#include "cmmasnapshot.h"
#include "mmmaguiplayer.h"
#include "mmmasnapshotreadycallback.h"
#include "mmmasnapshot.h"
// CONSTANTS
const TInt KIgnoreSize = -1;
// CONSTRUCTION
CMMASnapshot* CMMASnapshot::NewL(MMMAGuiPlayer* aGuiPlayer,
MMMASnapshotReadyCallback& aCallBack)
{
CMMASnapshot* self = new(ELeave) CMMASnapshot(aGuiPlayer,
aCallBack);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(); // self
return self;
}
CMMASnapshot::~CMMASnapshot()
{
if (iScaler)
{
iScaler->Cancel();
delete iScaler;
}
if (iEncoder)
{
iEncoder->Cancel();
delete iEncoder;
}
delete iBitmap;
delete iBuffer;
delete iSettings;
}
void CMMASnapshot::ConstructL()
{
CActiveScheduler::Add(this);
iScaler = CBitmapScaler::NewL();
}
CMMASnapshot::CMMASnapshot(MMMAGuiPlayer* aGuiPlayer,
MMMASnapshotReadyCallback& aCallBack):
CActive(EPriorityStandard),
iEncoding(MMMASnapshot::EBitmap),
iCallBack(aCallBack),
iState(EIdle)
{
iGUIPlayer = aGuiPlayer;
}
void CMMASnapshot::TakeSnapShotL(const TDesC& aProperties)
{
// snapshot sequence is not finished
__ASSERT_DEBUG(iState == EIdle, User::Invariant());
// image buffer must be taken with ImageBuffer before taking new snapshot
__ASSERT_DEBUG(iBuffer == NULL, User::Invariant());
CMMAImageSettings* settings
= TMMAParameterValidator::ValidateImagePropertiesL(aProperties);
CleanupStack::PushL(settings);
delete iSettings;
CleanupStack::Pop(settings);
iSettings = settings;
// take snapshot from player. RunL is called when image is ready
// or error occures
iState = ETakingSnapshot;
TSize snapshotSize(iSettings->iWidth, iSettings->iHeight);
iEncoding = iGUIPlayer->SnapshoterL()->TakeSnapshotL(&iStatus,
snapshotSize,
*iSettings);
SetActive();
}
HBufC8* CMMASnapshot::ImageBuffer()
{
// this must not be called when snapshot sequence is running
__ASSERT_DEBUG(iState == EIdle, User::Invariant());
HBufC8* buffer = iBuffer;
// caller takes ownership of the buffer
iBuffer = NULL;
return buffer;
}
void CMMASnapshot::ResizeL()
{
iState = EResizing;
TSize imageSize(iBitmap->SizeInPixels());
if (iSettings->iWidth != KIgnoreSize)
{
imageSize.iWidth = iSettings->iWidth;
}
if (iSettings->iHeight != KIgnoreSize)
{
imageSize.iHeight = iSettings->iHeight;
}
if (imageSize == iBitmap->SizeInPixels())
{
// no user resizing needed, continue sequence
EncodeL();
}
else
{
iScaler->Scale(&iStatus, *iBitmap, imageSize, EFalse);
SetActive();
}
}
void CMMASnapshot::EncodeL()
{
// CImageEncoder cannot be reused, so have to make it every time
CImageEncoder* encoder = CImageEncoder::DataNewL(iBuffer, *iSettings->iMimeType);
delete iEncoder;
iEncoder = encoder;
iState = EEncoding;
iEncoder->Convert(&iStatus, *iBitmap, iSettings->iImageData);
SetActive();
}
void CMMASnapshot::Completed(TInt aError)
{
iStatus = aError;
iCallBack.SnapshotReady();
}
void CMMASnapshot::RunL()
{
if (iStatus != KErrNone)
{
// Error has occured, inform java side and change state
iState = EIdle;
Completed(iStatus.Int());
return;
}
switch (iState)
{
case ETakingSnapshot:
{
DEBUG_INT("MMA::CMMASnapshot::RunL: iEncoding = %d", iEncoding);
if (iEncoding == MMMASnapshot::EEncoded)
{
// take encoded image from player.
// Ownership transfers to this class.
iBuffer = iGUIPlayer->SnapshoterL()->SnapshotEncoded();
if (!iBuffer)
{
// error has occured with taking image
Completed(KErrNotFound);
}
// Image is ready, update internal state and inform listener
// Encoded images are not resized
iState = EIdle;
Completed(KErrNone);
}
else
{
// take bitmap from player.
// Ownership transfers to this class.
iBitmap = iGUIPlayer->SnapshoterL()->SnapshotBitmap();
if (!iBitmap)
{
// error has occured with taking image
Completed(KErrNotFound);
}
// Continue to next state
ResizeL();
}
break;
}
case EResizing:
{
// Continue to next state
EncodeL();
break;
}
case EEncoding:
{
delete iEncoder;
iEncoder = NULL;
delete iBitmap;
iBitmap = NULL;
iState = EIdle;
// encoding is ready, inform listener
Completed(KErrNone);
break;
}
default:
{
// unknown state
__ASSERT_DEBUG(EFalse, User::Invariant());
}
}
}
TInt CMMASnapshot::RunError(TInt aError)
{
// Reset state
iState = EIdle;
// Pass error code to observer
Completed(aError);
return KErrNone;
}
void CMMASnapshot::DoCancel()
{
// snapshot taking cannot be cancelled
if (iScaler)
{
iScaler->Cancel();
}
if (iEncoder)
{
iEncoder->Cancel();
}
iState = EIdle;
}
// END OF FILE