33e4ded676419c5ea24e1019a99efbeded16bbe9
[framework/web/wrt-plugins-common.git] / src / modules / tizen / Camera-Webkit / Camera.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @author      Grzegorz Krawczyk (g.krawczyk@samsung.com)
18  * @version     0.1
19  * @brief
20  */
21
22 #include "Camera.h"
23 #include <pthread.h>
24 #include <dpl/assert.h>
25 #include <dpl/shared_ptr.h>
26 #include <dpl/noncopyable.h>
27 #include <Commons/Exception.h>
28 #include <Commons/TypeTraits.h>
29
30
31 namespace WrtDeviceApis {
32 namespace Camera {
33
34 template<typename EventPtr>
35 class CameraPrivateData
36 {
37 public:
38     Camera* camera;
39     EventPtr event;
40 };
41
42 enum EventTypeId
43 {
44     BeginRecordingType,
45     TakePictureType,
46     CreatePreviewType
47 };
48
49 class OpaquePrivateData
50 {
51 public:
52     EventTypeId eventTypeId;
53     void* cameraPrivateData;
54 };
55
56
57 //GetEventTypeId
58 template<typename T>
59 EventTypeId getEventTypeId(const T& event){ Assert(0); }
60
61 template<>
62 EventTypeId getEventTypeId<Api::EventBeginRecordingSharedPtr>(
63     const Api::EventBeginRecordingSharedPtr& /*event*/)
64 {
65     return BeginRecordingType;
66 }
67
68 template<>
69 EventTypeId getEventTypeId<Api::EventTakePictureSharedPtr>(
70     const Api::EventTakePictureSharedPtr& /*event*/)
71 {
72     return TakePictureType;
73 }
74
75 template<>
76 EventTypeId getEventTypeId<Api::EventGetPreviewNodeSharedPtr>(
77     const Api::EventGetPreviewNodeSharedPtr& /*event*/)
78 {
79     return CreatePreviewType;
80 }
81
82 template<typename EventPtr>
83 OpaquePrivateData* createPrivateOpaqueData(Camera* camera,
84                                            const EventPtr& event)
85 {
86     //create private opaque data
87     OpaquePrivateData* opaqueData = new OpaquePrivateData;
88
89     CameraPrivateData<EventPtr>* privateData = new CameraPrivateData<EventPtr>;
90     privateData->camera = camera;
91     privateData->event = event;
92
93     opaqueData->eventTypeId = getEventTypeId(event);
94     opaqueData->cameraPrivateData = privateData;
95
96     return opaqueData;
97 }
98
99 template<typename EventPtr>
100 CameraPrivateData<EventPtr>* getPrivateData(void* data)
101 {
102     OpaquePrivateData* opaqueData = static_cast<OpaquePrivateData*> (data);
103
104     CameraPrivateData<EventPtr>* privateData =
105         static_cast<CameraPrivateData<EventPtr> *>
106         (opaqueData->cameraPrivateData);
107
108     return privateData;
109 }
110
111 template<typename EventPtr>
112 void deletePrivateData(void* data)
113 {
114     OpaquePrivateData* opaqueData = static_cast<OpaquePrivateData*> (data);
115
116     CameraPrivateData<EventPtr>* privateData =
117         static_cast<CameraPrivateData<EventPtr> *>
118         (opaqueData->cameraPrivateData);
119
120     delete privateData;
121     delete opaqueData;
122 }
123
124
125 template<typename EventType, typename EventArg>
126 EventType createEvent(const EventArg& arg1)
127 {
128     return EventType(arg1);
129 }
130
131
132 template<typename EventType>
133 class BaseCallbackHandler : private DPL::Noncopyable
134 {
135 public:
136     explicit BaseCallbackHandler(void* data) :
137         m_camera(NULL)
138     {
139         Assert(data);
140         CameraPrivateData<EventType>* privateData =
141             getPrivateData<EventType>(data);
142         m_camera = privateData->camera;
143         m_event = privateData->event;
144
145         deletePrivateData<EventType>(data);
146     }
147
148     virtual void handleErrorCallback(int error)
149     {
150         LogError("Error: " << error);
151         m_event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
152         this->post();
153     }
154
155     virtual void handleSuccessCallback(void* data)
156     {
157         setPrivate(data);
158         this->post();
159     }
160
161     virtual void post() = 0;
162
163     virtual ~BaseCallbackHandler(){ }
164
165   protected:
166     virtual void setPrivate(void* /*data*/) {};
167
168 protected:
169     Camera* m_camera;
170     EventType m_event;
171 };
172
173 template<typename EventType>
174 class CallbackHandler : public BaseCallbackHandler<EventType>
175 {
176     static_assert(WrtDeviceApis::Commons::AlwaysFalse<EventType>::value,
177                       "Error, no specialization found for given type");
178
179   public:
180     explicit CallbackHandler(void* data) :
181         BaseCallbackHandler<EventType>(data)
182     {
183     }
184
185     //virtual void post(){ }
186 };
187
188 template<>
189 class CallbackHandler<Api::EventBeginRecordingSharedPtr>
190  : public BaseCallbackHandler<Api::EventBeginRecordingSharedPtr>
191 {
192   public:
193     explicit CallbackHandler(void* data) :
194         BaseCallbackHandler(data)
195     {}
196
197     virtual void post(){
198         this->m_camera->setRecordingState(Camera::COMPLETED);
199         this->m_camera->
200             DPL::Event::ControllerEventHandler<JobDoneVideoRecordingEvent>::PostEvent(
201                 createEvent<JobDoneVideoRecordingEvent,
202                 Api::EventBeginRecordingSharedPtr>(this->m_event));
203     }
204
205     virtual void handleSuccessCallback(void* data)
206     {
207         this->m_camera->setRecordingState(Camera::COMPLETED);
208         BaseCallbackHandler<Api::EventBeginRecordingSharedPtr>::
209             handleSuccessCallback(data);
210     }
211 };
212
213 template<>
214 class CallbackHandler<Api::EventTakePictureSharedPtr>
215  : public BaseCallbackHandler<Api::EventTakePictureSharedPtr>
216 {
217   public:
218     explicit CallbackHandler(void* data) :
219         BaseCallbackHandler(data)
220     {}
221
222     virtual void post(){
223         this->m_camera->
224             DPL::Event::ControllerEventHandler<JobDoneTakePictureEvent>::PostEvent(
225                 createEvent<JobDoneTakePictureEvent,
226                 Api::EventTakePictureSharedPtr>(this->m_event));
227     }
228
229     virtual void setPrivate(void* data)
230     {
231         m_event->getCaptureOptionsRef()->setFileName(static_cast<char*>(data));
232     }
233 };
234
235 template<>
236 class CallbackHandler<Api::EventGetPreviewNodeSharedPtr>
237  : public BaseCallbackHandler<Api::EventGetPreviewNodeSharedPtr>
238 {
239   public:
240     explicit CallbackHandler(void* data) :
241         BaseCallbackHandler(data)
242     {}
243
244     virtual void post(){
245         this->m_camera->
246             DPL::Event::ControllerEventHandler<JobDoneCreatePreviewEvent>::PostEvent(
247                 createEvent<JobDoneCreatePreviewEvent,
248                 Api::EventGetPreviewNodeSharedPtr>(this->m_event));
249     }
250
251     virtual void setPrivate(void* data)
252     {
253         LogDebug("Enter");
254         m_event->setPreviewNode(data);
255     }
256 };
257
258 Camera::Camera(const Commons::IWrtCameraPtr& wrtCamera) :
259     m_wrtCamera(wrtCamera),
260     m_stateRecordingVideo (Camera::IDLE)
261 {
262     CameraJobDoneController::Touch();
263 }
264
265 Camera::~Camera()
266 {
267     LogDebug("enter");
268
269     CameraJobDoneController::SwitchToThread(NULL);
270 }
271
272
273 void Camera::OnRequestReceived(
274         const Api::EventTakePictureSharedPtr & event)
275 {
276     LogDebug("enter");
277
278     event->switchToManualAnswer();
279
280     m_wrtCamera->captureImage(event->getCaptureOptionsRef()->getFileName(),
281                               checkHighResolutionRequired(event),
282                               camCaptureImageSuccessCallback,
283                               camCaptureImageErrorCallback,
284                               setPendingOperation,
285                               createPrivateOpaqueData(this,event));
286
287     LogDebug("leaving");
288 }
289
290 void Camera::OnRequestReceived(
291         const Api::EventBeginRecordingSharedPtr & event)
292 {
293     LogDebug("enter");
294
295     if (m_stateRecordingVideo != Camera::IDLE) {
296         event->setExceptionCode(Commons::ExceptionCodes::AlreadyInUseException);
297         return;
298     }
299     m_stateRecordingVideo = Camera::PROCESSING;
300
301     //from now on we will have to call answer manually
302     event->switchToManualAnswer();
303
304     m_wrtCamera->startVideoCapture(event->getCaptureOptionsRef()->getFileName(),
305                                    checkHighResolutionRequired(event),
306                                    camCaptureVideoSuccessCallback,
307                                    camCaptureVideoErrorCallback,
308                                    setPendingOperation,
309                                    createPrivateOpaqueData(this,event));
310
311     LogDebug("leaving");
312 }
313
314 void Camera::OnRequestReceived(
315         const Api::EventEndRecordingSharedPtr & event)
316 {
317     LogDebug("end request");
318     if (m_stateRecordingVideo == Camera::PROCESSING) {
319         m_wrtCamera->stopVideoCapture();
320     } else {
321         LogDebug("stopVideo has been called but no recording is in progress");
322         event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
323     }
324 }
325
326 void Camera::OnRequestReceived(
327         const Api::EventGetPreviewNodeSharedPtr & event)
328 {
329     LogDebug("enter");
330
331     event->switchToManualAnswer();
332
333     LogDebug("start createPreview");
334
335     m_wrtCamera->createPreviewNode(camPreviewSuccessCallback,
336                                    camPreviewErrorCallback,
337                                    setPendingOperation,
338                                    createPrivateOpaqueData(this,event));
339     LogDebug("leaving");
340 }
341
342 void Camera::camCaptureImageSuccessCallback(
343         const char* filename, void* data)
344 {
345     LogDebug("*Picture* Captured. !!!");
346
347     CallbackHandler<Api::EventTakePictureSharedPtr> handler(data);
348     handler.handleSuccessCallback(const_cast<char*>(filename));
349 }
350
351 void Camera::camCaptureVideoSuccessCallback(const char* filename, void* data)
352 {
353     LogDebug("*Video* Captured. !!!");
354
355     CallbackHandler<Api::EventBeginRecordingSharedPtr> handler(data);
356     handler.handleSuccessCallback(const_cast<char*>(filename));
357 }
358
359 void Camera::camPreviewSuccessCallback(
360         Commons::IWrtCamera::CameraPreviewNode node, void* data)
361 {
362     LogDebug("enter");
363
364     CallbackHandler<Api::EventGetPreviewNodeSharedPtr> handler(data);
365     handler.handleSuccessCallback(node);
366 }
367
368 void Camera::camPreviewErrorCallback(int errorCode, void* data)
369 {
370     LogDebug("enter");
371
372     CallbackHandler<Api::EventGetPreviewNodeSharedPtr> handler(data);
373     handler.handleErrorCallback(errorCode);
374 }
375
376 void Camera::camCaptureImageErrorCallback(int errorCode, void* data)
377 {
378     LogDebug("enter");
379
380     CallbackHandler<Api::EventTakePictureSharedPtr> handler(data);
381     handler.handleErrorCallback(errorCode);
382 }
383
384 void Camera::camCaptureVideoErrorCallback(int errorCode, void* data)
385 {
386     LogDebug("enter");
387
388     CallbackHandler<Api::EventBeginRecordingSharedPtr> handler(data);
389     handler.handleErrorCallback(errorCode);
390 }
391
392 void Camera::OnEventReceived(const JobDoneVideoRecordingEvent &event)
393 {
394     LogDebug("enter");
395     if (m_stateRecordingVideo == COMPLETED && event.GetArg0()) {
396         EventRequestReceiver<Api::EventBeginRecording>::
397             ManualAnswer(event.GetArg0());
398         //event.Reset();
399     }
400     m_stateRecordingVideo = Camera::IDLE;
401 }
402
403 void Camera::OnEventReceived(const JobDoneCreatePreviewEvent &event)
404 {
405     OnJobDoneReceived(event.GetArg0());
406 }
407
408 void Camera::OnEventReceived(const JobDoneTakePictureEvent &event)
409 {
410     OnJobDoneReceived(event.GetArg0());
411 }
412
413 void Camera::OnCancelEvent(
414         const Api::EventBeginRecordingSharedPtr& event)
415 {
416     LogDebug(__FUNCTION__);
417
418     if (Camera::PROCESSING == m_stateRecordingVideo) {
419         if (event->checkPendingOperation()) {
420             m_wrtCamera->cancelAsyncOperation(event->getPendingOperation());
421         }
422         setRecordingState(Camera::IDLE);
423     } else {
424         LogError("Cancel invoked, but the state is wrong");
425     }
426 }
427
428 void Camera::OnCancelEvent(const Api::EventTakePictureSharedPtr& event)
429 {
430     cancelEvent(event);
431 }
432
433 void Camera::OnCancelEvent(
434     const Api::EventGetPreviewNodeSharedPtr& event)
435 {
436     cancelEvent(event);
437 }
438
439 void Camera::setRecordingState(CameraState state)
440 {
441     m_stateRecordingVideo = state;
442 }
443
444 void Camera::setPendingOperation(
445     Commons::IWrtCamera::CameraPendingOperation pendingOperation, void* data)
446 {
447     LogDebug("Set pending operation callback invoked");
448
449     Assert(data);
450     OpaquePrivateData* opaqueData = static_cast<OpaquePrivateData*> (data);
451     Assert(opaqueData->cameraPrivateData);
452
453     switch (opaqueData->eventTypeId) {
454     case BeginRecordingType:
455         {
456             static_cast<CameraPrivateData<Api::EventBeginRecordingSharedPtr>* > (
457                     opaqueData->cameraPrivateData)
458                 ->event->setPendingOperation(pendingOperation);
459             break;
460         }
461     case CreatePreviewType:
462         {
463             static_cast<CameraPrivateData<Api::EventGetPreviewNodeSharedPtr>* > (
464                     opaqueData->cameraPrivateData)
465                 ->event->setPendingOperation(pendingOperation);
466             break;
467         }
468     case TakePictureType:
469         {
470             static_cast<CameraPrivateData<Api::EventGetPreviewNodeSharedPtr>* > (
471                     opaqueData->cameraPrivateData)
472                 ->event->setPendingOperation(pendingOperation);
473             break;
474         }
475         default:
476             Assert(0);
477     }
478 }
479
480
481 }
482 }