2 * Copyright 2012 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
18 #include "cam_continuous_shot.h"
20 #include "cam_error.h"
22 #include "cam_sound.h"
24 #include "camera_utils.h"
28 static Ecore_Timer *conti_update_progressbar_timer = NULL;
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;
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);
42 static gboolean __data_init(void *data)
44 struct appdata *ad = (struct appdata *)data;
45 CamAppData *camapp = NULL;
46 gchar *temp_file_name1 = NULL, *filename = NULL;
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");
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.");
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;
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);
67 char* save_string = NULL;
68 char* first_filename = strtok_r(filename, ".",&save_string);
69 if (first_filename == NULL) {
70 if (filename != NULL) {
77 camapp->continuous_shot_data->first_filename = strdup(first_filename);
78 if (filename != NULL) {
84 free(temp_file_name1);
85 temp_file_name1 = NULL;
92 static Eina_Bool __update_pb_timer_cb(void *data)
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) {
105 (double)camapp->continuous_shot_data->shot_num /
106 (double)MAX_CONTINUOUS_SHOT;
107 cam_app_set_progressbar_value(ad, pb_value);
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);
114 pre_shot_num = camapp->continuous_shot_data->shot_num;
120 void cam_continuous_shot_update_progress_value(void *data)
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);
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;
144 static void __set_error(CamContinuousShotData *continuous_shot_data, int code, char *message)
146 cam_debug(LOG_SYS, " start");
148 if (continuous_shot_data == NULL)
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"));
158 continuous_shot_data->error = cam_error_new_literal(code, message);
162 continuous_shot_data->capture_status = CAM_CONTI_SHOT_STATUS_STOPPING;
163 cam_mm_set_conti_shot_break(TRUE);
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);
170 void cam_continuous_shot_data_free(void *data)
172 struct appdata *ad = (struct appdata *)data;
173 CamAppData *camapp = NULL;
175 cam_retm_if(ad == NULL, "appdata is NULL");
176 camapp = ad->camapp_handle;
177 cam_retm_if(camapp == NULL, "camapp_handle is NULL");
179 cam_debug(LOG_FILE, "");
181 if (camapp->continuous_shot_data) {
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;
190 if(camapp->continuous_shot_data->first_filename){
191 free(camapp->continuous_shot_data->first_filename);
192 camapp->continuous_shot_data->first_filename = NULL;
195 if (camapp->continuous_shot_data->error) {
196 g_error_free(camapp->continuous_shot_data->error);
197 camapp->continuous_shot_data->error = NULL;
200 free(camapp->continuous_shot_data);
201 camapp->continuous_shot_data = NULL;
203 cam_debug(LOG_UI, "remove continuous_shot_data");
206 cam_debug(LOG_FILE, " done.");
211 void cam_continuous_shot_capture_start(void *data)
214 struct appdata *ad = (struct appdata *)data;
216 cam_retm_if(ad == NULL, "appdata is NULL");
217 CamAppData *camapp = ad->camapp_handle;
219 cam_continuous_shot_data_free(ad);
222 DEL_EVAS_OBJECT(ad->progressbar_edje);
223 elm_object_part_content_unset(ad->ug_base, "progressbar_layout");
225 cam_app_create_progressbar(ad);
226 ad->progressbar_edje = cam_app_load_edj(ad->ug_base, CAM_MAIN_LAYOUT_EDJ_NAME, "progressbar");
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);
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");
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");
242 DEBUG_TRACE("wow, reached un-able reached codes");
247 cam_set_orient_value(ad);
251 remain = cam_system_get_still_count_by_resolution(ad);
253 if(remain <= MAX_CONTINUOUS_SHOT)
256 max_count = MAX_CONTINUOUS_SHOT;
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);
263 cam_mm_capture_start(camapp->capture_cb, camapp->capture_completed_cb, (void*)ad);
267 void *cam_continuous_shot_file_save_thread_run(void *data)
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");
274 gboolean Exit_loop = FALSE;
276 cam_debug(LOG_FILE, "");
278 pthread_mutex_lock(&file_save_mutex);
281 cam_debug(LOG_FILE, " wait signal...");
283 pthread_cond_wait(&file_save_cond, &file_save_mutex);
285 cam_debug(LOG_FILE, " signal received");
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);
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);
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);
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;
307 if (file_info->filename != NULL) {
308 free(file_info->filename);
309 file_info->filename = NULL;
311 if (file_info->cmd == NULL) {
312 free(file_info->cmd);
313 file_info->cmd = NULL;
321 if (strcmp(SAVE_THREAD_FINISH, file_info->cmd) == 0) {
323 cam_utils_request_main_pipe_handler(ad, NULL, CAM_MAIN_PIPE_OP_TYPE_BEST_SHOT_IMAGE_HANDLE);
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);
332 FILE *fd = fopen(file_info->filename, "w+");
334 __set_error(camapp->continuous_shot_data, CAM_CONTI_SHOT_ERROR_FILE_WRITE, _("File Open Fail"));
335 pthread_mutex_unlock(&file_save_mutex);
338 int ret = fwrite(file_info->buffer, file_info->buf_size, 1, fd);
343 __set_error(camapp->continuous_shot_data, CAM_CONTI_SHOT_ERROR_FILE_WRITE, _("File Write Fail"));
344 pthread_mutex_unlock(&file_save_mutex);
349 /*note: reg to media info*/
350 __cam_single_shot_reg_file(file_info->filename);
352 cam_debug(LOG_FILE, " register done.");
354 if (file_info->buffer != NULL) {
355 free(file_info->buffer);
356 file_info->buffer = NULL;
359 if (file_info->filename != NULL) {
360 free(file_info->filename);
361 file_info->filename = NULL;
364 if (file_info->cmd == NULL) {
365 free(file_info->cmd);
366 file_info->cmd = NULL;
371 cam_debug(LOG_FILE, " save file done.");
376 pthread_mutex_unlock(&file_save_mutex);
378 pthread_mutex_destroy(&file_save_mutex);
379 pthread_cond_destroy(&file_save_cond);
381 cam_debug(LOG_SYS, " thread exit...");
386 void cam_continuous_shot_file_save_thread_exit(void *data)
388 if (file_save_queue != NULL) {
389 File_Save_Info *file_info = calloc(1, sizeof(File_Save_Info));
391 if (file_info == NULL)
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);
404 gboolean cam_continuous_shot_create_file_save_thread(void *data)
406 struct appdata *ad = (struct appdata *)data;
409 cam_debug(LOG_SYS, "");
411 cam_retvm_if(ad == NULL, FALSE, "appdata is NULL");
413 err = pthread_mutex_init(&file_save_mutex, NULL);
415 cam_critical(LOG_CAM,
416 "Create Camera file register mutex failed");
420 err = pthread_cond_init(&file_save_cond, NULL);
422 cam_critical(LOG_CAM,
423 "Create Camera file register cond failed");
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");
434 err = pthread_create(&file_save_thread, NULL, cam_continuous_shot_file_save_thread_run, (void *)ad);
436 cam_critical(LOG_CAM,
437 "Create Camera file register thread failed");
444 void cam_continuous_shot_finish_save_image()
446 File_Save_Info *file_info = calloc(1, sizeof(File_Save_Info));
448 if (file_info == NULL)
451 file_info->buffer = NULL;
452 file_info->buf_size = 0;
453 file_info->filename = NULL;
454 file_info->cmd = strdup(SAVE_THREAD_FINISH);
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);
461 void cam_continuous_shot_capture_callback(camera_image_data_s* image,
462 camera_image_data_s* postview,
463 camera_image_data_s* thumbnail,
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");
471 cam_debug(LOG_MM, "");
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*/
478 gchar *filename = 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);
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);
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);
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);
512 camapp->continuous_shot_data->lock = TRUE;
514 #ifdef USE_CAMERA_APP_SHUTTER_SOUND
515 __cam_ta__(" cam_sound_play", cam_sound_play(camapp->shutter_sound, ad););
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");
522 CAM_TA_ACUM_ITEM_BEGIN(" File open+write", 0);
524 if (filename == NULL) {
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)
535 memcpy(image_buffer, image->data, image->size);
536 File_Save_Info *file_info = calloc(1, sizeof(File_Save_Info));
538 if (file_info == NULL) {
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");
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);
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);
559 cam_debug(LOG_MM, " continuous_shot_data is null");
565 CAM_TA_ACUM_ITEM_END(" File open+write", 0);
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);
572 camapp->continuous_shot_data->lock = FALSE;
574 cam_utils_request_main_pipe_handler(ad, NULL, CAM_MAIN_PIPE_OP_TYPE_BURST_SHOT_UPDATE_PROGRESS);
576 if (ad->stop_continuous_shot == TRUE
577 || (camapp->continuous_shot_data && camapp->continuous_shot_data->shot_num == MAX_CONTINUOUS_SHOT)) {
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);
582 if (ad->stop_continuous_shot)
583 cam_mm_set_conti_shot_break(TRUE);
585 ad->stop_continuous_shot =FALSE;
592 gboolean cam_continuous_shot_reg_file(int shot_num, char *file_path[])
595 GError *error = NULL;
597 cam_debug(LOG_FILE, "");
599 for (i = 0; i < shot_num; i++) {
601 cam_debug(LOG_FILE, "register file : %s", file_path[i]);
603 if (!cam_file_register(file_path[i], &error)) {
604 cam_critical(LOG_FILE,
605 "cam_file_register fail");
607 cam_critical(LOG_FILE,
608 "cam_file_register error [%s]",
617 cam_debug(LOG_SYS, " file register done.");