focus_server: Add support for delivery focus to another node
[platform/core/multimedia/libmm-sound.git] / focus_server / mm_sound_mgr_focus_dbus.c
1
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include <mm_error.h>
6 #include <mm_debug.h>
7
8 #include <gio/gio.h>
9
10 #include "include/mm_sound_mgr_focus_dbus.h"
11 #include "include/mm_sound_mgr_focus_ipc.h"
12 #include "../include/mm_sound_dbus.h"
13
14
15 #define BUS_NAME_FOCUS_SERVER "org.tizen.FocusServer"
16 #define OBJECT_FOCUS_SERVER "/org/tizen/FocusServer1"
17 #define INTERFACE_FOCUS_SERVER "org.tizen.FocusServer1"
18
19 /* Introspection data for the service we are exporting */
20 static const gchar introspection_xml[] =
21   "<node>"
22   "  <interface name='org.tizen.FocusServer1'>"
23   "    <method name='GetUniqueId'>"
24   "      <arg name='id' type='i' direction='out'/>"
25   "    </method>"
26   "    <method name='RegisterFocus'>"
27   "      <arg name='pid' type='i' direction='in'/>"
28   "      <arg name='handle_id' type='i' direction='in'/>"
29   "      <arg name='stream_type' type='s' direction='in'/>"
30   "      <arg name='is_for_session' type='b' direction='in'/>"
31   "    </method>"
32   "    <method name='UnregisterFocus'>"
33   "      <arg name='pid' type='i' direction='in'/>"
34   "      <arg name='handle_id' type='i' direction='in'/>"
35   "      <arg name='is_for_session' type='b' direction='in'/>"
36   "    </method>"
37   "    <method name='SetFocusReacquisition'>"
38   "      <arg name='pid' type='i' direction='in'/>"
39   "      <arg name='handle_id' type='i' direction='in'/>"
40   "      <arg name='reacquisition' type='b' direction='in'/>"
41   "      <arg name='is_for_session' type='b' direction='in'/>"
42   "    </method>"
43   "    <method name='GetAcquiredFocusStreamType'>"
44   "      <arg name='focus_type' type='i' direction='in'/>"
45   "      <arg name='stream_type' type='s' direction='out'/>"
46   "      <arg name='option' type='i' direction='out'/>"
47   "      <arg name='ext_info' type='s' direction='out'/>"
48   "    </method>"
49   "    <method name='AcquireFocus'>"
50   "      <arg name='pid' type='i' direction='in'/>"
51   "      <arg name='handle_id' type='i' direction='in'/>"
52   "      <arg name='focus_type' type='i' direction='in'/>"
53   "      <arg name='option' type='i' direction='in'/>"
54   "      <arg name='ext_info' type='s' direction='in'/>"
55   "      <arg name='is_for_session' type='b' direction='in'/>"
56   "    </method>"
57   "    <method name='ReleaseFocus'>"
58   "      <arg name='pid' type='i' direction='in'/>"
59   "      <arg name='handle_id' type='i' direction='in'/>"
60   "      <arg name='focus_type' type='i' direction='in'/>"
61   "      <arg name='option' type='i' direction='in'/>"
62   "      <arg name='ext_info' type='s' direction='in'/>"
63   "      <arg name='is_for_session' type='b' direction='in'/>"
64   "    </method>"
65   "    <method name='WatchFocus'>"
66   "      <arg name='pid' type='i' direction='in'/>"
67   "      <arg name='handle_id' type='i' direction='in'/>"
68   "      <arg name='focus_type' type='i' direction='in'/>"
69   "      <arg name='is_for_session' type='b' direction='in'/>"
70   "      <arg name='is_for_monitor' type='b' direction='in'/>"
71   "    </method>"
72   "    <method name='UnwatchFocus'>"
73   "      <arg name='pid' type='i' direction='in'/>"
74   "      <arg name='handle_id' type='i' direction='in'/>"
75   "      <arg name='is_for_session' type='b' direction='in'/>"
76   "    </method>"
77   "    <method name='DeliverFocus'>"
78   "      <arg name='pid' type='i' direction='in'/>"
79   "      <arg name='src_handle_id' type='i' direction='in'/>"
80   "      <arg name='dst_handle_id' type='i' direction='in'/>"
81   "      <arg name='focus_type' type='i' direction='in'/>"
82   "    </method>"
83   "    <method name='EmergentExitFocus'>"
84   "      <arg name='pid' type='i' direction='in'/>"
85   "    </method>"
86   "  </interface>"
87   "</node>";
88 static GDBusConnection* conn_g;
89
90 typedef void (*dbus_method_handler)(GDBusMethodInvocation *invocation);
91 typedef int (*dbus_signal_sender)(GDBusConnection *conn, GVariant *parameter);
92
93 struct mm_sound_mgr_focus_dbus_method{
94         struct mm_sound_dbus_method_info info;
95         dbus_method_handler handler;
96 };
97
98 struct mm_sound_mgr_focus_dbus_signal{
99         struct mm_sound_dbus_signal_info info;
100         dbus_signal_sender sender;
101 };
102
103 static void handle_method_get_unique_id(GDBusMethodInvocation* invocation);
104 static void handle_method_register_focus(GDBusMethodInvocation* invocation);
105 static void handle_method_unregister_focus(GDBusMethodInvocation* invocation);
106 static void handle_method_set_focus_reacquisition(GDBusMethodInvocation* invocation);
107 static void handle_method_get_acquired_focus_stream_type(GDBusMethodInvocation* invocation);
108 static void handle_method_acquire_focus(GDBusMethodInvocation* invocation);
109 static void handle_method_release_focus(GDBusMethodInvocation* invocation);
110 static void handle_method_watch_focus(GDBusMethodInvocation* invocation);
111 static void handle_method_unwatch_focus(GDBusMethodInvocation* invocation);
112 static void handle_method_deliver_focus(GDBusMethodInvocation* invocation);
113
114 /* Currently , Just using method's name and handler */
115 /* TODO : generate introspection xml automatically, with these value include argument and reply */
116 /* TODO : argument check with these information */
117 /* TODO : divide object and interface with features (ex. play, path, device, focus, asm) */
118 static mm_sound_dbus_method_intf_t methods[AUDIO_METHOD_MAX] = {
119         [AUDIO_METHOD_GET_UNIQUE_ID] = {
120                 .info = {
121                         .name = "GetUniqueId",
122                 },
123                 .handler = handle_method_get_unique_id
124         },
125         [AUDIO_METHOD_REGISTER_FOCUS] = {
126                 .info = {
127                         .name = "RegisterFocus",
128                 },
129                 .handler = handle_method_register_focus
130         },
131         [AUDIO_METHOD_UNREGISTER_FOCUS] = {
132                 .info = {
133                         .name = "UnregisterFocus",
134                 },
135                 .handler = handle_method_unregister_focus
136         },
137         [AUDIO_METHOD_SET_FOCUS_REACQUISITION] = {
138                 .info = {
139                         .name = "SetFocusReacquisition",
140                 },
141                 .handler = handle_method_set_focus_reacquisition
142         },
143         [AUDIO_METHOD_GET_ACQUIRED_FOCUS_STREAM_TYPE] = {
144                 .info = {
145                         .name = "GetAcquiredFocusStreamType",
146                 },
147                 .handler = handle_method_get_acquired_focus_stream_type
148         },
149         [AUDIO_METHOD_ACQUIRE_FOCUS] = {
150                 .info = {
151                         .name = "AcquireFocus",
152                 },
153                 .handler = handle_method_acquire_focus
154         },
155         [AUDIO_METHOD_RELEASE_FOCUS] = {
156                 .info = {
157                         .name = "ReleaseFocus",
158                 },
159                 .handler = handle_method_release_focus
160         },
161         [AUDIO_METHOD_WATCH_FOCUS] = {
162                 .info = {
163                         .name = "WatchFocus",
164                 },
165                 .handler = handle_method_watch_focus
166         },
167         [AUDIO_METHOD_UNWATCH_FOCUS] = {
168                 .info = {
169                         .name = "UnwatchFocus",
170                 },
171                 .handler = handle_method_unwatch_focus
172         },
173         [AUDIO_METHOD_DELIVER_FOCUS] = {
174                 .info = {
175                         .name = "DeliverFocus",
176                 },
177                 .handler = handle_method_deliver_focus
178         }
179 };
180
181 static GDBusNodeInfo *introspection_data = NULL;
182 guint focus_server_owner_id ;
183 unsigned emergent_exit_subs_id;
184
185 /*
186         For pass error code with 'g_dbus_method_invocation_return_error'
187         We have to use some glib features like GError, GQuark
188 */
189 /* Only For error types which is currently being used in server-side */
190 static const GDBusErrorEntry mm_sound_error_entries[] =
191 {
192         {MM_ERROR_OUT_OF_MEMORY, "org.tizen.multimedia.OutOfMemory"},
193         {MM_ERROR_OUT_OF_STORAGE, "org.tizen.multimedia.OutOfStorage"},
194         {MM_ERROR_INVALID_ARGUMENT, "org.tizen.multimedia.InvalidArgument"},
195         {MM_ERROR_POLICY_INTERNAL, "org.tizen.multimedia.PolicyInternal"},
196         {MM_ERROR_NOT_SUPPORT_API, "org.tizen.multimedia.NotSupportAPI"},
197         {MM_ERROR_POLICY_BLOCKED, "org.tizen.multimedia.PolicyBlocked"},
198         {MM_ERROR_END_OF_FILE, "org.tizen.multimedia.EndOfFile"},
199         {MM_ERROR_COMMON_OUT_OF_RANGE, "org.tizen.multimedia.common.OutOfRange"},
200         {MM_ERROR_COMMON_UNKNOWN, "org.tizen.multimedia.common.Unknown"},
201         {MM_ERROR_COMMON_NO_FREE_SPACE, "org.tizen.multimedia.common.NoFreeSpace"},
202         {MM_ERROR_SOUND_INTERNAL, "org.tizen.multimedia.audio.Internal"},
203         {MM_ERROR_SOUND_INVALID_STATE, "org.tizen.multimedia.audio.InvalidState"},
204         {MM_ERROR_SOUND_NO_FREE_SPACE, "org.tizen.multimedia.audio.NoFreeSpace"},
205         {MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE, "org.tizen.multimedia.audio.UnsupportedMediaType"},
206         {MM_ERROR_SOUND_INVALID_POINTER, "org.tizen.multimedia.audio.InvalidPointer"},
207         {MM_ERROR_SOUND_INVALID_FILE, "org.tizen.multimedia.audio.InvalidFile"},
208         {MM_ERROR_SOUND_FILE_NOT_FOUND, "org.tizen.multimedia.audio.FileNotFound"},
209         {MM_ERROR_SOUND_NO_DATA, "org.tizen.multimedia.audio.NoData"},
210         {MM_ERROR_SOUND_INVALID_PATH, "org.tizen.multimedia.audio.InvalidPath"},
211 };
212
213 static const char* _convert_error_code(int err_code)
214 {
215         int i = 0;
216
217         for (i = 0; i < G_N_ELEMENTS(mm_sound_error_entries); i++) {
218                 if (err_code == mm_sound_error_entries[i].error_code) {
219                         return mm_sound_error_entries[i].dbus_error_name;
220                 }
221         }
222
223         return "org.tizen.multimedia.common.Unknown";
224 }
225
226 static int _get_sender_pid(GDBusMethodInvocation* invocation)
227 {
228         GVariant* value;
229         guint pid = 0;
230         const gchar* sender;
231         GDBusConnection * connection = NULL;
232         GError* err = NULL;
233
234         connection = g_dbus_method_invocation_get_connection(invocation);
235         sender = g_dbus_method_invocation_get_sender(invocation);
236
237         debug_msg("connection = %p, sender = %s", connection, sender);
238
239         value = g_dbus_connection_call_sync(connection, "org.freedesktop.DBus", "/org/freedesktop/DBus",
240                                                                                 "org.freedesktop.DBus", "GetConnectionUnixProcessID",
241                                                                                 g_variant_new("(s)", sender, NULL), NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
242         if (value) {
243                 g_variant_get(value, "(u)", &pid);
244                 debug_msg("Sender PID = [%d]", pid);
245                 g_variant_unref(value);
246         } else {
247                 debug_error("err code = %d, err msg = %s", err->code, err->message);
248         }
249         return pid;
250 }
251
252 static void _method_call_return_value(GDBusMethodInvocation *invocation, GVariant *params)
253 {
254         const char *method_name;
255         method_name = g_dbus_method_invocation_get_method_name(invocation);
256         debug_msg("Method Call '%s' success", method_name);
257         g_dbus_method_invocation_return_value(invocation, params);
258 }
259 static void _method_call_return_error(GDBusMethodInvocation *invocation, int ret)
260 {
261         const char *err_name, *method_name;
262         err_name = _convert_error_code(ret);
263         method_name = g_dbus_method_invocation_get_method_name(invocation);
264         debug_error("Method Call '%s' failed, err '%s(%X)'", method_name, err_name, ret);
265         g_dbus_method_invocation_return_dbus_error(invocation, err_name, "failed");
266 }
267
268 static void handle_method_get_unique_id(GDBusMethodInvocation* invocation)
269 {
270         static int unique_id = 0;
271
272         debug_fenter();
273
274         _method_call_return_value(invocation, g_variant_new("(i)", ++unique_id));
275
276         debug_fleave();
277 }
278
279 static void handle_method_register_focus(GDBusMethodInvocation* invocation)
280 {
281         int ret = MM_ERROR_NONE;
282         int handle_id = 0;
283         const char* stream_type = NULL;
284         gboolean is_for_session;
285         GVariant *params = NULL;
286         int pid = 0;
287
288         debug_fenter();
289
290         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
291                 debug_error("Parameter for Method is NULL");
292                 ret = MM_ERROR_SOUND_INTERNAL;
293                 goto send_reply;
294         }
295
296         g_variant_get(params, "(ii&sb)", &pid, &handle_id, &stream_type, &is_for_session);
297         ret = __mm_sound_mgr_focus_ipc_register_focus((is_for_session) ? pid : _get_sender_pid(invocation), handle_id, stream_type, is_for_session);
298
299 send_reply:
300         if (ret == MM_ERROR_NONE) {
301                 _method_call_return_value(invocation, g_variant_new("()"));
302         } else {
303                 _method_call_return_error(invocation, ret);
304         }
305
306         debug_fleave();
307 }
308
309 static void handle_method_unregister_focus(GDBusMethodInvocation* invocation)
310 {
311         int ret = MM_ERROR_NONE;
312         int pid = 0, handle_id = 0;
313         gboolean is_for_session;
314         GVariant *params = NULL;
315
316         debug_fenter();
317
318         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
319                 debug_error("Parameter for Method is NULL");
320                 ret = MM_ERROR_SOUND_INTERNAL;
321                 goto send_reply;
322         }
323
324         g_variant_get(params, "(iib)", &pid, &handle_id, &is_for_session);
325         ret = __mm_sound_mgr_focus_ipc_unregister_focus((is_for_session) ? pid : _get_sender_pid(invocation), handle_id, is_for_session);
326
327 send_reply:
328         if (ret == MM_ERROR_NONE) {
329                 _method_call_return_value(invocation, g_variant_new("()"));
330         } else {
331                 _method_call_return_error(invocation, ret);
332         }
333
334         debug_fleave();
335 }
336
337 static void handle_method_set_focus_reacquisition(GDBusMethodInvocation* invocation)
338 {
339         int ret = MM_ERROR_NONE;
340         int pid = 0, handle_id = 0;
341         gboolean reacquisition;
342         gboolean is_for_session;
343         GVariant *params = NULL;
344
345         debug_fenter();
346
347         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
348                 debug_error("Parameter for Method is NULL");
349                 ret = MM_ERROR_SOUND_INTERNAL;
350                 goto send_reply;
351         }
352
353         g_variant_get(params, "(iibb)", &pid, &handle_id, &reacquisition, &is_for_session);
354         ret = __mm_sound_mgr_focus_ipc_set_focus_reacquisition(_get_sender_pid(invocation), handle_id, reacquisition, is_for_session);
355
356 send_reply:
357         if (ret == MM_ERROR_NONE) {
358                 _method_call_return_value(invocation, g_variant_new("()"));
359         } else {
360                 _method_call_return_error(invocation, ret);
361         }
362
363         debug_fleave();
364 }
365
366 static void handle_method_get_acquired_focus_stream_type(GDBusMethodInvocation* invocation)
367 {
368         int ret = MM_ERROR_NONE;
369         int focus_type = 0;
370         char *stream_type = NULL;
371         int option = 0;
372         char *ext_info = NULL;
373         GVariant *params = NULL;
374
375         debug_fenter();
376
377         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
378                 debug_error("Parameter for Method is NULL");
379                 ret = MM_ERROR_SOUND_INTERNAL;
380                 goto send_reply;
381         }
382
383         g_variant_get(params, "(i)", &focus_type);
384         ret = __mm_sound_mgr_focus_ipc_get_acquired_focus_stream_type(focus_type, &stream_type, &option, &ext_info);
385
386 send_reply:
387         if (ret == MM_ERROR_NONE)
388                 _method_call_return_value(invocation, g_variant_new("(sis)", stream_type, option, ext_info));
389         else
390                 _method_call_return_error(invocation, ret);
391
392         debug_fleave();
393 }
394
395 static void handle_method_acquire_focus(GDBusMethodInvocation* invocation)
396 {
397         int ret = MM_ERROR_NONE;
398         int pid = 0, handle_id = 0, focus_type = 0, option = 0;
399         const char* ext_info = NULL;
400         gboolean is_for_session;
401         GVariant *params = NULL;
402
403         debug_fenter();
404
405         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
406                 debug_error("Parameter for Method is NULL");
407                 ret = MM_ERROR_SOUND_INTERNAL;
408                 goto send_reply;
409         }
410
411         g_variant_get(params, "(iiiisb)", &pid, &handle_id, &focus_type, &option, &ext_info, &is_for_session);
412         ret = __mm_sound_mgr_focus_ipc_acquire_focus((is_for_session) ? pid : _get_sender_pid(invocation),
413                                                      handle_id, focus_type, option, ext_info, false, is_for_session);
414
415 send_reply:
416         if (ret == MM_ERROR_NONE) {
417                 _method_call_return_value(invocation, g_variant_new("()"));
418         } else {
419                 _method_call_return_error(invocation, ret);
420         }
421
422         debug_fleave();
423 }
424
425 static void handle_method_release_focus(GDBusMethodInvocation* invocation)
426 {
427         int ret = MM_ERROR_NONE;
428         int pid = 0, handle_id = 0, focus_type = 0, option = 0;
429         const char* ext_info = NULL;
430         gboolean is_for_session;
431         GVariant *params = NULL;
432
433         debug_fenter();
434
435         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
436                 debug_error("Parameter for Method is NULL");
437                 ret = MM_ERROR_SOUND_INTERNAL;
438                 goto send_reply;
439         }
440
441         g_variant_get(params, "(iiiisb)", &pid, &handle_id, &focus_type, &option, &ext_info, &is_for_session);
442         ret = __mm_sound_mgr_focus_ipc_release_focus((is_for_session) ? pid : _get_sender_pid(invocation),
443                                                      handle_id, focus_type, option, ext_info, false, is_for_session);
444
445 send_reply:
446         if (ret == MM_ERROR_NONE) {
447                 _method_call_return_value(invocation, g_variant_new("()"));
448         } else {
449                 _method_call_return_error(invocation, ret);
450         }
451
452         debug_fleave();
453 }
454
455 static void handle_method_watch_focus(GDBusMethodInvocation* invocation)
456 {
457         int ret = MM_ERROR_NONE;
458         int handle_id = 0, focus_type = 0;
459         gboolean is_for_session;
460         gboolean is_for_monitor;
461         GVariant *params = NULL;
462         int pid = 0;
463
464         debug_fenter();
465
466         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
467                 debug_error("Parameter for Method is NULL");
468                 ret = MM_ERROR_SOUND_INTERNAL;
469                 goto send_reply;
470         }
471
472         g_variant_get(params, "(iiibb)", &pid, &handle_id, &focus_type, &is_for_session, &is_for_monitor);
473         ret = __mm_sound_mgr_focus_ipc_watch_focus((is_for_session) ? pid : _get_sender_pid(invocation), handle_id, focus_type, is_for_session, is_for_monitor);
474
475 send_reply:
476         if (ret == MM_ERROR_NONE) {
477                 _method_call_return_value(invocation, g_variant_new("()"));
478         } else {
479                 _method_call_return_error(invocation, ret);
480         }
481
482         debug_fleave();
483 }
484
485 static void handle_method_unwatch_focus(GDBusMethodInvocation* invocation)
486 {
487         int ret = MM_ERROR_NONE;
488         int pid = 0;
489         int handle_id = 0;
490         gboolean is_for_session;
491         GVariant *params = NULL;
492
493         debug_fenter();
494
495         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
496                 debug_error("Parameter for Method is NULL");
497                 ret = MM_ERROR_SOUND_INTERNAL;
498                 goto send_reply;
499         }
500
501         g_variant_get(params, "(iib)", &pid, &handle_id, &is_for_session);
502         ret = __mm_sound_mgr_focus_ipc_unwatch_focus((is_for_session) ? pid : _get_sender_pid(invocation), handle_id);
503
504 send_reply:
505         if (ret == MM_ERROR_NONE) {
506                 _method_call_return_value(invocation, g_variant_new("()"));
507         } else {
508                 _method_call_return_error(invocation, ret);
509         }
510
511         debug_fleave();
512 }
513
514 static void handle_method_deliver_focus(GDBusMethodInvocation* invocation)
515 {
516         int ret = MM_ERROR_NONE;
517         int pid = 0;
518         int src_handle_id = 0;
519         int dst_handle_id = 0;
520         int focus_type = 0;
521         GVariant *params = NULL;
522
523         debug_fenter();
524
525         if (!(params = g_dbus_method_invocation_get_parameters(invocation))) {
526                 debug_error("Parameter for Method is NULL");
527                 ret = MM_ERROR_SOUND_INTERNAL;
528                 goto send_reply;
529         }
530
531         g_variant_get(params, "(iiii)", &pid, &src_handle_id, &dst_handle_id, &focus_type);
532         ret = __mm_sound_mgr_focus_ipc_deliver_focus(pid, src_handle_id, dst_handle_id, focus_type);
533
534 send_reply:
535         if (ret == MM_ERROR_NONE) {
536                 _method_call_return_value(invocation, g_variant_new("()"));
537         } else {
538                 _method_call_return_error(invocation, ret);
539         }
540
541         debug_fleave();
542 }
543
544 /**********************************************************************************/
545 static void handle_method_call(GDBusConnection *connection,
546                                                         const gchar *sender,
547                                                         const gchar *object_path,
548                                                         const gchar *interface_name,
549                                                         const gchar *method_name,
550                                                         GVariant *parameters,
551                                                         GDBusMethodInvocation *invocation,
552                                                         gpointer userdata)
553 {
554         int method_idx = 0;
555
556         if (!parameters) {
557                 debug_error("Parameter Null");
558                 return;
559         }
560         debug_msg("Method Call, obj : %s, intf : %s, method : %s", object_path, interface_name, method_name);
561
562         for (method_idx = AUDIO_METHOD_GET_UNIQUE_ID; method_idx < AUDIO_METHOD_MAX; method_idx++) {
563                 if (!g_strcmp0(method_name, methods[method_idx].info.name)) {
564                         methods[method_idx].handler(invocation);
565                 }
566         }
567 }
568
569 static GVariant* handle_get_property(GDBusConnection *connection,
570                                                                         const gchar *sender,
571                                                                         const gchar *object_path,
572                                                                         const gchar *interface_name,
573                                                                         const gchar *property_name,
574                                                                         GError **error,
575                                                                         gpointer userdata)
576 {
577         debug_log("Get Property, obj : %s, intf : %s, prop : %s", object_path, interface_name, property_name);
578         return NULL;
579 }
580
581 static gboolean handle_set_property(GDBusConnection *connection,
582                                                                         const gchar *sender,
583                                                                         const gchar *object_path,
584                                                                         const gchar *interface_name,
585                                                                         const gchar *property_name,
586                                                                         GVariant *value,
587                                                                         GError **error,
588                                                                         gpointer userdata)
589 {
590         debug_log("Set Property, obj : %s, intf : %s, prop : %s", object_path, interface_name, property_name);
591         return TRUE;
592 }
593
594 void emergent_exit_signal_handler(audio_event_t event, GVariant *param, void *userdata)
595 {
596         int ret = MM_ERROR_NONE;
597         int pid = 0;
598
599         if (event != AUDIO_EVENT_EMERGENT_EXIT)
600                 return;
601
602         debug_fenter();
603
604         g_variant_get(param, "(i)", &pid);
605         debug_log("emergent exit : pid %d", pid);
606         ret = __mm_sound_mgr_focus_ipc_emergent_exit(pid);
607         if (ret)
608                 debug_error("__mm_sound_mgr_focus_ipc_emergent_exit failed : 0x%x", ret);
609
610         debug_fleave();
611 }
612
613 static const GDBusInterfaceVTable interface_vtable =
614 {
615         handle_method_call,
616         handle_get_property,
617         handle_set_property
618 };
619
620 static void on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
621 {
622         guint reg_id;
623         debug_log("Bus Acquired (%s)", name);
624
625         conn_g = connection;
626         reg_id = g_dbus_connection_register_object(connection,
627                                           OBJECT_FOCUS_SERVER,
628                                           introspection_data->interfaces[0],
629                                           &interface_vtable,
630                                           NULL,
631                                           NULL,
632                                           NULL);
633         if (!reg_id) {
634                 debug_error("Register object(%s) failed", OBJECT_FOCUS_SERVER);
635                 return ;
636         }
637 }
638
639 static void on_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
640 {
641         debug_log("Name Acquired (%s)", name);
642 }
643
644 static void on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
645 {
646         debug_log("Name Lost (%s)", name);
647 }
648
649 static int _mm_sound_mgr_focus_dbus_own_name(GBusType bus_type, const char* wellknown_name, guint* owner_id)
650 {
651         guint oid;
652
653         debug_msg("Own name (%s) for focus-server", wellknown_name);
654
655         oid = g_bus_own_name(bus_type, wellknown_name, G_BUS_NAME_OWNER_FLAGS_NONE,
656                         on_bus_acquired, on_name_acquired, on_name_lost, NULL, NULL);
657         if (oid <= 0) {
658                 debug_error("Dbus own name failed");
659                 return MM_ERROR_SOUND_INTERNAL;
660         } else {
661                 *owner_id = oid;
662         }
663
664         debug_msg("OwnerID (%d) for focus-server", *owner_id);
665
666         return MM_ERROR_NONE;
667 }
668
669 static void _mm_sound_mgr_focus_dbus_unown_name(guint oid)
670 {
671         debug_msg("Unown name for focus-server [%d]", oid);
672         if (oid > 0) {
673                 g_bus_unown_name(oid);
674         }
675 }
676
677 #define PA_BUS_NAME                                    "org.pulseaudio.Server"
678 #define PA_STREAM_MANAGER_OBJECT_PATH                  "/org/pulseaudio/StreamManager"
679 #define PA_STREAM_MANAGER_INTERFACE                    "org.pulseaudio.StreamManager"
680 #define PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_LIST  "GetStreamList"
681 int __mm_sound_mgr_focus_dbus_get_stream_list(stream_list_t* stream_list)
682 {
683         int ret = MM_ERROR_NONE;
684         GVariant *result = NULL;
685         GVariant *child = NULL;
686         GDBusConnection *conn = NULL;
687         GError *err = NULL;
688         int i = 0;
689
690         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
691         if (!conn && err) {
692                 LOGE("g_bus_get_sync() error (%s)", err->message);
693                 g_error_free(err);
694                 ret = MM_ERROR_SOUND_INTERNAL;
695                 return ret;
696         }
697         result = g_dbus_connection_call_sync(conn,
698                                                         PA_BUS_NAME,
699                                                         PA_STREAM_MANAGER_OBJECT_PATH,
700                                                         PA_STREAM_MANAGER_INTERFACE,
701                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_LIST,
702                                                         NULL,
703                                                         G_VARIANT_TYPE("(vv)"),
704                                                         G_DBUS_CALL_FLAGS_NONE,
705                                                         2000,
706                                                         NULL,
707                                                         &err);
708         if (!result && err) {
709                 debug_error("g_dbus_connection_call_sync() error (%s)", err->message);
710                 ret = MM_ERROR_SOUND_INTERNAL;
711         } else {
712                 GVariantIter iter;
713                 GVariant *item = NULL;
714                 child = g_variant_get_child_value(result, 0);
715                 item = g_variant_get_variant(child);
716                 gchar *name;
717                 i = 0;
718                 g_variant_iter_init(&iter, item);
719                 while ((i < AVAIL_STREAMS_MAX) && g_variant_iter_loop(&iter, "&s", &name)) {
720                         debug_log("name : %s", name);
721                         stream_list->stream_types[i++] = strdup(name);
722                 }
723                 g_variant_unref(item);
724                 g_variant_unref(child);
725
726                 child = g_variant_get_child_value(result, 1);
727                 item = g_variant_get_variant(child);
728                 gint32 priority;
729                 i = 0;
730                 g_variant_iter_init(&iter, item);
731                 while ((i < AVAIL_STREAMS_MAX) && g_variant_iter_loop(&iter, "i", &priority)) {
732                         debug_log("priority : %d", priority);
733                         stream_list->priorities[i++] = priority;
734                 }
735                 g_variant_unref(item);
736                 g_variant_unref(child);
737
738                 g_variant_unref(result);
739         }
740         g_object_unref(conn);
741
742         return ret;
743 }
744
745 int MMSoundMgrFocusDbusInit(void)
746 {
747         debug_enter();
748
749         introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
750         if (!introspection_data)
751                 return MM_ERROR_SOUND_INTERNAL;
752
753         if (_mm_sound_mgr_focus_dbus_own_name(G_BUS_TYPE_SYSTEM, BUS_NAME_FOCUS_SERVER, &focus_server_owner_id) != MM_ERROR_NONE) {
754                 debug_error("dbus own name for focus-server error\n");
755                 return MM_ERROR_SOUND_INTERNAL;
756         }
757         if (mm_sound_dbus_signal_subscribe_to(AUDIO_PROVIDER_AUDIO_CLIENT, AUDIO_EVENT_EMERGENT_EXIT, emergent_exit_signal_handler, NULL, NULL, &emergent_exit_subs_id) != MM_ERROR_NONE) {
758                 debug_error("dbus signal subscribe for emergent exit error\n");
759                 return MM_ERROR_SOUND_INTERNAL;
760         }
761
762         debug_leave();
763
764         return MM_ERROR_NONE;
765 }
766
767 void MMSoundMgrFocusDbusFini(void)
768 {
769         debug_enter();
770
771         if (emergent_exit_subs_id != 0)
772                 mm_sound_dbus_signal_unsubscribe(emergent_exit_subs_id);
773         _mm_sound_mgr_focus_dbus_unown_name(focus_server_owner_id);
774         g_dbus_node_info_unref(introspection_data);
775
776         debug_leave();
777 }