Add smack rule
[apps/core/preloaded/ug-camera-efl.git] / src / cam_continuous_shot.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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
18 #include "cam_continuous_shot.h"
19 #include "cam_ta.h"
20 #include "cam_error.h"
21 #include "cam_mm.h"
22 #include "cam_sound.h"
23 #include "cam_file.h"
24 #include "camera_utils.h"
25 #include "cam_app.h"
26
27 /*
28 static Ecore_Timer *conti_update_progressbar_timer = NULL;
29 */
30 static int pre_shot_num = 0;
31 static pthread_t file_save_thread;
32 static pthread_mutex_t file_save_mutex;
33 static pthread_cond_t file_save_cond;
34 static GQueue *file_save_queue;
35
36 static gboolean __data_init(void *data);
37 static Eina_Bool __update_pb_timer_cb(void *data);
38 static void __set_error(CamContinuousShotData *continuous_shot_data,
39                                                 int code, char *message);
40
41
42 static gboolean __data_init(void *data)
43 {
44         struct appdata *ad = (struct appdata *)data;
45         CamAppData *camapp = NULL;
46         gchar *temp_file_name1 = NULL, *filename = NULL;
47
48         cam_retvm_if(ad == NULL, FALSE, "appdata is NULL");
49         camapp = ad->camapp_handle;
50         cam_retvm_if(camapp == NULL, FALSE, "camapp_handle is NULL");
51
52         camapp->continuous_shot_data = (CamContinuousShotData *)malloc(sizeof(CamContinuousShotData));
53         if (camapp->continuous_shot_data == NULL) {
54                 cam_critical(LOG_SYS, "continuous_shot_data malloc failed.");
55                 return FALSE;
56         }
57
58         camapp->continuous_shot_data->shot_num = 0;
59         camapp->continuous_shot_data->lock = FALSE;
60         camapp->continuous_shot_data->capture_status = CAM_CONTI_SHOT_STATUS_DEFAULT;
61         camapp->continuous_shot_data->error = NULL;
62
63         temp_file_name1 = cam_app_get_next_filename(CAM_FILE_EXTENTION_IMAGE);
64         if (temp_file_name1) {
65                 filename = g_path_get_basename(temp_file_name1);
66                 if (filename) {
67                         char* save_string = NULL;
68                         char* first_filename = strtok_r(filename, ".",&save_string);
69                         if (first_filename == NULL) {
70                                 if (filename != NULL) {
71                                         free(filename);
72                                         filename = NULL;
73                                         save_string = NULL;
74                                 }
75                                 return FALSE;
76                         }
77                         camapp->continuous_shot_data->first_filename = strdup(first_filename);
78                         if (filename != NULL) {
79                                 free(filename);
80                                 filename = NULL;
81                                 save_string = NULL;
82                         }
83                 }
84                 free(temp_file_name1);
85                 temp_file_name1 = NULL;
86         }
87
88         return TRUE;
89 }
90
91
92 static Eina_Bool __update_pb_timer_cb(void *data)
93 {
94         struct appdata *ad = data;
95         cam_retv_if(ad == NULL, FALSE);
96         CamAppData *camapp = ad->camapp_handle;
97         cam_retv_if(camapp == NULL, FALSE);
98         char pb_text[10] = "";
99         double pb_value = 0.0;
100         camapp = ad->camapp_handle;
101         DEBUG_TRACE("camapp->continuous_shot_data->shot_num %d", camapp->continuous_shot_data->shot_num);
102         DEBUG_TRACE("pre_shot_num %d", pre_shot_num);
103         if (camapp->continuous_shot_data->shot_num > pre_shot_num) {
104                 pb_value =
105                     (double)camapp->continuous_shot_data->shot_num /
106                     (double)MAX_CONTINUOUS_SHOT;
107                 cam_app_set_progressbar_value(ad, pb_value);
108
109                 snprintf(pb_text, sizeof(pb_text), "%d/%d",
110                          camapp->continuous_shot_data->shot_num,
111                          MAX_CONTINUOUS_SHOT);
112                 cam_app_set_progressbar_text(ad, pb_text);
113
114                 pre_shot_num = camapp->continuous_shot_data->shot_num;
115         }
116
117         return 1;
118 }
119
120 void cam_continuous_shot_update_progress_value(void *data)
121 {
122         struct appdata *ad = data;
123         cam_ret_if(ad == NULL);
124         CamAppData *camapp = ad->camapp_handle;
125         cam_ret_if(camapp == NULL);
126         cam_ret_if(camapp->continuous_shot_data == NULL);
127
128         char pb_text[10] = "";
129         double pb_value = 0.0;
130         camapp = ad->camapp_handle;
131         DEBUG_TRACE("camapp->continuous_shot_data->shot_num %d", camapp->continuous_shot_data->shot_num);
132         DEBUG_TRACE("pre_shot_num %d", pre_shot_num);
133         DEBUG_TRACE("ad->progressbar %p", ad->progressbar);
134         if (camapp->continuous_shot_data->shot_num > pre_shot_num) {
135                 pb_value = (double)camapp->continuous_shot_data->shot_num / (double)MAX_CONTINUOUS_SHOT;
136                 cam_app_set_progressbar_value(ad, pb_value);
137                 snprintf(pb_text, sizeof(pb_text), "%d/%d", camapp->continuous_shot_data->shot_num, MAX_CONTINUOUS_SHOT);
138                 cam_app_set_progressbar_text(ad, pb_text);
139                 pre_shot_num = camapp->continuous_shot_data->shot_num;
140         }
141
142 }
143
144 static void __set_error(CamContinuousShotData *continuous_shot_data, int code, char *message)
145 {
146         cam_debug(LOG_SYS, " start");
147
148         if (continuous_shot_data == NULL)
149                 return;
150
151         if (continuous_shot_data->error == NULL) {
152                 if (cam_utils_check_mmc_status() == VCONFKEY_SYSMAN_MMC_REMOVED) {
153                         continuous_shot_data->error =
154                             cam_error_new_literal(CAM_CONTI_SHOT_ERROR_MMC_REMOVED,
155                                           dgettext(PACKAGE, "IDS_CAM_POP_MEMORY_CARD_REMOVED"));
156                 } else {
157                         if (message)
158                                 continuous_shot_data->error = cam_error_new_literal(code, message);
159                 }
160         }
161
162         continuous_shot_data->capture_status = CAM_CONTI_SHOT_STATUS_STOPPING;
163         cam_mm_set_conti_shot_break(TRUE);
164
165         if (continuous_shot_data->error && continuous_shot_data->error->message)
166                 cam_critical(LOG_SYS, " Done: Continuous shot failed [%s]", continuous_shot_data->error->message);
167 }
168
169
170 void cam_continuous_shot_data_free(void *data)
171 {
172         struct appdata *ad = (struct appdata *)data;
173         CamAppData *camapp = NULL;
174
175         cam_retm_if(ad == NULL, "appdata is NULL");
176         camapp = ad->camapp_handle;
177         cam_retm_if(camapp == NULL, "camapp_handle is NULL");
178
179         cam_debug(LOG_FILE, "");
180
181         if (camapp->continuous_shot_data) {
182                 int i = 0;
183                 for (i = 0; i < camapp->continuous_shot_data->shot_num; i++) {
184                         if (camapp->continuous_shot_data->file_path[i]) {
185                                 free(camapp->continuous_shot_data->file_path[i]);
186                                 camapp->continuous_shot_data->file_path[i] = NULL;
187                         }
188                 }
189
190                 if(camapp->continuous_shot_data->first_filename){
191                         free(camapp->continuous_shot_data->first_filename);
192                         camapp->continuous_shot_data->first_filename = NULL;
193                 }
194
195                 if (camapp->continuous_shot_data->error) {
196                         g_error_free(camapp->continuous_shot_data->error);
197                         camapp->continuous_shot_data->error = NULL;
198                 }
199
200                 free(camapp->continuous_shot_data);
201                 camapp->continuous_shot_data = NULL;
202
203                 cam_debug(LOG_UI, "remove continuous_shot_data");
204         }
205
206         cam_debug(LOG_FILE, " done.");
207
208         return;
209 }
210
211 void cam_continuous_shot_capture_start(void *data)
212 {
213         DEBUG_TRACE("");
214         struct appdata *ad = (struct appdata *)data;
215
216         cam_retm_if(ad == NULL, "appdata is NULL");
217         CamAppData *camapp = ad->camapp_handle;
218
219         cam_continuous_shot_data_free(ad);
220         __data_init(ad);
221
222         DEL_EVAS_OBJECT(ad->progressbar_edje);
223         elm_object_part_content_unset(ad->ug_base, "progressbar_layout");
224
225         cam_app_create_progressbar(ad);
226         ad->progressbar_edje = cam_app_load_edj(ad->ug_base, CAM_MAIN_LAYOUT_EDJ_NAME, "progressbar");
227
228         cam_retm_if(ad->progressbar_edje == NULL,"ad->progressbar_edje is NULL");
229         elm_object_part_content_set(ad->progressbar_edje, "progressbar", ad->progressbar);
230         elm_object_part_content_set(ad->ug_base, "progressbar_layout", ad->progressbar_edje);
231
232         switch (ad->target_direction) {
233         case CAM_TARGET_DIRECTION_LANDSCAPE:
234         case CAM_TARGET_DIRECTION_LANDSCAPE_INVERSE:
235                 edje_object_signal_emit(_EDJ(ad->progressbar_edje), "progressbar,default", "prog");
236                 break;
237         case CAM_TARGET_DIRECTION_PORTRAIT:
238         case CAM_TARGET_DIRECTION_PORTRAIT_INVERSE:
239                 edje_object_signal_emit(_EDJ(ad->progressbar_edje), "progressbar,vertical", "prog");
240                 break;
241         default:
242                 DEBUG_TRACE("wow, reached un-able reached codes");
243         }
244
245         pre_shot_num = 0;
246
247         cam_set_orient_value(ad);
248
249         int remain = 0;
250         int max_count = 0;
251         remain = cam_system_get_still_count_by_resolution(ad);
252
253         if(remain <= MAX_CONTINUOUS_SHOT)
254                 max_count = remain;
255         else
256                 max_count = MAX_CONTINUOUS_SHOT;
257
258         if(max_count > 1) {
259                 camapp->continuous_shot_data->capture_status = CAM_CONTI_SHOT_STATUS_CAPTURING;
260                 cam_toolbar_update(ad);
261                 cam_mm_continuous_capture_start(max_count, CONTINUOUS_SHOT_INTERVAL, (camera_capturing_cb)cam_continuous_shot_capture_callback, camapp->capture_completed_cb, (void*)ad);
262         } else {
263                 cam_mm_capture_start(camapp->capture_cb, camapp->capture_completed_cb, (void*)ad);
264         }
265 }
266
267 void *cam_continuous_shot_file_save_thread_run(void *data)
268 {
269         struct appdata *ad = (struct appdata *)data;
270         cam_retvm_if(ad == NULL, NULL, "appdata is NULL");
271         CamAppData *camapp = ad->camapp_handle;
272         cam_retvm_if(camapp == NULL, NULL, "camapp_handle is NULL");
273
274         gboolean Exit_loop = FALSE;
275
276         cam_debug(LOG_FILE, "");
277
278         pthread_mutex_lock(&file_save_mutex);
279
280         while (!Exit_loop) {
281                 cam_debug(LOG_FILE, " wait signal...");
282
283                 pthread_cond_wait(&file_save_cond, &file_save_mutex);
284
285                 cam_debug(LOG_FILE, " signal received");
286
287                 while (!g_queue_is_empty(file_save_queue)) {
288                         File_Save_Info *file_info = NULL;
289                         /*TODO: consider sync*/
290                         file_info = g_queue_pop_head(file_save_queue);
291
292                         if ((file_info == NULL) || (file_info->cmd == NULL)) {
293                                 __set_error(camapp->continuous_shot_data, CAM_CONTI_SHOT_ERROR_FILE_WRITE, _("File Info Error"));
294                                 pthread_mutex_unlock(&file_save_mutex);
295                                 return NULL;
296                         }
297
298                         DEBUG_TRACE("%p", file_info);
299             DEBUG_TRACE("file_info->cmd %s", file_info->cmd);
300                         DEBUG_TRACE("file_info->filename %s", file_info->filename);
301
302                         if (strcmp(SAVE_THREAD_EXIT, file_info->cmd) == 0) {
303                                 if (file_info->buffer != NULL) {
304                                         free(file_info->buffer);
305                                         file_info->buffer = NULL;
306                                 }
307                                 if (file_info->filename != NULL) {
308                                         free(file_info->filename);
309                                         file_info->filename = NULL;
310                                 }
311                                 if (file_info->cmd == NULL) {
312                                         free(file_info->cmd);
313                                         file_info->cmd = NULL;
314                                 }
315                                 free(file_info);
316                                 file_info = NULL;
317                                 Exit_loop = TRUE;
318                                 break;
319                         }
320
321                         if (strcmp(SAVE_THREAD_FINISH, file_info->cmd) == 0) {
322                                 sync();
323                                 cam_utils_request_main_pipe_handler(ad, NULL, CAM_MAIN_PIPE_OP_TYPE_BEST_SHOT_IMAGE_HANDLE);
324                 } else {
325                         if (file_info->filename == NULL) {
326                                         __set_error(camapp->continuous_shot_data, CAM_CONTI_SHOT_ERROR_FILE_WRITE, _("File Name Error"));
327                                         pthread_mutex_unlock(&file_save_mutex);
328                                         return NULL;
329                         }
330
331                                 /*note: write file*/
332                                 FILE *fd = fopen(file_info->filename, "w+");
333                                 if (fd == NULL) {
334                                         __set_error(camapp->continuous_shot_data, CAM_CONTI_SHOT_ERROR_FILE_WRITE, _("File Open Fail"));
335                                         pthread_mutex_unlock(&file_save_mutex);
336                                         return NULL;
337                                 } else {
338                                         int ret = fwrite(file_info->buffer, file_info->buf_size, 1, fd);
339                     fclose(fd);
340
341                                         fd = NULL;
342                                         if (ret != 1) {
343                                                 __set_error(camapp->continuous_shot_data, CAM_CONTI_SHOT_ERROR_FILE_WRITE, _("File Write Fail"));
344                                                 pthread_mutex_unlock(&file_save_mutex);
345                                                 return NULL;
346                                         }
347                                 }
348
349                     /*note: reg to media info*/
350                         __cam_single_shot_reg_file(file_info->filename);
351
352                                 cam_debug(LOG_FILE, " register done.");
353
354                                 if (file_info->buffer != NULL) {
355                                         free(file_info->buffer);
356                                         file_info->buffer = NULL;
357                                 }
358
359                                 if (file_info->filename != NULL) {
360                                         free(file_info->filename);
361                                         file_info->filename = NULL;
362                                 }
363
364                                 if (file_info->cmd == NULL) {
365                                         free(file_info->cmd);
366                                         file_info->cmd = NULL;
367                                 }
368
369                                 free(file_info);
370                                 file_info = NULL;
371                                 cam_debug(LOG_FILE, " save file done.");
372                         }
373                 }
374         }
375
376         pthread_mutex_unlock(&file_save_mutex);
377
378         pthread_mutex_destroy(&file_save_mutex);
379         pthread_cond_destroy(&file_save_cond);
380
381         cam_debug(LOG_SYS, " thread exit...");
382
383         return NULL;
384 }
385
386 void cam_continuous_shot_file_save_thread_exit(void *data)
387 {
388         if (file_save_queue != NULL) {
389                 File_Save_Info *file_info = calloc(1, sizeof(File_Save_Info));
390
391                 if (file_info == NULL)
392                         return;
393
394                 file_info->buffer = NULL;
395                 file_info->buf_size = 0;
396                 file_info->filename = NULL;
397                 file_info->cmd = strdup(SAVE_THREAD_EXIT);
398                 g_queue_push_tail(file_save_queue, file_info);
399                 pthread_cond_signal(&file_save_cond);
400         }
401         return;
402 }
403
404 gboolean cam_continuous_shot_create_file_save_thread(void *data)
405 {
406         struct appdata *ad = (struct appdata *)data;
407
408         int err = 0;
409         cam_debug(LOG_SYS, "");
410
411         cam_retvm_if(ad == NULL, FALSE, "appdata is NULL");
412
413         err = pthread_mutex_init(&file_save_mutex, NULL);
414         if (err != 0) {
415                 cam_critical(LOG_CAM,
416                              "Create Camera file register mutex failed");
417                 return FALSE;
418         }
419
420         err = pthread_cond_init(&file_save_cond, NULL);
421         if (err != 0) {
422                 cam_critical(LOG_CAM,
423                              "Create Camera file register cond failed");
424                 return FALSE;
425         }
426
427         file_save_queue = g_queue_new();
428         if (file_save_queue == NULL) {
429                 cam_critical(LOG_CAM,
430                              "Create Camera file register queue failed");
431                 return FALSE;
432         }
433
434         err = pthread_create(&file_save_thread, NULL, cam_continuous_shot_file_save_thread_run, (void *)ad);
435         if (err != 0) {
436                 cam_critical(LOG_CAM,
437                              "Create Camera file register thread failed");
438                 return FALSE;
439         }
440
441         return TRUE;
442 }
443
444 void cam_continuous_shot_finish_save_image()
445 {
446         File_Save_Info *file_info = calloc(1, sizeof(File_Save_Info));
447
448         if (file_info == NULL)
449                 return;
450
451         file_info->buffer = NULL;
452         file_info->buf_size = 0;
453         file_info->filename = NULL;
454         file_info->cmd = strdup(SAVE_THREAD_FINISH);
455
456         DEBUG_TRACE("file_info->cmd %s", file_info->cmd);
457         g_queue_push_tail(file_save_queue, file_info);
458         pthread_cond_signal(&file_save_cond);
459 }
460
461 void cam_continuous_shot_capture_callback(camera_image_data_s* image,
462                                                                 camera_image_data_s* postview,
463                                                                 camera_image_data_s* thumbnail,
464                                                                 void *user_data)
465 {
466         struct appdata *ad = (struct appdata *)user_data;
467         cam_retm_if(ad == NULL, "appdata is NULL");
468         CamAppData *camapp = ad->camapp_handle;
469         cam_retm_if(camapp == NULL, "camapp is NULL");
470
471         cam_debug(LOG_MM, "");
472
473         if (ad->ug_state == CAM_UG_TERMINATE_STATE
474                 || ad->ug_state == CAM_UG_PAUSE_STATE) {/*NOTE: in pause state, and terminate state, not cb*/
475                 return;
476         }
477
478         gchar *filename = NULL;
479
480         if (image == NULL) {
481                 if (camapp->filename)
482                         free(camapp->filename);
483                 camapp->filename = NULL;
484                 DEBUG_TRACE(" ERROR - capture data is NULL");
485                 cam_mm_set_conti_shot_break(TRUE);
486                 return;
487         }
488         if (image->data == NULL) {
489                 if (camapp->filename)
490                         free(camapp->filename);
491                 camapp->filename = NULL;
492                 DEBUG_TRACE(" ERROR - capture data is NULL");
493                 cam_mm_set_conti_shot_break(TRUE);
494                 return;
495         }
496
497
498         if (camapp->continuous_shot_data == NULL) {
499                 cam_critical(LOG_SYS, " continuous_shot_data is NULL");
500                 CAM_TA_ACUM_ITEM_END(" cam_continuous_shot_capture_callback", 0);
501                 cam_mm_set_conti_shot_break(TRUE);
502                 return;
503         }
504
505         if (camapp->continuous_shot_data->lock == TRUE) {
506                 cam_debug(LOG_MM, " Skip this data... because capture was stopped.");
507                 CAM_TA_ACUM_ITEM_END(" cam_continuous_shot_capture_callback", 0);
508                 cam_mm_set_conti_shot_break(TRUE);
509                 return;
510         }
511
512         camapp->continuous_shot_data->lock = TRUE;
513
514 #ifdef USE_CAMERA_APP_SHUTTER_SOUND
515         __cam_ta__(" cam_sound_play", cam_sound_play(camapp->shutter_sound, ad););
516 #endif
517         filename = cam_file_get_next_filename_for_multishot(cam_app_get_target_path(),
518                                                                 (const gchar *)camapp->continuous_shot_data->first_filename,
519                                                                 (const gint) camapp->continuous_shot_data->shot_num,
520                                                                 (const gchar *)".jpg");
521
522         CAM_TA_ACUM_ITEM_BEGIN("                File open+write", 0);
523
524         if (filename == NULL) {
525                 DEBUG_TRACE("");
526                 return;
527         }
528
529         if (image->format == CAMERA_PIXEL_FORMAT_JPEG) {
530                 /*TODO: use thread to save file*/
531                 void *image_buffer = calloc(1, image->size);
532                 if (image_buffer == NULL)
533                         return;
534
535                 memcpy(image_buffer, image->data, image->size);
536                 File_Save_Info *file_info = calloc(1, sizeof(File_Save_Info));
537
538                 if (file_info == NULL) {
539                         if (image_buffer)
540                                 free(image_buffer);
541                         return;
542                 }
543
544                 file_info->buffer = image_buffer;
545                 file_info->buf_size = image->size;
546                 file_info->filename = strdup(filename);
547                 file_info->cmd = strdup("run_thread");
548
549         DEBUG_TRACE("file_info->cmd %s", file_info->cmd);
550                 g_queue_push_tail(file_save_queue, file_info);
551                 pthread_cond_signal(&file_save_cond);
552
553                 {/*TODO: consider  synchro issue in future*/
554                         if (camapp->continuous_shot_data) {
555                                 camapp->continuous_shot_data->file_path[camapp->continuous_shot_data->shot_num] = filename;
556                                 camapp->continuous_shot_data->shot_num++;
557                                 cam_debug(LOG_MM, " Continuous shot captured [%s] count [%d]", filename, camapp->continuous_shot_data->shot_num);
558                         } else {
559                                 cam_debug(LOG_MM, " continuous_shot_data is null");
560                                 return;
561                         }
562                 }
563         }
564
565         CAM_TA_ACUM_ITEM_END("            File open+write", 0);
566
567         if (camapp->continuous_shot_data->capture_status == CAM_CONTI_SHOT_STATUS_STOPPING
568                 && camapp->continuous_shot_data->shot_num == 1) {
569                 cam_mm_set_conti_shot_break(TRUE);
570         }
571
572         camapp->continuous_shot_data->lock = FALSE;
573
574         cam_utils_request_main_pipe_handler(ad, NULL, CAM_MAIN_PIPE_OP_TYPE_BURST_SHOT_UPDATE_PROGRESS);
575
576         if (ad->stop_continuous_shot == TRUE
577                 || (camapp->continuous_shot_data && camapp->continuous_shot_data->shot_num == MAX_CONTINUOUS_SHOT)) {
578
579                 camapp->continuous_shot_data->capture_status = CAM_CONTI_SHOT_STATUS_STOPPING;
580                 cam_debug(LOG_UI, " Captured count [%d]", camapp->continuous_shot_data->shot_num);
581
582                 if (ad->stop_continuous_shot)
583                         cam_mm_set_conti_shot_break(TRUE);
584
585                 ad->stop_continuous_shot =FALSE;
586         }
587
588         return;
589
590 }
591
592 gboolean cam_continuous_shot_reg_file(int shot_num, char *file_path[])
593 {
594         int i = 0;
595         GError *error = NULL;
596
597         cam_debug(LOG_FILE, "");
598
599         for (i = 0; i < shot_num; i++) {
600                 if (file_path[i]) {
601                         cam_debug(LOG_FILE, "register file : %s", file_path[i]);
602
603                         if (!cam_file_register(file_path[i], &error)) {
604                                 cam_critical(LOG_FILE,
605                                              "cam_file_register fail");
606                                 if (error != NULL) {
607                                         cam_critical(LOG_FILE,
608                                                      "cam_file_register error [%s]",
609                                                      error->message);
610                                         g_error_free(error);
611                                         error = NULL;
612                                 }
613                         }
614                 }
615         }
616
617         cam_debug(LOG_SYS, " file register done.");
618
619         return TRUE;
620 }
621