Make ASM handling external.
[profile/ivi/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 <error.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <unistd.h>
29 #include <signal.h>
30 #include <pthread.h>
31 #include <getopt.h>
32
33 #include <vconf.h>
34 #include <avsys-audio.h>
35 #include <mm_error.h>
36 #include <mm_debug.h>
37
38 #include "../include/mm_sound_common.h"
39 #include "../include/mm_sound_utils.h"
40 #include "include/mm_sound_thread_pool.h"
41 #include "include/mm_sound_mgr_run.h"
42 #include "include/mm_sound_mgr_codec.h"
43 #include "include/mm_sound_mgr_ipc.h"
44 #include "include/mm_sound_mgr_pulse.h"
45 #include "include/mm_sound_mgr_asm.h"
46 #include "include/mm_sound_mgr_session.h"
47 #include "include/mm_sound_mgr_device.h"
48 #include "include/mm_sound_mgr_headset.h"
49 #include "include/mm_sound_mgr_dock.h"
50 #include "include/mm_sound_mgr_hdmi.h"
51 #include "include/mm_sound_mgr_wfd.h"
52
53 #include <heynoti.h>
54
55 #include <glib.h>
56
57 #define PLUGIN_ENV "MM_SOUND_PLUGIN_PATH"
58 #define PLUGIN_DIR "/usr/lib/soundplugins/"
59 #define PLUGIN_MAX 30
60
61 #define HIBERNATION_SOUND_CHECK_PATH    "/tmp/hibernation/sound_ready"
62 #define USE_SYSTEM_SERVER_PROCESS_MONITORING
63
64 #define ASM_CHECK_INTERVAL      10000
65
66 #define MAX_PLUGIN_DIR_PATH_LEN 256
67
68 typedef struct {
69     char plugdir[MAX_PLUGIN_DIR_PATH_LEN];
70     int startserver;
71     int printlist;
72     int testmode;
73 } server_arg;
74
75 static int getOption(int argc, char **argv, server_arg *arg);
76 static int usgae(int argc, char **argv);
77
78 static struct sigaction sigint_action;  /* Backup pointer of SIGINT handler */
79 static struct sigaction sigabrt_action; /* Backup pointer of SIGABRT signal handler */
80 static struct sigaction sigsegv_action; /* Backup pointer of SIGSEGV fault signal handler */
81 static struct sigaction sigterm_action; /* Backup pointer of SIGTERM signal handler */
82 static struct sigaction sigsys_action;  /* Backup pointer of SIGSYS signal handler */
83 static void _exit_handler(int sig);
84
85 GMainLoop *g_mainloop;
86
87 void* pulse_handle;
88
89 gpointer event_loop_thread(gpointer data)
90 {
91         g_mainloop = g_main_loop_new(NULL, TRUE);
92         if(g_mainloop == NULL) {
93                 debug_error("g_main_loop_new() failed\n");
94         }
95         g_main_loop_run(g_mainloop);
96         return NULL;
97 }
98
99 #ifdef USE_HIBERNATION
100 static void __hibernation_leave_cb()
101 {
102         int volumes[VOLUME_TYPE_MAX] = {0, };
103
104         MMSoundMgrPulseHandleRegisterMonoAudio(pulse_handle);
105         MMSoundMgrPulseHandleRegisterBluetoothStatus (pulse_handle);
106
107         _mm_sound_volume_get_values_on_bootup(volumes);
108         if (avsys_audio_hibernation_reset(volumes)) {
109                 debug_error("Audio reset failed\n");
110         } else {
111                 debug_msg("Audio reset success\n");
112         }
113 }
114 #endif
115
116 static void __wait_for_asm_ready ()
117 {
118         int retry_count = 0;
119         int asm_ready = 0;
120         while (!asm_ready) {
121                 debug_log("Checking ASM ready....[%d]\n", retry_count++);
122                 if (vconf_get_int(ASM_READY_KEY, &asm_ready)) {
123                         debug_warning("vconf_get_int for ASM_READY_KEY (%s) failed\n", ASM_READY_KEY);
124                 }
125                 usleep (ASM_CHECK_INTERVAL);
126         }
127         debug_log("ASM is now ready...clear key!!!\n");
128         vconf_unset (ASM_READY_KEY);
129 }
130
131 int main(int argc, char **argv)
132 {
133         server_arg serveropt;
134         struct sigaction action;
135 #ifdef USE_HIBERNATION
136         int heynotifd = -1;
137 #endif
138         int volumes[VOLUME_TYPE_MAX] = {0, };
139 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
140         int pid;
141         int ret;
142 #endif
143
144         action.sa_handler = _exit_handler;
145         action.sa_flags = 0;
146         sigemptyset(&action.sa_mask);
147
148         if (getOption(argc, argv, &serveropt))
149                 return 1;
150
151         /* Daemon process create */
152         if (!serveropt.testmode && serveropt.startserver) {
153 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
154                 daemon(0,0); //chdir to ("/"), and close stdio
155 #endif
156         }
157
158         signal(SIGPIPE, SIG_IGN); //ignore SIGPIPE
159
160         _mm_sound_volume_get_values_on_bootup(volumes);
161         if (avsys_audio_hibernation_reset(volumes)) {
162                 debug_error("Audio reset failed\n");
163         } else {
164                 debug_msg("Audio reset success\n");
165         }
166
167 #ifdef USE_HIBERNATION
168         heynotifd = heynoti_init();
169         if(heynoti_subscribe(heynotifd, "HIBERNATION_LEAVE", __hibernation_leave_cb, NULL)) {
170                 debug_error("heynoti_subscribe failed...\n");
171         } else {
172                 debug_msg("heynoti_subscribe() success\n");
173         }
174
175         if(heynoti_attach_handler(heynotifd)) {
176                 debug_error("heynoti_attach_handler() failed\n");
177         } else {
178                 debug_msg("heynoti_attach_handler() success\n");
179         }
180 #endif
181
182 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
183         while(1)
184         {
185                 if ((pid = fork()) < 0)
186                 {
187                         fprintf(stderr, "Sub Fork Error\n");
188                         return 2;
189                 }
190                 else if(pid == 0)
191                 {
192                         break;
193                 }
194                 else if(pid > 0)
195                 {
196                         wait(&ret);
197                         fprintf(stderr, "Killed by signal [%05X]\n", ret);      
198                         fprintf(stderr, "Daemon is run againg\n");
199                 }
200         }
201 #endif
202         sigaction(SIGABRT, &action, &sigabrt_action);
203         sigaction(SIGSEGV, &action, &sigsegv_action);
204         sigaction(SIGTERM, &action, &sigterm_action);
205         sigaction(SIGSYS, &action, &sigsys_action);
206
207         if (!g_thread_supported ())
208                 g_thread_init (NULL);
209
210         if(NULL == g_thread_create(event_loop_thread, NULL, FALSE, NULL)) {
211                 fprintf(stderr,"event loop thread create failed\n");
212                 return 3;
213         }
214
215
216         if (serveropt.startserver || serveropt.printlist) {
217                 MMSoundThreadPoolInit();
218                 MMSoundMgrRunInit(serveropt.plugdir);
219                 MMSoundMgrCodecInit(serveropt.plugdir);
220                 if (!serveropt.testmode)
221                         MMSoundMgrIpcInit();
222
223                 pulse_handle = MMSoundMgrPulseInit();
224 #if 0
225                 MMSoundMgrASMInit();
226                 /* Wait for ASM Ready */
227                 __wait_for_asm_ready();
228 #endif
229                 _mm_sound_mgr_device_init();
230                 MMSoundMgrHeadsetInit();
231                 MMSoundMgrDockInit();
232                 MMSoundMgrHdmiInit();
233                 MMSoundMgrWfdInit();
234                 MMSoundMgrSessionInit();
235         }
236
237         if (serveropt.startserver) {
238                 /* Start Run types */
239                 MMSoundMgrRunRunAll();
240
241 #ifdef USE_HIBERNATION
242                 /* set hibernation check */
243                 _mm_sound_check_hibernation (HIBERNATION_SOUND_CHECK_PATH);
244 #endif
245
246                 /* Start Ipc mgr */
247                 MMSoundMgrIpcReady();
248         }
249
250         if (serveropt.startserver || serveropt.printlist) {
251                 MMSoundMgrRunStopAll();
252                 if (!serveropt.testmode)
253                         MMSoundMgrIpcFini();
254
255                 MMSoundMgrCodecFini();
256                 MMSoundMgrRunFini();
257                 MMSoundThreadPoolFini();
258
259                 MMSoundMgrWfdFini();
260                 MMSoundMgrHdmiFini();
261                 MMSoundMgrDockFini();
262                 MMSoundMgrHeadsetFini();
263                 MMSoundMgrSessionFini();
264                 _mm_sound_mgr_device_fini();
265                 MMSoundMgrASMFini();
266                 MMSoundMgrPulseFini(pulse_handle);
267
268 #ifdef USE_HIBERNATION
269                 if(heynoti_unsubscribe(heynotifd, "HIBERNATION_LEAVE", NULL)) {
270                         debug_error("heynoti_unsubscribe failed..\n");
271                 }
272                 heynoti_close(heynotifd);
273 #endif
274         }
275         return 0;
276 }
277
278 static int getOption(int argc, char **argv, server_arg *arg)
279 {
280         int c;
281         char *plugin_env_dir = NULL;
282         static struct option long_options[] = {
283                 {"start", 0, 0, 'S'},
284                 {"list", 0, 0, 'L'},
285                 {"help", 0, 0, 'H'},
286                 {"plugdir", 1, 0, 'P'},
287                 {"testmode", 0, 0, 'T'},
288                 {0, 0, 0, 0}
289         };
290         memset(arg, 0, sizeof(server_arg));
291
292         plugin_env_dir = getenv(PLUGIN_ENV);
293         if (plugin_env_dir) {
294                 strncpy (arg->plugdir, plugin_env_dir, sizeof(arg->plugdir)-1);
295         } else {
296                 strncpy (arg->plugdir, PLUGIN_DIR, sizeof(arg->plugdir)-1);
297         }
298                 
299         arg->testmode = 0;
300
301         while (1)
302         {
303                 int opt_idx = 0;
304
305                 c = getopt_long (argc, argv, "SLHRP:T", long_options, &opt_idx);
306                 if (c == -1)
307                         break;
308                 switch (c)
309                 {
310                 case 'S': /* Start daemon */
311                         arg->startserver = 1;
312                         break;
313                 case 'L': /* list of plugins */
314                         arg->printlist = 1;
315                         break;
316                 case 'R':
317                         MMSoundMgrCodecInit(arg->plugdir);
318                         break;
319                 case 'P': /* Custom plugindir */
320                         strncpy (arg->plugdir, optarg, sizeof(arg->plugdir)-1);
321                         break;
322                 case 'T': /* Test mode */
323                         arg->testmode = 1;
324                         break;
325                 case 'H': /* help msg */
326                 default:
327                 return usgae(argc, argv);
328                 }
329         }
330         if (argc == 1)
331                 return usgae(argc, argv);
332         return 0;
333 }
334
335 //__attribute__ ((destructor))
336 static void _exit_handler(int sig)
337 {
338         int ret = MM_ERROR_NONE;
339         
340         ret = MMSoundMgrRunStopAll();
341         if (ret != MM_ERROR_NONE) {
342                 debug_error("Fail to stop run-plugin\n");
343         } else {
344                 debug_log("All run-type plugin stopped\n");
345         }
346
347         switch(sig)
348         {
349         case SIGINT:
350                 sigaction(SIGINT, &sigint_action, NULL);
351                 debug_error("signal(SIGINT) error");
352                 break;
353         case SIGABRT:
354                 sigaction(SIGABRT, &sigabrt_action, NULL);
355                 debug_error("signal(SIGABRT) error");
356                 break;
357         case SIGSEGV:
358                 sigaction(SIGSEGV, &sigsegv_action, NULL);
359                 debug_error("signal(SIGSEGV) error");
360                 break;
361         case SIGTERM:
362                 sigaction(SIGTERM, &sigterm_action, NULL);
363                 debug_error("signal(SIGTERM) error");
364                 break;
365         case SIGSYS:
366                 sigaction(SIGSYS, &sigsys_action, NULL);
367                 debug_error("signal(SIGSYS) error");
368                 break;
369         default:
370                 break;
371         }
372         raise(sig);
373 }
374
375 static int usgae(int argc, char **argv)
376 {
377         fprintf(stderr, "Usage: %s [Options]\n", argv[0]);
378         fprintf(stderr, "\t%-20s: start sound server.\n", "--start,-S");
379         fprintf(stderr, "\t%-20s: print plugin list.\n", "--list,-L");
380         fprintf(stderr, "\t%-20s: print this message.\n", "--help,-H");
381         fprintf(stderr, "\t%-20s: print this message.\n", "--plugdir,-P");
382
383         return 1;
384 }
385