2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.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
8 * http://www.tizenopensource.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 <sys/statvfs.h>
20 #include <vconf-keys.h>
23 #include <media-thumbnail.h>
26 #include "gl-albums.h"
27 #include "gl-gridview.h"
28 #include "gl-listview.h"
30 #include "gl-ui-util.h"
31 #include "gl-controlbar.h"
32 #include "gl-thread-util.h"
34 #include "gl-progressbar.h"
35 #include "gl-ext-ug-load.h"
36 #include "gl-ext-exec.h"
38 #include "gl-nocontents.h"
39 #include "gl-notify.h"
40 #include "gl-editfield.h"
41 #include "gl-strings.h"
42 #include "gl-data-type.h"
47 #define GL_FILE_COPY_BUF_MAX 16384
48 #define GL_CREATE_DIR_MASK_DEFAULT 0775
49 /* Time for displaying progressbar UI compeletely */
50 #define GL_TIMER_INTERVAL_PBAR_SHOWED 0.5
51 #define GL_TIMER_INTERVAL_VIBRATION 0.5
52 #define GL_VIBRATION_DEVICE 0
53 #define GL_VIBRATION_DURATION 500
55 #define GL_ROTATE_DELAY 0.25
58 /* Use timer to show progressbar totally before write pipe */
59 static Eina_Bool _gl_start_thread_op_timer_cb(void *data)
61 gl_dbg("Emit START signal...");
62 GL_CHECK_CANCEL(data);
63 gl_appdata *ad = (gl_appdata *)data;
64 /* Emit signal to notice child thread to handle next item. */
65 gl_thread_emit_next_signal(ad);
66 if (ad->pbarinfo.start_thread_timer) {
67 ecore_timer_del(ad->pbarinfo.start_thread_timer);
68 ad->pbarinfo.start_thread_timer = NULL;
70 return ECORE_CALLBACK_CANCEL;
74 * Use thread to move/delete medias
75 * for displaying progrssabar UI
77 static int _gl_use_thread_operate_medias(void *data, char *pbar_title, int all_cnt, int op_type)
79 gl_dbg("all_cnt: %d, op_type: %d.", all_cnt, op_type);
80 GL_CHECK_VAL(data, -1);
81 gl_appdata *ad = (gl_appdata *)data;
83 /* Initialize thread mutex lock */
84 gl_thread_init_lock(ad);
85 /* Make progressbar */
86 gl_pb_make_thread_pbar(ad, ad->maininfo.win, pbar_title);
87 /* Set pb_cancel, indicates thread operation is beginning */
88 gl_thread_set_cancel_state(ad, GL_PB_CANCEL_NORMAL);
89 /* Initialize progressbar */
90 gl_pb_refresh_thread_pbar(ad, 0, all_cnt);
91 /* Use timer to emit next signal to show progressbarbar totally */
92 if (ad->pbarinfo.start_thread_timer) {
93 ecore_timer_del(ad->pbarinfo.start_thread_timer);
94 ad->pbarinfo.start_thread_timer = NULL;
96 Ecore_Timer *timer = NULL;
97 timer = ecore_timer_add(GL_TIMER_INTERVAL_PBAR_SHOWED,
98 _gl_start_thread_op_timer_cb, ad);
99 ad->pbarinfo.start_thread_timer = timer;
100 /* Set media operation type */
101 ad->maininfo.medias_op_type = op_type;
102 /* Generate child thread */
103 gl_thread_gen_data_thread(ad);
107 static void _gl_db_update_noti_cb(keynode_t *key, void *data)
110 gl_appdata *ad = (gl_appdata *)data;
111 gl_dbgW("VCONFKEY_FILEMANAGER_DB_STATUS changed!");
114 vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &mmc_state);
118 gl_dbg("Error when check MMC Status");
122 if (mmc_state == VCONFKEY_SYSMAN_MMC_MOUNTED)
124 gl_dbg("mmc_state[%d] : VCONFKEY_SYSMAN_MMC_MOUNTED", mmc_state);
125 if (ad->maininfo.mmc_state == GL_MMC_STATE_REMOVED)
126 ad->maininfo.mmc_state = GL_MMC_STATE_ADDING_MOVING;
128 ad->maininfo.mmc_state = GL_MMC_STATE_ADDED;
130 gl_update_view(ad, GL_UPDATE_VIEW_MMC_ADDED);
132 /* Update popup content after albums list updated */
133 if (ad->popupinfo.popup &&
134 (ad->popupinfo.popup_mode == GL_POPUP_THUMB_MOVE)) {
135 gl_dbg("Add MMC albums to popup.");
136 gl_popup_update_content(ad, GL_POPUP_THUMB_MOVE);
139 else if (mmc_state == VCONFKEY_SYSMAN_MMC_REMOVED ||
140 mmc_state == VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED)
142 gl_dbg("mmc_state[%d] : VCONFKEY_SYSMAN_MMC_REMOVED", mmc_state);
143 if (ad->maininfo.mmc_state == GL_MMC_STATE_ADDED_MOVING)
146 * Set pb_cancel status,
147 * indicates MMC removed while moving or deleting.
149 gl_thread_set_cancel_state(ad, GL_PB_CANCEL_MMC);
150 /* MMC moved while moving or deleting */
151 ad->maininfo.mmc_state = GL_MMC_STATE_REMOVED_MOVING;
152 } else if (ad->maininfo.mmc_state == GL_MMC_STATE_REMOVED_MOVING) {
153 gl_dbgW("View updated on GL_MMC_STATE_ADDED_MOVING");
157 /* MMC is extracted */
158 ad->maininfo.mmc_state = GL_MMC_STATE_REMOVED;
161 gl_update_view(ad, GL_UPDATE_VIEW_MMC_REMOVED);
163 /* Update popup content after albums list updated */
164 if (ad->popupinfo.popup &&
165 (ad->popupinfo.popup_mode == GL_POPUP_THUMB_MOVE)) {
166 gl_dbg("Remove MMC albums from popup.");
167 gl_popup_update_content(ad, GL_POPUP_THUMB_MOVE);
174 * @param: b_update_albums_list
175 * True: Update albums list and medias list, then update normal view.
176 * False: Get new medias for current view from DB
177 * then update view to synchronize data with Myfile.
179 * Update edit gridview/listview.
181 static int _gl_update_thumb_items(void *data, bool b_update_albums_list)
183 GL_CHECK_VAL(data, -1);
184 gl_appdata *ad = (gl_appdata *)data;
185 int view_mode = gl_get_view_mode(ad);
186 bool b_edit_m = false;
188 gl_dbg("view_mode: %d, b_update_albums_list: %d.", view_mode,
189 b_update_albums_list);
190 if (view_mode == GL_VIEW_THUMBS_EDIT ||
191 view_mode == GL_VIEW_VIDEOLIST_EDIT) {
192 gl_dbg("Edit view.");
196 if (view_mode == GL_VIEW_VIDEOLIST &&
197 ad->listinfo.played_uuid == NULL &&
198 _gl_data_check_update(ad, false) == false) {
199 gl_dbg("Nothing changed.");
204 * 1, Update albums list and medias_elist,
205 * 2, Update medias_elist.
207 if (b_update_albums_list)
208 gl_refresh_albums_list(ad);
210 _gl_data_update_item_list(ad);
212 if (ad->maininfo.medias_cnt == 0) {
213 /* All items deleted, change to albms view */
214 gl_pop_to_ctrlbar_ly(ad, !b_update_albums_list);
216 if (view_mode == GL_VIEW_VIDEOLIST) {
217 gl_list_update_view(ad);
218 } else if (_gl_nocontents_show(ad)) {
219 gl_dbg("none video/image, show nocontents");
220 /* Remove invalid widgets */
221 gl_del_invalid_widgets(ad, GL_INVALID_NEW_ENTRY_NOC);
222 } else if (view_mode == GL_VIEW_THUMBS) {
223 gl_grid_update_items(ad);
224 } else if (view_mode == GL_VIEW_THUMBS_EDIT) {
225 gl_grid_change_to_edit(ad);
226 } else if (view_mode == GL_VIEW_VIDEOLIST_EDIT) {
227 gl_list_change_to_edit(ad);
230 /* Normal view, return */
234 /* Get selected medias count */
235 int sel_cnt = _gl_data_selected_list_count(ad);
236 /* Remove invalid widgets */
238 gl_del_invalid_widgets(ad, GL_INVALID_NEW_ENTRY);
239 /* Display selectioninfo */
240 _gl_notify_create_selinfo(ad, ad->gridinfo.edit_layout,
241 ad->gridinfo.nf_it_edit,
242 ad->maininfo.medias_cnt, sel_cnt,
246 * Update albums list when change to normal view.
247 * Maybe some empty albums exist.
249 if (!b_update_albums_list) {
250 gl_dbg("Update albums list when cancelled.");
251 ad->albuminfo.update_albums_list = true;
252 } else if (ad->popupinfo.popup_mode == GL_POPUP_THUMB_MOVE) {
253 gl_popup_update_content(ad, GL_POPUP_THUMB_MOVE);
261 * return file extension, f.e. jpg; then return new path without ext.
264 _gl_get_file_ext(const char *file_path, char *file_ext, char *new_path)
268 for (i = strlen(file_path); i >= 0; i--)
270 if ((file_path[i] == '.') && (i < GL_FILE_PATH_LEN_MAX))
272 g_strlcpy(file_ext, &file_path[i + 1], GL_FILE_EXT_LEN_MAX);
273 g_strlcpy(new_path, file_path, i + 1);
275 gl_dbg("path without extension :%s", new_path);
279 if (file_path[i] == '/') //meet the dir. no ext
287 /* Check if there is any MMC file contained in select_medias_elist */
288 static bool _gl_check_mmc_file_selected(void *data)
291 GL_CHECK_FALSE(data);
292 gl_appdata *ad = (gl_appdata *)data;
293 gl_item *gitem = NULL;
296 int cnt = _gl_data_selected_list_count(ad);
297 for (i = 0; i < cnt; i++) {
301 gitem = _gl_data_selected_list_get_nth(ad, i);
302 /* File on MMC is selected */
303 if (gitem && gitem->item && gitem->item->file_url) {
304 on_mmc = strncmp(GL_ROOT_PATH_MMC,
305 gitem->item->file_url,
306 strlen(GL_ROOT_PATH_MMC));
314 /* Stop vibrate device */
315 static int _gl_stop_vibration(void *data)
318 GL_CHECK_VAL(data, -1);
319 gl_appdata *ad = (gl_appdata *)data;
322 if (ad->entryinfo.haptic_handle >= 0) {
323 ret = haptic_stop_device(GL_VIBRATION_DEVICE);
325 gl_dbgE("haptic_stop_device failed[%d]!", ret);
327 ret = haptic_deinitialize();
328 if (ret != HAPTIC_ERROR_NONE)
329 gl_dbgE("haptic_deinitialize failed[%d]!", ret);
330 ad->entryinfo.haptic_handle = -1;
336 static Eina_Bool _gl_vibration_timer_cb(void *data)
339 GL_CHECK_VAL(data, -1);
340 gl_appdata *ad = (gl_appdata *)data;
342 _gl_stop_vibration(data);
344 if (ad->entryinfo.vibration_timer) {
345 ecore_timer_del(ad->entryinfo.vibration_timer);
346 ad->entryinfo.vibration_timer = NULL;
348 return ECORE_CALLBACK_CANCEL;
351 /* one copy of function "ecore_file_mv" from the file "ecore_file.c" for lock debugging */
353 * Use gl_file_mv() to move medias to other album.
354 * Media-server, which is different with libmedia-info, watches src and dest folder,
355 * it updates libmedia-info DB asynchronously.
356 * While move/copy mass data in My Files appliation,
357 * After move/copy done in My files, check the dest folder in Gallery.
358 * You'll find its content is changing.
359 * gl_file_mv() operate libmedia-info DB synchronously, so it's faster than media-server.
363 * stop using "rename" when moving from mmc to phone for correct db update.
365 static Eina_Bool __gl_file_mv(gl_item *gitem, const char *src, const char *dst, int type)
369 GL_CHECK_FALSE(gitem);
371 gl_dbg("\n\tSrc: %s\n\tDest: %s", src, dst);
373 /* Move thumb first */
374 if (_gl_local_data_move_media(gitem->item, dst) < 0) {
375 gl_dbgE("Move media thumbnail failed!");
380 * From->To: MMC->MMC or Phone->Phone
382 if (rename(src, dst)) {
384 * File cannot be moved directly because
385 * it resides on a different mount point.
387 if (errno == EXDEV) {
389 * From->To: MMC->Phone or Phone->MMC
391 gl_dbgW("errno = EXDEV(%d): Cross-device link", errno);
395 * Make sure this is a regular file before
396 * we do anything fancy.
399 if (S_ISREG(st.st_mode)) {
403 if (!ecore_file_cp(src, dst)) {
404 gl_dbgE("Copy file failed[%d]!", errno);
412 if (!ecore_file_unlink(src))
413 gl_dbgE("Delete file failed[%d]!", errno);
417 gl_dbgE("S_ISREG fail[%d]!", errno);
421 gl_dbgE("Fail[%d]!", errno);
428 #ifdef _USE_ROTATE_BG
429 /* b_path == true, Use saved folder path to check cluster uuid */
430 static int __gl_refresh_albums_list(void *data, bool b_path)
432 GL_CHECK_VAL(data, -1);
433 gl_appdata *ad = (gl_appdata *)data;
434 gl_cluster *current_album = ad->albuminfo.current_album;
436 gl_cluster *current = NULL;
437 bool b_get_cur_album = false;
438 /* Albums list would be update, reset flag */
439 ad->albuminfo.update_albums_list = false;
441 uuid = calloc(1, GL_MTYPE_ITEN_ID_LEN_MAX);
442 GL_CHECK_VAL(uuid, -1);
444 /* Save cluster ID to set new current_album from new albums list */
445 if (current_album && current_album->cluster &&
446 current_album->cluster->uuid) {
447 g_strlcpy(uuid, current_album->cluster->uuid,
448 GL_MTYPE_ITEN_ID_LEN_MAX);
449 b_get_cur_album = true;
451 gl_dbg("None album selected, current album is unavailable.");
454 _gl_data_get_cluster_list(ad);
455 /* need to reset current album */
456 ad->albuminfo.current_album = NULL;
458 if (b_get_cur_album) {
460 gl_dbg("Path: %s", ad->albuminfo.dest_folder);
461 if (strlen(ad->albuminfo.dest_folder) > 0 &&
462 GL_FILE_EXISTS(ad->albuminfo.dest_folder)) {
463 gl_dbgW("Cluster record updated!");
464 _gl_data_get_cluster_by_path(ad,
465 ad->albuminfo.dest_folder,
468 gl_dbgE("Invalid folder path!");
469 _gl_data_get_cluster_by_id(ad, uuid, ¤t);
472 _gl_data_get_cluster_by_id(ad, uuid, ¤t);
475 if(current && current->cluster) {
476 ad->albuminfo.current_album = current;
477 gl_dbg("Reset current album: %s",
478 current->cluster->display_name);
479 _gl_data_update_item_list(ad);
481 /* Clear items list if current album doesn't exist */
482 if (ad->selectedinfo.medias_elist)
483 _gl_data_selected_list_finalize(ad);
484 _gl_data_clear_default_item_list(ad);
485 ad->maininfo.medias_cnt = 0;
496 static char *__gl_get_unique_full_path(char *file_path, char *ext)
498 char *file_name = file_path;
499 char *extension = ext;
500 char *final_path = NULL;
501 int final_path_len = 0;
502 int extension_len = 0;
503 int suffix_count = 0;
504 /* means suffix on file name. up to "_99999" */
505 const int max_suffix_count = 99999;
507 int suffix_len = (int)log10(max_suffix_count + 1) + 1;
512 gl_dbg("file_path=[%s], ext=[%s]", file_path, ext);
515 extension_len = strlen(extension);
517 /* first 1 for ".", last 1 for NULL */
518 final_path_len = strlen(file_name) + 1 + suffix_len + extension_len + 1;
520 final_path = (char*)calloc(1, final_path_len);
522 gl_dbgE("calloc failed!");
528 * if there is no extension name, just make a file name without extension */
529 if (0 == extension_len) {
530 if (suffix_count == 0) {
531 snprintf(final_path, final_path_len, "%s",
534 snprintf(final_path, final_path_len, "%s_%d",
535 file_name, suffix_count);
538 if (suffix_count == 0) {
539 snprintf(final_path, final_path_len, "%s.%s",
540 file_name, extension);
542 snprintf(final_path, final_path_len, "%s_%d.%s",
543 file_name, suffix_count, extension);
547 if (ecore_file_exists(final_path)) {
549 if (suffix_count > max_suffix_count) {
550 gl_dbgE("Max suffix count!");
555 memset(final_path, 0x00, final_path_len);
563 gl_dbg("Decided path = [%s]", final_path);
568 gl_validate_album_name(const char *new_name)
570 GL_CHECK_FALSE(new_name);
571 char invalid_chars[] = { '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\0' };
572 char *ptr = invalid_chars;
574 gl_dbg("new album name is %s\n", new_name);
577 gl_dbg("invalid character is %c", *ptr);
578 if (strchr(new_name, (*ptr)) != NULL)
589 gl_get_entry_text(Evas_Object * entry, char *entry_text, int len_max)
592 GL_CHECK_VAL(entry_text, -1);
593 GL_CHECK_VAL(entry, -1);
595 memset(entry_text, 0x00, len_max);
597 char *entry_str = (char *)elm_entry_entry_get(entry);
600 if (strlen(entry_str) == 0)
602 gl_dbg("Entry string is empty!");
607 char *entry_utf8 = elm_entry_markup_to_utf8(entry_str); // changes user input to utf-8 encoding format
608 if (entry_utf8 == NULL)
610 gl_dbgE("Make entry string to UTF8 failed!");
613 else if (strlen(entry_utf8) == 0)
615 gl_dbg("Entry text is empty!");
619 g_strlcpy(entry_text, entry_utf8, len_max);
620 entry_text[len_max - 1] = '\0';
629 gl_dbgE("Get entry string failed!");
637 * Change utf8 string to markup, then set it as entry text.
638 * To fix special character "&" issue, to convert "&" to "&". f.e.
639 * Myfiles->rename folder to AB&C->Gallery/Rename ->displayed as "AB"
641 int gl_set_entry_text(Evas_Object *entry, char *entry_text)
643 GL_CHECK_VAL(entry, -1);
644 char *entry_makeup = NULL;
645 gl_dbg("Entry UTF8 text: %s.", entry_text);
648 entry_makeup = elm_entry_utf8_to_markup(entry_text);
649 if (entry_makeup == NULL) {
650 gl_dbgE("Make utf8 string to makeup failed!");
653 gl_dbg("Entry makeup text: %s.", entry_makeup);
655 /* Empty string set if entry_makeup is NULL */
656 elm_entry_entry_set(entry, entry_makeup);
667 gl_get_default_images_path(char *directory_path)
670 GL_CHECK_VAL(directory_path, -1);
672 len = snprintf(directory_path, GL_DIR_PATH_LEN_MAX, "%s",
675 gl_dbgE("snprintf returns failure!");
678 directory_path[len] = '\0';
682 len = g_strlcat(directory_path, GL_DEFAULT_PATH_IMAGES,
683 GL_DIR_PATH_LEN_MAX);
684 if (len >= GL_DIR_PATH_LEN_MAX) {
685 gl_dbgE("strlcat returns failure(%d)!", len);
688 gl_dbg("Default images path: %s.", directory_path);
693 int gl_get_selected_files_path_str(void *data, gchar sep_c, char **path_str, int *sel_cnt)
695 GL_CHECK_VAL(path_str, -1);
696 GL_CHECK_VAL(data, -1);
697 gl_appdata *ad = (gl_appdata *)data;
698 GL_CHECK_VAL(ad->selectedinfo.medias_elist, -1);
699 GString *selected_path_list = g_string_new(NULL);
700 gl_item *current = NULL;
701 int selected_item_cnt = 0;
704 EINA_LIST_FOREACH(ad->selectedinfo.medias_elist, l, current) {
705 if (current == NULL || current->item == NULL) {
706 if (selected_path_list) {
707 g_string_free(selected_path_list, true);
708 selected_path_list = NULL;
713 g_string_append(selected_path_list, current->item->file_url);
714 g_string_append_c(selected_path_list, sep_c);
717 gl_dbg("Selected items count: %d.", selected_item_cnt);
719 *sel_cnt = selected_item_cnt;
720 int len = strlen(selected_path_list->str);
721 g_string_truncate(selected_path_list, len - 1);
723 * Frees the memory allocated for the GString.
724 * If free_segment is true it also frees the character data.
725 * If it's false, the caller gains ownership of the buffer
726 * and must free it after use with g_free().
728 *path_str = g_string_free(selected_path_list, false);
729 GL_CHECK_VAL(*path_str, -1);
730 gl_dbg("Total string:\n\n\t>>@@:> %s <:@@<<\n", *path_str);
735 gl_make_dir(const char *dir_full_path)
737 GL_CHECK_VAL(dir_full_path, -1);
739 return mkdir(dir_full_path, GL_CREATE_DIR_MASK_DEFAULT);
743 gl_make_new_album(const char *name)
746 char path[GL_DIR_PATH_LEN_MAX] = { 0, };
747 char dir_path[GL_DIR_PATH_LEN_MAX] = { 0, };
749 if (gl_get_default_images_path(dir_path) != 0)
751 gl_dbg("FAIL to get dir path");
755 snprintf(path, GL_DIR_PATH_LEN_MAX, "%s/%s", dir_path, name);
756 path[strlen(path)] = '\0';
757 gl_dbg("Making %s directory", path);
759 if (ecore_file_dir_is_empty(path) == -1) // new folder doesn't exist
761 if (ecore_file_dir_is_empty(dir_path) == -1) // default images folder doesn't exist
763 gl_dbgE("[Error] Default images path[%s] doesn't exist. Create it...");
764 gl_make_dir(dir_path);
767 return gl_make_dir(path);
771 gl_dbg("new folder already exists, no need to make!");
777 gl_move_media_item(gl_item * gitem, char *new_dir_name, bool is_full_path, int *popup_op)
779 gl_dbg("Move media item START>>>");
780 char new_path[GL_FILE_PATH_LEN_MAX] = { 0, };
781 char ext[GL_FILE_EXT_LEN_MAX] = { 0, };
782 char new_path_noext[GL_FILE_PATH_LEN_MAX] = { 0, };
783 char dir_path[GL_DIR_PATH_LEN_MAX] = { 0, };
784 if (gitem == NULL || gitem->item == NULL || gitem->item->uuid == NULL ||
787 gl_dbg("gitem == NULL || gitem->item == NULL");
791 *popup_op = GL_POPUP_OP_NONE;
795 if (!gitem->item->file_url ||
796 !strlen(gitem->item->file_url) ||
797 !gitem->item->display_name)
799 gl_dbg("file url or name is error.");
802 snprintf(new_path, sizeof(new_path), "%s/%s",
803 new_dir_name, (char *)(gitem->item->display_name));
804 gl_dbg("New path : %s", new_path);
806 if (!g_strcmp0(new_path, gitem->item->file_url)) //do not need to move. ("All" album case)
808 //create popup in pipe callback
809 *popup_op = GL_POPUP_OP_SAME_ALBUM;
810 gl_dbg("File already in destination, do not need to move, just return...");
812 snprintf(msg, sizeof(msg), "Cann't move %s to the same album!", gitem->item->display_name);
813 gl_popup_create_popup(ad, GL_POPUP_NOBUT_MOV_DEL, msg);
818 else if (ecore_file_exists(new_path)) // return true if file exists, rename new file.
820 _gl_get_file_ext(new_path, ext, new_path_noext);
821 char *final_path = NULL;
822 final_path = __gl_get_unique_full_path(new_path_noext, ext);
823 if (final_path == NULL)
825 gl_dbg("Created unique path: %s", final_path);
826 memset(new_path, 0x00, GL_FILE_PATH_LEN_MAX);
827 g_strlcpy(new_path, final_path, GL_FILE_PATH_LEN_MAX);
830 //create popup in pipe callback
831 *popup_op = GL_POPUP_OP_DUPLICATED_NAME;
832 /*memset(msg, 0x00, GL_FILE_PATH_LEN_MAX);
833 snprintf(msg, sizeof(msg), "%s is duplicated, rename it!", gitem->item->display_name);
834 gl_popup_create_popup(ad, GL_POPUP_NOBUT_MOV_DEL, msg);
840 if (gl_get_default_images_path(dir_path) != 0)
842 gl_dbg("FAIL to get dir path!");
845 snprintf(new_path, GL_FILE_PATH_LEN_MAX, "%s/%s/%s",
846 dir_path, new_dir_name, (char *)(gitem->item->display_name));
849 new_path[strlen(new_path)] = '\0';
851 // stop using "rename" when moving from mmc to phone for correct db update.
852 if (!__gl_file_mv(gitem, gitem->item->file_url, new_path, gitem->item->type))
854 gl_dbg("Move media item OVER<<<");
859 gl_dbg("Move media item OVER<<<");
865 * Check if there is any media in Gallery.
867 * False returned if none medias exist, other return True.
869 bool gl_check_gallery_empty(void* data)
871 GL_CHECK_FALSE(data);
872 gl_appdata *ad = (gl_appdata *)data;
874 if (ad->albuminfo.cluster_list == NULL) {
875 gl_dbgE("ad->albuminfo.cluster_list is empty!");
879 Eina_List *clist = ad->albuminfo.cluster_list->clist;
881 gl_dbgW("Albums list is invalid!");
885 int len = eina_list_count(clist);
887 gl_dbgW("Albums list is empty!");
894 bool gl_is_image_valid(void *data, char *filepath)
896 GL_CHECK_FALSE(data);
897 gl_appdata *ad = (gl_appdata *)data;
898 GL_CHECK_FALSE(filepath);
900 Evas_Object *image = NULL;
905 evas = evas_object_evas_get(ad->maininfo.win);
906 GL_CHECK_FALSE(evas);
908 image = evas_object_image_add(evas);
909 GL_CHECK_FALSE(image);
911 evas_object_image_filled_set(image, 0);
912 evas_object_image_load_scale_down_set(image, 0);
913 evas_object_image_file_set(image, filepath, NULL);
914 evas_object_image_size_get(image, &width, &height);
916 evas_object_del(image);
920 if (width <= 0 || height <= 0) {
921 gl_dbg("Cannot load file : %s", filepath);
929 gl_is_rotation_locked(void)
931 gl_dbg_launch(" gl_is_rotation_locked:start");
934 if (!vconf_get_bool(VCONFKEY_SETAPPL_ROTATE_LOCK_BOOL, &lock))
936 gl_dbg("Rotation locked state[%d].", lock);
937 gl_dbg_launch(" gl_is_rotation_locked:end");
942 gl_dbgE("Get rotation lock state failed!");
943 gl_dbg_launch(" gl_is_rotation_locked:end");
949 * Check MMC state(Inserted/Removed) for Move/Delete
952 gl_check_mmc_state(void *data, char *dest_folder)
954 GL_CHECK_VAL(data, -1);
955 gl_appdata *ad = (gl_appdata *)data;
957 /* MMC hasn't been inserted */
958 if (ad->maininfo.mmc_state == GL_MMC_STATE_REMOVED)
963 /* Move files to MMC album */
965 on_mmc = strncmp(GL_ROOT_PATH_MMC, dest_folder,
966 strlen(GL_ROOT_PATH_MMC));
971 gl_cluster *cur_album = ad->albuminfo.current_album;
972 char src_folder_path[GL_DIR_PATH_LEN_MAX] = { 0, };
973 GL_CHECK_VAL(cur_album, -1);
974 GL_CHECK_VAL(cur_album->cluster, -1);
975 /* Move files from MMC album */
976 GL_CHECK_VAL(cur_album->cluster->uuid, -1);
977 g_strlcpy(src_folder_path, cur_album->cluster->path,
978 GL_DIR_PATH_LEN_MAX);
979 on_mmc = strncmp(GL_ROOT_PATH_MMC, src_folder_path,
980 strlen(GL_ROOT_PATH_MMC));
981 /* Check MMC files selected in album [All albums] */
984 } else if (!g_strcmp0(cur_album->cluster->uuid, GL_ALBUM_ALL_ID)) {
985 gl_dbg("In album [All albums].");
986 if (_gl_check_mmc_file_selected(ad))
993 gl_dbgW("Operate medias on MMC!");
994 ad->maininfo.mmc_state = GL_MMC_STATE_ADDED_MOVING;
998 int gl_reg_db_update_noti(void *data)
1000 GL_CHECK_VAL(data, -1);
1001 gl_appdata *ad = (gl_appdata *)data;
1002 int error_code = -1;
1005 vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &mmc_state);
1006 /* Save the init status of MMC */
1007 if (mmc_state == VCONFKEY_SYSMAN_MMC_MOUNTED)
1009 gl_dbg("###### :::::: MMC loaded! :::::: ######");
1010 ad->maininfo.mmc_state = GL_MMC_STATE_ADDED;
1012 else if (mmc_state == VCONFKEY_SYSMAN_MMC_REMOVED ||
1013 mmc_state == VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED)
1015 gl_dbg("###### :::::: MMC removed! :::::: ######");
1016 ad->maininfo.mmc_state = GL_MMC_STATE_REMOVED;
1019 gl_dbg("Enable the noti handle for DB update status!");
1020 /* Set DB update status callback */
1021 error_code = vconf_notify_key_changed(VCONFKEY_FILEMANAGER_DB_STATUS,
1022 _gl_db_update_noti_cb, ad);
1023 if (error_code == -1) {
1024 gl_dbgE("vconf_notify_key_changed for DB_STATUS failed!");
1031 int gl_dereg_db_update_noti(void)
1033 int error_code = -1;
1035 gl_dbg("Disable the noti handle for DB update status!");
1036 error_code = vconf_ignore_key_changed(VCONFKEY_FILEMANAGER_DB_STATUS,
1037 _gl_db_update_noti_cb);
1038 if (error_code == -1) {
1039 gl_dbgE("vconf_ignore_key_changed for DB_STATUS failed!");
1047 * Get view mode of app
1049 int gl_get_view_mode(void *data)
1051 GL_CHECK_VAL(data, GL_VIEW_NONE);
1052 gl_appdata *ad = (gl_appdata *)data;
1053 return ad->maininfo.view_mode;
1057 * Set view mode of app
1059 int gl_set_view_mode(void *data, int mode)
1061 GL_CHECK_VAL(data, -1);
1062 gl_appdata *ad = (gl_appdata *)data;
1064 ad->maininfo.view_mode = mode;
1069 int gl_del_invalid_widgets(void *data, int invalid_m)
1071 GL_CHECK_VAL(data, -1);
1072 gl_appdata *ad = (gl_appdata *)data;
1074 if (ad->popupinfo.popup) {
1076 evas_object_del(ad->popupinfo.popup);
1077 ad->popupinfo.popup = NULL;
1078 } else if (ad->uginfo.ug_called_by_me) {
1080 gl_dbg("Destroy UG!");
1081 if (ad->uginfo.ug_called_by_me) {
1082 ug_destroy(ad->uginfo.ug_called_by_me);
1083 ad->uginfo.ug_called_by_me = NULL;
1084 ad->uginfo.ug_type = -1;
1086 if (ad->uginfo.gallery_ug_called_by_me) {
1087 ug_destroy(ad->uginfo.gallery_ug_called_by_me);
1088 ad->uginfo.gallery_ug_called_by_me = NULL;
1092 switch (invalid_m) {
1093 case GL_INVALID_RENAME_ALBUM:
1094 /* gl_ui_edit_cancel pop navigationbar */
1095 gl_dbgW("Destroy Rename album view!");
1096 elm_naviframe_item_pop(ad->maininfo.naviframe);
1097 gl_set_view_mode(ad, GL_VIEW_ALBUMS_EDIT);
1098 _gl_editfield_destroy_imf(ad);
1100 case GL_INVALID_NEW_ENTRY:
1101 case GL_INVALID_NEW_ENTRY_NOC:
1102 if (ad->entryinfo.entry_mode == GL_ENTRY_NEW_ALBUM) {
1103 gl_dbg("Destroy New album view!");
1104 if (invalid_m == GL_INVALID_NEW_ENTRY) {
1105 gl_dbg("Pop to nf_it_edit");
1106 elm_naviframe_item_pop_to(ad->gridinfo.nf_it_edit);
1108 _gl_editfield_destroy_imf(ad);
1109 Evas_Object *edit_ly = NULL;
1110 edit_ly = ad->gridinfo.edit_layout;
1111 const char *sig = NULL;
1112 sig = "elm,swallow_view,state,edit";
1113 edje_object_signal_emit(_EDJ(edit_ly), sig, "elm");
1117 ad->entryinfo.entry_mode = GL_ENTRY_NONE;
1123 int gl_del_medias(void *data)
1126 GL_CHECK_VAL(data, -1);
1127 gl_appdata *ad = (gl_appdata *)data;
1128 /* Get all selected medias count */
1129 int cnt = _gl_data_selected_list_count(ad);
1130 /* Check MMC state for cancel operation */
1131 gl_check_mmc_state(ad, NULL);
1132 gl_dbg("MMC state: %d.", ad->maininfo.mmc_state);
1133 _gl_use_thread_operate_medias(ad, GL_STR_DELETING, cnt,
1134 GL_MEDIA_OP_DELETE);
1139 /* 'Delete medias' is available in Albums view */
1140 int gl_del_selected(void *data)
1142 GL_CHECK_VAL(data, -1);
1143 gl_appdata *ad = (gl_appdata *)data;
1144 /* Get all selected medias count */
1145 int cnt = _gl_data_selected_list_count(ad);
1146 gl_item *gitem = NULL;
1148 int popup_op = GL_POPUP_OP_NONE;
1150 /* Removed media from selected_media_elist */
1151 for (i = 1; i <= cnt; i++) {
1152 _gl_data_get_item_by_index(ad, i, true, &gitem);
1153 if (gitem != NULL && gitem->item != NULL)
1154 _gl_data_remove_item(gitem);
1156 gl_dbgE("Invalid item!");
1158 gl_dbg("Write pipe, make progressbar updated!");
1159 gl_thread_write_pipe(ad, i, popup_op);
1166 int _gl_update_operation_view(void *data, const char *noti_str)
1168 GL_CHECK_VAL(data, -1);
1169 gl_appdata *ad = (gl_appdata *)data;
1170 gl_dbg("String: %s", noti_str);
1172 if (ad->maininfo.medias_cnt > 0) {
1173 /* Deleting process done, change to normal view */
1174 _gl_ui_pop_to_thumb(ad);
1176 if (gl_get_view_mode(ad) == GL_VIEW_THUMBS)
1177 _gl_nocontents_show(ad);
1179 /* Add notification */
1180 _gl_notify_create_notiinfo(ad, ad->gridinfo.layout,
1183 gl_dbgW("Empty album, change to Albums view!");
1184 gl_albums_comeback_from_view(ad);
1185 elm_naviframe_item_pop_to(ad->albuminfo.nf_it);
1187 if (gl_check_gallery_empty(ad)) {
1188 _gl_ctrl_disable_toolbar_item(ad, true, GL_NAVI_ALBUMS,
1190 } else if (ad->albuminfo.cluster_list->edit_cnt == 0) {
1191 _gl_ctrl_disable_toolbar_item(ad, true, GL_NAVI_ALBUMS,
1195 _gl_notify_destroy_selinfo(ad);
1196 /* Add notification */
1197 _gl_notify_create_notiinfo(ad, ad->albuminfo.layout,
1203 /* Update view after deleting process done */
1204 int gl_update_del_view(void *data)
1206 GL_CHECK_VAL(data, -1);
1207 gl_appdata *ad = (gl_appdata *)data;
1208 _gl_data_selected_list_finalize(ad);
1210 int view_mode = gl_get_view_mode(ad);
1211 gl_dbg("view_mode: %d.", view_mode);
1212 gl_refresh_albums_list(ad);
1214 _gl_update_operation_view(ad, GL_STR_DELETED);
1219 /* Delete video file */
1220 int _gl_del_video(void *data)
1222 GL_CHECK_VAL(data, -1);
1223 gl_item *gitem = (gl_item *) data;
1224 GL_CHECK_VAL(gitem->ad, -1);
1225 gl_appdata *ad = (gl_appdata *)gitem->ad;
1228 Elm_Object_Item *it = NULL;
1229 it = (Elm_Object_Item *)elm_genlist_decorated_item_get(ad->listinfo.videos_view);
1230 /* Finish genlist sweep*/
1232 elm_genlist_item_decorate_mode_set(it, "slide", EINA_FALSE);
1233 elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DEFAULT);
1235 if (ad->listinfo.sweep_file_path) {
1236 free(ad->listinfo.sweep_file_path);
1237 ad->listinfo.sweep_file_path = NULL;
1240 /* Destroy it and remove its record from DB */
1241 _gl_data_remove_item(gitem);
1243 int view_mode = gl_get_view_mode(ad);
1244 gl_dbg("view_mode: %d.", view_mode);
1245 gl_refresh_albums_list(ad);
1247 if (ad->maininfo.medias_cnt > 0) {
1248 gl_list_update_view(ad);
1249 /* Add notification */
1250 _gl_notify_create_notiinfo(ad, ad->gridinfo.layout,
1253 gl_dbgW("Empty album, change to Albums view!");
1254 gl_albums_comeback_from_view(ad);
1255 elm_naviframe_item_pop_to(ad->albuminfo.nf_it);
1256 if (gl_check_gallery_empty(ad)) {
1257 _gl_ctrl_disable_toolbar_item(ad, true, GL_NAVI_ALBUMS,
1259 } else if (ad->albuminfo.cluster_list->edit_cnt == 0) {
1260 _gl_ctrl_disable_toolbar_item(ad, true, GL_NAVI_ALBUMS,
1264 /* Add notification */
1265 _gl_notify_create_notiinfo(ad, ad->albuminfo.layout,
1272 int gl_remove_album(void *data, gl_cluster * album_item)
1274 GL_CHECK_VAL(data, -1);
1275 gl_appdata *ad = (gl_appdata *)data;
1277 char dir_path[GL_DIR_PATH_LEN_MAX] = { 0, };
1279 if (album_item == NULL || album_item->cluster == NULL ||
1280 album_item->cluster->uuid == NULL) {
1281 gl_dbgE("Invalid album!");
1285 gl_dbg("Remove album: %s, id=%s", album_item->cluster->display_name,
1286 album_item->cluster->uuid);
1288 /* get folder path of album */
1289 if (album_item->cluster->path &&
1290 strlen(album_item->cluster->path) > 0) {
1291 gl_dbg("Folder fullpath: %s", dir_path);
1292 g_strlcpy(dir_path, album_item->cluster->path,
1293 GL_DIR_PATH_LEN_MAX);
1295 gl_dbgE("Get folder fullpath failed[%d]!", res);
1298 /* remove all items in the album from file system and db */
1299 _gl_data_get_item_list(ad, album_item, GL_GET_ALL_RECORDS,
1300 GL_GET_ALL_RECORDS);
1302 gl_item *gitem = NULL;
1304 /* Get all medias count of current album */
1305 int cnt = ad->maininfo.medias_cnt;
1306 gl_dbg("cnt: %d", cnt);
1307 /* Remove files, _gl_local_data_delete_album would delete medias record */
1308 for (i = cnt; i >= 1; i--) {
1309 _gl_data_get_item_by_index(ad, i, false, &gitem);
1310 if (gitem && gitem->item && gitem->item->file_url) {
1311 if (!ecore_file_unlink(gitem->item->file_url))
1312 gl_dbgE("ecore_file_unlink failed!");
1316 /* remove album from db*/
1317 res = _gl_local_data_delete_album(album_item->cluster->uuid);
1319 gl_dbgE("_gl_local_data_delete_album failed[%d]!", res);
1321 /* remove album from file system */
1322 if (ecore_file_rmdir(dir_path) == EINA_FALSE) {
1323 gl_dbg("ecore_file_rmdir failed!");
1330 int gl_del_albums(void *data)
1332 GL_CHECK_VAL(data, -1);
1333 gl_appdata *ad = (gl_appdata *)data;
1334 gl_cluster *album_item = NULL;
1335 int cnt = _gl_data_get_albums_selected_cnt(ad);
1341 Eina_List *selected_list = ad->albuminfo.selected_albums_elist;
1342 if ((selected_list == NULL) || (eina_list_count(selected_list) == 0))
1344 gl_dbg("zero length, return!");
1349 gl_dbg("cnt= %d, list length=%d", cnt, eina_list_count(selected_list));
1351 for (i = 0; i < cnt; i++)
1353 album_item = eina_list_nth(selected_list, i);
1355 if (album_item && album_item->cluster &&
1356 album_item->cluster->uuid) {
1357 gl_dbg("Delete album: %s, id=%s",
1358 album_item->cluster->display_name,
1359 album_item->cluster->uuid);
1361 ret = gl_remove_album(ad, album_item);
1364 gl_dbg("gl_remove_album failed, error=%d", ret);
1370 // update the albums view
1371 gl_ui_edit_cancel(ad);
1374 _gl_notify_create_notiinfo(ad, ad->albuminfo.layout,
1379 int gl_refresh_albums_list(void *data)
1381 #ifdef _USE_ROTATE_BG
1382 return __gl_refresh_albums_list(data, false);
1384 GL_CHECK_VAL(data, -1);
1385 gl_appdata *ad = (gl_appdata *)data;
1386 gl_cluster *old_current_album = ad->albuminfo.current_album;
1387 char cluster_id[GL_MTYPE_ITEN_ID_LEN_MAX] = { 0, };
1388 gl_cluster *current = NULL;
1389 bool b_get_cur_album = false;
1390 /* Albums list would be update, reset flag */
1391 ad->albuminfo.update_albums_list = false;
1393 /* Save cluster ID to set new current_album from new albums list */
1394 if (old_current_album && old_current_album->cluster &&
1395 old_current_album->cluster->uuid) {
1396 g_strlcpy(cluster_id, old_current_album->cluster->uuid,
1397 GL_MTYPE_ITEN_ID_LEN_MAX);
1398 b_get_cur_album = true;
1400 gl_dbg("None album selected, current album is unavailable.");
1403 _gl_data_get_cluster_list(ad);
1404 /* need to reset current album */
1405 ad->albuminfo.current_album = NULL;
1407 if (b_get_cur_album) {
1408 _gl_data_get_cluster_by_id(ad, cluster_id, ¤t);
1409 if(current && current->cluster) {
1410 ad->albuminfo.current_album = current;
1411 gl_dbg("Reset current album: %s",
1412 current->cluster->display_name);
1413 _gl_data_update_item_list(ad);
1416 /* Clear items list if current album doesn't exist */
1417 if (ad->selectedinfo.medias_elist)
1418 _gl_data_selected_list_finalize(ad);
1419 _gl_data_clear_default_item_list(ad);
1420 ad->maininfo.medias_cnt = 0;
1429 * Move files under root album [/opt/media or /opt/storage/sdcard] to a newly created album.
1430 * Used in 'Rename' album case.
1433 gl_move_root_album(void* data, gl_cluster* cur_album, char* dest_path)
1435 GL_CHECK_VAL(data, -1);
1436 GL_CHECK_VAL(cur_album, -1);
1437 GL_CHECK_VAL(cur_album->cluster, -1);
1438 gl_appdata *ad = (gl_appdata *)data;
1440 /* Get all medias of current album */
1441 _gl_data_get_item_list(ad, cur_album, GL_GET_ALL_RECORDS,
1442 GL_GET_ALL_RECORDS);
1444 Eina_List* tmp_elist = NULL;
1445 gl_item* gitem = NULL;
1446 int popup_op = GL_POPUP_OP_NONE;
1447 GL_CHECK_VAL(ad->maininfo.medias_elist, -1);
1449 /* Move medias of album to dest folder */
1450 EINA_LIST_FOREACH(ad->maininfo.medias_elist, tmp_elist, gitem)
1452 if (gitem && gitem->item)
1454 gl_dbg("Move [%s]", gitem->item->file_url);
1455 if (gl_move_media_item(gitem, dest_path, true, &popup_op) != 0)
1457 gl_dbgW("Failed to move this item");
1464 gl_dbgE("Invalid item!");
1465 _gl_data_clear_default_item_list(ad);
1470 /* Free item list */
1471 _gl_data_clear_default_item_list(ad);
1476 /* 'Move medias' is only available in tab Albums */
1477 int gl_move_selected(void *data)
1479 GL_CHECK_VAL(data, -1);
1480 gl_appdata *ad = (gl_appdata *)data;
1482 /* Get selected medias count */
1483 int cnt = _gl_data_selected_list_count(ad);
1484 gl_item *gitem = NULL;
1485 int popup_op = GL_POPUP_OP_NONE;
1487 for (i = 1; i <= cnt; i++)
1489 _gl_data_get_item_by_index(ad, i, true, &gitem);
1490 if (gitem && gitem->item)
1492 gl_dbg("Selected [%s]", gitem->item->file_url);
1493 if (gl_move_media_item(gitem, ad->albuminfo.dest_folder, true, &popup_op) != 0)
1495 gl_dbg("Failed to move this item");
1497 gl_dbg("File Moved:::::::%d/%d-->try to update progressbar", i, cnt);
1501 gl_dbg("Invalid item!");
1504 gl_dbg("Write pipe, make progressbar updated!");
1505 gl_thread_write_pipe(ad, i, popup_op);
1507 popup_op = GL_POPUP_OP_NONE;
1513 int gl_move_to_album(void *data)
1515 GL_CHECK_VAL(data, -1);
1516 gl_appdata *ad = (gl_appdata *)data;
1517 char folder_fullpath[GL_DIR_PATH_LEN_MAX] = { 0, };
1518 char default_path[GL_DIR_PATH_LEN_MAX] = { 0, };
1519 gl_cluster *cur_album = ad->albuminfo.current_album;
1520 int cnt = _gl_data_selected_list_count(ad);
1523 * 'move_album_id == NULL' is new album case,
1524 * other move/save to some existed album.
1526 if (ad->albuminfo.path == NULL) {
1527 gl_dbg("---Popup list item: New album---");
1528 ad->albuminfo.move_new_album = true;
1530 if (gl_make_new_album(ad->albuminfo.new_album_name) != 0)
1532 gl_popup_create_popup(ad, GL_POPUP_NOBUT,
1533 GL_STR_SAME_NAME_ALREADY_IN_USE);
1534 gl_dbgE("Failed to make a new directory!");
1535 gl_ui_update_select_widgets(ad);
1538 if (gl_get_default_images_path(default_path) != 0)
1540 gl_dbgE("Failed to get default images path!");
1541 gl_ui_update_select_widgets(ad);
1544 snprintf(folder_fullpath, GL_DIR_PATH_LEN_MAX, "%s/%s",
1545 default_path, ad->albuminfo.new_album_name);
1547 ad->albuminfo.move_new_album = false;
1548 g_strlcpy(folder_fullpath, ad->albuminfo.path,
1549 GL_DIR_PATH_LEN_MAX);
1550 free(ad->albuminfo.path);
1551 ad->albuminfo.path = NULL;
1554 if (cur_album == NULL || cur_album->cluster == NULL)
1556 gl_dbgE("[Error] Current album is NULL!");
1557 gl_ui_update_select_widgets(ad);
1561 memset(ad->albuminfo.dest_folder, 0x00, GL_DIR_PATH_LEN_MAX);
1562 g_strlcpy(ad->albuminfo.dest_folder, folder_fullpath, GL_DIR_PATH_LEN_MAX);
1563 /* Check MMC state for cancel operation */
1564 gl_check_mmc_state(ad, folder_fullpath);
1565 gl_dbg("MMC state: %d.", ad->maininfo.mmc_state);
1566 _gl_use_thread_operate_medias(ad, GL_STR_MOVING, cnt,
1571 /* Update view after moving process done */
1572 int gl_update_move_view(void *data)
1574 GL_CHECK_VAL(data, -1);
1575 gl_appdata *ad = (gl_appdata *)data;
1576 int view_mode = gl_get_view_mode(ad);
1577 gl_dbg("view_mode: %d", view_mode);
1578 _gl_data_selected_list_finalize(ad);
1579 _gl_notify_destroy_selinfo(ad);
1580 /* Update albums list and items list */
1581 gl_refresh_albums_list(ad);
1583 _gl_update_operation_view(ad, GL_STR_MOVED);
1588 /* Share album's content */
1589 int _gl_share_select_album(void *data)
1591 GL_CHECK_VAL(data, -1);
1592 gl_appdata *ad = (gl_appdata *)data;
1593 char *label = ad->popupinfo.popup_item_label;
1594 gl_dbg("label : %s ", label);
1596 int cnt = _gl_data_get_albums_selected_cnt(ad);
1597 gl_dbg("Selected album(s) count: %d.", cnt);
1599 gl_dbgE("None album selected!");
1600 gl_popup_create_popup(ad, GL_POPUP_NOBUT,
1601 GL_STR_NO_ALBUMS_SELECTED);
1604 if (_gl_data_is_albums_selected_empty(ad)) {
1605 gl_dbgE("None thumb selected!");
1606 gl_popup_create_popup(ad, GL_POPUP_NOBUT,
1607 GL_STR_NO_FILES_SELECTED);
1611 if (!g_strcmp0(label, GL_SHARE_MESSAGE)) {
1612 gl_ext_load_ug(ad, GL_UG_MSG);
1613 } else if (!g_strcmp0(label, GL_SHARE_EMAIL)) {
1614 gl_ext_load_ug(ad, GL_UG_EMAIL);
1615 } else if (!g_strcmp0(label, GL_SHARE_BLUETOOTH)) {
1616 gl_ext_load_ug(ad, GL_UG_BT);
1618 gl_dbgE("Wrong UG name!");
1624 int gl_share_select_item(void *data)
1626 GL_CHECK_VAL(data, -1);
1627 gl_appdata *ad = (gl_appdata *)data;
1628 char *label = ad->popupinfo.popup_item_label;
1629 gl_dbg("label : %s ", label);
1632 int view_mode = gl_get_view_mode(ad);
1633 if (view_mode == GL_VIEW_VIDEOLIST)
1636 cnt = _gl_data_selected_list_count(ad);
1638 gl_dbg("Selected item(s) count: %d.", cnt);
1640 gl_dbgE("None items selected!");
1641 gl_popup_create_popup(ad, GL_POPUP_NOBUT,
1642 GL_STR_NO_FILES_SELECTED);
1646 if (!g_strcmp0(label, GL_SHARE_MESSAGE)) {
1647 gl_ext_load_ug(ad, GL_UG_MSG);
1648 } else if (!g_strcmp0(label, GL_SHARE_EMAIL)) {
1649 gl_ext_load_ug(ad, GL_UG_EMAIL);
1650 } else if (!g_strcmp0(label, GL_SHARE_BLUETOOTH)) {
1651 gl_ext_load_ug(ad, GL_UG_BT);
1654 else if (!g_strcmp0(label, GL_SHARE_WIFI)) {
1655 gl_ext_load_ug(ad, GL_UG_WIFI);
1659 gl_dbgE("Wrong UG name!");
1666 #ifdef _USE_ROTATE_BG
1668 int _gl_delay(double sec)
1672 unsigned int start_t = 0;
1673 unsigned int end_t = 0;
1674 unsigned int delay_t = (unsigned int)(sec * GL_TIME_USEC_PER_SEC);
1676 gettimeofday(&tv, NULL);
1677 start_t = tv.tv_sec * GL_TIME_USEC_PER_SEC + tv.tv_usec;
1679 for(end_t = start_t; end_t - start_t < delay_t;) {
1680 gettimeofday(&tv, NULL);
1681 end_t = tv.tv_sec * GL_TIME_USEC_PER_SEC + tv.tv_usec;
1688 int _gl_rotate_images(void *data, bool b_left)
1691 GL_CHECK_VAL(data, -1);
1692 gl_appdata *ad = (gl_appdata *)data;
1693 /* Get all selected medias count */
1694 int cnt = _gl_data_selected_list_count(ad);
1695 /* Check MMC state for cancel operation */
1696 gl_check_mmc_state(ad, NULL);
1697 gl_dbg("MMC state: %d.", ad->maininfo.mmc_state);
1699 int op_type = GL_MEDIA_OP_ROTATING_LEFT;
1702 op_type = GL_MEDIA_OP_ROTATING_RIGHT;
1703 _gl_use_thread_operate_medias(ad, GL_STR_ROTATING, cnt, op_type);
1708 int _gl_rotate_selected(void *data, int op_type)
1710 GL_CHECK_VAL(data, -1);
1711 gl_appdata *ad = (gl_appdata *)data;
1712 /* Get all selected medias count */
1713 int cnt = _gl_data_selected_list_count(ad);
1714 gl_item *gitem = NULL;
1715 gl_media_s *new_item= NULL;
1717 int popup_op = GL_POPUP_OP_NONE;
1718 unsigned int orient = GL_ORIENTATION_ROT_ERR;
1719 unsigned int new_orient = GL_ORIENTATION_ROT_ERR;
1721 bool b_left = false;
1723 if (op_type == GL_MEDIA_OP_ROTATING_LEFT)
1726 gl_cluster *current_album = ad->albuminfo.current_album;
1727 /* Save cluster path to set new current_album from new albums list */
1728 if (current_album && current_album->cluster &&
1729 current_album->cluster->path &&
1730 strlen(current_album->cluster->path))
1731 g_strlcpy(ad->albuminfo.dest_folder,
1732 current_album->cluster->path, GL_DIR_PATH_LEN_MAX);
1734 gl_dbgE("Invalid folder path!");
1736 /* Removed media from selected_media_elist */
1737 for (i = 1; i <= cnt; i++) {
1738 _gl_data_get_item_by_index(ad, i, true, &gitem);
1739 if (gitem != NULL && gitem->item != NULL &&
1740 gitem->item->file_url &&
1741 gitem->item->type == MEDIA_CONTENT_TYPE_IMAGE &&
1742 GL_FILE_EXISTS(gitem->item->file_url)) {
1743 /* Save orient in file */
1744 ret = _gl_exif_get_orientation(gitem->item->file_url,
1747 new_orient = _gl_exif_get_rotated_orientation(orient,
1750 /* Delete old record */
1751 ret = _gl_data_delete_media(ad, gitem->item);
1753 gl_dbgE("media_info_delete_from_db failed[%d]!",
1756 _gl_exif_set_orientation(gitem->item->file_url,
1759 /* Add new record */
1760 ret = _gl_local_data_add_media(gitem->item->file_url,
1763 gl_dbgE("Add media failed[%d]!", ret);
1764 /* Get handle via file_url */
1766 _gl_local_data_get_media_by_path(gitem->item->file_url,
1770 gl_dbgE("Invalid item!");
1773 /* Add some delay for last two images to wait for thumb updated */
1775 _gl_delay(GL_ROTATE_DELAY);
1777 /* Check new thumb of last image */
1779 gl_dbgW("Last image rotated, check thumb!");
1780 /* Fetch thumbnail from media-service */
1781 char *thumb = calloc(1, GL_FILE_PATH_LEN_MAX);
1782 GL_CHECK_VAL(thumb, -1);
1784 if (new_item && new_item->media_h)
1785 _gl_local_data_get_thumb(new_item, &thumb);
1786 gl_dbg("Thumbnail[%s]", thumb);
1787 /* Add another delay if thumb is invalid */
1788 if (!GL_FILE_EXISTS(thumb))
1789 _gl_delay(GL_ROTATE_DELAY);
1792 /* Free gl_media_s item */
1794 _gl_data_type_free_glitem((void **)(&new_item));
1796 gl_dbg("Write pipe, make progressbar updated!");
1797 gl_thread_write_pipe(ad, i, popup_op);
1804 /* Update view after deleting process done */
1805 int _gl_update_rotate_view(void *data)
1807 GL_CHECK_VAL(data, -1);
1808 gl_appdata *ad = (gl_appdata *)data;
1809 _gl_data_selected_list_finalize(ad);
1811 int view_mode = gl_get_view_mode(ad);
1812 gl_dbg("view_mode: %d.", view_mode);
1813 __gl_refresh_albums_list(ad, true);
1815 memset(ad->albuminfo.dest_folder, 0x00, GL_DIR_PATH_LEN_MAX);
1817 _gl_update_operation_view(ad, GL_STR_ROTATED);
1824 Eina_Bool gl_update_view(void *data, int mode)
1826 GL_CHECK_FALSE(data);
1827 gl_appdata *ad = (gl_appdata *)data;
1828 int view_mode = gl_get_view_mode(ad);
1829 gl_dbg("view_mode: %d", view_mode);
1830 if (mode == GL_UPDATE_VIEW_NONE) {
1831 gl_dbg("Don't need to update");
1835 if (view_mode == GL_VIEW_ALBUMS ||
1836 view_mode == GL_VIEW_ALBUMS_EDIT ||
1837 view_mode == GL_VIEW_ALBUMS_RENAME) {
1838 /* Albums list should be updated first */
1839 gl_albums_update_view(ad);
1840 } else if (view_mode == GL_VIEW_THUMBS ||
1841 view_mode == GL_VIEW_VIDEOLIST) {
1842 gl_cluster *cur_album = ad->albuminfo.current_album;
1843 /* MMC removed, change to albums view if in mmc album */
1844 if (mode == GL_UPDATE_VIEW_MMC_REMOVED && cur_album &&
1845 cur_album->cluster &&
1846 cur_album->cluster->type == GL_MMC) {
1847 gl_dbgW("MMC removed, change to albums view!");
1848 gl_pop_to_ctrlbar_ly(ad, true);
1852 /* Albums list should be updated first */
1853 _gl_update_thumb_items(ad, true);
1854 } else if (view_mode == GL_VIEW_THUMBS_EDIT ||
1855 view_mode == GL_VIEW_VIDEOLIST_EDIT) {
1856 /* Check thread operation case */
1857 if (ad->pbarinfo.sync_pipe) {
1858 gl_dbgW("Thread operation is in process!");
1862 gl_cluster *cur_album = ad->albuminfo.current_album;
1863 /* MMC removed, change to albums view if in mmc album */
1864 if (mode == GL_UPDATE_VIEW_MMC_REMOVED && cur_album &&
1865 cur_album->cluster &&
1866 cur_album->cluster->type == GL_MMC) {
1867 gl_dbgW("MMC removed, change to albums view!");
1868 gl_pop_to_ctrlbar_ly(ad, true);
1872 /* Albums list should be updated first */
1873 _gl_update_thumb_items(ad, true);
1880 * Parse medias type and count of selected items,
1881 * and set different type for share items.
1883 int gl_get_share_mode(void *data)
1885 GL_CHECK_VAL(data, -1);
1886 gl_appdata *ad = (gl_appdata *)data;
1887 int share_mode = GL_SHARE_NONE;
1891 int view_m = gl_get_view_mode(ad);
1892 if (view_m == GL_VIEW_ALBUMS_EDIT) {
1893 GL_CHECK_VAL(ad->albuminfo.selected_albums_elist, -1);
1894 gl_cluster *cur_album = NULL;
1895 cur_album = eina_list_nth(ad->albuminfo.selected_albums_elist, 0);
1896 GL_CHECK_VAL(cur_album, -1);
1897 GL_CHECK_VAL(cur_album->cluster, -1);
1898 sel_cnt = ad->selectedinfo.sel_cnt;
1899 } else if (view_m == GL_VIEW_VIDEOLIST) {
1900 return GL_SHARE_VIDEO_ONE;
1901 } else if (view_m == GL_VIEW_ALBUMS) {
1902 sel_cnt = ad->selectedinfo.sel_cnt;
1904 GL_CHECK_VAL(ad->selectedinfo.medias_elist, -1);
1905 sel_cnt = eina_list_count(ad->selectedinfo.medias_elist);
1907 image_cnt = ad->selectedinfo.images_cnt;
1908 if(image_cnt > sel_cnt) {
1909 gl_dbgE("Images count is wrong!");
1913 video_cnt = sel_cnt - image_cnt;
1914 gl_dbg("Selected items count: %d, image count: %d, video count: %d.",
1915 sel_cnt, image_cnt, video_cnt);
1917 if (ad->selectedinfo.drms_cnt) {
1918 share_mode = GL_SHARE_DRM;
1919 } else if (image_cnt && video_cnt) {
1920 share_mode = GL_SHARE_IMAGE_VIDEO;
1921 } else if (image_cnt) {
1922 if (ad->selectedinfo.jpeg_cnt == sel_cnt) {
1924 share_mode = GL_SHARE_IMAGE_ONE_JPEG;
1926 share_mode = GL_SHARE_IMAGE_MULTI_JPEG;
1929 share_mode = GL_SHARE_IMAGE_ONE;
1931 share_mode = GL_SHARE_IMAGE_MULTI;
1933 } else if (video_cnt) {
1934 if (video_cnt == 1) {
1935 share_mode = GL_SHARE_VIDEO_ONE;
1937 share_mode = GL_SHARE_VIDEO_MULTI;
1940 gl_dbgE("Error: no video and image!");
1943 gl_dbg("share_mode is %d.", share_mode);
1948 int _gl_destroy_albums_edit_view(void *data)
1950 GL_CHECK_VAL(data, -1);
1951 gl_appdata *ad = (gl_appdata *)data;
1953 if (ad->albuminfo.edit_layout) {
1954 evas_object_del(ad->albuminfo.edit_layout);
1955 ad->albuminfo.edit_view = NULL;
1956 ad->albuminfo.edit_layout = NULL;
1961 int _gl_destroy_thumbs_edit_view(void *data)
1963 GL_CHECK_VAL(data, -1);
1964 gl_appdata *ad = (gl_appdata *)data;
1966 if (ad->gridinfo.edit_layout) {
1967 evas_object_del(ad->gridinfo.edit_layout);
1968 ad->gridinfo.edit_view = NULL;
1969 ad->gridinfo.edit_layout = NULL;
1974 int gl_destroy_thumbs_view(void *data)
1976 GL_CHECK_VAL(data, -1);
1977 gl_appdata *ad = (gl_appdata *)data;
1978 int view_mode = gl_get_view_mode(ad);
1979 gl_dbg("view_mode: %d.", view_mode);
1981 gl_del_invalid_widgets(ad, GL_INVALID_NONE);
1983 if(ad->gridinfo.edit_view) {
1984 _gl_destroy_thumbs_edit_view(ad);
1985 _gl_data_selected_list_finalize(ad);
1987 _gl_grid_del_append_idler(ad);
1989 _gl_notify_destroy_selinfo(ad);
1991 _gl_editfield_destroy_imf(ad);
1993 gl_grid_clear_view(ad);
1994 gl_list_clear_view(ad);
1996 ad->albuminfo.current_album = NULL;
1997 ad->maininfo.seg_mode = GL_CTRL_SEG_ALL;
1999 /* Pop to controlbar layout */
2000 elm_naviframe_item_pop_to(ad->albuminfo.nf_it);
2006 * b_update_albums_list
2007 * True: Update albums list. False: Albums list already updated.
2009 * It's in thumbnails view, video list view, or selectioinfo view.
2010 * Destroy invalid widegets or UGs.
2011 * Pop current invalid view to controlbar layout,
2012 * to show Albums view
2014 int gl_pop_to_ctrlbar_ly(void *data, bool b_update_albums_list)
2016 GL_CHECK_VAL(data, -1);
2017 gl_appdata *ad = (gl_appdata *)data;
2018 gl_dbg("b_update_albums_list: %d", b_update_albums_list);
2020 /* Destroy thumbnails/video_list view then pop to ctrlbar_ly */
2021 gl_destroy_thumbs_view(ad);
2023 /* Update albums list */
2024 if (b_update_albums_list)
2025 gl_refresh_albums_list(ad);
2027 if (gl_check_gallery_empty(ad)) {
2028 gl_albums_comeback_from_view(ad);
2029 /* None albums, disable edit button/controlbar */
2030 _gl_ctrl_disable_toolbar_item(ad, true, GL_NAVI_ALBUMS, true);
2032 /* Change to albums view. */
2033 gl_dbg("Change to Albums view.");
2034 gl_albums_comeback_from_view(ad);
2035 /* None editable albums, disable edit button */
2036 if (ad->albuminfo.cluster_list->edit_cnt == 0)
2037 _gl_ctrl_disable_toolbar_item(ad, true, GL_NAVI_ALBUMS,
2043 /* Vibrate device */
2044 int gl_play_vibration(void *data)
2047 GL_CHECK_VAL(data, -1);
2048 gl_appdata *ad = (gl_appdata *)data;
2051 if (ad->entryinfo.haptic_handle >= 0) {
2052 gl_dbg("Remove previous haptic handle.");
2053 _gl_stop_vibration(ad);
2056 ret = haptic_initialize();
2057 if (ret != HAPTIC_ERROR_NONE) {
2058 gl_dbgE("haptic_initialize failed[%d]!", ret);
2062 if (ad->entryinfo.vibration_timer) {
2063 ecore_timer_del(ad->entryinfo.vibration_timer);
2064 ad->entryinfo.vibration_timer = NULL;
2066 Ecore_Timer *vibration_timer = NULL;
2067 vibration_timer = ecore_timer_add(GL_TIMER_INTERVAL_VIBRATION,
2068 _gl_vibration_timer_cb, data);
2069 ad->entryinfo.vibration_timer = vibration_timer;
2070 ret = haptic_vibrate_monotone(GL_VIBRATION_DEVICE,
2071 GL_VIBRATION_DURATION, HAPTIC_LEVEL_AUTO);
2072 if (ret != HAPTIC_ERROR_NONE) {
2073 gl_dbgE("haptic_play_pattern failed[%d]!", ret);
2076 ad->entryinfo.haptic_handle = GL_VIBRATION_DEVICE;
2081 /* Change int to char * of video duration, caller need to free the allocated memory */
2082 char *_gl_get_duration_string(unsigned int v_dur)
2084 char *dur_str = calloc(1, GL_FILE_PATH_LEN_MAX);
2085 GL_CHECK_NULL(dur_str);
2087 int duration = floor(v_dur / GL_TIME_MSEC_PER_SEC);
2093 if (duration >= GL_TIME_SEC_PER_HOUR) {
2094 dur_sec = duration % GL_TIME_SEC_PER_MIN;
2095 tmp = floor(duration / GL_TIME_SEC_PER_MIN);
2096 dur_min = tmp % GL_TIME_MIN_PER_HOUR;
2097 dur_hr = floor(tmp / GL_TIME_MIN_PER_HOUR);
2098 } else if (duration >= GL_TIME_SEC_PER_MIN) {
2100 dur_min = floor(duration / GL_TIME_SEC_PER_MIN);
2101 dur_sec = duration % GL_TIME_SEC_PER_MIN;
2105 dur_sec = duration % GL_TIME_SEC_PER_MIN;
2108 snprintf(dur_str, GL_FILE_PATH_LEN_MAX, "%02d:%02d:%02d",
2109 dur_hr, dur_min, dur_sec);
2111 snprintf(dur_str, GL_FILE_PATH_LEN_MAX, "00:00:00");
2113 dur_str[strlen(dur_str)] = '\0';
2117 /* Fetch thumbnail from media-service, if it's invalid, generate new one */
2118 int _gl_get_thumb(void *data, const char *file_path, char **thumb_path)
2120 GL_CHECK_VAL(thumb_path, -1);
2121 GL_CHECK_VAL(file_path, -1);
2122 GL_CHECK_VAL(data, -1);
2123 /* Return if thumbnail is valid */
2124 if (*thumb_path && ecore_file_exists(*thumb_path) &&
2125 (ecore_file_size(*thumb_path) > 0)) {
2129 /* Free allocated memory first */
2131 gl_dbgW("Wrong thumb path[%s]", *thumb_path);
2135 gl_dbg("File[%s]", file_path);
2137 char *new_path = calloc(1, GL_FILE_PATH_LEN_MAX);
2138 GL_CHECK_VAL(new_path, -1);
2140 /* Generate thumbnail via thumbnail-service */
2142 ret = thumbnail_request_from_db(file_path, new_path,
2143 GL_FILE_PATH_LEN_MAX);
2145 gl_dbgE("thumbnail_request_from_db failed!");
2149 *thumb_path = new_path;
2150 gl_dbg("Request thumbnail[%s]", new_path);