Remove deprecated/unused functions
[platform/core/multimedia/libmm-sound.git] / mm_sound.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 <stdlib.h>
23 #include <memory.h>
24 #include <unistd.h>
25 #include <pthread.h>
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <fcntl.h>
29
30 #include <sys/stat.h>
31 #include <errno.h>
32
33 #include <vconf.h>
34 #include <mm_types.h>
35 #include <mm_error.h>
36 #include <mm_message.h>
37 #include <mm_debug.h>
38 #include "include/mm_sound_private.h"
39 #include "include/mm_sound.h"
40 #include "include/mm_sound_utils.h"
41 #include "include/mm_sound_client.h"
42 #include "include/mm_sound_pa_client.h"
43 #include "include/mm_ipc.h"
44 #include "include/mm_sound_common.h"
45
46
47 #define VOLUME_MAX_MULTIMEDIA   16
48 #define VOLUME_MAX_BASIC                8
49 #define VOLUME_MAX_SINGLE               1
50
51
52 #define MASTER_VOLUME_MAX 100
53 #define MASTER_VOLUME_MIN 0
54
55 static pthread_mutex_t g_volume_mutex = PTHREAD_MUTEX_INITIALIZER;
56
57 #include <gio/gio.h>
58
59 static GList *g_subscribe_cb_list = NULL;
60 static pthread_mutex_t g_subscribe_cb_list_mutex = PTHREAD_MUTEX_INITIALIZER;
61
62 #define MM_SOUND_DBUS_BUS_NAME_PREPIX  "org.tizen.MMSound"
63 #define MM_SOUND_DBUS_OBJECT_PATH  "/org/tizen/MMSound"
64 #define MM_SOUND_DBUS_INTERFACE    "org.tizen.mmsound"
65
66 GDBusConnection *g_dbus_conn_mmsound;
67
68 int g_dbus_signal_values[MM_SOUND_SIGNAL_MAX] = {0,};
69
70 const char* dbus_signal_name_str[] = {
71         "ReleaseInternalFocus",
72 };
73
74 typedef struct _subscribe_cb {
75         mm_sound_signal_name_t signal_type;
76         mm_sound_signal_callback callback;
77         void *user_data;
78         unsigned int id;
79 } subscribe_cb_t;
80
81 static const char* _get_volume_str (volume_type_t type)
82 {
83         static const char *volume_type_str[VOLUME_TYPE_MAX] =
84                 { "SYSTEM", "NOTIFICATION", "ALARM", "RINGTONE", "MEDIA", "CALL", "VOIP", "VOICE", "FIXED"};
85
86         return (type >= VOLUME_TYPE_SYSTEM && type < VOLUME_TYPE_MAX)? volume_type_str[type] : "Unknown";
87 }
88
89 static int _validate_volume(volume_type_t type, int value)
90 {
91         if (value < 0)
92                 return -1;
93
94         switch (type)
95         {
96         case VOLUME_TYPE_CALL:
97         case VOLUME_TYPE_VOIP:
98                 if (value >= VOLUME_MAX_BASIC) {
99                         return -1;
100                 }
101                 break;
102         case VOLUME_TYPE_SYSTEM:
103         case VOLUME_TYPE_MEDIA:
104         case VOLUME_TYPE_ALARM:
105         case VOLUME_TYPE_NOTIFICATION:
106         case VOLUME_TYPE_RINGTONE:
107         case VOLUME_TYPE_VOICE:
108                 if (value >= VOLUME_MAX_MULTIMEDIA) {
109                         return -1;
110                 }
111                 break;
112         default:
113                 return -1;
114                 break;
115         }
116         return 0;
117 }
118
119 EXPORT_API
120 int mm_sound_volume_remove_callback(volume_type_t type)
121 {
122         /* FIXME : Will be removed */
123         return MM_ERROR_NOT_SUPPORT_API;
124 }
125
126 EXPORT_API
127 int mm_sound_add_volume_changed_callback(mm_sound_volume_changed_cb func, void* user_data, unsigned int *subs_id)
128 {
129         int ret = MM_ERROR_NONE;
130
131         if (func == NULL || subs_id == NULL) {
132                 debug_error("argument is not valid\n");
133                 return MM_ERROR_INVALID_ARGUMENT;
134         }
135
136         ret = mm_sound_client_add_volume_changed_callback(func, user_data, subs_id);
137         if (ret < 0) {
138                 debug_error("Can not add volume changed callback, ret = %x\n", ret);
139         }
140
141         return ret;
142 }
143
144 EXPORT_API
145 int mm_sound_remove_volume_changed_callback(unsigned int subs_id)
146 {
147         int ret = MM_ERROR_NONE;
148
149         ret = mm_sound_client_remove_volume_changed_callback(subs_id);
150         if (ret < 0) {
151                 debug_error("Can not remove volume changed callback, ret = %x\n", ret);
152         }
153
154         return ret;
155 }
156
157 EXPORT_API
158 int mm_sound_volume_set_value(volume_type_t volume_type, const unsigned int volume_level)
159 {
160         int ret = MM_ERROR_NONE;
161
162         debug_msg("type = (%d)%s, value = %d", volume_type, _get_volume_str(volume_type), volume_level);
163
164         /* Check input param */
165         if (0 > _validate_volume(volume_type, (int)volume_level)) {
166                 debug_error("invalid volume type %d, value %u\n", volume_type, volume_level);
167                 return MM_ERROR_INVALID_ARGUMENT;
168         }
169
170         ret = mm_sound_util_volume_set_value_by_type(volume_type, volume_level);
171         if (ret == MM_ERROR_NONE) {
172                 /* update shared memory value */
173                 if(MM_ERROR_NONE != mm_sound_client_set_volume_by_type(volume_type, volume_level)) {
174                         debug_error("Can not set volume to shared memory 0x%x\n", ret);
175                 }
176         }
177
178         return ret;
179 }
180
181 EXPORT_API
182 int mm_sound_volume_get_value(volume_type_t type, unsigned int *value)
183 {
184         int ret = MM_ERROR_NONE;
185
186         /* Check input param */
187         if (value == NULL) {
188                 debug_error("invalid argument\n");
189                 return MM_ERROR_INVALID_ARGUMENT;
190         }
191         if (type < 0 || type >= VOLUME_TYPE_MAX) {
192                 debug_error("invalid volume type value %d\n", type);
193                 return MM_ERROR_INVALID_ARGUMENT;
194         }
195
196         ret = mm_sound_util_volume_get_value_by_type(type, value);
197
198         debug_msg("returned %s = %d", _get_volume_str(type), *value);
199         return ret;
200 }
201
202 EXPORT_API
203 int mm_sound_volume_primary_type_set(volume_type_t type)
204 {
205         int ret = MM_ERROR_NONE;
206
207         /* Check input param */
208         if(type < VOLUME_TYPE_UNKNOWN || type >= VOLUME_TYPE_MAX) {
209                 debug_error("invalid argument\n");
210                 return MM_ERROR_INVALID_ARGUMENT;
211         }
212
213         if (vconf_set_int(VCONFKEY_SOUND_PRIMARY_VOLUME_TYPE, type)) {
214                 debug_error("could not set vconf for RIMARY_VOLUME_TYPE\n");
215                 ret = MM_ERROR_SOUND_INTERNAL;
216         } else {
217                 debug_msg("set primary volume type forcibly %d(%s)", type, _get_volume_str(type));
218         }
219
220         return ret;
221 }
222
223 EXPORT_API
224 int mm_sound_volume_primary_type_get(volume_type_t *type)
225 {
226         int ret = MM_ERROR_NONE;
227         int voltype = VOLUME_TYPE_RINGTONE;
228
229         /* Check input param */
230         if(type == NULL) {
231                 debug_error("invalid argument\n");
232                 return MM_ERROR_INVALID_ARGUMENT;
233         }
234
235         /* check force set */
236         if (vconf_get_int(VCONFKEY_SOUND_PRIMARY_VOLUME_TYPE, &voltype)) {
237                 debug_error("could not get vconf for PRIMARY_VOLUME_TYPE\n");
238                 ret = MM_ERROR_SOUND_INTERNAL;
239         } else {
240                 debug_msg("get primary volume type %d(%s)", voltype, _get_volume_str(voltype));
241                 *type = voltype;
242         }
243
244         return ret;
245 }
246
247 ///////////////////////////////////
248 ////     MMSOUND PLAY APIs
249 ///////////////////////////////////
250 static inline void _mm_sound_fill_play_param(MMSoundPlayParam *param, const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int priority, int handle_route)
251 {
252         param->filename = filename;
253         param->volume = 0; //volume value dose not effect anymore
254         param->callback = callback;
255         param->data = data;
256         param->loop = 1;
257         param->volume_config = volume_config;
258         param->priority = priority;
259         param->handle_route = handle_route;
260 }
261
262 EXPORT_API
263 int mm_sound_play_loud_solo_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
264 {
265         MMSoundPlayParam param = { 0, };
266
267     /* FIXME : this function will be deleted */
268         _mm_sound_fill_play_param(&param, filename, volume_config, callback, data, HANDLE_PRIORITY_NORMAL, MM_SOUND_HANDLE_ROUTE_USING_CURRENT);
269         return mm_sound_play_sound_ex(&param, handle);
270 }
271
272 EXPORT_API
273 int mm_sound_play_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
274 {
275         MMSoundPlayParam param = { 0, };
276
277         _mm_sound_fill_play_param(&param, filename, volume_config, callback, data, HANDLE_PRIORITY_NORMAL, MM_SOUND_HANDLE_ROUTE_USING_CURRENT);
278         return mm_sound_play_sound_ex(&param, handle);
279 }
280
281 EXPORT_API
282 int mm_sound_play_sound_ex(MMSoundPlayParam *param, int *handle)
283 {
284         int err;
285         int lhandle = -1;
286         int volume_type = 0;
287         /* Check input param */
288         if (param == NULL) {
289                 debug_error("param is null\n");
290                 return MM_ERROR_INVALID_ARGUMENT;
291         }
292
293         volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(param->volume_config);
294
295         if (param->filename == NULL) {
296                 debug_error("filename is NULL\n");
297                 return MM_ERROR_SOUND_FILE_NOT_FOUND;
298         }
299         if (volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
300                 debug_error("Volume type is invalid %d\n", volume_type);
301                 return MM_ERROR_INVALID_ARGUMENT;
302         }
303
304         debug_warning ("play sound : priority=[%d], handle_route=[%d]\n", param->priority, param->handle_route);
305
306         /* Play sound */
307         err = mm_sound_client_play_sound(param, 0, &lhandle);
308         if (err < 0) {
309                 debug_error("Failed to play sound\n");
310                 return err;
311         }
312
313         /* Set handle to return */
314         if (handle) {
315                 *handle = lhandle;
316         } else {
317                 debug_critical("The sound hadle cannot be get [%d]\n", lhandle);
318         }
319
320         debug_warning ("success : handle=[%p]\n", handle);
321
322         return MM_ERROR_NONE;
323 }
324
325 EXPORT_API
326 int mm_sound_play_sound_with_stream_info(const char *filename, char *stream_type, int stream_id, mm_sound_stop_callback_func callback, void *data, int *handle)
327 {
328         MMSoundPlayParam param = { 0, };
329         int err;
330
331         param.filename = filename;
332         param.volume = 0; //volume value dose not effect anymore
333         param.callback = callback;
334         param.data = data;
335         param.loop = 1;
336         param.priority = HANDLE_PRIORITY_NORMAL;
337         param.handle_route = MM_SOUND_HANDLE_ROUTE_USING_CURRENT;
338
339         err = mm_sound_client_play_sound_with_stream_info(&param, handle, stream_type, stream_id);
340         if (err < 0) {
341                 debug_error("Failed to play sound\n");
342                 return err;
343         }
344
345         debug_warning ("success : handle=[%p]\n", handle);
346
347         return MM_ERROR_NONE;
348
349 }
350
351
352 EXPORT_API
353 int mm_sound_stop_sound(int handle)
354 {
355         int err;
356
357         debug_warning ("enter : handle=[%p]\n", handle);
358         /* Stop sound */
359         err = mm_sound_client_stop_sound(handle);
360         if (err < 0) {
361                 debug_error("Fail to stop sound\n");
362                 return err;
363         }
364         debug_warning ("success : handle=[%p]\n", handle);
365
366         return MM_ERROR_NONE;
367 }
368
369 ///////////////////////////////////
370 ////     MMSOUND TONE APIs
371 ///////////////////////////////////
372 EXPORT_API
373 int mm_sound_play_tone_ex (MMSoundTone_t num, int volume_config, const double volume, const int duration, int *handle, bool enable_session)
374 {
375         int lhandle = -1;
376         int err = MM_ERROR_NONE;
377         int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(volume_config);
378
379         debug_fenter();
380
381         /* Check input param */
382         if (duration < -1) {
383                 debug_error("number is invalid %d\n", duration);
384                 return MM_ERROR_INVALID_ARGUMENT;
385         }
386         if (num < MM_SOUND_TONE_DTMF_0 || num >= MM_SOUND_TONE_NUM) {
387                 debug_error("TONE Value is invalid %d\n", num);
388                 return MM_ERROR_INVALID_ARGUMENT;
389         }
390         if (volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
391                 debug_error("Volume type is invalid %d\n", volume_type);
392                 return MM_ERROR_INVALID_ARGUMENT;
393         }
394         if (volume < 0.0 || volume > 1.0) {
395                 debug_error("Volume Value is invalid %d\n", volume);
396                 return MM_ERROR_INVALID_ARGUMENT;
397         }
398
399         /* Play tone */
400         debug_msg("Call MMSoundClientPlayTone\n");
401         err = mm_sound_client_play_tone(num, volume_config, volume, duration, &lhandle, enable_session);
402         if (err < 0) {
403                 debug_error("Failed to play sound\n");
404                 return err;
405         }
406
407         /* Set handle to return */
408         if (handle)
409                 *handle = lhandle;
410         else
411                 debug_critical("The sound handle cannot be get [%d]\n", lhandle);
412
413         debug_fleave();
414         return MM_ERROR_NONE;
415 }
416
417 EXPORT_API
418 int mm_sound_play_tone_with_stream_info(MMSoundTone_t tone, char *stream_type, int stream_id, const double volume, const int duration, int *handle)
419 {
420
421         int err = MM_ERROR_NONE;
422
423         err = mm_sound_client_play_tone_with_stream_info(tone, stream_type, stream_id, volume, duration, handle);
424         if (err <0) {
425                 debug_error("Failed to play sound\n");
426                 return err;
427         }
428
429         return err;
430
431 }
432
433
434 EXPORT_API
435 int mm_sound_play_tone (MMSoundTone_t num, int volume_config, const double volume, const int duration, int *handle)
436 {
437         return mm_sound_play_tone_ex (num, volume_config, volume, duration, handle, true);
438 }
439
440 ///////////////////////////////////
441 ////     MMSOUND ROUTING APIs
442 ///////////////////////////////////
443
444 EXPORT_API
445 int mm_sound_get_active_device(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
446 {
447         /* FIXME : Will be removed */
448         return MM_ERROR_NOT_SUPPORT_API;
449 }
450
451 EXPORT_API
452 int mm_sound_test(int a, int b, int* getv)
453 {
454         int ret = MM_ERROR_NONE;
455
456         debug_log("mm_sound_test enter");
457         if (!getv) {
458                 debug_error("argu null");
459                 return MM_ERROR_INVALID_ARGUMENT;
460         }
461         ret = mm_sound_client_test(a, b, getv);
462         if (ret < 0) {
463                 debug_error("Can not mm sound test, ret = %x\n", ret);
464         }
465         debug_log("mm_sound_test leave");
466
467         return ret;
468 }
469
470 EXPORT_API
471 int mm_sound_add_test_callback(mm_sound_test_cb func, void *user_data, unsigned int *subs_id)
472 {
473         int ret = MM_ERROR_NONE;
474
475         debug_log("mm_sound_add_test_callback enter");
476         if (!func || !subs_id) {
477                 debug_error("argument is not valid\n");
478                 return MM_ERROR_INVALID_ARGUMENT;
479         }
480
481         ret = mm_sound_client_add_test_callback(func, user_data, subs_id);
482         if (ret < 0) {
483                 debug_error("Can not add test callback, ret = %x\n", ret);
484         }
485         debug_log("mm_sound_add_test_callback leave");
486
487         return ret;
488 }
489
490 EXPORT_API
491 int mm_sound_remove_test_callback(unsigned int subs_id)
492 {
493         int ret = MM_ERROR_NONE;
494
495         debug_log("mm_sound_remove_test_callback enter");
496         ret = mm_sound_client_remove_test_callback(subs_id);
497         if (ret < 0) {
498                 debug_error("Can not remove test callback, ret = %x\n", ret);
499         }
500         debug_log("mm_sound_remove_test_callback leave");
501
502         return ret;
503 }
504
505 static int _convert_signal_name_str_to_enum (const char *name_str, mm_sound_signal_name_t *name_enum) {
506         int ret = MM_ERROR_NONE;
507
508         if (!name_str || !name_enum)
509                 return MM_ERROR_INVALID_ARGUMENT;
510
511         if (!strncmp(name_str, "ReleaseInternalFocus", strlen("ReleaseInternalFocus"))) {
512                 *name_enum = MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS;
513         } else {
514                 ret = MM_ERROR_INVALID_ARGUMENT;
515                 LOGE("not supported signal name(%s), err(0x%08x)", name_str, ret);
516         }
517         return ret;
518 }
519
520 static void _dbus_signal_callback (const char *signal_name, int value, void *user_data)
521 {
522         int ret = MM_ERROR_NONE;
523         mm_sound_signal_name_t signal;
524         subscribe_cb_t *subscribe_cb = (subscribe_cb_t*)user_data;
525
526         debug_fenter();
527
528         if (!subscribe_cb)
529                 return;
530
531         ret = _convert_signal_name_str_to_enum(signal_name, &signal);
532         if (ret)
533                 return;
534
535         debug_msg ("signal_name[%s], value[%d], user_data[0x%x]\n", signal_name, value, user_data);
536
537         if (subscribe_cb->signal_type == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) {
538                 /* trigger the signal callback when it comes from the same process */
539                 if (getpid() == ((value & 0xFFFF0000) >> 16)) {
540                         subscribe_cb->callback(signal, (value & 0x0000FFFF), subscribe_cb->user_data);
541                 }
542         } else {
543                 subscribe_cb->callback(signal, value, subscribe_cb->user_data);
544         }
545
546         debug_fleave();
547
548         return;
549 }
550
551 static void signal_callback(GDBusConnection *conn,
552                                                            const gchar *sender_name,
553                                                            const gchar *object_path,
554                                                            const gchar *interface_name,
555                                                            const gchar *signal_name,
556                                                            GVariant *parameters,
557                                                            gpointer user_data)
558 {
559         int value=0;
560         const GVariantType* value_type;
561
562         debug_msg ("sender : %s, object : %s, interface : %s, signal : %s",
563                         sender_name, object_path, interface_name, signal_name);
564         if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(i)"))) {
565                 g_variant_get(parameters, "(i)",&value);
566                 debug_msg(" - value : %d\n", value);
567                 _dbus_signal_callback(signal_name, value, user_data);
568         } else  {
569                 value_type = g_variant_get_type(parameters);
570                 debug_warning("signal type is %s", value_type);
571         }
572 }
573
574 EXPORT_API
575 int mm_sound_subscribe_signal(mm_sound_signal_name_t signal, unsigned int *subscribe_id, mm_sound_signal_callback callback, void *user_data)
576 {
577         int ret = MM_ERROR_NONE;
578         GError *err = NULL;
579
580         subscribe_cb_t *subscribe_cb = NULL;
581
582         debug_fenter();
583
584         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_subscribe_cb_list_mutex, MM_ERROR_SOUND_INTERNAL);
585
586         if (signal < 0 || signal >= MM_SOUND_SIGNAL_MAX || !subscribe_id) {
587                 debug_error ("invalid argument, signal(%d), subscribe_id(0x%p)", signal, subscribe_id);
588                 ret = MM_ERROR_INVALID_ARGUMENT;
589                 goto error;
590         }
591
592         subscribe_cb = malloc(sizeof(subscribe_cb_t));
593         if (!subscribe_cb) {
594                 ret = MM_ERROR_SOUND_INTERNAL;
595                 goto error;
596         }
597         memset(subscribe_cb, 0, sizeof(subscribe_cb_t));
598
599         g_dbus_conn_mmsound = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
600         if (!g_dbus_conn_mmsound && err) {
601                 debug_error ("g_bus_get_sync() error (%s) ", err->message);
602                 g_error_free (err);
603                 ret = MM_ERROR_SOUND_INTERNAL;
604                 goto error;
605         }
606
607         subscribe_cb->signal_type = signal;
608         subscribe_cb->callback = callback;
609         subscribe_cb->user_data = user_data;
610
611         *subscribe_id = g_dbus_connection_signal_subscribe(g_dbus_conn_mmsound,
612                         NULL, MM_SOUND_DBUS_INTERFACE, dbus_signal_name_str[signal], MM_SOUND_DBUS_OBJECT_PATH, NULL, 0,
613                         signal_callback, subscribe_cb, NULL);
614         if (*subscribe_id == 0) {
615                 debug_error ("g_dbus_connection_signal_subscribe() error (%d)", *subscribe_id);
616                 ret = MM_ERROR_SOUND_INTERNAL;
617                 goto sig_error;
618         }
619
620         subscribe_cb->id = *subscribe_id;
621
622         g_subscribe_cb_list = g_list_append(g_subscribe_cb_list, subscribe_cb);
623         if (g_subscribe_cb_list) {
624                 debug_log("new subscribe_cb(0x%x)[user_callback(0x%x), subscribe_id(%u)] is added\n", subscribe_cb, subscribe_cb->callback, subscribe_cb->id);
625         } else {
626                 debug_error("g_list_append failed\n");
627                 ret = MM_ERROR_SOUND_INTERNAL;
628                 goto error;
629         }
630
631         MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
632
633         debug_fleave();
634
635         return ret;
636
637 sig_error:
638         g_dbus_connection_signal_unsubscribe(g_dbus_conn_mmsound, *subscribe_id);
639         g_object_unref(g_dbus_conn_mmsound);
640
641 error:
642         if (subscribe_cb)
643                 free (subscribe_cb);
644
645         MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
646
647         return ret;
648 }
649
650 EXPORT_API
651 void mm_sound_unsubscribe_signal(unsigned int subscribe_id)
652 {
653         GList *list = NULL;
654         subscribe_cb_t *subscribe_cb = NULL;
655
656         debug_fenter();
657
658         MMSOUND_ENTER_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
659
660         if (g_dbus_conn_mmsound && subscribe_id) {
661                 g_dbus_connection_signal_unsubscribe(g_dbus_conn_mmsound, subscribe_id);
662                 g_object_unref(g_dbus_conn_mmsound);
663                 for (list = g_subscribe_cb_list; list != NULL; list = list->next) {
664                         subscribe_cb = (subscribe_cb_t *)list->data;
665                         if (subscribe_cb && (subscribe_cb->id == subscribe_id)) {
666                                 g_subscribe_cb_list = g_list_remove(g_subscribe_cb_list, subscribe_cb);
667                                 debug_log("subscribe_cb(0x%x) is removed\n", subscribe_cb);
668                                 free (subscribe_cb);
669                         }
670                 }
671         }
672
673         MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
674
675         debug_fleave();
676 }
677
678 EXPORT_API
679 int mm_sound_send_signal(mm_sound_signal_name_t signal, int value)
680 {
681         int ret = MM_ERROR_NONE;
682         GError *err = NULL;
683         GDBusConnection *conn = NULL;
684         gboolean dbus_ret = TRUE;
685
686         debug_fenter();
687
688         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_subscribe_cb_list_mutex, MM_ERROR_SOUND_INTERNAL);
689
690         if (signal < 0 || signal >= MM_SOUND_SIGNAL_MAX) {
691                 debug_error ("invalid argument, signal(%d)", signal);
692                 ret = MM_ERROR_INVALID_ARGUMENT;
693                 goto error;
694         }
695
696         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
697         if (!conn && err) {
698                 debug_error ("g_bus_get_sync() error (%s)", err->message);
699                 ret = MM_ERROR_SOUND_INTERNAL;
700                 goto error;
701         }
702
703         g_dbus_signal_values[signal] = value;
704         if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) {
705                 /* trigger the signal callback when it comes from the same process */
706                 value |= ((int)getpid() << 16);
707         }
708         dbus_ret = g_dbus_connection_emit_signal (conn,
709                                 NULL, MM_SOUND_DBUS_OBJECT_PATH, MM_SOUND_DBUS_INTERFACE, dbus_signal_name_str[signal],
710                                 g_variant_new ("(i)", value),
711                                 &err);
712         if (!dbus_ret && err) {
713                 debug_error ("g_dbus_connection_emit_signal() error (%s)", err->message);
714                 ret = MM_ERROR_SOUND_INTERNAL;
715                 goto error;
716         }
717
718         dbus_ret = g_dbus_connection_flush_sync(conn, NULL, &err);
719         if (!dbus_ret && err) {
720                 debug_error ("g_dbus_connection_flush_sync() error (%s)", err->message);
721                 ret = MM_ERROR_SOUND_INTERNAL;
722                 goto error;
723         }
724
725         g_object_unref(conn);
726         debug_msg ("sending signal[%s], value[%d] success", dbus_signal_name_str[signal], value);
727
728         MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
729
730         debug_fleave();
731
732         return ret;
733
734 error:
735         if (err)
736                 g_error_free (err);
737         if (conn)
738                 g_object_unref(conn);
739
740         MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
741
742         return ret;
743 }
744
745 EXPORT_API
746 int mm_sound_get_signal_value(mm_sound_signal_name_t signal, int *value)
747 {
748         int ret = MM_ERROR_NONE;
749
750         debug_fenter();
751
752         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_subscribe_cb_list_mutex, MM_ERROR_SOUND_INTERNAL);
753
754         *value = g_dbus_signal_values[signal];
755
756         MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
757
758         debug_fleave();
759
760         return ret;
761 }
762
763 __attribute__ ((constructor))
764 static void _mm_sound_initialize(void)
765 {
766         mm_sound_client_initialize();
767         /* Will be Fixed */
768 }
769
770 __attribute__ ((destructor))
771 static void _mm_sound_finalize(void)
772 {
773         mm_sound_client_finalize();
774 }
775
776