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