Fix memory leak due to missing unref on returned g_variant value
[platform/core/multimedia/libmm-sound.git] / server / mm_sound_mgr_ipc_dbus.c
1
2 #include <string.h>
3
4 #include <mm_error.h>
5 #include <mm_debug.h>
6
7 #include <gio/gio.h>
8
9 #include "include/mm_sound_mgr_ipc_dbus.h"
10 #include "include/mm_sound_mgr_ipc.h"
11 #include "../include/mm_sound_dbus.h"
12
13
14 #define BUS_NAME_SOUND_SERVER "org.tizen.SoundServer"
15 #define OBJECT_SOUND_SERVER "/org/tizen/SoundServer1"
16 #define INTERFACE_SOUND_SERVER "org.tizen.SoundServer1"
17
18 /* workaround for AF volume gain tuning */
19 #define PROC_DBUS_OBJECT        "/Org/Tizen/ResourceD/Process"
20 #define PROC_DBUS_INTERFACE     "org.tizen.resourced.process"
21 #define PROC_DBUS_METHOD        "ProcExclude"
22
23 /* Introspection data for the service we are exporting */
24 static const gchar introspection_xml[] =
25   "<node>"
26   "  <interface name='org.tizen.SoundServer1'>"
27   "    <method name='MethodTest1'>"
28   "      <arg type='i' name='num1' direction='in'/>"
29   "      <arg type='i' name='num2' direction='in'/>"
30   "      <arg type='i' name='multiple' direction='out'/>"
31   "    </method>"
32   "    <method name='GetBTA2DPStatus'>"
33   "      <arg type='b' name='is_bt_on' direction='out'/>"
34   "      <arg type='s' name='bt_name' direction='out'/>"
35   "    </method>"
36   "    <method name='PlayFileStart'>"
37   "      <arg type='s' name='filename' direction='in'/>"
38   "      <arg type='i' name='tone' direction='in'/>"
39   "      <arg type='i' name='repeat' direction='in'/>"
40   "      <arg type='i' name='volume' direction='in'/>"
41   "      <arg type='i' name='vol_config' direction='in'/>"
42   "      <arg type='i' name='priority' direction='in'/>"
43   "      <arg type='i' name='session_type' direction='in'/>"
44   "      <arg type='i' name='session_option' direction='in'/>"
45   "      <arg type='i' name='client_pid' direction='in'/>"
46   "      <arg type='i' name='handle_route' direction='in'/>"
47   "      <arg type='b' name='enable_session' direction='in'/>"
48   "      <arg type='s' name='stream_type' direction='in'/>"
49   "      <arg type='i' name='stream_index' direction='in'/>"
50   "      <arg type='i' name='handle' direction='out'/>"
51   "    </method>"
52   "        <method name='PlayFileStartWithStreamInfo'>"
53   "          <arg type='s' name='filename' direction='in'/>"
54   "          <arg type='i' name='repeat' direction='in'/>"
55   "          <arg type='i' name='volume' direction='in'/>"
56   "          <arg type='i' name='priority' direction='in'/>"
57   "          <arg type='i' name='client_pid' direction='in'/>"
58   "          <arg type='i' name='handle_route' direction='in'/>"
59   "          <arg type='s' name='stream_type' direction='in'/>"
60   "          <arg type='i' name='stream_index' direction='in'/>"
61   "          <arg type='i' name='handle' direction='out'/>"
62   "        </method>"
63   "    <method name='PlayFileStop'>"
64   "      <arg type='i' name='handle' direction='in'/>"
65   "    </method>"
66 #ifdef FOCUS_INTEGRATION
67   "    <method name='ClearFocus'>"
68   "      <arg type='i' name='pid' direction='in'/>"
69   "    </method>"
70 #endif
71   "    <method name='PlayDTMF'>"
72   "      <arg type='i' name='tone' direction='in'/>"
73   "      <arg type='i' name='repeat' direction='in'/>"
74   "      <arg type='i' name='volume' direction='in'/>"
75   "      <arg type='i' name='vol_config' direction='in'/>"
76   "      <arg type='i' name='session_type' direction='in'/>"
77   "      <arg type='i' name='session_option' direction='in'/>"
78   "      <arg type='i' name='client_pid' direction='in'/>"
79   "      <arg type='b' name='enable_session' direction='in'/>"
80   "          <arg type='s' name='stream_type' direction='in'/>"
81   "          <arg type='i' name='stream_index' direction='in'/>"
82   "      <arg type='i' name='handle' direction='out'/>"
83   "    </method>"
84   "        <method name='PlayDTMFWithStreamInfo'>"
85   "          <arg type='i' name='tone' direction='in'/>"
86   "          <arg type='i' name='repeat' direction='in'/>"
87   "          <arg type='i' name='volume' direction='in'/>"
88   "          <arg type='i' name='client_pid' direction='in'/>"
89   "          <arg type='s' name='stream_type' direction='in'/>"
90   "          <arg type='i' name='stream_index' direction='in'/>"
91   "          <arg type='i' name='handle' direction='out'/>"
92   "        </method>"
93   "    <method name='GetConnectedDeviceList'>"
94   "      <arg type='i' name='device_mask' direction='in'/>"
95   "      <arg type='a(iiiis)' name='device_list' direction='out'/>"
96   "    </method>"
97   "  </interface>"
98   "</node>";
99 static GDBusConnection* conn_g;
100
101 static void handle_method_play_file_start(GDBusMethodInvocation* invocation);
102 static void handle_method_play_file_start_with_stream_info(GDBusMethodInvocation* invocation);
103 static void handle_method_play_file_stop(GDBusMethodInvocation* invocation);
104 static void handle_method_play_dtmf(GDBusMethodInvocation* invocation);
105 static void handle_method_play_dtmf_with_stream_info(GDBusMethodInvocation* invocation);
106 #ifdef FOCUS_INTEGRATION
107 static void handle_method_clear_focus(GDBusMethodInvocation* invocation);
108 #endif
109 static void handle_method_test(GDBusMethodInvocation* invocation);
110 static void handle_method_get_connected_device_list(GDBusMethodInvocation* invocation);
111
112 /* Currently , Just using method's name and handler */
113 /* TODO : generate introspection xml automatically, with these value include argument and reply */
114 /* TODO : argument check with these information */
115 /* TODO : divide object and interface with features (ex. play, path, device) */
116 static mm_sound_dbus_method_intf_t methods[AUDIO_METHOD_MAX] = {
117         [AUDIO_METHOD_TEST] = {
118                 .info = {
119                         .name = "MethodTest1",
120                 },
121                 .handler = handle_method_test
122         },
123         [AUDIO_METHOD_PLAY_FILE_START] = {
124                 .info = {
125                         .name = "PlayFileStart",
126                 },
127                 .handler = handle_method_play_file_start
128         },
129         [AUDIO_METHOD_PLAY_FILE_START_WITH_STREAM_INFO] = {
130                 .info = {
131                         .name = "PlayFileStartWithStreamInfo",
132                 },
133                 .handler = handle_method_play_file_start_with_stream_info
134         },
135         [AUDIO_METHOD_PLAY_FILE_STOP] = {
136                 .info = {
137                         .name = "PlayFileStop",
138                 },
139                 .handler = handle_method_play_file_stop
140         },
141 #ifdef FOCUS_INTEGRATION
142         [AUDIO_METHOD_CLEAR_FOCUS] = {
143                 .info = {
144                         .name = "ClearFocus",
145                 },
146                 .handler = handle_method_clear_focus
147         },
148 #endif
149         [AUDIO_METHOD_PLAY_DTMF] = {
150                 .info = {
151                         .name = "PlayDTMF",
152                 },
153                 .handler = handle_method_play_dtmf
154         },
155         [AUDIO_METHOD_PLAY_DTMF_WITH_STREAM_INFO] = {
156                 .info = {
157                         .name = "PlayDTMFWithStreamInfo",
158                 },
159                 .handler = handle_method_play_dtmf_with_stream_info
160         },
161         [AUDIO_METHOD_GET_CONNECTED_DEVICE_LIST] = {
162                 .info = {
163                         .name = "GetConnectedDeviceList",
164                 },
165                 .handler = handle_method_get_connected_device_list
166         },
167 };
168
169 static GDBusNodeInfo *introspection_data = NULL;
170 guint sound_server_owner_id ;
171
172 /*
173         For pass error code with 'g_dbus_method_invocation_return_error'
174         We have to use some glib features like GError, GQuark
175 */
176 /* Only For error types which is currently being used in server-side */
177 static const GDBusErrorEntry mm_sound_error_entries[] =
178 {
179         {MM_ERROR_OUT_OF_MEMORY, "org.tizen.multimedia.OutOfMemory"},
180         {MM_ERROR_OUT_OF_STORAGE, "org.tizen.multimedia.OutOfStorage"},
181         {MM_ERROR_INVALID_ARGUMENT, "org.tizen.multimedia.InvalidArgument"},
182         {MM_ERROR_POLICY_INTERNAL, "org.tizen.multimedia.PolicyInternal"},
183         {MM_ERROR_NOT_SUPPORT_API, "org.tizen.multimedia.NotSupportAPI"},
184         {MM_ERROR_POLICY_BLOCKED, "org.tizen.multimedia.PolicyBlocked"},
185         {MM_ERROR_END_OF_FILE, "org.tizen.multimedia.EndOfFile"},
186         {MM_ERROR_COMMON_OUT_OF_RANGE, "org.tizen.multimedia.common.OutOfRange"},
187         {MM_ERROR_COMMON_UNKNOWN, "org.tizen.multimedia.common.Unknown"},
188         {MM_ERROR_COMMON_NO_FREE_SPACE, "org.tizen.multimedia.common.NoFreeSpace"},
189         {MM_ERROR_SOUND_INTERNAL, "org.tizen.multimedia.audio.Internal"},
190         {MM_ERROR_SOUND_INVALID_STATE, "org.tizen.multimedia.audio.InvalidState"},
191         {MM_ERROR_SOUND_NO_FREE_SPACE, "org.tizen.multimedia.audio.NoFreeSpace"},
192         {MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE, "org.tizen.multimedia.audio.UnsupportedMediaType"},
193         {MM_ERROR_SOUND_INVALID_POINTER, "org.tizen.multimedia.audio.InvalidPointer"},
194         {MM_ERROR_SOUND_INVALID_FILE, "org.tizen.multimedia.audio.InvalidFile"},
195         {MM_ERROR_SOUND_FILE_NOT_FOUND, "org.tizen.multimedia.audio.FileNotFound"},
196         {MM_ERROR_SOUND_NO_DATA, "org.tizen.multimedia.audio.NoData"},
197         {MM_ERROR_SOUND_INVALID_PATH, "org.tizen.multimedia.audio.InvalidPath"},
198 };
199
200 static const char* _convert_error_code(int err_code)
201 {
202         int i = 0;
203
204         for (i = 0; i < G_N_ELEMENTS(mm_sound_error_entries); i++) {
205                 if (err_code == mm_sound_error_entries[i].error_code) {
206                         return mm_sound_error_entries[i].dbus_error_name;
207                 }
208         }
209
210         return "org.tizen.multimedia.common.Unknown";
211 }
212
213 static int mm_sound_mgr_ipc_dbus_send_signal(audio_event_t event, GVariant *parameter)
214 {
215         if(mm_sound_dbus_emit_signal(AUDIO_PROVIDER_SOUND_SERVER, event, parameter) != MM_ERROR_NONE) {
216                 debug_error("Sound Server Emit signal failed");
217                 return MM_ERROR_SOUND_INTERNAL;
218         }
219         return MM_ERROR_NONE;
220 }
221
222 static int _get_sender_pid(GDBusMethodInvocation* invocation)
223 {
224         GVariant* value;
225         guint pid = 0;
226         const gchar* sender;
227         GDBusConnection * connection = NULL;
228         GError* err = NULL;
229
230         connection = g_dbus_method_invocation_get_connection(invocation);
231         sender = g_dbus_method_invocation_get_sender(invocation);
232
233         debug_error("connection = %p, sender = %s", connection, sender);
234
235         value = g_dbus_connection_call_sync(connection, "org.freedesktop.DBus", "/org/freedesktop/DBus",
236                                                                                 "org.freedesktop.DBus", "GetConnectionUnixProcessID",
237                                                                                 g_variant_new("(s)", sender, NULL), NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
238         if (value) {
239                 g_variant_get(value, "(u)", &pid);
240                 debug_msg("Sender PID = [%d]", pid);
241                 g_variant_unref(value);
242         } else {
243                 debug_error("err code = %d, err msg = %s", err->code, err->message);
244         }
245         return pid;
246 }
247
248 static void _method_call_return_value(GDBusMethodInvocation *invocation, GVariant *params)
249 {
250         const char *method_name;
251         method_name = g_dbus_method_invocation_get_method_name(invocation);
252         debug_msg("Method Call '%s' success", method_name);
253         g_dbus_method_invocation_return_value(invocation, params);
254 }
255 static void _method_call_return_error(GDBusMethodInvocation *invocation, int ret)
256 {
257         const char *err_name, *method_name;
258         err_name = _convert_error_code(ret);
259         method_name = g_dbus_method_invocation_get_method_name(invocation);
260         debug_error("Method Call '%s' failed, err '%s(%X)'", method_name, err_name, ret);
261         g_dbus_method_invocation_return_dbus_error(invocation, err_name, "failed");
262 }
263
264 static void handle_method_test(GDBusMethodInvocation* invocation)
265 {
266         int ret = MM_ERROR_NONE;
267         int val = 0, val2 = 0;
268         GVariant *params = NULL;
269
270         debug_fenter();
271
272         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
273                 debug_error("Parameter for Method is NULL");
274                 ret = MM_ERROR_SOUND_INTERNAL;
275                 goto send_reply;
276         }
277
278         g_variant_get(params, "(ii)", &val, &val2);
279         debug_log("Got value : %d , %d", val, val2);
280
281         if ((ret = mm_sound_mgr_ipc_dbus_send_signal(AUDIO_EVENT_TEST, g_variant_new("(i)", val+val2))) != MM_ERROR_NONE) {
282                 debug_error("signal send error : %X", ret);
283         } else {
284                 debug_error("signal send success");
285         }
286
287 send_reply:
288         if (ret == MM_ERROR_NONE) {
289                 _method_call_return_value(invocation, g_variant_new("(i)", val * val2));
290         } else {
291                 ret = MM_ERROR_INVALID_ARGUMENT;
292                 _method_call_return_error(invocation,  ret);
293         }
294
295         debug_fleave();
296 }
297
298 static void handle_method_play_file_start(GDBusMethodInvocation* invocation)
299 {
300         gchar* filename = NULL;
301         char *stream_type = NULL;
302         gint32 ret = MM_ERROR_NONE, slotid = 0;
303         gint32 tone = 0, repeat = 0, volume = 0, vol_config = 0, priority = 0;
304         gint32 session_type = 0, session_option = 0, pid = 0, handle_route =0, stream_index = 0;
305         gboolean enable_session = 0;
306         GVariant *params = NULL;
307
308         debug_fenter();
309
310         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
311                 debug_error("Parameter for Method is NULL");
312                 ret = MM_ERROR_SOUND_INTERNAL;
313                 goto send_reply;
314         }
315
316         g_variant_get(params, "(siiiiiiiiibsi)", &filename, &tone, &repeat, &volume,
317                       &vol_config, &priority, &session_type, &session_option, &pid, &handle_route, &enable_session, &stream_type, &stream_index);
318         if (!filename) {
319             debug_error("filename null");
320             ret = MM_ERROR_SOUND_INTERNAL;
321             goto send_reply;
322         }
323         ret = _MMSoundMgrIpcPlayFile(filename, tone, repeat, volume, vol_config, priority,
324                                 session_type, session_option, _get_sender_pid(invocation), handle_route, enable_session, &slotid, stream_type, stream_index);
325
326 send_reply:
327         if (ret == MM_ERROR_NONE) {
328                 _method_call_return_value(invocation, g_variant_new("(i)", slotid));
329         } else {
330                 _method_call_return_error(invocation, ret);
331         }
332
333         debug_fleave();
334 }
335
336 static void handle_method_play_file_start_with_stream_info(GDBusMethodInvocation* invocation)
337 {
338         gchar* filename = NULL;
339         char *stream_type = NULL;
340         gint32 ret = MM_ERROR_NONE, slotid = 0;
341         gint32 repeat = 0, volume = 0, priority = 0, pid = 0, handle_route =0, stream_index = 0;
342         GVariant *params = NULL;
343
344         debug_fenter();
345
346         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
347                 debug_error("Parameter for Method is NULL");
348                 ret = MM_ERROR_SOUND_INTERNAL;
349                 goto send_reply;
350         }
351
352         g_variant_get(params, "(siiiiisi)", &filename, &repeat, &volume,
353                       &priority, &pid, &handle_route, &stream_type, &stream_index);
354         if (!filename) {
355             debug_error("filename null");
356             ret = MM_ERROR_SOUND_INTERNAL;
357             goto send_reply;
358         }
359         ret = _MMSoundMgrIpcPlayFileWithStreamInfo(filename, repeat, volume, priority,
360                                 _get_sender_pid(invocation), handle_route, &slotid, stream_type, stream_index);
361
362 send_reply:
363         if (ret == MM_ERROR_NONE) {
364                 _method_call_return_value(invocation, g_variant_new("(i)", slotid));
365         } else {
366                 _method_call_return_error(invocation, ret);
367         }
368
369         debug_fleave();
370 }
371
372 static void handle_method_play_dtmf(GDBusMethodInvocation* invocation)
373 {
374         int ret = MM_ERROR_NONE, slotid = 0;
375         int tone = 0, repeat = 0, volume = 0, vol_config = 0, session_type = 0, session_option = 0, pid = 0, stream_index = 0;
376         char* stream_type = NULL;
377         gboolean enable_session = 0;
378         GVariant *params = NULL;
379
380         debug_fenter();
381
382         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
383                 debug_error("Parameter for Method is NULL");
384                 ret = MM_ERROR_SOUND_INTERNAL;
385                 goto send_reply;
386         }
387
388         g_variant_get(params, "(iiiiiiibsi)", &tone, &repeat, &volume,
389                       &vol_config, &session_type, &session_option, &pid, &enable_session, &stream_type, &stream_index);
390         debug_error("volume - %d", volume);
391         ret = _MMSoundMgrIpcPlayDTMF(tone, repeat, volume, vol_config,
392                                      session_type, session_option, _get_sender_pid(invocation), enable_session, &slotid, stream_type, stream_index);
393
394 send_reply:
395         if (ret == MM_ERROR_NONE) {
396                 _method_call_return_value(invocation, g_variant_new("(i)", slotid));
397         } else {
398                 _method_call_return_error(invocation, ret);
399         }
400
401
402         debug_fleave();
403 }
404
405 static void handle_method_play_dtmf_with_stream_info(GDBusMethodInvocation* invocation)
406 {
407         int ret = MM_ERROR_NONE, slotid = 0;
408         int tone = 0, repeat = 0, volume = 0, pid = 0, stream_index = 0;
409         char* stream_type = NULL;
410         GVariant *params = NULL;
411
412         debug_fenter();
413
414         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
415                 debug_error("Parameter for Method is NULL");
416                 ret = MM_ERROR_SOUND_INTERNAL;
417                 goto send_reply;
418         }
419
420         g_variant_get(params, "(iiiisi)", &tone, &repeat, &volume, &pid, &stream_type, &stream_index);
421         ret = _MMSoundMgrIpcPlayDTMFWithStreamInfo(tone, repeat, volume, _get_sender_pid(invocation), &slotid, stream_type, stream_index);
422
423 send_reply:
424         if (ret == MM_ERROR_NONE) {
425                 _method_call_return_value(invocation, g_variant_new("(i)", slotid));
426         } else {
427                 _method_call_return_error(invocation, ret);
428         }
429
430         debug_fleave();
431 }
432
433 static void handle_method_play_file_stop(GDBusMethodInvocation* invocation)
434 {
435         int ret = MM_ERROR_NONE;
436         int handle = 0;
437         GVariant *params = NULL;
438
439         debug_fenter();
440
441         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
442                 debug_error("Parameter for Method is NULL");
443                 ret = MM_ERROR_SOUND_INTERNAL;
444                 goto send_reply;
445         }
446
447         g_variant_get(params, "(i)", &handle);
448         ret = _MMSoundMgrIpcStop(handle);
449
450 send_reply:
451         if (ret == MM_ERROR_NONE) {
452                 _method_call_return_value(invocation, g_variant_new("()"));
453         } else {
454                 _method_call_return_error(invocation, ret);
455         }
456
457         debug_fleave();
458 }
459
460 #ifdef FOCUS_INTEGRATION
461 static void handle_method_clear_focus(GDBusMethodInvocation* invocation)
462 {
463         int ret = MM_ERROR_NONE;
464         int pid = 0;
465         GVariant *params = NULL;
466
467         debug_fenter();
468
469         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
470                 debug_error("Parameter for Method is NULL");
471                 ret = MM_ERROR_SOUND_INTERNAL;
472                 goto send_reply;
473         }
474
475         g_variant_get(params, "(i)", &pid);
476         ret = _MMSoundMgrIpcClearFocus(pid);
477
478 send_reply:
479         if (ret == MM_ERROR_NONE) {
480                 _method_call_return_value(invocation, g_variant_new("()"));
481         } else {
482                 _method_call_return_error(invocation, ret);
483         }
484
485         debug_fleave();
486 }
487 #endif
488
489 static void handle_method_get_connected_device_list(GDBusMethodInvocation* invocation)
490 {
491         int ret = MM_ERROR_NONE;
492         GVariant *params = NULL;
493         GVariantBuilder reply_builder;
494         int mask_flags = 0;
495         int devices_num = 0, device_idx = 0;
496         mm_sound_device_t *device_list = NULL, *device_entry = NULL;
497
498         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
499                 debug_error("Parameter for Method is NULL");
500                 ret = MM_ERROR_SOUND_INTERNAL;
501                 goto send_reply;
502         }
503
504         g_variant_get(params, "(i)", &mask_flags);
505         debug_log("Get device list with device_flag %X", mask_flags);
506         if ((ret = __mm_sound_mgr_ipc_get_current_connected_device_list(mask_flags, &device_list, &devices_num))==MM_ERROR_NONE) {
507                 g_variant_builder_init(&reply_builder, G_VARIANT_TYPE("(a(iiiis))"));
508                 g_variant_builder_open(&reply_builder, G_VARIANT_TYPE("a(iiiis)"));
509                 for (device_idx = 0; device_idx < devices_num; device_idx++) {
510                         device_entry = &device_list[device_idx];
511 //                      debug_log("device(%d): id(%d), type(%d), io(%d), state(%d), name(%s) ", device_idx, device_entry->id, device_entry->type, device_entry->io_direction, device_entry->state, device_entry->name);
512                         g_variant_builder_add(&reply_builder, "(iiiis)", device_entry->id, device_entry->type, device_entry->io_direction, device_entry->state, device_entry->name);
513                 }
514                 g_variant_builder_close(&reply_builder);
515         }
516
517 send_reply:
518         if (ret == MM_ERROR_NONE) {
519                 _method_call_return_value(invocation, g_variant_builder_end(&reply_builder));
520                 debug_log("Reply Sent");
521         } else {
522                 _method_call_return_error(invocation, ret);
523         }
524 }
525
526 static void handle_method_call(GDBusConnection *connection,
527                                                         const gchar *sender,
528                                                         const gchar *object_path,
529                                                         const gchar *interface_name,
530                                                         const gchar *method_name,
531                                                         GVariant *parameters,
532                                                         GDBusMethodInvocation *invocation,
533                                                         gpointer userdata)
534 {
535         int method_idx = 0;
536
537         if (!parameters) {
538                 debug_error("Parameter Null");
539                 return;
540         }
541         debug_log("Method Call, obj : %s, intf : %s, method : %s", object_path, interface_name, method_name);
542
543         for (method_idx = 0; method_idx < AUDIO_METHOD_MAX; method_idx++) {
544                 if (!g_strcmp0(method_name, methods[method_idx].info.name)) {
545                         methods[method_idx].handler(invocation);
546                 }
547         }
548 }
549
550
551 static GVariant* handle_get_property(GDBusConnection *connection,
552                                                                         const gchar *sender,
553                                                                         const gchar *object_path,
554                                                                         const gchar *interface_name,
555                                                                         const gchar *property_name,
556                                                                         GError **error,
557                                                                         gpointer userdata)
558 {
559         debug_log("Get Property, obj : %s, intf : %s, prop : %s", object_path, interface_name, property_name);
560         return NULL;
561 }
562
563 static gboolean handle_set_property(GDBusConnection *connection,
564                                                                         const gchar *sender,
565                                                                         const gchar *object_path,
566                                                                         const gchar *interface_name,
567                                                                         const gchar *property_name,
568                                                                         GVariant *value,
569                                                                         GError **error,
570                                                                         gpointer userdata)
571 {
572         debug_log("Set Property, obj : %s, intf : %s, prop : %s", object_path, interface_name, property_name);
573         return TRUE;
574 }
575
576 static const GDBusInterfaceVTable interface_vtable =
577 {
578         handle_method_call,
579         handle_get_property,
580         handle_set_property
581 };
582
583 static void on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
584 {
585         guint reg_id;
586         debug_log("Bus Acquired (%s)", name);
587
588         conn_g = connection;
589         reg_id = g_dbus_connection_register_object(connection,
590                                           OBJECT_SOUND_SERVER,
591                                           introspection_data->interfaces[0],
592                                           &interface_vtable,
593                                           NULL,
594                                           NULL,
595                                           NULL);
596         if (!reg_id) {
597                 debug_error("Register object(%s) failed", OBJECT_SOUND_SERVER);
598                 return ;
599         }
600
601 }
602
603 static void on_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
604 {
605         debug_log("Name Acquired (%s)", name);
606 }
607
608 static void on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
609 {
610         debug_log("Name Lost (%s)", name);
611 }
612
613 static int _mm_sound_mgr_dbus_own_name(GBusType bus_type, const char* wellknown_name, guint* owner_id)
614 {
615         guint oid;
616
617         debug_log("Own name (%s) for sound-server", wellknown_name);
618
619         oid = g_bus_own_name(bus_type, wellknown_name, G_BUS_NAME_OWNER_FLAGS_NONE,
620                         on_bus_acquired, on_name_acquired, on_name_lost, NULL, NULL);
621         if (oid <= 0) {
622                 debug_error("Dbus own name failed");
623                 return MM_ERROR_SOUND_INTERNAL;
624         } else {
625                 *owner_id = oid;
626         }
627
628         debug_log("OwnerID (%d) for sound-server", *owner_id);
629
630         return MM_ERROR_NONE;
631 }
632
633 static void _mm_sound_mgr_dbus_unown_name(guint oid)
634 {
635         debug_log("Unown name for Sound-Server [%d]", oid);
636         if (oid > 0) {
637                 g_bus_unown_name(oid);
638         }
639 }
640
641 int __mm_sound_mgr_ipc_dbus_notify_device_connected(mm_sound_device_t *device, gboolean is_connected)
642 {
643         int ret = MM_ERROR_NONE;
644         GVariantBuilder builder;
645         GVariant* param = NULL;
646
647         debug_log("Send device connected signal");
648
649         g_variant_builder_init(&builder, G_VARIANT_TYPE("((iiiis)b)"));
650         g_variant_builder_open(&builder, G_VARIANT_TYPE_TUPLE);
651         g_variant_builder_add(&builder, "(iiiis)", device->id, device->type, device->io_direction, device->state, device->name);
652         g_variant_builder_close(&builder);
653         g_variant_builder_add(&builder, "b", is_connected);
654         param = g_variant_builder_end(&builder);
655         if (param) {
656                 if ((ret = mm_sound_mgr_ipc_dbus_send_signal(AUDIO_EVENT_DEVICE_CONNECTED, param))!= MM_ERROR_NONE) {
657                         debug_error("Send device connected signal failed");
658                 }
659         } else {
660                 debug_error("Build variant for dbus param failed");
661         }
662
663         return ret;
664 }
665
666 int __mm_sound_mgr_ipc_dbus_notify_device_info_changed(mm_sound_device_t *device, int changed_device_info_type)
667 {
668         int ret = MM_ERROR_NONE;
669         GVariantBuilder builder;
670         GVariant* param = NULL;
671
672         debug_log("Send device info changed signal");
673
674         g_variant_builder_init(&builder, G_VARIANT_TYPE("((iiiis)i)"));
675         g_variant_builder_open(&builder, G_VARIANT_TYPE_TUPLE);
676         g_variant_builder_add(&builder, "(iiiis)", device->id, device->type, device->io_direction, device->state, device->name);
677         g_variant_builder_close(&builder);
678         g_variant_builder_add(&builder, "i", changed_device_info_type);
679         param = g_variant_builder_end(&builder);
680         if (param) {
681                 if ((ret = mm_sound_mgr_ipc_dbus_send_signal(AUDIO_EVENT_DEVICE_INFO_CHANGED, param)) != MM_ERROR_NONE) {
682                         debug_error("Send device info changed signal failed");
683                 }
684         } else {
685                 debug_error("Build variant for dbus param failed");
686         }
687
688         return ret;
689 }
690
691 int __mm_sound_mgr_ipc_dbus_notify_volume_changed(unsigned int vol_type, unsigned int value)
692 {
693         int ret = MM_ERROR_NONE;
694         GVariant* param = NULL;
695
696         debug_log("Send Signal volume changed signal");
697
698         param = g_variant_new("(uu)", vol_type, value);
699         if (param) {
700                 if ((ret = mm_sound_mgr_ipc_dbus_send_signal(AUDIO_EVENT_VOLUME_CHANGED, param)) != MM_ERROR_NONE) {
701                         debug_error("Send device connected signal failed");
702                 }
703         } else {
704                 debug_error("Build variant for dbus param failed");
705         }
706
707         return ret;
708 }
709
710 int __mm_sound_mgr_ipc_dbus_notify_play_file_end(int handle)
711 {
712         int ret = MM_ERROR_NONE;
713         GVariant* param = NULL;
714
715         debug_log("Send play file ended signal");
716
717         param = g_variant_new("(i)", handle);
718         if (param) {
719                 if ((ret = mm_sound_mgr_ipc_dbus_send_signal(AUDIO_EVENT_PLAY_FILE_END, param)) != MM_ERROR_NONE) {
720                         debug_error("Send play file end for '%d' failed", handle);
721                 }
722         } else {
723                 debug_error("Build variant for dbus param failed");
724         }
725
726         return ret;
727 }
728
729 int __mm_sound_mgr_ipc_dbus_notify_active_device_changed(int device_in, int device_out)
730 {
731         return MM_ERROR_SOUND_INTERNAL;
732 }
733
734 int __mm_sound_mgr_ipc_dbus_notify_available_device_changed(int device_in, int device_out, int available)
735 {
736         return MM_ERROR_SOUND_INTERNAL;
737 }
738
739 #define PA_BUS_NAME                                    "org.pulseaudio.Server"
740 #define PA_STREAM_MANAGER_OBJECT_PATH                  "/org/pulseaudio/StreamManager"
741 #define PA_STREAM_MANAGER_INTERFACE                    "org.pulseaudio.StreamManager"
742 #define PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_LIST  "GetStreamList"
743 int __mm_sound_mgr_ipc_dbus_get_stream_list(stream_list_t* stream_list)
744 {
745         int ret = MM_ERROR_NONE;
746         GVariant *result = NULL;
747         GVariant *child = NULL;
748         GDBusConnection *conn = NULL;
749         GError *err = NULL;
750         int i = 0;
751
752         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
753         if (!conn && err) {
754                 LOGE("g_bus_get_sync() error (%s)", err->message);
755                 g_error_free(err);
756                 ret = MM_ERROR_SOUND_INTERNAL;
757                 return ret;
758         }
759         result = g_dbus_connection_call_sync(conn,
760                                                         PA_BUS_NAME,
761                                                         PA_STREAM_MANAGER_OBJECT_PATH,
762                                                         PA_STREAM_MANAGER_INTERFACE,
763                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_LIST,
764                                                         NULL,
765                                                         G_VARIANT_TYPE("(vv)"),
766                                                         G_DBUS_CALL_FLAGS_NONE,
767                                                         2000,
768                                                         NULL,
769                                                         &err);
770         if (!result && err) {
771                 debug_error("g_dbus_connection_call_sync() error (%s)", err->message);
772                 ret = MM_ERROR_SOUND_INTERNAL;
773         } else {
774                 GVariantIter iter;
775                 GVariant *item = NULL;
776                 child = g_variant_get_child_value(result, 0);
777                 item = g_variant_get_variant(child);
778                 gchar *name;
779                 i = 0;
780                 g_variant_iter_init(&iter, item);
781                 while ((i < AVAIL_STREAMS_MAX) && g_variant_iter_loop(&iter, "&s", &name)) {
782                         debug_log("name : %s", name);
783                         stream_list->stream_types[i++] = strdup(name);
784                 }
785                 g_variant_unref(item);
786                 g_variant_unref(child);
787
788                 child = g_variant_get_child_value(result, 1);
789                 item = g_variant_get_variant(child);
790                 gint32 priority;
791                 i = 0;
792                 g_variant_iter_init(&iter, item);
793                 while ((i < AVAIL_STREAMS_MAX) && g_variant_iter_loop(&iter, "i", &priority)) {
794                         debug_log("priority : %d", priority);
795                         stream_list->priorities[i++] = priority;
796                 }
797                 g_variant_unref(item);
798                 g_variant_unref(child);
799
800                 g_variant_unref(result);
801         }
802         g_object_unref(conn);
803
804         return ret;
805 }
806
807 int MMSoundMgrDbusInit(void)
808 {
809         debug_enter();
810
811         introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
812         if (!introspection_data) {
813                 debug_error("g_dbus_node_info_new_for_xml() failed...");
814                 return MM_ERROR_SOUND_INTERNAL;
815         }
816
817         if (_mm_sound_mgr_dbus_own_name(G_BUS_TYPE_SYSTEM, BUS_NAME_SOUND_SERVER, &sound_server_owner_id) != MM_ERROR_NONE) {
818                 debug_error("dbus own name for sound-server error\n");
819                 return MM_ERROR_SOUND_INTERNAL;
820         }
821
822         debug_leave();
823
824         return MM_ERROR_NONE;
825 }
826
827 void MMSoundMgrDbusFini(void)
828 {
829         debug_enter("\n");
830
831         _mm_sound_mgr_dbus_unown_name(sound_server_owner_id);
832         g_dbus_node_info_unref(introspection_data);
833
834         debug_leave("\n");
835 }
836
837
838