Modify thumbnail creation and cancellation logic
[platform/core/multimedia/libmedia-thumbnail.git] / server / thumb-server-internal.c
1 /*
2  * media-thumbnail-server
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hyunjun Ko <zzoon.ko@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include "thumb-server-internal.h"
23 #include "media-thumb-util.h"
24 #include "media-thumb-debug.h"
25
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <dirent.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <Ecore_Evas.h>
32 #include <vconf.h>
33 #include <grp.h>
34 #include <pwd.h>
35
36 #ifdef LOG_TAG
37 #undef LOG_TAG
38 #endif
39
40 #define LOG_TAG "MEDIA_THUMBNAIL_SERVER"
41 #define THUMB_DEFAULT_WIDTH 320
42 #define THUMB_DEFAULT_HEIGHT 240
43 #define THUMB_BLOCK_SIZE 512
44 #define THUMB_ROOT_UID "0"
45
46 static __thread char **arr_path;
47 static __thread uid_t *arr_uid;
48 static __thread int g_idx = 0;
49 static __thread int g_cur_idx = 0;
50
51 GMainLoop *g_thumb_server_mainloop; // defined in thumb-server.c as extern
52
53 static gboolean __thumb_server_send_msg_to_agent(int msg_type);
54 static void __thumb_daemon_stop_job(void);
55 static int __thumb_daemon_all_extract(uid_t uid);
56 int _thumb_daemon_process_queue_jobs(gpointer data);
57 static gboolean _thumb_server_send_deny_message(int sockfd);
58
59 gboolean _thumb_daemon_start_jobs(gpointer data)
60 {
61         thumb_dbg("");
62         /* Initialize ecore-evas to use evas library */
63         ecore_evas_init();
64
65         __thumb_server_send_msg_to_agent(MS_MSG_THUMB_SERVER_READY);
66
67         return FALSE;
68 }
69
70 void _thumb_daemon_finish_jobs(void)
71 {
72         sqlite3 *sqlite_db_handle = _media_thumb_db_get_handle();
73
74         if (sqlite_db_handle != NULL) {
75                 _media_thumb_db_disconnect();
76                 thumb_dbg("sqlite3 handle is alive. So disconnect to sqlite3");
77         }
78
79         /* Shutdown ecore-evas */
80         ecore_evas_shutdown();
81         g_main_loop_quit(g_thumb_server_mainloop);
82
83         return;
84 }
85
86 int _thumb_daemon_mmc_status(void)
87 {
88         int err = -1;
89         int status = -1;
90
91         err = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &status);
92         if (err == 0) {
93                 return status;
94         } else if (err == -1) {
95                 thumb_err("vconf_get_int failed : %d", err);
96         } else {
97                 thumb_err("vconf_get_int Unexpected error code: %d", err);
98         }
99
100         return status;
101 }
102
103 void _thumb_daemon_mmc_eject_vconf_cb(void *data)
104 {
105         int err = -1;
106         int status = 0;
107
108         thumb_warn("_thumb_daemon_vconf_cb called");
109
110         err = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &status);
111         if (err == 0) {
112                 if (status == VCONFKEY_SYSMAN_MMC_REMOVED || status == VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED) {
113                         thumb_warn("SD card is ejected or not mounted. So media-thumbnail-server stops jobs to extract all thumbnails");
114
115                         __thumb_daemon_stop_job();
116                 }
117         } else if (err == -1) {
118                 thumb_err("vconf_get_int failed : %d", err);
119         } else {
120                 thumb_err("vconf_get_int Unexpected error code: %d", err);
121         }
122
123         return;
124 }
125
126 void _thumb_daemon_vconf_cb(void *data)
127 {
128         int err = -1;
129         int status = 0;
130
131         thumb_warn("_thumb_daemon_vconf_cb called");
132
133         err = vconf_get_int(VCONFKEY_SYSMAN_MMC_FORMAT, &status);
134         if (err == 0) {
135                 if (status == VCONFKEY_SYSMAN_MMC_FORMAT_COMPLETED) {
136                         thumb_warn("SD card format is completed. So media-thumbnail-server stops jobs to extract all thumbnails");
137
138                         __thumb_daemon_stop_job();
139                 } else {
140                         thumb_dbg("not completed");
141                 }
142         } else if (err == -1) {
143                 thumb_err("vconf_get_int failed : %d", err);
144         } else {
145                 thumb_err("vconf_get_int Unexpected error code: %d", err);
146         }
147
148         return;
149 }
150
151 static void __thumb_daemon_stop_job()
152 {
153         int i = 0;
154         char *path = NULL;
155
156         thumb_warn("There are %d jobs in the queue. But all jobs will be stopped", g_idx - g_cur_idx);
157
158         for (i = g_cur_idx; i < g_idx; i++) {
159                 path = arr_path[g_cur_idx++];
160                 SAFE_FREE(path);
161         }
162
163         return;
164 }
165
166 int _thumb_daemon_process_job(thumbMsg *req_msg, thumbMsg *res_msg, uid_t uid)
167 {
168         int err = MS_MEDIA_ERR_NONE;
169
170         err = _media_thumb_process(req_msg, res_msg, uid);
171         if (err != MS_MEDIA_ERR_NONE) {
172                 if (req_msg->msg_type == THUMB_REQUEST_SAVE_FILE) {
173                         thumb_err("_media_thumb_process is failed: %d", err);
174                         res_msg->status = THUMB_FAIL;
175                 } else {
176                         thumb_warn("_media_thumb_process is failed: %d, So use default thumb", err);
177                         res_msg->status = THUMB_SUCCESS;
178                 }
179         } else {
180                 res_msg->status = THUMB_SUCCESS;
181         }
182
183         return err;
184 }
185
186 static int __thumb_daemon_process_job_raw(thumbMsg *req_msg, thumbMsg *res_msg)
187 {
188         int err = MS_MEDIA_ERR_NONE;
189
190         err = _media_thumb_process_raw(req_msg, res_msg);
191         if (err != MS_MEDIA_ERR_NONE) {
192                 if (err != MS_MEDIA_ERR_FILE_NOT_EXIST) {
193                         thumb_warn("_media_thumb_process is failed: %d, So use default thumb", err);
194                         res_msg->status = THUMB_SUCCESS;
195                 } else {
196                         thumb_warn("_media_thumb_process is failed: %d, (file not exist) ", err);
197                         res_msg->status = THUMB_FAIL;
198                 }
199         } else {
200                 res_msg->status = THUMB_SUCCESS;
201         }
202
203         return err;
204 }
205
206 static int __thumb_daemon_all_extract(uid_t uid)
207 {
208         int err = MS_MEDIA_ERR_NONE;
209         char query_string[MAX_PATH_SIZE + 1] = { 0, };
210         char path[MAX_PATH_SIZE + 1] = { 0, };
211         sqlite3 *sqlite_db_handle = NULL;
212         sqlite3_stmt *sqlite_stmt = NULL;
213
214         err = _media_thumb_db_connect(uid);
215         if (err != MS_MEDIA_ERR_NONE) {
216                 thumb_err("_media_thumb_db_connect failed: %d", err);
217                 return err;
218         }
219
220         sqlite_db_handle = _media_thumb_db_get_handle();
221         if (sqlite_db_handle == NULL) {
222                 thumb_err("sqlite handle is NULL");
223                 return MS_MEDIA_ERR_INTERNAL;
224         }
225
226         if (_thumb_daemon_mmc_status() == VCONFKEY_SYSMAN_MMC_MOUNTED) {
227                 snprintf(query_string, sizeof(query_string), SELECT_PATH_FROM_UNEXTRACTED_THUMB_MEDIA);
228         } else {
229                 snprintf(query_string, sizeof(query_string), SELECT_PATH_FROM_UNEXTRACTED_THUMB_INTERNAL_MEDIA);
230         }
231
232         thumb_warn("Query: %s", query_string);
233
234         err = sqlite3_prepare_v2(sqlite_db_handle, query_string, strlen(query_string), &sqlite_stmt, NULL);
235         if (SQLITE_OK != err) {
236                 thumb_err("prepare error [%s]", sqlite3_errmsg(sqlite_db_handle));
237                 _media_thumb_db_disconnect();
238                 return MS_MEDIA_ERR_INTERNAL;
239         }
240
241         while(1) {
242                 err = sqlite3_step(sqlite_stmt);
243                 if (err != SQLITE_ROW) {
244                         thumb_dbg("end of row [%s]", sqlite3_errmsg(sqlite_db_handle));
245                         break;
246                 }
247
248                 strncpy(path, (const char *)sqlite3_column_text(sqlite_stmt, 0), sizeof(path));
249                 path[sizeof(path) - 1] = '\0';
250
251                 thumb_dbg_slog("Path : %s", path);
252
253                 if (g_idx == 0) {
254                         arr_path = (char**)malloc(sizeof(char*));
255                         arr_uid = (uid_t*)malloc(sizeof(uid_t));
256                 } else {
257                         arr_path = (char**)realloc(arr_path, (g_idx + 1) * sizeof(char*));
258                         arr_uid = (uid_t*)realloc(arr_uid, (g_idx + 1) * sizeof(uid_t));
259                 }
260                 arr_uid[g_idx] = uid;
261                 arr_path[g_idx++] = strdup(path);
262         }
263
264         sqlite3_finalize(sqlite_stmt);
265         _media_thumb_db_disconnect();
266
267         return MS_MEDIA_ERR_NONE;
268 }
269
270 int _thumb_daemon_process_queue_jobs(gpointer data)
271 {
272         int err = MS_MEDIA_ERR_NONE;
273         char *path = NULL;
274         uid_t uid = NULL;
275
276         if (g_cur_idx < g_idx) {
277                 thumb_warn("There are %d jobs in the queue", g_idx - g_cur_idx);
278                 thumb_dbg("Current idx : [%d]", g_cur_idx);
279                 uid = arr_uid[g_cur_idx];
280                 path = arr_path[g_cur_idx++];
281
282                 thumbMsg recv_msg, res_msg;
283                 memset(&recv_msg, 0x00, sizeof(thumbMsg));
284                 memset(&res_msg, 0x00, sizeof(thumbMsg));
285
286                 recv_msg.msg_type = THUMB_REQUEST_DB_INSERT;
287                 strncpy(recv_msg.org_path, path, sizeof(recv_msg.org_path));
288                 recv_msg.org_path[sizeof(recv_msg.org_path) - 1] = '\0';
289
290                 err = _thumb_daemon_process_job(&recv_msg, &res_msg,uid );
291                 if (err == MS_MEDIA_ERR_FILE_NOT_EXIST) {
292                         thumb_err("Thumbnail processing is failed : %d", err);
293                 } else {
294                         if (res_msg.status == THUMB_SUCCESS) {
295
296                                 err = _media_thumb_db_connect(uid);
297                                 if (err != MS_MEDIA_ERR_NONE) {
298                                         thumb_err("_media_thumb_mb_svc_connect failed: %d", err);
299                                         return TRUE;
300                                 }
301
302                                 /* Need to update DB once generating thumb is done */
303                                 err = _media_thumb_update_db(recv_msg.org_path,
304                                                                                         res_msg.dst_path,
305                                                                                         res_msg.origin_width,
306                                                                                         res_msg.origin_height,
307                                                                                         uid);
308                                 if (err != MS_MEDIA_ERR_NONE) {
309                                         thumb_err("_media_thumb_update_db failed : %d", err);
310                                 }
311
312                                 _media_thumb_db_disconnect();
313                         }
314                 }
315
316                 SAFE_FREE(path);
317         } else {
318                 g_cur_idx = 0;
319                 g_idx = 0;
320                 thumb_warn("Deleting array");
321                 SAFE_FREE(arr_path);
322                 SAFE_FREE(arr_uid);
323                 //_media_thumb_db_disconnect();
324
325                 __thumb_server_send_msg_to_agent(MS_MSG_THUMB_EXTRACT_ALL_DONE); // MS_MSG_THUMB_EXTRACT_ALL_DONE
326
327                 return FALSE;
328         }
329
330         return TRUE;
331 }
332
333 gboolean _thumb_server_read_socket(GIOChannel *src,
334                                                                         GIOCondition condition,
335                                                                         gpointer data)
336 {
337         struct sockaddr_un client_addr;
338         unsigned int client_addr_len;
339         thumbMsg recv_msg;
340         thumbMsg res_msg;
341         ms_peer_credentials credentials;
342
343         int sock = -1;
344         int client_sock = -1;
345
346         memset((void *)&recv_msg, 0, sizeof(recv_msg));
347         memset((void *)&res_msg, 0, sizeof(res_msg));
348         memset((void *)&credentials, 0, sizeof(credentials));
349
350         sock = g_io_channel_unix_get_fd(src);
351         if (sock < 0) {
352                 thumb_err("sock fd is invalid!");
353                 return TRUE;
354         }
355
356         client_addr_len = sizeof(client_addr);
357
358         if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
359                 thumb_stderror("accept failed : %s");
360                 return TRUE;
361         }
362
363         if (ms_cynara_receive_untrusted_message_thumb(client_sock, &recv_msg, &credentials) != MS_MEDIA_ERR_NONE) {
364                 thumb_err("ms_cynara_receive_untrusted_message_thumb failed");  
365                 close(client_sock);
366                 return FALSE;
367         }
368
369         if (recv_msg.msg_type == THUMB_REQUEST_KILL_SERVER && strncmp(credentials.uid, THUMB_ROOT_UID, strlen(THUMB_ROOT_UID)) != 0) {
370                 thumb_err("Only root can send THUMB_REQUEST_KILL_SERVER request");
371                 _thumb_server_send_deny_message(client_sock);
372                 close(client_sock);
373                 return TRUE;
374         }
375
376         if(recv_msg.msg_type != THUMB_REQUEST_KILL_SERVER) {
377                 if (ms_cynara_check(&credentials, MEDIA_STORAGE_PRIVILEGE) != MS_MEDIA_ERR_NONE) {
378                         thumb_err("Cynara denied access to process request");
379                         _thumb_server_send_deny_message(client_sock);
380                         close(client_sock);
381                         return TRUE;
382                 }
383         }
384
385         SAFE_FREE(credentials.smack);
386         SAFE_FREE(credentials.uid);
387
388         thumb_warn_slog("Received [%d] %s(%d) from PID(%d)", recv_msg.msg_type, recv_msg.org_path, strlen(recv_msg.org_path), recv_msg.pid);
389
390         if (recv_msg.msg_type == THUMB_REQUEST_ALL_MEDIA) {
391                 thumb_dbg("All thumbnails are being extracted now");
392                 __thumb_daemon_all_extract(recv_msg.uid);
393                 g_idle_add(_thumb_daemon_process_queue_jobs, NULL);
394         } else if(recv_msg.msg_type == THUMB_REQUEST_RAW_DATA) {
395                 __thumb_daemon_process_job_raw(&recv_msg, &res_msg);
396         } else if(recv_msg.msg_type == THUMB_REQUEST_KILL_SERVER) {
397                 thumb_warn("received KILL msg from thumbnail agent.");
398         } else {
399                 _thumb_daemon_process_job(&recv_msg, &res_msg,recv_msg.uid);
400         }
401
402         if(res_msg.msg_type == 0)
403                 res_msg.msg_type = recv_msg.msg_type;
404         res_msg.request_id = recv_msg.request_id;
405         strncpy(res_msg.org_path, recv_msg.org_path, recv_msg.origin_path_size);
406         res_msg.origin_path_size = recv_msg.origin_path_size;
407         if(res_msg.msg_type != THUMB_RESPONSE_RAW_DATA) {
408                 res_msg.dest_path_size = strlen(res_msg.dst_path)+1;
409                 res_msg.thumb_size = 0;
410         } else {
411                 res_msg.dest_path_size = 1;
412                 res_msg.dst_path[0] = '\0';
413         }
414
415         int buf_size = 0;
416         int sending_block = 0;
417         int block_size = sizeof(res_msg) - MAX_FILEPATH_LEN*2 - sizeof(unsigned char *);
418         unsigned char *buf = NULL;
419         _media_thumb_set_buffer(&res_msg, &buf, &buf_size);
420
421         while(buf_size > 0) {
422                 if(buf_size < THUMB_BLOCK_SIZE) {
423                         block_size = buf_size;
424                 }
425                 if (send(client_sock, buf+sending_block, block_size, 0) != block_size) {
426                         thumb_stderror("sendto failed : %s");
427                 }
428                 sending_block += block_size;
429                 buf_size -= block_size;
430                 if(block_size < THUMB_BLOCK_SIZE) {
431                         block_size = THUMB_BLOCK_SIZE;
432                 }
433         }
434         if(buf_size == 0) {
435                 thumb_dbg_slog("Sent data(%d) from %s", res_msg.thumb_size, res_msg.org_path);
436         }
437         SAFE_FREE(buf);
438
439         if(recv_msg.msg_type == THUMB_REQUEST_KILL_SERVER) {
440                 thumb_warn("Shutting down...");
441                 g_main_loop_quit(g_thumb_server_mainloop);
442         }
443
444         close(client_sock);
445
446         return TRUE;
447 }
448
449 static gboolean __thumb_server_send_msg_to_agent(int msg_type)
450 {
451         int sock;
452         ms_sock_info_s sock_info;
453         struct sockaddr_un serv_addr;
454         ms_thumb_server_msg send_msg;
455         sock_info.port = MS_THUMB_COMM_PORT;
456
457         if (ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_10, &sock_info) < 0) {
458                 thumb_err("ms_ipc_create_server_socket failed");
459                 return FALSE;
460         }
461
462         memset(&serv_addr, 0, sizeof(serv_addr));
463
464         sock = sock_info.sock_fd;
465         serv_addr.sun_family = AF_UNIX;
466         strcpy(serv_addr.sun_path, "/var/run/media-server/media_ipc_thumbcomm.socket");
467
468
469         /* Connecting to the thumbnail server */
470         if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
471                 thumb_stderror("connect");
472                 ms_ipc_delete_client_socket(&sock_info);
473                 return MS_MEDIA_ERR_SOCKET_CONN;
474         }
475
476         send_msg.msg_type = msg_type;
477
478         if (send(sock, &send_msg, sizeof(ms_thumb_server_msg), 0) != sizeof(ms_thumb_server_msg)) {
479                 thumb_stderror("sendto failed");
480                 ms_ipc_delete_client_socket(&sock_info);
481                 return FALSE;
482         }
483
484         thumb_dbg("Sending msg to thumbnail agent[%d] is successful", send_msg.msg_type);
485
486         ms_ipc_delete_client_socket(&sock_info);
487
488         return TRUE;
489 }
490
491 static gboolean _thumb_server_send_deny_message(int sockfd)
492 {
493         thumbMsg msg = {0};
494         int bytes_to_send = sizeof(msg) - sizeof(msg.org_path) - sizeof(msg.dst_path);
495
496         msg.msg_type = THUMB_RESPONSE;
497         msg.status = THUMB_FAIL;
498
499         if (send(sockfd, &msg, bytes_to_send, 0) != bytes_to_send) {
500                 thumb_stderror("send failed");
501                 return FALSE;
502         }
503
504         return TRUE;
505 }
506
507 gboolean _thumb_server_prepare_socket(int *sock_fd)
508 {
509         int sock;
510         unsigned short serv_port;
511
512         thumbMsg recv_msg;
513         thumbMsg res_msg;
514
515         memset((void *)&recv_msg, 0, sizeof(recv_msg));
516         memset((void *)&res_msg, 0, sizeof(res_msg));
517         serv_port = MS_THUMB_DAEMON_PORT;
518
519         if (ms_ipc_create_server_socket(MS_PROTOCOL_TCP, serv_port, &sock) < 0) {
520                 thumb_err("ms_ipc_create_server_socket failed");
521                 return FALSE;
522         }
523
524         if (ms_cynara_enable_credentials_passing(sock) != MS_MEDIA_ERR_NONE) {
525                 thumb_err("ms_cynara_enable_credentials_passing failed");
526                 return FALSE;
527         }
528
529         *sock_fd = sock;
530
531         return TRUE;
532 }
533
534 static char* _media_thumb_get_default_path(uid_t uid)
535 {
536         char *result_psswd = NULL;
537         struct group *grpinfo = NULL;
538         if(uid == getuid())
539         {
540                 result_psswd = strdup(THUMB_DEFAULT_PATH);
541                 grpinfo = getgrnam("users");
542                 if(grpinfo == NULL) {
543                         thumb_err("getgrnam(users) returns NULL !");
544                         if(result_psswd)
545                                 free(result_psswd);
546                         return NULL;
547                 }
548         }
549         else
550         {
551                 struct passwd *userinfo = getpwuid(uid);
552                 if(userinfo == NULL) {
553                         thumb_err("getpwuid(%d) returns NULL !", uid);
554                         return NULL;
555                 }
556                 grpinfo = getgrnam("users");
557                 if(grpinfo == NULL) {
558                         thumb_err("getgrnam(users) returns NULL !");
559                         return NULL;
560                 }
561                 // Compare git_t type and not group name
562                 if (grpinfo->gr_gid != userinfo->pw_gid) {
563                         thumb_err("UID [%d] does not belong to 'users' group!", uid);
564                         return NULL;
565                 }
566                 asprintf(&result_psswd, "%s/share/media/.thumb/phone", userinfo->pw_dir);
567         }
568
569         return result_psswd;
570 }
571
572 int _thumbnail_get_data(const char *origin_path,
573                                                 media_thumb_format format,
574                                                 char *thumb_path,
575                                                 unsigned char **data,
576                                                 int *size,
577                                                 int *width,
578                                                 int *height,
579                                                 int *origin_width,
580                                                 int *origin_height,
581                                                 int *alpha,
582                                                 bool *is_saved)
583 {
584         int err = MS_MEDIA_ERR_NONE;
585         int thumb_width = -1;
586         int thumb_height = -1;
587
588         if (origin_path == NULL || size == NULL
589                         || width == NULL || height == NULL) {
590                 thumb_err("Invalid parameter");
591                 return MS_MEDIA_ERR_INVALID_PARAMETER;
592         }
593
594         if (format < MEDIA_THUMB_BGRA || format > MEDIA_THUMB_RGB888) {
595                 thumb_err("parameter format is invalid");
596                 return MS_MEDIA_ERR_INVALID_PARAMETER;
597         }
598
599         if (!g_file_test
600                 (origin_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
601                         thumb_err("Original path (%s) does not exist", origin_path);
602                         return MS_MEDIA_ERR_INVALID_PARAMETER;
603         }
604
605         thumb_dbg("Origin path : %s", origin_path);
606
607         int file_type = THUMB_NONE_TYPE;
608         media_thumb_info thumb_info = {0,};
609         file_type = _media_thumb_get_file_type(origin_path);
610         thumb_width = *width;
611         thumb_height = *height;
612         if(thumb_width == 0) {
613                 thumb_width = THUMB_DEFAULT_WIDTH;
614                 thumb_height = THUMB_DEFAULT_HEIGHT;
615         }
616
617         if (file_type == THUMB_IMAGE_TYPE) {
618                 err = _media_thumb_image(origin_path, thumb_path, thumb_width, thumb_height, format, &thumb_info, FALSE);
619                 if (err != MS_MEDIA_ERR_NONE) {
620                         thumb_err("_media_thumb_image failed");
621                         return err;
622                 }
623         } else if (file_type == THUMB_VIDEO_TYPE) {
624                 err = _media_thumb_video(origin_path, thumb_width, thumb_height, format, &thumb_info);
625                 if (err != MS_MEDIA_ERR_NONE) {
626                         thumb_err("_media_thumb_image failed");
627                         return err;
628                 }
629         } else {
630                 thumb_err("invalid file type");
631                 return MS_MEDIA_ERR_INVALID_PARAMETER;
632         }
633
634         if (size) *size = thumb_info.size;
635         if (width) *width = thumb_info.width;
636         if (height) *height = thumb_info.height;
637         *data = thumb_info.data;
638         if (origin_width) *origin_width = thumb_info.origin_width;
639         if (origin_height) *origin_height = thumb_info.origin_height;
640         if (alpha) *alpha = thumb_info.alpha;
641         if (is_saved) *is_saved= thumb_info.is_saved;
642
643         thumb_dbg("Thumb data is generated successfully (Size:%d, W:%d, H:%d) 0x%x",
644                                 *size, *width, *height, *data);
645
646         return MS_MEDIA_ERR_NONE;
647 }
648
649 int _thumbnail_get_raw_data(const char *origin_path,
650                                                 media_thumb_format format,
651                                                 int *width,
652                                                 int *height,
653                                                 unsigned char **data,
654                                                 int *size)
655 {
656         int err = MS_MEDIA_ERR_NONE;
657         int thumb_width = -1;
658         int thumb_height = -1;
659         const char * thumb_path = NULL;
660
661         if (origin_path == NULL || *width <= 0 || *height <= 0) {
662                 thumb_err("Invalid parameter");
663                 return MS_MEDIA_ERR_INVALID_PARAMETER;
664         }
665
666         if (format < MEDIA_THUMB_BGRA || format > MEDIA_THUMB_RGB888) {
667                 thumb_err("parameter format is invalid");
668                 return MS_MEDIA_ERR_INVALID_PARAMETER;
669         }
670
671         if (!g_file_test
672                 (origin_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
673                         thumb_err("Original path (%s) does not exist", origin_path);
674                         return MS_MEDIA_ERR_INVALID_PARAMETER;
675         }
676
677 //      thumb_dbg_slog("Origin path : %s", origin_path);
678
679         int file_type = THUMB_NONE_TYPE;
680         media_thumb_info thumb_info = {0,};
681         file_type = _media_thumb_get_file_type(origin_path);
682         thumb_width = *width;
683         thumb_height = *height;
684
685         if (file_type == THUMB_IMAGE_TYPE) {
686                 err = _media_thumb_image(origin_path, thumb_path, thumb_width, thumb_height, format, &thumb_info, TRUE);
687                 if (err != MS_MEDIA_ERR_NONE) {
688                         thumb_err("_media_thumb_image failed");
689                         return err;
690                 }
691         } else if (file_type == THUMB_VIDEO_TYPE) {
692                 err = _media_thumb_video(origin_path, thumb_width, thumb_height, format, &thumb_info);
693                 if (err != MS_MEDIA_ERR_NONE) {
694                         thumb_err("_media_thumb_image failed");
695                         return err;
696                 }
697         } else {
698                 thumb_err("invalid file type");
699                 return MS_MEDIA_ERR_INVALID_PARAMETER;
700         }
701
702         if (size) *size = thumb_info.size;
703         *data = thumb_info.data;
704         *width = thumb_info.width;
705         *height = thumb_info.height;
706
707         //thumb_dbg("Thumb data is generated successfully (Size:%d, W:%d, H:%d) 0x%x", *size, *width, *height, *data);
708
709         return MS_MEDIA_ERR_NONE;
710 }
711
712 int _media_thumb_process(thumbMsg *req_msg, thumbMsg *res_msg, uid_t uid)
713 {
714         int err = MS_MEDIA_ERR_NONE;
715         unsigned char *data = NULL;
716         int thumb_size = 0;
717         int thumb_w = 0;
718         int thumb_h = 0;
719         int origin_w = 0;
720         int origin_h = 0;
721         int max_length = 0;
722         char *thumb_path = NULL;
723         int need_update_db = 0;
724         int alpha = 0;
725         bool is_saved = FALSE;
726
727         if (req_msg == NULL || res_msg == NULL) {
728                 thumb_err("Invalid msg!");
729                 return MS_MEDIA_ERR_INVALID_PARAMETER;
730         }
731
732         int msg_type = req_msg->msg_type;
733         const char *origin_path = req_msg->org_path;
734
735         media_thumb_format thumb_format = MEDIA_THUMB_BGRA;
736         thumb_w = req_msg->thumb_width;
737         thumb_h = req_msg->thumb_height;
738         thumb_path = res_msg->dst_path;
739         thumb_path[0] = '\0';
740         max_length = sizeof(res_msg->dst_path);
741
742         if (!g_file_test(origin_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
743                 thumb_err("origin_path does not exist in file system.");
744                 return MS_MEDIA_ERR_FILE_NOT_EXIST;
745         }
746
747         err = _media_thumb_db_connect(uid);
748         if (err != MS_MEDIA_ERR_NONE) {
749                 thumb_err("_media_thumb_mb_svc_connect failed: %d", err);
750                 return err;
751         }
752
753         if (msg_type == THUMB_REQUEST_DB_INSERT) {
754                 err = _media_thumb_get_thumb_from_db_with_size(origin_path, thumb_path, max_length, &need_update_db, &origin_w, &origin_h);
755                 if (err == MS_MEDIA_ERR_NONE) {
756                         res_msg->origin_width = origin_w;
757                         res_msg->origin_height = origin_h;
758                         _media_thumb_db_disconnect();
759                         return MS_MEDIA_ERR_NONE;
760                 } else {
761                         if (strlen(thumb_path) == 0) {
762                                 err = _media_thumb_get_hash_name(origin_path, thumb_path, max_length,uid);
763                                 if (err != MS_MEDIA_ERR_NONE) {
764                                         char *default_path = _media_thumb_get_default_path(uid);
765                                         if(default_path) {
766                                                 thumb_err("_media_thumb_get_hash_name failed - %d", err);
767                                                 strncpy(thumb_path, default_path, max_length);
768                                                 free(default_path);
769                                         }
770                                         _media_thumb_db_disconnect();
771                                         return err;
772                                 }
773
774                                 thumb_path[strlen(thumb_path)] = '\0';
775                         }
776                 }
777
778         } else if (msg_type == THUMB_REQUEST_SAVE_FILE) {
779                 strncpy(thumb_path, req_msg->dst_path, max_length);
780
781         } else if (msg_type == THUMB_REQUEST_ALL_MEDIA) {
782                 err = _media_thumb_get_hash_name(origin_path, thumb_path, max_length,uid);
783                 if (err != MS_MEDIA_ERR_NONE) {
784                         char *default_path = _media_thumb_get_default_path(uid);
785                         if(default_path) {
786                                 thumb_err("_media_thumb_get_hash_name failed - %d", err);
787                                 strncpy(thumb_path, default_path, max_length);
788                                 free(default_path);
789                         }
790                         _media_thumb_db_disconnect();
791                         return err;
792                 }
793
794                 thumb_path[strlen(thumb_path)] = '\0';
795         }
796
797         thumb_dbg_slog("Thumb path : %s", thumb_path);
798
799         if (g_file_test(thumb_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
800                 thumb_warn("thumb path already exists in file system.. remove the existed file");
801                 _media_thumb_remove_file(thumb_path);
802         }
803
804         err = _thumbnail_get_data(origin_path, thumb_format, thumb_path, &data, &thumb_size, &thumb_w, &thumb_h, &origin_w, &origin_h, &alpha, &is_saved);
805         if (err != MS_MEDIA_ERR_NONE) {
806                 char *default_path = _media_thumb_get_default_path(uid);
807                 thumb_err("_thumbnail_get_data failed - %d", err);
808                 SAFE_FREE(data);
809
810                 if(default_path) {
811                         strncpy(thumb_path, default_path, max_length);
812                         free(default_path);
813                 }
814                 goto DB_UPDATE;
815 //              _media_thumb_db_disconnect();
816 //              return err;
817         }
818
819         //thumb_dbg("Size : %d, W:%d, H:%d", thumb_size, thumb_w, thumb_h);
820         //thumb_dbg("Origin W:%d, Origin H:%d\n", origin_w, origin_h);
821         //thumb_dbg("Thumb : %s", thumb_path);
822
823         res_msg->msg_type = THUMB_RESPONSE;
824         res_msg->thumb_size = thumb_size;
825         res_msg->thumb_width = thumb_w;
826         res_msg->thumb_height = thumb_h;
827         res_msg->origin_width = origin_w;
828         res_msg->origin_height = origin_h;
829
830         /* If the image is transparent PNG format, make png file as thumbnail of this image */
831         if (alpha) {
832                 char file_ext[10];
833                 err = _media_thumb_get_file_ext(origin_path, file_ext, sizeof(file_ext));
834                 if (strncasecmp(file_ext, "png", 3) == 0) {
835                         int len = strlen(thumb_path);
836                         thumb_path[len - 3] = 'p';
837                         thumb_path[len - 2] = 'n';
838                         thumb_path[len - 1] = 'g';
839                 }
840                 thumb_dbg_slog("Thumb path is changed : %s", thumb_path);
841         }
842
843         if (is_saved == FALSE && data != NULL) {
844                 err = _media_thumb_save_to_file_with_evas(data, thumb_w, thumb_h, alpha, thumb_path);
845                 if (err != MS_MEDIA_ERR_NONE) {
846                         char *default_path = _media_thumb_get_default_path(uid);
847                         thumb_err("save_to_file_with_evas failed - %d", err);
848                         SAFE_FREE(data);
849
850                         if (msg_type == THUMB_REQUEST_DB_INSERT || msg_type == THUMB_REQUEST_ALL_MEDIA) {
851                                 if(default_path) {
852                                         strncpy(thumb_path, default_path, max_length);
853                                         free(default_path);
854                                 }
855                         }
856                         _media_thumb_db_disconnect();
857                         return err;
858                 } else {
859                         thumb_dbg("file save success");
860                 }
861         } else {
862                 thumb_dbg("file is already saved");
863         }
864
865         /* fsync */
866         int fd = 0;
867         fd = open(thumb_path, O_WRONLY);
868         if (fd < 0) {
869                 thumb_warn("open failed");
870         } else {
871                 err = fsync(fd);
872                 if (err == -1) {
873                         thumb_warn("fsync failed");
874                 }
875
876                 close(fd);
877         }
878         /* End of fsync */
879
880         SAFE_FREE(data);
881 DB_UPDATE:
882         /* DB update if needed */
883         if (need_update_db == 1) {
884                 err = _media_thumb_update_db(origin_path, thumb_path, res_msg->origin_width, res_msg->origin_height, uid);
885                 if (err != MS_MEDIA_ERR_NONE) {
886                         thumb_err("_media_thumb_update_db failed : %d", err);
887                 }
888         }
889
890         _media_thumb_db_disconnect();
891
892         return MS_MEDIA_ERR_NONE;
893 }
894
895 int
896 _media_thumb_process_raw(thumbMsg *req_msg, thumbMsg *res_msg)
897 {
898         int err = MS_MEDIA_ERR_NONE;
899         unsigned char *data = NULL;
900         int thumb_size = 0;
901         int thumb_w = 0;
902         int thumb_h = 0;
903
904         if (req_msg == NULL || res_msg == NULL) {
905                 thumb_err("Invalid msg!");
906                 return MS_MEDIA_ERR_INVALID_PARAMETER;
907         }
908
909         const char *origin_path = req_msg->org_path;
910
911         media_thumb_format thumb_format = MEDIA_THUMB_BGRA;
912         thumb_w = req_msg->thumb_width;
913         thumb_h = req_msg->thumb_height;
914
915         //thumb_dbg("origin_path : %s, thumb_w : %d, thumb_h : %d ", origin_path, thumb_w, thumb_h);
916
917         if (!g_file_test(origin_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
918                 thumb_err("origin_path does not exist in file system.");
919                 return MS_MEDIA_ERR_FILE_NOT_EXIST;
920         }
921
922         err = _thumbnail_get_raw_data(origin_path, thumb_format, &thumb_w, &thumb_h, &data, &thumb_size);
923
924         if (err != MS_MEDIA_ERR_NONE) {
925                 thumb_err("_thumbnail_get_data failed - %d", err);
926                 SAFE_FREE(data);
927         }
928
929         res_msg->msg_type = THUMB_RESPONSE_RAW_DATA;
930         res_msg->thumb_width = thumb_w;
931         res_msg->thumb_height = thumb_h;
932         res_msg->thumb_size = thumb_size;
933         res_msg->thumb_data = malloc(thumb_size * sizeof(unsigned char));
934         memcpy(res_msg->thumb_data, data, thumb_size);
935
936         //thumb_dbg("Size : %d, W:%d, H:%d", thumb_size, thumb_w, thumb_h);
937         SAFE_FREE(data);
938
939         return MS_MEDIA_ERR_NONE;
940 }