/* * media-thumbnail-server * * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: Hyunjun Ko * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "thumb-server-internal.h" #include #include #include #include #include #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "MEDIA_THUMBNAIL_SERVER" static __thread char **arr_path; static __thread int g_idx = 0; static __thread int g_cur_idx = 0; GMainLoop *g_thumb_server_mainloop; // defined in thumb-server.c as extern #ifdef _USE_MEDIA_UTIL_ gboolean _thumb_server_send_msg_to_agent(int msg_type); #endif gboolean _thumb_daemon_start_jobs(gpointer data) { thumb_dbg(""); /* Initialize ecore-evas to use evas library */ ecore_evas_init(); #ifdef _USE_MEDIA_UTIL_ _thumb_server_send_msg_to_agent(MS_MSG_THUMB_SERVER_READY); #endif return FALSE; } void _thumb_daemon_finish_jobs() { sqlite3 *sqlite_db_handle = _media_thumb_db_get_handle(); if (sqlite_db_handle != NULL) { _media_thumb_db_disconnect(); thumb_dbg("sqlite3 handle is alive. So disconnect to sqlite3"); } /* Shutdown ecore-evas */ ecore_evas_shutdown(); return; } int _thumb_daemon_process_job(thumbMsg *req_msg, thumbMsg *res_msg) { int err = -1; err = _media_thumb_process(req_msg, res_msg); if (err < 0) { if (req_msg->msg_type == THUMB_REQUEST_SAVE_FILE) { thumb_err("_media_thumb_process is failed: %d", err); res_msg->status = THUMB_FAIL; } else { thumb_warn("_media_thumb_process is failed: %d, So use default thumb", err); res_msg->status = THUMB_SUCCESS; } } else { res_msg->status = THUMB_SUCCESS; } return err; } int _thumb_daemon_all_extract() { int err = -1; int count = 0; char query_string[MAX_PATH_SIZE + 1] = { 0, }; char path[MAX_PATH_SIZE + 1] = { 0, }; sqlite3 *sqlite_db_handle = NULL; sqlite3_stmt *sqlite_stmt = NULL; err = _media_thumb_db_connect(); if (err < 0) { thumb_err("_media_thumb_db_connect failed: %d", err); return MEDIA_THUMB_ERROR_DB; } sqlite_db_handle = _media_thumb_db_get_handle(); if (sqlite_db_handle == NULL) { thumb_err("sqlite handle is NULL"); return MEDIA_THUMB_ERROR_DB; } snprintf(query_string, sizeof(query_string), SELECT_PATH_FROM_UNEXTRACTED_THUMB_MEDIA); thumb_dbg("Query: %s", query_string); err = sqlite3_prepare_v2(sqlite_db_handle, query_string, strlen(query_string), &sqlite_stmt, NULL); if (SQLITE_OK != err) { thumb_err("prepare error [%s]\n", sqlite3_errmsg(sqlite_db_handle)); _media_thumb_db_disconnect(); return MEDIA_THUMB_ERROR_DB; } while(1) { err = sqlite3_step(sqlite_stmt); if (err != SQLITE_ROW) { thumb_dbg("end of row [%s]\n", sqlite3_errmsg(sqlite_db_handle)); break; } strncpy(path, (const char *)sqlite3_column_text(sqlite_stmt, 0), MAX_PATH_SIZE + 1); count = sqlite3_column_int(sqlite_stmt, 1); thumb_dbg("Path : %s", path); if (g_idx == 0) { arr_path = (char**)malloc(sizeof(char*)); } else { arr_path = (char**)realloc(arr_path, (g_idx + 1) * sizeof(char*)); } arr_path[g_idx++] = strdup(path); } sqlite3_finalize(sqlite_stmt); _media_thumb_db_disconnect(); return MEDIA_THUMB_ERROR_NONE; } int _thumb_daemon_process_queue_jobs(gpointer data) { int err = -1; char *path = NULL; if (g_cur_idx < g_idx) { thumb_dbg("There are %d jobs in the queue", g_idx - g_cur_idx); thumb_dbg("Current idx : [%d]", g_cur_idx); path = arr_path[g_cur_idx++]; thumbMsg recv_msg, res_msg; memset(&recv_msg, 0x00, sizeof(thumbMsg)); memset(&res_msg, 0x00, sizeof(thumbMsg)); recv_msg.msg_type = THUMB_REQUEST_DB_INSERT; recv_msg.thumb_type = MEDIA_THUMB_LARGE; strncpy(recv_msg.org_path, path, sizeof(recv_msg.org_path)); recv_msg.org_path[sizeof(recv_msg.org_path) - 1] = '\0'; _thumb_daemon_process_job(&recv_msg, &res_msg); if (res_msg.status == THUMB_SUCCESS) { err = _media_thumb_db_connect(); if (err < 0) { thumb_err("_media_thumb_mb_svc_connect failed: %d", err); return TRUE; } /* Need to update DB once generating thumb is done */ err = _media_thumb_update_db(recv_msg.org_path, res_msg.dst_path, res_msg.origin_width, res_msg.origin_height); if (err < 0) { thumb_err("_media_thumb_update_db failed : %d", err); } _media_thumb_db_disconnect(); } SAFE_FREE(path); } else { g_cur_idx = 0; g_idx = 0; thumb_warn("Deleting array"); SAFE_FREE(arr_path); //_media_thumb_db_disconnect(); _thumb_server_send_msg_to_agent(MS_MSG_THUMB_EXTRACT_ALL_DONE); // MS_MSG_THUMB_EXTRACT_ALL_DONE return FALSE; } return TRUE; } gboolean _thumb_server_read_socket(GIOChannel *src, GIOCondition condition, gpointer data) { struct sockaddr_in client_addr; unsigned int client_addr_len; #ifndef _USE_MEDIA_UTIL_ int client_sock; #endif thumbMsg recv_msg; thumbMsg res_msg; int sock = -1; int header_size = 0; memset((void *)&recv_msg, 0, sizeof(recv_msg)); memset((void *)&res_msg, 0, sizeof(res_msg)); sock = g_io_channel_unix_get_fd(src); if (sock < 0) { thumb_err("sock fd is invalid!"); return TRUE; } header_size = sizeof(thumbMsg) - MAX_PATH_SIZE*2; #ifndef _USE_MEDIA_UTIL_ if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) { thumb_err("accept failed : %s", strerror(errno)); return TRUE; } thumb_dbg("Client[%d] is accepted", client_sock); if (_media_thumb_recv_msg(client_sock, header_size, &recv_msg) < 0) { thumb_err("_media_thumb_recv_msg failed "); close(client_sock); return TRUE; } #else if (_media_thumb_recv_udp_msg(sock, header_size, &recv_msg, &client_addr, &client_addr_len) < 0) { thumb_err("_media_thumb_recv_udp_msg failed"); return FALSE; } #endif thumb_dbg("Received [%d] %s(%d) from PID(%d) \n", recv_msg.msg_type, recv_msg.org_path, strlen(recv_msg.org_path), recv_msg.pid); if (recv_msg.msg_type == THUMB_REQUEST_ALL_MEDIA) { thumb_dbg("All thumbnails are being extracted now"); _thumb_daemon_all_extract(); g_idle_add(_thumb_daemon_process_queue_jobs, NULL); } else if(recv_msg.msg_type == THUMB_REQUEST_KILL_SERVER) { thumb_dbg("received KILL msg from thumbnail agent."); } else { long start = thumb_get_debug_time(); _thumb_daemon_process_job(&recv_msg, &res_msg); long end = thumb_get_debug_time(); thumb_dbg("Time : %f (%s)", ((double)(end - start) / (double)CLOCKS_PER_SEC), recv_msg.org_path); } res_msg.msg_type = recv_msg.msg_type; strncpy(res_msg.org_path, recv_msg.org_path, recv_msg.origin_path_size); res_msg.origin_path_size = recv_msg.origin_path_size; res_msg.dest_path_size = strlen(res_msg.dst_path) + 1; int buf_size = 0; unsigned char *buf = NULL; _media_thumb_set_buffer(&res_msg, &buf, &buf_size); //thumb_dbg("buffer size : %d", buf_size); #ifndef _USE_MEDIA_UTIL_ if (send(client_sock, buf, buf_size, 0) != buf_size) { thumb_err("sendto failed : %s", strerror(errno)); } else { thumb_dbg("Sent %s(%d) \n", res_msg.dst_path, strlen(res_msg.dst_path)); } close(client_sock); #else if (sendto(sock, buf, buf_size, 0, (struct sockaddr *)&client_addr, sizeof(client_addr)) != buf_size) { thumb_err("sendto failed: %s\n", strerror(errno)); SAFE_FREE(buf); return FALSE; } #endif thumb_dbg("Sent %s(%d)", res_msg.dst_path, strlen(res_msg.dst_path)); SAFE_FREE(buf); if(recv_msg.msg_type == THUMB_REQUEST_KILL_SERVER) { thumb_dbg("Shutting down..."); g_main_loop_quit(g_thumb_server_mainloop); } return TRUE; } #ifdef _USE_MEDIA_UTIL_ gboolean _thumb_server_send_msg_to_agent(int msg_type) { int sock; const char *serv_ip = "127.0.0.1"; struct sockaddr_in serv_addr; ms_thumb_server_msg send_msg; #if 0 /* Creaete a UDP socket */ if (_media_thumb_create_udp_socket(&sock) < 0) { thumb_err("_media_thumb_create_udp_socket failed"); return FALSE; } #endif if (ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sock) < 0) { thumb_err("ms_ipc_create_server_socket failed"); return FALSE; } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(serv_ip); serv_addr.sin_port = htons(MS_THUMB_COMM_PORT); send_msg.msg_type = msg_type; if (sendto(sock, &send_msg, sizeof(ms_thumb_server_msg), 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != sizeof(ms_thumb_server_msg)) { thumb_err("sendto failed: %s\n", strerror(errno)); return FALSE; } thumb_dbg("Sending msg to thumbnail agent[%d] is successful", send_msg.msg_type); return TRUE; } #endif gboolean _thumb_server_prepare_socket(int *sock_fd) { int sock; unsigned short serv_port; thumbMsg recv_msg; thumbMsg res_msg; memset((void *)&recv_msg, 0, sizeof(recv_msg)); memset((void *)&res_msg, 0, sizeof(res_msg)); #ifdef _USE_MEDIA_UTIL_ serv_port = MS_THUMB_DAEMON_PORT; if (ms_ipc_create_server_socket(MS_PROTOCOL_UDP, serv_port, &sock) < 0) { thumb_err("ms_ipc_create_server_socket failed"); return FALSE; } #if 0 /* Creaete a UDP socket */ if (_media_thumb_create_udp_socket(&sock) < 0) { thumb_err("_media_thumb_create_udp_socket failed"); return FALSE; } #endif #else char thumb_path[MAX_PATH_SIZE + 1]; struct sockaddr_in serv_addr; serv_port = THUMB_DAEMON_PORT; /* Creaete a TCP socket */ if (_media_thumb_create_socket(SERVER_SOCKET, &sock) < 0) { thumb_err("_media_thumb_create_socket failed"); return FALSE; } memset(thumb_path, 0, sizeof(thumb_path)); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(serv_port); /* Bind to the local address */ if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { thumb_err("bind failed : %s", strerror(errno)); return FALSE; } thumb_dbg("bind success"); /* Listening */ if (listen(sock, SOMAXCONN) < 0) { thumb_err("listen failed : %s", strerror(errno)); } thumb_dbg("Listening..."); #endif *sock_fd = sock; return TRUE; }