zxing/symbian/ZXingBarcodeReader/src/ZXingBarcodeReaderAppView.cpp
2010-05-21 09:47:21 +00:00

583 lines
14 KiB
C++

/*
* Copyright (c) 2009 Nokia Corporation.
*/
// INCLUDE FILES
#include <coemain.h>
#include <eikon.hrh>
#include <aknutils.h>
#include <pathinfo.h>
#include <f32file.h>
#include <BAUTILS.H>
#include "ZXingBarcodeReaderAppView.h"
#include "ZXingBarcodeReaderAppUi.h"
// ============================ MEMBER FUNCTIONS ===============================
CZXingBarcodeReaderAppView* CZXingBarcodeReaderAppView::NewL (const TRect& aRect )
{
CZXingBarcodeReaderAppView* self = CZXingBarcodeReaderAppView::NewLC (aRect );
CleanupStack::Pop (self );
return self;
}
CZXingBarcodeReaderAppView* CZXingBarcodeReaderAppView::NewLC (const TRect& aRect )
{
CZXingBarcodeReaderAppView* self = new (ELeave) CZXingBarcodeReaderAppView;
CleanupStack::PushL (self );
self->ConstructL (aRect );
return self;
}
void CZXingBarcodeReaderAppView::ConstructL (const TRect& aRect )
{
// Create a window for this application view
CreateWindowL ();
iTitleFont = AknLayoutUtils::FontFromId(EAknLogicalFontPrimarySmallFont);
iAppUi = static_cast<CZXingBarcodeReaderAppUi*>(iEikonEnv->EikAppUi());
// Set the windows size
SetRect (aRect );
//Start decoder timer.
StartTimer();
// Activate the window, which makes it ready to be drawn
ActivateL ();
}
CZXingBarcodeReaderAppView::CZXingBarcodeReaderAppView () : iPeriodic(NULL)
{
}
CZXingBarcodeReaderAppView::~CZXingBarcodeReaderAppView ()
{
if (iCameraWrapper)
{
iCameraWrapper->ReleaseAndPowerOff();
}
delete iCameraWrapper;
delete iData;
ReleaseBackBuffer();
}
TKeyResponse CZXingBarcodeReaderAppView::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
switch ( aKeyEvent.iCode )
{
case EKeyOK:
case EStdKeyDevice3:
{
// Capture picture
iCameraShutterFocusing = EFalse;
StartFocusing();
return EKeyWasConsumed;
}
case EKeyUpArrow:
{
if (iCameraWrapper->State() == CCameraEngine::EEngineViewFinding)
{
iCameraWrapper->AdjustDigitalZoom(ETrue);
}
return EKeyWasConsumed;
}
case EKeyDownArrow:
{
if (iCameraWrapper->State() == CCameraEngine::EEngineViewFinding)
{
iCameraWrapper->AdjustDigitalZoom(EFalse);
}
return EKeyWasConsumed;
}
default:
{
break;
}
};
#ifdef ENABLE_CAMERA_SHUTTER
// Camera shutter autofocus
switch ( aKeyEvent.iScanCode )
{
case KStdKeyCameraFocus:
case KStdKeyCameraFocus2:
{
// Camera shutter autofocus
if (aType == EEventKeyDown)
{
if (!iAppUi->IsBackCBA())
{
iCameraShutterFocusing = ETrue;
StartFocusing();
}
return EKeyWasConsumed;
}
else if (aType == EEventKeyUp)
{
// Camera state can be EEngineIdle or EEngineFocusing
if (!iAppUi->IsBackCBA() && (iCameraWrapper->State() == CCameraEngine::EEngineFocusing ||
iCameraWrapper->State() == CCameraEngine::EEngineIdle))
{
iCameraWrapper->FocusCancel();
CancelCapturedPicture();
iAppUi->UseOptionsExitCbaL();
}
return EKeyWasConsumed;
}
}
default:
{
break;
}
};
#endif
return EKeyWasNotConsumed;
}
void CZXingBarcodeReaderAppView::CancelCapturedPicture(TBool aCleanTexts)
{
if (iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineIdle)
{
TRAPD(err,iCameraWrapper->StartViewFinderL(iViewFinderSize));
if (aCleanTexts)
{
if (err)
{
SetError(_L("Camera viewfinder error %d"), err);
}
else
{
SetTitle(_L("Camera viewfinder"));
}
}
}
}
void CZXingBarcodeReaderAppView::Draw(const TRect& /*aRect*/) const
{
CWindowGc& gc = SystemGc ();
// Draw backbuffer that has camera picture
gc.BitBlt(TPoint(0, 0), iBackBuffer);
// Draw texts
DrawTexts(gc);
// Focus rect
if (iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineFocusing)
{
gc.SetPenColor(KRgbWhite);
gc.DrawRect(iFocusRect);
}
}
void CZXingBarcodeReaderAppView::DrawTexts(CWindowGc& gc) const
{
if (iTitle.Length()>0)
{
TRect rect(Rect());
gc.SetPenColor(KRgbWhite);
gc.UseFont(iTitleFont);
gc.DrawText(iTitle, rect, rect.Height()/10, CGraphicsContext::ECenter );
gc.DiscardFont();
}
}
void CZXingBarcodeReaderAppView::SizeChanged()
{
// Create camera wrapper class here because
// whole camera wrapper and all handles have to reset
// while orientatio of the application changes.
if (iCameraWrapper)
{
// Power off camera if it is on
iCameraWrapper->StopViewFinder();
iCameraWrapper->ReleaseAndPowerOff();
delete iCameraWrapper; iCameraWrapper = NULL;
}
TInt camErr(KErrNotSupported);
if(CCameraEngine::CamerasAvailable() > 0)
{
TRAP(camErr, iCameraWrapper = CCameraEngine::NewL(0,0,this));
}
// iViewFinderSize is picture size for viewfinder.
// iCaptureSize is picture size for capturing picture.
// We want fill whole screen
if (Rect().Size().iWidth > Rect().Size().iHeight)
{
iViewFinderSize = TSize(Rect().Size().iWidth,Rect().Size().iWidth);
iCaptureSize = TSize(1280,960); // Captured picture size
}
else
{
iViewFinderSize = TSize(Rect().Size().iHeight,Rect().Size().iHeight);
iCaptureSize = TSize(1280,960); // Captured picture size
}
// Focus rectangle
iFocusRect = Rect();
iFocusRect.Shrink(Rect().Size().iWidth/4, Rect().Size().iHeight/4);
// Create back buffer where recieved camera pictures are copied
ReleaseBackBuffer();
CreateBackBufferL();
// Power on camera, start viewfinder when MceoCameraReady() received
if(camErr == KErrNone)
{
iCameraWrapper->ReserveAndPowerOn();
SetTitle(_L("Camera power on"));
}
else
{
SetTitle(_L("no camera found"));
}
}
void CZXingBarcodeReaderAppView::HandlePointerEventL (
const TPointerEvent& aPointerEvent )
{
if (aPointerEvent.iType == TPointerEvent::EButton1Down)
{
// When pointing to screen camera capture picture
if (!iAppUi->IsBackCBA() &&
iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineViewFinding)
{
iCameraShutterFocusing = EFalse;
StartFocusing();
}
// After captureing, when pointing again to screen camera
// start viewfinder again
else if (!iAppUi->IsBackCBA() &&
iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineIdle)
{
CancelCapturedPicture();
iAppUi->UseOptionsExitCbaL();
}
}
}
void CZXingBarcodeReaderAppView::SetTitle(const TDesC& aTitle)
{
iTitle.Copy(aTitle);
DrawNow();
}
void CZXingBarcodeReaderAppView::SetError( const TDesC& aMsg, TInt aVal )
{
iTitle.Format(aMsg, aVal);
DrawNow();
}
void CZXingBarcodeReaderAppView::SetError( const TDesC& aMsg, TInt aVal1, TInt aVal2 )
{
iTitle.Format(aMsg, aVal1, aVal2);
DrawNow();
}
void CZXingBarcodeReaderAppView::CreateBackBufferL()
{
// create back buffer bitmap
iBackBuffer = new (ELeave) CFbsBitmap;
User::LeaveIfError( iBackBuffer->Create(Size(),EColor16M));
// create back buffer graphics context
iBackBufferDevice = CFbsBitmapDevice::NewL(iBackBuffer);
User::LeaveIfError(iBackBufferDevice->CreateContext(iBackBufferContext));
iBackBufferContext->SetPenStyle(CGraphicsContext::ESolidPen);
iBackBufferContext->SetBrushColor(KRgbBlack);
iBackBufferContext->Clear();
}
void CZXingBarcodeReaderAppView::ReleaseBackBuffer()
{
if (iBackBufferContext)
{
delete iBackBufferContext;
iBackBufferContext = NULL;
}
if (iBackBufferDevice)
{
delete iBackBufferDevice;
iBackBufferDevice = NULL;
}
if (iBackBuffer)
{
delete iBackBuffer;
iBackBuffer = NULL;
}
}
void CZXingBarcodeReaderAppView::MceoCameraReady()
{
iAppUi->UseOptionsExitCbaL();
if (iCameraWrapper->State() == CCameraEngine::EEngineIdle)
{
// Prepare camera
TRAPD(err,iCameraWrapper->PrepareL(iCaptureSize));
if (err)
{
SetError(_L("Camera prepare error %d"), err);
return;
}
// Start viewfinder. Viewfinder pictures starts coming into MceoViewFinderFrameReady();
TRAPD(err2,iCameraWrapper->StartViewFinderL(iViewFinderSize));
if (err2)
{
SetError(_L("Camera start viewfinder error %d"), err2);
return;
}
SetTitle(_L("Camera viewfinder"));
}
}
void CZXingBarcodeReaderAppView::Capture()
{
// This method is called when picture is focused with camera shutter and pressed whole down
// as taking a new picture
#ifdef ENABLE_CAMERA_SHUTTER
if (iCameraWrapper && !iAppUi->IsBackCBA())
{
// No focus supported
SetTitle(_L("Capturing picture"));
iCameraWrapper->StopViewFinder();
TRAPD(err,iCameraWrapper->CaptureL());
if (err)
{
SetError(_L("Camera capture error %d"), err);
}
}
#endif
}
void CZXingBarcodeReaderAppView::StartFocusing()
{
if (iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineViewFinding)
{
if (!iCameraWrapper->IsAutoFocusSupported())
{
// No focus supported
SetTitle(_L("Capturing picture"));
iCameraWrapper->StopViewFinder();
TRAPD(err,iCameraWrapper->CaptureL());
if (err)
{
SetError(_L("Camera capture error %d"), err);
}
}
else
{
// Focusing supported
iCameraWrapper->StartFocusL();
SetTitle(_L("Autofocusing..."));
}
}
}
void CZXingBarcodeReaderAppView::MceoFocusComplete()
{
// CameraEngine state is EEngineIdle
SetTitle(_L("Focused"));
if (iCameraShutterFocusing)
{
// Leave as focused. User must press whole camera shutter down for capturing
// then CZXingBarcodeReaderAppView::Capture() is called
}
else
{
// Capture picture after it has focused
iCameraWrapper->StopViewFinder();
TRAPD(err,iCameraWrapper->CaptureL());
if (err)
{
SetError(_L("Camera capture error %d"), err);
}
}
}
void CZXingBarcodeReaderAppView::MceoCapturedDataReady( TDesC8* aData )
{
SetTitle(_L("Saving picture..."));
delete iData; iData = NULL;
iData = aData->Alloc();
if (iCameraWrapper)
iCameraWrapper->ReleaseImageBuffer();
TRAP_IGNORE(iAppUi->UseOptionsBackCbaL());
StorePicture(iData);
}
void CZXingBarcodeReaderAppView::StorePicture( TDesC8* aData )
{
// Create path for filename
TFileName path = PathInfo::PhoneMemoryRootPath();
path.Append(PathInfo::ImagesPath());
// Ensure that path exists
BaflUtils::EnsurePathExistsL(iEikonEnv->FsSession(),path);
// Get next free filename for the image
TFileName fileToSave;
TBool fileExists = ETrue;
for (TInt i=1 ; i<100 ; i++)
{
fileToSave.Copy(path);
fileToSave.Append(_L("cw_image_"));
fileToSave.AppendNum(i);
fileToSave.Append(_L(".jpg"));
fileExists = BaflUtils::FileExists(iEikonEnv->FsSession(),fileToSave);
if (!fileExists)
{
break;
}
}
// Save file
if (!fileExists)
{
RFile file;
TInt err = file.Create(iEikonEnv->FsSession(),fileToSave,EFileWrite);
if (!err)
{
file.Write(*aData);
file.Close();
SetTitle(fileToSave);
}
else
{
SetError(_L("File saving error %d"),err);
}
}
else
{
SetTitle(_L("File not saved, delete old pictures!"));
}
}
void CZXingBarcodeReaderAppView::MceoCapturedBitmapReady( CFbsBitmap* aBitmap )
{
if (iBackBufferContext)
{
TSize bmpSizeInPixels = aBitmap->SizeInPixels();
TInt xDelta = (Rect().Width() - bmpSizeInPixels.iWidth) / 2;
TInt yDelta = (Rect().Height() - bmpSizeInPixels.iHeight) / 2;
TPoint pos( xDelta, yDelta );
// Copy received viewfinder picture to back buffer
iBackBufferContext->BitBlt( pos, aBitmap, TRect( TPoint( 0, 0 ), bmpSizeInPixels ));
// Update backbuffer into screen
SetTitle(_L("New picture"));
}
if (iCameraWrapper)
iCameraWrapper->ReleaseImageBuffer();
}
void CZXingBarcodeReaderAppView::MceoViewFinderFrameReady( CFbsBitmap& aFrame )
{
if (iBackBufferContext)
{
TSize bmpSizeInPixels = aFrame.SizeInPixels();
TInt xDelta = (Rect().Width() - bmpSizeInPixels.iWidth) / 2;
TInt yDelta = (Rect().Height() - bmpSizeInPixels.iHeight) / 2;
TPoint pos( xDelta, yDelta );
// Copy received viewfinder picture to back buffer
iBackBufferContext->BitBlt( pos, &aFrame, TRect( TPoint( 0, 0 ), bmpSizeInPixels ));
// Update backbuffer into screen
DrawNow();
}
if (iCameraWrapper)
iCameraWrapper->ReleaseViewFinderBuffer();
}
void CZXingBarcodeReaderAppView::MceoHandleError( TCameraEngineError aErrorType, TInt aError )
{
// NOTE: CameraEngine state seems to go into CCameraEngine::EEngineIdle state
if (aErrorType == EErrReserve)
{
return; //-18 comes on application startup, but everything works ok
}
switch (aErrorType)
{
case EErrReserve:
{
SetError(_L("Camera reserved error (%d)"), aError);
break;
}
case EErrPowerOn:
{
SetError(_L("Camera power on error (%d)"), aError);
break;
}
case EErrViewFinderReady:
{
SetError(_L("Camera viewfinder error (%d)"), aError);
break;
}
case EErrImageReady:
{
SetError(_L("Camera image ready error (%d)"), aError);
break;
}
case EErrAutoFocusInit:
case EErrAutoFocusMode:
case EErrAutoFocusArea:
case EErrAutoFocusRange:
case EErrAutoFocusType:
case EErrOptimisedFocusComplete:
{
//SetTitle(_L("Try focusing again"));
break;
}
default:
{
SetError(_L("Error %d (%d)"), aErrorType, aError);
break;
}
};
// Try handle error
CancelCapturedPicture(EFalse);
iAppUi->UseOptionsExitCbaL();
}
void CZXingBarcodeReaderAppView::MceoHandleOtherEvent( const TECAMEvent& /*aEvent*/ )
{
}
void CZXingBarcodeReaderAppView::StopTimer()
{
if(iPeriodic)
iPeriodic->Cancel();
}
// End of File