Fixes from Konstantin
[zxing.git] / symbian / ZXingBarcodeReader / src / ZXingBarcodeReaderAppView.cpp
1 /*\r
2  * Copyright (c) 2009 Nokia Corporation.\r
3  */\r
4 \r
5 // INCLUDE FILES\r
6 #include <coemain.h>\r
7 #include <eikon.hrh>\r
8 #include <aknutils.h>\r
9 #include <pathinfo.h>\r
10 #include <f32file.h>\r
11 #include <BAUTILS.H>\r
12 #include "ZXingBarcodeReaderAppView.h"\r
13 #include "ZXingBarcodeReaderAppUi.h"\r
14 \r
15 \r
16 \r
17 // ============================ MEMBER FUNCTIONS ===============================\r
18 \r
19 CZXingBarcodeReaderAppView* CZXingBarcodeReaderAppView::NewL (const TRect& aRect )\r
20         {\r
21         CZXingBarcodeReaderAppView* self = CZXingBarcodeReaderAppView::NewLC (aRect );\r
22         CleanupStack::Pop (self );\r
23         return self;\r
24         }\r
25 \r
26 CZXingBarcodeReaderAppView* CZXingBarcodeReaderAppView::NewLC (const TRect& aRect )\r
27         {\r
28         CZXingBarcodeReaderAppView* self = new (ELeave) CZXingBarcodeReaderAppView;\r
29         CleanupStack::PushL (self );\r
30         self->ConstructL (aRect );\r
31         return self;\r
32         }\r
33 \r
34 void CZXingBarcodeReaderAppView::ConstructL (const TRect& aRect )\r
35         {\r
36         // Create a window for this application view\r
37         CreateWindowL ();\r
38 \r
39         iTitleFont = AknLayoutUtils::FontFromId(EAknLogicalFontPrimarySmallFont);\r
40 \r
41         iAppUi = static_cast<CZXingBarcodeReaderAppUi*>(iEikonEnv->EikAppUi());\r
42 \r
43         // Set the windows size\r
44         SetRect (aRect );\r
45 \r
46         //Start decoder timer.\r
47         StartTimer();\r
48         \r
49         // Activate the window, which makes it ready to be drawn\r
50         ActivateL ();\r
51         }\r
52 \r
53 CZXingBarcodeReaderAppView::CZXingBarcodeReaderAppView () : iPeriodic(NULL)\r
54         {\r
55         }\r
56 \r
57 CZXingBarcodeReaderAppView::~CZXingBarcodeReaderAppView ()\r
58         {\r
59         if (iCameraWrapper)\r
60                 {\r
61         iCameraWrapper->ReleaseAndPowerOff();\r
62                 }\r
63         delete iCameraWrapper;\r
64         delete iData;\r
65 \r
66         ReleaseBackBuffer();\r
67         }\r
68 \r
69 TKeyResponse CZXingBarcodeReaderAppView::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)\r
70         {\r
71         switch ( aKeyEvent.iCode )\r
72                 {\r
73                 case EKeyOK:\r
74                 case EStdKeyDevice3:\r
75                         {\r
76                         // Capture picture\r
77                         iCameraShutterFocusing = EFalse;\r
78                         StartFocusing();\r
79                         return EKeyWasConsumed;\r
80                         }\r
81                 case EKeyUpArrow:\r
82                         {\r
83                         if (iCameraWrapper->State() == CCameraEngine::EEngineViewFinding)\r
84                                 {\r
85                         iCameraWrapper->AdjustDigitalZoom(ETrue);\r
86                                 }\r
87                         return EKeyWasConsumed;\r
88                         }\r
89                 case EKeyDownArrow:\r
90                         {\r
91                         if (iCameraWrapper->State() == CCameraEngine::EEngineViewFinding)\r
92                                 {\r
93                         iCameraWrapper->AdjustDigitalZoom(EFalse);\r
94 \r
95                                 }\r
96                         return EKeyWasConsumed;\r
97                         }\r
98                 default:\r
99                         {\r
100                         break;\r
101                         }\r
102                 };\r
103 \r
104 \r
105 \r
106 #ifdef ENABLE_CAMERA_SHUTTER\r
107         // Camera shutter autofocus\r
108         switch ( aKeyEvent.iScanCode )\r
109                 {\r
110                 case KStdKeyCameraFocus:\r
111                 case KStdKeyCameraFocus2:\r
112                         {\r
113                         // Camera shutter autofocus\r
114                         if (aType == EEventKeyDown)\r
115                                 {\r
116                         if (!iAppUi->IsBackCBA())\r
117                                 {\r
118                         iCameraShutterFocusing = ETrue;\r
119                         StartFocusing();\r
120                                 }\r
121                         return EKeyWasConsumed;\r
122                                 }\r
123                         else if (aType == EEventKeyUp)\r
124                                 {\r
125                         // Camera state can be EEngineIdle or EEngineFocusing\r
126                         if (!iAppUi->IsBackCBA() && (iCameraWrapper->State() == CCameraEngine::EEngineFocusing ||\r
127                                         iCameraWrapper->State() == CCameraEngine::EEngineIdle))\r
128                                 {\r
129                         iCameraWrapper->FocusCancel();\r
130                         CancelCapturedPicture();\r
131                         iAppUi->UseOptionsExitCbaL();\r
132                                 }\r
133                         return EKeyWasConsumed;\r
134                                 }\r
135                         }\r
136                 default:\r
137                         {\r
138                         break;\r
139                         }\r
140                 };\r
141 #endif\r
142 \r
143         return EKeyWasNotConsumed;\r
144         }\r
145 \r
146 void CZXingBarcodeReaderAppView::CancelCapturedPicture(TBool aCleanTexts)\r
147         {\r
148         if (iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineIdle)\r
149                 {\r
150         TRAPD(err,iCameraWrapper->StartViewFinderL(iViewFinderSize));\r
151         if (aCleanTexts)\r
152                 {\r
153         if (err)\r
154                 {\r
155         SetError(_L("Camera viewfinder error %d"), err);                    \r
156                 }\r
157         else\r
158                 {\r
159         SetTitle(_L("Camera viewfinder"));\r
160                 }            \r
161                 }\r
162                 }\r
163         }\r
164 \r
165 void CZXingBarcodeReaderAppView::Draw(const TRect& /*aRect*/) const\r
166                 {\r
167         CWindowGc& gc = SystemGc ();\r
168 \r
169         // Draw backbuffer that has camera picture\r
170         gc.BitBlt(TPoint(0, 0), iBackBuffer);\r
171 \r
172         // Draw texts\r
173         DrawTexts(gc);\r
174 \r
175         // Focus rect\r
176         if (iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineFocusing)\r
177                 {\r
178         gc.SetPenColor(KRgbWhite);\r
179         gc.DrawRect(iFocusRect);\r
180                 }\r
181                 }\r
182 \r
183 void CZXingBarcodeReaderAppView::DrawTexts(CWindowGc& gc) const\r
184                 {\r
185         if (iTitle.Length()>0)\r
186                 {\r
187         TRect rect(Rect());\r
188         gc.SetPenColor(KRgbWhite);\r
189         gc.UseFont(iTitleFont);\r
190         gc.DrawText(iTitle, rect, rect.Height()/10, CGraphicsContext::ECenter );\r
191         gc.DiscardFont();\r
192                 }\r
193                 }\r
194 \r
195 void CZXingBarcodeReaderAppView::SizeChanged()\r
196         {\r
197         // Create camera wrapper class here because\r
198         // whole camera wrapper and all handles have to reset\r
199         // while orientatio of the application changes.\r
200         if (iCameraWrapper)\r
201                 {\r
202         // Power off camera if it is on\r
203         iCameraWrapper->StopViewFinder();\r
204         iCameraWrapper->ReleaseAndPowerOff();\r
205         delete iCameraWrapper; iCameraWrapper = NULL;\r
206                 }\r
207         TInt camErr(KErrNotSupported);\r
208         if(CCameraEngine::CamerasAvailable() > 0)\r
209                 {\r
210         TRAP(camErr, iCameraWrapper = CCameraEngine::NewL(0,0,this));\r
211                 }\r
212 \r
213         // iViewFinderSize is picture size for viewfinder.\r
214         // iCaptureSize is picture size for capturing picture.\r
215         // We want fill whole screen\r
216         if (Rect().Size().iWidth > Rect().Size().iHeight)\r
217                 {\r
218         iViewFinderSize = TSize(Rect().Size().iWidth,Rect().Size().iWidth);\r
219         iCaptureSize = TSize(1280,960); // Captured picture size\r
220                 }\r
221         else\r
222                 {\r
223         iViewFinderSize = TSize(Rect().Size().iHeight,Rect().Size().iHeight);\r
224         iCaptureSize = TSize(1280,960); // Captured picture size\r
225                 }\r
226 \r
227         // Focus rectangle\r
228         iFocusRect = Rect();\r
229         iFocusRect.Shrink(Rect().Size().iWidth/4, Rect().Size().iHeight/4);\r
230 \r
231         // Create back buffer where recieved camera pictures are copied\r
232         ReleaseBackBuffer();\r
233         CreateBackBufferL();\r
234 \r
235         // Power on camera, start viewfinder when MceoCameraReady() received\r
236         if(camErr == KErrNone)\r
237                 {\r
238         iCameraWrapper->ReserveAndPowerOn();    \r
239         SetTitle(_L("Camera power on"));\r
240                 }\r
241         else\r
242                 {\r
243         SetTitle(_L("no camera found"));\r
244                 }\r
245         }\r
246 \r
247 void CZXingBarcodeReaderAppView::HandlePointerEventL (\r
248                 const TPointerEvent& aPointerEvent )\r
249         {\r
250         if (aPointerEvent.iType == TPointerEvent::EButton1Down)\r
251                 {\r
252         // When pointing to screen camera capture picture\r
253         if (!iAppUi->IsBackCBA() && \r
254                         iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineViewFinding)\r
255                 {\r
256         iCameraShutterFocusing = EFalse;\r
257         StartFocusing();\r
258                 }\r
259         // After captureing, when pointing again to screen camera\r
260         // start viewfinder again\r
261         else if (!iAppUi->IsBackCBA() &&\r
262                         iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineIdle)\r
263                 {\r
264         CancelCapturedPicture();\r
265         iAppUi->UseOptionsExitCbaL();\r
266                 }\r
267                 }\r
268         }\r
269 \r
270 void CZXingBarcodeReaderAppView::SetTitle(const TDesC& aTitle)\r
271         {\r
272         iTitle.Copy(aTitle);\r
273         DrawNow();\r
274         }\r
275 \r
276 void CZXingBarcodeReaderAppView::SetError( const TDesC& aMsg, TInt aVal )\r
277         {\r
278         iTitle.Format(aMsg, aVal);\r
279         DrawNow();\r
280         }\r
281 \r
282 void CZXingBarcodeReaderAppView::SetError( const TDesC& aMsg, TInt aVal1, TInt aVal2 )\r
283         {\r
284         iTitle.Format(aMsg, aVal1, aVal2);\r
285         DrawNow();\r
286         }\r
287 \r
288 void CZXingBarcodeReaderAppView::CreateBackBufferL()\r
289         {\r
290         // create back buffer bitmap\r
291         iBackBuffer = new (ELeave) CFbsBitmap;\r
292 \r
293         User::LeaveIfError( iBackBuffer->Create(Size(),EColor16M));\r
294 \r
295         // create back buffer graphics context\r
296         iBackBufferDevice = CFbsBitmapDevice::NewL(iBackBuffer);\r
297         User::LeaveIfError(iBackBufferDevice->CreateContext(iBackBufferContext));\r
298         iBackBufferContext->SetPenStyle(CGraphicsContext::ESolidPen);\r
299 \r
300         iBackBufferContext->SetBrushColor(KRgbBlack);\r
301         iBackBufferContext->Clear();\r
302         }\r
303 \r
304 void CZXingBarcodeReaderAppView::ReleaseBackBuffer()\r
305         {\r
306         if (iBackBufferContext)\r
307                 {\r
308         delete iBackBufferContext;\r
309         iBackBufferContext = NULL;\r
310                 }\r
311         if (iBackBufferDevice)\r
312                 {\r
313         delete iBackBufferDevice;\r
314         iBackBufferDevice = NULL;\r
315                 }\r
316         if (iBackBuffer)\r
317                 {\r
318         delete iBackBuffer;\r
319         iBackBuffer = NULL;\r
320                 }\r
321         }\r
322 \r
323 void CZXingBarcodeReaderAppView::MceoCameraReady()\r
324         {\r
325         iAppUi->UseOptionsExitCbaL();\r
326 \r
327         if (iCameraWrapper->State() == CCameraEngine::EEngineIdle)\r
328                 {\r
329         // Prepare camera\r
330         TRAPD(err,iCameraWrapper->PrepareL(iCaptureSize));\r
331         if (err)\r
332                 {\r
333         SetError(_L("Camera prepare error %d"), err);\r
334         return;\r
335                 }\r
336 \r
337         // Start viewfinder. Viewfinder pictures starts coming into MceoViewFinderFrameReady();\r
338         TRAPD(err2,iCameraWrapper->StartViewFinderL(iViewFinderSize));\r
339         if (err2)\r
340                 {\r
341         SetError(_L("Camera start viewfinder error %d"), err2);\r
342         return;\r
343                 }\r
344 \r
345         SetTitle(_L("Camera viewfinder"));\r
346                 }\r
347         }\r
348 \r
349 void CZXingBarcodeReaderAppView::Capture()\r
350         {\r
351         // This method is called when picture is focused with camera shutter and pressed whole down\r
352         // as taking a new picture\r
353 #ifdef ENABLE_CAMERA_SHUTTER\r
354         if (iCameraWrapper && !iAppUi->IsBackCBA())\r
355                 {\r
356         // No focus supported\r
357         SetTitle(_L("Capturing picture"));\r
358         iCameraWrapper->StopViewFinder();\r
359         TRAPD(err,iCameraWrapper->CaptureL());\r
360         if (err)\r
361                 {\r
362         SetError(_L("Camera capture error %d"), err);                    \r
363                 }\r
364                 }\r
365 #endif\r
366         }\r
367 \r
368 void CZXingBarcodeReaderAppView::StartFocusing()\r
369         {\r
370         if (iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineViewFinding)\r
371                 {\r
372         if (!iCameraWrapper->IsAutoFocusSupported())\r
373                 {\r
374         // No focus supported\r
375         SetTitle(_L("Capturing picture"));\r
376         iCameraWrapper->StopViewFinder();\r
377         TRAPD(err,iCameraWrapper->CaptureL());\r
378         if (err)\r
379                 {\r
380         SetError(_L("Camera capture error %d"), err);                    \r
381                 }\r
382                 }\r
383         else\r
384                 {\r
385         // Focusing supported\r
386         iCameraWrapper->StartFocusL();\r
387         SetTitle(_L("Autofocusing..."));                    \r
388                 }\r
389                 }\r
390         }\r
391 \r
392 void CZXingBarcodeReaderAppView::MceoFocusComplete()\r
393         {\r
394         // CameraEngine state is EEngineIdle\r
395         SetTitle(_L("Focused"));                    \r
396 \r
397         if (iCameraShutterFocusing)\r
398                 {\r
399         // Leave as focused. User must press whole camera shutter down for capturing\r
400         // then CZXingBarcodeReaderAppView::Capture() is called\r
401                 }\r
402         else\r
403                 {\r
404         // Capture picture after it has focused\r
405         iCameraWrapper->StopViewFinder();\r
406         TRAPD(err,iCameraWrapper->CaptureL());\r
407         if (err)\r
408                 {\r
409         SetError(_L("Camera capture error %d"), err);                    \r
410                 }\r
411                 }\r
412         }\r
413 \r
414 void CZXingBarcodeReaderAppView::MceoCapturedDataReady( TDesC8* aData )\r
415         {\r
416         SetTitle(_L("Saving picture..."));\r
417 \r
418         delete iData; iData = NULL;\r
419         iData = aData->Alloc();\r
420 \r
421         if (iCameraWrapper)\r
422                 iCameraWrapper->ReleaseImageBuffer();\r
423 \r
424         TRAP_IGNORE(iAppUi->UseOptionsBackCbaL());\r
425 \r
426         StorePicture(iData);\r
427         }\r
428 \r
429 void CZXingBarcodeReaderAppView::StorePicture( TDesC8* aData )\r
430         {\r
431         // Create path for filename\r
432         TFileName path = PathInfo::PhoneMemoryRootPath(); \r
433         path.Append(PathInfo::ImagesPath());\r
434 \r
435         // Ensure that path exists\r
436         BaflUtils::EnsurePathExistsL(iEikonEnv->FsSession(),path);\r
437 \r
438         // Get next free filename for the image\r
439         TFileName fileToSave;\r
440         TBool fileExists = ETrue;\r
441         for (TInt i=1 ; i<100 ; i++)\r
442                 {\r
443         fileToSave.Copy(path);\r
444         fileToSave.Append(_L("cw_image_"));\r
445         fileToSave.AppendNum(i);\r
446         fileToSave.Append(_L(".jpg"));\r
447         fileExists = BaflUtils::FileExists(iEikonEnv->FsSession(),fileToSave);\r
448         if (!fileExists)\r
449                 {\r
450         break;\r
451                 }\r
452                 }\r
453 \r
454         // Save file\r
455         if (!fileExists)\r
456                 {\r
457         RFile file;\r
458         TInt err = file.Create(iEikonEnv->FsSession(),fileToSave,EFileWrite);\r
459         if (!err)\r
460                 {\r
461         file.Write(*aData);\r
462         file.Close();\r
463         SetTitle(fileToSave);\r
464                 }\r
465         else\r
466                 {\r
467         SetError(_L("File saving error %d"),err);\r
468                 }\r
469                 }\r
470         else\r
471                 {\r
472         SetTitle(_L("File not saved, delete old pictures!"));\r
473                 }\r
474         }\r
475 \r
476 \r
477 void CZXingBarcodeReaderAppView::MceoCapturedBitmapReady( CFbsBitmap* aBitmap )\r
478         {\r
479         if (iBackBufferContext)\r
480                 {\r
481         TSize bmpSizeInPixels = aBitmap->SizeInPixels();\r
482         TInt xDelta = (Rect().Width() - bmpSizeInPixels.iWidth) / 2;\r
483         TInt yDelta = (Rect().Height() - bmpSizeInPixels.iHeight) / 2;\r
484         TPoint pos( xDelta, yDelta );\r
485 \r
486         // Copy received viewfinder picture to back buffer\r
487         iBackBufferContext->BitBlt( pos, aBitmap, TRect( TPoint( 0, 0 ), bmpSizeInPixels ));\r
488 \r
489         // Update backbuffer into screen \r
490         SetTitle(_L("New picture"));\r
491                 }\r
492         if (iCameraWrapper)\r
493                 iCameraWrapper->ReleaseImageBuffer();\r
494         }\r
495 \r
496 void CZXingBarcodeReaderAppView::MceoViewFinderFrameReady( CFbsBitmap& aFrame )\r
497         {\r
498         if (iBackBufferContext)\r
499                 {\r
500         TSize bmpSizeInPixels = aFrame.SizeInPixels();\r
501         TInt xDelta = (Rect().Width() - bmpSizeInPixels.iWidth) / 2;\r
502         TInt yDelta = (Rect().Height() - bmpSizeInPixels.iHeight) / 2;\r
503         TPoint pos( xDelta, yDelta );\r
504 \r
505         // Copy received viewfinder picture to back buffer\r
506         iBackBufferContext->BitBlt( pos, &aFrame, TRect( TPoint( 0, 0 ), bmpSizeInPixels ));\r
507 \r
508         // Update backbuffer into screen \r
509         DrawNow();\r
510                 }\r
511         if (iCameraWrapper)\r
512                 iCameraWrapper->ReleaseViewFinderBuffer();\r
513         }\r
514 \r
515 void CZXingBarcodeReaderAppView::MceoHandleError( TCameraEngineError aErrorType, TInt aError )\r
516         {\r
517         // NOTE: CameraEngine state seems to go into CCameraEngine::EEngineIdle state\r
518 \r
519         if (aErrorType == EErrReserve)\r
520                 {\r
521         return; //-18 comes on application startup, but everything works ok\r
522                 }\r
523 \r
524         switch (aErrorType)\r
525                 {\r
526                 case EErrReserve:\r
527                         {\r
528                         SetError(_L("Camera reserved error  (%d)"), aError);\r
529                         break;\r
530                         }\r
531                 case EErrPowerOn:\r
532                         {\r
533                         SetError(_L("Camera power on error  (%d)"), aError);\r
534                         break;\r
535                         }\r
536                 case EErrViewFinderReady:\r
537                         {\r
538                         SetError(_L("Camera viewfinder error  (%d)"), aError);\r
539                         break;\r
540                         }\r
541                 case EErrImageReady:\r
542                         {\r
543                         SetError(_L("Camera image ready error  (%d)"), aError);\r
544                         break;\r
545                         }\r
546                 case EErrAutoFocusInit:\r
547                 case EErrAutoFocusMode:\r
548                 case EErrAutoFocusArea:\r
549                 case EErrAutoFocusRange:\r
550                 case EErrAutoFocusType:\r
551                 case EErrOptimisedFocusComplete:\r
552                         {\r
553                         //SetTitle(_L("Try focusing again"));\r
554                         break;\r
555                         }\r
556                 default:\r
557                         {\r
558                         SetError(_L("Error %d (%d)"), aErrorType, aError);\r
559                         break;\r
560                         }\r
561                 };\r
562 \r
563         // Try handle error\r
564         CancelCapturedPicture(EFalse);\r
565         iAppUi->UseOptionsExitCbaL();\r
566         }\r
567 \r
568 void CZXingBarcodeReaderAppView::MceoHandleOtherEvent( const TECAMEvent& /*aEvent*/ )\r
569         {\r
570         }\r
571 \r
572 \r
573 \r
574 \r
575 // End of File\r