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