device-manager: Add Dbus interfaces to specify stream role to usb device
[platform/core/multimedia/pulseaudio-modules-tizen.git] / src / device-manager.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2015-2016 Jeonho Mok <jho.mok@samsung.com>
5
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2.1 of the License,
9   or (at your option) any later version.
10
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <ctype.h>
28 #include <stdbool.h>
29 #include <json.h>
30 #include <pulse/proplist.h>
31 #include <pulse/util.h>
32 #include <pulse/rtclock.h>
33 #include <pulsecore/core-subscribe.h>
34 #include <pulsecore/core-util.h>
35 #include <pulsecore/log.h>
36 #include <pulsecore/strbuf.h>
37 #include <pulsecore/modargs.h>
38 #include <pulsecore/namereg.h>
39 #include <pulsecore/shared.h>
40 #include <pulsecore/dynarray.h>
41 #include <pulsecore/hashmap.h>
42
43 #include <vconf.h>
44 #include <vconf-keys.h>
45 #ifdef HAVE_DBUS
46 #include <pulsecore/dbus-shared.h>
47 #include <pulsecore/dbus-util.h>
48 #include <pulsecore/protocol-dbus.h>
49 #endif
50
51 #include "communicator.h"
52 #include "hal-interface.h"
53 #include "stream-manager.h"
54 #include "device-manager.h"
55
56 #define SHARED_DEVICE_MANAGER "tizen-device-manager"
57
58 #define DEVICE_MAP_FILE                    "/etc/pulse/device-map.json"
59 #define DEVICE_STR_MAX                      30
60 #define DEVICE_DIRECTION_MAX                3
61 #define DEVICE_PARAM_STRING_MAX             150
62 #define DEVICE_AVAIL_COND_NUM_MAX           2
63 #define DEVICE_AVAIL_COND_STR_MAX           6
64 #define DEVICE_FILE_PER_TYPE_MAX            4
65 #define DEVICE_FILE_STRING_MAX              4
66 #define DEVICE_TYPE_STR_MAX                 20
67 #define DEVICE_ROLE_STR_MAX                 15
68
69 #define DEVICE_TYPE_OBJECT                  "device-types"
70 #define DEVICE_FILE_OBJECT                  "device-files"
71 #define DEVICE_TYPE_PROP_DEVICE_TYPE        "device-type"
72 #define DEVICE_TYPE_PROP_PLAYBACK_DEVICES   "playback-devices"
73 #define DEVICE_TYPE_PROP_CAPTURE_DEVICES    "capture-devices"
74 #define DEVICE_TYPE_PROP_DEVICE_STRING      "device-string"
75 #define DEVICE_TYPE_PROP_ROLE               "role"
76
77 #define DEVICE_TYPE_STR_MAX                 20
78
79 /* Properties of sink/sources */
80 #define DEVICE_API_BLUEZ                    "bluez"
81 #define DEVICE_API_ALSA                     "alsa"
82 #define DEVICE_API_NULL                     "null"
83 #define DEVICE_BUS_USB                      "usb"
84 #define DEVICE_CLASS_SOUND                  "sound"
85 #define DEVICE_CLASS_MONITOR                "monitor"
86
87 /* Dbus defines */
88 #define DBUS_INTERFACE_DEVICE_MANAGER       "org.pulseaudio.DeviceManager"
89 #define DBUS_OBJECT_DEVICE_MANAGER          "/org/pulseaudio/DeviceManager"
90
91 #define DBUS_INTERFACE_DEVICED_SYSNOTI      "org.tizen.system.deviced.SysNoti"
92 #define DBUS_OBJECT_DEVICED_SYSNOTI         "/Org/Tizen/System/DeviceD/SysNoti"
93
94 #define DBUS_INTERFACE_SOUND_SERVER         "org.tizen.SoundServer1"
95 #define DBUS_OBJECT_SOUND_SERVER            "/org/tizen/SoundServer1"
96
97 #define DBUS_SERVICE_BLUEZ                  "org.bluez"
98 #define DBUS_INTERFACE_BLUEZ_HEADSET        "org.bluez.Headset"
99 #define DBUS_INTERFACE_BLUEZ_DEVICE         "org.bluez.Device1"
100 #define DBUS_OBJECT_BLUEZ                   "/org/bluez"
101
102 #define DBUS_INTERFACE_MIRRORING_SERVER     "org.tizen.scmirroring.server"
103 #define DBUS_OBJECT_MIRRORING_SERVER        "/org/tizen/scmirroring/server"
104
105 #define DBUS_SERVICE_HFP_AGENT "org.bluez.ag_agent"
106 #define DBUS_OBJECT_HFP_AGENT "/org/bluez/hfp_agent"
107 #define DBUS_INTERFACE_HFP_AGENT "Org.Hfp.App.Interface"
108
109 #define DEVICE_MANAGER_INTROSPECT_XML                                                       \
110     DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                                               \
111     "<node>\n"                                                                              \
112     " <interface name=\"" DBUS_INTERFACE_DEVICE_MANAGER "\">\n"                             \
113     "  <method name=\"GetConnectedDeviceList\">\n"                                          \
114     "   <arg name=\"mask_flags\" direction=\"in\" type=\"i\"/>\n"                           \
115     "   <arg name=\"ConnectedDeviceList\" direction=\"out\" type=\"a(isiisii)\"/>\n"        \
116     "  </method>\n"                                                                         \
117     "  <method name=\"GetDeviceById\">\n"                                                   \
118     "   <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n"                            \
119     "   <arg name=\"device\" direction=\"out\" type=\"(isiisii)\"/>\n"                      \
120     "  </method>\n"                                                                         \
121     "  <method name=\"IsStreamOnDevice\">\n"                                                \
122     "   <arg name=\"stream_id\" direction=\"in\" type=\"i\"/>\n"                            \
123     "   <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n"                            \
124     "   <arg name=\"is_on\" direction=\"out\" type=\"b\"/>\n"                               \
125     "  </method>\n"                                                                         \
126     "  <method name='GetBTA2DPStatus'>"                                                     \
127     "    <arg type='b' name='is_bt_on' direction='out'/>"                                   \
128     "    <arg type='s' name='bt_name' direction='out'/>"                                    \
129     "  </method>"                                                                           \
130     "  <method name=\"LoadSink\">\n"                                                        \
131     "   <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n"                          \
132     "   <arg name=\"role\" direction=\"in\" type=\"s\"/>\n"                                 \
133     "  </method>\n"                                                                         \
134     "  <method name=\"UnloadSink\">\n"                                                      \
135     "   <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n"                          \
136     "   <arg name=\"role\" direction=\"in\" type=\"s\"/>\n"                                 \
137     "  </method>\n"                                                                         \
138     "  <method name=\"GetSupportedSampleRates\">\n"                                         \
139     "   <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n"                            \
140     "   <arg name=\"sample_rates\" direction=\"out\" type=\"a(u)\"/>\n"                     \
141     "  </method>\n"                                                                         \
142     "  <method name=\"SetSampleRate\">\n"                                                   \
143     "   <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n"                            \
144     "   <arg name=\"sample_rate\" direction=\"in\" type=\"u\"/>\n"                          \
145     "  </method>\n"                                                                         \
146     "  <method name=\"GetSampleRate\">\n"                                                   \
147     "   <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n"                            \
148     "   <arg name=\"sample_rate\" direction=\"out\" type=\"u\"/>\n"                         \
149     "  </method>\n"                                                                         \
150     "  <method name=\"SetSpecificStreamOnly\">\n"                                           \
151     "   <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n"                            \
152     "   <arg name=\"stream_role\" direction=\"in\" type=\"s\"/>\n"                          \
153     "  </method>\n"                                                                         \
154     "  <method name=\"GetSpecifiedStream\">\n"                                              \
155     "   <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n"                            \
156     "   <arg name=\"stream_role\" direction=\"out\" type=\"s\"/>\n"                         \
157     "  </method>\n"                                                                         \
158     "  <method name=\"DumpDeviceList\">\n"                                                  \
159     "  </method>\n"                                                                         \
160     "  <method name=\"TestStatusChange\">\n"                                                \
161     "   <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n"                          \
162     "   <arg name=\"status\" direction=\"in\" type=\"i\"/>\n"                               \
163     "  </method>\n"                                                                         \
164     "  <property name=\"PropertyTest1\" type=\"i\" access=\"readwrite\"/>\n"                \
165     "  <property name=\"PropertyTest2\" type=\"s\" access=\"read\"/>\n"                     \
166     "  <signal name=\"DeviceConnected\">\n"                                                 \
167     "   <arg name=\"arg1\" type=\"i\"/>\n"                                                  \
168     "  </signal>\n"                                                                         \
169     "  <signal name=\"DeviceInfoChanged\">\n"                                               \
170     "   <arg name=\"arg1\" type=\"s\"/>\n"                                                  \
171     "  </signal>\n"                                                                         \
172     " </interface>\n"                                                                       \
173     " <interface name=\"" DBUS_INTERFACE_INTROSPECTABLE "\">\n"                             \
174     "  <method name=\"Introspect\">\n"                                                      \
175     "   <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"                                \
176     "  </method>\n"                                                                         \
177     " </interface>\n"                                                                       \
178     " <interface name=\"" DBUS_INTERFACE_PROPERTIES "\">\n"                                 \
179     "  <method name=\"Get\">\n"                                                             \
180     "   <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n"                       \
181     "   <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n"                        \
182     "   <arg name=\"value\" type=\"v\" direction=\"out\"/>\n"                               \
183     "  </method>\n"                                                                         \
184     "  <method name=\"Set\">\n"                                                             \
185     "   <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n"                       \
186     "   <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n"                        \
187     "   <arg name=\"value\" type=\"v\" direction=\"in\"/>\n"                                \
188     "  </method>\n"                                                                         \
189     "  <method name=\"GetAll\">\n"                                                          \
190     "   <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n"                       \
191     "   <arg name=\"props\" type=\"a{sv}\" direction=\"out\"/>\n"                           \
192     "  </method>\n"                                                                         \
193     " </interface>\n"                                                                       \
194     "</node>\n"
195
196 #define FILTER_DEVICED_SYSNOTI                             \
197     "type='signal',"                                       \
198     " interface='" DBUS_INTERFACE_DEVICED_SYSNOTI "'"
199
200 #define FILTER_SOUND_SERVER                                \
201     "type='signal',"                                       \
202     " interface='" DBUS_INTERFACE_SOUND_SERVER "'"
203
204 #define FILTER_MIRRORING                                   \
205     "type='signal',"                                       \
206     " interface='" DBUS_INTERFACE_MIRRORING_SERVER "', member='miracast_wfd_source_status_changed'"
207
208 #define FILTER_BLUEZ                                       \
209     "type='signal',"                                       \
210     " interface='" DBUS_INTERFACE_BLUEZ_HEADSET "', member='PropertyChanged'"
211
212 static const char* const valid_alsa_device_modargs[] = {
213     "name",
214     "sink_name",
215     "sink_properties",
216     "source_name",
217     "source_properties",
218     "namereg_fail",
219     "device",
220     "device_id",
221     "format",
222     "rate",
223     "alternate_rate",
224     "channels",
225     "channel_map",
226     "fragments",
227     "fragment_size",
228     "mmap",
229     "tsched",
230     "tsched_buffer_size",
231     "tsched_buffer_watermark",
232     "ignore_dB",
233     "control",
234     "rewind_safeguard",
235     "deferred_volume",
236     "deferred_volume_safety_margin",
237     "deferred_volume_extra_delay",
238     "fixed_latency_range",
239     "need_audio_pm",
240     "start_threshold",
241     NULL
242 };
243
244 #define BT_CVSD_CODEC_ID 1 // narrow-band
245 #define BT_MSBC_CODEC_ID 2 // wide-band
246 /*
247     Enums for represent values which is defined on other module.
248     This is needed to identify values which are sent by dbus or vconf.
249 */
250 typedef enum external_value_earjack_type {
251     EARJACK_DISCONNECTED = 0,
252     EARJACK_TYPE_SPK_ONLY = 1,
253     EARJACK_TYPE_SPK_WITH_MIC = 3,
254 } external_value_earjack_t;
255
256 typedef enum external_value_bt_sco_type {
257     BT_SCO_DISCONNECTED = 0,
258     BT_SCO_CONNECTED = 1,
259 } external_value_bt_sco_t;
260
261 typedef enum external_value_forwarding_type {
262     FORWARDING_DISCONNECTED = 0,
263     FORWARDING_CONNECTED = 1,
264 } external_value_mirroring_t;
265
266 typedef enum external_value_hdmi_type {
267     HDMI_AUDIO_DISCONNECTED = -1,
268     HDMI_AUDIO_NOT_AVAILABLE = 0,
269     HDMI_AUDIO_AVAILABLE = 1,
270 } external_value_hdmi_t;
271
272
273 /*
274     Enums for represent device detected status (through dbus)
275     When some device is detected, one of these values should be saved in device_status hashmap.
276     device_detected_type_t is needed to distinguish detected device-types ( ex. earjack which can be out or both way)
277     So If you just want to know whether detected or not, can device_detected_t as mask.
278 */
279
280 typedef enum device_detected_type {
281     DEVICE_DISCONNECTED = 0x0,
282     DEVICE_CONNECTED = 0x1,
283     DEVICE_CONNECTED_AUDIO_JACK_4P = DEVICE_CONNECTED | 0x2,
284     DEVICE_CONNECTED_AUDIO_JACK_3P = DEVICE_CONNECTED | 0x4,
285     DEVICE_CONNECTED_SCO = DEVICE_CONNECTED | 0x8,
286     DEVICE_OPENED_SCO = DEVICE_CONNECTED | 0xF,
287 } device_detected_type_t;
288
289 typedef enum dm_device_class_type {
290     DM_DEVICE_CLASS_NONE,
291     DM_DEVICE_CLASS_ALSA,
292     DM_DEVICE_CLASS_TIZEN,
293     DM_DEVICE_CLASS_BT,
294     DM_DEVICE_CLASS_NULL,
295     DM_DEVICE_CLASS_MAX,
296 } dm_device_class_t;
297
298 typedef enum {
299     DEVICE_IO_DIRECTION_IN_FLAG      = 0x0001,  /**< Flag for input devices */
300     DEVICE_IO_DIRECTION_OUT_FLAG     = 0x0002,  /**< Flag for output devices */
301     DEVICE_IO_DIRECTION_BOTH_FLAG    = 0x0004,  /**< Flag for input/output devices (both directions are available) */
302     DEVICE_TYPE_INTERNAL_FLAG        = 0x0010,  /**< Flag for built-in devices */
303     DEVICE_TYPE_EXTERNAL_FLAG        = 0x0020,  /**< Flag for external devices */
304     DEVICE_STATE_DEACTIVATED_FLAG    = 0x1000,  /**< Flag for deactivated devices */
305     DEVICE_STATE_ACTIVATED_FLAG      = 0x2000,  /**< Flag for activated devices */
306     DEVICE_ALL_FLAG                  = 0xFFFF,  /**< Flag for all devices */
307 } device_flag_t;
308
309 typedef enum {
310     DEVICE_IO_DIRECTION_FLAGS        = 0x000F,  /**< Flag for io direction */
311     DEVICE_TYPE_FLAGS                = 0x00F0,  /**< Flag for device type */
312     DEVICE_STATE_FLAGS               = 0xF000,  /**< Flag for device state */
313 } device_flags_type_t;
314
315 typedef enum dm_device_bt_mode_type {
316     DM_DEVICE_BT_MODE_MEDIA = 0x1,
317     DM_DEVICE_BT_MODE_VOICE = 0x2
318 } dm_device_bt_mode_t;
319
320 typedef enum dm_device_changed_into_type {
321     DM_DEVICE_CHANGED_INFO_STATE,
322     DM_DEVICE_CHANGED_INFO_IO_DIRECTION,
323     DM_DEVICE_CHANGED_INFO_MAX
324 } dm_device_changed_info_t;
325
326
327 /*
328     Structure to save parsed information about device-file.
329 */
330 struct device_file_map {
331     /* { key:device_string -> value:device_file_prop } */
332     pa_idxset *playback;
333     pa_idxset *capture;
334 };
335
336 /***************** structures for static information get from json *********/
337
338 /*
339     Structure for informations related to some device-file(ex. 0:0)
340 */
341 struct device_file_info {
342     /*
343         String for identify target device.
344         ex) alsa:0,0  or null ..
345     */
346     const char *device_string;
347     /*
348         For save roles which are supported on device file, and parameters.
349         { key:device_role -> value:parameters for load sink/source }
350         ex) "normal"->"rate=44100 tsched=0", "uhqa"->"rate=192000 mmap=1"
351     */
352     pa_hashmap *roles;
353     /*
354         For save device-types related to device file.
355         { key:device_type-> value:pulse_device_prop }
356     */
357     pa_hashmap *device_types;
358 };
359
360 /* structure for represent device-types(ex. builtin-speaker) properties*/
361 struct device_type_info {
362     const char *type;
363     /*
364         For save supported roles and related device-file.
365         { key:role -> value:device_string ]
366     */
367     pa_hashmap *playback_devices;
368     pa_hashmap *capture_devices;
369 };
370
371 struct device_status_info {
372     char *type;
373     char *name;
374     /* Identify devices among same device-types (for multi-device), currently not works*/
375     char *system_id;
376     device_detected_type_t detected;
377 };
378
379 struct pulse_device_prop {
380     /* roles related to (device_type + device_file)*/
381     pa_idxset *roles;
382     /* For save that this devie_type is activated or not on sink/source */
383     int status;
384 };
385 /******************************************************************************/
386 struct pa_device_manager {
387     PA_REFCNT_DECLARE;
388
389     pa_core *core;
390     pa_hook_slot *sink_put_hook_slot, *sink_unlink_hook_slot, *sink_state_changed_slot;
391     pa_hook_slot *source_put_hook_slot, *source_unlink_hook_slot, *source_state_changed_slot;
392     pa_hook_slot *comm_hook_device_connection_changed_slot;
393     pa_hook_slot *comm_hook_device_state_changed_slot;
394     pa_hook_slot *comm_hook_device_running_changed_slot;
395     pa_communicator *comm;
396     pa_hal_interface *hal_interface;
397
398     /*
399        Idxset for save parsed information about device-type.
400        { device_type_info }
401     */
402     pa_idxset *type_infos;
403     /* For save Parsed information about device-file */
404     struct device_file_map *file_map;
405
406     /* device list */
407     pa_idxset *device_list;
408     /*
409        Hashmap for save statuses got through dbus.
410        { key:device_type -> value:(audio_detected_type_t or device_detected_t) }
411     */
412     pa_idxset *device_status;
413     pa_dbus_connection *dbus_conn;
414 };
415
416 struct composite_type {
417     const char *type;
418     const char *role;
419 };
420
421 #ifdef HAVE_DBUS
422
423 /*** Defines for method handle ***/
424 /* method handlers */
425 static void handle_get_connected_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
426 static void handle_get_device_by_id(DBusConnection *conn, DBusMessage *msg, void *userdata);
427 static void handle_is_stream_on_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
428 static void handle_get_bt_a2dp_status(DBusConnection *conn, DBusMessage *msg, void *userdata);
429 static void handle_get_supported_sample_rates(DBusConnection *conn, DBusMessage *msg, void *userdata);
430 static void handle_set_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata);
431 static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata);
432 static void handle_set_specific_stream_only(DBusConnection *conn, DBusMessage *msg, void *userdata);
433 static void handle_get_specified_stream(DBusConnection *conn, DBusMessage *msg, void *userdata);
434 static void handle_load_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
435 static void handle_unload_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
436 static void handle_unload_sink_with_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata);
437 static void handle_get_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata);
438 static void handle_dump_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
439 static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata);
440
441 static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name);
442
443 enum method_handler_index {
444     METHOD_HANDLER_GET_CONNECTED_DEVICE_LIST,
445     METHOD_HANDLER_GET_DEVICE_BY_ID,
446     METHOD_HANDLER_IS_STREAM_ON_DEVICE,
447     METHOD_HANDLER_GET_BT_A2DP_STATUS,
448     METHOD_HANDLER_LOAD_SINK,
449     METHOD_HANDLER_UNLOAD_SINK,
450     METHOD_HANDLER_UNLOAD_SINK_WITH_DEVICE_STRING,
451     METHOD_HANDLER_GET_DEVICE_STRING,
452     METHOD_HANDLER_GET_SUPPORTED_SAMPLE_RATES,
453     METHOD_HANDLER_SET_SAMPLE_RATE,
454     METHOD_HANDLER_GET_SAMPLE_RATE,
455     METHOD_HANDLER_SET_SPECIFIC_STREAM_ONLY,
456     METHOD_HANDLER_GET_SPECIFIED_STREAM,
457     METHOD_HANDLER_DUMP_DEVICE_LIST,
458     METHOD_HANDLER_STATUS_TEST,
459     METHOD_HANDLER_MAX
460 };
461
462 static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
463     [METHOD_HANDLER_GET_CONNECTED_DEVICE_LIST] = {
464         .method_name = "GetConnectedDeviceList",
465         .receive_cb = handle_get_connected_device_list },
466     [METHOD_HANDLER_GET_DEVICE_BY_ID] = {
467         .method_name = "GetDeviceById",
468         .receive_cb = handle_get_device_by_id },
469     [METHOD_HANDLER_IS_STREAM_ON_DEVICE] = {
470         .method_name = "IsStreamOnDevice",
471         .receive_cb = handle_is_stream_on_device },
472     [METHOD_HANDLER_GET_BT_A2DP_STATUS] = {
473         .method_name = "GetBTA2DPStatus",
474         .receive_cb = handle_get_bt_a2dp_status },
475     [METHOD_HANDLER_LOAD_SINK] = {
476         .method_name = "LoadSink",
477         .receive_cb = handle_load_sink },
478     [METHOD_HANDLER_UNLOAD_SINK] = {
479         .method_name = "UnloadSink",
480         .receive_cb = handle_unload_sink },
481     [METHOD_HANDLER_UNLOAD_SINK_WITH_DEVICE_STRING] = {
482         .method_name = "UnloadSinkWithDeviceString",
483         .receive_cb = handle_unload_sink_with_device_string },
484     [METHOD_HANDLER_GET_DEVICE_STRING] = {
485         .method_name = "GetDeviceString",
486         .receive_cb = handle_get_device_string },
487     [METHOD_HANDLER_GET_SUPPORTED_SAMPLE_RATES] = {
488         .method_name = "GetSupportedSampleRates",
489         .receive_cb = handle_get_supported_sample_rates },
490     [METHOD_HANDLER_SET_SAMPLE_RATE] = {
491         .method_name = "SetSampleRate",
492         .receive_cb = handle_set_sample_rate },
493     [METHOD_HANDLER_GET_SAMPLE_RATE] = {
494         .method_name = "GetSampleRate",
495         .receive_cb = handle_get_sample_rate },
496     [METHOD_HANDLER_SET_SPECIFIC_STREAM_ONLY] = {
497         .method_name = "SetSpecificStreamOnly",
498         .receive_cb = handle_set_specific_stream_only },
499     [METHOD_HANDLER_GET_SPECIFIED_STREAM] = {
500         .method_name = "GetSpecifiedStream",
501         .receive_cb = handle_get_specified_stream },
502     [METHOD_HANDLER_DUMP_DEVICE_LIST] = {
503         .method_name = "DumpDeviceList",
504         .receive_cb = handle_dump_device_list },
505     [METHOD_HANDLER_STATUS_TEST] = {
506         .method_name = "TestStatusChange",
507         .receive_cb = handle_test_device_status_change },
508 };
509
510 #endif
511
512 enum internal_codec_device_index {
513     DEVICE_INDEX_BUILTIN_SPEAKER,
514     DEVICE_INDEX_BUILTIN_RECEIVER,
515     DEVICE_INDEX_BUILTIN_MIC,
516     DEVICE_INDEX_AUDIO_JACK,
517     DEVICE_INDEX_BT_SCO,
518     DEVICE_INDEX_MAX
519 };
520
521 typedef struct _internal_codec_device {
522     const char *type;
523     bool is_running[2]; /* index[in:0, out:1] */
524 } internal_codec_device;
525
526 static internal_codec_device internal_codec_devices[DEVICE_INDEX_MAX] = {
527     [DEVICE_INDEX_BUILTIN_SPEAKER] = {
528         .type = DEVICE_TYPE_SPEAKER,
529         .is_running[0] = false,
530         .is_running[1] = false },
531     [DEVICE_INDEX_BUILTIN_RECEIVER] = {
532         .type = DEVICE_TYPE_RECEIVER,
533         .is_running[0] = false,
534         .is_running[1] = false },
535     [DEVICE_INDEX_BUILTIN_MIC] = {
536         .type = DEVICE_TYPE_MIC,
537         .is_running[0] = false,
538         .is_running[1] = false },
539     [DEVICE_INDEX_AUDIO_JACK] = {
540         .type = DEVICE_TYPE_AUDIO_JACK,
541         .is_running[0] = false,
542         .is_running[1] = false },
543     [DEVICE_INDEX_BT_SCO] = {
544         .type = DEVICE_TYPE_BT_SCO,
545         .is_running[0] = false,
546         .is_running[1] = false },
547 };
548
549 static inline void internal_codec_devices_dump() {
550     uint32_t i;
551     pa_log_info("========== devices using internal codec ==========");
552     for (i = 0; i < DEVICE_INDEX_MAX; i++)
553         pa_log_info(" type[%18s], is_running[in:%d,out:%d]", internal_codec_devices[i].type,
554                      internal_codec_devices[i].is_running[0], internal_codec_devices[i].is_running[1]);
555     pa_log_info("==================================================");
556 }
557
558 static inline void simple_device_dump(pa_log_level_t level, const char *prefix, int id, const char *type, const char *name, int direction, int state) {
559     pa_logl(level, "%s device id(%d) type(%s) name (%s) direction(%d) state(%d)",
560             pa_strempty(prefix), id, pa_strnull(type), pa_strnull(name), direction, state);
561 }
562
563 static void find_device_and_set_running(pa_device_manager *dm, const char *type, bool is_running) {
564     pa_tz_device* device;
565
566     pa_assert(dm);
567
568     if (!type)
569         return;
570
571     pa_log_info("find device [%s]", type);
572
573     if ((device = pa_device_manager_get_device(dm, type))) {
574         if (pa_tz_device_is_use_internal_codec(device))
575             pa_tz_device_set_running_and_notify(device, is_running);
576         else
577             pa_log_warn("this device [%s] does not use internal codec, skip it", type);
578     } else {
579         pa_log_warn("cound not find a device of [%s]", type);
580     }
581 }
582
583 static void type_info_free_func(struct device_type_info *type_info) {
584     if (!type_info)
585         return;
586
587     if (type_info->playback_devices)
588         pa_hashmap_free(type_info->playback_devices);
589     if (type_info->capture_devices)
590         pa_hashmap_free(type_info->capture_devices);
591
592 }
593
594 static void file_info_free_func(struct device_file_info *file_info) {
595     if (!file_info)
596         return;
597
598     if (file_info->roles)
599         pa_hashmap_free(file_info->roles);
600 }
601
602 static dm_device_class_t device_string_get_class(const char *device_string) {
603     if (!device_string) {
604         return DM_DEVICE_CLASS_NONE;
605     }
606
607     if (device_string == strstr(device_string, "alsa")) {
608         return DM_DEVICE_CLASS_ALSA;
609     } else if (device_string == strstr(device_string, "null")) {
610         return DM_DEVICE_CLASS_NULL;
611     } else if (device_string == strstr(device_string, "tizen")) {
612         return DM_DEVICE_CLASS_TIZEN;
613     } else {
614         return DM_DEVICE_CLASS_NONE;
615     }
616 }
617
618 static const char* device_string_get_value(const char *device_string) {
619     int len;
620     const char *end_p, *value_p;
621
622     if (!device_string) {
623         return NULL;
624     }
625
626     len = strlen(device_string);
627     end_p = device_string + len -1;
628
629     if (!(value_p = strchr(device_string, ':'))) {
630         return NULL;
631     }
632     if (value_p < end_p) {
633         return value_p + 1;
634     } else {
635         return NULL;
636     }
637 }
638
639 static pa_proplist* pulse_device_get_proplist(pa_object *pdevice) {
640     if (pa_sink_isinstance(pdevice))
641         return PA_SINK(pdevice)->proplist;
642     else
643         return PA_SOURCE(pdevice)->proplist;
644 }
645
646 static bool pulse_device_is_alsa(pa_object *pdevice) {
647     const char *api_name = NULL;
648     pa_proplist *prop;
649
650     if ((prop = pulse_device_get_proplist(pdevice)) == NULL)
651         return false;
652
653     if ((api_name = pa_proplist_gets(prop, PA_PROP_DEVICE_API))) {
654         if (pa_streq(api_name, DEVICE_API_ALSA)) {
655             return true;
656         } else {
657             return false;
658         }
659     } else {
660         return false;
661     }
662 }
663
664 static bool pulse_device_is_bluez(pa_object *pdevice) {
665     const char *api_name = NULL;
666     pa_proplist *prop;
667
668     if ((prop = pulse_device_get_proplist(pdevice)) == NULL)
669         return false;
670
671     if ((api_name = pa_proplist_gets(prop, PA_PROP_DEVICE_API))) {
672         if (pa_streq(api_name, DEVICE_API_BLUEZ)) {
673             return true;
674         } else {
675             return false;
676         }
677     } else {
678         return false;
679     }
680 }
681
682 static bool pulse_device_is_tizenaudio(pa_object *pdevice) {
683     if (!pdevice)
684         return false;
685
686     if (pa_sink_isinstance(pdevice)) {
687         pa_sink *sink = PA_SINK(pdevice);
688         return pa_streq(sink->module->name, "module-tizenaudio-sink");
689     } else {
690         pa_source *source = PA_SOURCE(pdevice);
691         return pa_streq(source->module->name, "module-tizenaudio-source");
692     }
693 }
694
695 static bool pulse_device_is_usb(pa_object *pdevice) {
696     const char *bus_name = NULL;
697     pa_proplist *prop;
698
699     if ((prop = pulse_device_get_proplist(pdevice)) == NULL)
700         return false;
701
702     if ((bus_name = pa_proplist_gets(prop, PA_PROP_DEVICE_BUS))) {
703         if (pa_streq(bus_name, DEVICE_BUS_USB)) {
704             return true;
705         } else {
706             return false;
707         }
708     } else {
709         pa_log_debug("This device doesn't have property '%s'", PA_PROP_DEVICE_BUS);
710         return false;
711     }
712 }
713
714 static bool pulse_device_is_null(pa_object *pdevice) {
715     pa_sink *sink;
716     pa_source *source;
717
718     if (!pdevice)
719         return false;
720
721     if (pa_sink_isinstance(pdevice)) {
722         sink = PA_SINK(pdevice);
723         return pa_streq(sink->module->name, "module-null-sink");
724     } else {
725         source = PA_SOURCE(pdevice);
726         return pa_streq(source->module->name, "module-null-source");
727     }
728 }
729
730 static const char* pulse_device_get_device_string_removed_argument(pa_object *pdevice) {
731     static char removed_param[DEVICE_PARAM_STRING_MAX] = {0,};
732     char *device_string_p = NULL;
733     char *next_p = NULL;
734     const char *params_p, *params;
735     char *end_p = NULL;
736     int len = 0, prev_len = 0;
737     pa_sink *sink;
738     pa_source *source;
739
740     if (pa_sink_isinstance(pdevice)) {
741         sink = PA_SINK(pdevice);
742         params = sink->module->argument;
743     } else {
744         source = PA_SOURCE(pdevice);
745         params = source->module->argument;
746     }
747
748     params_p = params;
749
750     if (!params) {
751         return NULL;
752     }
753     if (!(device_string_p = strstr(params, "device="))) {
754         return params;
755     }
756
757     next_p = device_string_p;
758     while (!isblank(*next_p)) {
759         next_p++;
760     }
761     while (isblank(*next_p)) {
762         next_p++;
763     }
764
765     pa_strlcpy(removed_param, next_p, DEVICE_PARAM_STRING_MAX);
766
767     if (device_string_p > params_p) {
768         prev_len = device_string_p - params_p;
769         len = strlen(removed_param);
770         end_p = removed_param + len;
771         *end_p = ' ';
772         end_p++;
773         strncpy(end_p, params_p, prev_len);
774     }
775
776     return removed_param;
777 }
778
779 static dm_device_class_t pulse_device_get_class(pa_object *pdevice) {
780
781     if (!pdevice) {
782         pa_log_error("pdevice null");
783         return DM_DEVICE_CLASS_NONE;
784     }
785
786     if (pulse_device_is_null(pdevice)) {
787         return DM_DEVICE_CLASS_NULL;
788     } else if (pulse_device_is_alsa(pdevice)) {
789         return DM_DEVICE_CLASS_ALSA;
790     } else if (pulse_device_is_tizenaudio(pdevice)) {
791         return DM_DEVICE_CLASS_TIZEN;
792     } else if (pulse_device_is_bluez(pdevice)) {
793         return DM_DEVICE_CLASS_BT;
794     } else {
795         return DM_DEVICE_CLASS_NONE;
796     }
797 }
798
799 static dm_device_direction_t pulse_device_get_direction(pa_object *pdevice) {
800     if (pa_sink_isinstance(pdevice))
801         return DM_DEVICE_DIRECTION_OUT;
802     else
803         return DM_DEVICE_DIRECTION_IN;
804 }
805
806 static bool pulse_device_is_monitor(pa_object *pdevice) {
807     const char *device_class = NULL;
808     pa_proplist *prop;
809
810     prop = pulse_device_get_proplist(pdevice);
811
812     if ((device_class = pa_proplist_gets(prop, PA_PROP_DEVICE_CLASS))) {
813         if (device_class && pa_streq(device_class, DEVICE_CLASS_MONITOR)) {
814             return true;
815         } else {
816             return false;
817         }
818     } else {
819         return false;
820     }
821 }
822
823 static int pulse_device_get_alsa_device_string(pa_proplist *prop, char **device_string) {
824     const char *device_string_prop = NULL;
825     char *device_string_tmp;
826
827     if (!prop || !device_string) {
828         pa_log_error("Invalid Parameter");
829         return -1;
830     }
831
832     if (!(device_string_prop = pa_proplist_gets(prop, "device.string"))) {
833         pa_log_error("failed to get property 'device.string'");
834         return -1;
835     }
836     if (!(device_string_tmp = strchr(device_string_prop, ':'))) {
837         pa_log_error("failed to parse device string");
838         return -1;
839     }
840
841     *device_string = device_string_tmp + 1;
842
843     return 0;
844 }
845
846 static const char* device_class_get_module_name(dm_device_class_t device_class, bool is_sink) {
847     if (device_class == DM_DEVICE_CLASS_NONE) {
848         return NULL;
849     } else if (device_class == DM_DEVICE_CLASS_ALSA) {
850         return is_sink ? "module-alsa-sink" : "module-alsa-source";
851     } else if (device_class == DM_DEVICE_CLASS_TIZEN) {
852         return is_sink ? "module-tizenaudio-sink" : NULL;
853     } else if (device_class == DM_DEVICE_CLASS_BT) {
854         return is_sink ? "module-bluez5-device" : NULL;
855     } else if (device_class == DM_DEVICE_CLASS_NULL) {
856         return is_sink ? "module-null-sink" : "module-null-source";
857     } else {
858         return NULL;
859     }
860 }
861
862 static struct device_type_info* _device_manager_get_type_info(pa_idxset *type_infos, const char *type) {
863     struct device_type_info *type_info;
864     uint32_t type_idx;
865
866     PA_IDXSET_FOREACH(type_info, type_infos, type_idx) {
867         if (device_type_is_equal(type_info->type, type)) {
868             return type_info;
869         }
870     }
871
872     return NULL;
873 }
874
875 static struct device_file_info* _device_manager_get_file_info(pa_idxset *file_infos, const char *device_string) {
876     struct device_file_info *file_info;
877     uint32_t file_idx;
878
879     pa_assert(file_infos);
880
881     PA_IDXSET_FOREACH(file_info, file_infos, file_idx) {
882         if (file_info->device_string) {
883             if (pa_streq(file_info->device_string, device_string)) {
884                 return file_info;
885             }
886         }
887     }
888
889     return NULL;
890 }
891
892 static struct device_status_info* _device_status_new(const char *type,
893         const char *name, const char *system_id) {
894     struct device_status_info *status_info;
895
896     status_info = (struct device_status_info *) pa_xmalloc0(sizeof(struct device_status_info));
897     status_info->type = pa_xstrdup(type);
898     status_info->name = pa_xstrdup(name);
899     status_info->system_id = pa_xstrdup(system_id);
900     status_info->detected = DEVICE_DISCONNECTED;
901
902     return status_info;
903 }
904
905 static void _device_status_free(struct device_status_info *status_info) {
906     if (!status_info)
907         return ;
908
909     pa_xfree(status_info->type);
910     pa_xfree(status_info->name);
911     pa_xfree(status_info->system_id);
912     pa_xfree(status_info);
913 }
914
915 static struct device_status_info* _get_device_status(pa_device_manager *manager, const char *type,
916         const char *system_id) {
917     struct device_status_info *status_info = NULL;
918     uint32_t status_idx;
919
920     pa_assert(manager);
921     pa_assert(manager->device_status);
922
923     PA_IDXSET_FOREACH(status_info, manager->device_status, status_idx) {
924         if (device_type_is_equal(status_info->type, type)) {
925             if (device_type_is_avail_multi_device(type)) {
926                 /* if system_id is null, just compare type */
927                 if (system_id == NULL)
928                     return status_info;
929                 else if (status_info->system_id == NULL)
930                     continue;
931                 else if (pa_streq(status_info->system_id, system_id))
932                     return status_info;
933                 else
934                     continue;
935             } else {
936                 return status_info;
937             }
938         }
939     }
940
941     return NULL;
942 }
943
944 static const char* _file_infos_get_param(pa_idxset *file_infos, const char *device_string, const char *role) {
945     struct device_file_info *file_info;
946     const char *params;
947
948     if (!(file_info = _device_manager_get_file_info(file_infos, device_string))) {
949         pa_log_error("No file map for '%s'", device_string);
950         return NULL;
951     }
952
953     if (!(params = pa_hashmap_get(file_info->roles, role)))
954         pa_log_error("No params for '%s:%s'", device_string, role);
955
956     return params;
957 }
958
959 static device_detected_type_t _device_get_detected(pa_device_manager *manager, const char *type,
960         const char *system_id) {
961     struct device_status_info *status_info;
962
963     pa_assert(manager);
964     pa_assert(manager->device_status);
965     pa_assert(type);
966
967     if (!device_type_is_need_detect(type))
968         return DEVICE_CONNECTED;
969
970     status_info = _get_device_status(manager, type, system_id);
971     if (!status_info) {
972         pa_log_info("No status info for type(%s) system_id(%s)",
973                 type, pa_strempty(system_id));
974         return DEVICE_DISCONNECTED;
975     }
976
977     pa_log_debug("Get device detected, type(%s) system_id(%s) : %s(%d)",
978             type, pa_strempty(system_id),
979              (status_info->detected & DEVICE_CONNECTED) ? "Connected" : "Disconnected", status_info->detected);
980
981     return status_info->detected;
982 }
983
984 static void _device_set_detected(pa_device_manager *manager, const char *type,
985         const char *name, const char *system_id, device_detected_type_t detected_type) {
986     struct device_status_info *status_info;
987
988     pa_assert(manager);
989     pa_assert(manager->device_status);
990     pa_assert(type);
991
992     if (!device_type_is_need_detect(type))
993         return ;
994
995     pa_log_info("Set device detected, type(%s) system_id(%s) -> %s(%d)",
996             type, pa_strempty(system_id),
997             (detected_type & DEVICE_CONNECTED) ? "Connected" : "Disconnected", detected_type);
998
999     if (detected_type & DEVICE_CONNECTED) {
1000         status_info = _get_device_status(manager, type, system_id);
1001         if (!status_info) {
1002             status_info = _device_status_new(type, name, system_id);
1003             pa_idxset_put(manager->device_status, status_info, NULL);
1004         }
1005         status_info->detected = detected_type;
1006     } else {
1007         status_info = _get_device_status(manager, type, system_id);
1008         if (status_info) {
1009             pa_idxset_remove_by_data(manager->device_status, status_info, NULL);
1010             _device_status_free(status_info);
1011         }
1012     }
1013 }
1014
1015 static pa_tz_device* _device_list_get_device(pa_device_manager *manager, const char *type, const char *system_id) {
1016     pa_tz_device *device;
1017     uint32_t idx;
1018     char *_type, *_system_id;
1019
1020     pa_assert(manager);
1021     pa_assert(manager->device_list);
1022     pa_assert(type);
1023
1024     PA_IDXSET_FOREACH(device, manager->device_list, idx) {
1025         _type = pa_tz_device_get_type(device);
1026         _system_id = pa_tz_device_get_system_id(device);
1027         if (pa_streq(_type, type)) {
1028             if (device_type_is_avail_multi_device(type)) {
1029                 if (system_id == NULL)
1030                     return device;
1031                 else if (_system_id == NULL)
1032                     continue;
1033                 else if (pa_streq(_system_id, system_id))
1034                     return device;
1035                 else
1036                     continue;
1037             } else {
1038                 return device;
1039             }
1040         }
1041     }
1042
1043     return NULL;
1044 }
1045
1046
1047 static pa_tz_device* _device_list_get_device_by_id(pa_device_manager *manager, uint32_t id) {
1048     pa_tz_device *device;
1049     uint32_t idx;
1050
1051     pa_assert(manager);
1052     pa_assert(manager->device_list);
1053
1054     PA_IDXSET_FOREACH(device, manager->device_list, idx) {
1055         if (pa_tz_device_get_id(device) == id) {
1056             return device;
1057         }
1058     }
1059     return NULL;
1060 }
1061
1062 static const char* build_params_to_load_device(const char *device_string, const char *params, dm_device_class_t device_class) {
1063     pa_strbuf *args_buf;
1064     static char args[DEVICE_PARAM_STRING_MAX] = {0,};
1065
1066     if (!device_string) {
1067         pa_log_error("device string null");
1068         return NULL;
1069     }
1070
1071     if (device_class == DM_DEVICE_CLASS_NULL) {
1072         return params;
1073     } else if (device_class == DM_DEVICE_CLASS_ALSA) {
1074         const char *alsa_device_name;
1075         if (!(alsa_device_name = device_string_get_value(device_string))) {
1076             pa_log_error("Invalid device string for alsa-device, '%s'", device_string);
1077             return NULL;
1078         }
1079         args_buf = pa_strbuf_new();
1080         pa_strbuf_printf(args_buf, "device=hw:%s ", alsa_device_name);
1081         if (params) {
1082             pa_strbuf_printf(args_buf, "%s", params);
1083         }
1084         pa_strlcpy(args, pa_strbuf_to_string_free(args_buf), DEVICE_PARAM_STRING_MAX);
1085     } else {
1086         return params;
1087     }
1088
1089     return (const char*) args;
1090 }
1091
1092 static bool device_params_is_equal(const char *params1, const char *params2) {
1093     const char *key = NULL;
1094     const char *value1, *value2;
1095     pa_modargs *modargs1, *modargs2;
1096     void *state = NULL;
1097     bool equal = true;
1098
1099     if (!params1 && !params2)
1100         return true;
1101     if (!params1 || !params2)
1102         return false;
1103
1104     modargs1 = pa_modargs_new(params1, valid_alsa_device_modargs);
1105     modargs2 = pa_modargs_new(params2, valid_alsa_device_modargs);
1106
1107     if (!modargs1 || !modargs2) {
1108         equal = false;
1109         goto finish;
1110     }
1111
1112     for (state = NULL, key = pa_modargs_iterate(modargs1, &state); key; key = pa_modargs_iterate(modargs1, &state)) {
1113         value1 = pa_modargs_get_value(modargs1, key, NULL);
1114         value2 = pa_modargs_get_value(modargs2, key, NULL);
1115         if (!value1 || !value2 || !pa_streq(value1, value2)) {
1116             equal = false;
1117             goto finish;
1118         }
1119     }
1120
1121     for (state = NULL, key = pa_modargs_iterate(modargs2, &state); key; key = pa_modargs_iterate(modargs2, &state)) {
1122         value1 = pa_modargs_get_value(modargs1, key, NULL);
1123         value2 = pa_modargs_get_value(modargs2, key, NULL);
1124         if (!value1 || !value2 || !pa_streq(value1, value2)) {
1125             equal = false;
1126             goto finish;
1127         }
1128     }
1129
1130 finish:
1131
1132     if (modargs1)
1133         pa_modargs_free(modargs1);
1134     if (modargs2)
1135         pa_modargs_free(modargs2);
1136
1137
1138     return equal;
1139 }
1140
1141 static bool pulse_device_params_is_equal(pa_object *pdevice, const char *params) {
1142     const char *removed_module_args;
1143     const char *module_args;
1144     pa_sink *sink;
1145     pa_source *source;
1146
1147     pa_assert(pdevice);
1148
1149     if (pa_sink_isinstance(pdevice)) {
1150         sink = PA_SINK(pdevice);
1151         module_args = sink->module->argument;
1152     } else {
1153         source = PA_SOURCE(pdevice);
1154         module_args = source->module->argument;
1155     }
1156
1157     if (!params && !module_args)
1158         return 0;
1159     if (!params || !module_args)
1160         return -1;
1161
1162     removed_module_args = pulse_device_get_device_string_removed_argument(pdevice);
1163     return device_params_is_equal(params, removed_module_args);
1164 }
1165
1166 static const char* pulse_device_get_device_string(pa_object *pdevice) {
1167     dm_device_class_t device_class;
1168     static char device_string[DEVICE_STR_MAX] = {0,};
1169     char *device_string_val = NULL;
1170     pa_proplist *prop;
1171
1172     pa_assert(pdevice);
1173
1174     device_class = pulse_device_get_class(pdevice);
1175     prop = pulse_device_get_proplist(pdevice);
1176
1177     if (device_class == DM_DEVICE_CLASS_ALSA) {
1178         if (pulse_device_get_alsa_device_string(prop, &device_string_val) < 0)
1179             return NULL;
1180         snprintf(device_string, DEVICE_STR_MAX, "alsa:%s", device_string_val);
1181         return device_string;
1182     } else if (device_class == DM_DEVICE_CLASS_NULL) {
1183         return "null";
1184     } else if (device_class == DM_DEVICE_CLASS_TIZEN) {
1185         return "tizen";
1186     } else if (device_class == DM_DEVICE_CLASS_BT) {
1187         return "bt";
1188     } else {
1189         return device_string;
1190     }
1191 }
1192
1193 /*  pdevice is sink or source */
1194 static bool pulse_device_same_device_string(pa_object *pdevice, const char *device_string) {
1195     const char *_device_string;
1196
1197     pa_assert(pdevice);
1198     pa_assert(device_string);
1199
1200     if (!(_device_string = pulse_device_get_device_string(pdevice)))
1201         return false;
1202
1203     return pa_streq(_device_string, device_string);
1204 }
1205
1206 static const char* device_type_info_get_device_string(struct device_type_info *type_info, bool is_playback, const char *role) {
1207     const char *_role, *device_string;
1208     void *state;
1209     pa_hashmap *pcm_devices;
1210
1211     pcm_devices = is_playback ? type_info->playback_devices : type_info->capture_devices;
1212     if (pcm_devices == NULL) {
1213         pa_log_error("No pcm device config for %s %s %s", is_playback ? "Playback" : "Capture", type_info->type, role);
1214         return NULL;
1215     }
1216
1217     PA_HASHMAP_FOREACH_KV(_role, device_string, pcm_devices, state) {
1218         if (pa_safe_streq(role, _role))
1219             return device_string;
1220     }
1221
1222     return NULL;
1223 }
1224
1225 pa_dynarray* pulse_device_get_belongs_type(pa_object *pdevice, pa_device_manager *dm) {
1226     pa_dynarray *ctypes;
1227     struct composite_type *ctype;
1228     struct device_type_info *type_info;
1229     const char *device_string, *role, *param;
1230     uint32_t type_idx;
1231     pa_device_type_t pdt;
1232     pa_idxset *file_infos;
1233     pa_hashmap *pcm_devices;
1234     void *state;
1235
1236     pa_assert(pdevice);
1237     pa_assert(dm);
1238
1239     pa_log_info("pulse device get belongs type");
1240
1241     if (pulse_device_is_monitor(pdevice))
1242         return NULL;
1243     if (pulse_device_is_usb(pdevice))
1244         return NULL;
1245     if (pulse_device_is_bluez(pdevice))
1246         return NULL;
1247
1248     ctypes = pa_dynarray_new(pa_xfree);
1249
1250     if (pa_sink_isinstance(pdevice)) {
1251         pdt = PA_DEVICE_TYPE_SINK;
1252         file_infos = dm->file_map->playback;
1253     } else {
1254         pdt = PA_DEVICE_TYPE_SOURCE;
1255         file_infos = dm->file_map->capture;
1256     }
1257
1258     /* iterate "device-types" in device-map.json */
1259     PA_IDXSET_FOREACH(type_info, dm->type_infos, type_idx) {
1260         if (pdt == PA_DEVICE_TYPE_SINK)
1261             pcm_devices = type_info->playback_devices;
1262         else
1263             pcm_devices = type_info->capture_devices;
1264         if (pcm_devices == NULL)
1265             continue;
1266         /* iterate "{playback,capture}-devices" in specific device-type */
1267         PA_HASHMAP_FOREACH_KV(role, device_string, pcm_devices, state) {
1268             if (pulse_device_same_device_string(pdevice, device_string) == false)
1269                 continue;
1270             param = _file_infos_get_param(file_infos, device_string, role);
1271             if (pulse_device_params_is_equal(pdevice, param) == false)
1272                 continue;
1273             /* Found type.role which is matching with pulse_device */
1274             ctype = pa_xmalloc0(sizeof(struct composite_type));
1275             ctype->type = type_info->type;
1276             ctype->role = role;
1277             pa_dynarray_append(ctypes, ctype);
1278         }
1279     }
1280
1281     if (pa_dynarray_size(ctypes) == 0) {
1282         pa_dynarray_free(ctypes);
1283         ctypes = NULL;
1284     }
1285
1286     return ctypes;
1287 }
1288
1289 static const char* pulse_device_get_device_name(pa_object *pdevice, const char *type) {
1290     pa_proplist *prop;
1291
1292     pa_assert(pdevice);
1293     pa_assert(device_type_is_valid(type));
1294
1295     prop = pulse_device_get_proplist(pdevice);
1296
1297     if (pa_streq(type, DEVICE_TYPE_USB_AUDIO))
1298         return pa_proplist_gets(prop, "udev.id");
1299     else if (pa_streq(type, DEVICE_TYPE_BT_A2DP))
1300         return pa_proplist_gets(prop, "bluez.alias");
1301     else
1302         return NULL;
1303 }
1304
1305 /* If fails return -1 */
1306 static int atoi_base16(const char *s) {
1307     char *x = NULL;
1308     long l;
1309
1310     pa_assert(s);
1311
1312     errno = 0;
1313     l = strtol(s, &x, 16);
1314
1315     if (!x || *x || errno) {
1316         pa_log_error("Convert Failed");
1317         return -1;
1318     }
1319
1320     if ((int) l != l) {
1321         pa_log_error("Range error, does not fit into int");
1322         return -1;
1323     }
1324
1325     return (int) l;
1326 }
1327
1328 static int pulse_device_get_vendor_id(pa_object *pdevice) {
1329     pa_proplist *prop;
1330     const char *vendor_id_s;
1331     int vendor_id;
1332
1333     pa_assert(pdevice);
1334
1335     if (pulse_device_is_usb(pdevice) == false) {
1336         pa_log_warn("Not USB device");
1337         return -1;
1338     }
1339
1340     prop = pulse_device_get_proplist(pdevice);
1341
1342     if ((vendor_id_s = pa_proplist_gets(prop, PA_PROP_DEVICE_VENDOR_ID)) == NULL) {
1343         pa_log_error("No vendor id");
1344         return -1;
1345     }
1346
1347     if ((vendor_id = atoi_base16(vendor_id_s)) == -1) {
1348         pa_log_error("Failed to convert to int");
1349         return -1;
1350     }
1351
1352     return vendor_id;
1353 }
1354
1355 static int pulse_device_get_product_id(pa_object *pdevice) {
1356     pa_proplist *prop;
1357     const char *product_id_s;
1358     int product_id;
1359
1360     pa_assert(pdevice);
1361
1362     if (pulse_device_is_usb(pdevice) == false) {
1363         pa_log_warn("Not USB device");
1364         return -1;
1365     }
1366
1367     prop = pulse_device_get_proplist(pdevice);
1368
1369     if ((product_id_s = pa_proplist_gets(prop, PA_PROP_DEVICE_PRODUCT_ID)) == NULL) {
1370         pa_log_error("No product id");
1371         return -1;
1372     }
1373
1374     if ((product_id = atoi_base16(product_id_s)) == -1) {
1375         pa_log_error("Failed to convert to int");
1376         return -1;
1377     }
1378
1379     return product_id;
1380 }
1381
1382 static void pulse_device_set_use_internal_codec(pa_object *pdevice, bool use_internal_codec) {
1383     pa_assert(pdevice);
1384
1385     if (pa_sink_isinstance(pdevice)) {
1386         pa_sink *sink = PA_SINK(pdevice);
1387         sink->use_internal_codec = use_internal_codec;
1388     } else {
1389         pa_source *source = PA_SOURCE(pdevice);
1390         source->use_internal_codec = use_internal_codec;
1391     }
1392 }
1393
1394 /* Get system_id of physical device, if external device */
1395 static const char* pulse_device_get_system_id(pa_object *pdevice) {
1396     pa_proplist *prop;
1397
1398     prop = pulse_device_get_proplist(pdevice);
1399     if (pulse_device_is_usb(pdevice))
1400         return pa_proplist_gets(prop, "sysfs.path");
1401     else if (pulse_device_is_bluez(pdevice))
1402         return pa_proplist_gets(prop, "bluez.path");
1403     else
1404         return NULL;
1405 }
1406
1407 static pa_sink* _core_get_sink(pa_core *core, const char *device_string, const char *params) {
1408     uint32_t device_idx;
1409     pa_sink *sink;
1410
1411     pa_assert(core);
1412     pa_assert(device_string);
1413
1414     PA_IDXSET_FOREACH(sink, core->sinks, device_idx) {
1415         if (pulse_device_is_monitor(PA_OBJECT(sink)))
1416             continue;
1417         if (pulse_device_same_device_string(PA_OBJECT(sink), device_string)) {
1418             if (params == NULL)
1419                 return sink;
1420             else if (pulse_device_params_is_equal(PA_OBJECT(sink), params))
1421                 return sink;
1422         }
1423     }
1424
1425     return NULL;
1426 }
1427
1428 static pa_source* _core_get_source(pa_core *core, const char *device_string, const char *params) {
1429     uint32_t device_idx;
1430     pa_source *source;
1431
1432     pa_assert(core);
1433     pa_assert(device_string);
1434
1435     PA_IDXSET_FOREACH(source, core->sources, device_idx) {
1436         if (pulse_device_is_monitor(PA_OBJECT(source)))
1437             continue;
1438         if (pulse_device_same_device_string(PA_OBJECT(source), device_string)) {
1439             if (params == NULL)
1440                 return source;
1441             else if (pulse_device_params_is_equal(PA_OBJECT(source), params))
1442                 return source;
1443         }
1444     }
1445
1446     return NULL;
1447 }
1448
1449
1450 static void _fill_new_data_basic(pa_tz_device_new_data *data, const char *type,
1451         dm_device_direction_t direction, bool use_internal_codec, pa_device_manager *dm) {
1452     pa_assert(data);
1453
1454     pa_tz_device_new_data_set_type(data, type);
1455     pa_tz_device_new_data_set_direction(data, direction);
1456     pa_tz_device_new_data_set_use_internal_codec(data, use_internal_codec);
1457 }
1458
1459 static int _fill_new_data_sinks(pa_tz_device_new_data *data, struct device_type_info *type_info, pa_device_manager *dm) {
1460     pa_sink *sink;
1461     const char *device_string, *role, *param;
1462     void *state;
1463     pa_idxset *file_infos;
1464
1465     pa_assert(data);
1466     pa_assert(type_info);
1467
1468     if (type_info->playback_devices == NULL) {
1469         pa_log_error("No playback devices for %s", type_info->type);
1470         return -1;
1471     }
1472
1473     file_infos = dm->file_map->playback;
1474     if (file_infos == NULL) {
1475         pa_log_error("No playback pcm device config");
1476         return -1;
1477     }
1478
1479     PA_HASHMAP_FOREACH_KV(role, device_string, type_info->playback_devices, state) {
1480         param = _file_infos_get_param(file_infos, device_string, role);
1481         sink = _core_get_sink(dm->core, device_string, param);
1482         if (sink)
1483             pa_tz_device_new_data_add_sink(data, role, sink);
1484         else
1485             pa_log_warn("No matching sink for %s %s", device_string, role);
1486     }
1487
1488     return 0;
1489 }
1490
1491 static int _fill_new_data_sources(pa_tz_device_new_data *data, struct device_type_info *type_info, pa_device_manager *dm) {
1492     pa_source *source;
1493     const char *device_string, *role, *param;
1494     void *state;
1495     pa_idxset *file_infos;
1496
1497     pa_assert(data);
1498     pa_assert(type_info);
1499
1500     if (type_info->capture_devices == NULL) {
1501         pa_log_error("No capture devices for %s", type_info->type);
1502         return -1;
1503     }
1504
1505     file_infos = dm->file_map->capture;
1506     if (file_infos == NULL) {
1507         pa_log_error("No capture pcm device config");
1508         return -1;
1509     }
1510
1511     PA_HASHMAP_FOREACH_KV(role, device_string, type_info->capture_devices, state) {
1512         param = _file_infos_get_param(file_infos, device_string, role);
1513         source = _core_get_source(dm->core, device_string, param);
1514         if (source)
1515             pa_tz_device_new_data_add_source(data, role, source);
1516         else
1517             pa_log_warn("No matching source for %s %s", device_string, role);
1518     }
1519
1520     return 0;
1521 }
1522
1523 static pa_sink* _device_manager_set_default_sink(pa_device_manager *dm,  const char *type, const char *role) {
1524     pa_tz_device *device;
1525     pa_sink *sink;
1526
1527     if (!type || !role) {
1528         pa_log_warn("Argument for set_default_sink invalid");
1529         return NULL;
1530     }
1531
1532     if (!(device = _device_list_get_device(dm, type, NULL))) {
1533         pa_log_warn("cannot get device item for %s", type);
1534         return NULL;
1535     }
1536
1537     if (!(sink = pa_tz_device_get_sink(device, role))) {
1538         pa_log_warn("cannot get sink for %s", role);
1539         return NULL;
1540     }
1541
1542 //    sink = pa_namereg_set_default_sink(dm->core, sink);
1543     return sink;
1544 }
1545
1546 static pa_source* _device_manager_set_default_source(pa_device_manager *dm,  const char *type, const char *role) {
1547     pa_tz_device *device;
1548     pa_source *source;
1549
1550     if (!type || !role) {
1551         pa_log_warn("Argument for set_default_source invalid");
1552         return NULL;
1553     }
1554
1555     if (!(device = _device_list_get_device(dm, type, NULL))) {
1556         pa_log_warn("cannot get device item for %s", type);
1557         return NULL;
1558     }
1559
1560     if (!(source = pa_tz_device_get_source(device, role))) {
1561         pa_log_warn("cannot get source for %s", role);
1562         return NULL;
1563     }
1564
1565  //   source = pa_namereg_set_default_source(dm->core, source);
1566     return source;
1567 }
1568
1569 static void handle_usb_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *manager) {
1570     const char *name, *system_id;
1571     dm_device_direction_t direction;
1572     pa_tz_device *device;
1573
1574     pa_assert(pdevice);
1575     pa_assert(manager);
1576
1577     pa_log_info("Handle usb pulse device");
1578
1579     system_id = pulse_device_get_system_id(pdevice);
1580     direction = pulse_device_get_direction(pdevice);
1581
1582     if (is_loaded) {
1583         pa_tz_device_new_data data;
1584         int product_id, vendor_id;
1585
1586         name = pulse_device_get_device_name(pdevice, DEVICE_TYPE_USB_AUDIO);
1587         vendor_id = pulse_device_get_vendor_id(pdevice);
1588         product_id = pulse_device_get_product_id(pdevice);
1589
1590         pa_tz_device_new_data_init(&data, manager->device_list, manager->comm, NULL);
1591         pa_tz_device_new_data_set_type(&data, DEVICE_TYPE_USB_AUDIO);
1592         pa_tz_device_new_data_set_name(&data, name);
1593         pa_tz_device_new_data_set_direction(&data, direction);
1594         pa_tz_device_new_data_set_system_id(&data, system_id);
1595         if (vendor_id > 0)
1596             pa_tz_device_new_data_set_vendor_id(&data, vendor_id);
1597         if (product_id > 0)
1598             pa_tz_device_new_data_set_product_id(&data, product_id);
1599         pa_tz_device_new_data_set_use_internal_codec(&data, false);
1600         if (direction == DM_DEVICE_DIRECTION_OUT)
1601             pa_tz_device_new_data_add_sink(&data, DEVICE_ROLE_NORMAL, PA_SINK(pdevice));
1602         else
1603             pa_tz_device_new_data_add_source(&data, DEVICE_ROLE_NORMAL, PA_SOURCE(pdevice));
1604
1605         pa_tz_device_new(&data);
1606         pa_tz_device_new_data_done(&data);
1607     } else {
1608         if (!(device = _device_list_get_device(manager, DEVICE_TYPE_USB_AUDIO, system_id)))
1609             pa_log_warn("Can't get usb device for %s", system_id);
1610         else
1611             pa_tz_device_free(device);
1612     }
1613 }
1614
1615 static void handle_bt_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *manager) {
1616     dm_device_direction_t direction;
1617     pa_tz_device *device;
1618     const char *system_id;
1619
1620     pa_assert(pdevice);
1621     pa_assert(manager);
1622
1623     pa_log_info("Handle bt pulse device");
1624
1625     direction = pulse_device_get_direction(pdevice);
1626     system_id = pulse_device_get_system_id(pdevice);
1627
1628     if (is_loaded) {
1629         pa_tz_device_new_data data;
1630
1631         const char *name;
1632         name = pulse_device_get_device_name(pdevice, DEVICE_TYPE_BT_A2DP);
1633
1634         pa_tz_device_new_data_init(&data, manager->device_list, manager->comm, manager->dbus_conn);
1635         _fill_new_data_basic(&data, DEVICE_TYPE_BT_A2DP, direction, false, manager);
1636         pa_tz_device_new_data_set_name(&data, name);
1637         pa_tz_device_new_data_set_system_id(&data, system_id);
1638         if (direction == DM_DEVICE_DIRECTION_OUT)
1639             pa_tz_device_new_data_add_sink(&data, DEVICE_ROLE_NORMAL, PA_SINK(pdevice));
1640         else
1641             pa_tz_device_new_data_add_source(&data, DEVICE_ROLE_NORMAL, PA_SOURCE(pdevice));
1642
1643         pa_tz_device_new(&data);
1644         pa_tz_device_new_data_done(&data);
1645     } else {
1646
1647         if (!(device = _device_list_get_device(manager, DEVICE_TYPE_BT_A2DP, system_id)))
1648             pa_log_warn("Can't get bt device for %s", system_id);
1649         else
1650             pa_tz_device_free(device);
1651     }
1652 }
1653
1654 static void handle_internal_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *manager) {
1655     pa_tz_device *device;
1656     struct composite_type *ctype;
1657     pa_dynarray *ctypes;
1658     dm_device_direction_t direction;
1659
1660     pa_assert(pdevice);
1661     pa_assert(manager);
1662
1663     pa_log_info("Handle internal pulse device");
1664     direction = pulse_device_get_direction(pdevice);
1665
1666     /* Get types which this pulse_device belongs to */
1667     if ((ctypes = pulse_device_get_belongs_type(pdevice, manager)) == NULL) {
1668         pa_log_debug("Failed to get device type. Skip this");
1669         return ;
1670     }
1671
1672     if (is_loaded) {
1673         /* Put this pulse_device to already loaded devices */
1674         for (int i = 0; i < pa_dynarray_size(ctypes); i++) {
1675             ctype = pa_dynarray_get(ctypes, i);
1676             pa_log_info("Found belongs type %s %s", ctype->type, ctype->role);
1677             if ((device = _device_list_get_device(manager, ctype->type, NULL))) {
1678                 pa_log_info("Add this pulse_device to device(%u)", pa_tz_device_get_id(device));
1679                 if (direction == DM_DEVICE_DIRECTION_OUT)
1680                     pa_tz_device_add_sink(device, ctype->role, PA_SINK(pdevice));
1681                 else
1682                     pa_tz_device_add_source(device, ctype->role, PA_SOURCE(pdevice));
1683             } else {
1684                 pa_log_info("No device for %s", ctype->type);
1685             }
1686         }
1687     } else {
1688         /* Remove this pulse_device from already loaded devices */
1689         for (int i = 0; i < pa_dynarray_size(ctypes); i++) {
1690             ctype = pa_dynarray_get(ctypes, i);
1691             pa_log_info("Found belongs type %s %s", ctype->type, ctype->role);
1692             if ((device = _device_list_get_device(manager, ctype->type, NULL))) {
1693                 pa_log_info("Remove this pulse_device from device(%u)", pa_tz_device_get_id(device));
1694                 if (direction == DM_DEVICE_DIRECTION_OUT)
1695                     pa_tz_device_remove_sink(device, PA_SINK(pdevice));
1696                 else
1697                     pa_tz_device_remove_source(device, PA_SOURCE(pdevice));
1698             } else {
1699                 pa_log_info("No device for %s", ctype->type);
1700             }
1701         }
1702     }
1703
1704     pa_dynarray_free(ctypes);
1705 }
1706
1707 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, pa_device_manager *dm) {
1708     pa_assert(c);
1709     pa_assert(sink);
1710     pa_assert(dm);
1711
1712     pa_log_info("========== Sink Put Hook Callback '%s'(%d) ==========", sink->name, sink->index);
1713
1714     if (pulse_device_is_monitor(PA_OBJECT(sink)))
1715         return PA_HOOK_OK;
1716
1717     if (pulse_device_is_usb(PA_OBJECT(sink))) {
1718         pulse_device_set_use_internal_codec(PA_OBJECT(sink), false);
1719         handle_usb_pulse_device(PA_OBJECT(sink), true, dm);
1720         return PA_HOOK_OK;
1721     } else if (pulse_device_is_bluez(PA_OBJECT(sink))) {
1722         pulse_device_set_use_internal_codec(PA_OBJECT(sink), false);
1723         handle_bt_pulse_device(PA_OBJECT(sink), true, dm);
1724         return PA_HOOK_OK;
1725     } else if (pulse_device_is_alsa(PA_OBJECT(sink)) || pulse_device_is_tizenaudio(PA_OBJECT(sink))) {
1726         pulse_device_set_use_internal_codec(PA_OBJECT(sink), true);
1727         handle_internal_pulse_device(PA_OBJECT(sink), true, dm);
1728         return PA_HOOK_OK;
1729     } else {
1730         pa_log_debug("Don't care this sink");
1731     }
1732
1733     return PA_HOOK_OK;
1734 }
1735
1736 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, pa_device_manager *dm) {
1737     pa_assert(c);
1738     pa_assert(sink);
1739     pa_assert(dm);
1740
1741     pa_log_info("=========== Sink unlink Hook Callback '%s'(%d) ==========", sink->name, sink->index);
1742
1743     if (pulse_device_is_monitor(PA_OBJECT(sink)))
1744         return PA_HOOK_OK;
1745
1746     if (pulse_device_is_usb(PA_OBJECT(sink))) {
1747         handle_usb_pulse_device(PA_OBJECT(sink), false, dm);
1748         return PA_HOOK_OK;
1749     } else if (pulse_device_is_bluez(PA_OBJECT(sink))) {
1750         handle_bt_pulse_device(PA_OBJECT(sink), false, dm);
1751         return PA_HOOK_OK;
1752     } else if (pulse_device_is_alsa(PA_OBJECT(sink)) || pulse_device_is_tizenaudio(PA_OBJECT(sink))) {
1753         handle_internal_pulse_device(PA_OBJECT(sink), false, dm);
1754         return PA_HOOK_OK;
1755     } else {
1756         pa_log_debug("Don't care this sink");
1757     }
1758
1759     return PA_HOOK_OK;
1760 }
1761
1762 static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, pa_device_manager *dm) {
1763     pa_assert(c);
1764     pa_assert(source);
1765     pa_assert(dm);
1766
1767     pa_log_info("========== source Put Hook Callback '%s'(%d) ==========", source->name, source->index);
1768
1769     if (pulse_device_is_monitor(PA_OBJECT(source)))
1770         return PA_HOOK_OK;
1771
1772     if (pulse_device_is_usb(PA_OBJECT(source))) {
1773         pulse_device_set_use_internal_codec(PA_OBJECT(source), false);
1774         handle_usb_pulse_device(PA_OBJECT(source), true, dm);
1775         return PA_HOOK_OK;
1776     } else if (pulse_device_is_bluez(PA_OBJECT(source))) {
1777         pulse_device_set_use_internal_codec(PA_OBJECT(source), false);
1778         handle_bt_pulse_device(PA_OBJECT(source), true, dm);
1779         return PA_HOOK_OK;
1780     } else if (pulse_device_is_alsa(PA_OBJECT(source)) || pulse_device_is_tizenaudio(PA_OBJECT(source))) {
1781         pulse_device_set_use_internal_codec(PA_OBJECT(source), true);
1782         handle_internal_pulse_device(PA_OBJECT(source), true, dm);
1783         return PA_HOOK_OK;
1784     } else {
1785         pa_log_debug("Don't care this source");
1786     }
1787
1788     return PA_HOOK_OK;
1789 }
1790
1791 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, pa_device_manager *dm) {
1792     pa_assert(c);
1793     pa_assert(source);
1794     pa_assert(dm);
1795
1796     pa_log_info("=========== source unlink Hook Callback '%s'(%d) ==========", source->name, source->index);
1797
1798     if (pulse_device_is_monitor(PA_OBJECT(source)))
1799         return PA_HOOK_OK;
1800
1801     if (pulse_device_is_usb(PA_OBJECT(source))) {
1802         handle_usb_pulse_device(PA_OBJECT(source), false, dm);
1803         return PA_HOOK_OK;
1804     } else if (pulse_device_is_bluez(PA_OBJECT(source))) {
1805         handle_bt_pulse_device(PA_OBJECT(source), false, dm);
1806         return PA_HOOK_OK;
1807     } else if (pulse_device_is_alsa(PA_OBJECT(source)) || pulse_device_is_tizenaudio(PA_OBJECT(source))) {
1808         handle_internal_pulse_device(PA_OBJECT(source), false, dm);
1809         return PA_HOOK_OK;
1810     } else {
1811         pa_log_debug("Don't care this source");
1812     }
1813
1814     return PA_HOOK_OK;
1815 }
1816
1817 #define SINK_NAME_NULL "sink_null"
1818 #define SOURCE_NAME_NULL "source_null"
1819 static pa_hook_result_t sink_source_state_changed_hook_cb(pa_core *c, pa_object *pdevice, pa_device_manager *dm) {
1820     pa_tz_device *device;
1821
1822     pa_assert(c);
1823     pa_object_assert_ref(pdevice);
1824     pa_assert(dm);
1825
1826     if (pa_sink_isinstance(pdevice)) {
1827         pa_sink *s = PA_SINK(pdevice);
1828         pa_sink_state_t state = pa_sink_get_state(s);
1829         pa_log_debug("=========== Sink(%p,%s) state has been changed to [%d](0:RUNNING, 1:IDLE, 2:SUSPEND) ==========", s, s->name, state);
1830         if (!s->use_internal_codec && !pa_streq(s->name, SINK_NAME_NULL))
1831             if ((device = pa_device_manager_get_device_with_sink(s)))
1832                 pa_tz_device_set_running_and_notify(device, (state == PA_SINK_RUNNING));
1833     } else if (pa_source_isinstance(pdevice)) {
1834         pa_source *s = PA_SOURCE(pdevice);
1835         pa_source_state_t state = pa_source_get_state(s);
1836         pa_log_debug("=========== Source(%p,%s) state has been changed to [%d](0:RUNNING, 1:IDLE, 2:SUSPEND) ==========", s, s->name, state);
1837         if (!s->use_internal_codec && !pa_streq(s->name, SOURCE_NAME_NULL))
1838             if ((device = pa_device_manager_get_device_with_source(s)))
1839                 pa_tz_device_set_running_and_notify(device, (state == PA_SOURCE_RUNNING));
1840     }
1841     pa_log_debug("========= sink_source_state_changed_hook_cb END =====");
1842
1843     return PA_HOOK_OK;
1844 }
1845
1846 /*
1847     Build params for load sink or source, and load it.
1848 */
1849
1850 static void* load_device(pa_core *c, bool is_sink, const char *device_string, const char *device_params) {
1851     const char *args = NULL;
1852     const char *module_name;
1853     pa_module *module;
1854     pa_sink *sink;
1855     pa_source *source;
1856     uint32_t device_idx;
1857     dm_device_class_t device_class;
1858
1859     pa_assert(c);
1860     pa_assert(device_string);
1861     pa_assert(device_params);
1862
1863     pa_log_info("Load %s Device : String'%s' Param'%s'", is_sink ? "Playback" : "Capture", device_string, device_params);
1864
1865     device_class = device_string_get_class(device_string);
1866     if (device_class <= DM_DEVICE_CLASS_NONE || device_class >= DM_DEVICE_CLASS_MAX) {
1867         pa_log_warn("Invalid device_string '%s'", device_string);
1868         return NULL;
1869     }
1870
1871     if (!(module_name = device_class_get_module_name(device_class, is_sink))) {
1872         pa_log_error("Get proper module name to load failed");
1873         return NULL;
1874     }
1875     if (!(args = build_params_to_load_device(device_string, device_params, device_class))) {
1876         pa_log_error("Get proper module name to load failed");
1877         return NULL;
1878     }
1879     if (!(module = pa_module_load(c, module_name, args))) {
1880         pa_log_error("Load module with name '%s' argu '%s' failed", module_name, args);
1881         return NULL;
1882     }
1883
1884
1885     if (is_sink) {
1886         PA_IDXSET_FOREACH(sink, c->sinks, device_idx) {
1887             if (sink->module == module) {
1888                 return sink;
1889             }
1890         }
1891     } else {
1892         PA_IDXSET_FOREACH(source, c->sources, device_idx) {
1893             if (source->module == module) {
1894                 return source;
1895             }
1896         }
1897     }
1898
1899     return NULL;
1900 }
1901
1902 static void unload_device(pa_core *c, bool is_sink, const char *device_string) {
1903     uint32_t device_idx;
1904
1905     pa_assert(c);
1906     pa_assert(device_string);
1907
1908     pa_log_info("Unload %s Device : String'%s'", is_sink ? "Playback" : "Capture", device_string);
1909
1910     if (is_sink) {
1911         pa_sink *sink;
1912
1913         PA_IDXSET_FOREACH(sink, c->sinks, device_idx) {
1914             if (pulse_device_is_monitor(PA_OBJECT(sink)))
1915                 continue;
1916             if (pulse_device_same_device_string(PA_OBJECT(sink), device_string))
1917                 pa_module_unload(sink->module, true);
1918         }
1919     } else {
1920         pa_source *source;
1921
1922         PA_IDXSET_FOREACH(source, c->sources, device_idx) {
1923             if (pulse_device_is_monitor(PA_OBJECT(source)))
1924                 continue;
1925             if (pulse_device_same_device_string(PA_OBJECT(source), device_string))
1926                 pa_module_unload(source->module, true);
1927         }
1928     }
1929 }
1930
1931 static int _load_type_devices(struct device_type_info *type_info, bool is_playback, pa_device_manager *dm) {
1932     pa_hashmap *pcm_devices;
1933     pa_idxset *file_infos;
1934     void *state;
1935     char *role;
1936     const char *device_string, *params;
1937
1938     pa_assert(dm);
1939     pa_assert(type_info);
1940
1941     pa_log_info("Load type devices : %s %s", type_info->type, is_playback ? "playback" : "capture");
1942
1943     if (is_playback) {
1944         pcm_devices = type_info->playback_devices;
1945         file_infos = dm->file_map->playback;
1946     } else {
1947         pcm_devices = type_info->capture_devices;
1948         file_infos = dm->file_map->capture;
1949     }
1950
1951     if (!pcm_devices || !file_infos) {
1952         pa_log_error("No information to load");
1953         return -1;
1954     }
1955
1956     PA_HASHMAP_FOREACH_KV(role, device_string, pcm_devices, state) {
1957         /* skip duplicate load */
1958         if (is_playback && _core_get_sink(dm->core, device_string, NULL)) {
1959             pa_log_debug("Already loaded %s", device_string);
1960             continue;
1961         }
1962         if (!is_playback && _core_get_source(dm->core, device_string, NULL)) {
1963             pa_log_debug("Already loaded %s", device_string);
1964             continue;
1965         }
1966
1967         params = _file_infos_get_param(file_infos, device_string, role);
1968         if (params == NULL) {
1969             pa_log_error("Failed to get param for %s", device_string);
1970             continue;
1971         }
1972         if (!(load_device(dm->core, is_playback, device_string, params))) {
1973             pa_log_warn("load device failed %s %s", device_string, params);
1974         }
1975     }
1976
1977     return 0;
1978 }
1979
1980 static pa_tz_device* _load_forwarding_device(pa_device_manager *dm) {
1981     pa_tz_device_new_data data;
1982     pa_tz_device *spk_device, *forwarding_device;
1983     pa_sink *spk_sink;
1984
1985     pa_assert(dm);
1986
1987     pa_log_info("Load forwarding device");
1988
1989     if ((forwarding_device = _device_list_get_device(dm, DEVICE_TYPE_FORWARDING, NULL))) {
1990         pa_log_info("Forwarding device already exists");
1991         return forwarding_device;
1992     }
1993
1994     if ((spk_device = _device_list_get_device(dm, DEVICE_TYPE_SPEAKER, NULL)) == NULL) {
1995         pa_log_error("Get speaker device failed");
1996         return NULL;
1997     }
1998
1999     if ((spk_sink = pa_tz_device_get_sink(spk_device, DEVICE_ROLE_NORMAL)) == NULL) {
2000         pa_log_error("Get speaker sink failed");
2001         return NULL;
2002     }
2003
2004     pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL);
2005     _fill_new_data_basic(&data, DEVICE_TYPE_FORWARDING, DM_DEVICE_DIRECTION_BOTH, true, dm);
2006     pa_tz_device_new_data_add_sink(&data, DEVICE_ROLE_NORMAL, spk_sink);
2007     pa_tz_device_new_data_add_source(&data, DEVICE_ROLE_NORMAL, spk_sink->monitor_source);
2008
2009     if ((forwarding_device = pa_tz_device_new(&data)) == NULL)
2010         pa_log_error("Failed to create forwarding device");
2011
2012     pa_tz_device_new_data_done(&data);
2013
2014     return forwarding_device;
2015 }
2016
2017 /*
2018     Handle device connection detected through dbus.
2019     First, update device-status hashmap.
2020     And if correnspondent sink/sources for device_type exist, should make device and notify it.
2021     Use [device_type->roles] mappings in sink/source for find proper sink/source.
2022 */
2023 static void handle_device_connected(pa_device_manager *dm, const char *type,
2024         const char *name, const char *system_id, device_detected_type_t detected_type) {
2025     struct device_type_info *type_info;
2026     pa_tz_device_new_data data;
2027
2028     pa_assert(dm);
2029     pa_assert(dm->device_status);
2030     pa_assert(dm->device_list);
2031
2032     pa_log_info("Device connected, type(%s) name(%s) system_id(%s) detected_type(%d)",
2033             type, pa_strempty(name), pa_strempty(system_id), detected_type);
2034
2035     type_info = _device_manager_get_type_info(dm->type_infos, type);
2036
2037     if (device_type_is_equal(type, DEVICE_TYPE_BT_SCO)) {
2038         pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, dm->dbus_conn);
2039         _fill_new_data_basic(&data, DEVICE_TYPE_BT_SCO, DM_DEVICE_DIRECTION_BOTH, true, dm);
2040         _fill_new_data_sinks(&data, type_info, dm);
2041         _fill_new_data_sources(&data, type_info, dm);
2042         pa_tz_device_new_data_set_name(&data, name);
2043         pa_tz_device_new_data_set_system_id(&data, system_id);
2044         pa_tz_device_new(&data);
2045         pa_tz_device_new_data_done(&data);
2046     } else if (device_type_is_equal(type, DEVICE_TYPE_AUDIO_JACK)) {
2047         dm_device_direction_t direction;
2048
2049         if (detected_type == DEVICE_CONNECTED_AUDIO_JACK_4P)
2050             direction = DM_DEVICE_DIRECTION_BOTH;
2051         else
2052             direction = DM_DEVICE_DIRECTION_OUT;
2053         pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL);
2054         _fill_new_data_basic(&data, DEVICE_TYPE_AUDIO_JACK, direction, true, dm);
2055         _fill_new_data_sinks(&data, type_info, dm);
2056         _fill_new_data_sources(&data, type_info, dm);
2057
2058         pa_tz_device_new(&data);
2059         pa_tz_device_new_data_done(&data);
2060     } else if (device_type_is_equal(type, DEVICE_TYPE_HDMI)) {
2061         pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL);
2062         _fill_new_data_basic(&data, DEVICE_TYPE_HDMI, DM_DEVICE_DIRECTION_OUT, true, dm);
2063         _fill_new_data_sinks(&data, type_info, dm);
2064
2065         pa_tz_device_new(&data);
2066         pa_tz_device_new_data_done(&data);
2067     } else if (device_type_is_equal(type, DEVICE_TYPE_FORWARDING)) {
2068         _load_forwarding_device(dm);
2069     } else {
2070         dm_device_direction_t direction;
2071
2072         direction = device_type_get_static_direction(type);
2073         if (direction != DM_DEVICE_DIRECTION_NONE) {
2074             pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL);
2075             _fill_new_data_basic(&data, type, direction, true, dm);
2076             if (direction & DM_DEVICE_DIRECTION_OUT)
2077                 _fill_new_data_sinks(&data, type_info, dm);
2078             if (direction & DM_DEVICE_DIRECTION_IN)
2079                 _fill_new_data_sources(&data, type_info, dm);
2080
2081             pa_tz_device_new(&data);
2082             pa_tz_device_new_data_done(&data);
2083         } else {
2084             pa_log_error("Invalid case : not static direction");
2085             return ;
2086         }
2087     }
2088
2089     return ;
2090 }
2091
2092 /*
2093     Handle device disconnection detected through dbus.
2094     First, update device-status hashmap.
2095     And if there is device which has the device_type, remove it.
2096 */
2097 static int handle_device_disconnected(pa_device_manager *dm, const char *type, const char *system_id) {
2098     pa_tz_device *device;
2099
2100     pa_assert(dm);
2101     pa_assert(dm->device_status);
2102
2103     pa_log_info("Device type(%s) system_id(%s) disconnected",
2104             type, pa_strempty(system_id));
2105
2106     device = _device_list_get_device(dm, type, system_id);
2107     if (!device) {
2108         pa_log_error("Disconnection detected but no device for that");
2109         return -1;
2110     }
2111
2112     pa_tz_device_free(device);
2113
2114     return 0;
2115 }
2116
2117 static int load_builtin_devices(pa_device_manager *dm) {
2118     struct device_type_info *type_info;
2119     uint32_t type_idx;
2120     device_detected_type_t detected_type = DEVICE_CONNECTED;
2121     const char *type;
2122
2123     pa_assert(dm);
2124
2125     pa_log_debug("\n==================== Load Builtin Devices ====================");
2126
2127     PA_IDXSET_FOREACH(type_info, dm->type_infos, type_idx) {
2128
2129         type = type_info->type;
2130
2131         pa_log_info("type_info : %s", type);
2132         detected_type = _device_get_detected(dm, type, NULL);
2133         if (detected_type == DEVICE_DISCONNECTED) {
2134             pa_log_info("Not detected yet");
2135             continue;
2136         }
2137
2138         if (device_type_is_equal(type, DEVICE_TYPE_AUDIO_JACK)) {
2139             if (detected_type == DEVICE_CONNECTED_AUDIO_JACK_4P) {
2140                 _load_type_devices(type_info, true, dm);
2141                 _load_type_devices(type_info, false, dm);
2142             } else {
2143                 _load_type_devices(type_info, true, dm);
2144             }
2145             handle_device_connected(dm, type, NULL, NULL, detected_type);
2146         } else if (device_type_is_use_external_card(type) == false) {
2147             dm_device_direction_t direction;
2148             direction = device_type_get_static_direction(type);
2149             if (direction == DM_DEVICE_DIRECTION_NONE) {
2150                 pa_log_warn("Wrong direction");
2151                 continue;
2152             }
2153             if (direction & DM_DEVICE_DIRECTION_OUT)
2154                 _load_type_devices(type_info, true, dm);
2155             if (direction & DM_DEVICE_DIRECTION_IN)
2156                 _load_type_devices(type_info, false, dm);
2157             handle_device_connected(dm, type, NULL, NULL, detected_type);
2158         } else {
2159             pa_log_warn("Invalid case");
2160         }
2161     }
2162
2163     return 0;
2164 }
2165
2166 /***************** Parse json file *******************/
2167 static pa_hashmap* parse_device_role_object(json_object *device_role_o) {
2168     pa_hashmap *roles = NULL;
2169     const char *params, *device_role;
2170     struct json_object_iterator it, it_end;
2171     json_object *params_o;
2172
2173     pa_assert(device_role_o);
2174     pa_assert(json_object_is_type(device_role_o, json_type_object));
2175
2176     roles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
2177     if (!roles) {
2178         pa_log_debug("hashmap new failed");
2179         goto fail;
2180     }
2181
2182     it = json_object_iter_begin(device_role_o);
2183     it_end = json_object_iter_end(device_role_o);
2184
2185     while (!json_object_iter_equal(&it, &it_end)) {
2186         device_role = json_object_iter_peek_name(&it);
2187         params_o = json_object_iter_peek_value(&it);
2188
2189         if (!(params = json_object_get_string(params_o))) {
2190             pa_log_debug("There is no device params for role '%s'", device_role);
2191         }
2192         pa_log_info("- Role '%s' -> '%s'", device_role, params);
2193         if (device_role_is_valid(device_role)) {
2194             if (pa_hashmap_put(roles, (void *)device_role, (void *)params)) {
2195                 pa_log_error("put new role to hashmap faild");
2196                 goto fail;
2197             }
2198         } else {
2199             pa_log_error("Invalid device role '%s'", device_role);
2200         }
2201
2202         json_object_iter_next(&it);
2203     }
2204
2205     if (pa_hashmap_size(roles) == 0) {
2206         pa_log_warn("There is no role for device.. free hashmap");
2207         pa_hashmap_free(roles);
2208         roles = NULL;
2209     }
2210
2211     return roles;
2212
2213 fail:
2214     if (roles)
2215         pa_hashmap_free(roles);
2216
2217     return NULL;
2218 }
2219
2220 static struct device_file_info* parse_device_file_object(json_object *device_file_o, const char **device_string_key) {
2221     pa_hashmap *roles = NULL;
2222     json_object *device_file_prop_o = NULL;
2223     const char *device_string = NULL;
2224     struct device_file_info *file_info = NULL;
2225
2226     pa_assert(device_file_o);
2227     pa_assert(device_string_key);
2228     pa_assert(json_object_is_type(device_file_o, json_type_object));
2229
2230     if (json_object_object_get_ex(device_file_o, DEVICE_TYPE_PROP_DEVICE_STRING, &device_file_prop_o) && json_object_is_type(device_file_prop_o, json_type_string)) {
2231         if ((device_string = json_object_get_string(device_file_prop_o))) {
2232             pa_log_info("[ Device File - %s ]", device_string);
2233         } else {
2234             pa_log_error("Get device-string failed");
2235             return NULL;
2236         }
2237     } else {
2238         pa_log_error("Get device-string object failed");
2239         return NULL;
2240     }
2241
2242     if (json_object_object_get_ex(device_file_o, DEVICE_TYPE_PROP_ROLE, &device_file_prop_o)) {
2243         if (!(roles = parse_device_role_object(device_file_prop_o))) {
2244             pa_log_error("Parse device role for '%s' failed", device_string);
2245             goto fail;
2246         }
2247     } else {
2248         pa_log_error("Get device role object failed");
2249     }
2250
2251     file_info = pa_xmalloc0(sizeof(struct device_file_info));
2252     file_info->device_string = device_string;
2253     file_info->device_types = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
2254     file_info->roles = roles;
2255
2256 //    *device_string_key = device_string;
2257
2258     return file_info;
2259
2260 fail:
2261
2262     return NULL;
2263 }
2264
2265 static pa_idxset* parse_device_file_array_object(json_object *device_file_array_o) {
2266     int device_file_num, device_file_idx;
2267     struct device_file_info *file_info = NULL;
2268     json_object *device_file_o = NULL;
2269     pa_idxset *device_files = NULL;
2270     const char *device_string = NULL;
2271
2272     pa_assert(device_file_array_o);
2273     pa_assert(json_object_is_type(device_file_array_o, json_type_array));
2274
2275     device_files = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
2276
2277     device_file_num = json_object_array_length(device_file_array_o);
2278     for (device_file_idx = 0; device_file_idx < device_file_num; device_file_idx++) {
2279         if ((device_file_o = json_object_array_get_idx(device_file_array_o, device_file_idx)) && json_object_is_type(device_file_o, json_type_object)) {
2280             if ((file_info = parse_device_file_object(device_file_o, &device_string))) {
2281                 pa_idxset_put(device_files, file_info, NULL);
2282             } else {
2283                 pa_log_error("parse device file object failed");
2284                 goto fail;
2285             }
2286         } else {
2287             pa_log_error("Get device file object failed");
2288             goto fail;
2289         }
2290     }
2291
2292     if (pa_idxset_size(device_files) == 0) {
2293         pa_idxset_free(device_files, NULL);
2294         device_files = NULL;
2295     }
2296
2297     return device_files;
2298
2299 fail:
2300     if (device_files)
2301         pa_xfree(device_files);
2302     return NULL;
2303 }
2304
2305 static struct device_file_map *parse_device_file_map() {
2306     struct device_file_map *file_map = NULL;
2307     json_object *o, *device_files_o;
2308     json_object *playback_devices_o = NULL, *capture_devices_o = NULL;
2309
2310     pa_log_info("\nParse device files");
2311
2312     o = json_object_from_file(DEVICE_MAP_FILE);
2313
2314     if (o == NULL) {
2315         pa_log_error("Read device-map file failed");
2316         return NULL;
2317     }
2318
2319     file_map = pa_xmalloc0(sizeof(struct device_file_map));
2320
2321     if (json_object_object_get_ex(o, DEVICE_FILE_OBJECT, &device_files_o) && json_object_is_type(device_files_o, json_type_object)) {
2322         if (json_object_object_get_ex(device_files_o, DEVICE_TYPE_PROP_PLAYBACK_DEVICES, &playback_devices_o)) {
2323             pa_log_info("Playback Device Files");
2324             file_map->playback = parse_device_file_array_object(playback_devices_o);
2325         }
2326         if (json_object_object_get_ex(device_files_o, DEVICE_TYPE_PROP_CAPTURE_DEVICES, &capture_devices_o)) {
2327             pa_log_info("Capture Device Files");
2328             file_map->capture = parse_device_file_array_object(capture_devices_o);
2329         }
2330     } else {
2331         pa_log_error("Get device files object failed");
2332         pa_xfree(file_map);
2333         return NULL;
2334     }
2335
2336     return file_map;
2337 }
2338
2339
2340 static pa_hashmap* parse_device_role_map(json_object *device_role_map_o) {
2341     pa_hashmap *roles = NULL;
2342     const char *device_string, *device_role;
2343     struct json_object_iterator it, it_end;
2344     json_object *device_string_o;
2345
2346     pa_assert(device_role_map_o);
2347     pa_assert(json_object_is_type(device_role_map_o, json_type_object));
2348
2349     roles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
2350
2351     it = json_object_iter_begin(device_role_map_o);
2352     it_end = json_object_iter_end(device_role_map_o);
2353
2354     while (!json_object_iter_equal(&it, &it_end)) {
2355         device_role = json_object_iter_peek_name(&it);
2356         device_string_o = json_object_iter_peek_value(&it);
2357
2358         if (!(device_string = json_object_get_string(device_string_o))) {
2359             pa_log_debug("There is no device string for role '%s'", device_role);
2360         }
2361         pa_log_info("- Role '%s' -> '%s'", device_role, device_string);
2362         if (device_role_is_valid(device_role)) {
2363             if (pa_hashmap_put(roles, (void *)device_role, (void *)device_string)) {
2364                 pa_log_error("put new role to hashmap faild");
2365                 goto fail;
2366             }
2367         } else {
2368             pa_log_error("Invalid device role '%s'", device_role);
2369             goto fail;
2370         }
2371
2372         json_object_iter_next(&it);
2373     }
2374
2375     return roles;
2376
2377 fail:
2378     if (roles)
2379         pa_xfree(roles);
2380
2381     return NULL;
2382 }
2383
2384
2385
2386 static pa_idxset* parse_device_type_infos() {
2387     json_object *o, *device_array_o = NULL;
2388     int device_type_num = 0;
2389     int device_type_idx = 0;
2390     struct device_type_info *type_info = NULL;
2391     //pa_hashmap *type_infos = NULL;
2392     pa_idxset *type_infos = NULL;
2393
2394     o = json_object_from_file(DEVICE_MAP_FILE);
2395     if (o == NULL) {
2396         pa_log_error("Read device-map file failed");
2397         return NULL;
2398     }
2399
2400     pa_log_info("\nParse device types");
2401     type_infos = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
2402
2403     if (json_object_object_get_ex(o, DEVICE_TYPE_OBJECT, &device_array_o) && json_object_is_type(device_array_o, json_type_array)) {
2404         device_type_num = json_object_array_length(device_array_o);
2405         for (device_type_idx = 0; device_type_idx < device_type_num ; device_type_idx++) {
2406             json_object *device_o;
2407
2408             if ((device_o = json_object_array_get_idx(device_array_o, device_type_idx)) && json_object_is_type(device_o, json_type_object)) {
2409                 json_object *device_prop_o;
2410                 const char *type = NULL;
2411
2412                 if (!json_object_object_get_ex(device_o, DEVICE_TYPE_PROP_DEVICE_TYPE, &device_prop_o) && json_object_is_type(device_prop_o, json_type_string)) {
2413                     pa_log_error("Get device type failed");
2414                     goto fail;
2415                 }
2416                 type = json_object_get_string(device_prop_o);
2417                 pa_log_info("[ Device - %s ]", type);
2418
2419                 type_info = pa_xmalloc0(sizeof(struct device_type_info));
2420                 type_info->type = type;
2421
2422                 if (json_object_object_get_ex(device_o, DEVICE_TYPE_PROP_PLAYBACK_DEVICES, &device_prop_o) && json_object_is_type(device_prop_o, json_type_object)) {
2423                     pa_log_info("Playback Devices");
2424                     type_info->playback_devices = parse_device_role_map(device_prop_o);
2425                 }
2426
2427                 if (json_object_object_get_ex(device_o, DEVICE_TYPE_PROP_CAPTURE_DEVICES, &device_prop_o) && json_object_is_type(device_prop_o, json_type_object)) {
2428                     pa_log_info("Capture Devices");
2429                     type_info->capture_devices = parse_device_role_map(device_prop_o);
2430                 }
2431                 pa_idxset_put(type_infos, type_info, NULL);
2432
2433             } else {
2434                 pa_log_debug("Get device type object failed");
2435             }
2436         }
2437     } else {
2438         pa_log_debug("Get device type array object failed");
2439     }
2440     return type_infos;
2441
2442 fail:
2443     if (type_infos)
2444         pa_xfree(type_infos);
2445
2446     return NULL;
2447 }
2448
2449 /*
2450    look detected status which is external value, make conversion to internal consistent value, and handle it
2451    device_type, which type of device is detected
2452    system_id : system_id among same device types for support multi-device
2453 */
2454 static int handle_device_status_changed(pa_device_manager *dm, const char *type,
2455         const char *name, const char *system_id, device_detected_type_t detected) {
2456     pa_assert(dm);
2457     pa_assert(device_type_is_valid(type));
2458
2459     pa_log_info("Device Status Changed, type(%s) system_id(%s), detected_type(%d)",
2460             type, pa_strempty(system_id), detected);
2461
2462     if (device_type_is_equal(type, DEVICE_TYPE_BT_SCO)) {
2463         _device_set_detected(dm, type, name, system_id, detected);
2464         if (detected == DEVICE_DISCONNECTED)
2465             handle_device_disconnected(dm, type, system_id);
2466         else
2467             handle_device_connected(dm, type, name, system_id, detected);
2468     } else if (device_type_is_need_detect(type)) {
2469         _device_set_detected(dm, type, name, system_id, detected);
2470         if (detected == DEVICE_DISCONNECTED)
2471             handle_device_disconnected(dm, type, system_id);
2472         else
2473             handle_device_connected(dm, type, name, system_id, detected);
2474     } else {
2475         pa_log_debug("No need to detect type %s", type);
2476     }
2477
2478     return 0;
2479 }
2480
2481 /*
2482     Initialize device-status idxset.
2483     This is for device-status detected through dbus.
2484     So, if device_type is not detected through dbus, let's initialize them to detected. (ex. spk, rcv,...)
2485     If not, initialize to not detected.
2486 */
2487 static void device_type_status_init(pa_device_manager *manager) {
2488     struct device_type_info *type_info;
2489     uint32_t type_idx;
2490     const char *type;
2491
2492     pa_assert(manager);
2493     pa_assert(manager->type_infos);
2494
2495     pa_log_debug("\n==================== Init Device Status ====================");
2496
2497     PA_IDXSET_FOREACH(type_info, manager->type_infos, type_idx) {
2498         type = type_info->type;
2499         if (device_type_is_equal(type, DEVICE_TYPE_AUDIO_JACK)) {
2500             int earjack_status = 0;
2501             if (vconf_get_int(VCONFKEY_SYSMAN_EARJACK, &earjack_status) < 0) {
2502                 pa_log_error("Get earjack status failed");
2503                 continue;
2504             }
2505             if (earjack_status == EARJACK_TYPE_SPK_ONLY)
2506                 _device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED_AUDIO_JACK_3P);
2507             else if (earjack_status == EARJACK_TYPE_SPK_WITH_MIC)
2508                 _device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED_AUDIO_JACK_4P);
2509             else if (earjack_status == EARJACK_DISCONNECTED)
2510                 _device_set_detected(manager, type, NULL, NULL, DEVICE_DISCONNECTED);
2511             else
2512                 pa_log_warn("Unknown earjack status : %d", earjack_status);
2513         } else if (device_type_is_equal(type, DEVICE_TYPE_BT_SCO)) {
2514                 _device_set_detected(manager, type, NULL, NULL, DEVICE_DISCONNECTED);
2515         } else if (device_type_is_equal(type, DEVICE_TYPE_HDMI)) {
2516                 _device_set_detected(manager, type, NULL, NULL, DEVICE_DISCONNECTED);
2517         } else if (device_type_is_equal(type, DEVICE_TYPE_FORWARDING)) {
2518             int miracast_wfd_status = 0;
2519             if (vconf_get_bool(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS, &miracast_wfd_status) < 0) {
2520                 pa_log_error("Get mirroring status failed");
2521                 continue;
2522             }
2523             if (miracast_wfd_status == FORWARDING_CONNECTED)
2524                 _device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED);
2525         } else {
2526             _device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED);
2527         }
2528     }
2529     return ;
2530 }
2531
2532 #ifdef HAVE_DBUS
2533
2534 static int _translate_external_value(const char *type, int value, device_detected_type_t *detected) {
2535
2536     if (!type || !detected) {
2537         pa_log_error("Invalid Parameter for translate");
2538         return -1;
2539     }
2540
2541     if (device_type_is_equal(DEVICE_TYPE_AUDIO_JACK, type)) {
2542         if (value == EARJACK_DISCONNECTED)
2543             *detected = DEVICE_DISCONNECTED;
2544         else if (value == EARJACK_TYPE_SPK_ONLY)
2545             *detected = DEVICE_CONNECTED_AUDIO_JACK_3P;
2546         else if (value == EARJACK_TYPE_SPK_WITH_MIC)
2547             *detected = DEVICE_CONNECTED_AUDIO_JACK_4P;
2548         else
2549             return -1;
2550     } else if (device_type_is_equal(DEVICE_TYPE_HDMI, type)) {
2551         if (value == HDMI_AUDIO_DISCONNECTED)
2552             *detected = DEVICE_DISCONNECTED;
2553         else if (value == HDMI_AUDIO_AVAILABLE)
2554             *detected = DEVICE_CONNECTED;
2555         else
2556             return -1;
2557     } else if (device_type_is_equal(DEVICE_TYPE_FORWARDING, type)) {
2558         if (value == FORWARDING_DISCONNECTED)
2559             *detected = DEVICE_DISCONNECTED;
2560         else if (value == FORWARDING_CONNECTED)
2561             *detected = DEVICE_CONNECTED;
2562         else
2563             return -1;
2564     } else if (device_type_is_equal(DEVICE_TYPE_BT_SCO, type)) {
2565         if (value == BT_SCO_DISCONNECTED)
2566             *detected = DEVICE_DISCONNECTED;
2567         else if (value == BT_SCO_CONNECTED)
2568             *detected = DEVICE_CONNECTED_SCO;
2569         else
2570             return -1;
2571     }
2572
2573     return 0;
2574 }
2575
2576 static DBusHandlerResult dbus_filter_device_detect_handler(DBusConnection *c, DBusMessage *s, void *userdata) {
2577     DBusError error;
2578     int status = 0;
2579     pa_device_manager *dm = (pa_device_manager *) userdata;
2580     device_detected_type_t detected;
2581
2582     pa_assert(userdata);
2583
2584     if (dbus_message_get_type(s) != DBUS_MESSAGE_TYPE_SIGNAL)
2585         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2586
2587     pa_log_info("Device detect handler : Path(%s) Intf(%s) Member(%s) Signature(%s)",
2588             dbus_message_get_path(s), dbus_message_get_interface(s), dbus_message_get_member(s), dbus_message_get_signature(s));
2589
2590     dbus_error_init(&error);
2591
2592     if (dbus_message_is_signal(s, DBUS_INTERFACE_DEVICED_SYSNOTI, "ChangedEarjack")) {
2593         if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
2594             goto fail;
2595         } else {
2596             if (_translate_external_value(DEVICE_TYPE_AUDIO_JACK, status, &detected) < 0) {
2597                 pa_log_warn("failed to translate audio-jack detected value");
2598                 goto fail;
2599             }
2600             handle_device_status_changed(dm, DEVICE_TYPE_AUDIO_JACK, NULL, NULL, detected);
2601         }
2602     } else if (dbus_message_is_signal(s, DBUS_INTERFACE_DEVICED_SYSNOTI, "ChangedHDMIAudio")) {
2603         if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
2604             goto fail;
2605         } else {
2606             if (_translate_external_value(DEVICE_TYPE_HDMI, status, &detected) < 0) {
2607                 pa_log_warn("failed to translate HDMI detected value");
2608                 goto fail;
2609             }
2610             handle_device_status_changed(dm, DEVICE_TYPE_HDMI, NULL, NULL, detected);
2611         }
2612     } else if (dbus_message_is_signal(s, DBUS_INTERFACE_MIRRORING_SERVER, "miracast_wfd_source_status_changed")) {
2613         if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
2614             goto fail;
2615         } else {
2616             if (_translate_external_value(DEVICE_TYPE_FORWARDING, status, &detected) < 0) {
2617                 pa_log_warn("failed to translate forwarding detected value");
2618                 goto fail;
2619             }
2620             handle_device_status_changed(dm, DEVICE_TYPE_FORWARDING, NULL, NULL, detected);
2621         }
2622     } else if (dbus_message_is_signal(s, DBUS_INTERFACE_BLUEZ_HEADSET, "PropertyChanged")) {
2623         DBusMessageIter msg_iter, variant_iter;
2624         char *property_name;
2625
2626         pa_log_debug("Got %s PropertyChanged signal", DBUS_INTERFACE_BLUEZ_HEADSET);
2627         dbus_message_iter_init(s, &msg_iter);
2628         if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_STRING) {
2629             pa_log_error("Property name not string");
2630             goto fail;
2631         }
2632         dbus_message_iter_get_basic(&msg_iter, &property_name);
2633         pa_log_info("Changed Property name : %s", property_name);
2634
2635         if (!dbus_message_iter_next(&msg_iter)) {
2636             pa_log_debug("Property value missing");
2637             goto fail;
2638         }
2639
2640         if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_VARIANT) {
2641             pa_log_debug("Property value not a variant.");
2642             goto fail;
2643         }
2644
2645         dbus_message_iter_recurse(&msg_iter, &variant_iter);
2646
2647         if (DBUS_TYPE_BOOLEAN == dbus_message_iter_get_arg_type(&variant_iter)) {
2648             dbus_bool_t value;
2649             char *name = NULL;
2650             dbus_message_iter_get_basic(&variant_iter, &value);
2651             if (pa_streq(property_name, "Connected")) {
2652                 pa_log_info("HFP Connection : %d", value);
2653                 if (value) {
2654                     method_call_bt_get_name(c, dbus_message_get_path(s), &name);
2655                     status = BT_SCO_CONNECTED;
2656                 } else {
2657                     status = BT_SCO_DISCONNECTED;
2658                 }
2659                 if (_translate_external_value(DEVICE_TYPE_BT_SCO, status, &detected) < 0) {
2660                     pa_log_warn("failed to translate bt-sco detected value");
2661                     goto fail;
2662                 }
2663                 handle_device_status_changed(dm, DEVICE_TYPE_BT_SCO,
2664                         name, dbus_message_get_path(s),  detected);
2665             } else if (pa_streq(property_name, "Playing")) {
2666                 pa_tz_device *device;
2667                 pa_log_info("SCO Playing : %d", value);
2668                 if ((device = _device_list_get_device(dm, DEVICE_TYPE_BT_SCO, NULL)) != NULL) {
2669                     device->sco_opened = value;
2670                     if (value) {
2671                         /* update BT band/nrec information */
2672                         bool is_wide_band = false;
2673                         bool nrec = false;
2674                         pa_tz_device_sco_get_property(device, &is_wide_band, &nrec);
2675                         pa_log_info("got new wideband:%d, nrec:%d", is_wide_band, nrec);
2676
2677                         UPDATE_HAL_ROUTE_OPTION(dm->hal_interface, NULL, "bt-wideband", is_wide_band);
2678                         UPDATE_HAL_ROUTE_OPTION(dm->hal_interface, NULL, "bt-nrec", nrec);
2679                     }
2680                 }
2681                 UPDATE_HAL_ROUTE_OPTION(dm->hal_interface, NULL, "bt-sco-ready", value);
2682             }
2683         }
2684     } else {
2685         pa_log_debug("Unknown message, not handle it");
2686         dbus_error_free(&error);
2687         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2688     }
2689
2690     pa_log_debug("Dbus Message handled");
2691
2692     dbus_error_free(&error);
2693     return DBUS_HANDLER_RESULT_HANDLED;
2694
2695 fail:
2696     pa_log_error("Fail to handle dbus signal");
2697     dbus_error_free(&error);
2698     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2699 }
2700
2701 static int watch_signals(pa_device_manager *dm) {
2702     DBusError error;
2703
2704     pa_assert(dm);
2705     pa_assert(dm->dbus_conn);
2706
2707     dbus_error_init(&error);
2708
2709     pa_log_info("Watch Dbus signals");
2710
2711     if (!dbus_connection_add_filter(pa_dbus_connection_get(dm->dbus_conn), dbus_filter_device_detect_handler, dm, NULL)) {
2712         pa_log_error("Unable to add D-Bus filter : %s: %s", error.name, error.message);
2713         goto fail;
2714     }
2715
2716     if (pa_dbus_add_matches(pa_dbus_connection_get(dm->dbus_conn), &error, FILTER_DEVICED_SYSNOTI, FILTER_SOUND_SERVER, FILTER_BLUEZ, FILTER_MIRRORING, NULL) < 0) {
2717         pa_log_error("Unable to subscribe to signals: %s: %s", error.name, error.message);
2718         goto fail;
2719     }
2720     return 0;
2721
2722 fail:
2723     dbus_error_free(&error);
2724     return -1;
2725 }
2726
2727 static void unwatch_signals(pa_device_manager *dm) {
2728     pa_log_info("Unwatch Dbus signals");
2729
2730     pa_assert(dm);
2731     pa_assert(dm->dbus_conn);
2732
2733     pa_dbus_remove_matches(pa_dbus_connection_get(dm->dbus_conn), FILTER_DEVICED_SYSNOTI, FILTER_SOUND_SERVER, FILTER_BLUEZ, FILTER_MIRRORING, NULL);
2734     dbus_connection_remove_filter(pa_dbus_connection_get(dm->dbus_conn), dbus_filter_device_detect_handler, dm);
2735 }
2736
2737 static void fill_signal_msg_with_device(const char *description, DBusMessageIter *msg_iter, uint32_t event_id, pa_tz_device *device) {
2738     DBusMessageIter array_iter, device_iter;
2739     char *type, *name;
2740     dbus_int32_t device_id, direction, state, stream_id;
2741     dbus_int32_t vendor_id, product_id;
2742     dbus_bool_t is_running;
2743     pa_intset *stream_id_set = NULL;
2744     int32_t stream_id_val;
2745     int ret;
2746
2747     pa_assert(msg_iter);
2748     pa_assert(device);
2749
2750     dbus_message_iter_append_basic(msg_iter, DBUS_TYPE_UINT32, &event_id);
2751     pa_assert_se(dbus_message_iter_open_container(msg_iter, DBUS_TYPE_STRUCT, NULL, &device_iter));
2752
2753     direction = (dbus_int32_t) pa_tz_device_get_direction(device);
2754     type = pa_tz_device_get_type(device);
2755     name = pa_tz_device_get_name(device);
2756     device_id = (dbus_int32_t) pa_tz_device_get_id(device);
2757     state = pa_tz_device_get_state(device);
2758     vendor_id = (dbus_int32_t) pa_tz_device_get_vendor_id(device);
2759     product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
2760     is_running = (dbus_bool_t) pa_tz_device_is_running(device);
2761
2762     simple_device_dump(PA_LOG_INFO, description, device_id, type, name, direction, state);
2763
2764     dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &device_id);
2765     dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &type);
2766     dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &direction);
2767     dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &state);
2768     dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &name);
2769     dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &vendor_id);
2770     dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &product_id);
2771     dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_BOOLEAN, &is_running);
2772     if (state == DM_DEVICE_STATE_ACTIVATED)
2773         stream_id_set = pa_tz_device_get_stream_list(device);
2774     pa_assert_se(dbus_message_iter_open_container(&device_iter, DBUS_TYPE_ARRAY, "i", &array_iter));
2775     if (state == DM_DEVICE_STATE_ACTIVATED) {
2776         PA_INTSET_FOREACH(stream_id_val, stream_id_set, ret) {
2777             stream_id = stream_id_val;
2778             dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_INT32, &stream_id);
2779         }
2780     }
2781     pa_assert_se(dbus_message_iter_close_container(&device_iter, &array_iter));
2782     if (stream_id_set)
2783         pa_intset_free(stream_id_set);
2784     pa_assert_se(dbus_message_iter_close_container(msg_iter, &device_iter));
2785     pa_log_info("end of fill signal msg");
2786 }
2787
2788 static void send_device_connection_changed_signal(uint32_t event_id, pa_tz_device *device, bool connected, pa_device_manager *dm) {
2789     DBusMessage *signal_msg;
2790     DBusMessageIter msg_iter;
2791     dbus_bool_t _connected = connected;
2792
2793     pa_assert(device);
2794     pa_assert(dm);
2795
2796     pa_log_info("Send device connection changed signal, event_id(%u)", event_id);
2797
2798     pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceConnected"));
2799     dbus_message_iter_init_append(signal_msg, &msg_iter);
2800     fill_signal_msg_with_device(connected ? "[Connected]" : "[Disconnected]", &msg_iter, event_id, device);
2801
2802     dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_BOOLEAN, &_connected);
2803
2804     pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
2805
2806     dbus_message_unref(signal_msg);
2807     pa_log_info("end of send device connection changed signal");
2808 }
2809
2810 static void send_device_info_changed_signal(uint32_t event_id, pa_tz_device *device, int changed_type, pa_device_manager *dm) {
2811     DBusMessage *signal_msg;
2812     DBusMessageIter msg_iter;
2813     const char *changed_prefix[] = {"[State Changed]", "[Direction Changed]", "[Avail-Mode Changed]"};
2814
2815     pa_assert(device);
2816     pa_assert(dm);
2817
2818     pa_log_debug("Send device info changed signal, event_id(%u)", event_id);
2819
2820     pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceInfoChanged"));
2821     dbus_message_iter_init_append(signal_msg, &msg_iter);
2822     fill_signal_msg_with_device(changed_prefix[changed_type], &msg_iter, event_id, device);
2823     dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &changed_type);
2824
2825     pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
2826
2827     dbus_message_unref(signal_msg);
2828 }
2829
2830 static void send_device_state_changed_signal(uint32_t event_id, pa_tz_device *device, bool activated, pa_device_manager *dm) {
2831     DBusMessage *signal_msg;
2832     DBusMessageIter msg_iter;
2833
2834     pa_assert(device);
2835     pa_assert(dm);
2836
2837     pa_log_debug("Send device state changed signal, event_id(%u)", event_id);
2838
2839     pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceStateChanged"));
2840     dbus_message_iter_init_append(signal_msg, &msg_iter);
2841     fill_signal_msg_with_device(activated ? "[Activated]" : "[Deactivated]", &msg_iter, event_id, device);
2842
2843     pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
2844
2845     dbus_message_unref(signal_msg);
2846 }
2847
2848 static void send_device_running_changed_signal(uint32_t event_id, pa_tz_device *device, bool is_running, pa_device_manager *dm) {
2849     DBusMessage *signal_msg;
2850     DBusMessageIter msg_iter;
2851
2852     pa_assert(device);
2853     pa_assert(dm);
2854
2855     pa_log_debug("Send device running changed signal, event_id(%u)", event_id);
2856
2857     pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceRunningChanged"));
2858     dbus_message_iter_init_append(signal_msg, &msg_iter);
2859     fill_signal_msg_with_device(is_running ? "[Running]" : "[NotRunning]", &msg_iter, event_id, device);
2860
2861     pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
2862
2863     dbus_message_unref(signal_msg);
2864 }
2865
2866 static bool device_is_match_direction(pa_tz_device *device, int direction_mask) {
2867     dm_device_direction_t direction;
2868
2869     if (direction_mask == DEVICE_IO_DIRECTION_FLAGS || direction_mask == 0)
2870         return true;
2871
2872     direction = pa_tz_device_get_direction(device);
2873
2874     if ((direction_mask & DEVICE_IO_DIRECTION_IN_FLAG) && (direction & DM_DEVICE_DIRECTION_IN))
2875         return true;
2876     if ((direction_mask & DEVICE_IO_DIRECTION_OUT_FLAG) && (direction & DM_DEVICE_DIRECTION_OUT))
2877         return true;
2878     if ((direction_mask & DEVICE_IO_DIRECTION_BOTH_FLAG) && (direction == DM_DEVICE_DIRECTION_BOTH))
2879         return true;
2880
2881     return false;
2882 }
2883
2884 static bool device_is_match_state(pa_tz_device *device, int state_mask) {
2885     dm_device_state_t state;
2886
2887     if (state_mask == DEVICE_STATE_FLAGS || state_mask == 0)
2888         return true;
2889
2890     state = pa_tz_device_get_state(device);
2891
2892     if ((state_mask & DEVICE_STATE_DEACTIVATED_FLAG) && (state == DM_DEVICE_STATE_DEACTIVATED))
2893         return true;
2894     if ((state_mask & DEVICE_STATE_ACTIVATED_FLAG) && (state == DM_DEVICE_STATE_ACTIVATED))
2895         return true;
2896
2897     return false;
2898 }
2899
2900 static bool device_is_match_type(pa_tz_device *device, int type_mask) {
2901     char *type;
2902     bool is_builtin;
2903
2904     if (type_mask == DEVICE_TYPE_FLAGS || type_mask == 0)
2905         return true;
2906
2907     type = pa_tz_device_get_type(device);
2908     is_builtin = device_type_is_builtin(type);
2909
2910     if ((type_mask & DEVICE_TYPE_INTERNAL_FLAG) && is_builtin)
2911         return true;
2912     if ((type_mask & DEVICE_TYPE_EXTERNAL_FLAG) && !is_builtin)
2913         return true;
2914
2915     return false;
2916 }
2917
2918 static bool device_is_match_with_mask(pa_tz_device *device, int mask) {
2919     pa_assert(device);
2920
2921     if (mask == DEVICE_ALL_FLAG)
2922         return true;
2923
2924     return (device_is_match_direction(device, mask & DEVICE_IO_DIRECTION_FLAGS) &&
2925             device_is_match_state(device, mask & DEVICE_STATE_FLAGS) &&
2926             device_is_match_type(device, mask & DEVICE_TYPE_FLAGS));
2927 }
2928
2929 static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name) {
2930     const char *intf = DBUS_INTERFACE_BLUEZ_DEVICE, *prop = "Alias";
2931     DBusMessage *msg, *reply;
2932     DBusMessageIter reply_iter, variant_iter;
2933     DBusError err;
2934
2935     pa_assert(conn);
2936     pa_assert(device_path);
2937     pa_assert(name);
2938
2939     if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_BLUEZ, device_path, "org.freedesktop.DBus.Properties", "Get"))) {
2940         pa_log_error("dbus method call failed");
2941         return -1;
2942     }
2943
2944     dbus_message_append_args(msg,
2945                 DBUS_TYPE_STRING, &intf,
2946                 DBUS_TYPE_STRING, &prop,
2947                 DBUS_TYPE_INVALID);
2948
2949     dbus_error_init(&err);
2950     if (!(reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err))) {
2951         pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_BLUEZ_DEVICE, "Get", err.message);
2952         dbus_error_free(&err);
2953         return -1;
2954     }
2955
2956     dbus_message_iter_init(reply,  &reply_iter);
2957
2958     if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_VARIANT) {
2959         pa_log_error("Cannot get reply argument");
2960         return -1;
2961     }
2962
2963     dbus_message_iter_recurse(&reply_iter,  &variant_iter);
2964
2965     if (dbus_message_iter_get_arg_type(&variant_iter) == DBUS_TYPE_STRING) {
2966         dbus_message_iter_get_basic(&variant_iter, name);
2967     }
2968
2969     dbus_message_unref(reply);
2970     return 0;
2971 }
2972
2973 static void handle_get_connected_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
2974     pa_device_manager *dm;
2975     DBusMessage *reply = NULL;
2976     DBusMessageIter msg_iter, array_iter, device_iter;
2977     pa_tz_device *device;
2978     dm_device_state_t state;
2979     uint32_t device_idx;
2980     dbus_int32_t device_id, direction;
2981     int mask;
2982     char *type, *name;
2983     dbus_int32_t vendor_id, product_id;
2984     dbus_bool_t is_running;
2985
2986     pa_assert(conn);
2987     pa_assert(msg);
2988     pa_assert(userdata);
2989
2990
2991     dm = (pa_device_manager*) userdata;
2992
2993     pa_assert_se((reply = dbus_message_new_method_return(msg)));
2994
2995     pa_assert_se(dbus_message_get_args(msg, NULL,
2996                                        DBUS_TYPE_INT32, &mask,
2997                                        DBUS_TYPE_INVALID));
2998
2999     pa_log_info("Get connected device list (mask : %d)", mask);
3000
3001     dbus_message_iter_init_append(reply, &msg_iter);
3002     pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(isiisiib)", &array_iter));
3003
3004     PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
3005         device_id = (dbus_int32_t)pa_tz_device_get_id(device);
3006         state = pa_tz_device_get_state(device);
3007         direction = pa_tz_device_get_direction(device);
3008         type = pa_tz_device_get_type(device);
3009         name = pa_tz_device_get_name(device);
3010         vendor_id = (dbus_int32_t) pa_tz_device_get_vendor_id(device);
3011         product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
3012         product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
3013         is_running = (dbus_bool_t) pa_tz_device_is_running(device);
3014         if (device_is_match_with_mask(device,  mask)) {
3015             simple_device_dump(PA_LOG_INFO, "[MATCH]", device_id, type, name, direction, state);
3016             pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &device_iter));
3017             dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &device_id);
3018             dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &type);
3019             dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &direction);
3020             dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &state);
3021             dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &name);
3022             dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &vendor_id);
3023             dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &product_id);
3024             dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_BOOLEAN, &is_running);
3025             pa_assert_se(dbus_message_iter_close_container(&array_iter, &device_iter));
3026         } else {
3027             simple_device_dump(PA_LOG_INFO, "[UNMATCH]", device_id, type, name, direction, state);
3028         }
3029     }
3030
3031     pa_assert_se(dbus_message_iter_close_container(&msg_iter, &array_iter));
3032
3033     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3034     dbus_message_unref(reply);
3035 }
3036
3037 static void handle_get_device_by_id(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3038     pa_device_manager *manager;
3039     DBusMessage *reply;
3040     DBusMessageIter msg_iter;
3041     pa_tz_device *device;
3042     dbus_int32_t device_id;
3043     dbus_int32_t id, direction, state;
3044     dbus_int32_t vendor_id, product_id;
3045     char *type, *name;
3046
3047     pa_assert(conn);
3048     pa_assert(msg);
3049     pa_assert(userdata);
3050
3051     manager = (pa_device_manager*) userdata;
3052
3053     pa_assert_se(dbus_message_get_args(msg, NULL,
3054                                        DBUS_TYPE_INT32, &device_id,
3055                                        DBUS_TYPE_INVALID));
3056
3057     pa_log_info("Get device by id(%d)", device_id);
3058
3059     if ((device = _device_list_get_device_by_id(manager, device_id))) {
3060         pa_assert_se((reply = dbus_message_new_method_return(msg)));
3061         dbus_message_iter_init_append(reply, &msg_iter);
3062
3063         id = (dbus_int32_t)pa_tz_device_get_id(device);
3064         state = pa_tz_device_get_state(device);
3065         direction = pa_tz_device_get_direction(device);
3066         type = pa_tz_device_get_type(device);
3067         name = pa_tz_device_get_name(device);
3068         vendor_id = (dbus_int32_t) pa_tz_device_get_vendor_id(device);
3069         product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
3070
3071         simple_device_dump(PA_LOG_INFO, "[GET_BY_ID]", device_id, type, name, direction, state);
3072
3073         dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &id);
3074         dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &type);
3075         dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &direction);
3076         dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &state);
3077         dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name);
3078         dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &vendor_id);
3079         dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &product_id);
3080
3081         pa_assert_se(dbus_connection_send(conn, reply, NULL));
3082         dbus_message_unref(reply);
3083     } else {
3084         pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
3085     }
3086 }
3087
3088 static void handle_is_stream_on_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3089     pa_device_manager *manager;
3090     DBusMessage *reply;
3091     pa_tz_device *device;
3092     dbus_bool_t is_on = false;
3093     dbus_int32_t stream_id, device_id;
3094     pa_intset *stream_id_set;
3095     int32_t stream_id_val;
3096     int ret;
3097     dm_device_state_t state;
3098
3099     pa_assert(conn);
3100     pa_assert(msg);
3101     pa_assert(userdata);
3102
3103     pa_log_info("Is stream on device");
3104
3105     manager = (pa_device_manager*) userdata;
3106
3107
3108     pa_assert_se(dbus_message_get_args(msg, NULL,
3109                                        DBUS_TYPE_INT32, &stream_id,
3110                                        DBUS_TYPE_INT32, &device_id,
3111                                        DBUS_TYPE_INVALID));
3112
3113     if ((device = _device_list_get_device_by_id(manager, device_id))) {
3114         pa_assert_se((reply = dbus_message_new_method_return(msg)));
3115
3116         state = pa_tz_device_get_state(device);
3117         if (state == DM_DEVICE_STATE_ACTIVATED) {
3118             stream_id_set = pa_tz_device_get_stream_list(device);
3119             PA_INTSET_FOREACH(stream_id_val, stream_id_set, ret) {
3120                 if (stream_id_val == stream_id) {
3121                     is_on = true;
3122                     pa_log_info("stream(%d) is on device(%d)", stream_id, device_id);
3123                     break;
3124                 }
3125             }
3126             pa_intset_free(stream_id_set);
3127         } else {
3128             pa_log_info("device(%d) is not activated, regard as no stream on it", device_id);
3129             is_on = false;
3130         }
3131
3132         pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &is_on,
3133                                                      DBUS_TYPE_INVALID));
3134
3135         pa_assert_se(dbus_connection_send(conn, reply, NULL));
3136         dbus_message_unref(reply);
3137     } else {
3138         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.Internal");
3139     }
3140 }
3141
3142 static void handle_get_bt_a2dp_status(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3143     pa_device_manager *dm;
3144     DBusMessage *reply = NULL;
3145     pa_tz_device *device;
3146     dbus_bool_t is_bt_on = false;
3147     const char *bt_name = "none";
3148
3149     pa_assert(conn);
3150     pa_assert(msg);
3151     pa_assert(userdata);
3152
3153     pa_log_info("Get BT A2DP list");
3154
3155     dm = (pa_device_manager*) userdata;
3156
3157     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3158
3159     /* FIXME : Give system_id for multi device */
3160     if ((device = _device_list_get_device(dm, DEVICE_TYPE_BT_A2DP, NULL)) != NULL) {
3161         is_bt_on = true;
3162         bt_name = pa_tz_device_get_name(device);
3163     }
3164
3165     pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &is_bt_on,
3166                                                  DBUS_TYPE_STRING, &bt_name,
3167                                                  DBUS_TYPE_INVALID));
3168
3169     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3170     dbus_message_unref(reply);
3171 }
3172
3173
3174
3175 static void handle_load_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3176     pa_device_manager *dm;
3177     char *type, *role;
3178     DBusMessage *reply = NULL;
3179
3180     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3181     dm = (pa_device_manager *) userdata;
3182     pa_assert_se(dbus_message_get_args(msg, NULL,
3183                                        DBUS_TYPE_STRING, &type,
3184                                        DBUS_TYPE_STRING, &role,
3185                                        DBUS_TYPE_INVALID));
3186
3187     pa_device_manager_load_sink(dm, type, role);
3188     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3189     dbus_message_unref(reply);
3190 }
3191
3192 static void handle_unload_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3193     pa_device_manager *dm;
3194     char *type, *role;
3195     DBusMessage *reply = NULL;
3196
3197     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3198     dm = (pa_device_manager *) userdata;
3199     pa_assert_se(dbus_message_get_args(msg, NULL,
3200                                        DBUS_TYPE_STRING, &type,
3201                                        DBUS_TYPE_STRING, &role,
3202                                        DBUS_TYPE_INVALID));
3203
3204     pa_device_manager_unload_sink(dm, type, role);
3205     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3206     dbus_message_unref(reply);
3207 }
3208
3209 static void handle_unload_sink_with_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3210     pa_device_manager *dm;
3211     char *device_string;
3212     DBusMessage *reply = NULL;
3213
3214     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3215     dm = (pa_device_manager *) userdata;
3216     pa_assert_se(dbus_message_get_args(msg, NULL,
3217                                        DBUS_TYPE_STRING, &device_string,
3218                                        DBUS_TYPE_INVALID));
3219
3220     pa_device_manager_unload_sink_with_device_string(dm, device_string);
3221     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3222     dbus_message_unref(reply);
3223 }
3224
3225 static void handle_get_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3226     pa_device_manager *dm;
3227     char *type, *role;
3228     const char *device_string;
3229     dbus_bool_t is_playback;
3230     DBusMessage *reply;
3231
3232     dm = (pa_device_manager *) userdata;
3233     pa_assert_se(dbus_message_get_args(msg, NULL,
3234                                        DBUS_TYPE_BOOLEAN, &is_playback,
3235                                        DBUS_TYPE_STRING, &type,
3236                                        DBUS_TYPE_STRING, &role,
3237                                        DBUS_TYPE_INVALID));
3238
3239     device_string = pa_device_manager_get_device_string(dm, is_playback, type, role);
3240     if (device_string == NULL) {
3241         pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
3242         return;
3243     }
3244
3245     pa_log_info("device string : %s", device_string);
3246     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3247     pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &device_string,
3248                                                  DBUS_TYPE_INVALID));
3249     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3250     dbus_message_unref(reply);
3251 }
3252
3253 static void handle_dump_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3254     pa_device_manager *dm;
3255     pa_tz_device *device;
3256     uint32_t device_idx;
3257     DBusMessage *reply = NULL;
3258
3259     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3260     dm = (pa_device_manager *) userdata;
3261
3262     PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
3263         pa_tz_device_dump_info(device, PA_LOG_INFO);
3264     }
3265     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3266     dbus_message_unref(reply);
3267 }
3268
3269 static bool is_usb_output_device(pa_tz_device *device) {
3270     char *type;
3271     dm_device_direction_t direction;
3272     pa_sink *sink;
3273
3274     pa_assert(device);
3275
3276     type = pa_tz_device_get_type(device);
3277     if (!pa_streq(type, DEVICE_TYPE_USB_AUDIO)) {
3278         pa_log_error("device(id:%d, %s) is not USB AUDIO type", pa_tz_device_get_id(device), type);
3279         return false;
3280     }
3281     direction = pa_tz_device_get_direction(device);
3282     if (direction & DM_DEVICE_DIRECTION_OUT) {
3283         if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
3284             pa_log_error("sink is null");
3285             return false;
3286         }
3287     } else {
3288         pa_log_error("this device is not for output");
3289         return false;
3290     }
3291
3292     return true;
3293 }
3294
3295 static bool is_supported_sample_rate(uint32_t *supported_sample_rates, uint32_t sample_rate) {
3296     int i;
3297
3298     pa_assert(supported_sample_rates);
3299
3300     /* use a supported sample rate selected by user */
3301     for (i = 0; supported_sample_rates[i]; i++) {
3302         if (supported_sample_rates[i] == sample_rate) {
3303             pa_log_info("%u is supported", sample_rate);
3304             return true;
3305         }
3306     }
3307     pa_log_error("%u is not supported", sample_rate);
3308     return false;
3309 }
3310
3311 static void handle_get_supported_sample_rates(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3312     pa_device_manager *dm;
3313     DBusMessage *reply = NULL;
3314     DBusMessageIter msg_iter, array_iter, item_iter;
3315     dbus_int32_t device_id;
3316     pa_tz_device *device;
3317     pa_sink *sink;
3318     int i;
3319
3320     pa_assert(conn);
3321     pa_assert(msg);
3322     pa_assert(userdata);
3323
3324     dm = (pa_device_manager *)userdata;
3325
3326     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3327
3328     pa_assert_se(dbus_message_get_args(msg, NULL,
3329                                        DBUS_TYPE_INT32, &device_id,
3330                                        DBUS_TYPE_INVALID));
3331
3332     pa_log_info("Get supported sample rates of the device(id:%d)", device_id);
3333
3334     if (!(device = _device_list_get_device_by_id(dm, device_id))) {
3335         pa_log_error("could not find any device with id:%d", device_id);
3336         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
3337         return;
3338     }
3339     if (!is_usb_output_device(device)) {
3340         pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
3341         return;
3342     }
3343     sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL);
3344
3345     dbus_message_iter_init_append(reply, &msg_iter);
3346     pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(u)", &array_iter));
3347     for (i = 0; sink->supported_sample_rates[i]; i++) {
3348         pa_log_info("%u is supported", sink->supported_sample_rates[i]);
3349         pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &item_iter));
3350         dbus_message_iter_append_basic(&item_iter, DBUS_TYPE_UINT32, &sink->supported_sample_rates[i]);
3351         pa_assert_se(dbus_message_iter_close_container(&array_iter, &item_iter));
3352     }
3353     pa_assert_se(dbus_message_iter_close_container(&msg_iter, &array_iter));
3354     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3355     dbus_message_unref(reply);
3356 }
3357
3358 static void handle_set_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3359     pa_device_manager *dm;
3360     DBusMessage *reply = NULL;
3361     dbus_int32_t device_id;
3362     dbus_uint32_t sample_rate;
3363     uint32_t prev_selected_sample_rate;
3364     pa_tz_device *device;
3365     pa_sink *sink;
3366     pa_sink_input *si;
3367     uint32_t idx;
3368
3369     pa_assert(conn);
3370     pa_assert(msg);
3371     pa_assert(userdata);
3372
3373     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3374     dm = (pa_device_manager *)userdata;
3375     pa_assert_se(dbus_message_get_args(msg, NULL,
3376                                        DBUS_TYPE_INT32, &device_id,
3377                                        DBUS_TYPE_UINT32, &sample_rate,
3378                                        DBUS_TYPE_INVALID));
3379
3380     pa_log_info("Set sample rate(%u) of the device(id:%d)", sample_rate, device_id);
3381
3382     if (!(device = _device_list_get_device_by_id(dm, device_id))) {
3383         pa_log_error("could not find any device with id:%d", device_id);
3384         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
3385         return;
3386     }
3387     if (!is_usb_output_device(device)) {
3388         pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
3389         return;
3390     }
3391     sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL);
3392
3393     /* use stream original sample rate if possible */
3394     if (sample_rate == 0) {
3395         sink->avoid_resampling = true;
3396         PA_IDXSET_FOREACH(si, sink->inputs, idx) {
3397             if (pa_sink_reconfigure(sink, &si->sample_spec, pa_sink_input_is_passthrough(si)) == -1) {
3398                 pa_log_error("failed to reconfigure");
3399                 pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
3400                 sink->avoid_resampling = sink->origin_avoid_resampling;
3401                 return;
3402             }
3403         }
3404         sink->selected_sample_rate = 0;
3405
3406         pa_log_info("Set sample rate to avoid resampling for the device(%u) successfully", device_id);
3407         pa_assert_se(dbus_connection_send(conn, reply, NULL));
3408         dbus_message_unref(reply);
3409         return;
3410     }
3411
3412     /* use a supported sample rate selected by user */
3413     if (!is_supported_sample_rate(sink->supported_sample_rates, sample_rate)) {
3414         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
3415         return;
3416     }
3417     prev_selected_sample_rate = sink->selected_sample_rate;
3418     sink->selected_sample_rate = sample_rate;
3419
3420     PA_IDXSET_FOREACH(si, sink->inputs, idx) {
3421         if (pa_sink_reconfigure(sink, &si->sample_spec, pa_sink_input_is_passthrough(si)) == -1) {
3422             pa_log_error("failed to reconfigure");
3423             pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
3424             sink->selected_sample_rate = prev_selected_sample_rate;
3425             return;
3426         }
3427         break;
3428     }
3429     sink->avoid_resampling = sink->origin_avoid_resampling;
3430
3431     pa_log_info("Set sample rate(%u) of the device(id:%d) successfully", sample_rate, device_id);
3432     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3433     dbus_message_unref(reply);
3434 }
3435
3436 static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3437     pa_device_manager *dm;
3438     DBusMessage *reply = NULL;
3439     dbus_int32_t device_id;
3440     pa_tz_device *device;
3441     pa_sink *sink;
3442
3443     pa_assert(conn);
3444     pa_assert(msg);
3445     pa_assert(userdata);
3446
3447     dm = (pa_device_manager *)userdata;
3448
3449     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3450
3451     pa_assert_se(dbus_message_get_args(msg, NULL,
3452                                        DBUS_TYPE_INT32, &device_id,
3453                                        DBUS_TYPE_INVALID));
3454
3455     pa_log_info("Get sample rate of the device(id:%d)", device_id);
3456
3457     if (!(device = _device_list_get_device_by_id(dm, device_id))) {
3458         pa_log_error("could not find any device with id:%d", device_id);
3459         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
3460         return;
3461     }
3462     if (!is_usb_output_device(device)) {
3463         pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
3464         return;
3465     }
3466     sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL);
3467
3468     pa_log_info("Get sample rate(%u) of the device(id:%d) successfully", sink->selected_sample_rate, device_id);
3469     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3470     pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &sink->selected_sample_rate, DBUS_TYPE_INVALID));
3471     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3472     dbus_message_unref(reply);
3473 }
3474
3475 static void handle_set_specific_stream_only(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3476     pa_device_manager *dm;
3477     DBusMessage *reply = NULL;
3478     dbus_int32_t device_id;
3479     char *stream_role;
3480     pa_tz_device *device;
3481
3482     pa_assert(conn);
3483     pa_assert(msg);
3484     pa_assert(userdata);
3485
3486     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3487     dm = (pa_device_manager *)userdata;
3488     pa_assert_se(dbus_message_get_args(msg, NULL,
3489                                        DBUS_TYPE_INT32, &device_id,
3490                                        DBUS_TYPE_STRING, &stream_role,
3491                                        DBUS_TYPE_INVALID));
3492
3493     pa_log_info("Set the device(id:%d) only for the stream role(%s)", device_id, stream_role);
3494
3495     if (!(device = _device_list_get_device_by_id(dm, device_id))) {
3496         pa_log_error("could not find any device with id:%d", device_id);
3497         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
3498         return;
3499     }
3500     if (!is_usb_output_device(device)) {
3501         pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
3502         return;
3503     }
3504
3505     device->specified_stream_role = stream_role;
3506
3507     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3508     dbus_message_unref(reply);
3509 }
3510
3511 static void handle_get_specified_stream(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3512     pa_device_manager *dm;
3513     DBusMessage *reply = NULL;
3514     dbus_int32_t device_id;
3515     char *specified_stream_role;
3516     pa_tz_device *device;
3517
3518     pa_assert(conn);
3519     pa_assert(msg);
3520     pa_assert(userdata);
3521
3522     dm = (pa_device_manager *)userdata;
3523
3524     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3525
3526     pa_assert_se(dbus_message_get_args(msg, NULL,
3527                                        DBUS_TYPE_INT32, &device_id,
3528                                        DBUS_TYPE_INVALID));
3529
3530     pa_log_info("Get specified stream role for the device(id:%d)", device_id);
3531
3532     if (!(device = _device_list_get_device_by_id(dm, device_id))) {
3533         pa_log_error("could not find any device with id:%d", device_id);
3534         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
3535         return;
3536     }
3537     if (!is_usb_output_device(device)) {
3538         pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
3539         return;
3540     }
3541
3542     specified_stream_role = device->specified_stream_role;
3543
3544     pa_log_info("stream role(%s) is specified for the device(id:%d)", device->specified_stream_role, device_id);
3545     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3546     pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &specified_stream_role, DBUS_TYPE_INVALID));
3547     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3548     dbus_message_unref(reply);
3549 }
3550
3551 static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3552     pa_device_manager *dm = (pa_device_manager *)userdata;
3553     char *type;
3554     dbus_int32_t status;
3555     DBusMessage *reply = NULL;
3556     DBusError error;
3557
3558     pa_assert_se((reply = dbus_message_new_method_return(msg)));
3559
3560     dbus_error_init(&error);
3561     if (!dbus_message_get_args(msg, NULL,
3562                                        DBUS_TYPE_STRING, &type,
3563                                        DBUS_TYPE_INT32, &status,
3564                                        DBUS_TYPE_INVALID)) {
3565         pa_log_error("failed to get dbus args : %s", error.message);
3566         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
3567         dbus_error_free(&error);
3568     }
3569
3570     pa_log_debug("handle_test_device_status_change, type:%s, status:%d", type, status);
3571
3572     handle_device_status_changed(dm, type, NULL,  NULL, status);
3573     pa_assert_se(dbus_connection_send(conn, reply, NULL));
3574     dbus_message_unref(reply);
3575 }
3576
3577 static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3578     const char *xml = DEVICE_MANAGER_INTROSPECT_XML;
3579     DBusMessage *r = NULL;
3580
3581     pa_assert(conn);
3582     pa_assert(msg);
3583     pa_assert(userdata);
3584
3585     pa_assert_se(r = dbus_message_new_method_return(msg));
3586     pa_assert_se(dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID));
3587
3588     if (r) {
3589         pa_assert_se(dbus_connection_send((conn), r, NULL));
3590         dbus_message_unref(r);
3591     }
3592
3593     return DBUS_HANDLER_RESULT_HANDLED;
3594 }
3595
3596 static DBusHandlerResult handle_device_manager_methods(DBusConnection *conn, DBusMessage *msg, void *userdata) {
3597     int method_idx = 0;
3598
3599     pa_assert(conn);
3600     pa_assert(msg);
3601     pa_assert(userdata);
3602
3603     for (method_idx = 0; method_idx < METHOD_HANDLER_MAX; method_idx++) {
3604         if (dbus_message_is_method_call(msg, DBUS_INTERFACE_DEVICE_MANAGER, method_handlers[method_idx].method_name)) {
3605             method_handlers[method_idx].receive_cb(conn, msg, userdata);
3606             return DBUS_HANDLER_RESULT_HANDLED;
3607         }
3608     }
3609
3610     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3611 }
3612
3613 static DBusHandlerResult method_call_handler(DBusConnection *c, DBusMessage *m, void *userdata) {
3614     struct userdata *u = userdata;
3615     const char *path, *interface, *member;
3616
3617     pa_assert(c);
3618     pa_assert(m);
3619     pa_assert(u);
3620
3621     path = dbus_message_get_path(m);
3622     interface = dbus_message_get_interface(m);
3623     member = dbus_message_get_member(m);
3624
3625     pa_log_info("DeviceManager Method Call Handler : path=%s, interface=%s, member=%s", path, interface, member);
3626
3627     if (!pa_streq(path, DBUS_OBJECT_DEVICE_MANAGER))
3628         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3629
3630     if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
3631         return handle_introspect(c, m, u);
3632         /*
3633     } else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get")) {
3634         return handle_get_property(c, m, u);
3635     } else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set")) {
3636         return  handle_set_property(c, m, u);
3637     } else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "GetAll")) {
3638         return handle_get_all_property(c, m, u);
3639         */
3640     } else {
3641         return handle_device_manager_methods(c, m, u);
3642     }
3643
3644     return DBUS_HANDLER_RESULT_HANDLED;
3645 }
3646
3647 static void endpoint_init(pa_device_manager *dm) {
3648     static const DBusObjectPathVTable vtable_endpoint = {
3649         .message_function = method_call_handler,
3650     };
3651
3652     pa_log_info("Device manager dbus endpoint init");
3653
3654     if (dm && dm->dbus_conn) {
3655         if (!dbus_connection_register_object_path(pa_dbus_connection_get(dm->dbus_conn), DBUS_OBJECT_DEVICE_MANAGER, &vtable_endpoint, dm))
3656             pa_log_error("Failed to register object path");
3657     } else {
3658         pa_log_error("Cannot get dbus connection to register object path");
3659     }
3660 }
3661
3662 static void endpoint_done(pa_device_manager *dm) {
3663     pa_log_info("Device manager dbus endpoint done");
3664     if (dm && dm->dbus_conn) {
3665         if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(dm->dbus_conn), DBUS_OBJECT_DEVICE_MANAGER))
3666             pa_log_error("Failed to unregister object path");
3667     } else {
3668         pa_log_error("Cannot get dbus connection to unregister object path");
3669     }
3670 }
3671
3672 static void dbus_init(pa_device_manager *dm) {
3673     DBusError error;
3674     pa_dbus_connection *connection = NULL;
3675
3676     pa_assert(dm);
3677     pa_log_info("Dbus init");
3678     dbus_error_init(&error);
3679
3680     if (!(connection = pa_dbus_bus_get(dm->core, DBUS_BUS_SYSTEM, &error)) || dbus_error_is_set(&error)) {
3681         if (connection) {
3682             pa_dbus_connection_unref(connection);
3683         }
3684         pa_log_error("Unable to contact D-Bus system bus: %s: %s", error.name, error.message);
3685         goto fail;
3686     } else {
3687         pa_log_info("Got dbus connection");
3688     }
3689
3690     dm->dbus_conn = connection;
3691
3692     if (watch_signals(dm) < 0)
3693         pa_log_error("dbus watch signals failed");
3694     else
3695         pa_log_debug("dbus ready to get signals");
3696
3697     endpoint_init(dm);
3698
3699 fail:
3700     dbus_error_free(&error);
3701 }
3702
3703 static void dbus_deinit(pa_device_manager *dm) {
3704     pa_assert(dm);
3705
3706     pa_log_info("Dbus deinit");
3707
3708     endpoint_done(dm);
3709     unwatch_signals(dm);
3710
3711     if (dm->dbus_conn) {
3712         pa_dbus_connection_unref(dm->dbus_conn);
3713         dm->dbus_conn = NULL;
3714     }
3715 }
3716 #endif
3717
3718 pa_idxset* pa_device_manager_get_device_list(pa_device_manager *dm) {
3719     pa_assert(dm);
3720     pa_assert(dm->device_list);
3721
3722     return dm->device_list;
3723 }
3724
3725 pa_tz_device* pa_device_manager_get_device(pa_device_manager *dm, const char *type) {
3726     pa_assert(dm);
3727
3728     return _device_list_get_device(dm, type, NULL);
3729 }
3730
3731 pa_tz_device* pa_device_manager_get_device_by_id(pa_device_manager *dm, uint32_t id) {
3732     pa_assert(dm);
3733
3734     return _device_list_get_device_by_id(dm, id);
3735 }
3736
3737 pa_tz_device* pa_device_manager_get_device_with_sink(pa_sink *sink) {
3738     pa_assert(sink);
3739
3740     return sink->device_item;
3741 }
3742
3743 pa_tz_device* pa_device_manager_get_device_with_source(pa_source *source) {
3744     pa_assert(source);
3745
3746     return source->device_item;
3747 }
3748
3749 pa_tz_device* pa_device_manager_load_forwarding(pa_device_manager *dm) {
3750     return _load_forwarding_device(dm);
3751 }
3752
3753 void pa_device_manager_unload_forwarding(pa_device_manager *dm) {
3754     pa_tz_device *forwarding_device;
3755
3756     forwarding_device = _device_list_get_device(dm, DEVICE_TYPE_FORWARDING, NULL);
3757     if (forwarding_device)
3758         pa_tz_device_free(forwarding_device);
3759     else
3760         pa_log_warn("There is no forwarding device");
3761 }
3762
3763 pa_sink* pa_device_manager_load_sink(pa_device_manager *dm, const char *type, const char *role) {
3764     const char *device_string, *params;
3765     struct device_type_info *type_info;
3766     struct device_file_info *file_info;
3767     pa_tz_device *device;
3768     pa_sink *sink;
3769     uint32_t device_idx;
3770
3771     pa_assert(dm);
3772     pa_assert(dm->device_list);
3773     pa_assert(type);
3774     pa_assert(role);
3775
3776     pa_log_info("Load Sink for '%s.%s'", type, role);
3777     PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
3778         if (pa_streq(type, pa_tz_device_get_type(device))) {
3779             if (pa_tz_device_get_sink(device, role)) {
3780                 pa_log_warn("Proper sink for '%s.%s' already loaded", type, role);
3781                 return NULL;
3782             }
3783         }
3784     }
3785
3786     if (!(type_info = _device_manager_get_type_info(dm->type_infos, type))) {
3787         pa_log_error("No type map for %s", type);
3788         return NULL;
3789     }
3790
3791     if (type_info->playback_devices == NULL) {
3792         pa_log_error("No playback devices for %s", type_info->type);
3793         goto fail;
3794     }
3795
3796     if (!(device_string = pa_hashmap_get(type_info->playback_devices, role))) {
3797         pa_log_error("No device-string for '%s.%s'", type, role);
3798         goto fail;
3799     }
3800
3801     if (!(file_info = _device_manager_get_file_info(dm->file_map->playback, device_string))) {
3802         pa_log_error("No playback file-map for '%s'", device_string);
3803         goto fail;
3804     }
3805
3806     if (!(params = pa_hashmap_get(file_info->roles, role))) {
3807         pa_log_error("No params for '%s,%s'", device_string, role);
3808         goto fail;
3809     }
3810
3811     if ((sink = load_device(dm->core, true, device_string, params))) {
3812         pa_log_debug("loaded sink '%s' for '%s,%s' success", sink->name, type, role);
3813     } else {
3814         pa_log_warn("Cannot load playback device with '%s,%s'", device_string, params);
3815         goto fail;
3816     }
3817
3818     return sink;
3819
3820 fail:
3821     return NULL;
3822 }
3823
3824 void pa_device_manager_unload_sink(pa_device_manager *dm, const char *type, const char *role) {
3825     const char *device_string;
3826     struct device_type_info *type_info;
3827
3828     pa_assert(dm);
3829     pa_assert(dm->device_list);
3830     pa_assert(type);
3831     pa_assert(role);
3832
3833     pa_log_info("Unload Sink for '%s.%s'", type, role);
3834
3835     if (!(type_info = _device_manager_get_type_info(dm->type_infos, type))) {
3836         pa_log_error("No type map for %s", type);
3837         return;
3838     }
3839
3840     if (type_info->playback_devices == NULL) {
3841         pa_log_error("No playback devices for %s", type_info->type);
3842         return;
3843     }
3844
3845     if (!(device_string = pa_hashmap_get(type_info->playback_devices, role))) {
3846         pa_log_error("No device-string for '%s.%s'", type, role);
3847         return;
3848     }
3849
3850     unload_device(dm->core, true, device_string);
3851 }
3852
3853 void pa_device_manager_unload_sink_with_device_string(pa_device_manager *dm, const char *device_string) {
3854     pa_assert(dm);
3855     pa_assert(device_string);
3856
3857     unload_device(dm->core, true, device_string);
3858 }
3859
3860 pa_source* pa_device_manager_load_source(pa_device_manager *dm, const char *type, const char *role) {
3861     const char *device_string, *params;
3862     struct device_type_info *type_info;
3863     struct device_file_info *file_info;
3864     pa_tz_device *device;
3865     pa_source *source;
3866     uint32_t device_idx;
3867
3868     pa_assert(dm);
3869     pa_assert(dm->device_list);
3870     pa_assert(type);
3871     pa_assert(role);
3872
3873     pa_log_info("Load Source for '%s.%s'", type, role);
3874
3875     PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
3876         if (pa_streq(type, pa_tz_device_get_type(device))) {
3877             if (pa_tz_device_get_source(device, role)) {
3878                 pa_log_warn("Proper source for '%s.%s' already loaded", type, role);
3879                 return NULL;
3880             }
3881         }
3882     }
3883
3884     if (!(type_info = _device_manager_get_type_info(dm->type_infos, type))) {
3885         pa_log_error("No type map for %s", type);
3886         return NULL;
3887     }
3888
3889     if (type_info->capture_devices == NULL) {
3890         pa_log_error("No capture devices for %s", type_info->type);
3891         goto fail;
3892     }
3893
3894     if (!(device_string = pa_hashmap_get(type_info->capture_devices, role))) {
3895         pa_log_error("No device-string for '%s.%s'", type, role);
3896         goto fail;
3897     }
3898
3899     if (!(file_info = _device_manager_get_file_info(dm->file_map->capture, device_string))) {
3900         pa_log_error("No capture file-map for '%s'", device_string);
3901         goto fail;
3902     }
3903
3904     if (!(params = pa_hashmap_get(file_info->roles, role))) {
3905         pa_log_error("No params for '%s,%s'", device_string, role);
3906         goto fail;
3907     }
3908
3909     if ((source = load_device(dm->core, false, device_string, params))) {
3910         pa_log_debug("loaded source '%s' for '%s,%s' success", source->name, type, role);
3911     } else {
3912         pa_log_warn("Cannot load capture device with '%s,%s'", device_string, params);
3913         goto fail;
3914     }
3915
3916     return source;
3917
3918 fail:
3919     return NULL;
3920 }
3921
3922 void pa_device_manager_unload_source(pa_device_manager *dm, const char *type, const char *role) {
3923     const char *device_string;
3924     struct device_type_info *type_info;
3925
3926     pa_assert(dm);
3927     pa_assert(dm->device_list);
3928     pa_assert(type);
3929     pa_assert(role);
3930
3931     pa_log_info("Unload Source for '%s.%s'", type, role);
3932
3933     if (!(type_info = _device_manager_get_type_info(dm->type_infos, type))) {
3934         pa_log_error("No type map for %s", type);
3935         return;
3936     }
3937
3938     if (type_info->capture_devices == NULL) {
3939         pa_log_error("No capture devices for %s", type_info->type);
3940         return;
3941     }
3942
3943     if (!(device_string = pa_hashmap_get(type_info->capture_devices, role))) {
3944         pa_log_error("No device-string for '%s.%s'", type, role);
3945         return;
3946     }
3947
3948     unload_device(dm->core, false, device_string);
3949 }
3950
3951 void pa_device_manager_unload_source_with_device_string(pa_device_manager *dm, const char *device_string) {
3952     pa_assert(dm);
3953     pa_assert(device_string);
3954
3955     unload_device(dm->core, false, device_string);
3956 }
3957
3958 const char* pa_device_manager_get_device_string(pa_device_manager *dm, bool is_playback, const char *type, const char *role) {
3959     struct device_type_info *type_info;
3960
3961     pa_assert(dm);
3962     pa_assert(type);
3963     pa_assert(role);
3964
3965     type_info = _device_manager_get_type_info(dm->type_infos, type);
3966     if (type_info == NULL) {
3967         pa_log_error("No type info for %s", type);
3968         return NULL;
3969     }
3970
3971     return device_type_info_get_device_string(type_info, is_playback, role);
3972 }
3973
3974 void pa_device_manager_update_device_running_state(pa_device_manager *dm, uint32_t num_of_devices, pa_device_info *device_infos, bool output_device) {
3975     int32_t i, j;
3976     uint32_t index;
3977
3978     pa_assert(dm);
3979
3980     index = (uint32_t)output_device; /* input:0, output:1 */
3981
3982     /* reset case */
3983     if (num_of_devices == 0) {
3984         for (i = 0; i < DEVICE_INDEX_MAX; i++) {
3985             if (!internal_codec_devices[i].is_running[index])
3986                 continue;
3987             internal_codec_devices[i].is_running[index] = false;
3988             /* change to NOT RUNNING */
3989             if (!internal_codec_devices[i].is_running[!index]) {
3990                 find_device_and_set_running(dm, internal_codec_devices[i].type, false);
3991                 internal_codec_devices_dump();
3992             }
3993         }
3994         return;
3995     }
3996
3997     for (i = 0; i < DEVICE_INDEX_MAX; i++) {
3998         bool skip = false;
3999         if (!internal_codec_devices[i].is_running[index])
4000             continue;
4001         for (j = 0; j < num_of_devices; j++) {
4002             if (pa_safe_streq(device_infos[j].type, internal_codec_devices[i].type))
4003                 skip = true;
4004         }
4005         if (!skip) {
4006             internal_codec_devices[i].is_running[index] = false;
4007             /* change to NOT RUNNING */
4008             if (!internal_codec_devices[i].is_running[!index]) {
4009                 find_device_and_set_running(dm, internal_codec_devices[i].type, false);
4010                 internal_codec_devices_dump();
4011             }
4012         }
4013     }
4014
4015     for (i = 0; i < num_of_devices; i++) {
4016         for (j = 0; j < DEVICE_INDEX_MAX; j++) {
4017             if (!pa_safe_streq(device_infos[i].type, internal_codec_devices[j].type))
4018                 continue;
4019             if (!internal_codec_devices[j].is_running[index]) {
4020                 internal_codec_devices[j].is_running[index] = true;
4021                 /* change to RUNNING */
4022                 find_device_and_set_running(dm, internal_codec_devices[j].type, true);
4023                 internal_codec_devices_dump();
4024             }
4025         }
4026     }
4027 }
4028
4029 static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_tz_device_hook_data_for_conn_changed *data, pa_device_manager *dm) {
4030     send_device_connection_changed_signal(data->event_id, data->device, data->is_connected, dm);
4031     return PA_HOOK_OK;
4032 }
4033
4034 /* it will be replaced by running_changed_hook_cb() */
4035 static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_tz_device_hook_data_for_state_changed *data, pa_device_manager *dm) {
4036     send_device_info_changed_signal(data->event_id, data->device, DM_DEVICE_CHANGED_INFO_STATE, dm);
4037     send_device_state_changed_signal(data->event_id, data->device, data->activated, dm);
4038     return PA_HOOK_OK;
4039 }
4040
4041 static pa_hook_result_t device_running_changed_hook_cb(pa_core *c, pa_tz_device_hook_data_for_running_changed *data, pa_device_manager *dm) {
4042     send_device_running_changed_signal(data->event_id, data->device, data->is_running, dm);
4043     pa_log_info("RUNNING CHANGED!! device type[%s], is running[%d]", data->device->type, data->is_running);
4044     return PA_HOOK_OK;
4045 }
4046
4047 pa_device_manager* pa_device_manager_get(pa_core *c) {
4048     pa_device_manager *dm;
4049
4050     pa_assert(c);
4051
4052     pa_log_info("pa_device_manager_get");
4053
4054     if ((dm = pa_shared_get(c, SHARED_DEVICE_MANAGER)))
4055         return pa_device_manager_ref(dm);
4056
4057     dm = pa_xnew0(pa_device_manager, 1);
4058     PA_REFCNT_INIT(dm);
4059     dm->core = c;
4060     dm->device_list = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
4061     dm->device_status = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
4062
4063     dbus_init(dm);
4064
4065     dm->sink_put_hook_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+10, (pa_hook_cb_t) sink_put_hook_callback, dm);
4066     dm->sink_unlink_hook_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_EARLY, (pa_hook_cb_t) sink_unlink_hook_callback, dm);
4067     dm->sink_state_changed_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_source_state_changed_hook_cb, dm);
4068     dm->source_put_hook_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+10, (pa_hook_cb_t) source_put_hook_callback, dm);
4069     dm->source_unlink_hook_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_EARLY, (pa_hook_cb_t) source_unlink_hook_callback, dm);
4070     dm->source_state_changed_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_source_state_changed_hook_cb, dm);
4071     dm->comm = pa_communicator_get(dm->core);
4072     dm->comm_hook_device_connection_changed_slot = pa_hook_connect(pa_communicator_hook(dm->comm, PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED),
4073             PA_HOOK_EARLY, (pa_hook_cb_t)device_connection_changed_hook_cb, dm);
4074     dm->comm_hook_device_state_changed_slot = pa_hook_connect(pa_communicator_hook(dm->comm, PA_COMMUNICATOR_HOOK_DEVICE_STATE_CHANGED),
4075             PA_HOOK_EARLY, (pa_hook_cb_t)device_state_changed_hook_cb, dm);
4076     dm->comm_hook_device_running_changed_slot = pa_hook_connect(pa_communicator_hook(dm->comm, PA_COMMUNICATOR_HOOK_DEVICE_RUNNING_CHANGED),
4077         PA_HOOK_EARLY, (pa_hook_cb_t)device_running_changed_hook_cb, dm);
4078
4079     dm->hal_interface = pa_hal_interface_get(dm->core);
4080
4081     if (!(dm->type_infos = parse_device_type_infos())) {
4082         pa_log_error("Parse device-type-map failed");
4083         return NULL;
4084     }
4085
4086     if (!(dm->file_map = parse_device_file_map())) {
4087         pa_log_error("Parse device-file-map failed");
4088         return NULL;
4089     }
4090
4091     device_type_status_init(dm);
4092
4093     if (load_builtin_devices(dm) != 0) {
4094         pa_log_error("Load Builtin Devices faled");
4095         return NULL;
4096     }
4097
4098     /* Just for convenience when test*/
4099     if (!_device_manager_set_default_sink(dm,  DEVICE_TYPE_SPEAKER, "normal")) {
4100         pa_log_warn("Set default sink with speaker(normal) failed");
4101     }
4102     if (!_device_manager_set_default_source(dm,  DEVICE_TYPE_MIC, "normal")) {
4103         pa_log_warn("Set default source with mic(normal) failed");
4104     }
4105
4106     pa_shared_set(c, SHARED_DEVICE_MANAGER, dm);
4107
4108     return dm;
4109 }
4110
4111 pa_device_manager* pa_device_manager_ref(pa_device_manager *dm) {
4112     pa_assert(dm);
4113     pa_assert(PA_REFCNT_VALUE(dm) > 0);
4114
4115     pa_log_info("pa_device_manager_ref");
4116     PA_REFCNT_INC(dm);
4117
4118     return dm;
4119 }
4120
4121 void pa_device_manager_unref(pa_device_manager *dm) {
4122     pa_assert(dm);
4123     pa_assert(PA_REFCNT_VALUE(dm) > 0);
4124
4125     pa_log_info("pa_device_manager_unref");
4126     if (PA_REFCNT_DEC(dm) > 0)
4127         return;
4128
4129     if (dm->comm_hook_device_connection_changed_slot)
4130         pa_hook_slot_free(dm->comm_hook_device_connection_changed_slot);
4131     if (dm->comm_hook_device_state_changed_slot)
4132         pa_hook_slot_free(dm->comm_hook_device_state_changed_slot);
4133     if (dm->comm_hook_device_running_changed_slot)
4134         pa_hook_slot_free(dm->comm_hook_device_running_changed_slot);
4135     if (dm->sink_put_hook_slot)
4136         pa_hook_slot_free(dm->sink_put_hook_slot);
4137     if (dm->sink_unlink_hook_slot)
4138         pa_hook_slot_free(dm->sink_unlink_hook_slot);
4139     if (dm->sink_state_changed_slot)
4140         pa_hook_slot_free(dm->sink_state_changed_slot);
4141     if (dm->source_put_hook_slot)
4142         pa_hook_slot_free(dm->source_put_hook_slot);
4143     if (dm->source_unlink_hook_slot)
4144         pa_hook_slot_free(dm->source_unlink_hook_slot);
4145     if (dm->source_state_changed_slot)
4146         pa_hook_slot_free(dm->source_state_changed_slot);
4147
4148     if (dm->hal_interface)
4149         pa_hal_interface_unref(dm->hal_interface);
4150
4151     if (dm->comm)
4152         pa_communicator_unref(dm->comm);
4153
4154     if (dm->type_infos)
4155         pa_idxset_free(dm->type_infos, (pa_free_cb_t)type_info_free_func);
4156     if (dm->file_map) {
4157         if (dm->file_map->playback)
4158             pa_idxset_free(dm->file_map->playback, (pa_free_cb_t)file_info_free_func);
4159         if (dm->file_map->capture)
4160             pa_idxset_free(dm->file_map->capture, (pa_free_cb_t)file_info_free_func);
4161         pa_xfree(dm->file_map);
4162     }
4163     if (dm->device_list)
4164         pa_idxset_free(dm->device_list, (pa_free_cb_t)pa_tz_device_free);
4165     if (dm->device_status)
4166         pa_idxset_free(dm->device_status, NULL);
4167
4168     dbus_deinit(dm);
4169
4170     if (dm->core)
4171         pa_shared_remove(dm->core, SHARED_DEVICE_MANAGER);
4172
4173     pa_xfree(dm);
4174 }