Enable agc, denoise, dereverb
[platform/core/multimedia/libmm-sound.git] / mm_sound_proxy.c
1 #include <stdint.h>
2 #include <glib.h>
3
4 #ifdef TIZEN_TV
5 #include <vconf.h>
6 #endif
7
8 #include <mm_error.h>
9 #include <mm_debug.h>
10
11 #include "include/mm_sound_proxy.h"
12 #include "include/mm_sound_common.h"
13 #include "include/mm_sound_dbus.h"
14 #include "include/mm_sound_intf.h"
15 #include "include/mm_sound_focus_socket.h"
16 #include "include/mm_sound_focus_private.h"
17
18 struct callback_data {
19         void *user_cb;
20         void *user_data;
21         mm_sound_proxy_userdata_free free_func;
22         uint32_t subs_id;
23 };
24
25 #define CB_DATA_NEW(_cb_data, _func, _userdata, _freefunc) \
26         do { \
27                 _cb_data = (struct callback_data*) g_try_malloc0(sizeof(struct callback_data)); \
28                 if (!_cb_data) { \
29                         debug_error("failed to allocate callback_data"); \
30                         return MM_ERROR_OUT_OF_MEMORY; \
31                 } \
32                 _cb_data->user_cb = _func; \
33                 _cb_data->user_data = _userdata; \
34                 _cb_data->free_func = _freefunc; \
35                 _cb_data->subs_id = 0; \
36         } while (0)
37
38 /* subscribe is true when add callback,
39  * false when remove callback */
40 static int _notify_subscription(audio_event_t event, uint32_t subs_id, gboolean subscribe)
41 {
42         int ret = MM_ERROR_NONE;
43         GVariant *params = NULL;
44         const char *event_name = NULL;
45
46         debug_fenter();
47
48         if ((ret = mm_sound_dbus_get_event_name(event, &event_name)) != MM_ERROR_NONE) {
49                 debug_error("Failed to get event name");
50                 return MM_ERROR_SOUND_INTERNAL;
51         }
52
53         if (!(params = g_variant_new("(sub)", event_name, subs_id, subscribe))) {
54                 debug_error("Construct Param failed");
55                 return MM_ERROR_SOUND_INTERNAL;
56         }
57
58         if ((ret = mm_sound_dbus_emit_signal(AUDIO_PROVIDER_AUDIO_CLIENT, AUDIO_EVENT_CLIENT_SUBSCRIBED, params)))
59                 debug_error("dbus send signal for client subscribed failed");
60
61         debug_fleave();
62         return ret;
63 }
64
65 static int _notify_signal_handled(audio_event_t event, uint32_t event_id, uint32_t subs_id, GVariant *signal_params)
66 {
67         int ret = MM_ERROR_NONE;
68         GVariant *params = NULL;
69         const char *event_name = NULL;
70
71         debug_fenter();
72
73         if ((ret = mm_sound_dbus_get_event_name(event, &event_name)) != MM_ERROR_NONE) {
74                 debug_error("Failed to get event name");
75                 return MM_ERROR_SOUND_INTERNAL;
76         }
77
78         if (!(params = g_variant_new("(usuv)", event_id, event_name, subs_id, signal_params))) {
79                 debug_error("Construct Param failed");
80                 return MM_ERROR_SOUND_INTERNAL;
81         }
82
83         if ((ret = mm_sound_dbus_emit_signal(AUDIO_PROVIDER_AUDIO_CLIENT, AUDIO_EVENT_CLIENT_HANDLED, params)))
84                 debug_error("dbus send signal for client handled failed");
85
86         debug_fleave();
87         return ret;
88 }
89
90 static int parse_device_variant(GVariant *v, int *device_id, const char **device_type, int *direction, int *state,
91                                                 const char **device_name, int *vendor_id, int *product_id, gboolean *is_running, int *stream_id, int *stream_num)
92 {
93         const char *v_type;
94         GVariant *array_v;
95         GVariantIter iter, array_iter;
96         int i = 0;
97         int ret = MM_ERROR_NONE;
98
99         if (v == NULL) {
100                 debug_error("Variant NULL");
101                 return MM_ERROR_NONE;
102         }
103
104         v_type = g_variant_get_type_string(v);
105         if (g_variant_type_equal(v_type, "(isiisiibai)") == FALSE) {
106                 debug_error("device variant type not matching '%s'", v_type);
107                 return MM_ERROR_NONE;
108         }
109
110         g_variant_iter_init(&iter, v);
111         g_variant_iter_next(&iter, "i", device_id);
112         g_variant_iter_next(&iter, "&s", device_type);
113         g_variant_iter_next(&iter, "i", direction);
114         g_variant_iter_next(&iter, "i", state);
115         g_variant_iter_next(&iter, "&s", device_name);
116         g_variant_iter_next(&iter, "i", vendor_id);
117         g_variant_iter_next(&iter, "i", product_id);
118         g_variant_iter_next(&iter, "b", is_running);
119
120         array_v = g_variant_iter_next_value(&iter);
121         if (!array_v) {
122                 debug_error("Error iterate on next value");
123                 return MM_ERROR_SOUND_INTERNAL;
124         }
125
126         *stream_num = g_variant_iter_init(&array_iter, array_v);
127         if (*stream_num > MAX_STREAM_ON_DEVICE) {
128                 debug_error("too many streams on device %d", *stream_num);
129                 ret = MM_ERROR_SOUND_INTERNAL;
130                 goto cleanup;
131         }
132
133         while (g_variant_iter_loop(&array_iter, "i", &stream_id[i++])) {}
134
135 cleanup:
136         g_variant_unref(array_v);
137
138         return ret;
139 }
140
141 /* This callback unmarshall general-formed parameters to subject specific parameters,
142  * and call proper callback */
143 static void dbus_callback(audio_event_t event, GVariant *params, void *userdata)
144 {
145         struct callback_data *cb_data  = (struct callback_data*) userdata;
146         uint32_t event_id;
147         const char *name = NULL, *device_type = NULL;
148         int device_id, direction, state;
149         const gchar *v_type;
150         GVariantIter iter;
151         GVariant *device_v;
152         int stream_id[MAX_STREAM_ON_DEVICE];
153         int stream_num;
154         int vendor_id, product_id;
155         gboolean is_running = FALSE;
156
157         v_type = g_variant_get_type_string(params);
158
159         if (event == AUDIO_EVENT_VOLUME_CHANGED) {
160                 char *volume_type_str = NULL, *direction = NULL;
161                 unsigned volume_level;
162
163                 g_variant_get(params, "(&s&su)", &direction, &volume_type_str, &volume_level);
164                 ((mm_sound_volume_changed_wrapper_cb)(cb_data->user_cb))(direction, volume_type_str, volume_level, cb_data->user_data);
165         } else if (event == AUDIO_EVENT_DEVICE_CONNECTED) {
166                 gboolean is_connected = FALSE;
167
168                 if (g_variant_type_equal(v_type, "(u(isiisiibai)b)") == FALSE) {
169                         debug_error("Device connection changed signature not matching : %s", v_type);
170                         return ;
171                 }
172                 g_variant_iter_init(&iter, params);
173                 g_variant_iter_next(&iter, "u", &event_id);
174                 device_v = g_variant_iter_next_value(&iter);
175                 if (parse_device_variant(device_v, &device_id, &device_type, &direction, &state,
176                                                         &name, &vendor_id, &product_id, &is_running, stream_id, &stream_num) < 0) {
177                         debug_error("Failed to parse device variant");
178                         return ;
179                 }
180                 g_variant_iter_next(&iter, "b", &is_connected);
181
182                 ((mm_sound_device_connected_wrapper_cb)(cb_data->user_cb))(device_id, device_type, direction,
183                         state, name, vendor_id, product_id, (bool)is_running, stream_id, stream_num, (bool)is_connected, cb_data->user_data);
184                 _notify_signal_handled(event, event_id, cb_data->subs_id, g_variant_new("(ib)", device_id, (bool)is_connected));
185         } else if (event == AUDIO_EVENT_DEVICE_INFO_CHANGED) {
186                 int changed_device_info_type = 0;
187
188                 if (g_variant_type_equal(v_type, "(u(isiisiibai)i)") == FALSE) {
189                         debug_error("Device information changed signature not matching : %s", v_type);
190                         return ;
191                 }
192
193                 g_variant_iter_init(&iter, params);
194                 g_variant_iter_next(&iter, "u", &event_id);
195                 device_v = g_variant_iter_next_value(&iter);
196                 if (parse_device_variant(device_v, &device_id, &device_type, &direction, &state,
197                                                         &name, &vendor_id, &product_id, &is_running, stream_id, &stream_num) < 0) {
198                         debug_error("Failed to parse device variant");
199                         return ;
200                 }
201                 g_variant_iter_next(&iter, "i", &changed_device_info_type);
202
203                 ((mm_sound_device_info_changed_wrapper_cb)(cb_data->user_cb))(device_id, device_type, direction,
204                         state, name, vendor_id, product_id, (bool)is_running, stream_id, stream_num, changed_device_info_type, cb_data->user_data);
205         } else if (event == AUDIO_EVENT_DEVICE_STATE_CHANGED) {
206
207                 if (g_variant_type_equal(v_type, "(u(isiisiibai))") == FALSE) {
208                         debug_error("Device state changed signature not matching : %s", v_type);
209                         return ;
210                 }
211
212                 g_variant_iter_init(&iter, params);
213                 g_variant_iter_next(&iter, "u", &event_id);
214                 device_v = g_variant_iter_next_value(&iter);
215                 if (parse_device_variant(device_v, &device_id, &device_type, &direction, &state,
216                                                         &name, &vendor_id, &product_id, &is_running, stream_id, &stream_num) < 0) {
217                         debug_error("Failed to parse device variant");
218                         return ;
219                 }
220
221                 ((mm_sound_device_state_changed_wrapper_cb)(cb_data->user_cb))(device_id, device_type, direction,
222                         state, name, vendor_id, product_id, (bool)is_running, stream_id, stream_num, cb_data->user_data);
223         } else if (event == AUDIO_EVENT_DEVICE_RUNNING_CHANGED) {
224
225                 if (g_variant_type_equal(v_type, "(u(isiisiibai))") == FALSE) {
226                         debug_error("Device state changed signature not matching : %s", v_type);
227                         return ;
228                 }
229
230                 g_variant_iter_init(&iter, params);
231                 g_variant_iter_next(&iter, "u", &event_id);
232                 device_v = g_variant_iter_next_value(&iter);
233                 if (parse_device_variant(device_v, &device_id, &device_type, &direction, &state,
234                                                         &name, &vendor_id, &product_id, &is_running, stream_id, &stream_num) < 0) {
235                         debug_error("Failed to parse device variant");
236                         return ;
237                 }
238
239                 ((mm_sound_device_running_changed_wrapper_cb)(cb_data->user_cb))(device_id, device_type, direction,
240                         state, name, vendor_id, product_id, (bool)is_running, stream_id, stream_num, cb_data->user_data);
241         } else if (event == AUDIO_EVENT_FOCUS_CHANGED) {
242         } else if (event == AUDIO_EVENT_FOCUS_WATCH) {
243         } else if (event == AUDIO_EVENT_TEST) {
244                 int test_var = 0;
245                 g_variant_get(params, "(i)", &test_var);
246                 ((mm_sound_test_cb)(cb_data->user_cb))(test_var, cb_data->user_data);
247         } else if (event == AUDIO_EVENT_DUCKING_STATE_CHANGED) {
248                 int idx = 0;
249                 int is_ducked = 0;
250
251                 g_variant_get(params, "(ii)", &idx, &is_ducked);
252
253                 ((mm_sound_ducking_state_changed_wrapper_cb)(cb_data->user_cb))(idx, is_ducked, cb_data->user_data);
254         }
255 }
256
257 static void simple_callback_data_free_func(void *data)
258 {
259         struct callback_data *cb_data = (struct callback_data*) data;
260
261         if (cb_data) {
262                 if (cb_data->free_func)
263                         cb_data->free_func(cb_data->user_data);
264                 g_free(cb_data);
265         }
266 }
267
268 int mm_sound_proxy_is_stream_on_device(int stream_id, int device_id, bool *is_on)
269 {
270         int ret = MM_ERROR_NONE;
271         GVariant *params = NULL, *result = NULL;
272         gboolean _is_on;
273
274         debug_fenter();
275
276         if (!is_on) {
277                 debug_error("Invalid Parameter, is_on null");
278                 return MM_ERROR_INVALID_ARGUMENT;
279         }
280
281         if ((params = g_variant_new("(ii)", stream_id, device_id)) == NULL) {
282                 debug_error("Construct Param for query is stream on device failed");
283                 return MM_ERROR_SOUND_INTERNAL;
284         }
285
286         if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_METHOD_IS_STREAM_ON_DEVICE, params, &result)) != MM_ERROR_NONE) {
287                 debug_error("is stream on device failed");
288                 goto cleanup;
289         }
290
291         if (result) {
292                 g_variant_get(result, "(b)",  &_is_on);
293                 debug_log("is_on : %d", _is_on);
294                 *is_on = (bool)_is_on;
295         } else {
296                 debug_error("reply null");
297                 ret = MM_ERROR_SOUND_INTERNAL;
298         }
299
300 cleanup:
301         if (result)
302                 g_variant_unref(result);
303
304         debug_fleave();
305         return ret;
306 }
307
308 #ifdef TIZEN_TV
309 #define _VCONF_KEY_SOUND_SPEAKER_SELECTION "file/private/sound/feature/SpeakerSelection"
310 #define _AUDIO_TV_OUTPUT_BT_HEADSET 5
311
312 static mm_sound_device_t* _get_tv_bt_device(int device_flags)
313 {
314         int speaker_value = 0;
315         mm_sound_device_t* device_item = NULL;
316
317         /* check precondition mask first here */
318         if (device_flags != DEVICE_ALL_FLAG) {
319                 if (!(device_flags & DEVICE_IO_DIRECTION_OUT_FLAG)) {
320                         debug_warning("no out flag given, skip checking bt a2dp");
321                         return NULL;
322                 }
323                 if (device_flags & DEVICE_TYPE_INTERNAL_FLAG) {
324                         debug_warning("internal flag given, skip checking bt a2dp");
325                         return NULL;
326                 }
327         }
328
329         if (vconf_get_int(_VCONF_KEY_SOUND_SPEAKER_SELECTION, &speaker_value) == VCONF_ERROR) {
330                 debug_error("vconf_get_int(%s) failed..", _VCONF_KEY_SOUND_SPEAKER_SELECTION);
331                 return NULL;
332         }
333
334         debug_warning("speaker selection value = %d", speaker_value);
335         if (speaker_value != _AUDIO_TV_OUTPUT_BT_HEADSET)
336                 return NULL;
337
338         device_item = g_new0(mm_sound_device_t, 1);
339
340         MMSOUND_STRNCPY(device_item->name, "BluetoothMedia", MAX_DEVICE_NAME_NUM);
341         MMSOUND_STRNCPY(device_item->type, "bt-a2dp", MAX_DEVICE_TYPE_STR_LEN);
342         device_item->id = 99;
343         device_item->io_direction = DEVICE_IO_DIRECTION_OUT;
344         device_item->state = DEVICE_STATE_ACTIVATED;
345         device_item->vendor_id = -1;
346         device_item->product_id = -1;
347         device_item->stream_num = -1;
348
349         return device_item;
350 }
351 #endif /* TIZEN_TV */
352
353 int mm_sound_proxy_get_current_connected_device_list(int device_flags, GList** device_list)
354 {
355         int ret = MM_ERROR_NONE;
356         GVariant *result = NULL, *child = NULL;
357         GVariant *params = NULL;
358         GVariantIter iter;
359         mm_sound_device_t* device_item;
360         const gchar *device_name_tmp = NULL, *device_type_tmp = NULL;
361
362         debug_fenter();
363
364         if (!device_list) {
365                 debug_error("Invalid Parameter, device_list null");
366                 ret = MM_ERROR_INVALID_ARGUMENT;
367                 goto cleanup;
368         }
369
370         params = g_variant_new("(i)", device_flags);
371
372         if (params) {
373                 if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_METHOD_GET_CONNECTED_DEVICE_LIST, params, &result)) != MM_ERROR_NONE) {
374                         debug_error("Get current connected device list failed");
375                         goto cleanup;
376                 }
377         } else {
378                 debug_error("Construct Param for get current connected device failed");
379                 return MM_ERROR_SOUND_INTERNAL;
380         }
381
382         child = g_variant_get_child_value(result, 0);
383         if (!child) {
384                 debug_error("Error getting child value from result");
385                 goto cleanup;
386         }
387         g_variant_iter_init(&iter, child);
388         while (1) {
389                 device_item = g_malloc0(sizeof(mm_sound_device_t));
390                 if (device_item && g_variant_iter_loop(&iter, "(i&sii&siib)",
391                                         &device_item->id, &device_type_tmp, &device_item->io_direction, &device_item->state,
392                                         &device_name_tmp, &device_item->vendor_id, &device_item->product_id, &device_item->is_running)) {
393                         MMSOUND_STRNCPY(device_item->name, device_name_tmp, MAX_DEVICE_NAME_NUM);
394                         MMSOUND_STRNCPY(device_item->type, device_type_tmp, MAX_DEVICE_TYPE_STR_LEN);
395                         *device_list = g_list_append(*device_list, device_item);
396                         debug_log("Added device id(%d) type(%17s) direction(%d) state(%d) name(%s) vendor-id(%04x) product-id(%04x) is_running(%d)",
397                                         device_item->id, device_item->type, device_item->io_direction, device_item->state,
398                                         device_item->name, device_item->vendor_id, device_item->product_id, device_item->is_running);
399                         device_item->stream_num = -1;
400                 } else {
401                         g_free(device_item);
402                         break;
403                 }
404         }
405         g_variant_unref(child);
406
407 #ifdef TIZEN_TV
408         device_item = _get_tv_bt_device(device_flags);
409         if (device_item) {
410                 *device_list = g_list_append(*device_list, device_item);
411                 debug_msg("Added TV bt device id(%d) type(%17s) direction(%d) state(%d) name(%s) vendor-id(%04x) product-id(%04x)",
412                                         device_item->id, device_item->type, device_item->io_direction, device_item->state,
413                                         device_item->name, device_item->vendor_id, device_item->product_id);
414         }
415 #endif /* TIZEN_TV */
416
417 cleanup:
418         if (result)
419                 g_variant_unref(result);
420
421         debug_fleave();
422         return ret;
423 }
424
425 int mm_sound_proxy_get_device_by_id(int device_id, mm_sound_device_t **device)
426 {
427         int ret = MM_ERROR_NONE;
428         GVariant *params = NULL, *result = NULL;
429         mm_sound_device_t* device_item = NULL;
430         const gchar *device_name_tmp = NULL, *device_type_tmp = NULL;
431
432         debug_fenter();
433
434         if (!device || device_id < 1) {
435                 debug_error("Invalid Parameter, device null or improper device id");
436                 return MM_ERROR_INVALID_ARGUMENT;
437         }
438
439         if ((params = g_variant_new("(i)", device_id)) == NULL) {
440                 debug_error("Construct Param for get device by id failed");
441                 return MM_ERROR_SOUND_INTERNAL;
442         }
443
444         if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_METHOD_GET_DEVICE_BY_ID, params, &result)) != MM_ERROR_NONE) {
445                 debug_error("get device by id failed");
446                 ret = MM_ERROR_SOUND_NO_DATA;
447                 goto cleanup;
448         }
449
450         if (result) {
451                 if ((device_item = g_malloc0(sizeof(mm_sound_device_t))) == NULL) {
452                         debug_error("Alloc device handle failed");
453                         ret = MM_ERROR_SOUND_INTERNAL;
454                         goto cleanup;
455                 }
456
457                 g_variant_get(result, "(i&sii&sii)",
458                                 &device_item->id, &device_type_tmp, &device_item->io_direction,
459                                 &device_item->state, &device_name_tmp,
460                                 &device_item->vendor_id, &device_item->product_id);
461                 MMSOUND_STRNCPY(device_item->name, device_name_tmp, MAX_DEVICE_NAME_NUM);
462                 MMSOUND_STRNCPY(device_item->type, device_type_tmp, MAX_DEVICE_TYPE_STR_LEN);
463                 debug_log("Get device id(%d) type(%17s) direction(%d) state(%d) name(%s) vendor-id(%04x) product-id(%04x)",
464                                 device_item->id, device_item->type, device_item->io_direction,
465                                 device_item->state, device_item->name,
466                                 device_item->vendor_id, device_item->product_id);
467                 device_item->stream_num = -1;
468                 *device = device_item;
469         } else {
470                 debug_error("reply null");
471                 ret = MM_ERROR_SOUND_INTERNAL;
472         }
473
474 cleanup:
475         if (result)
476                 g_variant_unref(result);
477
478         debug_fleave();
479         return ret;
480 }
481
482 int mm_sound_proxy_add_device_connected_callback(mm_sound_device_connected_wrapper_cb func, void *userdata, mm_sound_proxy_userdata_free freefunc, unsigned *subs_id)
483 {
484         int ret = MM_ERROR_NONE;
485         struct callback_data *cb_data;
486
487         debug_fenter();
488
489         CB_DATA_NEW(cb_data, func, userdata, freefunc);
490
491         if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_EVENT_DEVICE_CONNECTED, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE) {
492                 debug_error("add device connected callback failed");
493                 goto cleanup;
494         }
495
496         if ((ret = _notify_subscription(AUDIO_EVENT_DEVICE_CONNECTED, cb_data->subs_id, TRUE)) != MM_ERROR_NONE) {
497                 debug_error("failed to notify subscription of device connected event");
498                 goto cleanup;
499         }
500
501         *subs_id = cb_data->subs_id;
502
503 cleanup:
504         debug_fleave();
505         return ret;
506 }
507
508 int mm_sound_proxy_remove_device_connected_callback(unsigned subs_id)
509 {
510         int ret = MM_ERROR_NONE;
511         debug_fenter();
512
513         if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE) {
514                 debug_error("remove device connected callback failed");
515                 goto cleanup;
516         }
517
518         if ((ret = _notify_subscription(AUDIO_EVENT_DEVICE_CONNECTED, subs_id, FALSE)) != MM_ERROR_NONE)
519                 debug_error("failed to notify unsubscription of device connected event");
520
521 cleanup:
522         debug_fleave();
523         return ret;
524 }
525
526 int mm_sound_proxy_add_device_info_changed_callback(mm_sound_device_info_changed_wrapper_cb func, void* userdata, mm_sound_proxy_userdata_free freefunc, unsigned *subs_id)
527 {
528         int ret = MM_ERROR_NONE;
529         struct callback_data *cb_data;
530
531         debug_fenter();
532
533         CB_DATA_NEW(cb_data, func, userdata, freefunc);
534
535         if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_EVENT_DEVICE_INFO_CHANGED, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE)
536                 debug_error("Add device info changed callback failed");
537         else
538                 *subs_id = cb_data->subs_id;
539
540         debug_fleave();
541         return ret;
542 }
543
544 int mm_sound_proxy_remove_device_info_changed_callback(unsigned subs_id)
545 {
546         int ret = MM_ERROR_NONE;
547         debug_fenter();
548
549         if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE)
550                 debug_error("remove device info changed callback failed");
551
552         debug_fleave();
553         return ret;
554 }
555
556 int mm_sound_proxy_add_device_state_changed_callback(mm_sound_device_state_changed_wrapper_cb func, void* userdata, mm_sound_proxy_userdata_free freefunc, unsigned *subs_id)
557 {
558         int ret = MM_ERROR_NONE;
559         struct callback_data *cb_data;
560
561         debug_fenter();
562
563         CB_DATA_NEW(cb_data, func, userdata, freefunc);
564
565         if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_EVENT_DEVICE_STATE_CHANGED, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE)
566                 debug_error("Add device state changed callback failed");
567         else
568                 *subs_id = cb_data->subs_id;
569
570         debug_fleave();
571         return ret;
572 }
573
574 int mm_sound_proxy_remove_device_state_changed_callback(unsigned subs_id)
575 {
576         int ret = MM_ERROR_NONE;
577         debug_fenter();
578
579         if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE)
580                 debug_error("remove device state changed callback failed");
581
582         debug_fleave();
583         return ret;
584 }
585
586 int mm_sound_proxy_add_device_running_changed_callback(mm_sound_device_running_changed_wrapper_cb func, void* userdata, mm_sound_proxy_userdata_free freefunc, unsigned *subs_id)
587 {
588         int ret = MM_ERROR_NONE;
589         struct callback_data *cb_data;
590
591         debug_fenter();
592
593         CB_DATA_NEW(cb_data, func, userdata, freefunc);
594
595         if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_EVENT_DEVICE_RUNNING_CHANGED, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE)
596                 debug_error("Add device running changed callback failed");
597         else
598                 *subs_id = cb_data->subs_id;
599
600         debug_fleave();
601         return ret;
602 }
603
604 int mm_sound_proxy_remove_device_running_changed_callback(unsigned subs_id)
605 {
606         int ret = MM_ERROR_NONE;
607         debug_fenter();
608
609         if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE)
610                 debug_error("remove device running changed callback failed");
611
612         debug_fleave();
613         return ret;
614 }
615
616 int mm_sound_proxy_set_volume_by_type(const char *volume_type, const unsigned volume_level)
617 {
618         int ret = MM_ERROR_NONE;
619         const char *reply = NULL, *direction = "out";
620         GVariant *params = NULL, *result = NULL;
621
622         debug_fenter();
623
624         if ((params = g_variant_new("(ssu)", direction, volume_type, volume_level)) == NULL) {
625                 debug_error("Construct Param for method call failed");
626                 return MM_ERROR_SOUND_INTERNAL;
627         }
628
629         if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_STREAM_MANAGER, AUDIO_METHOD_SET_VOLUME_LEVEL, params, &result)) != MM_ERROR_NONE) {
630                 debug_error("dbus set volume by type failed");
631                 goto cleanup;
632         }
633
634         if (result) {
635                 g_variant_get(result, "(&s)",  &reply);
636                 debug_log("reply : %s", reply);
637                 if (!strcmp(reply, "STREAM_MANAGER_RETURN_ERROR_INVALID_ARGUMENT"))
638                         ret = MM_ERROR_INVALID_ARGUMENT;
639                 else if (strcmp(reply, "STREAM_MANAGER_RETURN_OK"))
640                         ret = MM_ERROR_SOUND_INTERNAL;
641         } else {
642                 debug_error("reply null");
643                 ret = MM_ERROR_SOUND_INTERNAL;
644         }
645
646 cleanup:
647         if (result)
648                 g_variant_unref(result);
649
650         debug_fleave();
651         return ret;
652 }
653
654 int mm_sound_proxy_add_volume_changed_callback(mm_sound_volume_changed_wrapper_cb func, void* userdata, mm_sound_proxy_userdata_free freefunc, unsigned *subs_id)
655 {
656         int ret = MM_ERROR_NONE;
657         struct callback_data *cb_data;
658
659         debug_fenter();
660
661         CB_DATA_NEW(cb_data, func, userdata, freefunc);
662
663         if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_STREAM_MANAGER, AUDIO_EVENT_VOLUME_CHANGED, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE)
664                 debug_error("Add Volume changed callback failed");
665         else
666                 *subs_id = cb_data->subs_id;
667
668         debug_fleave();
669
670         return ret;
671 }
672
673 int mm_sound_proxy_remove_volume_changed_callback(unsigned subs_id)
674 {
675         int ret = MM_ERROR_NONE;
676         debug_fenter();
677
678         if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE)
679                 debug_error("Remove Volume changed callback failed");
680
681         debug_fleave();
682         return ret;
683 }
684
685 int mm_sound_proxy_add_ducking_state_changed_callback(mm_sound_ducking_state_changed_wrapper_cb func, void* userdata, mm_sound_proxy_userdata_free freefunc, unsigned *subs_id)
686 {
687         int ret = MM_ERROR_NONE;
688         struct callback_data *cb_data;
689
690         debug_fenter();
691
692         CB_DATA_NEW(cb_data, func, userdata, freefunc);
693
694         if ((ret = mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_STREAM_MANAGER, AUDIO_EVENT_DUCKING_STATE_CHANGED, dbus_callback, cb_data, simple_callback_data_free_func, &cb_data->subs_id)) != MM_ERROR_NONE)
695                 debug_error("Add Ducking State changed callback failed");
696         else
697                 *subs_id = cb_data->subs_id;
698
699         debug_fleave();
700
701         return ret;
702 }
703
704 int mm_sound_proxy_remove_ducking_state_changed_callback(unsigned subs_id)
705 {
706         int ret = MM_ERROR_NONE;
707         debug_fenter();
708
709         if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE)
710                 debug_error("Remove Ducking State changed callback failed");
711
712         debug_fleave();
713         return ret;
714 }
715
716 int mm_sound_proxy_set_mute_by_type(const char *volume_type, bool mute)
717 {
718         int ret = MM_ERROR_NONE;
719         const char *reply = NULL, *direction = "out";
720         GVariant *params = NULL, *result = NULL;
721
722         debug_fenter();
723
724         if ((params = g_variant_new("(ssu)", direction, volume_type, (unsigned int)mute)) == NULL) {
725                 debug_error("Construct Param for method call failed");
726                 return MM_ERROR_SOUND_INTERNAL;
727         }
728
729         if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_STREAM_MANAGER, AUDIO_METHOD_SET_MUTE, params, &result)) != MM_ERROR_NONE) {
730                 debug_error("dbus set mute by type failed");
731                 goto cleanup;
732         }
733
734         if (result) {
735                 g_variant_get(result, "(&s)",  &reply);
736                 debug_log("reply : %s", reply);
737                 if (strcmp(reply, "STREAM_MANAGER_RETURN_OK"))
738                         ret = MM_ERROR_SOUND_INTERNAL;
739         } else {
740                 debug_error("reply null");
741                 ret = MM_ERROR_SOUND_INTERNAL;
742         }
743
744 cleanup:
745         if (result)
746                 g_variant_unref(result);
747
748         debug_fleave();
749         return ret;
750 }
751
752 int mm_sound_proxy_set_filter_by_type(const char *stream_type, const char *filter_name, const char *filter_parameters, const char *filter_group) {
753         int ret = MM_ERROR_NONE;
754         const char *reply = NULL;
755         GVariant *params = NULL, *result = NULL;
756
757         debug_fenter();
758
759         if ((params = g_variant_new("(ssss)", filter_name, filter_parameters, filter_group, stream_type)) == NULL) {
760                 debug_error("construct param for method call failed");
761                 return MM_ERROR_SOUND_INTERNAL;
762         }
763
764         if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_STREAM_MANAGER, AUDIO_METHOD_SET_FILTER, params, &result)) != MM_ERROR_NONE) {
765                 debug_error("dbus set filter by type failed");
766                 goto cleanup;
767         }
768
769         /* stream-manager always returns a string as return value */
770         if (result) {
771                 g_variant_get(result, "(&s)", &reply);
772                 debug_log("reply : %s", reply);
773                 if (strcmp(reply, "STREAM_MANAGER_RETURN_OK"))
774                         ret = MM_ERROR_SOUND_INTERNAL;
775         } else {
776                 debug_error("reply null");
777                 ret = MM_ERROR_SOUND_INTERNAL;
778         }
779
780 cleanup:
781         if (result)
782                 g_variant_unref(result);
783
784         debug_fleave();
785         return ret;
786 }
787
788 int mm_sound_proxy_unset_filter_by_type(const char *stream_type)
789 {
790         int ret = MM_ERROR_NONE;
791         const char *reply = NULL;
792         GVariant *params = NULL, *result = NULL;
793
794         debug_fenter();
795
796         if ((params = g_variant_new("(s)", stream_type)) == NULL) {
797                 debug_error("construct param for method call failed");
798                 return MM_ERROR_SOUND_INTERNAL;
799         }
800
801         if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_STREAM_MANAGER, AUDIO_METHOD_UNSET_FILTER, params, &result)) != MM_ERROR_NONE) {
802                 debug_error("dbus unset filter by type failed");
803                 goto cleanup;
804         }
805
806         /* stream-manager always returns a string as return value */
807         if (result) {
808                 g_variant_get(result, "(&s)", &reply);
809                 debug_log("reply : %s", reply);
810                 if (strcmp(reply, "STREAM_MANAGER_RETURN_OK"))
811                         ret = MM_ERROR_SOUND_INTERNAL;
812         } else {
813                 debug_error("reply null");
814                 ret = MM_ERROR_SOUND_INTERNAL;
815         }
816
817 cleanup:
818         if (result)
819                 g_variant_unref(result);
820
821         debug_fleave();
822         return ret;
823 }
824
825 int mm_sound_proxy_control_filter_by_type(const char *stream_type, const char *filter_name, const char *filter_controls)
826 {
827         int ret = MM_ERROR_NONE;
828         const char *reply = NULL;
829         GVariant *params = NULL, *result = NULL;
830
831         debug_fenter();
832
833         if ((params = g_variant_new("(sss)", filter_name, filter_controls, stream_type)) == NULL) {
834                 debug_error("construct param for method call failed");
835                 return MM_ERROR_SOUND_INTERNAL;
836         }
837
838         if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_STREAM_MANAGER, AUDIO_METHOD_CONTROL_FILTER, params, &result)) != MM_ERROR_NONE) {
839                 debug_error("dbus control filter by type failed");
840                 goto cleanup;
841         }
842         /* stream-manager always returns a string as return value */
843         if (result) {
844                 g_variant_get(result, "(&s)", &reply);
845                 debug_log("reply : %s", reply);
846                 if (strcmp(reply, "STREAM_MANAGER_RETURN_OK"))
847                         ret = MM_ERROR_SOUND_INTERNAL;
848         } else {
849                 debug_error("reply null");
850                 ret = MM_ERROR_SOUND_INTERNAL;
851         }
852
853 cleanup:
854         if (result)
855                 g_variant_unref(result);
856
857         debug_fleave();
858         return ret;
859 }
860
861 int mm_sound_proxy_register_focus(int index, const char *stream_type, int *id)
862 {
863         int ret = MM_ERROR_NONE;
864         int pid = g_focus_sound_handle[index].focus_pid;
865         int client_fd = 0;
866
867 #ifndef TIZEN_TV
868         debug_fenter();
869 #endif
870         ret = mm_sound_focus_socket_register(pid, stream_type, &client_fd, id);
871         if (ret) {
872                 debug_error("failed to mm_sound_focus_socket_register(), ret[0x%x]", ret);
873         } else {
874                 g_focus_sound_handle[index].client_fd = client_fd;
875                 g_focus_sound_handle[index].handle = *id;
876         }
877
878         debug_fleave();
879
880         return ret;
881 }
882
883 int mm_sound_proxy_unregister_focus(int index)
884 {
885         int ret = MM_ERROR_NONE;
886         int pid = g_focus_sound_handle[index].focus_pid;
887         int client_fd = g_focus_sound_handle[index].client_fd;
888         int id = g_focus_sound_handle[index].handle;
889
890         debug_fenter();
891
892         ret = mm_sound_focus_socket_unregister(pid, client_fd, id);
893         if (ret)
894                 debug_error("failed to mm_sound_focus_socket_unregister(), client_fd[%d], id[%d], ret[0x%x]", client_fd, id, ret);
895
896         debug_fleave();
897
898         return ret;
899 }
900
901 int mm_sound_proxy_set_focus_reacquisition(int index, bool reacquisition)
902 {
903         int ret = MM_ERROR_NONE;
904         int pid = g_focus_sound_handle[index].focus_pid;
905         int client_fd = g_focus_sound_handle[index].client_fd;
906         int id = g_focus_sound_handle[index].handle;
907
908         debug_fenter();
909
910         ret = mm_sound_focus_socket_set_reacquisition(pid, client_fd, id, reacquisition);
911         if (ret)
912                 debug_error("failed to mm_sound_focus_socket_set_reacquisition(), ret[0x%x]", ret);
913
914         debug_fleave();
915         return ret;
916 }
917
918 int mm_sound_proxy_get_acquired_focus_stream_type(int focus_type, char **stream_type, int *option, char **ext_info)
919 {
920         int ret = MM_ERROR_NONE;
921
922         debug_fenter();
923
924         ret = mm_sound_focus_socket_get_acquired_focus_stream_type(focus_type, stream_type, option, ext_info);
925         if (ret)
926                 debug_error("failed to mm_sound_focus_socket_get_acquired_focus_stream_type(), ret[0x%x]", ret);
927
928         debug_fleave();
929         return ret;
930 }
931
932 int mm_sound_proxy_acquire_focus(int index, mm_sound_focus_type_e type, int option, const char *ext_info)
933 {
934         int ret = MM_ERROR_NONE;
935         bool is_in_focus_cb_thread = false;
936         int pid = g_focus_sound_handle[index].focus_pid;
937         int client_fd = g_focus_sound_handle[index].client_fd;
938         int id = g_focus_sound_handle[index].handle;
939
940         debug_fenter();
941
942         mm_sound_client_is_focus_cb_thread(g_thread_self(), &is_in_focus_cb_thread, NULL);
943         if (!is_in_focus_cb_thread) {
944                 if ((ret = mm_sound_focus_socket_acquire(pid, client_fd, id,
945                                                                                                 type, option, ext_info ? ext_info : "", true)))
946                         debug_error("failed to mm_sound_focus_socket_acquire(), ret[0x%x]", ret);
947         } else {
948                 GVariant *params = NULL, *result = NULL;
949
950                 if ((params = g_variant_new("(iiiis)", pid, id, type, option, ext_info ? ext_info : "")) == NULL) {
951                         debug_error("Construct Param for method call failed");
952                         return MM_ERROR_SOUND_INTERNAL;
953                 }
954
955                 if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_ACQUIRE_FOCUS, params, &result)) != MM_ERROR_NONE)
956                         debug_error("dbus acquire focus failed");
957
958                 if (result)
959                         g_variant_unref(result);
960         }
961
962         debug_fleave();
963
964         return ret;
965 }
966
967 int mm_sound_proxy_release_focus(int index, mm_sound_focus_type_e type, int option, const char *ext_info)
968 {
969         int ret = MM_ERROR_NONE;
970         bool is_in_focus_cb_thread = false;
971         int pid = g_focus_sound_handle[index].focus_pid;
972         int client_fd = g_focus_sound_handle[index].client_fd;
973         int id = g_focus_sound_handle[index].handle;
974
975         debug_fenter();
976
977         mm_sound_client_is_focus_cb_thread(g_thread_self(), &is_in_focus_cb_thread, NULL);
978         if (!is_in_focus_cb_thread) {
979                 if ((ret = mm_sound_focus_socket_release(pid, client_fd, id, type, option, ext_info ? ext_info : "", true)))
980                         debug_error("failed to mm_sound_focus_socket_release(), ret[0x%x]", ret);
981         } else {
982                 GVariant *params = NULL, *result = NULL;
983
984                 if ((params = g_variant_new("(iiiis)", pid, id, type, option, ext_info ? ext_info : "")) == NULL) {
985                         debug_error("Construct Param for method call failed");
986                         return MM_ERROR_SOUND_INTERNAL;
987                 }
988
989                 if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_RELEASE_FOCUS, params, &result)) != MM_ERROR_NONE)
990                         debug_error("dbus release focus failed");
991
992                 if (result)
993                         g_variant_unref(result);
994         }
995
996         debug_fleave();
997         return ret;
998 }
999
1000 int mm_sound_proxy_update_stream_focus_status(int focus_id, unsigned int status)
1001 {
1002         int ret = MM_ERROR_NONE;
1003         const char *reply = NULL;
1004         GVariant *params = NULL, *result = NULL;
1005
1006         debug_fenter();
1007
1008         if ((params = g_variant_new("(iu)", focus_id, status)) == NULL) {
1009                 debug_error("Construct Param for method call failed");
1010                 return MM_ERROR_SOUND_INTERNAL;
1011         }
1012
1013         if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_STREAM_MANAGER, AUDIO_METHOD_UPDATE_STREAM_FOCUS_STATUS, params, &result)) != MM_ERROR_NONE) {
1014                 debug_error("dbus set volume by type failed");
1015                 goto cleanup;
1016         }
1017
1018         /* stream-manager always returns a string as return value */
1019         if (result) {
1020                 g_variant_get(result, "(&s)", &reply);
1021                 debug_log("reply : %s", reply);
1022                 if (strcmp(reply, "STREAM_MANAGER_RETURN_OK"))
1023                         ret = MM_ERROR_SOUND_INTERNAL;
1024         } else {
1025                 debug_error("reply null");
1026                 ret = MM_ERROR_SOUND_INTERNAL;
1027         }
1028
1029 cleanup:
1030         if (result)
1031                 g_variant_unref(result);
1032
1033         debug_fleave();
1034         return ret;
1035 }
1036
1037 int mm_sound_proxy_deliver_focus(int src_index, int dst_index, mm_sound_focus_type_e focus_type)
1038 {
1039         int ret = MM_ERROR_NONE;
1040         int pid = g_focus_sound_handle[src_index].focus_pid;
1041         int src_client_fd = g_focus_sound_handle[src_index].client_fd;
1042         int src_server_fd = g_focus_sound_handle[src_index].handle;
1043         int dst_client_fd = g_focus_sound_handle[dst_index].client_fd;
1044         int dst_server_fd = g_focus_sound_handle[dst_index].handle;
1045
1046         debug_fenter();
1047
1048         ret = mm_sound_focus_socket_deliver(pid, src_client_fd, src_server_fd, dst_client_fd, dst_server_fd, focus_type);
1049         if (ret)
1050                 debug_error("failed to mm_sound_focus_socket_deliver(), ret[0x%x]", ret);
1051
1052         debug_fleave();
1053         return ret;
1054 }
1055
1056 int mm_sound_proxy_add_focus_watch_callback(int index, mm_sound_focus_type_e type)
1057 {
1058         int ret = MM_ERROR_NONE;
1059         int pid = g_focus_sound_handle[index].focus_pid;
1060         int id = 0;
1061         int client_fd = 0;
1062
1063         debug_fenter();
1064
1065         ret = mm_sound_focus_socket_add_watch_cb(pid, type, &client_fd, &id);
1066         if (ret) {
1067                 debug_error("failed to mm_sound_focus_socket_add_watch_cb(), ret[0x%x]", ret);
1068         } else {
1069                 g_focus_sound_handle[index].handle = id;
1070                 g_focus_sound_handle[index].client_fd = client_fd;
1071         }
1072
1073         debug_fleave();
1074
1075         return ret;
1076 }
1077
1078 int mm_sound_proxy_remove_focus_watch_callback(int index)
1079 {
1080         int ret = MM_ERROR_NONE;
1081         int pid = g_focus_sound_handle[index].focus_pid;
1082         int client_fd = g_focus_sound_handle[index].client_fd;
1083         int id = g_focus_sound_handle[index].handle;
1084
1085         debug_fenter();
1086
1087         ret = mm_sound_focus_socket_remove_watch_cb(pid, client_fd, id);
1088         if (ret)
1089                 debug_error("failed to mm_sound_focus_socket_remove_watch_cb(), ret[0x%x]", ret);
1090
1091         debug_fleave();
1092
1093         return ret;
1094 }
1095
1096 int mm_sound_proxy_initialize(void)
1097 {
1098         int ret = MM_ERROR_NONE;
1099
1100         debug_fenter();
1101         debug_fleave();
1102
1103         return ret;
1104 }
1105
1106 int mm_sound_proxy_finalize(void)
1107 {
1108         int ret = MM_ERROR_NONE;
1109
1110         debug_fenter();
1111         debug_fleave();
1112
1113         return ret;
1114 }