4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Yong Yeon Kim <yy9875.kim@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * This file defines api utilities of contents manager engines.
25 * @file media-server-main.c
26 * @author Yong Yeon Kim(yy9875.kim@samsung.com)
32 #include <sys/types.h>
39 #include "media-util.h"
40 #include "media-server-dbg.h"
41 #include "media-server-utils.h"
42 #include "media-server-external-storage.h"
43 #include "media-server-db-svc.h"
44 #include "media-server-inotify.h"
45 #include "media-server-socket.h"
46 #include "media-server-db.h"
47 #include "media-server-drm.h"
48 #include "media-server-dbus.h"
49 #include "media-server-thumb.h"
50 #include "media-server-scanner.h"
52 #define APP_NAME "media-server"
54 extern GMutex *scanner_mutex;
55 extern GMutex *db_mutex;
59 extern GAsyncQueue* ret_queue;
60 extern GMutex *list_mutex;
61 extern GMutex *queue_mutex;
62 extern GArray *reg_list;
63 extern bool power_off; /*If this is TRUE, poweroff notification received*/
65 GMainLoop *mainloop = NULL;
71 struct dirent *result = NULL;
74 pid_t current_pid = 0;
76 current_pid = getpid();
78 pdir = opendir("/proc");
80 MS_DBG_ERR("err: NO_DIR\n");
84 while (!readdir_r(pdir, &pinfo, &result)) {
88 if (pinfo.d_type != 4 || pinfo.d_name[0] == '.'
89 || pinfo.d_name[0] > 57)
96 ms_strcopy(path, sizeof(path), "/proc/%s/status", pinfo.d_name);
97 fp = fopen(path, "rt");
99 if (fgets(buff, 128, fp) == NULL)
100 MS_DBG_ERR("fgets failed");
103 if (strstr(buff, APP_NAME)) {
104 find_pid = atoi(pinfo.d_name);
105 if (find_pid == current_pid)
113 MS_DBG_ERR("Can't read file [%s]", path);
127 static void _power_off_cb(void* data)
129 MS_DBG("++++++++++++++++++++++++++++++++++++++");
131 MS_DBG("++++++++++++++++++++++++++++++++++++++");
135 /*Quit Thumbnail Thread*/
136 GMainLoop *thumb_mainloop = ms_get_thumb_thread_mainloop();
137 if (thumb_mainloop && g_main_is_running(thumb_mainloop)) {
138 g_main_loop_quit(thumb_mainloop);
142 GMainLoop *db_mainloop = ms_db_get_mainloop();
143 if(db_mainloop && g_main_loop_is_running(db_mainloop)) {
144 g_main_loop_quit(db_mainloop);
148 if (mainloop && g_main_loop_is_running(mainloop)) {
149 g_main_loop_quit(mainloop);
155 static bool _db_clear(void** handle)
159 bool need_db_create = false;
161 /*update just valid type*/
162 err = ms_invalidate_all_items(handle, MS_STORAGE_EXTERNAL);
163 if (err != MS_MEDIA_ERR_NONE)
164 MS_DBG_ERR("ms_change_valid_type fail");
166 ms_config_get_int(MS_SCAN_STATUS_INTERNAL, &db_status);
167 MS_DBG("finish_phone_init_data db = %d", db_status);
169 if (db_status == P_VCONF_SCAN_DOING) {
170 need_db_create = true;
172 err = ms_invalidate_all_items(handle, MS_STORAGE_INTERNAL);
173 if (err != MS_MEDIA_ERR_NONE)
174 MS_DBG_ERR("ms_change_valid_type fail");
177 // ms_set_db_status(MS_DB_UPDATED);
179 return need_db_create;
182 void _ms_signal_handler(int n)
184 MS_DBG("Receive SIGNAL");
185 int stat, pid, thumb_pid;
188 thumb_pid = ms_thumb_get_server_pid();
189 MS_DBG("Thumbnail server pid : %d", thumb_pid);
191 scanner_pid = ms_get_scanner_pid();
193 pid = waitpid(-1, &stat, WNOHANG);
194 /* check pid of child process of thumbnail thread */
195 MS_DBG("[PID %d] signal ID %d", pid, n);
197 if (pid == thumb_pid) {
198 MS_DBG("Thumbnail server is dead");
199 ms_thumb_reset_server_status();
200 } else if (pid == scanner_pid) {
201 MS_DBG("Scanner is dead");
202 ms_reset_scanner_status();
203 } else if (pid == -1) {
204 MS_DBG("%s", strerror(errno));
207 if (WIFEXITED(stat)) {
208 MS_DBG("normal termination , exit status : %d", WEXITSTATUS(stat));
209 } else if (WIFSIGNALED(stat)) {
210 MS_DBG("abnormal termination , signal number : %d", WTERMSIG(stat));
211 } else if (WIFSTOPPED(stat)) {
212 MS_DBG("child process is stoped, signal number : %d", WSTOPSIG(stat));
218 static void _ms_new_global_variable(void)
221 /*Init for register file*/
222 if (!list_mutex) list_mutex = g_mutex_new();
223 if (!queue_mutex) queue_mutex = g_mutex_new();
224 if (!reg_list) reg_list = g_array_new(TRUE, TRUE, sizeof(char*));
225 /*These are a communicator for thread*/
226 if (!ret_queue) ret_queue = g_async_queue_new();
228 /*Init mutex variable*/
229 if (!db_mutex) db_mutex = g_mutex_new();
231 /*media scanner stop/start mutex*/
232 if (!scanner_mutex) scanner_mutex = g_mutex_new();
235 static void _ms_free_global_variable(void)
238 if (list_mutex) g_mutex_free(list_mutex);
239 if (queue_mutex)g_mutex_free(queue_mutex);
240 if (reg_list) g_array_free(reg_list, true);
241 if (ret_queue) g_async_queue_unref(ret_queue);
243 /*Clear mutex variable*/
244 if (db_mutex) g_mutex_free (db_mutex);
246 if (scanner_mutex) g_mutex_free(scanner_mutex);
249 int main(int argc, char **argv)
252 GThread *inoti_thread = NULL;
254 GThread *db_thread = NULL;
255 GThread *thumb_thread = NULL;
256 GSource *source = NULL;
257 GIOChannel *channel = NULL;
258 GMainContext *context = NULL;
259 int sockfd = MS_SOCK_NOT_ALLOCATE;
262 bool check_result = false;
264 void **handle = NULL;
265 struct sigaction sigset;
267 check_result = check_process();
268 if (check_result == false)
271 if (!g_thread_supported()) {
276 mainloop = g_main_loop_new(NULL, FALSE);
281 /*heynoti for power off*/
282 if ((heynoti_id = heynoti_init()) <0) {
283 MS_DBG("heynoti_init failed");
285 err = heynoti_subscribe(heynoti_id, POWEROFF_NOTI_NAME, _power_off_cb, NULL);
287 MS_DBG("heynoti_subscribe failed");
289 err = heynoti_attach_handler(heynoti_id);
291 MS_DBG("heynoti_attach_handler failed");
294 /*load functions from plusin(s)*/
295 err = ms_load_functions();
296 if (err != MS_MEDIA_ERR_NONE) {
297 MS_DBG_ERR("function load failed");
301 _ms_new_global_variable();
303 /*connect to media db, if conneting is failed, db updating is stopped*/
304 ms_connect_db(&handle);
308 ms_inoti_add_watch_all_directory(MS_STORAGE_INTERNAL);
311 /* Create and bind new UDP socket */
312 if (ms_ipc_create_server_socket(MS_PROTOCOL_UDP, MS_SCANNER_PORT, &sockfd)
313 != MS_MEDIA_ERR_NONE) {
314 MS_DBG_ERR("Failed to create socket");
316 context = g_main_loop_get_context(mainloop);
318 /* Create new channel to watch udp socket */
319 channel = g_io_channel_unix_new(sockfd);
320 source = g_io_create_watch(channel, G_IO_IN);
322 /* Set callback to be called when socket is readable */
323 g_source_set_callback(source, (GSourceFunc)ms_read_socket, handle, NULL);
324 g_source_attach(source, context);
325 g_source_unref(source);
328 /*create each threads*/
330 inoti_thread = g_thread_new("inotify_thread", (GThreadFunc)ms_inoti_thread, NULL);
332 db_thread = g_thread_new("db_thread", (GThreadFunc)ms_db_thread, NULL);
333 thumb_thread = g_thread_new("thumb_agent_thread", (GThreadFunc)ms_thumb_agent_start_thread, NULL);
335 /*set vconf callback function*/
336 err = vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS, (vconf_callback_fn) ms_mmc_vconf_cb, NULL);
338 MS_DBG_ERR("add call back function for event %s fails", VCONFKEY_SYSMAN_MMC_STATUS);
340 MS_DBG("*********************************************************");
341 MS_DBG("*** Begin to check tables of file manager in database ***");
342 MS_DBG("*********************************************************");
344 /* Add signal handler */
345 sigset.sa_handler = _ms_signal_handler;
346 if (sigaction(SIGCHLD, &sigset, NULL) < 0) {
347 MS_DBG_ERR("sigaction failed [%s]", strerror(errno));
349 MS_DBG("handler ok");
352 /*clear previous data of sdcard on media database and check db status for updating*/
353 while(!ms_db_get_thread_status()) {
354 MS_DBG("wait db thread");
358 need_db_create = _db_clear(handle);
359 if (need_db_create) {
361 ms_send_storage_scan_request(MS_STORAGE_INTERNAL, MS_SCAN_ALL);
363 ms_send_storage_scan_request(MS_STORAGE_INTERNAL, MS_SCAN_PART);
366 if (ms_is_mmc_inserted()) {
367 mmc_state = VCONFKEY_SYSMAN_MMC_MOUNTED;
369 if (!ms_drm_insert_ext_memory())
370 MS_DBG_ERR("ms_drm_insert_ext_memory failed");
372 ms_make_default_path_mmc();
374 ms_inoti_add_watch_all_directory(MS_STORAGE_EXTERNAL);
376 ms_present_mmc_insert();
378 ms_send_storage_scan_request(MS_STORAGE_EXTERNAL, ms_get_mmc_state());
384 MS_DBG("*****************************************");
385 MS_DBG("*** Server of File Manager is running ***");
386 MS_DBG("*****************************************");
388 g_main_loop_run(mainloop);
390 g_thread_join(inoti_thread);
392 g_thread_join(db_thread);
393 g_thread_join(thumb_thread);
395 /*close an IO channel*/
396 g_io_channel_shutdown(channel, FALSE, NULL);
397 g_io_channel_unref(channel);
399 heynoti_unsubscribe(heynoti_id, POWEROFF_NOTI_NAME, _power_off_cb);
400 heynoti_close(heynoti_id);
403 **remove call back functions
405 vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
406 (vconf_callback_fn) ms_mmc_vconf_cb);
408 _ms_free_global_variable();
410 /*disconnect form media db*/
411 if (handle) ms_disconnect_db(&handle);
417 ms_unload_functions();