Fix float->int(short) clipping issue when playing ogg content
[platform/core/multimedia/libmm-sound.git] / focus_server / mm_sound_focus_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 #include <sys/types.h>
29 #include <sys/stat.h>
30
31 #include <mm_debug.h>
32
33 #include <fcntl.h>
34 #include <semaphore.h>
35
36 #ifdef USE_LWIPC
37 #include <lwipc.h>
38 #endif
39
40 #include "../include/mm_sound_common.h"
41 #include "include/mm_sound_mgr_focus.h"
42 #include "include/mm_sound_mgr_focus_dbus.h"
43 #include "include/mm_sound_mgr_focus_socket.h"
44
45 #define USE_SYSTEM_SERVER_PROCESS_MONITORING
46
47 typedef struct {
48         int startserver;
49         int printlist;
50         int testmode;
51 } server_arg;
52
53 static int _get_option(int argc, char **argv, server_arg *arg);
54 static int _usage(int argc, char **argv);
55
56 GMainLoop *g_mainloop;
57
58 static void _mainloop_run()
59 {
60         g_mainloop = g_main_loop_new(NULL, TRUE);
61         if (g_mainloop == NULL)
62                 debug_error("g_main_loop_new() failed");
63
64         g_main_loop_run(g_mainloop);
65 }
66
67 static sem_t * _sem_create_n_wait()
68 {
69         sem_t *sem = NULL;
70
71         if ((sem = sem_open("booting-sound", O_CREAT, 0660, 0)) == SEM_FAILED) {
72                 debug_error("error creating sem : %d", errno);
73                 return NULL;
74         }
75
76         debug_msg("returning sem [%p]", sem);
77         return sem;
78 }
79
80 static int _get_option(int argc, char **argv, server_arg *arg)
81 {
82         int c;
83         static struct option long_options[] = {
84                 {"start", 0, 0, 'S'},
85                 {"help", 0, 0, 'H'},
86                 {"testmode", 0, 0, 'T'},
87                 {0, 0, 0, 0}
88         };
89         memset(arg, 0, sizeof(server_arg));
90
91         arg->testmode = 0;
92
93         while (1) {
94                 int opt_idx = 0;
95
96                 c = getopt_long (argc, argv, "SFLHRUP:Tiurd", long_options, &opt_idx);
97                 if (c == -1)
98                         break;
99                 switch (c) {
100                 case 'S': /* Start daemon */
101                         arg->startserver = 1;
102                         break;
103                 case 'T': /* Test mode */
104                         arg->testmode = 1;
105                         break;
106                 case 'H': /* help msg */
107                 default:
108                         return _usage(argc, argv);
109                 }
110         }
111         if (argc == 1)
112                 return _usage(argc, argv);
113         return 0;
114 }
115
116 static int _usage(int argc, char **argv)
117 {
118         fprintf(stderr, "Usage: %s [Options]\n", argv[0]);
119         fprintf(stderr, "\t%-20s: start focus server.\n", "--start,-S");
120         fprintf(stderr, "\t%-20s: help message.\n", "--help,-H");
121
122         return 1;
123 }
124
125 static void _generate_ready_file(const char *path)
126 {
127         int fd = -1;
128
129         if (path == NULL) {
130                 debug_error("path is NULL");
131                 return;
132         }
133
134         if ((fd = creat(path, 0644)) != -1) {
135                 debug_warning("ready file(%s) file was created", path);
136                 close(fd);
137         } else {
138                 debug_error("cannot create ready file(%s), errno(%d)", path, errno);
139         }
140 }
141
142 int g_socket_fd = -1;
143 struct sigaction _int_old_action;
144 struct sigaction _abrt_old_action;
145 struct sigaction _segv_old_action;
146 struct sigaction _term_old_action;
147 struct sigaction _sys_old_action;
148 struct sigaction _xcpu_old_action;
149 static void _signal_handler(int signo)
150 {
151         debug_warning("ENTER, sig.num(%d)", signo);
152
153         MMSoundMgrFocusDbusFini();
154         MMSoundMgrFocusFini();
155         MMSoundMgrFocusSocketFini(g_socket_fd);
156
157         /* signal block -------------- */
158         sigset_t old_mask, all_mask;
159         sigfillset(&all_mask);
160         sigprocmask(SIG_BLOCK, &all_mask, &old_mask);
161
162         sigprocmask(SIG_SETMASK, &old_mask, NULL);
163         /* signal unblock ------------ */
164
165         switch (signo) {
166         case SIGINT:
167                 sigaction(SIGINT, &_int_old_action, NULL);
168                 raise(signo);
169                 break;
170         case SIGABRT:
171                 sigaction(SIGABRT, &_abrt_old_action, NULL);
172                 raise(signo);
173                 break;
174         case SIGSEGV:
175                 sigaction(SIGSEGV, &_segv_old_action, NULL);
176                 raise(signo);
177                 break;
178         case SIGTERM:
179                 sigaction(SIGTERM, &_term_old_action, NULL);
180                 raise(signo);
181                 break;
182         case SIGSYS:
183                 sigaction(SIGSYS, &_sys_old_action, NULL);
184                 raise(signo);
185                 break;
186         case SIGXCPU:
187                 sigaction(SIGXCPU, &_xcpu_old_action, NULL);
188                 raise(signo);
189                 break;
190         default:
191                 break;
192         }
193         debug_warning("LEAVE");
194 }
195
196 static void _signal_initialize(void)
197 {
198         struct sigaction _action;
199         _action.sa_handler = _signal_handler;
200         _action.sa_flags = SA_NOCLDSTOP;
201
202         sigemptyset(&_action.sa_mask);
203
204         sigaction(SIGINT, &_action, &_int_old_action);
205         sigaction(SIGABRT, &_action, &_abrt_old_action);
206         sigaction(SIGSEGV, &_action, &_segv_old_action);
207         sigaction(SIGTERM, &_action, &_term_old_action);
208         sigaction(SIGSYS, &_action, &_sys_old_action);
209         sigaction(SIGXCPU, &_action, &_xcpu_old_action);
210
211 }
212
213 static void _signal_finalize(void)
214 {
215         sigaction(SIGINT, &_int_old_action, NULL);
216         sigaction(SIGABRT, &_abrt_old_action, NULL);
217         sigaction(SIGSEGV, &_segv_old_action, NULL);
218         sigaction(SIGTERM, &_term_old_action, NULL);
219         sigaction(SIGSYS, &_sys_old_action, NULL);
220         sigaction(SIGXCPU, &_xcpu_old_action, NULL);
221 }
222
223 int main(int argc, char **argv)
224 {
225         sem_t *sem = NULL;
226         server_arg serveropt;
227 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
228         int pid;
229 #endif
230         int socket_fd = -1;
231
232         if (_get_option(argc, argv, &serveropt))
233                 return 1;
234
235         debug_warning("focus_server [%d] init ", getpid());
236
237         _signal_initialize();
238
239         if (serveropt.startserver)
240                 sem = _sem_create_n_wait();
241
242         /* Daemon process create */
243         if (!serveropt.testmode && serveropt.startserver) {
244 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
245                 daemon(0, 0); //chdir to ("/"), and close stdio
246 #endif
247         }
248
249         /* focus Server Starts!!!*/
250         debug_warning("focus_server [%d] start ", getpid());
251
252         signal(SIGPIPE, SIG_IGN); //ignore SIGPIPE
253
254 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
255         while (1) {
256                 if ((pid = fork()) < 0) {
257                         fprintf(stderr, "Sub Fork Error\n");
258                         return 2;
259                 } else if (pid == 0) {
260                         break;
261                 } else if (pid > 0) {
262                         wait(&ret);
263                         fprintf(stderr, "Killed by signal [%05X]\n", ret);
264                         fprintf(stderr, "Daemon is run againg\n");
265                 }
266         }
267 #endif
268         if (serveropt.startserver) {
269                 /* Change the file mode mask */
270                 umask(0);
271
272                 if (MMSoundMgrFocusSocketInit(&socket_fd)) {
273                         debug_error("focus_server [%d] terminating, due to the error of socket init.", getpid());
274                         return 0;
275                 }
276                 if (MMSoundMgrFocusSocketReadyToWork(socket_fd)) {
277                         debug_error("focus_server [%d] terminating, due to the error of thread init.", getpid());
278                         return 0;
279                 }
280                 MMSoundMgrFocusDbusInit();
281                 MMSoundMgrFocusInit();
282                 g_socket_fd = socket_fd;
283         }
284
285         debug_warning("focus_server [%d] initialization complete...now, start running!!", getpid());
286
287         if (serveropt.startserver) {
288                 unlink(PA_READY); // remove pa_ready file after focus-server init.
289
290                 if (sem) {
291                         if (sem_post(sem) == -1)
292                                 debug_error("error sem post : %d", errno);
293                         else
294                                 debug_msg("Ready to play booting sound!!!!");
295                 }
296
297                 /* FIXME : This code is moved from sound_server temporally for TV migration
298                                         As other modules which has dependancy on this file is cleared,
299                                         this code will be removed */
300                 /* broadcast if we're ready */
301 #ifdef USE_LWIPC
302                 if (LwipcEventDone(SOUND_SERVER_READY) < 0)
303                         debug_error("cannot create SOUND_SERVER_READY(sound_server_ready)");
304                 else
305                         debug_warning("SOUND_SERVER_READY(%s) event was created", SOUND_SERVER_READY);
306 #else
307                 _generate_ready_file(SOUND_SERVER_READY);
308 #endif
309                 _generate_ready_file(FOCUS_SERVER_READY);
310
311                 _mainloop_run();
312         }
313
314         debug_warning("focus_server [%d] terminating ", getpid());
315
316         if (serveropt.startserver) {
317                 MMSoundMgrFocusDbusFini();
318                 MMSoundMgrFocusFini();
319                 MMSoundMgrFocusSocketFini(socket_fd);
320         }
321
322         _signal_finalize();
323
324         debug_warning("focus_server [%d] exit ----------------- END ", getpid());
325
326         return 0;
327 }