24afffcfe92daeb425316293227e5cb57bb9042d
[platform/core/multimedia/libmm-sound.git] / server / mm_sound_server.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungbae Shin <seungbae.shin@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 <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/wait.h>
26 #include <unistd.h>
27 #include <getopt.h>
28
29 #include <mm_error.h>
30 #include <mm_debug.h>
31
32 #include <glib.h>
33
34 #include "../include/mm_sound_common.h"
35 #include "../include/mm_sound_utils.h"
36 #include "include/mm_sound_thread_pool.h"
37 #include "include/mm_sound_mgr_codec.h"
38 #include "include/mm_sound_mgr_ipc_dbus.h"
39
40 #include "../config.h" /* for PLUGIN_DIR */
41
42 #define PLUGIN_ENV "MM_SOUND_PLUGIN_PATH"
43 #define PLUGIN_MAX 30
44 #define MAX_PLUGIN_DIR_PATH_LEN 256
45
46 #define USE_SYSTEM_SERVER_PROCESS_MONITORING
47
48 typedef struct {
49         char plugdir[MAX_PLUGIN_DIR_PATH_LEN];
50         int startserver;
51         int printlist;
52         int testmode;
53 } server_arg;
54
55 static int _get_option(int argc, char **argv, server_arg *arg);
56 static int _usage(int argc, char **argv);
57
58 static struct sigaction sigint_action;  /* Backup pointer of SIGINT handler */
59 static struct sigaction sigabrt_action; /* Backup pointer of SIGABRT signal handler */
60 static struct sigaction sigsegv_action; /* Backup pointer of SIGSEGV fault signal handler */
61 static struct sigaction sigterm_action; /* Backup pointer of SIGTERM signal handler */
62 static struct sigaction sigsys_action;  /* Backup pointer of SIGSYS signal handler */
63 static void _exit_handler(int sig);
64
65 static GMainLoop *g_mainloop;
66
67 static gboolean _shutdown_cb(gpointer user_data)
68 {
69         debug_warning("TIMER : quit mainloop now!");
70         g_main_loop_quit(g_mainloop);
71
72         return FALSE;
73 }
74
75 static void _mainloop_run()
76 {
77         g_mainloop = g_main_loop_new(NULL, TRUE);
78         if (g_mainloop == NULL) {
79                 debug_error("g_main_loop_new() failed");
80                 return;
81         }
82
83         g_main_loop_run(g_mainloop);
84 }
85
86 static int _get_option(int argc, char **argv, server_arg *arg)
87 {
88         int c;
89         static struct option long_options[] = {
90                 {"start", 0, 0, 'S'},
91                 {"list", 0, 0, 'L'},
92                 {"help", 0, 0, 'H'},
93                 {"plugdir", 1, 0, 'P'},
94                 {"testmode", 0, 0, 'T'},
95                 {0, 0, 0, 0}
96         };
97         memset(arg, 0, sizeof(server_arg));
98
99         MMSOUND_STRNCPY(arg->plugdir, PLUGIN_DIR, MAX_PLUGIN_DIR_PATH_LEN);
100
101         arg->testmode = 0;
102
103         while (1) {
104                 int opt_idx = 0;
105
106                 c = getopt_long(argc, argv, "SFLHRUP:Tiurd", long_options, &opt_idx);
107                 if (c == -1)
108                         break;
109                 switch (c) {
110                 case 'S': /* Start daemon */
111                         arg->startserver = 1;
112                         break;
113                 case 'L': /* list of plugins */
114                         arg->printlist = 1;
115                         break;
116                 case 'P': /* Custom plugindir */
117                         MMSOUND_STRNCPY(arg->plugdir, optarg, MAX_PLUGIN_DIR_PATH_LEN);
118                         break;
119                 case 'T': /* Test mode */
120                         arg->testmode = 1;
121                         break;
122                 case 'H': /* help msg */
123                 default:
124                         return _usage(argc, argv);
125                 }
126         }
127         if (argc == 1)
128                 return _usage(argc, argv);
129         return 0;
130 }
131
132 //__attribute__ ((destructor))
133 static void _exit_handler(int sig)
134 {
135 #ifdef USE_GCOV
136         mm_sound_gcov_flush();
137 #endif
138
139         switch (sig) {
140         case SIGINT:
141                 sigaction(SIGINT, &sigint_action, NULL);
142                 debug_error("signal(SIGINT) error");
143                 break;
144         case SIGABRT:
145                 sigaction(SIGABRT, &sigabrt_action, NULL);
146                 debug_error("signal(SIGABRT) error");
147                 break;
148         case SIGSEGV:
149                 sigaction(SIGSEGV, &sigsegv_action, NULL);
150                 debug_error("signal(SIGSEGV) error");
151                 break;
152         case SIGTERM:
153                 sigaction(SIGTERM, &sigterm_action, NULL);
154                 debug_error("signal(SIGTERM) error");
155                 break;
156         case SIGSYS:
157                 sigaction(SIGSYS, &sigsys_action, NULL);
158                 debug_error("signal(SIGSYS) error");
159                 break;
160         default:
161                 break;
162         }
163         raise(sig);
164 }
165
166 static int _usage(int argc, char **argv)
167 {
168         fprintf(stderr, "Usage: %s [Options]\n", argv[0]);
169         fprintf(stderr, "\t%-20s: start sound server.\n", "--start,-S");
170         fprintf(stderr, "\t%-20s: help message.\n", "--help,-H");
171
172         return 1;
173 }
174
175 int main(int argc, char **argv)
176 {
177         server_arg serveropt;
178         struct sigaction action;
179 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
180         int pid;
181 #endif
182
183         action.sa_handler = _exit_handler;
184         action.sa_flags = 0;
185         sigemptyset(&action.sa_mask);
186
187         if (_get_option(argc, argv, &serveropt))
188                 return 1;
189
190         debug_warning("sound_server [%d] init ", getpid());
191
192         /* Daemon process create */
193         if (!serveropt.testmode && serveropt.startserver) {
194 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
195                 daemon(0, 0); //chdir to ("/"), and close stdio
196 #endif
197         }
198
199         /* Sound Server Starts!!!*/
200         debug_warning("sound_server [%d] start ", getpid());
201
202         signal(SIGPIPE, SIG_IGN); //ignore SIGPIPE
203
204 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
205         while (1) {
206                 if ((pid = fork()) < 0) {
207                         fprintf(stderr, "Sub Fork Error\n");
208                         return 2;
209                 } else if (pid == 0) {
210                         break;
211                 } else if (pid > 0) {
212                         wait(&ret);
213                         fprintf(stderr, "Killed by signal [%05X]\n", ret);
214                         fprintf(stderr, "Daemon is run againg\n");
215                 }
216         }
217 #endif
218         sigaction(SIGABRT, &action, &sigabrt_action);
219         sigaction(SIGSEGV, &action, &sigsegv_action);
220         sigaction(SIGTERM, &action, &sigterm_action);
221         sigaction(SIGSYS, &action, &sigsys_action);
222
223 #ifdef USE_GCOV
224         mm_sound_gcov_set_prefix();
225 #endif
226
227         if (serveropt.startserver || serveropt.printlist) {
228                 MMSoundMgrDbusInit();
229                 if (MMSoundThreadPoolInit()) {
230                         debug_error("failed to MMSoundThreadPoolInit()");
231                         goto exit;
232                 }
233                 MMSoundMgrCodecInit(serveropt.plugdir, _shutdown_cb);
234         }
235
236         debug_warning("sound_server [%d] initialization complete...now, start running!!", getpid());
237
238         if (serveropt.startserver) {
239                 /* Start MainLoop */
240                 _mainloop_run();
241         }
242
243 exit:
244         debug_warning("sound_server [%d] terminating ", getpid());
245
246         if (serveropt.startserver || serveropt.printlist) {
247                 MMSoundMgrCodecFini();
248                 MMSoundThreadPoolFini();
249                 MMSoundMgrDbusFini();
250         }
251
252         debug_warning("sound_server [%d] exit ----------------- END ", getpid());
253
254         return 0;
255 }