#include <pulsecore/modargs.h>
#include <pulsecore/namereg.h>
#include <pulsecore/shared.h>
+#include <pulsecore/dynarray.h>
+#include <pulsecore/hashmap.h>
#include <vconf.h>
#include <vconf-keys.h>
#define DEVICE_AVAIL_COND_STR_MAX 6
#define DEVICE_FILE_PER_TYPE_MAX 4
#define DEVICE_FILE_STRING_MAX 4
+#define DEVICE_TYPE_STR_MAX 20
+#define DEVICE_PROFILE_STR_MAX 5
+#define DEVICE_ROLE_STR_MAX 15
#define DEVICE_TYPE_OBJECT "device-types"
#define DEVICE_FILE_OBJECT "device-files"
#define DEVICE_TYPE_STR_MAX 20
-#define DEVICE_DIRECTION_STR_NONE "none"
-#define DEVICE_DIRECTION_STR_OUT "out"
-#define DEVICE_DIRECTION_STR_IN "in"
-#define DEVICE_DIRECTION_STR_BOTH "both"
-
/* Properties of sink/sources */
#define DEVICE_API_BLUEZ "bluez"
#define DEVICE_API_ALSA "alsa"
NULL
};
-
-
/* A macro to ease iteration through all entries */
#define PA_HASHMAP_FOREACH_KEY(e, h, state, key) \
for ((state) = NULL, (e) = pa_hashmap_iterate((h), &(state), (const void**)&(key)); (e); (e) = pa_hashmap_iterate((h), &(state), (const void**)&(key)))
-#define PA_DEVICE(pulse_device, pdt) \
- pdt == PA_DEVICE_TYPE_SINK ? ((pa_sink *) pulse_device) : ((pa_source *) pulse_device)
-
-#define PA_DEVICES(core, pdt) \
- pdt == PA_DEVICE_TYPE_SINK ? (((pa_core *) core)->sinks) : (((pa_core *) core)->sources)
-
-#define MAKE_SINK(s) ((pa_sink*) (s))
-#define MAKE_SOURCE(s) ((pa_source*) (s))
-
-#define COMPOUND_STATE(d) (((dm_device_profile*)d)->playback_state | ((dm_device_profile*)d)->capture_state)
-
#define BT_CVSD_CODEC_ID 1 // narrow-band
#define BT_MSBC_CODEC_ID 2 // wide-band
/*
device_detected_type_t is needed to distinguish detected device-types ( ex. earjack which can be out or both way)
So If you just want to know whether detected or not, can device_detected_t as mask.
*/
-typedef enum device_detected {
- DEVICE_NOT_DETECTED = 0x00,
- DEVICE_DETECTED = 0x01,
-} device_detected_t;
typedef enum device_detected_type {
- DEVICE_DETECTED_BT_SCO = DEVICE_DETECTED,
- DEVICE_DETECTED_FORWARDING = DEVICE_DETECTED,
- DEVICE_DETECTED_HDMI = DEVICE_DETECTED,
- DEVICE_DETECTED_AUDIO_JACK_BOTH_DIREC = DEVICE_DETECTED | 0x2,
- DEVICE_DETECTED_AUDIO_JACK_OUT_DIREC = DEVICE_DETECTED | 0x4,
+ DEVICE_DISCONNECTED = 0x0,
+ DEVICE_CONNECTED = 0x1,
+ DEVICE_CONNECTED_AUDIO_JACK_4P = DEVICE_CONNECTED | 0x2,
+ DEVICE_CONNECTED_AUDIO_JACK_3P = DEVICE_CONNECTED | 0x4,
+ DEVICE_CONNECTED_SCO = DEVICE_CONNECTED | 0x8,
+ DEVICE_OPENED_SCO = DEVICE_CONNECTED | 0xF,
} device_detected_type_t;
typedef enum dm_device_class_type {
} device_flags_type_t;
-/************* structures for represent device items can be connected/disconnected */
-/*
- Before beginning, There are two structure(dm_device, dm_device_profile)
- for represent device by following reasons.
- When bt-a2dp and bt-sco are on physically same device ,it is of course same device.
- So those physically same device item are represended by dm_device,
- and each profile is represented by dm_device_profile.
-*/
-
-
-/*
- Structure to represent physicall device.
- This is profile known data-structure, which means it can have multiple profiles ( ex. bt-a2dp and sco)
-*/
-struct dm_device {
- uint32_t id;
- char *type;
- char *name;
- const char *identifier;
-
- /* Indicate currently activated profile */
- uint32_t active_profile;
- /* include profile_items(dm_device_profile) , currently has only one item except bt case*/
- pa_idxset *profiles;
-
- pa_device_manager *dm;
-};
-
-/*
- Structure to represent each device profile (subtype).
- Even if both-way device(earjack, sco..) , one device_profile.
-*/
-typedef struct dm_device_profile {
- char *profile;
- dm_device_direction_t direction;
- dm_device_state_t playback_state;
- dm_device_state_t capture_state;
-
- /* Can get proper sink/source in hashmaps with key(=device_role) */
- pa_hashmap *playback_devices;
- pa_hashmap *capture_devices;
-
- /* device belongs to */
- dm_device *device_item;
-
- /* creation time */
- pa_usec_t creation_time;
-
-} dm_device_profile;
-
/*
Structure to save parsed information about device-file.
*/
pa_idxset *capture;
};
-struct pa_device_manager {
- PA_REFCNT_DECLARE;
-
- pa_core *core;
- pa_hook_slot *sink_put_hook_slot, *sink_state_changed_slot, *sink_unlink_hook_slot;
- pa_hook_slot *source_put_hook_slot, *source_state_changed_slot, *source_unlink_hook_slot;
- pa_communicator *comm;
-
- /*
- Idxset for save parsed information about device-type.
- { device_type_info }
- */
- pa_idxset *type_infos;
- /* For save Parsed information about device-file */
- struct device_file_map *file_map;
-
- /* device list */
- pa_idxset *device_list;
- /*
- Hashmap for save statuses got through dbus.
- { key:device_type -> value:(audio_detected_type_t or device_detected_t) }
- */
- pa_idxset *device_status;
- pa_dbus_connection *dbus_conn;
- dm_device_bt_sco_status_t bt_sco_status;
-};
-
/***************** structures for static information get from json *********/
/*
};
struct device_status_info {
- const char *type;
- const char *profile;
+ char *type;
+ char *profile;
+ char *name;
/* Identify devices among same device-types (for multi-device), currently not works*/
- const char *identifier;
- device_detected_t detected;
- device_detected_type_t detected_type;
+ char *system_id;
+ device_detected_type_t detected;
};
struct pulse_device_prop {
int status;
};
/******************************************************************************/
+struct pa_device_manager {
+ PA_REFCNT_DECLARE;
+
+ pa_core *core;
+ pa_hook_slot *sink_put_hook_slot, *sink_state_changed_slot, *sink_unlink_hook_slot;
+ pa_hook_slot *source_put_hook_slot, *source_state_changed_slot, *source_unlink_hook_slot;
+ pa_hook_slot *comm_hook_device_connection_changed_slot, *comm_hook_device_info_changed_slot;
+ pa_communicator *comm;
+
+ /*
+ Idxset for save parsed information about device-type.
+ { device_type_info }
+ */
+ pa_idxset *type_infos;
+ /* For save Parsed information about device-file */
+ struct device_file_map *file_map;
+
+ /* device list */
+ pa_idxset *device_list;
+ /*
+ Hashmap for save statuses got through dbus.
+ { key:device_type -> value:(audio_detected_type_t or device_detected_t) }
+ */
+ pa_idxset *device_status;
+ pa_dbus_connection *dbus_conn;
+};
-int device_id_max_g = 1;
-uint32_t event_id_max_g = 1;
+
+struct composite_type {
+ const char *type;
+ const char *profile;
+ const char *role;
+};
#ifdef HAVE_DBUS
static void handle_load_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void notify_device_connection_changed(dm_device *device_item, bool connected, pa_device_manager *dm);
-static void notify_device_info_changed(dm_device *device_item, dm_device_changed_info_t changed_type, pa_device_manager *dm);
-
-static int method_call_bt_sco(DBusConnection *conn, bool onoff);
-static int method_call_bt_sco_get_property(DBusConnection *conn, bool *is_wide_band, bool *nrec);
static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name);
enum method_handler_index {
#endif
-static uint32_t _new_event_id() {
- return event_id_max_g++;
-}
-
-static bool device_type_is_builtin(const char *device_type) {
- if (!device_type)
- return false;
- else if (pa_streq(device_type, DEVICE_TYPE_SPEAKER))
- return true;
- else if (pa_streq(device_type, DEVICE_TYPE_RECEIVER))
- return true;
- else if (pa_streq(device_type, DEVICE_TYPE_MIC))
- return true;
- else
- return false;
-}
-
-static bool device_type_is_valid(const char *device_type) {
- if (!device_type)
- return false;
- else if (pa_streq(device_type, DEVICE_TYPE_SPEAKER))
- return true;
- else if (pa_streq(device_type, DEVICE_TYPE_RECEIVER))
- return true;
- else if (pa_streq(device_type, DEVICE_TYPE_MIC))
- return true;
- else if (pa_streq(device_type, DEVICE_TYPE_AUDIO_JACK))
- return true;
- else if (pa_streq(device_type, DEVICE_TYPE_BT))
- return true;
- else if (pa_streq(device_type, DEVICE_TYPE_HDMI))
- return true;
- else if (pa_streq(device_type, DEVICE_TYPE_FORWARDING))
- return true;
- else if (pa_streq(device_type, DEVICE_TYPE_USB_AUDIO))
- return true;
- else
- return false;
-}
-
-/* Check whether 'direction' is valid for 'device_type'
- * This is static device-type availability, not for runtime checking */
-static bool device_type_is_valid_direction(const char *device_type, const char *device_profile, dm_device_direction_t direction) {
- if (!device_type || direction == DM_DEVICE_DIRECTION_NONE)
- return false;
-
- if (pa_streq(device_type, DEVICE_TYPE_SPEAKER))
- return direction == DM_DEVICE_DIRECTION_OUT;
- else if (pa_streq(device_type, DEVICE_TYPE_RECEIVER))
- return direction == DM_DEVICE_DIRECTION_OUT;
- else if (pa_streq(device_type, DEVICE_TYPE_MIC))
- return direction == DM_DEVICE_DIRECTION_IN;
- else if (pa_streq(device_type, DEVICE_TYPE_AUDIO_JACK))
- return direction == DM_DEVICE_DIRECTION_OUT || direction == DM_DEVICE_DIRECTION_BOTH;
- else if (pa_streq(device_type, DEVICE_TYPE_BT) && pa_streq(device_profile, DEVICE_PROFILE_BT_SCO))
- return direction == DM_DEVICE_DIRECTION_BOTH;
- else if (pa_streq(device_type, DEVICE_TYPE_BT) && pa_streq(device_profile, DEVICE_PROFILE_BT_A2DP))
- return direction == DM_DEVICE_DIRECTION_OUT || direction == DM_DEVICE_DIRECTION_IN;
- else if (pa_streq(device_type, DEVICE_TYPE_HDMI))
- return direction == DM_DEVICE_DIRECTION_OUT;
- else if (pa_streq(device_type, DEVICE_TYPE_FORWARDING))
- return direction == DM_DEVICE_DIRECTION_BOTH;
- else if (pa_streq(device_type, DEVICE_TYPE_USB_AUDIO))
- return direction == DM_DEVICE_DIRECTION_BOTH || direction == DM_DEVICE_DIRECTION_OUT || direction == DM_DEVICE_DIRECTION_IN;
- else
- return false;
-}
-
-static const char* device_direction_to_string(dm_device_direction_t direction) {
- if (direction <= DM_DEVICE_DIRECTION_NONE || direction > DM_DEVICE_DIRECTION_BOTH) {
- return NULL;
- }
-
- if (direction == DM_DEVICE_DIRECTION_NONE)
- return DEVICE_DIRECTION_STR_NONE;
- else if (direction == DM_DEVICE_DIRECTION_OUT)
- return DEVICE_DIRECTION_STR_OUT;
- else if (direction == DM_DEVICE_DIRECTION_IN)
- return DEVICE_DIRECTION_STR_IN;
- else if (direction == DM_DEVICE_DIRECTION_BOTH)
- return DEVICE_DIRECTION_STR_BOTH;
- else
- return NULL;
-}
-
-static bool device_role_is_valid(const char *device_role) {
- if (!device_role)
- return false;
- else if (pa_streq(device_role, DEVICE_ROLE_NORMAL))
- return true;
- else if (pa_streq(device_role, DEVICE_ROLE_CALL_VOICE))
- return true;
- else if (pa_streq(device_role, DEVICE_ROLE_CALL_VIDEO))
- return true;
- else if (pa_streq(device_role, DEVICE_ROLE_VOIP))
- return true;
- else if (pa_streq(device_role, DEVICE_ROLE_LOW_LATENCY))
- return true;
- else if (pa_streq(device_role, DEVICE_ROLE_HIGH_LATENCY))
- return true;
- else if (pa_streq(device_role, DEVICE_ROLE_UHQA))
- return true;
- else
- return false;
-}
-
-static dm_device_direction_t device_direction_to_int(const char *device_direction) {
- if (!device_direction) {
- return -1;
- }
-
- if (pa_streq(device_direction, DEVICE_DIRECTION_STR_NONE)) {
- return DM_DEVICE_DIRECTION_NONE;
- } else if (pa_streq(device_direction, DEVICE_DIRECTION_STR_OUT)) {
- return DM_DEVICE_DIRECTION_OUT;
- } else if (pa_streq(device_direction, DEVICE_DIRECTION_STR_IN)) {
- return DM_DEVICE_DIRECTION_IN;
- } else if (pa_streq(device_direction, DEVICE_DIRECTION_STR_BOTH)) {
- return DM_DEVICE_DIRECTION_BOTH;
- } else {
- return -1;
- }
-}
-
static void type_info_free_func(struct device_type_info *type_info) {
if (!type_info)
return;
pa_hashmap_free(file_info->roles);
}
-static void profile_item_free_func(dm_device_profile *profile_item) {
- if (!profile_item)
- return;
-
- if (profile_item->profile) {
- pa_xfree(profile_item->profile);
+static dm_device_class_t device_string_get_class(const char *device_string) {
+ if (!device_string) {
+ return DM_DEVICE_CLASS_NONE;
}
- if (profile_item->playback_devices) {
- pa_hashmap_free(profile_item->playback_devices);
- }
- if (profile_item->capture_devices) {
- pa_hashmap_free(profile_item->capture_devices);
+ if (device_string == strstr(device_string, "alsa")) {
+ return DM_DEVICE_CLASS_ALSA;
+ } else if (device_string == strstr(device_string, "null")) {
+ return DM_DEVICE_CLASS_NULL;
+ } else if (device_string == strstr(device_string, "tizen")) {
+ return DM_DEVICE_CLASS_TIZEN;
+ } else {
+ return DM_DEVICE_CLASS_NONE;
}
-
- profile_item->device_item = NULL;
-
- pa_xfree(profile_item);
}
-static void device_item_free_func(dm_device *device_item) {
- if (!device_item)
- return;
-
- if (device_item->type)
- pa_xfree(device_item->type);
- if (device_item->name)
- pa_xfree(device_item->name);
- if (device_item->profiles)
- pa_idxset_free(device_item->profiles, (pa_free_cb_t)profile_item_free_func);
-
- pa_xfree(device_item);
-}
+static const char* device_string_get_value(const char *device_string) {
+ int len;
+ const char *end_p, *value_p;
-static pa_proplist* pulse_device_get_proplist(void *pulse_device, pa_device_type_t pdt) {
- if (pdt == PA_DEVICE_TYPE_SINK)
- return MAKE_SINK(pulse_device)->proplist;
- else
- return MAKE_SOURCE(pulse_device)->proplist;
-}
+ if (!device_string) {
+ return NULL;
+ }
-static pa_core* pulse_device_get_core(void *pulse_device, pa_device_type_t pdt) {
- if (pdt == PA_DEVICE_TYPE_SINK)
- return MAKE_SINK(pulse_device)->core;
- else
- return MAKE_SOURCE(pulse_device)->core;
-}
+ len = strlen(device_string);
+ end_p = device_string + len -1;
-static char* pulse_device_get_name(void *pulse_device, pa_device_type_t pdt) {
- if (pdt == PA_DEVICE_TYPE_SINK)
- return MAKE_SINK(pulse_device)->name;
- else
- return MAKE_SOURCE(pulse_device)->name;
+ if (!(value_p = strchr(device_string, ':'))) {
+ return NULL;
+ }
+ if (value_p < end_p) {
+ return value_p + 1;
+ } else {
+ return NULL;
+ }
}
-static pa_idxset* pulse_core_get_device_list(pa_core *core, pa_device_type_t pdt) {
- if (pdt == PA_DEVICE_TYPE_SINK)
- return core->sinks;
+static pa_proplist* pulse_device_get_proplist(pa_object *pdevice) {
+ if (pa_sink_isinstance(pdevice))
+ return PA_SINK(pdevice)->proplist;
else
- return core->sources;
+ return PA_SOURCE(pdevice)->proplist;
}
-static bool pulse_device_is_alsa(pa_proplist *prop) {
+static bool pulse_device_is_alsa(pa_object *pdevice) {
const char *api_name = NULL;
+ pa_proplist *prop;
- if (!prop) {
+ if ((prop = pulse_device_get_proplist(pdevice)) == NULL)
return false;
- }
if ((api_name = pa_proplist_gets(prop, PA_PROP_DEVICE_API))) {
if (pa_streq(api_name, DEVICE_API_ALSA)) {
}
-static bool pulse_device_is_bluez(pa_proplist *prop) {
+static bool pulse_device_is_bluez(pa_object *pdevice) {
const char *api_name = NULL;
+ pa_proplist *prop;
- if (!prop) {
+ if ((prop = pulse_device_get_proplist(pdevice)) == NULL)
return false;
- }
if ((api_name = pa_proplist_gets(prop, PA_PROP_DEVICE_API))) {
if (pa_streq(api_name, DEVICE_API_BLUEZ)) {
}
}
-static bool pulse_device_is_tizenaudio(void *pulse_device, pa_device_type_t pdt) {
- pa_sink *sink;
-
- if (!pulse_device) {
+static bool pulse_device_is_tizenaudio(pa_object *pdevice) {
+ if (!pdevice)
return false;
- }
- if (pdt == PA_DEVICE_TYPE_SOURCE) {
- return false;
+ if (pa_sink_isinstance(pdevice)) {
+ pa_sink *sink = PA_SINK(pdevice);
+ return pa_streq(sink->module->name, "module-tizenaudio-sink");
+ } else {
+ pa_source *source = PA_SOURCE(pdevice);
+ return pa_streq(source->module->name, "module-tizenaudio-source");
}
-
- sink = (pa_sink *) pulse_device;
- return pa_streq(sink->module->name, "module-tizenaudio-sink");
}
-static bool pulse_device_is_usb(pa_proplist *prop) {
+static bool pulse_device_is_usb(pa_object *pdevice) {
const char *bus_name = NULL;
+ pa_proplist *prop;
+
+ if ((prop = pulse_device_get_proplist(pdevice)) == NULL)
+ return false;
if ((bus_name = pa_proplist_gets(prop, PA_PROP_DEVICE_BUS))) {
if (pa_streq(bus_name, DEVICE_BUS_USB)) {
}
}
-static bool pulse_device_is_null(void *pulse_device, pa_device_type_t pdt) {
+static bool pulse_device_is_null(pa_object *pdevice) {
pa_sink *sink;
pa_source *source;
- if (!pulse_device)
+ if (!pdevice)
return false;
- if (pdt == PA_DEVICE_TYPE_SINK) {
- sink = (pa_sink *) pulse_device;
+ if (pa_sink_isinstance(pdevice)) {
+ sink = PA_SINK(pdevice);
return pa_streq(sink->module->name, "module-null-sink");
} else {
- source = (pa_source *) pulse_device;
-
+ source = PA_SOURCE(pdevice);
return pa_streq(source->module->name, "module-null-source");
}
}
-static const char* device_class_to_string(dm_device_class_t device_class) {
- if (device_class == DM_DEVICE_CLASS_ALSA) {
- return "alsa";
- } else if (device_class == DM_DEVICE_CLASS_TIZEN) {
- return "tizen";
- } else if (device_class == DM_DEVICE_CLASS_BT) {
- return "bt";
- } else if (device_class == DM_DEVICE_CLASS_NULL) {
- return "null";
- } else if (device_class == DM_DEVICE_CLASS_NONE) {
- return "none";
- } else {
- return NULL;
- }
-}
-
-static dm_device_class_t device_string_get_class(const char *device_string) {
- if (!device_string) {
- return DM_DEVICE_CLASS_NONE;
- }
+static const char* pulse_device_get_device_string_removed_argument(pa_object *pdevice) {
+ static char removed_param[DEVICE_PARAM_STRING_MAX] = {0,};
+ char *device_string_p = NULL;
+ char *next_p = NULL;
+ const char *params_p, *params;
+ char *end_p = NULL;
+ int len = 0, prev_len = 0;
+ pa_sink *sink;
+ pa_source *source;
- if (device_string == strstr(device_string, "alsa")) {
- return DM_DEVICE_CLASS_ALSA;
- } else if (device_string == strstr(device_string, "null")) {
- return DM_DEVICE_CLASS_NULL;
- } else if (device_string == strstr(device_string, "tizen")) {
- return DM_DEVICE_CLASS_TIZEN;
+ if (pa_sink_isinstance(pdevice)) {
+ sink = PA_SINK(pdevice);
+ params = sink->module->argument;
} else {
- return DM_DEVICE_CLASS_NONE;
+ source = PA_SOURCE(pdevice);
+ params = source->module->argument;
}
-}
-static const char* device_string_get_value(const char *device_string) {
- int len;
- const char *end_p, *value_p;
+ params_p = params;
- if (!device_string) {
+ if (!params) {
return NULL;
}
+ if (!(device_string_p = strstr(params, "device="))) {
+ return params;
+ }
- len = strlen(device_string);
- end_p = device_string + len -1;
-
- if (!(value_p = strchr(device_string, ':'))) {
- return NULL;
+ next_p = device_string_p;
+ while (!isblank(*next_p)) {
+ next_p++;
}
- if (value_p < end_p) {
- return value_p + 1;
- } else {
- return NULL;
+ while (isblank(*next_p)) {
+ next_p++;
+ }
+
+ strncpy(removed_param, next_p, DEVICE_PARAM_STRING_MAX);
+
+ if (device_string_p > params_p) {
+ prev_len = device_string_p - params_p;
+ len = strlen(removed_param);
+ end_p = removed_param + len;
+ *end_p = ' ';
+ end_p++;
+ strncpy(end_p, params_p, prev_len);
}
+
+ return removed_param;
}
-static dm_device_class_t pulse_device_get_class(void *pulse_device, pa_device_type_t pdt) {
- pa_sink *sink = NULL;
- pa_source *source = NULL;
+static dm_device_class_t pulse_device_get_class(pa_object *pdevice) {
- if (!pulse_device) {
- pa_log_error("pulse_device null");
+ if (!pdevice) {
+ pa_log_error("pdevice null");
return DM_DEVICE_CLASS_NONE;
}
- if (pdt == PA_DEVICE_TYPE_SINK)
- sink = (pa_sink *) pulse_device;
- else
- source = (pa_source *) pulse_device;
-
- if (pulse_device_is_null(pulse_device, pdt)) {
+ if (pulse_device_is_null(pdevice)) {
return DM_DEVICE_CLASS_NULL;
- } else if (pulse_device_is_alsa(pdt == PA_DEVICE_TYPE_SINK ? sink->proplist : source->proplist)) {
+ } else if (pulse_device_is_alsa(pdevice)) {
return DM_DEVICE_CLASS_ALSA;
- } else if (pulse_device_is_tizenaudio(pulse_device, pdt)) {
+ } else if (pulse_device_is_tizenaudio(pdevice)) {
return DM_DEVICE_CLASS_TIZEN;
- } else if (pulse_device_is_bluez(pdt == PA_DEVICE_TYPE_SINK ? sink->proplist : source->proplist)) {
+ } else if (pulse_device_is_bluez(pdevice)) {
return DM_DEVICE_CLASS_BT;
} else {
return DM_DEVICE_CLASS_NONE;
}
}
-static const char* device_class_get_module_name(dm_device_class_t device_class, pa_device_type_t pdt) {
- if (device_class == DM_DEVICE_CLASS_NONE) {
- return NULL;
- } else if (device_class == DM_DEVICE_CLASS_ALSA) {
- return pdt == PA_DEVICE_TYPE_SINK ? "module-alsa-sink" : "module-alsa-source";
- } else if (device_class == DM_DEVICE_CLASS_TIZEN) {
- return pdt == PA_DEVICE_TYPE_SINK ? "module-tizenaudio-sink" : NULL;
- } else if (device_class == DM_DEVICE_CLASS_BT) {
- return pdt == PA_DEVICE_TYPE_SINK ? "module-bluez5-device" : NULL;
- } else if (device_class == DM_DEVICE_CLASS_NULL) {
- return pdt == PA_DEVICE_TYPE_SINK ? "module-null-sink" : "module-null-source";
- } else {
- return NULL;
- }
+static dm_device_direction_t pulse_device_get_direction(pa_object *pdevice) {
+ if (pa_sink_isinstance(pdevice))
+ return DM_DEVICE_DIRECTION_OUT;
+ else
+ return DM_DEVICE_DIRECTION_IN;
}
-static int compare_device_profile(const char *device_profile1, const char *device_profile2) {
- if (!device_profile1 && !device_profile2) {
- return 0;
- } else if (!device_profile1 || !device_profile2) {
- return 1;
- } else if (pa_streq(device_profile1, device_profile2)) {
- return 0;
+static bool pulse_device_is_monitor(pa_object *pdevice) {
+ const char *device_class = NULL;
+ pa_proplist *prop;
+
+ prop = pulse_device_get_proplist(pdevice);
+
+ if ((device_class = pa_proplist_gets(prop, PA_PROP_DEVICE_CLASS))) {
+ if (device_class && pa_streq(device_class, DEVICE_CLASS_MONITOR)) {
+ return true;
+ } else {
+ return false;
+ }
} else {
- return 1;
+ return false;
}
}
-static int compare_device_type(const char *device_type1, const char *device_profile1, const char *device_type2, const char *device_profile2) {
- if (!device_type1 || !device_type2) {
+static int pulse_device_get_alsa_device_string(pa_proplist *prop, char **device_string) {
+ const char *device_string_prop = NULL;
+ char *device_string_tmp;
+
+ if (!prop || !device_string) {
+ pa_log_error("Invalid Parameter");
+ return -1;
+ }
+
+ if (!(device_string_prop = pa_proplist_gets(prop, "device.string"))) {
+ pa_log_error("failed to get property 'device.string'");
+ return -1;
+ }
+ if (!(device_string_tmp = strchr(device_string_prop, ':'))) {
+ pa_log_error("failed to parse device string");
+ return -1;
+ }
+
+ if (((device_string_tmp + 1) == '\0')) {
+ pa_log_error("no device string value");
return -1;
}
- if (pa_streq(device_type1, device_type2)) {
- return compare_device_profile(device_profile1, device_profile2);
+
+ *device_string = device_string_tmp + 1;
+
+ return 0;
+}
+
+static const char* device_class_get_module_name(dm_device_class_t device_class, bool is_sink) {
+ if (device_class == DM_DEVICE_CLASS_NONE) {
+ return NULL;
+ } else if (device_class == DM_DEVICE_CLASS_ALSA) {
+ return is_sink ? "module-alsa-sink" : "module-alsa-source";
+ } else if (device_class == DM_DEVICE_CLASS_TIZEN) {
+ return is_sink ? "module-tizenaudio-sink" : NULL;
+ } else if (device_class == DM_DEVICE_CLASS_BT) {
+ return is_sink ? "module-bluez5-device" : NULL;
+ } else if (device_class == DM_DEVICE_CLASS_NULL) {
+ return is_sink ? "module-null-sink" : "module-null-source";
+ } else {
+ return NULL;
}
- return 1;
}
-static struct device_type_info* _device_manager_get_type_info(pa_idxset *type_infos, const char *device_type, const char *device_profile) {
+static struct device_type_info* _device_manager_get_type_info(pa_idxset *type_infos, const char *type, const char *device_profile) {
struct device_type_info *type_info;
uint32_t type_idx;
PA_IDXSET_FOREACH(type_info, type_infos, type_idx) {
- if (!compare_device_type(type_info->type, type_info->profile, device_type, device_profile)) {
+ if (device_type_is_equal(type_info->type, type_info->profile, type, device_profile)) {
return type_info;
}
}
return NULL;
}
-static struct device_status_info* _device_manager_get_status_info(pa_idxset *status_infos, const char *device_type, const char *device_profile, const char *identifier) {
- struct device_status_info *status_info;
- uint32_t status_idx;
-
- PA_IDXSET_FOREACH(status_info, status_infos, status_idx) {
- if (!compare_device_type(status_info->type, status_info->profile, device_type, device_profile)) {
- if (!status_info->identifier && !identifier) {
- return status_info;
- } else if (!status_info->identifier || !identifier) {
- continue;
- } else if (pa_streq(status_info->identifier, identifier)) {
- return status_info;
- } else {
- continue;
- }
- }
- }
-
- return NULL;
-}
-
static struct device_file_info* _device_manager_get_file_info(pa_idxset *file_infos, const char *device_string) {
struct device_file_info *file_info;
uint32_t file_idx;
- if (!file_infos)
- return NULL;
+
+ pa_assert(file_infos);
PA_IDXSET_FOREACH(file_info, file_infos, file_idx) {
if (file_info->device_string) {
return NULL;
}
-static dm_device* _device_manager_get_device(pa_idxset *device_list, const char *device_type) {
- dm_device *device_item;
- uint32_t device_idx;
-
- if (!device_list || !device_type)
- return NULL;
+static struct device_status_info* _device_status_new(const char *type, const char *profile,
+ const char *name, const char *system_id) {
+ struct device_status_info *status_info;
- PA_IDXSET_FOREACH(device_item, device_list, device_idx) {
- if (pa_streq(device_item->type, device_type)) {
- return device_item;
- }
- }
+ status_info = (struct device_status_info *) pa_xmalloc0(sizeof(struct device_status_info));
+ status_info->type = pa_xstrdup(type);
+ status_info->profile = pa_xstrdup(profile);
+ status_info->name = pa_xstrdup(name);
+ status_info->system_id = pa_xstrdup(system_id);
+ status_info->detected = DEVICE_DISCONNECTED;
- return NULL;
+ return status_info;
}
-static dm_device* _device_manager_get_device_with_id(pa_idxset *device_list, uint32_t id) {
- dm_device *device_item;
- uint32_t idx;
-
- pa_assert(device_list);
+static void _device_status_free(struct device_status_info *status_info) {
+ if (!status_info)
+ return ;
- PA_IDXSET_FOREACH(device_item, device_list, idx) {
- if (device_item->id == id) {
- return device_item;
- }
- }
- return NULL;
+ pa_xfree(status_info->type);
+ pa_xfree(status_info->profile);
+ pa_xfree(status_info->name);
+ pa_xfree(status_info->system_id);
+ pa_xfree(status_info);
}
-static char* get_playback_list_str(pa_hashmap *playback_devices) {
- pa_sink *sink = NULL;
- void *state = NULL;
- const char *role;
- pa_strbuf *buf;
+static struct device_status_info* _get_device_status(pa_device_manager *manager, const char *type,
+ const char *device_profile, const char *system_id) {
+ struct device_status_info *status_info = NULL;
+ uint32_t status_idx;
- if (!playback_devices || !pa_hashmap_size(playback_devices))
- return NULL;
+ pa_assert(manager);
+ pa_assert(manager->device_status);
- buf = pa_strbuf_new();
- pa_strbuf_printf(buf, " Playback device list\n");
- PA_HASHMAP_FOREACH_KEY(sink, playback_devices, state, role)
- pa_strbuf_printf(buf, " %-13s -> %s\n", role, sink->name);
+ PA_IDXSET_FOREACH(status_info, manager->device_status, status_idx) {
+ if (device_type_is_equal(status_info->type, status_info->profile, type, device_profile)) {
+ if (device_type_is_avail_multi_device(type)) {
+ /* if system_id is null, just compare type */
+ if (system_id == NULL)
+ return status_info;
+ else if (status_info->system_id == NULL)
+ continue;
+ else if (pa_streq(status_info->system_id, system_id))
+ return status_info;
+ else
+ continue;
+ } else {
+ return status_info;
+ }
+ }
+ }
- return pa_strbuf_tostring_free(buf);
+ return NULL;
}
-static char* get_capture_list_str(pa_hashmap *capture_devices) {
- pa_source *source = NULL;
- void *state = NULL;
- const char *role;
- pa_strbuf *buf;
-
- if (!capture_devices || !pa_hashmap_size(capture_devices))
- return NULL;
-
- buf = pa_strbuf_new();
- pa_strbuf_printf(buf, " Capture device list\n");
- PA_HASHMAP_FOREACH_KEY(source, capture_devices, state, role)
- pa_strbuf_printf(buf, " %-13s -> %s\n", role, source->name);
-
- return pa_strbuf_tostring_free(buf);
-}
+static const char* _file_infos_get_param(pa_idxset *file_infos, const char *device_string, const char *role) {
+ struct device_file_info *file_info;
+ const char *params;
-/* Returned string must be freed */
-static char* get_device_profile_info_str(dm_device_profile *profile_item) {
- pa_strbuf *buf;
- char *playback_str, *capture_str;
- if (!profile_item)
+ if (!(file_info = _device_manager_get_file_info(file_infos, device_string))) {
+ pa_log_error("No file map for '%s'", device_string);
return NULL;
+ }
- buf = pa_strbuf_new();
- pa_strbuf_printf(buf, " Profile : %s\n", pa_strna(profile_item->profile));
- pa_strbuf_printf(buf, " Direction : %s\n", device_direction_to_string(profile_item->direction));
- pa_strbuf_printf(buf, " Is activated : %s\n", pa_yes_no(COMPOUND_STATE(profile_item) == DM_DEVICE_STATE_ACTIVATED));
- playback_str = get_playback_list_str(profile_item->playback_devices);
- capture_str = get_capture_list_str(profile_item->capture_devices);
-
- if (playback_str)
- pa_strbuf_puts(buf, playback_str);
- if (capture_str)
- pa_strbuf_puts(buf, capture_str);
-
- pa_xfree(playback_str);
- pa_xfree(capture_str);
+ if (!(params = pa_hashmap_get(file_info->roles, role)))
+ pa_log_error("No params for '%s:%s'", device_string, role);
- return pa_strbuf_tostring_free(buf);
+ return params;
}
-static char* get_device_info_str(dm_device *device_item) {
- pa_strbuf *buf;
- dm_device_profile *profile_item = NULL;
- uint32_t device_idx = 0;
- char *profile_info;
-
- if (!device_item || !device_item->profiles)
- return NULL;
-
- buf = pa_strbuf_new();
- pa_strbuf_printf(buf, "[Device #%u]\n", device_item->id);
- pa_strbuf_printf(buf, " ID : %u\n", device_item->id);
- pa_strbuf_printf(buf, " Type : %s\n", device_item->type);
- pa_strbuf_printf(buf, " Name : %s\n", device_item->name);
- pa_strbuf_printf(buf, " Active Profile : %u\n", device_item->active_profile);
- PA_IDXSET_FOREACH(profile_item, device_item->profiles, device_idx) {
- pa_strbuf_printf(buf, " (Profile #%u)\n", device_idx);
- profile_info = get_device_profile_info_str(profile_item);
- if (profile_info)
- pa_strbuf_puts(buf, profile_info);
- pa_xfree(profile_info);
- }
-
- return pa_strbuf_tostring_free(buf);
-}
+static device_detected_type_t _device_get_detected(pa_device_manager *manager, const char *type, const char *device_profile,
+ const char *system_id) {
+ struct device_status_info *status_info;
-static char* get_device_list_str(pa_device_manager *dm) {
- dm_device *device_item = NULL;
- uint32_t device_idx = 0;
- pa_strbuf *buf;
- char *device_info;
+ pa_assert(manager);
+ pa_assert(manager->device_status);
+ pa_assert(type);
- if (!dm || !dm->device_list)
- return NULL;
+ if (!device_type_is_need_detect(type, device_profile))
+ return DEVICE_CONNECTED;
- buf = pa_strbuf_new();
- pa_strbuf_printf(buf, "=========== Device List ================\n");
- PA_IDXSET_FOREACH(device_item, dm->device_list, device_idx) {
- device_info = get_device_info_str(device_item);
- if (device_info)
- pa_strbuf_puts(buf, device_info);
- pa_xfree(device_info);
+ status_info = _get_device_status(manager, type, device_profile, system_id);
+ if (!status_info) {
+ pa_log_info("No status info for type(%s) profile(%s) system_id(%s)",
+ type, pa_strempty(device_profile), pa_strempty(system_id));
+ return DEVICE_DISCONNECTED;
}
- pa_strbuf_printf(buf, "========================================\n");
-
- return pa_strbuf_tostring_free(buf);
-}
-
-static void dump_device_info(dm_device *device_item, pa_log_level_t log_level) {
- char *info;
- if (!device_item)
- return;
+ pa_log_debug("Get device detected, type(%s) profile(%s) system_id(%s) : %s(%d)",
+ type, pa_strempty(device_profile), pa_strempty(system_id),
+ (status_info->detected & DEVICE_CONNECTED) ? "Connected" : "Disconnected", status_info->detected);
- if ((info = get_device_info_str(device_item))) {
- pa_logl(log_level, "%s", info);
- pa_xfree(info);
- }
+ return status_info->detected;
}
-static void dump_device_list_info(pa_device_manager *dm, pa_log_level_t log_level) {
- char *info;
+static void _device_set_detected(pa_device_manager *manager, const char *type, const char *device_profile,
+ const char *name, const char *system_id, device_detected_type_t detected_type) {
+ struct device_status_info *status_info;
- if (!dm || !dm->device_list)
- return;
+ pa_assert(manager);
+ pa_assert(manager->device_status);
+ pa_assert(type);
- if ((info = get_device_list_str(dm))) {
- pa_logl(log_level, "%s", info);
- pa_xfree(info);
- }
-}
+ if (!device_type_is_need_detect(type, device_profile))
+ return ;
-static bool pulse_device_class_is_sound(pa_proplist *prop) {
- const char *device_class = NULL;
+ pa_log_info("Set device detected, type(%s) profile(%s) system_id(%s) -> %s(%d)",
+ type, pa_strempty(device_profile), pa_strempty(system_id),
+ (detected_type & DEVICE_CONNECTED) ? "Connected" : "Disconnected", detected_type);
- if ((device_class = pa_proplist_gets(prop, PA_PROP_DEVICE_CLASS))) {
- if (device_class && pa_streq(device_class, DEVICE_CLASS_SOUND)) {
- return true;
- } else {
- return false;
+ if (detected_type & DEVICE_CONNECTED) {
+ status_info = _get_device_status(manager, type, device_profile, system_id);
+ if (!status_info) {
+ status_info = _device_status_new(type, device_profile, name, system_id);
+ pa_idxset_put(manager->device_status, status_info, NULL);
}
+ status_info->detected = detected_type;
} else {
- return false;
+ status_info = _get_device_status(manager, type, device_profile, system_id);
+ if (status_info) {
+ pa_idxset_remove_by_data(manager->device_status, status_info, NULL);
+ _device_status_free(status_info);
+ }
}
}
-static bool pulse_device_class_is_monitor(pa_proplist *prop) {
- const char *device_class = NULL;
+/* return system_id of sco connected/opened bt device */
+static int _device_get_detected_sco(pa_device_manager *manager, device_detected_type_t detected,
+ char **system_id, char **name) {
+ struct device_status_info *status_info;
+ uint32_t status_idx;
- if (!prop) {
- return false;
- }
+ pa_assert(manager);
+ pa_assert(manager->device_status);
- if ((device_class = pa_proplist_gets(prop, PA_PROP_DEVICE_CLASS))) {
- if (device_class && pa_streq(device_class, DEVICE_CLASS_MONITOR)) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
+ if (detected != DEVICE_CONNECTED_SCO && detected != DEVICE_OPENED_SCO) {
+ pa_log_warn("Invalid detected type for sco");
+ return -1;
}
-}
-static void* pulse_device_get_opposite_sibling_device(void *pulse_device, pa_device_type_t pdt) {
- const char *sysfs_path, *sysfs_path_tmp;
- uint32_t device_idx;
- void *pulse_device_tmp;
- pa_core *core;
- pa_assert(pulse_device);
-
- if (!(sysfs_path = pa_proplist_gets(pulse_device_get_proplist(pulse_device, pdt), "sysfs.path"))) {
- pa_log_warn("No sysfs.path for '%s'", pulse_device_get_name(pulse_device, pdt));
- return NULL;
+ PA_IDXSET_FOREACH(status_info, manager->device_status, status_idx) {
+ if (device_type_is_equal(status_info->type, status_info->profile, DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO)) {
+ if (status_info->detected == detected) {
+ if (system_id)
+ *system_id = status_info->system_id;
+ if (name)
+ *name = status_info->name;
+ return 0;
+ }
+ }
}
- core = pulse_device_get_core(pulse_device, pdt);
+ return -1;
+}
- PA_IDXSET_FOREACH(pulse_device_tmp, pulse_core_get_device_list(core, !pdt), device_idx) {
- if (!pulse_device_class_is_sound(pulse_device_get_proplist(pulse_device_tmp, !pdt)))
- continue;
- sysfs_path_tmp = pa_proplist_gets(pulse_device_get_proplist(pulse_device_tmp, !pdt), "sysfs.path");
- if (sysfs_path_tmp && pa_streq(sysfs_path_tmp, sysfs_path)) {
- return pulse_device_tmp;
+static pa_tz_device* _device_list_get_device(pa_device_manager *manager, const char *type, const char *system_id) {
+ pa_tz_device *device;
+ uint32_t idx;
+ char *_type, *_system_id;
+
+ pa_assert(manager);
+ pa_assert(manager->device_list);
+ pa_assert(type);
+
+ PA_IDXSET_FOREACH(device, manager->device_list, idx) {
+ _type = pa_tz_device_get_type(device);
+ _system_id = pa_tz_device_get_system_id(device);
+ if (pa_streq(_type, type)) {
+ if (device_type_is_avail_multi_device(type)) {
+ if (system_id == NULL)
+ return device;
+ else if (_system_id == NULL)
+ continue;
+ else if (pa_streq(_system_id, system_id))
+ return device;
+ else
+ continue;
+ } else {
+ return device;
+ }
}
}
return NULL;
}
-static int pulse_device_get_alsa_device_string(pa_proplist *prop, char **device_string) {
- const char *device_string_prop = NULL;
- char *device_string_tmp;
- if (!prop || !device_string) {
- pa_log_error("Invalid Parameter");
- return -1;
- }
+static pa_tz_device* _device_list_get_device_with_id(pa_device_manager *manager, uint32_t id) {
+ pa_tz_device *device;
+ uint32_t idx;
- if (!(device_string_prop = pa_proplist_gets(prop, "device.string"))) {
- pa_log_error("failed to get property 'device.string'");
- return -1;
- }
- if (!(device_string_tmp = strchr(device_string_prop, ':'))) {
- pa_log_error("failed to parse device string");
- return -1;
- }
+ pa_assert(manager);
+ pa_assert(manager->device_list);
- if (((device_string_tmp + 1) == '\0')) {
- pa_log_error("no device string value");
- return -1;
+ PA_IDXSET_FOREACH(device, manager->device_list, idx) {
+ if (pa_tz_device_get_id(device) == id) {
+ return device;
+ }
}
+ return NULL;
+}
- *device_string = device_string_tmp + 1;
+static void dump_device_list_info(pa_device_manager *dm, pa_log_level_t log_level) {
+ pa_tz_device *device;
+ uint32_t device_idx;
- return 0;
+ if (!dm || !dm->device_list)
+ return;
+
+ pa_logl(log_level, "=========== Device List ================\n");
+ PA_IDXSET_FOREACH(device, dm->device_list, device_idx)
+ pa_tz_device_dump_info(device, log_level);
+ pa_logl(log_level, "========================================\n");
}
static const char* build_params_to_load_device(const char *device_string, const char *params, dm_device_class_t device_class) {
return (const char*) args;
}
-static const char* pulse_device_get_device_string_removed_argument(void *pulse_device, pa_device_type_t pdt) {
- static char removed_param[DEVICE_PARAM_STRING_MAX] = {0,};
- char *device_string_p = NULL;
- char *next_p = NULL;
- const char *params_p, *params;
- char *end_p = NULL;
- int len = 0, prev_len = 0;
- pa_sink *sink;
- pa_source *source;
+static bool device_params_is_equal(const char *params1, const char *params2) {
+ const char *key = NULL;
+ const char *value1, *value2;
+ pa_modargs *modargs1, *modargs2;
+ void *state = NULL;
+ bool equal = true;
- if (pdt == PA_DEVICE_TYPE_SINK)
- sink = (pa_sink *) pulse_device;
- else
- source = (pa_source *) pulse_device;
+ if (!params1 && !params2)
+ return true;
+ if (!params1 || !params2)
+ return false;
- params = pdt == PA_DEVICE_TYPE_SINK ? sink->module->argument : source->module->argument;
- params_p = params;
+ modargs1 = pa_modargs_new(params1, valid_alsa_device_modargs);
+ modargs2 = pa_modargs_new(params2, valid_alsa_device_modargs);
- if (!params) {
- return NULL;
- }
- if (!(device_string_p = strstr(params, "device="))) {
- return params;
+ if (!modargs1 || !modargs2) {
+ equal = false;
+ goto finish;
}
- next_p = device_string_p;
- while (!isblank(*next_p)) {
- next_p++;
- }
- while (isblank(*next_p)) {
- next_p++;
- }
-
- strncpy(removed_param, next_p, DEVICE_PARAM_STRING_MAX);
-
- if (device_string_p > params_p) {
- prev_len = device_string_p - params_p;
- len = strlen(removed_param);
- end_p = removed_param + len;
- *end_p = ' ';
- end_p++;
- strncpy(end_p, params_p, prev_len);
- }
-
- return removed_param;
-}
-
-
-static int compare_device_params(const char *params1, const char *params2) {
- const char *key = NULL;
- const char *value1, *value2;
- pa_modargs *modargs1, *modargs2;
- void *state = NULL;
- int ret = 0;
-
- if (!params1 && !params2)
- return 0;
- if (!params1 || !params2)
- return -1;
-
- modargs1 = pa_modargs_new(params1, valid_alsa_device_modargs);
- modargs2 = pa_modargs_new(params2, valid_alsa_device_modargs);
-
- if (!modargs1 || !modargs2) {
- ret = 1;
- goto end;
- }
-
- for (state = NULL, key = pa_modargs_iterate(modargs1, &state); key; key = pa_modargs_iterate(modargs1, &state)) {
- value1 = pa_modargs_get_value(modargs1, key, NULL);
- value2 = pa_modargs_get_value(modargs2, key, NULL);
- if (!value1 || !value2 || !pa_streq(value1, value2)) {
- ret = 1;
- goto end;
- }
+ for (state = NULL, key = pa_modargs_iterate(modargs1, &state); key; key = pa_modargs_iterate(modargs1, &state)) {
+ value1 = pa_modargs_get_value(modargs1, key, NULL);
+ value2 = pa_modargs_get_value(modargs2, key, NULL);
+ if (!value1 || !value2 || !pa_streq(value1, value2)) {
+ equal = false;
+ goto finish;
+ }
}
for (state = NULL, key = pa_modargs_iterate(modargs2, &state); key; key = pa_modargs_iterate(modargs2, &state)) {
value1 = pa_modargs_get_value(modargs1, key, NULL);
value2 = pa_modargs_get_value(modargs2, key, NULL);
if (!value1 || !value2 || !pa_streq(value1, value2)) {
- ret = 1;
- goto end;
+ equal = false;
+ goto finish;
}
}
-end:
+finish:
if (modargs1)
pa_modargs_free(modargs1);
pa_modargs_free(modargs2);
- return ret;
+ return equal;
}
-static int compare_device_params_with_module_args(void *pulse_device, pa_device_type_t pdt, const char *params) {
+static bool pulse_device_params_is_equal(pa_object *pdevice, const char *params) {
const char *removed_module_args;
const char *module_args;
pa_sink *sink;
pa_source *source;
- if (pdt == PA_DEVICE_TYPE_SINK) {
- sink = (pa_sink *) pulse_device;
+ pa_assert(pdevice);
+
+ if (pa_sink_isinstance(pdevice)) {
+ sink = PA_SINK(pdevice);
module_args = sink->module->argument;
} else {
- source = (pa_source *) pulse_device;
+ source = PA_SOURCE(pdevice);
module_args = source->module->argument;
}
if (!params || !module_args)
return -1;
- removed_module_args = pulse_device_get_device_string_removed_argument(pulse_device, pdt);
- return compare_device_params(params, removed_module_args);
+ removed_module_args = pulse_device_get_device_string_removed_argument(pdevice);
+ return device_params_is_equal(params, removed_module_args);
}
-static const char* pulse_device_get_device_string(void *pulse_device, pa_device_type_t pdt) {
+static const char* pulse_device_get_device_string(pa_object *pdevice) {
dm_device_class_t device_class;
static char device_string[DEVICE_STR_MAX] = {0,};
char *device_string_val = NULL;
- pa_sink *sink;
- pa_source *source;
-
- if (!pulse_device) {
- pa_log_error("pulse_device null");
- return NULL;
- }
+ pa_proplist *prop;
- device_class = pulse_device_get_class(pulse_device, pdt);
+ pa_assert(pdevice);
- if (pdt == PA_DEVICE_TYPE_SINK)
- sink = (pa_sink *) pulse_device;
- else
- source = (pa_source *) pulse_device;
+ device_class = pulse_device_get_class(pdevice);
+ prop = pulse_device_get_proplist(pdevice);
if (device_class == DM_DEVICE_CLASS_ALSA) {
- if (pulse_device_get_alsa_device_string(pdt == PA_DEVICE_TYPE_SINK ? sink->proplist : source->proplist, &device_string_val) < 0)
+ if (pulse_device_get_alsa_device_string(prop, &device_string_val) < 0)
return NULL;
snprintf(device_string, DEVICE_STR_MAX, "alsa:%s", device_string_val);
return device_string;
}
}
-/* pulse_device is sink or source */
-static bool pulse_device_same_device_string(void *pulse_device, pa_device_type_t pdt, const char *device_string) {
- const char *pulse_device_string;
+/* pdevice is sink or source */
+static bool pulse_device_same_device_string(pa_object *pdevice, const char *device_string) {
+ const char *_device_string;
- if (!pulse_device || !device_string) {
- return false;
- }
+ pa_assert(pdevice);
+ pa_assert(device_string);
- if (!(pulse_device_string = pulse_device_get_device_string(pulse_device, pdt))) {
+ if (!(_device_string = pulse_device_get_device_string(pdevice)))
return false;
- }
- return pa_streq(pulse_device_string, device_string);
+ return pa_streq(_device_string, device_string);
}
-static int get_profile_priority(const char *device_profile) {
- if (!device_profile) {
- return 0;
- } else if (pa_streq(device_profile, DEVICE_PROFILE_BT_A2DP)) {
- return 1;
- } else if (pa_streq(device_profile, DEVICE_PROFILE_BT_SCO)) {
- return 2;
- } else {
- return -1;
- }
-}
+static const char* device_type_info_get_role(struct device_type_info *type_info, bool is_playback, const char *device_string) {
+ pa_hashmap *pcm_devices;
+ void *state;
+ const char *role, *_device_string;
+ dm_device_direction_t direction;
-static int compare_profile_priority(const char *device_profile1, const char *device_profile2) {
- int priority1, priority2;
+ pa_assert(type_info);
+ pa_assert(device_string);
- priority1 = get_profile_priority(device_profile1);
- priority2 = get_profile_priority(device_profile2);
+ direction = device_type_get_static_direction(type_info->type, type_info->profile);
+ if (direction == DM_DEVICE_DIRECTION_NONE) {
+ pa_log_debug("Not static direction");
+ return NULL;
+ }
- if (priority1 > priority2) {
- return 1;
- } else if (priority1 == priority2) {
- return 0;
+ if (is_playback) {
+ if (direction == DM_DEVICE_DIRECTION_IN) {
+ pa_log_debug("Invalid direction");
+ return NULL;
+ }
+ pcm_devices = type_info->playback_devices;
} else {
- return -1;
+ if (direction == DM_DEVICE_DIRECTION_OUT) {
+ pa_log_debug("Invalid direction");
+ return NULL;
+ }
+ pcm_devices = type_info->capture_devices;
}
-}
-static dm_device* _device_item_set_active_profile_auto(dm_device *device_item) {
- dm_device_profile *profile_item = NULL, *prev_profile_item = NULL;
- uint32_t idx, prev_active_profile;
- unsigned int device_size;
-
- if (!device_item || !device_item->profiles) {
- pa_log_error("Invalid Parameter");
+ if (!pcm_devices) {
+ pa_log_warn("No %s pcm devices for %s %s", is_playback ? "playback" : "capture",
+ type_info->type, pa_strempty(type_info->profile));
return NULL;
}
- prev_active_profile = device_item->active_profile;
-
- device_size = pa_idxset_size(device_item->profiles);
- if (device_size == 1) {
- pa_idxset_first(device_item->profiles, &idx);
- device_item->active_profile = idx;
- } else if (device_size == 0) {
- device_item->active_profile = PA_INVALID_INDEX;
- return device_item;
- } else {
- PA_IDXSET_FOREACH(profile_item, device_item->profiles, idx) {
- if (prev_profile_item) {
- if (compare_profile_priority(profile_item->profile, prev_profile_item->profile) > 0) {
- device_item->active_profile = idx;
- }
- }
- prev_profile_item = profile_item;
+ PA_HASHMAP_FOREACH_KEY(_device_string, pcm_devices, state, role) {
+ if (pa_streq(_device_string, device_string)) {
+ return role;
}
}
- /* notify direction changed, if only new added profile is active */
- if ((prev_active_profile != PA_INVALID_INDEX) && (prev_active_profile != device_item->active_profile)) {
- pa_log_debug("%s's active profile : %u", device_item->name, device_item->active_profile);
- notify_device_info_changed(device_item, DM_DEVICE_CHANGED_INFO_IO_DIRECTION, device_item->dm);
- }
-
- return device_item;
+ return NULL;
}
-static dm_device* _device_item_add_profile(dm_device *device_item, dm_device_profile *profile_item, uint32_t *idx, pa_device_manager *dm) {
- uint32_t profile_idx;
+pa_dynarray* pulse_device_get_belongs_type(pa_object *pdevice, pa_device_manager *dm) {
+ pa_dynarray *ctypes;
+ struct composite_type *ctype;
+ struct device_type_info *type_info;
+ const char *device_string, *role;
+ uint32_t type_idx;
+ pa_device_type_t pdt;
- pa_assert(device_item);
- pa_assert(device_item->profiles);
- pa_assert(profile_item);
- pa_assert(dm);
+ pa_assert(pdevice);
+
+ if (pulse_device_is_monitor(pdevice))
+ return NULL;
+ if (pulse_device_is_usb(pdevice))
+ return NULL;
+ if (pulse_device_is_bluez(pdevice))
+ return NULL;
- pa_idxset_put(device_item->profiles, profile_item, &profile_idx);
- _device_item_set_active_profile_auto(device_item);
- profile_item->device_item = device_item;
+ ctypes = pa_dynarray_new(pa_xfree);
- return device_item;
-}
+ if (pa_sink_isinstance(pdevice))
+ pdt = PA_DEVICE_TYPE_SINK;
+ else
+ pdt = PA_DEVICE_TYPE_SOURCE;
+
+ PA_IDXSET_FOREACH(type_info, dm->type_infos, type_idx) {
+ device_string = pulse_device_get_device_string(pdevice);
+ role = device_type_info_get_role(type_info, pdt, device_string);
+ /* Found type_info which is matching with pulse_device */
+ if (role) {
+ ctype = pa_xmalloc0(sizeof(struct composite_type));
+ ctype->type = type_info->type;
+ ctype->profile = type_info->profile;
+ ctype->role = role;
+ pa_dynarray_append(ctypes, ctype);
+ }
+ }
+ if (pa_dynarray_size(ctypes) == 0) {
+ pa_dynarray_free(ctypes);
+ ctypes = NULL;
+ }
-static int _device_list_add_device(pa_idxset *device_list, dm_device *device_item, pa_device_manager *dm) {
- pa_assert(device_list);
- pa_assert(device_item);
+ return ctypes;
+}
- if (pa_idxset_put(device_list, device_item, NULL) < 0)
- return -1;
+static const char* pulse_device_get_device_name(pa_object *pdevice, const char *type) {
+ pa_proplist *prop;
- pa_log_debug("Notify Device connected");
+ pa_assert(pdevice);
+ pa_assert(device_type_is_valid(type));
- return 0;
+ prop = pulse_device_get_proplist(pdevice);
+
+ if (pa_streq(type, DEVICE_TYPE_USB_AUDIO))
+ return pa_proplist_gets(prop, "udev.id");
+ else if (pa_streq(type, DEVICE_TYPE_BT))
+ return pa_proplist_gets(prop, "bluez.alias");
+ else
+ return NULL;
}
+static void pulse_device_set_use_internal_codec(pa_object *pdevice, bool use_internal_codec) {
+ pa_assert(pdevice);
-static int _device_list_remove_device(pa_idxset *device_list, dm_device *device_item, pa_device_manager *dm) {
- pa_assert(device_list);
- pa_assert(device_item);
+ if (pa_sink_isinstance(pdevice)) {
+ pa_sink *sink = PA_SINK(pdevice);
+ sink->use_internal_codec = use_internal_codec;
+ } else {
+ pa_source *source = PA_SOURCE(pdevice);
+ source->use_internal_codec = use_internal_codec;
+ }
+}
- if (!pa_idxset_remove_by_data(device_list, device_item, NULL))
- return -1;
+/* Get system_id of physical device, if external device */
+static const char* pulse_device_get_system_id(pa_object *pdevice) {
+ pa_proplist *prop;
- return 0;
+ prop = pulse_device_get_proplist(pdevice);
+ if (pulse_device_is_usb(pdevice))
+ return pa_proplist_gets(prop, "sysfs.path");
+ else if (pulse_device_is_bluez(pdevice))
+ return pa_proplist_gets(prop, "bluez.path");
+ else
+ return NULL;
}
-static pa_sink* _device_profile_get_sink(dm_device_profile *profile_item, const char *role) {
+static pa_sink* _device_manager_set_default_sink(pa_device_manager *dm, const char *type, const char *device_profile, const char *role) {
+ pa_tz_device *device;
pa_sink *sink;
- if (!profile_item || !role || !device_role_is_valid(role)) {
- pa_log_error("Invalid Parameter");
+ if (!type || !role) {
+ pa_log_warn("Argument for set_default_sink invalid");
+ return NULL;
+ }
+
+ if (!(device = _device_list_get_device(dm, type, NULL))) {
+ pa_log_warn("cannot get device item for %s", type);
return NULL;
}
- if (!profile_item->playback_devices) {
- pa_log_error("No playback devices");
+ if (!(sink = pa_tz_device_get_sink(device, role))) {
+ pa_log_warn("cannot get sink for %s", role);
return NULL;
}
- sink = pa_hashmap_get(profile_item->playback_devices, role);
+ sink = pa_namereg_set_default_sink(dm->core, sink);
return sink;
}
-static pa_source* _device_profile_get_source(dm_device_profile *profile_item, const char *role) {
+static pa_source* _device_manager_set_default_source(pa_device_manager *dm, const char *type, const char *device_profile, const char *role) {
+ pa_tz_device *device;
pa_source *source;
- if (!profile_item || !role || !device_role_is_valid(role)) {
- pa_log_error("Invalid Parameter");
+ if (!type || !role) {
+ pa_log_warn("Argument for set_default_source invalid");
+ return NULL;
+ }
+
+ if (!(device = _device_list_get_device(dm, type, NULL))) {
+ pa_log_warn("cannot get device item for %s", type);
return NULL;
}
- if (!profile_item->capture_devices) {
- pa_log_error("No capture devices");
+ if (!(source = pa_tz_device_get_source(device, role))) {
+ pa_log_warn("cannot get source for %s", role);
return NULL;
}
- source = pa_hashmap_get(profile_item->capture_devices, role);
+ source = pa_namereg_set_default_source(dm->core, source);
return source;
}
-static dm_device* create_device_item(const char *device_type, const char *name, dm_device_profile *profile_item, pa_device_manager *dm) {
- dm_device *device_item = NULL;
- pa_sink *sink = NULL;
- pa_source *source = NULL;
-
- pa_assert(device_type);
- pa_assert(profile_item);
+static void handle_usb_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *manager) {
+ const char *name, *system_id;
+ dm_device_direction_t direction;
+ pa_tz_device *device;
- pa_log_info("Create device item for %s", device_type);
+ pa_assert(pdevice);
+ pa_assert(manager);
- device_item = (dm_device *)pa_xmalloc(sizeof(dm_device));
- device_item->id = device_id_max_g++;
- device_item->type = strdup(device_type);
- device_item->active_profile = PA_INVALID_INDEX;
- device_item->profiles = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
- device_item->dm = dm;
+ pa_log_info("Handle usb pulse device");
- if (name) {
- device_item->name = strdup(name);
- } else {
- device_item->name = strdup(device_type);
- }
+ system_id = pulse_device_get_system_id(pdevice);
+ direction = pulse_device_get_direction(pdevice);
- _device_item_add_profile(device_item, profile_item, NULL, dm);
- _device_list_add_device(dm->device_list, device_item, dm);
+ if (is_loaded) {
+ pa_tz_device_new_data data;
- // just for external device
- if ((sink = _device_profile_get_sink(profile_item, DEVICE_ROLE_NORMAL)))
- sink->device_item = device_item;
- if ((source = _device_profile_get_source(profile_item, DEVICE_ROLE_NORMAL)))
- source->device_item = device_item;
+ name = pulse_device_get_device_name(pdevice, DEVICE_TYPE_USB_AUDIO);
- notify_device_connection_changed(device_item, true, dm);
+ pa_tz_device_new_data_init(&data, manager->device_list, manager->comm, NULL);
+ pa_tz_device_new_data_set_type(&data, DEVICE_TYPE_USB_AUDIO);
+ pa_tz_device_new_data_set_name(&data, name);
+ pa_tz_device_new_data_set_direction(&data, direction);
+ pa_tz_device_new_data_set_system_id(&data, system_id);
+ pa_tz_device_new_data_set_use_internal_codec(&data, false);
+ if (direction == DM_DEVICE_DIRECTION_OUT)
+ pa_tz_device_new_data_add_sink(&data, DEVICE_ROLE_NORMAL, PA_SINK(pdevice));
+ else
+ pa_tz_device_new_data_add_source(&data, DEVICE_ROLE_NORMAL, PA_SOURCE(pdevice));
- return device_item;
+ pa_tz_device_new(&data);
+ pa_tz_device_new_data_done(&data);
+ } else {
+ if (!(device = _device_list_get_device(manager, DEVICE_TYPE_USB_AUDIO, system_id)))
+ pa_log_warn("Can't get usb device for %s", system_id);
+ else
+ pa_tz_device_free(device);
+ }
}
-static void destroy_device_item(dm_device *device_item, pa_device_manager *dm) {
- if (!device_item) {
- return;
- }
+static void handle_bt_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *manager) {
+ dm_device_direction_t direction;
+ pa_tz_device *device;
+ const char *system_id;
- pa_log_info("Destroy device item which of type is %s", device_item->type);
+ pa_assert(pdevice);
+ pa_assert(manager);
- device_item_free_func(device_item);
-}
+ pa_log_info("Handle bt pulse device");
-static unsigned _device_item_get_size(dm_device *device_item) {
- unsigned int profile_num;
- pa_assert(device_item);
+ direction = pulse_device_get_direction(pdevice);
+ system_id = pulse_device_get_system_id(pdevice);
- profile_num = pa_idxset_size(device_item->profiles);
- return profile_num;
-}
+ if (is_loaded) {
+ pa_tz_device_new_data data;
+ pa_tz_profile_new_data profile_data;
-static dm_device* _device_item_remove_profile(dm_device *device_item, dm_device_profile *profile_item, pa_device_manager *dm) {
- unsigned int profile_num;
+ /* Use profile_new_data, because BT is multi profile type */
+ pa_tz_profile_new_data_init(&profile_data);
+ pa_tz_profile_new_data_set_profile(&profile_data, DEVICE_PROFILE_BT_A2DP);
+ pa_tz_profile_new_data_set_direction(&profile_data, direction);
+ pa_tz_profile_new_data_set_use_internal_codec(&profile_data, false);
+ if (direction == DM_DEVICE_DIRECTION_OUT)
+ pa_tz_profile_new_data_add_sink(&profile_data, DEVICE_ROLE_NORMAL, PA_SINK(pdevice));
+ else
+ pa_tz_profile_new_data_add_source(&profile_data, DEVICE_ROLE_NORMAL, PA_SOURCE(pdevice));
+
+ device = _device_list_get_device(manager, DEVICE_TYPE_BT, system_id);
+ /* Just add profile, if already exists */
+ if (device) {
+ dm_device_bt_sco_status_t sco_status;
+ if (pa_tz_device_sco_get_status(device, &sco_status) < 0) {
+ pa_log_error("Failed to get sco status");
+ return ;
+ }
+ if (sco_status == DM_DEVICE_BT_SCO_STATUS_OPENED)
+ pa_tz_device_add_profile(device, &profile_data, false);
+ else
+ pa_tz_device_add_profile(device, &profile_data, true);
+ } else {
+ /* Create new device with profile */
+ const char *name;
+ name = pulse_device_get_device_name(pdevice, DEVICE_TYPE_BT);
- pa_assert(device_item);
- pa_assert(device_item->profiles);
- pa_assert(profile_item);
- pa_assert(dm);
+ pa_tz_device_new_data_init(&data, manager->device_list, manager->comm, manager->dbus_conn);
+ pa_tz_device_new_data_set_type(&data, DEVICE_TYPE_BT);
+ pa_tz_device_new_data_set_name(&data, name);
+ pa_tz_device_new_data_set_system_id(&data, system_id);
+ pa_tz_device_new_data_add_profile(&data, &profile_data, true);
- profile_num = pa_idxset_size(device_item->profiles);
+ pa_tz_device_new(&data);
+ pa_tz_device_new_data_done(&data);
+ }
+ pa_tz_profile_new_data_done(&profile_data);
+ } else {
- if (profile_num == 0) {
- pa_log_error("Already Empty device_item");
- return NULL;
+ if (!(device = _device_list_get_device(manager, DEVICE_TYPE_BT, system_id)))
+ pa_log_warn("Can't get bt device for %s", system_id);
+ else {
+ if (pa_tz_device_get_profile_num(device) > 1)
+ pa_tz_device_remove_profile(device, DEVICE_PROFILE_BT_A2DP);
+ else
+ pa_tz_device_free(device);
+ }
}
+}
+
+static void handle_internal_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *manager) {
+ pa_tz_device *device;
+ struct composite_type *ctype;
+ pa_dynarray *ctypes;
+ dm_device_direction_t direction;
- pa_idxset_remove_by_data(device_item->profiles, profile_item, NULL);
- _device_item_set_active_profile_auto(device_item);
+ pa_assert(pdevice);
+ pa_assert(manager);
+
+ pa_log_info("Handle internal pulse device");
+ direction = pulse_device_get_direction(pdevice);
+
+ /* Get types which this pulse_device belongs to */
+ if ((ctypes = pulse_device_get_belongs_type(pdevice, manager)) == NULL) {
+ pa_log_debug("Failed to get device type. Skip this");
+ return ;
+ }
+
+ if (is_loaded) {
+ /* Put this pulse_device to already loaded devices */
+ for (int i = 0; i < pa_dynarray_size(ctypes); i++) {
+ ctype = pa_dynarray_get(ctypes, i);
+ pa_log_info("Found belongs type %s %s %s", ctype->type, pa_strempty(ctype->profile), ctype->role);
+ if ((device = _device_list_get_device(manager, ctype->type, NULL))) {
+ pa_log_info("Add this pulse_device to device(%u)", pa_tz_device_get_id(device));
+ if (direction == DM_DEVICE_DIRECTION_OUT)
+ pa_tz_device_profile_add_sink(device, ctype->profile, ctype->role, PA_SINK(pdevice));
+ else
+ pa_tz_device_profile_add_source(device, ctype->profile, ctype->role, PA_SOURCE(pdevice));
+ } else {
+ pa_log_info("No device for %s", ctype->type);
+ }
+ }
+ } else {
+ /* Remove this pulse_device from already loaded devices */
+ for (int i = 0; i < pa_dynarray_size(ctypes); i++) {
+ ctype = pa_dynarray_get(ctypes, i);
+ pa_log_info("Found belongs type %s %s %s", ctype->type, ctype->profile, ctype->role);
+ if ((device = _device_list_get_device(manager, ctype->type, NULL))) {
+ pa_log_info("Remove this pulse_device from device(%u)", pa_tz_device_get_id(device));
+ if (direction == DM_DEVICE_DIRECTION_OUT)
+ pa_tz_device_remove_sink(device, PA_SINK(pdevice));
+ else
+ pa_tz_device_remove_source(device, PA_SOURCE(pdevice));
+ } else {
+ pa_log_info("No device for %s", ctype->type);
+ }
+ }
+ }
- return device_item;
+ pa_dynarray_free(ctypes);
}
-static dm_device_profile* create_device_profile(const char *device_profile, dm_device_direction_t direction, pa_hashmap *playback, pa_hashmap *capture) {
- dm_device_profile *profile_item = NULL;
+static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, pa_device_manager *dm) {
+ pa_assert(c);
+ pa_assert(sink);
+ pa_assert(dm);
- pa_assert(direction >= DM_DEVICE_DIRECTION_IN && direction <= DM_DEVICE_DIRECTION_BOTH);
+ pa_log_info("========== Sink Put Hook Callback '%s'(%d) ==========", sink->name, sink->index);
- pa_log_debug("Create device profile for %s, direction:%s", device_profile, device_direction_to_string(direction));
+ if (pulse_device_is_monitor(PA_OBJECT(sink)))
+ return PA_HOOK_OK;
- if (!(profile_item = (dm_device_profile *)pa_xmalloc(sizeof(dm_device_profile)))) {
- pa_log_error("Cannot alloc for device item");
- return NULL;
+ if (pulse_device_is_usb(PA_OBJECT(sink))) {
+ pulse_device_set_use_internal_codec(PA_OBJECT(sink), false);
+ handle_usb_pulse_device(PA_OBJECT(sink), true, dm);
+ return PA_HOOK_OK;
+ } else if (pulse_device_is_bluez(PA_OBJECT(sink))) {
+ pulse_device_set_use_internal_codec(PA_OBJECT(sink), false);
+ handle_bt_pulse_device(PA_OBJECT(sink), true, dm);
+ return PA_HOOK_OK;
+ } else if (pulse_device_is_alsa(PA_OBJECT(sink)) || pulse_device_is_tizenaudio(PA_OBJECT(sink))) {
+ pulse_device_set_use_internal_codec(PA_OBJECT(sink), true);
+ handle_internal_pulse_device(PA_OBJECT(sink), true, dm);
+ return PA_HOOK_OK;
+ } else {
+ pa_log_debug("Don't care this sink");
}
- profile_item->profile = device_profile ? strdup(device_profile) : NULL;
- profile_item->direction = direction;
- profile_item->playback_state = DM_DEVICE_STATE_DEACTIVATED;
- profile_item->capture_state = DM_DEVICE_STATE_DEACTIVATED;
- profile_item->playback_devices = playback;
- profile_item->capture_devices = capture;
- profile_item->creation_time = pa_rtclock_now();
- return profile_item;
+ return PA_HOOK_OK;
}
-static dm_device* destroy_device_profile(dm_device_profile *profile_item, pa_device_manager *dm) {
- dm_device *device_item;
-
- pa_assert(profile_item);
- pa_assert(profile_item->device_item);
+static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, pa_device_manager *dm) {
+ pa_assert(c);
+ pa_assert(sink);
+ pa_assert(dm);
- device_item = profile_item->device_item;
+ pa_log_info("=========== Sink unlink Hook Callback '%s'(%d) ==========", sink->name, sink->index);
- pa_log_info("Destroy device profile item which of profile is %s", profile_item->profile);
+ if (pulse_device_is_monitor(PA_OBJECT(sink)))
+ return PA_HOOK_OK;
- if (_device_item_get_size(device_item) == 1) {
- destroy_device_item(device_item, dm);
- return NULL;
+ if (pulse_device_is_usb(PA_OBJECT(sink))) {
+ handle_usb_pulse_device(PA_OBJECT(sink), false, dm);
+ return PA_HOOK_OK;
+ } else if (pulse_device_is_bluez(PA_OBJECT(sink))) {
+ handle_bt_pulse_device(PA_OBJECT(sink), false, dm);
+ return PA_HOOK_OK;
+ } else if (pulse_device_is_alsa(PA_OBJECT(sink)) || pulse_device_is_tizenaudio(PA_OBJECT(sink))) {
+ handle_internal_pulse_device(PA_OBJECT(sink), false, dm);
+ return PA_HOOK_OK;
} else {
- _device_item_remove_profile(device_item, profile_item, dm);
- profile_item_free_func(profile_item);
- return device_item;
+ pa_log_debug("Don't care this sink");
}
-}
-static void _device_profile_update_direction(dm_device_profile *profile_item) {
- int prev_direction;
- bool playback_exist = false, capture_exist = false;
+ return PA_HOOK_OK;
+}
- if (!profile_item)
- return;
+static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, pa_device_manager *dm) {
+ pa_assert(c);
+ pa_assert(source);
+ pa_assert(dm);
- prev_direction = profile_item->direction;
+ pa_log_info("========== source Put Hook Callback '%s'(%d) ==========", source->name, source->index);
- if (profile_item->playback_devices) {
- if (pa_hashmap_size(profile_item->playback_devices) > 0) {
- playback_exist = true;
- }
- }
- if (profile_item->capture_devices) {
- if (pa_hashmap_size(profile_item->capture_devices) > 0) {
- capture_exist = true;
- }
- }
+ if (pulse_device_is_monitor(PA_OBJECT(source)))
+ return PA_HOOK_OK;
- if (playback_exist && capture_exist) {
- profile_item->direction = DM_DEVICE_DIRECTION_BOTH;
- } else if (playback_exist) {
- profile_item->direction = DM_DEVICE_DIRECTION_OUT;
- } else if (capture_exist) {
- profile_item->direction = DM_DEVICE_DIRECTION_IN;
+ if (pulse_device_is_usb(PA_OBJECT(source))) {
+ pulse_device_set_use_internal_codec(PA_OBJECT(source), false);
+ handle_usb_pulse_device(PA_OBJECT(source), true, dm);
+ return PA_HOOK_OK;
+ } else if (pulse_device_is_bluez(PA_OBJECT(source))) {
+ pulse_device_set_use_internal_codec(PA_OBJECT(source), false);
+ handle_bt_pulse_device(PA_OBJECT(source), true, dm);
+ return PA_HOOK_OK;
+ } else if (pulse_device_is_alsa(PA_OBJECT(source)) || pulse_device_is_tizenaudio(PA_OBJECT(source))) {
+ pulse_device_set_use_internal_codec(PA_OBJECT(source), true);
+ handle_internal_pulse_device(PA_OBJECT(source), true, dm);
+ return PA_HOOK_OK;
} else {
- profile_item->direction = DM_DEVICE_DIRECTION_NONE;
+ pa_log_debug("Don't care this source");
}
- pa_log_debug("direction updated '%s'->'%s'", device_direction_to_string(prev_direction), device_direction_to_string(profile_item->direction));
+ return PA_HOOK_OK;
}
-static dm_device_profile* _device_profile_add_pulse_device(dm_device_profile *profile_item, const char *role, void *pulse_device, pa_device_type_t pdt) {
- if (!profile_item || !pulse_device || !device_role_is_valid(role)) {
- pa_log_error("Invalid Parameter");
- return NULL;
- }
+static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, pa_device_manager *dm) {
+ pa_assert(c);
+ pa_assert(source);
+ pa_assert(dm);
- if (pdt == PA_DEVICE_TYPE_SINK) {
- if (!(profile_item->playback_devices))
- profile_item->playback_devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- if (pa_hashmap_put(profile_item->playback_devices, (void *)role, pulse_device) < 0)
- return NULL;
+ pa_log_info("=========== source unlink Hook Callback '%s'(%d) ==========", source->name, source->index);
+
+ if (pulse_device_is_monitor(PA_OBJECT(source)))
+ return PA_HOOK_OK;
+
+ if (pulse_device_is_usb(PA_OBJECT(source))) {
+ handle_usb_pulse_device(PA_OBJECT(source), false, dm);
+ return PA_HOOK_OK;
+ } else if (pulse_device_is_bluez(PA_OBJECT(source))) {
+ handle_bt_pulse_device(PA_OBJECT(source), false, dm);
+ return PA_HOOK_OK;
+ } else if (pulse_device_is_alsa(PA_OBJECT(source)) || pulse_device_is_tizenaudio(PA_OBJECT(source))) {
+ handle_internal_pulse_device(PA_OBJECT(source), false, dm);
+ return PA_HOOK_OK;
} else {
- if (!(profile_item->capture_devices))
- profile_item->capture_devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- if (pa_hashmap_put(profile_item->capture_devices, (void *)role, pulse_device) < 0)
- return NULL;
+ pa_log_debug("Don't care this source");
}
- return profile_item;
+ return PA_HOOK_OK;
}
-static dm_device_profile* _device_profile_add_sink(dm_device_profile *profile_item, const char *role, pa_sink *sink) {
- if (!profile_item || !sink || !device_role_is_valid(role)) {
- pa_log_error("Invalid Parameter");
- return NULL;
- }
- if (!(profile_item->playback_devices))
- profile_item->playback_devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- if (pa_hashmap_put(profile_item->playback_devices, (void *)role, sink) < 0)
- return NULL;
- return profile_item;
-}
+static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *pdevice, pa_device_manager *dm) {
+ pa_tz_device *device;
+ bool use_internal_codec = false;
+ uint32_t idx = 0;
-static dm_device_profile* _device_profile_remove_sink(dm_device_profile *profile_item, const char *role) {
- if (!profile_item || !device_role_is_valid(role)) {
- pa_log_error("Invalid Parameter");
- return NULL;
- }
- pa_hashmap_remove(profile_item->playback_devices, role);
- return profile_item;
-}
+ pa_assert(c);
+ pa_object_assert_ref(pdevice);
+ pa_assert(dm);
-static dm_device_profile* _device_profile_add_source(dm_device_profile *profile_item, const char *role, pa_source *source) {
- if (!profile_item || !source || !device_role_is_valid(role)) {
- pa_log_error("Invalid Parameter");
- return NULL;
+ if (pa_sink_isinstance(pdevice)) {
+ pa_sink *s = PA_SINK(pdevice);
+ pa_sink_state_t state = pa_sink_get_state(s);
+ pa_log_debug("=========== Sink(%p,%s) state has been changed to [%d](0:RUNNING, 1:IDLE, 2:SUSPEND) ==========", s, s->name, state);
+ if (s->use_internal_codec) {
+ if (state == PA_SINK_SUSPENDED) {
+ PA_IDXSET_FOREACH(device, dm->device_list, idx) {
+ use_internal_codec = pa_tz_device_is_use_internal_codec(device);
+ if (use_internal_codec)
+ pa_tz_device_set_state(device, DM_DEVICE_DIRECTION_OUT, DM_DEVICE_STATE_DEACTIVATED);
+ }
+ }
+ } else {
+ if ((device = pa_device_manager_get_device_with_sink(s))) {
+ if (state == PA_SINK_RUNNING)
+ pa_tz_device_set_state(device, DM_DEVICE_DIRECTION_OUT, DM_DEVICE_STATE_ACTIVATED);
+ else if (state == PA_SINK_SUSPENDED)
+ pa_tz_device_set_state(device, DM_DEVICE_DIRECTION_OUT, DM_DEVICE_STATE_DEACTIVATED);
+ }
+ }
+ } else if (pa_source_isinstance(pdevice)) {
+ pa_source *s = PA_SOURCE(pdevice);
+ pa_source_state_t state = pa_source_get_state(s);
+ pa_log_debug("=========== Source(%p,%s) state has been changed to [%d](0:RUNNING, 1:IDLE, 2:SUSPEND) ==========", s, s->name, state);
+ if (s->use_internal_codec) {
+ if (state == PA_SOURCE_SUSPENDED) {
+ PA_IDXSET_FOREACH(device, dm->device_list, idx) {
+ use_internal_codec = pa_tz_device_is_use_internal_codec(device);
+ if (use_internal_codec)
+ pa_tz_device_set_state(device, DM_DEVICE_DIRECTION_IN, DM_DEVICE_STATE_DEACTIVATED);
+ }
+ }
+ } else {
+ if ((device = pa_device_manager_get_device_with_source(s))) {
+ if (state == PA_SOURCE_RUNNING)
+ pa_tz_device_set_state(device, DM_DEVICE_DIRECTION_IN, DM_DEVICE_STATE_ACTIVATED);
+ else if (state == PA_SOURCE_SUSPENDED)
+ pa_tz_device_set_state(device, DM_DEVICE_DIRECTION_IN, DM_DEVICE_STATE_DEACTIVATED);
+ }
+ }
}
+ pa_log_debug("========= device_state_changed_hook_cb END =====");
- if (!(profile_item->capture_devices))
- profile_item->capture_devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- if (pa_hashmap_put(profile_item->capture_devices, (void *)role, source) < 0)
- return NULL;
-
- return profile_item;
+ return PA_HOOK_OK;
}
-static int _device_profile_get_size(dm_device_profile *profile_item, unsigned int *playback_num, unsigned int *capture_num) {
- if (!profile_item || !playback_num || !capture_num) {
- pa_log_error("Invalid Parameter");
- return -1;
- }
+/*
+ Build params for load sink or source, and load it.
+*/
- if (!(profile_item->playback_devices))
- *playback_num = 0;
- else
- *playback_num = pa_hashmap_size(profile_item->playback_devices);
-
- if (!(profile_item->capture_devices))
- *capture_num = 0;
- else
- *capture_num = pa_hashmap_size(profile_item->capture_devices);
-
- return 0;
-}
-
-
-static dm_device_profile* _device_profile_remove_source(dm_device_profile *profile_item, const char *role) {
- if (!profile_item || !(profile_item->capture_devices) || !device_role_is_valid(role)) {
- pa_log_error("Invalid Parameter");
- return NULL;
- }
- pa_hashmap_remove(profile_item->capture_devices, role);
- return profile_item;
-}
-
-static void _device_profile_set_state(dm_device_profile *profile_item, dm_device_direction_t direction, dm_device_state_t state) {
- dm_device_state_t prev_state, new_state;
- pa_assert(profile_item);
-
- prev_state = COMPOUND_STATE(profile_item);
- pa_log_debug("previous playback_state : %d, capture_state : %d => state %d", profile_item->playback_state, profile_item->capture_state, prev_state);
- if (direction & DM_DEVICE_DIRECTION_IN)
- profile_item->capture_state = state;
- if (direction & DM_DEVICE_DIRECTION_OUT)
- profile_item->playback_state = state;
- new_state = COMPOUND_STATE(profile_item);
- pa_log_debug("new playback_state : %d, capture_state : %d => state %d", profile_item->playback_state, profile_item->capture_state, new_state);
-
- if (prev_state != new_state) {
- notify_device_info_changed(profile_item->device_item, DM_DEVICE_CHANGED_INFO_STATE, profile_item->device_item->dm);
- }
-}
-
-static int device_type_get_direction(pa_device_manager *dm, const char *device_type, const char *device_profile, const char *identifier) {
- struct device_type_info *type_info = NULL;
- struct device_status_info *status_info;
-
- if (!dm || !device_type) {
- pa_log_error("Invalid Parameter");
- return -1;
- }
-
- if (pa_streq(device_type, DEVICE_TYPE_SPEAKER)) {
- return DM_DEVICE_DIRECTION_OUT;
- } else if (pa_streq(device_type, DEVICE_TYPE_RECEIVER)) {
- return DM_DEVICE_DIRECTION_OUT;
- } else if (pa_streq(device_type, DEVICE_TYPE_MIC)) {
- return DM_DEVICE_DIRECTION_IN;
- } else if (pa_streq(device_type, DEVICE_TYPE_BT) && pa_streq(device_profile, DEVICE_PROFILE_BT_A2DP)) {
- return -1;
- } else if (pa_streq(device_type, DEVICE_TYPE_BT) && pa_streq(device_profile, DEVICE_PROFILE_BT_SCO)) {
- return DM_DEVICE_DIRECTION_BOTH;
- } else if (pa_streq(device_type, DEVICE_TYPE_HDMI)) {
- return DM_DEVICE_DIRECTION_OUT;
- } else if (pa_streq(device_type, DEVICE_TYPE_USB_AUDIO)) {
- return -1;
- } else if (pa_streq(device_type, DEVICE_TYPE_FORWARDING)) {
- return DM_DEVICE_DIRECTION_BOTH;
- } else if (pa_streq(device_type, DEVICE_TYPE_AUDIO_JACK)) {
- if (!(type_info = _device_manager_get_type_info(dm->type_infos, device_type, device_profile))) {
- pa_log_error("No type map for %s", device_type);
- return -1;
- }
- status_info = _device_manager_get_status_info(dm->device_status, type_info->type, type_info->profile, identifier);
- if (status_info->detected_type == DEVICE_DETECTED_AUDIO_JACK_BOTH_DIREC) {
- return DM_DEVICE_DIRECTION_BOTH;
- } else if (status_info->detected_type == DEVICE_DETECTED_AUDIO_JACK_OUT_DIREC) {
- return DM_DEVICE_DIRECTION_OUT;
- } else {
- pa_log_debug("Cannot get audio jack device direction");
- return -1;
- }
- }
-
- return -1;
-}
-
-static int pulse_device_get_device_type(void *pulse_device, pa_device_type_t pdt, dm_device_class_t device_class, const char **device_type, const char **device_profile, const char **device_name) {
- pa_proplist *prop;
+static void* load_device(pa_core *c, bool is_sink, const char *device_string, const char *device_params) {
+ const char *args = NULL;
+ const char *module_name;
+ pa_module *module;
pa_sink *sink;
pa_source *source;
+ uint32_t device_idx;
+ dm_device_class_t device_class;
- pa_assert(pulse_device);
- pa_assert(device_type);
- pa_assert(device_profile);
-
- if (pdt == PA_DEVICE_TYPE_SINK) {
- sink = (pa_sink *) pulse_device;
- prop = sink->proplist;
- } else {
- source = (pa_source*) pulse_device;
- prop = source->proplist;
- }
-
- if (device_class == DM_DEVICE_CLASS_ALSA) {
- if (pulse_device_is_usb(prop)) {
- *device_type = DEVICE_TYPE_USB_AUDIO;
- *device_profile = NULL;
- *device_name = pa_proplist_gets(prop, "udev.id");
- } else {
- pa_log_warn("This is alsa device, but not usb. really unknown device");
- return -1;
- }
- } else if (device_class == DM_DEVICE_CLASS_BT) {
- *device_type = DEVICE_TYPE_BT;
- *device_profile = DEVICE_PROFILE_BT_A2DP;
- *device_name = pa_proplist_gets(prop, "bluez.alias");
- } else {
- pa_log_warn("Invalid device type, neither alsa nor bluez");
- return -1;
- }
-
- return 0;
-}
-
-static dm_device_profile* _device_item_get_profile(dm_device *device_item, const char *profile) {
- dm_device_profile *profile_item;
- uint32_t profile_idx;
-
- if (!device_item || !device_item->profiles)
- return NULL;
-
- PA_IDXSET_FOREACH(profile_item, device_item->profiles, profile_idx) {
- if (!compare_device_profile(profile_item->profile, profile)) {
- return profile_item;
- }
- }
- return NULL;
-}
-
-static dm_device_profile* _device_item_get_active_profile(dm_device *device_item) {
- dm_device_profile *profile_item;
-
- if (!device_item || !device_item->profiles)
- return NULL;
-
- if ((profile_item = pa_idxset_get_by_index(device_item->profiles, device_item->active_profile)))
- return profile_item;
-
-
- return NULL;
-}
-
-static pa_sink* _device_manager_set_default_sink(pa_device_manager *dm, const char *device_type, const char *device_profile, const char *role) {
- dm_device *device_item;
- dm_device_profile *profile_item;
- pa_sink *sink;
-
- if (!device_type || !role) {
- pa_log_warn("Argument for set_default_sink invalid");
- return NULL;
- }
-
- if (!(device_item = _device_manager_get_device(dm->device_list, device_type))) {
- pa_log_warn("cannot get device item for %s", device_type);
- return NULL;
- }
- if (!(profile_item = _device_item_get_profile(device_item, device_profile))) {
- pa_log_warn("cannot get profile item for %s", device_profile);
- return NULL;
- }
-
- if (!(sink = pa_hashmap_get(profile_item->playback_devices, role))) {
- pa_log_warn("cannot get sink for %s", role);
- return NULL;
- }
-
- sink = pa_namereg_set_default_sink(dm->core, sink);
- return sink;
-}
+ pa_assert(c);
+ pa_assert(device_string);
+ pa_assert(device_params);
-static pa_source* _device_manager_set_default_source(pa_device_manager *dm, const char *device_type, const char *device_profile, const char *role) {
- dm_device *device_item;
- dm_device_profile *profile_item;
- pa_source *source;
+ pa_log_info("Load %s Device : String'%s' Param'%s'", is_sink ? "Playback" : "Capture", device_string, device_params);
- if (!device_type || !role) {
- pa_log_warn("Argument for set_default_source invalid");
+ device_class = device_string_get_class(device_string);
+ if (device_class <= DM_DEVICE_CLASS_NONE || device_class >= DM_DEVICE_CLASS_MAX) {
+ pa_log_warn("Invalid device_string '%s'", device_string);
return NULL;
}
- if (!(device_item = _device_manager_get_device(dm->device_list, device_type))) {
- pa_log_warn("cannot get device item for %s", device_type);
+ if (!(module_name = device_class_get_module_name(device_class, is_sink))) {
+ pa_log_error("Get proper module name to load failed");
return NULL;
}
- if (!(profile_item = _device_item_get_profile(device_item, device_profile))) {
- pa_log_warn("cannot get profile item for %s", device_profile);
+ if (!(args = build_params_to_load_device(device_string, device_params, device_class))) {
+ pa_log_error("Get proper module name to load failed");
return NULL;
}
-
- if (!(source = pa_hashmap_get(profile_item->capture_devices, role))) {
- pa_log_warn("cannot get source for %s", role);
+ if (!(module = pa_module_load(c, module_name, args))) {
+ pa_log_error("Load module with name '%s' argu '%s' failed", module_name, args);
return NULL;
}
- source = pa_namereg_set_default_source(dm->core, source);
- return source;
-}
-
-static dm_device_profile* handle_not_predefined_device_profile(void *pulse_device, pa_device_type_t pdt, const char *device_profile) {
- dm_device_profile *profile_item = NULL;
- dm_device_direction_t direc;
- pa_log_info("Create device profile item %s", device_profile);
- if (pdt == PA_DEVICE_TYPE_SINK)
- direc = DM_DEVICE_DIRECTION_OUT;
- else
- direc = DM_DEVICE_DIRECTION_IN;
-
- if (!(profile_item = create_device_profile(device_profile, direc, NULL, NULL))) {
- pa_log_error("create_device_profile failed");
- goto failed;
- }
- if (pdt == PA_DEVICE_TYPE_SINK) {
- if (!(_device_profile_add_sink(profile_item, DEVICE_ROLE_NORMAL, pulse_device))) {
- pa_log_error("failed to add sink");
- goto failed;
+ if (is_sink) {
+ PA_IDXSET_FOREACH(sink, c->sinks, device_idx) {
+ if (sink->module == module) {
+ return sink;
+ }
}
} else {
- if (!(_device_profile_add_source(profile_item, DEVICE_ROLE_NORMAL, pulse_device))) {
- pa_log_error("failed to add source");
- goto failed;
- }
- }
-
- return profile_item;
-failed:
- if (profile_item)
- pa_xfree(profile_item);
- return NULL;
-}
-
-
-static dm_device* handle_not_predefined_device(pa_device_manager *dm, void *pulse_device, pa_device_type_t pdt, dm_device_class_t device_class) {
- dm_device_profile *profile_item = NULL;
- const char *device_type, *device_profile, *device_name;
- dm_device *device_item = NULL;
- pa_source *sibling_source, *source;
- pa_sink *sibling_sink, *sink;
-
- pa_assert(dm);
- pa_assert(pulse_device);
-
- pa_log_info("handle_not_predefined_device");
-
- if (pdt == PA_DEVICE_TYPE_SINK)
- ((pa_sink*)pulse_device)->use_internal_codec = false;
- else
- ((pa_source*)pulse_device)->use_internal_codec = false;
-
- if (pulse_device_get_device_type(pulse_device, pdt, device_class, &device_type, &device_profile, &device_name) < 0) {
- pa_log_warn("Cannot get device type of this device");
- return NULL;
- }
-
- /*
- Find opposite direction sink/sources on same device.
- If Found, add sink or source to same device_item.
- */
- if (pa_streq(device_type, DEVICE_TYPE_USB_AUDIO)) {
- if (pdt == PA_DEVICE_TYPE_SINK) {
- sink = (pa_sink *) pulse_device;
- if ((sibling_source = pulse_device_get_opposite_sibling_device(sink, PA_DEVICE_TYPE_SINK))) {
- if (sibling_source->device_item) {
- device_item = (dm_device *) sibling_source->device_item;
- profile_item = _device_item_get_profile(device_item, NULL);
- if (!(_device_profile_add_sink(profile_item, DEVICE_ROLE_NORMAL, sink))) {
- pa_log_error("failed to add sink beside sibling source");
- goto failed;
- }
- _device_profile_update_direction(profile_item);
- notify_device_info_changed(device_item, DM_DEVICE_CHANGED_INFO_IO_DIRECTION, dm);
- goto end;
- }
- }
- } else {
- source = (pa_source*) pulse_device;
- if ((sibling_sink = pulse_device_get_opposite_sibling_device(source, PA_DEVICE_TYPE_SOURCE))) {
- if (sibling_sink->device_item) {
- device_item = (dm_device *) sibling_sink->device_item;
- profile_item = _device_item_get_profile(device_item, NULL);
- if (!(_device_profile_add_source(profile_item, DEVICE_ROLE_NORMAL, source))) {
- pa_log_error("failed to add source beside sibling sink");
- goto failed;
- }
- _device_profile_update_direction(profile_item);
- notify_device_info_changed(device_item, DM_DEVICE_CHANGED_INFO_IO_DIRECTION, dm);
- goto end;
- }
+ PA_IDXSET_FOREACH(source, c->sources, device_idx) {
+ if (source->module == module) {
+ return source;
}
}
}
- if (!(profile_item = handle_not_predefined_device_profile(pulse_device, pdt, device_profile))) {
- pa_log_error("failed to handle unknown device profile");
- goto failed;
- }
- _device_profile_update_direction(profile_item);
-
- if (device_class == DM_DEVICE_CLASS_BT) {
- if ((device_item = _device_manager_get_device(dm->device_list, DEVICE_TYPE_BT))) {
- pa_log_debug("found bt device");
- _device_item_add_profile(device_item, profile_item, NULL, dm);
- goto end;
- }
- }
-
- if (!(device_item = create_device_item(device_type, device_name, profile_item, dm))) {
- pa_log_error("failed to create device item for not predefined device");
- goto failed;
- }
-
-end:
-
- if (pdt == PA_DEVICE_TYPE_SINK) {
- sink = (pa_sink *) pulse_device;
- sink->device_item = device_item;
- } else {
- source = (pa_source *) pulse_device;
- source->device_item = device_item;
- }
-
- return device_item;
-
-failed:
- pa_log_error("Failed to handle external device");
- if (profile_item)
- pa_xfree(profile_item);
- if (pdt == PA_DEVICE_TYPE_SINK) {
- sink = (pa_sink *) pulse_device;
- sink->device_item = device_item;
- } else {
- source = (pa_source *) pulse_device;
- source->device_item = device_item;
- }
-
-
return NULL;
}
-static bool pulse_device_loaded_with_param(pa_core *core, pa_device_type_t pdt, const char *device_string, const char *params) {
- pa_sink *sink;
- pa_source *source;
+static pa_sink* _core_get_sink(pa_core *core, const char *device_string, const char *params) {
uint32_t device_idx;
+ pa_sink *sink;
pa_assert(core);
pa_assert(device_string);
- if (pdt == PA_DEVICE_TYPE_SINK) {
- PA_IDXSET_FOREACH(sink, core->sinks, device_idx) {
- if (pulse_device_class_is_monitor(sink->proplist))
- continue;
- if (pa_streq(device_string, pulse_device_get_device_string(sink, pdt))) {
- if (!compare_device_params_with_module_args(sink, pdt, params)) {
- return true;
- }
- }
- }
- } else {
- PA_IDXSET_FOREACH(source, core->sources, device_idx) {
- if (pulse_device_class_is_monitor(source->proplist))
- continue;
- if (pa_streq(device_string, pulse_device_get_device_string(source, pdt))) {
- if (!compare_device_params_with_module_args(source, pdt, params)) {
- return true;
- }
- }
+ PA_IDXSET_FOREACH(sink, core->sinks, device_idx) {
+ if (pulse_device_is_monitor(PA_OBJECT(sink)))
+ continue;
+ if (pulse_device_same_device_string(PA_OBJECT(sink), device_string)) {
+ if (params == NULL)
+ return sink;
+ else if (pulse_device_params_is_equal(PA_OBJECT(sink), params))
+ return sink;
}
}
- return false;
+
+ return NULL;
}
-static int device_type_get_pulse_devices(struct device_type_info *type_info, pa_hashmap **playback, pa_hashmap **capture, pa_device_manager *dm) {
- struct device_file_info *file_info;
- const char *device_string, *params, *role;
+static pa_source* _core_get_source(pa_core *core, const char *device_string, const char *params) {
uint32_t device_idx;
- pa_sink *sink;
pa_source *source;
- void *state;
-
- pa_assert(type_info);
- pa_assert(playback);
- pa_assert(capture);
- pa_assert(dm);
-
- if (pa_streq(type_info->type, DEVICE_TYPE_FORWARDING)) {
- dm_device *device_item;
- dm_device_profile *device_profile;
- pa_sink *spk_sink;
-
- /* Let sink of forwading device same as speaker,
- * source of forwarding device will be monitor of that sink */
- if (!(device_item = _device_manager_get_device(dm->device_list, DEVICE_TYPE_SPEAKER))) {
- pa_log_error("get speaker item failed");
- goto failed;
- } else if (!(device_profile = _device_item_get_profile(device_item, NULL))) {
- pa_log_error("get speaker profile failed");
- goto failed;
- } else if (!(spk_sink = _device_profile_get_sink(device_profile, DEVICE_ROLE_NORMAL)) || !(spk_sink->monitor_source)) {
- pa_log_error("get speaker sink and monitor source failed");
- goto failed;
- } else {
- *playback = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- *capture = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- pa_hashmap_put(*playback, (void *)DEVICE_ROLE_NORMAL, spk_sink);
- pa_hashmap_put(*capture, (void *)DEVICE_ROLE_NORMAL, spk_sink->monitor_source);
- ((pa_source*)(spk_sink->monitor_source))->use_internal_codec = true;
- }
- } else {
- if (type_info->playback_devices) {
- *playback = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- PA_HASHMAP_FOREACH_KEY(device_string, type_info->playback_devices, state, role) {
- if (!(file_info = _device_manager_get_file_info(dm->file_map->playback, device_string))) {
- pa_log_error("No playback file map for '%s'", device_string);
- goto failed;
- }
- if (!(params = pa_hashmap_get(file_info->roles, role))) {
- pa_log_error("No params for '%s:%s'", device_string, role);
- goto failed;
- }
+ pa_assert(core);
+ pa_assert(device_string);
- PA_IDXSET_FOREACH(sink, dm->core->sinks, device_idx) {
- if (pulse_device_class_is_monitor(sink->proplist))
- continue;
- if (pulse_device_same_device_string(sink, PA_DEVICE_TYPE_SINK, device_string)) {
- if (!compare_device_params_with_module_args(sink, PA_DEVICE_TYPE_SINK, params)) {
- pa_hashmap_put(*playback, (void *)role, sink);
- pa_log_debug("role:%s <- sink:%s", role, sink->name);
- break;
- }
- }
- }
- }
- }
- if (type_info->capture_devices) {
- *capture = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- PA_HASHMAP_FOREACH_KEY(device_string, type_info->capture_devices, state, role) {
- if (!(file_info = _device_manager_get_file_info(dm->file_map->capture, device_string))) {
- pa_log_error("No capture file map for '%s'", device_string);
- goto failed;
- }
- if (!(params = pa_hashmap_get(file_info->roles, role))) {
- pa_log_error("No params for '%s:%s'", device_string, role);
- goto failed;
- }
- PA_IDXSET_FOREACH(source, dm->core->sources, device_idx) {
- if (pulse_device_class_is_monitor(source->proplist))
- continue;
- if (pulse_device_same_device_string(source, PA_DEVICE_TYPE_SOURCE, device_string)) {
- if (!compare_device_params_with_module_args(source, PA_DEVICE_TYPE_SOURCE, params)) {
- pa_hashmap_put(*capture, (void *)role, source);
- pa_log_debug("role:%s <- source:%s", role, source->name);
- break;
- }
- }
- }
- }
+ PA_IDXSET_FOREACH(source, core->sources, device_idx) {
+ if (pulse_device_is_monitor(PA_OBJECT(source)))
+ continue;
+ if (pulse_device_same_device_string(PA_OBJECT(source), device_string)) {
+ if (params == NULL)
+ return source;
+ else if (pulse_device_params_is_equal(PA_OBJECT(source), params))
+ return source;
}
}
- return 0;
-
-failed:
- if (!(*playback))
- pa_hashmap_free(*playback);
- if (!(*capture))
- pa_hashmap_free(*capture);
- *playback = NULL;
- *capture = NULL;
-
- return -1;
-}
-
-static const char* device_type_info_get_device_string(struct device_type_info *type_info, const char *role, pa_device_type_t pdt) {
- pa_assert(type_info);
- pa_assert(role);
-
- if (pdt == PA_DEVICE_TYPE_SINK) {
- if (type_info->playback_devices)
- return pa_hashmap_get(type_info->playback_devices, role);
- else
- return NULL;
- } else {
- if (type_info->capture_devices)
- return pa_hashmap_get(type_info->capture_devices, role);
- else
- return NULL;
- }
-
-}
-
-static const char* device_file_info_get_role_with_params(struct device_file_info *file_info, const char *params) {
- char *params_tmp, *role;
- void *state;
-
- PA_HASHMAP_FOREACH_KEY(params_tmp, file_info->roles, state, role) {
- if (!compare_device_params(params_tmp, params)) {
- return role;
- }
- }
return NULL;
}
-static dm_device* handle_device_type_available(struct device_type_info *type_info, const char *name, pa_device_manager *dm) {
- dm_device_profile *profile_item = NULL;
- dm_device *device_item = NULL;
- dm_device_direction_t direction;
- pa_hashmap *playback = NULL, *capture = NULL;
-
- pa_assert(dm);
- pa_assert(dm->type_infos);
-
- pa_log_debug("handle_device_type_available, type:%s, profile:%s, name:%s", type_info->type, type_info->profile, name);
-
- /* Directions of some types are not statically defined, ex) earjack */
- if ((direction = device_type_get_direction(dm, type_info->type, type_info->profile, NULL)) < 0) {
- pa_log_error("Failed to get direction of %s.%s", type_info->type, type_info->profile);
- return NULL;
- }
- pa_log_debug("Direction of %s.%s is %s", type_info->type, type_info->profile, device_direction_to_string(direction));
-
- /* Get Sink/Sources for device_type, profile */
- if (device_type_get_pulse_devices(type_info, &playback, &capture, dm) < 0) {
- pa_log_error("Failed to get sink/sources related to %s.%s", type_info->type, type_info->profile);
- return NULL;
- }
-
- /* Check whether Sink/Sources for direction of type are loaded */
- if ((((direction & DM_DEVICE_DIRECTION_IN) && !capture) || ((direction & DM_DEVICE_DIRECTION_OUT) && !playback))) {
- pa_log_debug("Sink/Sources for %s.%s are not fully loaded yet", type_info->type, type_info->profile);
- goto failed;
- }
- profile_item = create_device_profile(type_info->profile, direction, playback, capture);
+static void _fill_new_data_basic(pa_tz_device_new_data *data, const char *type,
+ dm_device_direction_t direction, bool use_internal_codec, pa_device_manager *dm) {
+ pa_assert(data);
- if (!(device_item = _device_manager_get_device(dm->device_list, type_info->type))) {
- pa_log_debug("No device item for %s, Create", type_info->type);
- device_item = create_device_item(type_info->type, name, profile_item, dm);
- } else {
- _device_item_add_profile(device_item, profile_item, NULL, dm);
- }
-
- return device_item;
-
-failed:
- if (playback)
- pa_hashmap_free(playback);
- if (capture)
- pa_hashmap_free(capture);
- return NULL;
+ pa_tz_device_new_data_set_type(data, type);
+ pa_tz_device_new_data_set_direction(data, direction);
+ pa_tz_device_new_data_set_use_internal_codec(data, use_internal_codec);
}
-/* FIXME to get identifier of physical device */
-static const char* pulse_device_get_identifier(void *pulse_device, pa_device_type_t pdt, dm_device_class_t device_class) {
-/*
- const char *sysfs_path;
+static void _fill_profile_new_data_basic(pa_tz_profile_new_data *profile_data,
+ const char *profile, dm_device_direction_t direction, bool use_internal_codec, pa_device_manager *dm) {
+ pa_assert(profile_data);
- if (device_class == TIZEN_AUDIO_DEVICE_CLASS_ALSA) {
- if (!(sysfs_path = pa_proplist_gets(sink->proplist, "sysfs.path"))) {
- pa_log_warn("No sysfs.path for sink '%s'", sink->name);
- return NULL;
- } else {
- return sysfs_path;
- }
- } else if (device_class == TIZEN_AUDIO_DEVICE_CLASS_BT) {
- }
- */
- return NULL;
+ pa_tz_profile_new_data_set_profile(profile_data, profile);
+ pa_tz_profile_new_data_set_direction(profile_data, direction);
+ pa_tz_profile_new_data_set_use_internal_codec(profile_data, use_internal_codec);
}
-static void handle_predefined_device_loaded(void *pulse_device, pa_device_type_t pdt, dm_device_class_t device_class, const char *device_string, const char *role, pa_device_manager *dm) {
- const char *identifier, *device_string_tmp;
- struct device_type_info *type_info;
- struct device_status_info *status_info;
- uint32_t type_idx;
- dm_device *device_item;
- dm_device_profile *profile_item;
-
- pa_assert(pulse_device);
- pa_assert(dm);
- pa_assert(dm->file_map);
- pa_assert(device_string);
- pa_assert(role);
-
- pa_log_info("Predefined device loaded, Type:%s, Class:%d, device_string:%s, role:%s",
- pdt == PA_DEVICE_TYPE_SINK ? "sink" : "source", device_class, device_string, role);
-
- if (pdt == PA_DEVICE_TYPE_SINK)
- ((pa_sink*)pulse_device)->use_internal_codec = true;
- else
- ((pa_source*)pulse_device)->use_internal_codec = true;
-
- identifier = pulse_device_get_identifier(pulse_device, pdt, device_class);
- PA_IDXSET_FOREACH(type_info, dm->type_infos, type_idx) {
- /* foreach matching types (which has device_string-role) */
- if ((device_string_tmp = device_type_info_get_device_string(type_info, role, pdt)) && pa_streq(device_string_tmp, device_string)) {
- /*
- Check device_item is already exists.
- If already exists, add loaded sink or source to that.
- */
- if ((device_item = _device_manager_get_device(dm->device_list, type_info->type))) {
- if ((profile_item = _device_item_get_profile(device_item, type_info->profile))) {
- pa_log_debug("device_item for %s.%s already exists", type_info->type, type_info->profile);
- if (!_device_profile_add_pulse_device(profile_item, role, pulse_device, pdt))
- pa_log_error("add pulse device to profile_item failed");
- continue;
- }
- }
+static int _fill_new_data_sinks(pa_tz_device_new_data *data, struct device_type_info *type_info, pa_device_manager *dm) {
+ pa_sink *sink;
+ char *device_string, *role;
+ void *state;
- /* Get status_info for device_type, profile*/
- if (!(status_info = _device_manager_get_status_info(dm->device_status, type_info->type, type_info->profile, identifier))) {
- pa_log_error("%s.%s.%s doesn't have status_info", type_info->type, type_info->profile, identifier);
- continue;
- }
- /* Only if device_type is on detected state*/
- if (status_info->detected == DEVICE_DETECTED) {
- pa_log_debug("%s.%s type is detected status", type_info->type, type_info->profile);
+ pa_assert(data);
+ pa_assert(type_info);
- handle_device_type_available(type_info, NULL, dm);
- } else {
- pa_log_debug(" This type is not detected status");
- }
- }
+ if (type_info->playback_devices == NULL) {
+ pa_log_error("No playback devices for %s %s", type_info->type, pa_strempty(type_info->profile));
+ return -1;
}
-}
-static void handle_sink_unloaded(pa_sink *sink, pa_device_manager *dm) {
- dm_device_profile *profile_item = NULL;
- dm_device *device_item;
- uint32_t device_idx = 0, profile_idx;
- pa_sink *sink_iter = NULL;
- void *state = NULL;
- const char *role;
-
- if (!sink || !dm) {
- pa_log_error("Invalid Paramter");
- return;
+ PA_HASHMAP_FOREACH_KEY(device_string, type_info->playback_devices, state, role) {
+ sink = _core_get_sink(dm->core, device_string, NULL);
+ if (sink)
+ pa_tz_device_new_data_add_sink(data, role, sink);
+ else
+ pa_log_error("Failed to get matching sink for %s %s", role, device_string);
}
- pa_assert(sink);
- pa_assert(dm);
- pa_assert(dm->device_list);
- pa_log_debug("Sink unloaded, Let's remove associated device_profiles with this sink");
-
- PA_IDXSET_FOREACH(device_item, dm->device_list, device_idx) {
- PA_IDXSET_FOREACH(profile_item, device_item->profiles, profile_idx) {
- if (profile_item->playback_devices) {
- PA_HASHMAP_FOREACH_KEY(sink_iter, profile_item->playback_devices, state, role) {
- if (sink_iter == sink) {
- unsigned int profile_playback_size = 0, profile_capture_size = 0, item_size = 0;
- pa_log_info("device '%s' have this sink", device_item->name);
- _device_profile_get_size(profile_item, &profile_playback_size, &profile_capture_size);
- item_size = _device_item_get_size(device_item);
- pa_log_debug("profile playback size : %u, capture size : %u, item size : %u", profile_playback_size, profile_capture_size, item_size);
- if (profile_playback_size == 1 && profile_capture_size == 0) {
- if (item_size == 1) {
- pa_log_debug("notify device disconnected");
- _device_list_remove_device(dm->device_list, device_item, dm);
- notify_device_connection_changed(device_item, false, dm);
- }
- }
- _device_profile_remove_sink(profile_item, role);
- }
- }
- if (!pa_hashmap_size(profile_item->playback_devices)) {
- pa_hashmap_free(profile_item->playback_devices);
- profile_item->playback_devices = NULL;
-
- if (profile_item->direction == DM_DEVICE_DIRECTION_BOTH) {
- if (device_type_is_valid_direction(profile_item->device_item->type, profile_item->profile, DM_DEVICE_DIRECTION_IN)) {
- profile_item->direction = DM_DEVICE_DIRECTION_IN;
- } else {
- if (!destroy_device_profile(profile_item, dm))
- break;
- }
- } else {
- if (!destroy_device_profile(profile_item, dm))
- break;
- }
- } else {
- _device_profile_update_direction(profile_item);
- }
- }
- }
- }
+ return 0;
}
-static void handle_source_unloaded(pa_source *source, pa_device_manager *dm) {
- dm_device_profile *profile_item = NULL;
- dm_device *device_item;
- uint32_t device_idx = 0, profile_idx;
- pa_source *source_iter = NULL;
- void *state = NULL;
- const char *role;
-
- if (!source || !dm) {
- pa_log_error("Invalid Paramter");
- return;
- }
- pa_assert(source);
- pa_assert(dm);
- pa_assert(dm->device_list);
+static int _fill_new_data_sources(pa_tz_device_new_data *data, struct device_type_info *type_info, pa_device_manager *dm) {
+ pa_source *source;
+ char *device_string, *role;
+ void *state;
- pa_log_debug("Source unloaded, Let's remove associated device_profiles with this source");
-
- PA_IDXSET_FOREACH(device_item, dm->device_list, device_idx) {
- PA_IDXSET_FOREACH(profile_item, device_item->profiles, profile_idx) {
- if (profile_item->capture_devices) {
- PA_HASHMAP_FOREACH_KEY(source_iter, profile_item->capture_devices, state, role) {
- if (source_iter == source) {
- unsigned int profile_playback_size = 0, profile_capture_size = 0, item_size = 0;
- pa_log_info("device '%s' have this source", device_item->name);
- _device_profile_get_size(profile_item, &profile_playback_size, &profile_capture_size);
- item_size = _device_item_get_size(device_item);
- pa_log_debug("profile playback size : %u, capture size : %u, item size : %u", profile_playback_size, profile_capture_size, item_size);
- if (profile_capture_size == 1 && profile_playback_size == 0) {
- if (item_size == 1) {
- pa_log_debug("notify device disconnected");
- _device_list_remove_device(dm->device_list, device_item, dm);
- notify_device_connection_changed(device_item, false, dm);
- }
- }
-
- _device_profile_remove_source(profile_item, role);
- }
- }
+ pa_assert(data);
+ pa_assert(type_info);
- if (!pa_hashmap_size(profile_item->capture_devices)) {
- pa_hashmap_free(profile_item->capture_devices);
- profile_item->capture_devices = NULL;
-
- if (profile_item->direction == DM_DEVICE_DIRECTION_BOTH) {
- if (device_type_is_valid_direction(profile_item->device_item->type, profile_item->profile, DM_DEVICE_DIRECTION_OUT)) {
- profile_item->direction = DM_DEVICE_DIRECTION_OUT;
- } else {
- if (!destroy_device_profile(profile_item, dm))
- break;
- }
- } else {
- if (!destroy_device_profile(profile_item, dm))
- break;
- }
- } else {
- _device_profile_update_direction(profile_item);
- }
- }
- }
+ if (type_info->capture_devices == NULL) {
+ pa_log_error("No capture devices for %s %s", type_info->type, pa_strempty(type_info->profile));
+ return -1;
}
-}
-static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, pa_device_manager *dm) {
- const char *device_string = NULL, *role = NULL, *device_string_removed_params = NULL;
- struct device_file_info *file_info = NULL;
- dm_device_class_t device_class;
-
- pa_assert(c);
- pa_assert(sink);
- pa_assert(sink->proplist);
- pa_assert(dm);
-
- if (pulse_device_class_is_monitor(sink->proplist)) {
- pa_log_debug("This device's class is monitor. Skip this");
- return PA_HOOK_OK;
+ PA_HASHMAP_FOREACH_KEY(device_string, type_info->capture_devices, state, role) {
+ source = _core_get_source(dm->core, device_string, NULL);
+ if (source)
+ pa_tz_device_new_data_add_source(data, role, source);
+ else
+ pa_log_error("Failed to get matching source for %s %s", role, device_string);
}
- pa_log_info("========== Sink Put Hook Callback '%s'(%d) ==========", sink->name, sink->index);
+ return 0;
+}
- device_class = pulse_device_get_class(sink, PA_DEVICE_TYPE_SINK);
- pa_log_info("Device Class '%s'", device_class_to_string(device_class));
+static int _fill_profile_new_data_sinks(pa_tz_profile_new_data *data, struct device_type_info *type_info, pa_device_manager *dm) {
+ pa_sink *sink;
+ char *device_string, *role;
+ void *state;
- if (!(device_string = pulse_device_get_device_string(sink, PA_DEVICE_TYPE_SINK))) {
- return PA_HOOK_OK;
- } else {
- pa_log_info("Device String '%s'", device_string);
- }
+ pa_assert(data);
+ pa_assert(type_info);
- if (device_class == DM_DEVICE_CLASS_BT) {
- handle_not_predefined_device(dm, sink, PA_DEVICE_TYPE_SINK, device_class);
- } else if ((file_info = _device_manager_get_file_info(dm->file_map->playback, device_string))) {
- /* module's argument includes device-string(ex. device=hw:0,0 ),
- but key params for device_types hashmap is not. */
- if (!(device_string_removed_params = pulse_device_get_device_string_removed_argument(sink, PA_DEVICE_TYPE_SINK))) {
- pa_log_debug("argument null");
- return PA_HOOK_OK;
- }
- if (!(role = device_file_info_get_role_with_params(file_info, device_string_removed_params))) {
- pa_log_error("No role for %s", file_info->device_string);
- return PA_HOOK_OK;
- }
+ if (type_info->playback_devices == NULL) {
+ pa_log_error("No playback devices for %s %s", type_info->type, pa_strempty(type_info->profile));
+ return -1;
+ }
- handle_predefined_device_loaded(sink, PA_DEVICE_TYPE_SINK, device_class, device_string, role, dm);
- } else {
- pa_log_debug("Not-predefined device");
- handle_not_predefined_device(dm, sink, PA_DEVICE_TYPE_SINK, device_class);
+ PA_HASHMAP_FOREACH_KEY(device_string, type_info->playback_devices, state, role) {
+ sink = _core_get_sink(dm->core, device_string, NULL);
+ if (sink)
+ pa_tz_profile_new_data_add_sink(data, role, sink);
+ else
+ pa_log_error("Failed to get matching sink for %s %s", role, device_string);
}
- dump_device_list_info(dm, PA_LOG_INFO);
- return PA_HOOK_OK;
+ return 0;
}
-static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, pa_device_manager *dm) {
- pa_assert(c);
- pa_assert(sink);
- pa_assert(sink->proplist);
- pa_assert(dm);
+static int _fill_profile_new_data_sources(pa_tz_profile_new_data *data, struct device_type_info *type_info, pa_device_manager *dm) {
+ pa_source *source;
+ char *device_string, *role;
+ void *state;
- if (pulse_device_class_is_monitor(sink->proplist)) {
- pa_log_debug("This device's class is monitor. Skip this");
- return PA_HOOK_OK;
+ pa_assert(data);
+ pa_assert(type_info);
+
+ if (type_info->capture_devices == NULL) {
+ pa_log_error("No capture devices for %s %s", type_info->type, pa_strempty(type_info->profile));
+ return -1;
}
- pa_log_info("=========== Sink unlink Hook Callback '%s'(%d) ==========", sink->name, sink->index);
- handle_sink_unloaded(sink, dm);
- dump_device_list_info(dm, PA_LOG_INFO);
- return PA_HOOK_OK;
+ PA_HASHMAP_FOREACH_KEY(device_string, type_info->capture_devices, state, role) {
+ source = _core_get_source(dm->core, device_string, NULL);
+ if (source)
+ pa_tz_profile_new_data_add_source(data, role, source);
+ else
+ pa_log_error("Failed to get matching source for %s %s", role, device_string);
+ }
+
+ return 0;
}
-static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, pa_device_manager *dm) {
- dm_device *device_item;
- dm_device *_device_item;
- bool use_internal_codec = false;
- uint32_t idx = 0;
+static int _load_type_devices(struct device_type_info *type_info, bool is_playback, pa_device_manager *dm) {
+ pa_hashmap *pcm_devices;
+ pa_idxset *file_infos;
+ void *state = NULL;
+ char *role;
+ const char *device_string, *params;
- pa_assert(c);
- pa_object_assert_ref(o);
pa_assert(dm);
+ pa_assert(type_info);
- if (pa_sink_isinstance(o)) {
- pa_sink *s = PA_SINK(o);
- pa_sink_state_t state = pa_sink_get_state(s);
- pa_log_debug("=========== Sink(%p,%s) state has been changed to [%d](0:RUNNING, 1:IDLE, 2:SUSPEND) ==========", s, s->name, state);
- if (s->use_internal_codec) {
- if (state == PA_SINK_SUSPENDED) {
- PA_IDXSET_FOREACH(_device_item, dm->device_list, idx) {
- use_internal_codec = pa_device_manager_is_device_use_internal_codec(_device_item, DM_DEVICE_DIRECTION_OUT, DEVICE_ROLE_NORMAL);
- if (use_internal_codec)
- pa_device_manager_set_device_state(_device_item, DM_DEVICE_DIRECTION_OUT, DM_DEVICE_STATE_DEACTIVATED);
- }
- }
- } else {
- if ((device_item = pa_device_manager_get_device_with_sink(s))) {
- if (state == PA_SINK_RUNNING)
- pa_device_manager_set_device_state(device_item, DM_DEVICE_DIRECTION_OUT, DM_DEVICE_STATE_ACTIVATED);
- else if (state == PA_SINK_SUSPENDED)
- pa_device_manager_set_device_state(device_item, DM_DEVICE_DIRECTION_OUT, DM_DEVICE_STATE_DEACTIVATED);
- }
+ pa_log_info("Load type devices : %s %s %s", type_info->type, pa_strempty(type_info->profile),
+ is_playback ? "playback" : "capture");
+
+ if (is_playback) {
+ pcm_devices = type_info->playback_devices;
+ file_infos = dm->file_map->playback;
+ } else {
+ pcm_devices = type_info->capture_devices;
+ file_infos = dm->file_map->capture;
+ }
+
+ if (!pcm_devices || !file_infos) {
+ pa_log_error("No information to load");
+ return -1;
+ }
+
+ PA_HASHMAP_FOREACH_KEY(device_string, pcm_devices, state, role) {
+ params = _file_infos_get_param(file_infos, device_string, role);
+ /* Check duplicate load */
+ if (is_playback && _core_get_sink(dm->core, device_string, params)) {
+ pa_log_debug("Already loaded %s %s", device_string, params);
+ continue;
}
- } else if (pa_source_isinstance(o)) {
- pa_source *s = PA_SOURCE(o);
- pa_source_state_t state = pa_source_get_state(s);
- pa_log_debug("=========== Source(%p,%s) state has been changed to [%d](0:RUNNING, 1:IDLE, 2:SUSPEND) ==========", s, s->name, state);
- if (s->use_internal_codec) {
- if (state == PA_SOURCE_SUSPENDED) {
- PA_IDXSET_FOREACH(_device_item, dm->device_list, idx) {
- use_internal_codec = pa_device_manager_is_device_use_internal_codec(_device_item, DM_DEVICE_DIRECTION_IN, DEVICE_ROLE_NORMAL);
- if (use_internal_codec)
- pa_device_manager_set_device_state(_device_item, DM_DEVICE_DIRECTION_IN, DM_DEVICE_STATE_DEACTIVATED);
- }
- }
- } else {
- if ((device_item = pa_device_manager_get_device_with_source(s))) {
- if (state == PA_SOURCE_RUNNING)
- pa_device_manager_set_device_state(device_item, DM_DEVICE_DIRECTION_IN, DM_DEVICE_STATE_ACTIVATED);
- else if (state == PA_SOURCE_SUSPENDED)
- pa_device_manager_set_device_state(device_item, DM_DEVICE_DIRECTION_IN, DM_DEVICE_STATE_DEACTIVATED);
- }
+ if (!is_playback && _core_get_source(dm->core, device_string, params)) {
+ pa_log_debug("Already loaded %s %s", device_string, params);
+ continue;
+ }
+ if (!(load_device(dm->core, is_playback, device_string, params))) {
+ pa_log_warn("load device failed %s %s", device_string, params);
}
}
- return PA_HOOK_OK;
+ return 0;
}
-static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, pa_device_manager *dm) {
- const char *device_string = NULL, *role = NULL, *device_string_removed_params = NULL;
- struct device_file_info *file_info = NULL;
- dm_device_class_t device_class;
+/*
+ Handle device connection detected through dbus.
+ First, update device-status hashmap.
+ And if correnspondent sink/sources for device_type exist, should make device and notify it.
+ Use [device_type->roles] mappings in sink/source for find proper sink/source.
+*/
+static void handle_device_connected(pa_device_manager *dm, const char *type, const char *device_profile,
+ const char *name, const char *system_id, device_detected_type_t detected_type) {
+ struct device_type_info *type_info;
+ pa_tz_device *device;
+ pa_tz_device_new_data data;
- pa_assert(c);
- pa_assert(source);
- pa_assert(source->proplist);
pa_assert(dm);
+ pa_assert(dm->device_status);
+ pa_assert(dm->device_list);
- if (pulse_device_class_is_monitor(source->proplist)) {
- pa_log_debug("This device's class is monitor. Skip this");
- return PA_HOOK_OK;
- }
+ pa_log_info("Device connected, type(%s) profile(%s) name(%s) system_id(%s) detected_type(%d)",
+ type, pa_strempty(device_profile), pa_strempty(name), pa_strempty(system_id), detected_type);
- pa_log_info("========== Source Put Hook Callback '%s'(%d) ==========", source->name, source->index);
+ type_info = _device_manager_get_type_info(dm->type_infos, type, device_profile);
+ if (device_type_is_equal(type, device_profile, DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO)) {
+ pa_tz_profile_new_data profile_data;
- device_class = pulse_device_get_class(source, PA_DEVICE_TYPE_SOURCE);
- pa_log_info("Device Class '%s'", device_class_to_string(device_class));
+ /* Use profile_new_data, because BT is multi profile type */
+ pa_tz_profile_new_data_init(&profile_data);
+ _fill_profile_new_data_basic(&profile_data, DEVICE_PROFILE_BT_SCO,
+ DM_DEVICE_DIRECTION_BOTH, true, dm);
- if (!(device_string = pulse_device_get_device_string(source, PA_DEVICE_TYPE_SOURCE))) {
- return PA_HOOK_OK;
- } else {
- pa_log_info("Device String '%s'", device_string);
- }
+ _fill_profile_new_data_sinks(&profile_data, type_info, dm);
+ _fill_profile_new_data_sources(&profile_data, type_info, dm);
- if (device_class == DM_DEVICE_CLASS_BT) {
- handle_not_predefined_device(dm, source, PA_DEVICE_TYPE_SOURCE, device_class);
- } else if ((file_info = _device_manager_get_file_info(dm->file_map->capture, device_string))) {
- /* module's argument includes device-string(ex. device=hw:0,0 ),
- but key params for device_types hashmap is not. */
- if (!(device_string_removed_params = pulse_device_get_device_string_removed_argument(source, PA_DEVICE_TYPE_SOURCE))) {
- pa_log_debug("argument null");
- return PA_HOOK_OK;
- }
- if (!(role = device_file_info_get_role_with_params(file_info, device_string_removed_params))) {
- pa_log_error("No role for %s", file_info->device_string);
- return PA_HOOK_OK;
+ device = _device_list_get_device(dm, DEVICE_TYPE_BT, system_id);
+ if (device) {
+ /* Just add profile, if already exists */
+ pa_tz_device_add_profile(device, &profile_data, false);
+ } else {
+ /* Create new device with profile */
+
+ pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, dm->dbus_conn);
+ pa_tz_device_new_data_set_type(&data, DEVICE_TYPE_BT);
+ pa_tz_device_new_data_set_name(&data, name);
+ pa_tz_device_new_data_set_system_id(&data, system_id);
+ pa_tz_device_new_data_add_profile(&data, &profile_data, true);
+
+ pa_tz_device_new(&data);
+ pa_tz_device_new_data_done(&data);
}
+ pa_tz_profile_new_data_done(&profile_data);
+ } else if (device_type_is_equal(type, device_profile, DEVICE_TYPE_AUDIO_JACK, NULL)) {
+ dm_device_direction_t direction;
- handle_predefined_device_loaded(source, PA_DEVICE_TYPE_SOURCE, device_class, device_string, role, dm);
- } else {
- pa_log_debug("Not-predefined device");
- handle_not_predefined_device(dm, source, PA_DEVICE_TYPE_SOURCE, device_class);
- }
+ if (detected_type == DEVICE_CONNECTED_AUDIO_JACK_4P)
+ direction = DM_DEVICE_DIRECTION_BOTH;
+ else
+ direction = DM_DEVICE_DIRECTION_OUT;
+ pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL);
+ _fill_new_data_basic(&data, DEVICE_TYPE_AUDIO_JACK, direction, true, dm);
+ _fill_new_data_sinks(&data, type_info, dm);
+ _fill_new_data_sources(&data, type_info, dm);
+
+ pa_tz_device_new(&data);
+ pa_tz_device_new_data_done(&data);
+ } else if (device_type_is_equal(type, device_profile, DEVICE_TYPE_HDMI, NULL)) {
+ pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL);
+ _fill_new_data_basic(&data, DEVICE_TYPE_HDMI, DM_DEVICE_DIRECTION_OUT, true, dm);
+ _fill_new_data_sinks(&data, type_info, dm);
+
+ pa_tz_device_new(&data);
+ pa_tz_device_new_data_done(&data);
+ } else if (device_type_is_equal(type, device_profile, DEVICE_TYPE_FORWARDING, NULL)) {
+ pa_tz_device *spk_device;
+ pa_sink *spk_sink;
- dump_device_list_info(dm, PA_LOG_INFO);
- return PA_HOOK_OK;
-}
+ if (!(spk_device = _device_list_get_device(dm, DEVICE_TYPE_SPEAKER, NULL))) {
+ pa_log_error("Get speaker device failed");
+ return;
+ }
+ if (!(spk_sink = pa_tz_device_get_sink(spk_device, DEVICE_ROLE_NORMAL))) {
+ pa_log_error("Get speaker sink failed");
+ return;
+ }
-static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, pa_device_manager *dm) {
- pa_assert(c);
- pa_assert(source);
- pa_assert(source->proplist);
- pa_assert(dm);
+ pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL);
+ _fill_new_data_basic(&data, DEVICE_TYPE_FORWARDING, DM_DEVICE_DIRECTION_BOTH, true, dm);
+ pa_tz_device_new_data_add_sink(&data, DEVICE_ROLE_NORMAL, spk_sink);
+ pa_tz_device_new_data_add_source(&data, DEVICE_ROLE_NORMAL, spk_sink->monitor_source);
- if (pulse_device_class_is_monitor(source->proplist)) {
- pa_log_debug("This device's class is monitor. Skip this");
- return PA_HOOK_OK;
+ pa_tz_device_new(&data);
+ pa_tz_device_new_data_done(&data);
+ } else {
+ dm_device_direction_t direction;
+
+ direction = device_type_get_static_direction(type, device_profile);
+ if (direction != DM_DEVICE_DIRECTION_NONE) {
+ pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL);
+ _fill_new_data_basic(&data, type, direction, true, dm);
+ if (direction & DM_DEVICE_DIRECTION_OUT)
+ _fill_new_data_sinks(&data, type_info, dm);
+ if (direction & DM_DEVICE_DIRECTION_IN)
+ _fill_new_data_sources(&data, type_info, dm);
+
+ pa_tz_device_new(&data);
+ pa_tz_device_new_data_done(&data);
+ } else {
+ pa_log_error("Invalid case : not static direction");
+ return ;
+ }
}
- pa_log_info("========== Source unlink Hook Callback '%s'(%d) ==========", source->name, source->index);
- handle_source_unloaded(source, dm);
- dump_device_list_info(dm, PA_LOG_INFO);
-
- return PA_HOOK_OK;
+ return ;
}
/*
- Build params for load sink or source, and load it.
+ Handle device disconnection detected through dbus.
+ First, update device-status hashmap.
+ And if there is device which has the device_type, remove it.
*/
+static int handle_device_disconnected(pa_device_manager *dm, const char *type, const char *device_profile, const char *system_id) {
+ pa_tz_device *device;
+ uint32_t n_profile;
-static void* load_device(pa_core *c, pa_device_type_t pdt, const char *device_string, const char *device_params) {
- const char *args = NULL;
- const char *module_name;
- pa_module *module;
- pa_sink *sink;
- pa_source *source;
- uint32_t device_idx;
- dm_device_class_t device_class;
-
- pa_assert(c);
- pa_assert(device_string);
- pa_assert(device_params);
-
- pa_log_info("Load %s Device : String'%s' Param'%s'", pdt == PA_DEVICE_TYPE_SINK ? "Playback" : "Capture", device_string, device_params);
+ pa_assert(dm);
+ pa_assert(dm->device_status);
- device_class = device_string_get_class(device_string);
- if (device_class <= DM_DEVICE_CLASS_NONE || device_class >= DM_DEVICE_CLASS_MAX) {
- pa_log_warn("Invalid device_string '%s'", device_string);
- return NULL;
- }
+ pa_log_info("Device type(%s) profile(%s) system_id(%s) disconnected",
+ type, pa_strempty(device_profile), pa_strempty(system_id));
- if (!(module_name = device_class_get_module_name(device_class, pdt))) {
- pa_log_error("Get proper module name to load failed");
- return NULL;
- }
- if (!(args = build_params_to_load_device(device_string, device_params, device_class))) {
- pa_log_error("Get proper module name to load failed");
- return NULL;
- }
- if (!(module = pa_module_load(c, module_name, args))) {
- pa_log_error("Load module with name '%s' argu '%s' failed", module_name, args);
- return NULL;
+ device = _device_list_get_device(dm, type, system_id);
+ if (!device) {
+ pa_log_error("Disconnection detected but no device for that");
+ return -1;
}
+ if ((n_profile = pa_tz_device_get_profile_num(device)) > 1)
+ pa_tz_device_remove_profile(device, device_profile);
+ else
+ pa_tz_device_free(device);
- if (pdt == PA_DEVICE_TYPE_SINK) {
- PA_IDXSET_FOREACH(sink, c->sinks, device_idx) {
- if (sink->module == module) {
- return sink;
- }
- }
- } else {
- PA_IDXSET_FOREACH(source, c->sources, device_idx) {
- if (source->module == module) {
- return source;
- }
- }
- }
-
- return NULL;
+ return 0;
}
-/*
- Load sink/sources with information written in device-file map,
- If there is several roles in same device-file, then first load with 'normal' params
- and other roles with same params just reference it. if there is a role which is on same device
- but have different params, then do not load it. (ex.uhqa)
- This does not make device_item , just load sink or source.
-*/
static int load_builtin_devices(pa_device_manager *dm) {
- void *role_state = NULL;
- struct device_file_info *file_info = NULL;
- const char *params, *role;
- uint32_t file_idx;
+ struct device_type_info *type_info;
+ uint32_t type_idx;
+ device_detected_type_t detected_type = DEVICE_CONNECTED;
+ const char *type, *profile;
pa_assert(dm);
pa_log_debug("\n==================== Load Builtin Devices ====================");
- if (dm->file_map->playback) {
- PA_IDXSET_FOREACH(file_info, dm->file_map->playback, file_idx) {
- pa_log_debug("---------------- load sink for '%s' ------------------", file_info->device_string);
+ PA_IDXSET_FOREACH(type_info, dm->type_infos, type_idx) {
- /* if normal device exists , load first */
- if ((params = pa_hashmap_get(file_info->roles, DEVICE_ROLE_NORMAL))) {
- if (!load_device(dm->core, PA_DEVICE_TYPE_SINK, file_info->device_string, params))
- pa_log_error("load normal playback device failed");
- }
+ type = type_info->type;
+ profile = type_info->profile;
- PA_HASHMAP_FOREACH_KEY(params, file_info->roles, role_state, role) {
- if (pa_streq(role, DEVICE_ROLE_NORMAL))
- continue;
- pa_log_debug("load sink for role %s", role);
- if (!pulse_device_loaded_with_param(dm->core, PA_DEVICE_TYPE_SINK, file_info->device_string, params)) {
- if (!load_device(dm->core, PA_DEVICE_TYPE_SINK, file_info->device_string, params))
- pa_log_error("load playback device failed");
- }
- }
+ pa_log_info("type_info : %s %s", type, pa_strempty(profile));
+ detected_type = _device_get_detected(dm, type, profile, NULL);
+ if (detected_type == DEVICE_DISCONNECTED) {
+ pa_log_info("Not detected yet");
+ continue;
}
- }
-
- if (dm->file_map->capture) {
- PA_IDXSET_FOREACH(file_info, dm->file_map->capture, file_idx) {
- pa_log_debug("---------------- load source for '%s' ------------------", file_info->device_string);
- /* if normal device exists , load first */
- if ((params = pa_hashmap_get(file_info->roles, DEVICE_ROLE_NORMAL))) {
- if (!load_device(dm->core, PA_DEVICE_TYPE_SOURCE, file_info->device_string, params)) pa_log_error("load normal capture device failed");
+ if (device_type_is_equal(type, profile, DEVICE_TYPE_AUDIO_JACK, NULL)) {
+ if (detected_type == DEVICE_CONNECTED_AUDIO_JACK_4P) {
+ _load_type_devices(type_info, true, dm);
+ _load_type_devices(type_info, false, dm);
+ } else {
+ _load_type_devices(type_info, true, dm);
}
-
- PA_HASHMAP_FOREACH_KEY(params, file_info->roles, role_state, role) {
- if (pa_streq(role, DEVICE_ROLE_NORMAL))
- continue;
- pa_log_debug("load source for role %s", role);
- if (!pulse_device_loaded_with_param(dm->core, PA_DEVICE_TYPE_SOURCE, file_info->device_string, params)) {
- if (!load_device(dm->core, PA_DEVICE_TYPE_SOURCE, file_info->device_string, params)) {
- pa_log_error("load capture device failed");
- }
- }
+ handle_device_connected(dm, type, profile, NULL, NULL, detected_type);
+ } else if (device_type_is_use_external_card(type, profile) == false) {
+ dm_device_direction_t direction;
+ direction = device_type_get_static_direction(type, profile);
+ if (direction == DM_DEVICE_DIRECTION_NONE) {
+ pa_log_warn("Wrong direction");
+ continue;
}
+ if (direction & DM_DEVICE_DIRECTION_OUT)
+ _load_type_devices(type_info, true, dm);
+ if (direction & DM_DEVICE_DIRECTION_IN)
+ _load_type_devices(type_info, false, dm);
+ handle_device_connected(dm, type, profile, NULL, NULL, detected_type);
+ } else {
+ pa_log_warn("Invalid case");
}
}
return 0;
}
-
/***************** Parse json file *******************/
static pa_hashmap* parse_device_role_object(json_object *device_role_o) {
pa_hashmap *roles = NULL;
roles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
if (!roles) {
pa_log_debug("hashmap new failed");
- goto failed;
+ goto fail;
}
it = json_object_iter_begin(device_role_o);
if (device_role_is_valid(device_role)) {
if (pa_hashmap_put(roles, (void *)device_role, (void *)params)) {
pa_log_error("put new role to hashmap faild");
- goto failed;
+ goto fail;
}
} else {
pa_log_error("Invalid device role '%s'", device_role);
return roles;
-failed:
+fail:
if (roles)
pa_hashmap_free(roles);
if (json_object_object_get_ex(device_file_o, DEVICE_TYPE_PROP_ROLE, &device_file_prop_o)) {
if (!(roles = parse_device_role_object(device_file_prop_o))) {
pa_log_error("Parse device role for '%s' failed", device_string);
- goto failed;
+ goto fail;
}
} else {
pa_log_error("Get device role object failed");
return file_info;
-failed:
+fail:
return NULL;
}
pa_idxset_put(device_files, file_info, NULL);
} else {
pa_log_error("parse device file object failed");
- goto failed;
+ goto fail;
}
} else {
pa_log_error("Get device file object failed");
- goto failed;
+ goto fail;
}
}
pa_idxset_free(device_files, NULL);
device_files = NULL;
}
+
return device_files;
-failed:
+
+fail:
if (device_files)
pa_xfree(device_files);
return NULL;
if (device_role_is_valid(device_role)) {
if (pa_hashmap_put(roles, (void *)device_role, (void *)device_string)) {
pa_log_error("put new role to hashmap faild");
- goto failed;
+ goto fail;
}
} else {
pa_log_error("Invalid device role '%s'", device_role);
- goto failed;
+ goto fail;
}
json_object_iter_next(&it);
return roles;
-failed:
+fail:
if (roles)
pa_xfree(roles);
json_object *o, *device_array_o = NULL;
int device_type_num = 0;
int device_type_idx = 0;
- json_bool builtin;
struct device_type_info *type_info = NULL;
//pa_hashmap *type_infos = NULL;
pa_idxset *type_infos = NULL;
if ((device_o = json_object_array_get_idx(device_array_o, device_type_idx)) && json_object_is_type(device_o, json_type_object)) {
json_object *device_prop_o;
- const char *device_type = NULL, *device_profile = NULL;
+ const char *type = NULL, *device_profile = NULL;
type_info = pa_xmalloc0(sizeof(struct device_type_info));
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)) {
- device_type = json_object_get_string(device_prop_o);
- pa_log_info("[ Device - %s ]", device_type);
- type_info->type = device_type;
+ type = json_object_get_string(device_prop_o);
+ pa_log_info("[ Device - %s ]", type);
+ type_info->type = type;
} else {
pa_log_error("Get device type failed");
- goto failed;
+ goto fail;
}
if (json_object_object_get_ex(device_o, "profile", &device_prop_o) && json_object_is_type(device_prop_o, json_type_string)) {
device_profile = json_object_get_string(device_prop_o);
}
return type_infos;
-failed:
+fail:
if (type_infos)
pa_xfree(type_infos);
}
/*
- Handle device connection detected through dbus.
- First, update device-status hashmap.
- And if correnspondent sink/sources for device_type exist, should make device_item and notify it.
- Use [device_type->roles] mappings in sink/source for find proper sink/source.
-*/
-static int handle_device_connected(pa_device_manager *dm, const char *device_type, const char *device_profile, const char *name, const char *identifier, int detected_type) {
- struct device_status_info *status_info;
- struct device_type_info *type_info;
- dm_device *device_item;
- dm_device_profile *profile_item;
-
- pa_assert(dm);
- pa_assert(dm->device_status);
-
- pa_log_info("Device %s connected, detected_type : %d", device_type, detected_type);
- if (!(status_info = _device_manager_get_status_info(dm->device_status, device_type, device_profile, identifier))) {
- pa_log_error("No device_status_info for %s.%s", device_type, device_profile);
- return -1;
- }
- status_info->detected = DEVICE_DETECTED;
- status_info->detected_type = detected_type;
-
- if (!(type_info = _device_manager_get_type_info(dm->type_infos, device_type, device_profile))) {
- pa_log_error("Failed to get type_info for %s.%s", device_type, device_profile);
- return -1;
- }
-
- if ((device_item = _device_manager_get_device(dm->device_list, type_info->type))) {
- if ((profile_item = _device_item_get_profile(device_item, type_info->profile))) {
- pa_log_debug("device_item for %s.%s already exists", type_info->type, type_info->profile);
- return 0;
- }
- }
-
- handle_device_type_available(type_info, name, dm);
-
- return 0;
-}
-
-/*
- Handle device disconnection detected through dbus.
- First, update device-status hashmap.
- And if there is device_item which has the device_type, remove it.
-*/
-static int handle_device_disconnected(pa_device_manager *dm, const char *device_type, const char *device_profile, const char *identifier) {
- dm_device_profile *profile_item;
- dm_device *device_item;
- struct device_status_info *status_info;
- uint32_t device_idx = 0;
-
- pa_assert(dm);
- pa_assert(dm->device_status);
-
- pa_log_info("Device %s disconnected", device_type);
- if (!(status_info = _device_manager_get_status_info(dm->device_status, device_type, device_profile, identifier))) {
- pa_log_error("No device_status_info for %s.%s", device_type, device_profile);
- return -1;
- }
- status_info->detected = DEVICE_NOT_DETECTED;
-
- PA_IDXSET_FOREACH(device_item, dm->device_list, device_idx) {
- if (pa_streq(device_item->type, device_type)) {
- if ((profile_item = _device_item_get_profile(device_item, device_profile))) {
- if (_device_item_get_size(device_item) == 1) {
- _device_list_remove_device(dm->device_list, device_item, dm);
- notify_device_connection_changed(device_item, false, dm);
- }
- destroy_device_profile(profile_item, dm);
- } else {
- pa_log_debug("no matching profile");
- }
- }
- }
-
- return 0;
-}
-
-
-/*
look detected status which is external value, make conversion to internal consistent value, and handle it
device_type, device_profile : which type of device is detected
- identifier : identifier among same device types for support multi-device
+ system_id : system_id among same device types for support multi-device
*/
-static int handle_device_status_changed(pa_device_manager *dm, const char *device_type, const char *device_profile, const char *name, const char *identifier, int detected_status) {
+static int handle_device_status_changed(pa_device_manager *dm, const char *type,
+ const char *profile, const char *name, const char *system_id, device_detected_type_t detected) {
pa_assert(dm);
- pa_assert(device_type_is_valid(device_type));
-
- pa_log_info("Device Status Changed, type : '%s', profile : '%s', identifier : '%s', detected_status : %d",
- device_type, device_profile, identifier, detected_status);
- if (pa_streq(device_type, DEVICE_TYPE_AUDIO_JACK)) {
- if (detected_status == EARJACK_DISCONNECTED) {
- handle_device_disconnected(dm, device_type, device_profile, identifier);
- } else if (detected_status == EARJACK_TYPE_SPK_ONLY) {
- handle_device_connected(dm, device_type, device_profile, name, identifier, DEVICE_DETECTED_AUDIO_JACK_OUT_DIREC);
- } else if (detected_status == EARJACK_TYPE_SPK_WITH_MIC) {
- handle_device_connected(dm, device_type, device_profile, name, identifier, DEVICE_DETECTED_AUDIO_JACK_BOTH_DIREC);
- } else {
- pa_log_warn("Got invalid audio-jack detected value");
- return -1;
- }
- } else if (pa_streq(device_type, DEVICE_TYPE_BT) && device_profile && pa_streq(device_profile, DEVICE_PROFILE_BT_SCO)) {
- if (detected_status == BT_SCO_DISCONNECTED) {
- dm->bt_sco_status = DM_DEVICE_BT_SCO_STATUS_DISCONNECTED;
- } else if (detected_status == BT_SCO_CONNECTED) {
- dm->bt_sco_status = DM_DEVICE_BT_SCO_STATUS_CONNECTED;
- } else {
- pa_log_warn("Got invalid bt-sco detected value");
- return -1;
- }
- } else if (pa_streq(device_type, DEVICE_TYPE_HDMI)) {
- if (detected_status == HDMI_AUDIO_DISCONNECTED) {
- handle_device_disconnected(dm, device_type, device_profile, identifier);
- } else if (detected_status >= HDMI_AUDIO_AVAILABLE) {
- handle_device_connected(dm, device_type, device_profile, name, identifier, DEVICE_DETECTED_HDMI);
- } else if (detected_status == HDMI_AUDIO_NOT_AVAILABLE) {
- pa_log_debug("HDMI audio not available");
- return -1;
- } else {
- pa_log_warn("Got invalid hdmi detected value");
- return -1;
- }
- } else if (pa_streq(device_type, DEVICE_TYPE_FORWARDING)) {
- if (detected_status == FORWARDING_DISCONNECTED) {
- handle_device_disconnected(dm, device_type, device_profile, identifier);
- } else if (detected_status == FORWARDING_CONNECTED) {
- handle_device_connected(dm, device_type, device_profile, name, identifier, DEVICE_DETECTED_FORWARDING);
- } else {
- pa_log_warn("Got invalid mirroring detected value");
- return -1;
- }
+ pa_assert(device_type_is_valid(type));
+
+ pa_log_info("Device Status Changed, type(%s) profile(%s) system_id(%s), detected_type(%d)",
+ type, pa_strempty(profile), pa_strempty(system_id), detected);
+
+ if (device_type_is_equal(type, profile, DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO)) {
+ _device_set_detected(dm, type, profile, name, system_id, detected);
+ if (detected == DEVICE_DISCONNECTED)
+ handle_device_disconnected(dm, type, profile, system_id);
+ else
+ handle_device_connected(dm, type, profile, name, system_id, detected);
+ } else if (device_type_is_need_detect(type, profile)) {
+ _device_set_detected(dm, type, profile, name, system_id, detected);
+ if (detected == DEVICE_DISCONNECTED)
+ handle_device_disconnected(dm, type, profile, system_id);
+ else
+ handle_device_connected(dm, type, profile, name, system_id, detected);
} else {
- pa_log_debug("unknown device type");
+ pa_log_debug("No need to detect type %s %s", type, pa_strempty(profile));
}
+
return 0;
}
So, if device_type is not detected through dbus, let's initialize them to detected. (ex. spk, rcv,...)
If not, initialize to not detected.
*/
-static pa_idxset* device_type_status_init(pa_idxset *type_infos) {
- int avail_cond_idx = 0, avail_cond_num = 0, correct_avail_cond = 0;
+static void device_type_status_init(pa_device_manager *manager) {
struct device_type_info *type_info;
- struct device_status_info *status_info;
- pa_idxset *device_status;
uint32_t type_idx;
+ const char *type, *profile;
- pa_assert(type_infos);
+ pa_assert(manager);
+ pa_assert(manager->type_infos);
pa_log_debug("\n==================== Init Device Status ====================");
- device_status = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
-
- PA_IDXSET_FOREACH(type_info, type_infos, type_idx) {
- status_info = (struct device_status_info *) pa_xmalloc0(sizeof(struct device_status_info));
- status_info->type = type_info->type;
- status_info->profile = type_info->profile;
- if (!compare_device_type(status_info->type, status_info->profile, DEVICE_TYPE_AUDIO_JACK, NULL)) {
+ PA_IDXSET_FOREACH(type_info, manager->type_infos, type_idx) {
+ type = type_info->type;
+ profile = type_info->profile;
+ if (device_type_is_equal(type, profile, DEVICE_TYPE_AUDIO_JACK, NULL)) {
int earjack_status = 0;
if (vconf_get_int(VCONFKEY_SYSMAN_EARJACK, &earjack_status) < 0) {
- status_info->detected = DEVICE_NOT_DETECTED;
pa_log_error("Get earjack status failed");
- } else if (earjack_status == EARJACK_DISCONNECTED) {
- status_info->detected = DEVICE_NOT_DETECTED;
- } else if (earjack_status == EARJACK_TYPE_SPK_ONLY) {
- status_info->detected = DEVICE_DETECTED;
- status_info->detected_type = DEVICE_DETECTED_AUDIO_JACK_OUT_DIREC;
- } else if (earjack_status == EARJACK_TYPE_SPK_WITH_MIC) {
- status_info->detected = DEVICE_DETECTED;
- status_info->detected_type = DEVICE_DETECTED_AUDIO_JACK_BOTH_DIREC;
- } else {
- status_info->detected = DEVICE_NOT_DETECTED;
- pa_log_warn("Unknown earjack status : %d", earjack_status);
+ continue;
}
- } else if (!compare_device_type(status_info->type, status_info->profile, DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO)) {
- status_info->detected = DEVICE_NOT_DETECTED;
- } else if (!compare_device_type(status_info->type, status_info->profile, DEVICE_TYPE_HDMI, NULL)) {
- status_info->detected = DEVICE_NOT_DETECTED;
- } else if (!compare_device_type(status_info->type, status_info->profile, DEVICE_TYPE_FORWARDING, NULL)) {
+ if (earjack_status == EARJACK_TYPE_SPK_ONLY)
+ _device_set_detected(manager, type, profile, NULL, NULL, DEVICE_CONNECTED_AUDIO_JACK_3P);
+ else if (earjack_status == EARJACK_TYPE_SPK_WITH_MIC)
+ _device_set_detected(manager, type, profile, NULL, NULL, DEVICE_CONNECTED_AUDIO_JACK_4P);
+ else if (earjack_status == EARJACK_DISCONNECTED)
+ _device_set_detected(manager, type, profile, NULL, NULL, DEVICE_DISCONNECTED);
+ else
+ pa_log_warn("Unknown earjack status : %d", earjack_status);
+ } else if (device_type_is_equal(type, profile, DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO)) {
+ _device_set_detected(manager, type, profile, NULL, NULL, DEVICE_DISCONNECTED);
+ } else if (device_type_is_equal(type, profile, DEVICE_TYPE_HDMI, NULL)) {
+ _device_set_detected(manager, type, profile, NULL, NULL, DEVICE_DISCONNECTED);
+ } else if (device_type_is_equal(type, profile, DEVICE_TYPE_FORWARDING, NULL)) {
int miracast_wfd_status = 0;
if (vconf_get_bool(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS, &miracast_wfd_status) < 0) {
- status_info->detected = DEVICE_NOT_DETECTED;
pa_log_error("Get mirroring status failed");
- } else if (miracast_wfd_status == FORWARDING_DISCONNECTED) {
- status_info->detected = DEVICE_NOT_DETECTED;
- } else if (miracast_wfd_status == FORWARDING_CONNECTED) {
- status_info->detected = DEVICE_DETECTED;
- status_info->detected_type = DEVICE_DETECTED_FORWARDING;
- } else {
- status_info->detected = DEVICE_NOT_DETECTED;
- pa_log_warn("Unknown mirroring status : %d", miracast_wfd_status);
+ continue;
}
+ if (miracast_wfd_status == FORWARDING_CONNECTED)
+ _device_set_detected(manager, type, profile, NULL, NULL, DEVICE_CONNECTED);
} else {
- status_info->detected = DEVICE_DETECTED;
+ _device_set_detected(manager, type, profile, NULL, NULL, DEVICE_CONNECTED);
}
-
- pa_log_debug("Set %-17s %s detected", type_info->type, (status_info->detected == DEVICE_DETECTED) ? "" : "not");
- pa_idxset_put(device_status, status_info, NULL);
}
- return device_status;
+ return ;
}
-static int device_list_init(pa_device_manager *dm) {
- pa_assert(dm);
+#ifdef HAVE_DBUS
- dm->device_list = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+static int _translate_external_value(const char *type, const char *profile, int value, device_detected_type_t *detected) {
+
+ if (!type || !detected) {
+ pa_log_error("Invalid Parameter for translate");
+ return -1;
+ }
+
+ if (device_type_is_equal(DEVICE_TYPE_AUDIO_JACK, NULL, type, profile)) {
+ if (value == EARJACK_DISCONNECTED)
+ *detected = DEVICE_DISCONNECTED;
+ else if (value == EARJACK_TYPE_SPK_ONLY)
+ *detected = DEVICE_CONNECTED_AUDIO_JACK_3P;
+ else if (value == EARJACK_TYPE_SPK_WITH_MIC)
+ *detected = DEVICE_CONNECTED_AUDIO_JACK_4P;
+ else
+ return -1;
+ } else if (device_type_is_equal(DEVICE_TYPE_HDMI, NULL, type, profile)) {
+ if (value == HDMI_AUDIO_DISCONNECTED)
+ *detected = DEVICE_DISCONNECTED;
+ else if (value == HDMI_AUDIO_AVAILABLE)
+ *detected = DEVICE_CONNECTED;
+ else
+ return -1;
+ } else if (device_type_is_equal(DEVICE_TYPE_FORWARDING, NULL, type, profile)) {
+ if (value == FORWARDING_DISCONNECTED)
+ *detected = DEVICE_DISCONNECTED;
+ else if (value == FORWARDING_CONNECTED)
+ *detected = DEVICE_CONNECTED;
+ else
+ return -1;
+ } else if (device_type_is_equal(DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO, type, profile)) {
+ if (value == BT_SCO_DISCONNECTED)
+ *detected = DEVICE_DISCONNECTED;
+ else if (value == BT_SCO_CONNECTED)
+ *detected = DEVICE_CONNECTED_SCO;
+ else
+ return -1;
+ }
return 0;
}
-#ifdef HAVE_DBUS
-
static DBusHandlerResult dbus_filter_device_detect_handler(DBusConnection *c, DBusMessage *s, void *userdata) {
DBusError error;
int status = 0;
pa_device_manager *dm = (pa_device_manager *) userdata;
+ device_detected_type_t detected;
pa_assert(userdata);
if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
goto fail;
} else {
- handle_device_status_changed(dm, DEVICE_TYPE_AUDIO_JACK, NULL, NULL, NULL, status);
+ if (_translate_external_value(DEVICE_TYPE_AUDIO_JACK, NULL, status, &detected) < 0) {
+ pa_log_warn("failed to translate audio-jack detected value");
+ goto fail;
+ }
+ handle_device_status_changed(dm, DEVICE_TYPE_AUDIO_JACK, NULL, NULL, NULL, detected);
}
} else if (dbus_message_is_signal(s, DBUS_INTERFACE_DEVICED_SYSNOTI, "ChangedHDMIAudio")) {
if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
goto fail;
} else {
- handle_device_status_changed(dm, DEVICE_TYPE_HDMI, NULL, NULL, NULL, status);
+ if (_translate_external_value(DEVICE_TYPE_HDMI, NULL, status, &detected) < 0) {
+ pa_log_warn("failed to translate HDMI detected value");
+ goto fail;
+ }
+ handle_device_status_changed(dm, DEVICE_TYPE_HDMI, NULL, NULL, NULL, detected);
}
} else if (dbus_message_is_signal(s, DBUS_INTERFACE_MIRRORING_SERVER, "miracast_wfd_source_status_changed")) {
if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
goto fail;
} else {
- handle_device_status_changed(dm, DEVICE_TYPE_FORWARDING, NULL, NULL, NULL, status);
+ if (_translate_external_value(DEVICE_TYPE_FORWARDING, NULL, status, &detected) < 0) {
+ pa_log_warn("failed to translate forwarding detected value");
+ goto fail;
+ }
+ handle_device_status_changed(dm, DEVICE_TYPE_FORWARDING, NULL, NULL, NULL, detected);
}
} else if (dbus_message_is_signal(s, DBUS_INTERFACE_BLUEZ_HEADSET, "PropertyChanged")) {
DBusMessageIter msg_iter, variant_iter;
} else {
status = BT_SCO_DISCONNECTED;
}
- handle_device_status_changed(dm, DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO, name, NULL, status);
+ if (_translate_external_value(DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO, status, &detected) < 0) {
+ pa_log_warn("failed to translate bt-sco detected value");
+ goto fail;
+ }
+ handle_device_status_changed(dm, DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO,
+ name, dbus_message_get_path(s), detected);
}
}
} else {
}
-static void send_device_connected_signal(uint32_t event_id, dm_device *device_item, bool connected, pa_device_manager *dm) {
+static void send_device_connected_signal(uint32_t event_id, pa_tz_device *device, bool connected, pa_device_manager *dm) {
DBusMessage *signal_msg;
DBusMessageIter msg_iter, device_iter;
- dm_device_profile *profile_item;
dbus_bool_t _connected = connected;
dm_device_state_t compound_state;
- dbus_int32_t device_id;
- const char *device_info_str;
+ dbus_int32_t device_id, direction;
+ char *type, *name;
- pa_assert(device_item);
- pa_assert(device_item->profiles);
+ pa_assert(device);
pa_assert(dm);
pa_log_info("Send following device %s signal", connected ? "Connected" : "Disconnected");
- dump_device_info(device_item, PA_LOG_INFO);
pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceConnected"));
dbus_message_iter_init_append(signal_msg, &msg_iter);
dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_UINT32, &event_id);
pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_STRUCT, NULL, &device_iter));
- if (!(profile_item = _device_item_get_active_profile(device_item))) {
- pa_log_error("active profile null");
- goto finish;
- }
- device_id = (dbus_int32_t) device_item->id;
- compound_state = COMPOUND_STATE(profile_item);
+ direction = (dbus_int32_t) pa_tz_device_get_direction(device);
+ type = pa_tz_device_get_type(device);
+ name = pa_tz_device_get_name(device);
+
+ device_id = (dbus_int32_t) pa_tz_device_get_id(device);
+ compound_state = pa_tz_device_get_state(device, DM_DEVICE_DIRECTION_BOTH);
dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &device_id);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &device_item->type);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &profile_item->direction);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &type);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &direction);
dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &compound_state);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &device_item->name);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &name);
pa_assert_se(dbus_message_iter_close_container(&msg_iter, &device_iter));
dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_BOOLEAN, &_connected);
pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
-finish:
+
dbus_message_unref(signal_msg);
}
-static void send_device_info_changed_signal(uint32_t event_id, dm_device *device_item, int changed_type, pa_device_manager *dm) {
+static void send_device_info_changed_signal(uint32_t event_id, pa_tz_device *device, int changed_type, pa_device_manager *dm) {
DBusMessage *signal_msg;
DBusMessageIter msg_iter, device_iter;
- dm_device_profile *profile_item;
dm_device_state_t compound_state;
- dbus_int32_t device_id;
- const char *device_info_str;
+ dbus_int32_t device_id, direction;
+ char *type, *name;
- pa_assert(device_item);
- pa_assert(device_item->profiles);
+ pa_assert(device);
pa_assert(dm);
pa_log_debug("Send following device info changed signal");
- dump_device_info(device_item, PA_LOG_DEBUG);
pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceInfoChanged"));
dbus_message_iter_init_append(signal_msg, &msg_iter);
dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_UINT32, &event_id);
pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_STRUCT, NULL, &device_iter));
- if (!(profile_item = _device_item_get_active_profile(device_item))) {
- pa_log_error("active profile null");
- goto finish;
- }
- device_id = (dbus_int32_t) device_item->id;
- compound_state = COMPOUND_STATE(profile_item);
+
+ direction = (dbus_int32_t) pa_tz_device_get_direction(device);
+ type = pa_tz_device_get_type(device);
+ name = pa_tz_device_get_name(device);
+ device_id = (dbus_int32_t) pa_tz_device_get_id(device);
+ compound_state = pa_tz_device_get_state(device, DM_DEVICE_DIRECTION_BOTH);
+
dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &device_id);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &device_item->type);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &profile_item->direction);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &type);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &direction);
dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &compound_state);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &device_item->name);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &name);
pa_assert_se(dbus_message_iter_close_container(&msg_iter, &device_iter));
dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &changed_type);
pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
-finish:
- dbus_message_unref(signal_msg);
-}
-
-static void notify_device_connection_changed(dm_device *device_item, bool connected, pa_device_manager *dm) {
- pa_device_manager_hook_data_for_conn_changed hook_data;
- uint32_t event_id;
- event_id = _new_event_id();
-
- hook_data.event_id = event_id;
- hook_data.is_connected = connected;
- hook_data.device = device_item;
- pa_log_info("notify_device_connection_changed");
- pa_hook_fire(pa_communicator_hook(dm->comm, PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED), &hook_data);
- send_device_connected_signal(event_id, device_item, connected, dm);
-}
-
-static void notify_device_info_changed(dm_device *device_item, dm_device_changed_info_t changed_type, pa_device_manager *dm) {
- pa_device_manager_hook_data_for_info_changed hook_data;
- uint32_t event_id;
-
- event_id = _new_event_id();
-
- send_device_info_changed_signal(event_id, device_item, changed_type, dm);
-
- hook_data.event_id = event_id;
- hook_data.changed_info = changed_type;
- hook_data.device = device_item;
- pa_hook_fire(pa_communicator_hook(dm->comm, PA_COMMUNICATOR_HOOK_DEVICE_INFORMATION_CHANGED), &hook_data);
+ dbus_message_unref(signal_msg);
}
-static bool device_item_match_for_mask(dm_device *device_item, int device_flags, pa_device_manager *dm) {
- dm_device_profile *profile_item = NULL;
+static bool device_item_match_for_mask(pa_tz_device *device, int device_flags, pa_device_manager *dm) {
bool match = false;
int need_to_check_for_io_direction = device_flags & DEVICE_IO_DIRECTION_FLAGS;
int need_to_check_for_state = device_flags & DEVICE_STATE_FLAGS;
int need_to_check_for_type = device_flags & DEVICE_TYPE_FLAGS;
+ dm_device_direction_t direction;
+ char *type;
- pa_assert(device_item);
+ pa_assert(device);
if (device_flags == DEVICE_ALL_FLAG)
return true;
- profile_item = _device_item_get_active_profile(device_item);
+ direction = pa_tz_device_get_direction(device);
+ type = pa_tz_device_get_type(device);
+
if (need_to_check_for_io_direction) {
- if ((profile_item->direction == DM_DEVICE_DIRECTION_IN) && (device_flags & DEVICE_IO_DIRECTION_IN_FLAG)) match = true;
- else if ((profile_item->direction == DM_DEVICE_DIRECTION_OUT) && (device_flags & DEVICE_IO_DIRECTION_OUT_FLAG)) match = true;
- else if ((profile_item->direction == DM_DEVICE_DIRECTION_BOTH) && (device_flags & DEVICE_IO_DIRECTION_BOTH_FLAG)) match = true;
+ if ((direction == DM_DEVICE_DIRECTION_IN) && (device_flags & DEVICE_IO_DIRECTION_IN_FLAG)) match = true;
+ else if ((direction == DM_DEVICE_DIRECTION_OUT) && (device_flags & DEVICE_IO_DIRECTION_OUT_FLAG)) match = true;
+ else if ((direction == DM_DEVICE_DIRECTION_BOTH) && (device_flags & DEVICE_IO_DIRECTION_BOTH_FLAG)) match = true;
if (match) {
if (!need_to_check_for_state && !need_to_check_for_type) return true;
} else {
}
if (need_to_check_for_state) {
match = false;
- if ((COMPOUND_STATE(profile_item) == DM_DEVICE_STATE_DEACTIVATED) && (device_flags & DEVICE_STATE_DEACTIVATED_FLAG))
+ if ((pa_tz_device_get_state(device, DM_DEVICE_DIRECTION_BOTH) == DM_DEVICE_STATE_DEACTIVATED) && (device_flags & DEVICE_STATE_DEACTIVATED_FLAG))
match = true;
- else if ((COMPOUND_STATE(profile_item) == DM_DEVICE_STATE_ACTIVATED) && (device_flags & DEVICE_STATE_ACTIVATED_FLAG))
+ else if ((pa_tz_device_get_state(device, DM_DEVICE_DIRECTION_BOTH) == DM_DEVICE_STATE_ACTIVATED) && (device_flags & DEVICE_STATE_ACTIVATED_FLAG))
match = true;
if (match) {
if (!need_to_check_for_type)
}
}
if (need_to_check_for_type) {
- if (device_type_is_builtin(device_item->type) && (device_flags & DEVICE_TYPE_INTERNAL_FLAG))
+ if (device_type_is_builtin(type) && (device_flags & DEVICE_TYPE_INTERNAL_FLAG))
return true;
- else if (!device_type_is_builtin(device_item->type) && (device_flags & DEVICE_TYPE_EXTERNAL_FLAG))
+ else if (!device_type_is_builtin(type) && (device_flags & DEVICE_TYPE_EXTERNAL_FLAG))
return true;
}
return false;
}
-
-static int method_call_bt_sco(DBusConnection *conn, bool onoff) {
- DBusMessage *msg, *reply;
- DBusError err;
- const char *method;
-
- method = onoff ? "Play" : "Stop";
- if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_HFP_AGENT, DBUS_OBJECT_HFP_AGENT, DBUS_INTERFACE_HFP_AGENT, method))) {
- pa_log_error("dbus method call failed");
- return -1;
- }
-
- dbus_error_init(&err);
- if (!(reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err))) {
- pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_HFP_AGENT, method, err.message);
- dbus_error_free(&err);
- return -1;
- }
-
- dbus_message_unref(reply);
- return 0;
-}
-
-static int method_call_bt_sco_get_property(DBusConnection *conn, bool *is_wide_band, bool *nrec) {
- DBusMessage *msg, *reply;
- DBusMessageIter reply_iter, reply_iter_entry;
- DBusError err;
- unsigned int codec;
- const char *property;
-
- pa_assert(conn);
-
- if (!is_wide_band && !nrec) {
- return -1;
- }
-
- if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_HFP_AGENT, DBUS_OBJECT_HFP_AGENT, DBUS_INTERFACE_HFP_AGENT, "GetProperties"))) {
- pa_log_error("dbus method call failed");
- return -1;
- }
-
- dbus_error_init(&err);
- if (!(reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err))) {
- pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_HFP_AGENT, "GetProperties", err.message);
- dbus_error_free(&err);
- return -1;
- }
-
- dbus_message_iter_init(reply, &reply_iter);
-
- if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
- pa_log_error("Cannot get reply argument");
- return -1;
- }
-
- dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
-
- while (dbus_message_iter_get_arg_type(&reply_iter_entry) == DBUS_TYPE_DICT_ENTRY) {
- DBusMessageIter dict_entry, dict_entry_val;
- dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
- dbus_message_iter_get_basic(&dict_entry, &property);
- pa_log_debug("String received = %s", property);
- if (property) {
- if (pa_streq("codec", property) && is_wide_band) {
- dbus_message_iter_next(&dict_entry);
- dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
- if (dbus_message_iter_get_arg_type(&dict_entry_val) != DBUS_TYPE_UINT32)
- continue;
- dbus_message_iter_get_basic(&dict_entry_val, &codec);
- pa_log_debug("Codec = [%d]", codec);
- *is_wide_band = (codec == BT_MSBC_CODEC_ID) ? true : false;
- } else if (pa_streq("nrec", property) && nrec) {
- dbus_message_iter_next(&dict_entry);
- dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
- if (dbus_message_iter_get_arg_type(&dict_entry_val) != DBUS_TYPE_BOOLEAN)
- continue;
- dbus_message_iter_get_basic(&dict_entry_val, nrec);
- pa_log_debug("nrec= [%d]", *nrec);
- }
- }
- dbus_message_iter_next(&reply_iter_entry);
- }
-
-
- dbus_message_unref(reply);
- return 0;
-}
-
-
static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name) {
const char *intf = DBUS_INTERFACE_BLUEZ_DEVICE, *prop = "Alias";
DBusMessage *msg, *reply;
pa_device_manager *dm;
DBusMessage *reply = NULL;
DBusMessageIter msg_iter, array_iter, device_iter;
- dm_device *device_item;
- dm_device_profile *profile_item;
+ pa_tz_device *device;
dm_device_state_t compound_state;
uint32_t device_idx;
- dbus_int32_t device_id;
+ dbus_int32_t device_id, direction;
int mask_flags;
+ char *type, *name;
pa_assert(conn);
pa_assert(msg);
dbus_message_iter_init_append(reply, &msg_iter);
pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(isiis)", &array_iter));
- PA_IDXSET_FOREACH(device_item, dm->device_list, device_idx) {
- if (!(profile_item = pa_idxset_get_by_index(device_item->profiles, device_item->active_profile))) {
- pa_log_error("no active profile");
- continue;
- }
- compound_state = COMPOUND_STATE(profile_item);
- if (device_item_match_for_mask(device_item, mask_flags, dm)) {
- device_id = (dbus_int32_t)device_item->id;
+ PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
+ compound_state = pa_tz_device_get_state(device, DM_DEVICE_DIRECTION_BOTH);
+ direction = pa_tz_device_get_direction(device);
+ type = pa_tz_device_get_type(device);
+ name = pa_tz_device_get_name(device);
+ if (device_item_match_for_mask(device, mask_flags, dm)) {
+ device_id = (dbus_int32_t)pa_tz_device_get_id(device);
pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &device_iter));
dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &device_id);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &profile_item->device_item->type);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &profile_item->direction);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &type);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &direction);
dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &compound_state);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &device_item->name);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &name);
pa_assert_se(dbus_message_iter_close_container(&array_iter, &device_iter));
}
}
static void handle_get_bt_a2dp_status(DBusConnection *conn, DBusMessage *msg, void *userdata) {
pa_device_manager *dm;
DBusMessage *reply = NULL;
- dm_device *device_item;
- dm_device_profile *profile_item;
+ pa_tz_device *device;
dbus_bool_t is_bt_on = false;
const char *bt_name = "none";
pa_assert_se((reply = dbus_message_new_method_return(msg)));
- if ((device_item = _device_manager_get_device(dm->device_list, DEVICE_TYPE_BT)) != NULL) {
- if ((profile_item = _device_item_get_profile(device_item, DEVICE_PROFILE_BT_A2DP)) != NULL) {
+ /* FIXME : Give system_id for multi device */
+ if ((device = _device_list_get_device(dm, DEVICE_TYPE_BT, NULL)) != NULL) {
+ if (pa_tz_device_have_profile(device, DEVICE_PROFILE_BT_A2DP)) {
is_bt_on = true;
- bt_name = device_item->name;
+ bt_name = pa_tz_device_get_name(device);
}
}
static void handle_load_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) {
pa_device_manager *dm;
- char *device_type, *device_profile, *role;
+ char *type, *device_profile, *role;
DBusMessage *reply = NULL;
pa_assert_se((reply = dbus_message_new_method_return(msg)));
dm = (pa_device_manager *) userdata;
pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &device_type,
+ DBUS_TYPE_STRING, &type,
DBUS_TYPE_STRING, &device_profile,
DBUS_TYPE_STRING, &role,
DBUS_TYPE_INVALID));
if (pa_streq(device_profile, "none"))
device_profile = NULL;
- pa_device_manager_load_sink(dm, device_type, device_profile, role);
+ pa_device_manager_load_sink(dm, type, device_profile, role);
pa_assert_se(dbus_connection_send(conn, reply, NULL));
dbus_message_unref(reply);
}
static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata) {
pa_device_manager *dm = (pa_device_manager *)userdata;
- char *device_type, *device_profile;
+ char *type, *device_profile;
dbus_int32_t status;
DBusMessage *reply = NULL;
DBusError error;
dbus_error_init(&error);
if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &device_type,
+ DBUS_TYPE_STRING, &type,
DBUS_TYPE_STRING, &device_profile,
DBUS_TYPE_INT32, &status,
DBUS_TYPE_INVALID)) {
dbus_error_free(&error);
}
- pa_log_debug("handle_test_device_status_change, type:%s, profile:%s, status:%d", device_type, device_profile, status);
+ pa_log_debug("handle_test_device_status_change, type:%s, profile:%s, status:%d", type, device_profile, status);
if (pa_streq(device_profile, "none"))
device_profile = NULL;
- handle_device_status_changed(dm, device_type, device_profile, NULL, NULL, status);
+ handle_device_status_changed(dm, type, device_profile, NULL, NULL, status);
pa_assert_se(dbus_connection_send(conn, reply, NULL));
dbus_message_unref(reply);
}
return dm->device_list;
}
-dm_device* pa_device_manager_get_device(pa_device_manager *dm, const char *device_type) {
+pa_tz_device* pa_device_manager_get_device(pa_device_manager *dm, const char *type) {
pa_assert(dm);
- return _device_manager_get_device(dm->device_list, device_type);
+ return _device_list_get_device(dm, type, NULL);
}
-dm_device* pa_device_manager_get_device_by_id(pa_device_manager *dm, uint32_t id) {
+pa_tz_device* pa_device_manager_get_device_by_id(pa_device_manager *dm, uint32_t id) {
pa_assert(dm);
- return _device_manager_get_device_with_id(dm->device_list, id);
-}
-
-pa_sink* pa_device_manager_get_sink(dm_device *device_item, const char *role) {
- dm_device_profile *profile_item;
- pa_sink *sink;
-
- pa_assert(device_item);
- pa_assert(profile_item = _device_item_get_active_profile(device_item));
-
- if (!profile_item->playback_devices) {
- pa_log_debug("No playback device in %s", device_item->name);
- return NULL;
- }
- if ((sink = pa_hashmap_get(profile_item->playback_devices, role)))
- pa_log_debug("Got sink[%s] for [%s] role", sink->name, role);
- else {
- sink = pa_hashmap_get(profile_item->playback_devices, DEVICE_ROLE_NORMAL);
- pa_log_debug("Could not get sink for [%s] role. so get sink[%s] for normal role", role, sink->name);
- }
-
- return sink;
-}
-
-pa_source* pa_device_manager_get_source(dm_device *device_item, const char *role) {
- dm_device_profile *profile_item;
- pa_source *source;
-
- pa_assert(device_item);
- pa_assert(profile_item = _device_item_get_active_profile(device_item));
-
- if (!profile_item->capture_devices) {
- pa_log_debug("No capture device in %s", device_item->name);
- return NULL;
- }
-
- if ((source = pa_hashmap_get(profile_item->capture_devices, role)))
- pa_log_debug("Got source[%s] for [%s] role", source->name, role);
- else
- pa_log_warn("Could not get source for [%s] role", role);
-
- return source;
+ return _device_list_get_device_with_id(dm, id);
}
-dm_device* pa_device_manager_get_device_with_sink(pa_sink *sink) {
+pa_tz_device* pa_device_manager_get_device_with_sink(pa_sink *sink) {
pa_assert(sink);
return sink->device_item;
}
-dm_device* pa_device_manager_get_device_with_source(pa_source *source) {
+pa_tz_device* pa_device_manager_get_device_with_source(pa_source *source) {
pa_assert(source);
return source->device_item;
}
-void pa_device_manager_set_device_state(dm_device *device_item, dm_device_direction_t direction, dm_device_state_t state) {
- dm_device_profile *profile_item;
-
- pa_assert(device_item);
- pa_assert(profile_item = _device_item_get_active_profile(device_item));
-
- pa_log_info("pa_device_manager_set_device_state : %s.%s direction %s -> %d", device_item->type, profile_item->profile, device_direction_to_string(direction), state);
- _device_profile_set_state(profile_item, direction, state);
-}
-
-dm_device_state_t pa_device_manager_get_device_state(dm_device *device_item, dm_device_direction_t direction) {
- dm_device_profile *profile_item;
-
- pa_assert(device_item);
- pa_assert(profile_item = _device_item_get_active_profile(device_item));
-
- if (direction == DM_DEVICE_DIRECTION_BOTH)
- return COMPOUND_STATE(profile_item);
- else if (direction == DM_DEVICE_DIRECTION_OUT)
- return profile_item->playback_state;
- else if (direction == DM_DEVICE_DIRECTION_IN)
- return profile_item->capture_state;
- else
- return DM_DEVICE_STATE_DEACTIVATED;
-}
-
-uint32_t pa_device_manager_get_device_id(dm_device *device_item) {
- pa_assert(device_item);
-
- return device_item->id;
-}
-
-const char* pa_device_manager_get_device_type(dm_device *device_item) {
- pa_assert(device_item);
-
- return device_item->type;
-}
-
-const char* pa_device_manager_get_device_subtype(dm_device *device_item) {
- dm_device_profile *profile_item;
-
- pa_assert(device_item);
- pa_assert(profile_item = _device_item_get_active_profile(device_item));
-
- return profile_item->profile;
-}
-
-dm_device_direction_t pa_device_manager_get_device_direction(dm_device *device_item) {
- dm_device_profile *profile_item;
-
- pa_assert(device_item);
- pa_assert(profile_item = _device_item_get_active_profile(device_item));
-
- return profile_item->direction;
-}
-
-pa_usec_t pa_device_manager_get_device_creation_time(dm_device *device_item) {
- dm_device_profile *profile_item;
-
- pa_assert(device_item);
- pa_assert(profile_item = _device_item_get_active_profile(device_item));
-
- return profile_item->creation_time;
-}
-
-bool pa_device_manager_is_device_use_internal_codec(dm_device *device_item, dm_device_direction_t direction, const char *role) {
- pa_sink *sink;
- pa_source *source;
- bool use_internal_codec = false;
-
- pa_assert(device_item);
- pa_assert(role);
-
- if (direction == DM_DEVICE_DIRECTION_IN) {
- if ((source = pa_device_manager_get_source(device_item, role)))
- use_internal_codec = source->use_internal_codec;
- } else if (direction == DM_DEVICE_DIRECTION_OUT) {
- if ((sink = pa_device_manager_get_sink(device_item, role)))
- use_internal_codec = sink->use_internal_codec;
- } else if (direction == DM_DEVICE_DIRECTION_BOTH) {
- if ((sink = pa_device_manager_get_sink(device_item, role)) && (source = pa_device_manager_get_source(device_item, role)))
- use_internal_codec = sink->use_internal_codec & source->use_internal_codec;
- } else {
- pa_log_warn("invalid direction");
- }
-
- return use_internal_codec;
-}
-
-int pa_device_manager_bt_sco_open(pa_device_manager *dm) {
- dm_device *bt_device;
-
- pa_assert(dm);
- pa_assert(dm->dbus_conn);
-
- if (dm->bt_sco_status != DM_DEVICE_BT_SCO_STATUS_CONNECTED) {
- pa_log_error("BT SCO Not Connected");
- return -1;
- }
-
- if ((bt_device = _device_manager_get_device(dm->device_list, DEVICE_TYPE_BT)) == NULL) {
- pa_log_error("No BT Device");
- return -1;
- }
-
- pa_log_info("BT SCO Open - Request to BT FW");
- if (method_call_bt_sco(pa_dbus_connection_get(dm->dbus_conn), true) < 0) {
- pa_log_error("Failed to bt sco on");
- return -1;
- }
- pa_log_info("BT SCO Open - SUCCESS");
-
- dm->bt_sco_status = DM_DEVICE_BT_SCO_STATUS_OPENED;
- handle_device_connected(dm, DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO, NULL, NULL, DEVICE_DETECTED_BT_SCO);
-
- return 0;
-}
-
-void pa_device_manager_bt_sco_get_status(pa_device_manager *dm, dm_device_bt_sco_status_t *status) {
- pa_assert(dm);
- pa_assert(status);
-
- pa_log_info("BT SCO get status %d", dm->bt_sco_status);
- *status = dm->bt_sco_status;
-
- return;
-}
-
-int pa_device_manager_bt_sco_close(pa_device_manager *dm) {
- dm_device *bt_device;
-
- pa_assert(dm);
- pa_assert(dm->dbus_conn);
-
-
- if (dm->bt_sco_status != DM_DEVICE_BT_SCO_STATUS_OPENED) {
- pa_log_error("BT SCO Not Opened");
- return -1;
- }
-
- if ((bt_device = _device_manager_get_device(dm->device_list, DEVICE_TYPE_BT)) == NULL) {
- pa_log_error("No BT Device");
- return -1;
- }
-
- pa_log_info("BT SCO Close - Request to BT FW");
- if (method_call_bt_sco(pa_dbus_connection_get(dm->dbus_conn), false) < 0) {
- pa_log_error("Failed to BT SCO Close");
- return -1;
- }
- pa_log_info("BT SCO Close - Success");
-
- dm->bt_sco_status = DM_DEVICE_BT_SCO_STATUS_CONNECTED;
- handle_device_disconnected(dm, DEVICE_TYPE_BT, DEVICE_PROFILE_BT_SCO, NULL);
-
-
- return 0;
-}
-
-int pa_device_manager_bt_sco_get_property(pa_device_manager *dm, bool *is_wide_band, bool *nrec) {
- pa_assert(dm);
- pa_assert(dm->dbus_conn);
-
- pa_log_info("BT SCO Get Property - Request to BT FW");
-
- if (method_call_bt_sco_get_property(pa_dbus_connection_get(dm->dbus_conn), is_wide_band, nrec) < 0) {
- pa_log_error("Failed to get BT SCO Property");
- return -1;
- }
-
- pa_log_info("BT SCO Get Property - Success, is wide band : %s, nrec : %s", pa_yes_no(is_wide_band), pa_yes_no(nrec));
-
- return 0;
-}
-
-int pa_device_manager_load_sink(pa_device_manager *dm, const char *device_type, const char *device_profile, const char *role) {
+int pa_device_manager_load_sink(pa_device_manager *dm, const char *type, const char *device_profile, const char *role) {
const char *device_string, *params;
struct device_type_info *type_info;
struct device_file_info *file_info;
- dm_device_profile *profile_item;
- dm_device *device_item;
+ pa_tz_device *device;
pa_sink *sink;
uint32_t device_idx;
pa_assert(dm);
pa_assert(dm->device_list);
- pa_log_info("Load Sink for '%s.%s.%s'", device_type, device_profile, role);
- PA_IDXSET_FOREACH(device_item, dm->device_list, device_idx) {
- if (pa_streq(device_type, device_item->type)) {
- if ((profile_item = _device_item_get_profile(device_item, device_profile))) {
- if (pa_hashmap_get(profile_item->playback_devices, role)) {
- pa_log_warn("Proper sink for '%s.%s.%s' already loaded", device_type, device_profile, role);
- return -1;
- }
+ pa_log_info("Load Sink for '%s.%s.%s'", type, device_profile, role);
+ PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
+ if (pa_streq(type, pa_tz_device_get_type(device))) {
+ if (pa_tz_device_profile_get_sink(device, device_profile, role) == NULL) {
+ pa_log_warn("Proper sink for '%s.%s.%s' already loaded", type, device_profile, role);
+ return -1;
}
}
}
- if (!(type_info = _device_manager_get_type_info(dm->type_infos, device_type, device_profile))) {
- pa_log_error("No type map for %s", device_type);
+ if (!(type_info = _device_manager_get_type_info(dm->type_infos, type, device_profile))) {
+ pa_log_error("No type map for %s", type);
return -1;
}
+ if (type_info->playback_devices == NULL) {
+ pa_log_error("No playback devices for %s %s", type_info->type, pa_strempty(type_info->profile));
+ goto fail;
+ }
+
if (!(device_string = pa_hashmap_get(type_info->playback_devices, role))) {
- pa_log_error("No device-string for '%s.%s.%s'", device_type, device_profile, role);
- goto failed;
+ pa_log_error("No device-string for '%s.%s.%s'", type, device_profile, role);
+ goto fail;
}
if (!(file_info = _device_manager_get_file_info(dm->file_map->playback, device_string))) {
pa_log_error("No playback file-map for '%s'", device_string);
- goto failed;
+ goto fail;
}
if (!(params = pa_hashmap_get(file_info->roles, role))) {
pa_log_error("No params for '%s,%s'", device_string, role);
- goto failed;
+ goto fail;
}
if ((sink = load_device(dm->core, PA_DEVICE_TYPE_SINK, device_string, params))) {
- pa_log_debug("loaded sink '%s' for '%s,%s' success", sink->name, device_type, role);
+ pa_log_debug("loaded sink '%s' for '%s,%s' success", sink->name, type, role);
} else {
pa_log_warn("Cannot load playback device with '%s,%s'", device_string, params);
- goto failed;
+ goto fail;
}
return 0;
-failed:
+fail:
return -1;
}
-int pa_device_manager_load_source(pa_device_manager *dm, const char *device_type, const char *device_profile, const char *role) {
+int pa_device_manager_load_source(pa_device_manager *dm, const char *type, const char *device_profile, const char *role) {
const char *device_string, *params;
struct device_type_info *type_info;
struct device_file_info *file_info;
- dm_device_profile *profile_item;
- dm_device *device_item;
+ pa_tz_device *device;
pa_source *source;
uint32_t device_idx;
pa_assert(dm);
- pa_log_info("Load Source for '%s.%s.%s'", device_type, device_profile, role);
+ pa_log_info("Load Source for '%s.%s.%s'", type, device_profile, role);
- PA_IDXSET_FOREACH(device_item, dm->device_list, device_idx) {
- if (pa_streq(device_type, device_item->type)) {
- if ((profile_item = _device_item_get_profile(device_item, device_profile))) {
- if (pa_hashmap_get(profile_item->capture_devices, role)) {
- pa_log_warn("Proper source for '%s.%s.%s' already loaded", device_type, device_profile, role);
- return -1;
- }
+ PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
+ if (pa_streq(type, pa_tz_device_get_type(device))) {
+ if (pa_tz_device_profile_get_source(device, device_profile, role) == NULL) {
+ pa_log_warn("Proper source for '%s.%s.%s' already loaded", type, device_profile, role);
+ return -1;
}
}
}
-
- if (!(type_info = _device_manager_get_type_info(dm->type_infos, device_type, device_profile))) {
- pa_log_error("No type map for %s", device_type);
+ if (!(type_info = _device_manager_get_type_info(dm->type_infos, type, device_profile))) {
+ pa_log_error("No type map for %s", type);
return -1;
}
+ if (type_info->capture_devices == NULL) {
+ pa_log_error("No capture devices for %s %s", type_info->type, pa_strempty(type_info->profile));
+ goto fail;
+ }
+
if (!(device_string = pa_hashmap_get(type_info->capture_devices, role))) {
- pa_log_error("No device-string for '%s.%s.%s'", device_type, device_profile, role);
- goto failed;
+ pa_log_error("No device-string for '%s.%s.%s'", type, device_profile, role);
+ goto fail;
}
if (!(file_info = _device_manager_get_file_info(dm->file_map->capture, device_string))) {
pa_log_error("No capture file-map for '%s'", device_string);
- goto failed;
+ goto fail;
}
if (!(params = pa_hashmap_get(file_info->roles, role))) {
pa_log_error("No params for '%s,%s'", device_string, role);
- goto failed;
+ goto fail;
}
if ((source = load_device(dm->core, PA_DEVICE_TYPE_SOURCE, device_string, params))) {
- pa_log_debug("loaded source '%s' for '%s,%s' success", source->name, device_type, role);
+ pa_log_debug("loaded source '%s' for '%s,%s' success", source->name, type, role);
} else {
pa_log_warn("Cannot load capture device with '%s,%s'", device_string, params);
- goto failed;
+ goto fail;
}
return 0;
-failed:
+fail:
return -1;
}
+static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_manager_hook_data_for_conn_changed *data, pa_device_manager *dm) {
+ send_device_connected_signal(data->event_id, data->device, data->is_connected, dm);
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t device_info_changed_hook_cb(pa_core *c, pa_device_manager_hook_data_for_info_changed *data, pa_device_manager *dm) {
+ send_device_info_changed_signal(data->event_id, data->device, data->changed_info, dm);
+ return PA_HOOK_OK;
+}
+
pa_device_manager* pa_device_manager_get(pa_core *c) {
pa_device_manager *dm;
dm = pa_xnew0(pa_device_manager, 1);
PA_REFCNT_INIT(dm);
dm->core = c;
- dm->bt_sco_status = DM_DEVICE_BT_SCO_STATUS_DISCONNECTED;
+ dm->device_list = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+ dm->device_status = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
dbus_init(dm);
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);
dm->source_state_changed_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) device_state_changed_hook_cb, dm);
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);
-
dm->comm = pa_communicator_get(dm->core);
+ dm->comm_hook_device_connection_changed_slot = pa_hook_connect(pa_communicator_hook(dm->comm, PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED),
+ PA_HOOK_EARLY, (pa_hook_cb_t)device_connection_changed_hook_cb, dm);
+ dm->comm_hook_device_info_changed_slot = pa_hook_connect(pa_communicator_hook(dm->comm, PA_COMMUNICATOR_HOOK_DEVICE_INFORMATION_CHANGED),
+ PA_HOOK_EARLY, (pa_hook_cb_t)device_info_changed_hook_cb, dm);
if (!(dm->type_infos = parse_device_type_infos())) {
pa_log_error("Parse device-type-map failed");
return NULL;
return NULL;
}
- if (device_list_init(dm) < 0) {
- pa_log_error("Init device list failed");
- return NULL;
- }
-
- if (!(dm->device_status = device_type_status_init(dm->type_infos))) {
- pa_log_error("Init device status failed");
- return NULL;
- }
+ device_type_status_init(dm);
if (load_builtin_devices(dm) != 0) {
pa_log_error("Load Builtin Devices faled");
if (PA_REFCNT_DEC(dm) > 0)
return;
+ if (dm->comm_hook_device_connection_changed_slot)
+ pa_hook_slot_free(dm->comm_hook_device_connection_changed_slot);
+ if (dm->comm_hook_device_info_changed_slot)
+ pa_hook_slot_free(dm->comm_hook_device_info_changed_slot);
if (dm->sink_put_hook_slot)
pa_hook_slot_free(dm->sink_put_hook_slot);
if (dm->sink_state_changed_slot)
pa_xfree(dm->file_map);
}
if (dm->device_list)
- pa_idxset_free(dm->device_list, (pa_free_cb_t)device_item_free_func);
+ pa_idxset_free(dm->device_list, (pa_free_cb_t)pa_tz_device_free);
if (dm->device_status)
pa_idxset_free(dm->device_status, NULL);
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <pulse/proplist.h>
+#include <pulse/util.h>
+#include <pulse/rtclock.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/strbuf.h>
+
+#include "tizen-device.h"
+
+#define DBUS_SERVICE_HFP_AGENT "org.bluez.ag_agent"
+#define DBUS_OBJECT_HFP_AGENT "/org/bluez/hfp_agent"
+#define DBUS_INTERFACE_HFP_AGENT "Org.Hfp.App.Interface"
+
+#define BT_CVSD_CODEC_ID 1 // narrow-band
+#define BT_MSBC_CODEC_ID 2 // wide-band
+
+#define COMPOUND_STATE(d) (((pa_tz_profile*)d)->playback_state | ((pa_tz_profile*)d)->capture_state)
+
+int device_id_max_g = 1;
+uint32_t event_id_max_g = 1;
+
+static uint32_t _new_event_id() {
+ return event_id_max_g++;
+}
+
+static char* get_playback_list_str(pa_hashmap *playback_devices) {
+ pa_sink *sink = NULL;
+ void *state = NULL;
+ const char *role;
+ pa_strbuf *buf;
+
+ if (!playback_devices || !pa_hashmap_size(playback_devices))
+ return NULL;
+
+ buf = pa_strbuf_new();
+ pa_strbuf_printf(buf, " Playback device list\n");
+ PA_HASHMAP_FOREACH_KEY(sink, playback_devices, state, role)
+ pa_strbuf_printf(buf, " %-13s -> %s\n", role, sink->name);
+
+ return pa_strbuf_tostring_free(buf);
+}
+
+static char* get_capture_list_str(pa_hashmap *capture_devices) {
+ pa_source *source = NULL;
+ void *state = NULL;
+ const char *role;
+ pa_strbuf *buf;
+
+ if (!capture_devices || !pa_hashmap_size(capture_devices))
+ return NULL;
+
+ buf = pa_strbuf_new();
+ pa_strbuf_printf(buf, " Capture device list\n");
+ PA_HASHMAP_FOREACH_KEY(source, capture_devices, state, role)
+ pa_strbuf_printf(buf, " %-13s -> %s\n", role, source->name);
+
+ return pa_strbuf_tostring_free(buf);
+}
+
+/* Returned string must be freed */
+static char* get_device_profile_info_str(pa_tz_profile *profile) {
+ pa_strbuf *buf;
+ char *playback_str, *capture_str;
+ if (!profile)
+ return NULL;
+
+ buf = pa_strbuf_new();
+ pa_strbuf_printf(buf, " Profile : %s\n", pa_strna(profile->profile));
+ pa_strbuf_printf(buf, " Direction : %s\n", device_direction_to_string(profile->direction));
+ pa_strbuf_printf(buf, " Is activated : %s\n", pa_yes_no(COMPOUND_STATE(profile) == DM_DEVICE_STATE_ACTIVATED));
+ pa_strbuf_printf(buf, " Internal : %s\n", pa_yes_no(profile->use_internal_codec));
+ if (profile->profile && pa_streq(profile->profile, DEVICE_PROFILE_BT_SCO))
+ pa_strbuf_printf(buf, " SCO opened : %s\n", pa_yes_no(profile->sco_opened));
+ playback_str = get_playback_list_str(profile->playback_devices);
+ capture_str = get_capture_list_str(profile->capture_devices);
+
+ if (playback_str)
+ pa_strbuf_puts(buf, playback_str);
+ if (capture_str)
+ pa_strbuf_puts(buf, capture_str);
+
+ pa_xfree(playback_str);
+ pa_xfree(capture_str);
+
+ return pa_strbuf_tostring_free(buf);
+}
+
+static char* _device_get_info_str(pa_tz_device *device) {
+ pa_strbuf *buf;
+ char *profile_info;
+ pa_tz_profile *profile;
+ uint32_t profile_idx;
+
+ if (!device)
+ return NULL;
+
+ buf = pa_strbuf_new();
+ pa_strbuf_printf(buf, "[Device #%u]\n", device->id);
+ pa_strbuf_printf(buf, " ID : %u\n", device->id);
+ pa_strbuf_printf(buf, " Type : %s\n", device->type);
+ pa_strbuf_printf(buf, " Name : %s\n", device->name);
+ if (device_type_is_multi_profile(device->type))
+ pa_strbuf_printf(buf, " System ID : %s\n", device->system_id);
+ pa_strbuf_printf(buf, " Active Profile : %u\n", device->active_profile);
+
+ PA_IDXSET_FOREACH(profile, device->profiles, profile_idx) {
+ pa_strbuf_printf(buf, " (Profile #%d)\n", profile_idx);
+ profile_info = get_device_profile_info_str(profile);
+ if (profile_info)
+ pa_strbuf_puts(buf, profile_info);
+ pa_xfree(profile_info);
+ }
+
+ return pa_strbuf_tostring_free(buf);
+}
+
+
+void pa_tz_device_dump_info(pa_tz_device *device, pa_log_level_t log_level) {
+ char *info;
+
+ if (!device)
+ return;
+
+ if ((info = _device_get_info_str(device))) {
+ pa_logl(log_level, "%s", info);
+ pa_xfree(info);
+ }
+}
+
+static void notify_device_connection_changed(pa_tz_device *device, bool connected) {
+ pa_device_manager_hook_data_for_conn_changed hook_data;
+ uint32_t event_id;
+
+ event_id = _new_event_id();
+
+ hook_data.event_id = event_id;
+ hook_data.is_connected = connected;
+ hook_data.device = device;
+
+ pa_log_info("Fire hook for device connection changed, device(%u) %s",
+ device->id, connected ? "connected" : "disconnected");
+ pa_hook_fire(pa_communicator_hook(device->comm, PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED), &hook_data);
+}
+
+static void notify_device_info_changed(pa_tz_device *device, dm_device_changed_info_t changed_type) {
+ pa_device_manager_hook_data_for_info_changed hook_data;
+ uint32_t event_id;
+
+ event_id = _new_event_id();
+
+ hook_data.event_id = event_id;
+ hook_data.changed_info = changed_type;
+ hook_data.device = device;
+
+ pa_log_info("Fire hook for device info changed, device(%u) %s changed",
+ device->id, changed_type == DM_DEVICE_CHANGED_INFO_STATE ? "state" : "direction");
+ pa_hook_fire(pa_communicator_hook(device->comm, PA_COMMUNICATOR_HOOK_DEVICE_INFORMATION_CHANGED), &hook_data);
+}
+
+/* pa_tz_device_new_data */
+void pa_tz_device_new_data_init(pa_tz_device_new_data *data, pa_idxset *list,
+ pa_communicator *comm, pa_dbus_connection *conn) {
+ pa_assert(data);
+ pa_assert(list);
+ pa_assert(comm);
+
+ data->list = list;
+ data->comm = comm;
+ data->dbus_conn = conn;
+
+ data->type = NULL;
+ data->name = NULL;
+ data->system_id = NULL;
+ data->direction = DM_DEVICE_DIRECTION_NONE;
+
+ data->playback_pcms= pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+ data->capture_pcms = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+
+ data->n_profile = 0;
+}
+
+void pa_tz_device_new_data_set_type(pa_tz_device_new_data *data, const char *type) {
+ pa_assert(data);
+
+ data->type = pa_xstrdup(type);
+}
+
+void pa_tz_device_new_data_set_name(pa_tz_device_new_data *data, const char *name) {
+ pa_assert(data);
+
+ data->name = pa_xstrdup(name);
+}
+
+void pa_tz_device_new_data_set_direction(pa_tz_device_new_data *data, dm_device_direction_t direction) {
+ pa_assert(data);
+
+ data->direction = direction;
+}
+/* only for external? */
+void pa_tz_device_new_data_set_system_id(pa_tz_device_new_data *data, const char *system_id) {
+ pa_assert(data);
+
+ data->system_id = pa_xstrdup(system_id);
+}
+
+void pa_tz_device_new_data_set_use_internal_codec(pa_tz_device_new_data *data, bool use_internal_codec) {
+ pa_assert(data);
+
+ data->use_internal_codec = use_internal_codec;
+}
+
+void pa_tz_device_new_data_add_sink(pa_tz_device_new_data *data, const char *role, pa_sink *sink) {
+ pa_assert(data);
+
+ pa_hashmap_put(data->playback_pcms, (void*)role, sink);
+}
+
+void pa_tz_device_new_data_add_source(pa_tz_device_new_data *data, const char *role, pa_source *source) {
+ pa_assert(data);
+
+ pa_hashmap_put(data->playback_pcms, (void*)role, source);
+}
+/* after set_type, only for multi profile type, and check direction, profile */
+void pa_tz_device_new_data_add_profile(pa_tz_device_new_data *data, pa_tz_profile_new_data *profile_data, bool as_active) {
+ uint32_t profile_idx;
+ pa_assert(data);
+
+ profile_idx = data->n_profile;
+ data->profile_data[profile_idx] = profile_data;
+ if (as_active)
+ data->active_profile = profile_idx;
+
+ data->n_profile++;
+}
+
+void pa_tz_device_new_data_done(pa_tz_device_new_data *data) {
+ pa_assert(data);
+
+ pa_xfree(data->type);
+ pa_xfree(data->name);
+}
+
+static int _check_valid_device_new_data(pa_tz_device_new_data *data) {
+ bool is_multi_profile;
+ pa_assert(data);
+
+ if (data->type == NULL) {
+ pa_log_error("new data type is null");
+ return -1;
+ }
+
+ is_multi_profile = device_type_is_multi_profile(data->type);
+
+ if (is_multi_profile == false && data->direction == DM_DEVICE_DIRECTION_NONE) {
+ pa_log_error("new data direction is none");
+ return -1;
+ }
+
+ if (is_multi_profile == true && data->n_profile == 0) {
+ pa_log_error("multi profile type, but there is no profile");
+ return -1;
+ }
+ if (is_multi_profile == false && data->n_profile > 0) {
+ pa_log_error("not multi profile type, but there are profile");
+ return -1;
+ }
+
+ return 0;
+}
+
+static pa_tz_profile* profile_new(char *profile_str, dm_device_direction_t direction,
+ pa_hashmap *playbacks, pa_hashmap *captures, bool use_internal_codec, pa_tz_device *device) {
+ pa_tz_profile *profile;
+
+ pa_log_info("New profile(%s) direction(%s), for device(%u)",
+ pa_strempty(profile_str), device_direction_to_string(direction), device->id);
+
+ profile = pa_xmalloc(sizeof(pa_tz_profile));
+
+ profile->profile = pa_xstrdup(profile_str);
+ profile->playback_devices = playbacks;
+ profile->capture_devices = captures;
+ profile->direction = direction;
+ profile->playback_state = DM_DEVICE_STATE_DEACTIVATED;
+ profile->capture_state = DM_DEVICE_STATE_DEACTIVATED;
+ profile->device = device;
+ profile->creation_time = pa_rtclock_now();
+ profile->use_internal_codec = use_internal_codec;
+ profile->sco_opened = false;
+
+ return profile;
+}
+
+static void profile_free(pa_tz_profile *profile) {
+ if (!profile)
+ return;
+
+ pa_log_info("Free profile(%s) for device(%u)",
+ pa_strempty(profile->profile), profile->device->id);
+
+ pa_xfree(profile->profile);
+
+ if (profile->playback_devices)
+ pa_hashmap_free(profile->playback_devices);
+ if (profile->capture_devices)
+ pa_hashmap_free(profile->capture_devices);
+
+ pa_xfree(profile);
+}
+
+static int profile_add_sink(pa_tz_profile *profile, const char *role, pa_sink *sink) {
+ pa_assert(profile);
+
+ if (pa_hashmap_put(profile->playback_devices, (void*)role, sink) < 0) {
+ pa_log_error("Failed to add sink : put sink failed");
+ return -1;
+ }
+ return 0;
+}
+
+static int profile_add_source(pa_tz_profile *profile, const char *role, pa_source *source) {
+ pa_assert(profile);
+
+ if (pa_hashmap_put(profile->playback_devices, (void*)role, source) < 0) {
+ pa_log_error("Failed to add source : put source failed");
+ return -1;
+ }
+ return 0;
+}
+
+static pa_sink* profile_get_sink(pa_tz_profile *profile, const char *role) {
+ pa_sink *sink;
+ pa_assert(profile);
+
+ if ((sink = pa_hashmap_get(profile->playback_devices, role)) == NULL) {
+ pa_log_warn("Failed to get sink for %s", role);
+ return NULL;
+ }
+
+ return sink;
+}
+
+static pa_source* profile_get_source(pa_tz_profile *profile, const char *role) {
+ pa_source *source;
+ pa_assert(profile);
+
+ if ((source = pa_hashmap_get(profile->playback_devices, role)) == NULL) {
+ pa_log_warn("Failed to get source for %s", role);
+ return NULL;
+ }
+
+ return source;
+}
+
+static void profile_set_state(pa_tz_profile *profile, dm_device_direction_t direction, dm_device_state_t state) {
+ dm_device_state_t prev_state, new_state;
+ pa_assert(profile);
+
+ prev_state = COMPOUND_STATE(profile);
+ pa_log_debug("previous playback_state : %d, capture_state : %d => state %d", profile->playback_state, profile->capture_state, prev_state);
+ if (direction & DM_DEVICE_DIRECTION_IN)
+ profile->capture_state = state;
+ if (direction & DM_DEVICE_DIRECTION_OUT)
+ profile->playback_state = state;
+ new_state = COMPOUND_STATE(profile);
+ pa_log_debug("new playback_state : %d, capture_state : %d => state %d", profile->playback_state, profile->capture_state, new_state);
+
+ if (prev_state != new_state) {
+ notify_device_info_changed(profile->device, DM_DEVICE_CHANGED_INFO_STATE);
+ pa_tz_device_dump_info(profile->device, PA_LOG_DEBUG);
+ }
+}
+
+static dm_device_state_t profile_get_state(pa_tz_profile *profile, dm_device_direction_t direction) {
+ pa_assert(profile);
+
+ if (direction == DM_DEVICE_DIRECTION_BOTH)
+ return COMPOUND_STATE(profile);
+ else if (direction == DM_DEVICE_DIRECTION_OUT)
+ return profile->playback_state;
+ else if (direction == DM_DEVICE_DIRECTION_IN)
+ return profile->capture_state;
+ else
+ return DM_DEVICE_STATE_DEACTIVATED;
+}
+
+static int profile_remove_sink_with_role(pa_tz_profile *profile, const char *role) {
+ pa_sink *sink;
+ pa_assert(profile);
+
+ sink = pa_hashmap_remove(profile->playback_devices, role);
+ return sink ? 0 : -1;
+}
+
+static int profile_remove_source_with_role(pa_tz_profile *profile, const char *role) {
+ pa_source *source;
+ pa_assert(profile);
+
+ source = pa_hashmap_remove(profile->capture_devices, role);
+ return source ? 0 : -1;
+}
+
+static int profile_remove_sink(pa_tz_profile *profile, pa_sink *sink) {
+ pa_sink *_sink;
+ void *state;
+ char *role;
+
+ pa_assert(profile);
+
+ PA_HASHMAP_FOREACH_KEY(_sink, profile->playback_devices, state, role) {
+ if (sink == _sink)
+ return profile_remove_sink_with_role(profile, role);
+ }
+
+ return -1;
+}
+
+static int profile_remove_source(pa_tz_profile *profile, pa_source *source) {
+ pa_source *_source;
+ void *state;
+ char *role;
+
+ pa_assert(profile);
+
+ PA_HASHMAP_FOREACH_KEY(_source, profile->capture_devices, state, role) {
+ if (source == _source)
+ return profile_remove_source_with_role(profile, role);
+ }
+
+ return -1;
+}
+
+/* pa_tz_device */
+pa_tz_device* pa_tz_device_new(pa_tz_device_new_data *data) {
+ pa_tz_device *device;
+ pa_sink *sink;
+ pa_source *source;
+ pa_tz_profile *profile;
+ uint32_t profile_idx;
+
+ pa_assert(data);
+
+ if (_check_valid_device_new_data(data) < 0) {
+ pa_log_error("Invalid device_new_data");
+ return NULL;
+ }
+
+ device = pa_xmalloc(sizeof(pa_tz_device));
+ device->list = data->list;
+ device->comm = data->comm;
+ device->dbus_conn = data->dbus_conn;
+
+ device->id = device_id_max_g++;
+ device->type = pa_xstrdup(data->type);
+ if (data->name)
+ device->name = pa_xstrdup(data->name);
+ else
+ device->name = pa_xstrdup(data->type);
+ device->system_id = pa_xstrdup(data->system_id);
+ device->active_profile = 0;
+
+ pa_log_info("New device type(%s) id(%u) name(%s) system_id(%s)",
+ device->type, device->id, device->name, pa_strempty(device->system_id));
+
+ device->profiles = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+
+ /* If multi profile type, get from data->profile_data */
+ if (device_type_is_multi_profile(data->type)) {
+ pa_tz_profile_new_data *pdata;
+ for (int i = 0; i < data->n_profile; i++) {
+ pdata = data->profile_data[i];
+ profile = profile_new(pdata->profile, pdata->direction,
+ pdata->playback_pcms, pdata->capture_pcms, pdata->use_internal_codec, device);
+ pa_idxset_put(device->profiles, profile, NULL);
+ }
+ device->active_profile = data->active_profile;
+ } else {
+ profile = profile_new(NULL, data->direction,
+ data->playback_pcms, data->capture_pcms, data->use_internal_codec, device);
+ pa_idxset_put(device->profiles, profile, NULL);
+ }
+
+ PA_IDXSET_FOREACH(profile, device->profiles, profile_idx) {
+ if (device_type_is_use_external_card(device->type, profile->profile)) {
+ if ((sink = profile_get_sink(profile, DEVICE_ROLE_NORMAL)))
+ sink->device_item = device;
+ if ((source = profile_get_source(profile, DEVICE_ROLE_NORMAL)))
+ source->device_item = device;
+ }
+ }
+
+ pa_idxset_put(device->list, device, NULL);
+ notify_device_connection_changed(device, true);
+
+ pa_tz_device_dump_info(device, PA_LOG_INFO);
+
+ return device;
+}
+
+static uint32_t _get_profile_idx(pa_tz_device *device, const char *profile_str) {
+ pa_tz_profile *profile;
+ uint32_t profile_idx;
+
+ pa_assert(device);
+ pa_assert(device->profiles);
+
+ if (profile_str == NULL || pa_streq(profile_str, "")) {
+ pa_idxset_first(device->profiles, &profile_idx);
+ return profile_idx;
+ }
+
+ PA_IDXSET_FOREACH(profile, device->profiles, profile_idx) {
+ if (device_profile_is_equal(profile->profile, profile_str))
+ return profile_idx;
+ }
+
+ return PA_INVALID_INDEX;
+}
+
+static pa_tz_profile* _get_profile(pa_tz_device *device, const char *profile_str) {
+ pa_tz_profile *profile;
+ uint32_t profile_idx;
+
+ pa_assert(device);
+ pa_assert(device->profiles);
+
+ PA_IDXSET_FOREACH(profile, device->profiles, profile_idx) {
+ if (device_profile_is_equal(profile->profile, profile_str))
+ return profile;
+ }
+
+ return NULL;
+}
+
+static pa_tz_profile* _get_profile_by_idx(pa_tz_device *device, uint32_t profile_idx) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+
+ profile = pa_idxset_get_by_index(device->profiles, profile_idx);
+ if (profile == NULL)
+ pa_log_error("No profile(%u) in device(%u)", profile_idx, device->id);
+
+ return profile;
+}
+
+
+static pa_tz_profile* _get_active_profile(pa_tz_device *device) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+
+ profile = _get_profile_by_idx(device, device->active_profile);
+ if (profile == NULL)
+ pa_log_error("Failed to find active profile(%u)", device->active_profile);
+
+ return profile;
+}
+
+/* if noti_always is true, always noti this change without checking index
+ * if profile is null, set first profile as active */
+int _set_active_profile(pa_tz_device *device, const char *profile, bool noti_always) {
+ uint32_t profile_idx, prev_active_idx;
+
+ pa_assert(device);
+
+ pa_log_info("Set active profile, device(%u) profile(%s)",
+ device->id, pa_strempty(profile));
+
+ prev_active_idx = device->active_profile;
+ profile_idx = _get_profile_idx(device, profile);
+ if (profile_idx == PA_INVALID_INDEX) {
+ pa_log_error("index for profile(%s) is invalid", pa_strempty(profile));
+ return -1;
+ }
+ device->active_profile = profile_idx;
+ pa_log_info("new active profile index %u", profile_idx);
+
+ /* Compare index only when check_idx is true */
+ if (noti_always || prev_active_idx != device->active_profile)
+ notify_device_info_changed(device, DM_DEVICE_CHANGED_INFO_IO_DIRECTION);
+
+ return 0;
+}
+
+/* only for multi profile type */
+int pa_tz_device_add_profile(pa_tz_device *device, pa_tz_profile_new_data *pdata, bool as_active) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(device->profiles);
+
+ pa_log_info("device add profile, device(%u) profile(%s) as_active(%s)",
+ device->id, pa_strempty(pdata->profile), pa_yes_no(as_active));
+
+ if (device_type_is_multi_profile(device->type) == false) {
+ pa_log_error("Failed to add profile : not multi profile type");
+ return -1;
+ }
+ if (pa_idxset_size(device->profiles) >= PROFILE_NUM_MAX) {
+ pa_log_error("Failed to add profile : Too many profiles");
+ return -1;
+ }
+
+ profile = profile_new(pdata->profile, pdata->direction,
+ pdata->playback_pcms, pdata->capture_pcms, pdata->use_internal_codec, device);
+ pa_idxset_put(device->profiles, profile, NULL);
+
+ if (as_active)
+ _set_active_profile(device, pdata->profile, true);
+ pa_tz_device_dump_info(device, PA_LOG_INFO);
+
+ return 0;
+}
+
+int pa_tz_device_remove_profile(pa_tz_device *device, const char *profile_str) {
+ pa_tz_profile *profile;
+ uint32_t profile_idx, remove_idx;
+ bool found = false;
+ unsigned profile_num;
+
+ pa_assert(device);
+ pa_assert(device->profiles);
+
+ pa_log_info("device remove profile, device(%u) profile(%s)",
+ device->id, pa_strempty(profile_str));
+
+ if (device_type_is_multi_profile(device->type) == false) {
+ pa_log_error("Failed to add profile : not multi profile type");
+ return -1;
+ }
+
+ if ((profile_num = pa_tz_device_get_profile_num(device)) <= 1) {
+ pa_log_error("This device have too small profiles %u, Should be freed", profile_num);
+ return -1;
+ }
+
+ PA_IDXSET_FOREACH(profile, device->profiles, profile_idx) {
+ if (pa_safe_streq(profile->profile, profile_str)) {
+ pa_log_info("found matching profile to remove");
+ found = true;
+ remove_idx = profile_idx;
+ }
+ }
+
+ if (found) {
+ pa_idxset_remove_by_index(device->profiles, remove_idx);
+ /* change active profile if removed one was active */
+ if (device->active_profile == remove_idx)
+ _set_active_profile(device, NULL, true);
+ pa_tz_device_dump_info(device, PA_LOG_INFO);
+ return 0;
+ } else {
+ pa_log_warn("no matching profile to remove");
+ return -1;
+ }
+}
+
+/* only for single profile type */
+int pa_tz_device_add_sink(pa_tz_device *device, const char *role, pa_sink *sink) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(device_role_is_valid(role));
+ pa_assert(sink);
+
+ pa_log_info("device add sink, device(%u) role(%s) sink(%s)",
+ device->id, role, sink->name);
+
+ if (pa_tz_device_get_profile_num(device) > 1) {
+ pa_log_error("Failed to add sink : Too many profiles");
+ return -1;
+ }
+
+ profile = pa_idxset_first(device->profiles, NULL);
+
+ if (profile_add_sink(profile, role, sink) < 0) {
+ pa_log_error("Failed to add sink : Can't add to profile");
+ return -1;
+ }
+
+ return 0;
+}
+
+int pa_tz_device_add_source(pa_tz_device *device, const char *role, pa_source *source) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(device_role_is_valid(role));
+ pa_assert(source);
+
+ pa_log_info("device add source, device(%u) role(%s) source(%s)",
+ device->id, role, source->name);
+
+ if (pa_tz_device_get_profile_num(device) > 1) {
+ pa_log_warn("Failed to add source : Too many profiles");
+ return -1;
+ }
+
+ profile = pa_idxset_first(device->profiles, NULL);
+
+ if (profile_add_source(profile, role, source) < 0) {
+ pa_log_error("Failed to add source : Can't add to profile");
+ return -1;
+ }
+
+ return 0;
+}
+
+int pa_tz_device_remove_sink(pa_tz_device *device, pa_sink *sink) {
+ pa_tz_profile *profile;
+ int removed = 0;
+ uint32_t profile_idx;
+
+ pa_assert(device);
+ pa_assert(sink);
+
+ pa_log_info("device remove sink, device(%u) sink(%s)",
+ device->id, sink->name);
+
+ PA_IDXSET_FOREACH(profile, device->profiles, profile_idx)
+ removed &= profile_remove_sink(profile, sink);
+
+ return removed;
+}
+
+int pa_tz_device_remove_source(pa_tz_device *device, pa_source *source) {
+ pa_tz_profile *profile;
+ uint32_t profile_idx;
+ int removed = 0;
+
+ pa_assert(device);
+ pa_assert(source);
+
+ pa_log_info("device remove source, device(%u) source(%s)",
+ device->id, source->name);
+
+ PA_IDXSET_FOREACH(profile, device->profiles, profile_idx)
+ removed &= profile_remove_source(profile, source);
+
+ return removed;
+}
+
+int pa_tz_device_remove_sink_with_role(pa_tz_device *device, const char *role) {
+ pa_tz_profile *profile;
+ uint32_t profile_idx;
+ int removed = 0;
+
+ pa_assert(device);
+ pa_assert(device_role_is_valid(role));
+
+ pa_log_info("device remove sink with role, device(%u) role(%s)",
+ device->id, role);
+
+ PA_IDXSET_FOREACH(profile, device->profiles, profile_idx)
+ removed &= profile_remove_sink_with_role(profile, role);
+
+ return removed;
+}
+
+int pa_tz_device_remove_source_with_role(pa_tz_device *device, const char *role) {
+ pa_tz_profile *profile;
+ uint32_t profile_idx;
+ int removed = 0;
+
+ pa_assert(device);
+ pa_assert(device_role_is_valid(role));
+
+ pa_log_info("device remove source with role, device(%u) role(%s)",
+ device->id, role);
+
+ PA_IDXSET_FOREACH(profile, device->profiles, profile_idx)
+ removed &= profile_remove_source_with_role(profile, role);
+
+ return removed;
+}
+
+/* only for multi profile */
+int pa_tz_device_profile_add_sink(pa_tz_device *device, const char *profile_str, const char *role, pa_sink *sink) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+
+ pa_log_info("device profile add sink, device(%u) profile(%s) role(%s) sink(%s)",
+ device->id, pa_strempty(profile_str), role, sink->name);
+
+ if ((profile = _get_profile(device, profile_str)) == NULL) {
+ pa_log_error("Can't get profile %s", profile_str);
+ return -1;
+ }
+
+ if (profile_add_sink(profile, role, sink) < 0) {
+ pa_log_error("Can't add to profile");
+ return -1;
+ }
+
+ return 0;
+}
+
+int pa_tz_device_profile_add_source(pa_tz_device *device, const char *profile_str, const char *role, pa_source *source) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+
+ pa_log_info("device profile add source, device(%u) profile(%s) role(%s) source(%s)",
+ device->id, pa_strempty(profile_str), role, source->name);
+
+ if ((profile = _get_profile(device, profile_str)) == NULL) {
+ pa_log_error("Can't get profile %s", profile_str);
+ return -1;
+ }
+
+ if (profile_add_source(profile, role, source) < 0) {
+ pa_log_error("Can't add to profile");
+ return -1;
+ }
+
+ return 0;
+}
+
+int pa_tz_device_profile_remove_sink(pa_tz_device *device, const char *profile_str, pa_sink *sink) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+
+ pa_log_info("device profile remove sink, device(%u) profile(%s) sink(%s)",
+ device->id, pa_strempty(profile_str), sink->name);
+
+ if ((profile = _get_profile(device, profile_str)) == NULL) {
+ pa_log_error("Can't get profile %s", profile_str);
+ return -1;
+ }
+
+ if (profile_remove_sink(profile, sink) < 0) {
+ pa_log_error("Can't remove from profile");
+ return -1;
+ }
+
+ return 0;
+}
+
+int pa_tz_device_profile_remove_source(pa_tz_device *device, const char *profile_str, pa_source *source) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+
+ pa_log_info("device profile remove source, device(%u) profile(%s) source(%s)",
+ device->id, pa_strempty(profile_str), source->name);
+
+ if ((profile = _get_profile(device, profile_str)) == NULL) {
+ pa_log_error("Can't get profile %s", profile_str);
+ return -1;
+ }
+
+ if (profile_remove_source(profile, source) < 0) {
+ pa_log_error("Can't remove from profile");
+ return -1;
+ }
+
+ return 0;
+}
+
+int pa_tz_device_profile_remove_sink_with_role(pa_tz_device *device, const char *profile_str, const char *role) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(device_role_is_valid(role));
+
+ pa_log_info("device profile remove sink with role, device(%u) profile(%s) role(%s)",
+ device->id, pa_strempty(profile_str), role);
+
+ if ((profile = _get_profile(device, profile_str)) == NULL) {
+ pa_log_error("Can't get profile %s", profile_str);
+ return -1;
+ }
+
+ if (profile_remove_sink_with_role(profile, role) < 0) {
+ pa_log_error("Can't remove from profile");
+ return -1;
+ }
+
+ return 0;
+}
+
+int pa_tz_device_profile_remove_source_with_role(pa_tz_device *device, const char *profile_str, const char *role) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(device_role_is_valid(role));
+
+ pa_log_info("device profile remove source with role, device(%u) profile(%s) role(%s)",
+ device->id, pa_strempty(profile_str), role);
+
+ if ((profile = _get_profile(device, profile_str)) == NULL) {
+ pa_log_error("Can't get profile %s", profile_str);
+ return -1;
+ }
+
+ if (profile_remove_source_with_role(profile, role) < 0) {
+ pa_log_error("Can't remove from profile");
+ return -1;
+ }
+
+ return 0;
+}
+
+pa_sink* pa_tz_device_profile_get_sink(pa_tz_device *device, const char *profile_str, const char *role) {
+ pa_sink *sink;
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+
+ pa_log_info("device profile get sink, device(%u) profile(%s) role(%s)",
+ device->id, pa_strempty(profile_str), role);
+
+ if ((profile = _get_profile(device, profile_str)) == NULL) {
+ pa_log_error("Can't get profile %s", profile_str);
+ return NULL;
+ }
+
+ if ((sink = profile_get_sink(profile, role)) == NULL) {
+ pa_log_error("Can't get sink from profile");
+ return NULL;
+ }
+
+ return sink;
+}
+
+pa_source* pa_tz_device_profile_get_source(pa_tz_device *device, const char *profile_str, const char *role) {
+ pa_source *source;
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+
+ pa_log_info("device profile get source, device(%u) profile(%s) role(%s)",
+ device->id, pa_strempty(profile_str), role);
+
+ if ((profile = _get_profile(device, profile_str)) == NULL) {
+ pa_log_error("Can't get profile %s", profile_str);
+ return NULL;
+ }
+
+ if ((source = profile_get_source(profile, role)) == NULL) {
+ pa_log_error("Can't get source from profile");
+ return NULL;
+ }
+
+ return source;
+}
+
+void pa_tz_device_free(pa_tz_device *device) {
+ pa_assert(device);
+
+ pa_log_info("Free device type(%s) id(%u) name(%s) system_id(%s)",
+ device->type, device->id, device->name, device->system_id);
+
+ pa_tz_device_dump_info(device, PA_LOG_INFO);
+
+ pa_idxset_remove_by_data(device->list, device, NULL);
+ notify_device_connection_changed(device, false);
+
+ pa_xfree(device->type);
+ pa_xfree(device->name);
+ pa_xfree(device->system_id);
+
+ pa_idxset_free(device->profiles, (pa_free_cb_t)profile_free);
+
+ pa_xfree(device);
+}
+
+/* pa_tz_profile_new_data */
+void pa_tz_profile_new_data_init(pa_tz_profile_new_data *profile_data) {
+ pa_assert(profile_data);
+
+ profile_data->profile = NULL;
+ profile_data->direction = DM_DEVICE_DIRECTION_NONE;
+
+ profile_data->playback_pcms= pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+ profile_data->capture_pcms = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+}
+
+void pa_tz_profile_new_data_set_direction(pa_tz_profile_new_data *profile_data, dm_device_direction_t direction) {
+ pa_assert(profile_data);
+
+ profile_data->direction = direction;
+}
+
+void pa_tz_profile_new_data_set_profile(pa_tz_profile_new_data *profile_data, const char *profile) {
+ pa_assert(profile_data);
+
+ profile_data->profile = pa_xstrdup(profile);
+}
+
+void pa_tz_profile_new_data_set_use_internal_codec(pa_tz_profile_new_data *profile_data, bool use_internal_codec) {
+ pa_assert(profile_data);
+ profile_data->use_internal_codec = use_internal_codec;
+}
+
+void pa_tz_profile_new_data_add_sink(pa_tz_profile_new_data *profile_data, const char *role, pa_sink *sink) {
+ pa_assert(profile_data);
+
+ pa_hashmap_put(profile_data->playback_pcms, (void*)role, sink);
+}
+
+void pa_tz_profile_new_data_add_source(pa_tz_profile_new_data *profile_data, const char *role, pa_source *source) {
+ pa_assert(profile_data);
+
+ pa_hashmap_put(profile_data->capture_pcms, (void*)role, source);
+}
+
+void pa_tz_profile_new_data_done(pa_tz_profile_new_data *profile_data) {
+ pa_assert(profile_data);
+
+ pa_xfree(profile_data->profile);
+}
+
+/* exported api */
+pa_sink* pa_tz_device_get_sink(pa_tz_device *device, const char *role) {
+ pa_tz_profile *profile;
+ pa_sink *sink;
+
+ pa_assert(device);
+ pa_assert(profile = _get_active_profile(device));
+
+ pa_log_info("device get sink, device(%u) role(%s), active-profile(%s)",
+ device->id, role, pa_strempty(profile->profile));
+
+ if ((sink = profile_get_sink(profile, role)) == NULL) {
+ pa_log_error("Failed to get sink from profile");
+ return NULL;
+ }
+
+ return sink;
+}
+
+pa_source* pa_tz_device_get_source(pa_tz_device *device, const char *role) {
+ pa_tz_profile *profile;
+ pa_source *source;
+
+ pa_assert(device);
+ pa_assert(profile = _get_active_profile(device));
+
+ pa_log_info("device get source, device(%u) role(%s), active-profile(%s)",
+ device->id, role, pa_strempty(profile->profile));
+
+ if ((source = profile_get_source(profile, role)) == NULL) {
+ pa_log_error("Failed to get source from profile");
+ return NULL;
+ }
+
+ return source;
+}
+
+void pa_tz_device_set_state(pa_tz_device *device, dm_device_direction_t direction, dm_device_state_t state) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(profile = _get_active_profile(device));
+
+ pa_log_info("device set state, device(%u) type(%s) active-profile(%s) direction(%s) -> %d",
+ device->id, device->type, pa_strempty(profile->profile), device_direction_to_string(direction), state);
+ profile_set_state(profile, direction, state);
+}
+
+dm_device_state_t pa_tz_device_get_state(pa_tz_device *device, dm_device_direction_t direction) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(profile = _get_active_profile(device));
+
+ return profile_get_state(profile, direction);
+}
+
+uint32_t pa_tz_device_get_id(pa_tz_device *device) {
+ pa_assert(device);
+
+ return device->id;
+}
+
+char* pa_tz_device_get_type(pa_tz_device *device) {
+ pa_assert(device);
+
+ return device->type;
+}
+
+char* pa_tz_device_get_name(pa_tz_device *device) {
+ pa_assert(device);
+
+ return device->name;
+}
+
+char* pa_tz_device_get_system_id(pa_tz_device *device) {
+ pa_assert(device);
+
+ return device->system_id;
+}
+
+char* pa_tz_device_get_profile(pa_tz_device *device) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(profile = _get_active_profile(device));
+
+ return profile->profile;
+}
+
+dm_device_direction_t pa_tz_device_get_direction(pa_tz_device *device) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(profile = _get_active_profile(device));
+
+ return profile->direction;
+}
+
+pa_usec_t pa_tz_device_get_creation_time(pa_tz_device *device) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(profile = _get_active_profile(device));
+
+ return profile->creation_time;
+}
+
+bool pa_tz_device_is_use_internal_codec(pa_tz_device *device) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(profile = _get_active_profile(device));
+
+ return profile->use_internal_codec;
+}
+
+unsigned pa_tz_device_get_profile_num(pa_tz_device *device) {
+ pa_assert(device);
+ pa_assert(device->profiles);
+
+ return pa_idxset_size(device->profiles);
+}
+
+bool pa_tz_device_have_profile(pa_tz_device *device, const char *profile) {
+ pa_assert(device);
+
+ if (_get_profile(device, profile) == NULL)
+ return false;
+ else
+ return true;
+}
+
+static int method_call_bt_sco(pa_dbus_connection *conn, bool onoff) {
+ DBusMessage *msg, *reply;
+ DBusError err;
+ const char *method;
+
+ pa_assert(conn);
+
+ method = onoff ? "Play" : "Stop";
+ if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_HFP_AGENT, DBUS_OBJECT_HFP_AGENT, DBUS_INTERFACE_HFP_AGENT, method))) {
+ pa_log_error("dbus method call failed");
+ return -1;
+ }
+
+ dbus_error_init(&err);
+ if (!(reply = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(conn), msg, -1, &err))) {
+ pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_HFP_AGENT, method, err.message);
+ dbus_error_free(&err);
+ return -1;
+ }
+
+ dbus_message_unref(reply);
+ return 0;
+}
+
+static int method_call_bt_sco_get_property(pa_dbus_connection *conn, bool *is_wide_band, bool *nrec) {
+ DBusMessage *msg, *reply;
+ DBusMessageIter reply_iter, reply_iter_entry;
+ DBusError err;
+ unsigned int codec;
+ const char *property;
+
+ pa_assert(conn);
+
+ if (!is_wide_band && !nrec) {
+ return -1;
+ }
+
+ if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_HFP_AGENT, DBUS_OBJECT_HFP_AGENT, DBUS_INTERFACE_HFP_AGENT, "GetProperties"))) {
+ pa_log_error("dbus method call failed");
+ return -1;
+ }
+
+ dbus_error_init(&err);
+ if (!(reply = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(conn), msg, -1, &err))) {
+ pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_HFP_AGENT, "GetProperties", err.message);
+ dbus_error_free(&err);
+ return -1;
+ }
+
+ dbus_message_iter_init(reply, &reply_iter);
+
+ if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
+ pa_log_error("Cannot get reply argument");
+ return -1;
+ }
+
+ dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
+
+ while (dbus_message_iter_get_arg_type(&reply_iter_entry) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter dict_entry, dict_entry_val;
+ dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
+ dbus_message_iter_get_basic(&dict_entry, &property);
+ pa_log_debug("String received = %s", property);
+ if (property) {
+ if (pa_streq("codec", property) && is_wide_band) {
+ dbus_message_iter_next(&dict_entry);
+ dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
+ if (dbus_message_iter_get_arg_type(&dict_entry_val) != DBUS_TYPE_UINT32)
+ continue;
+ dbus_message_iter_get_basic(&dict_entry_val, &codec);
+ pa_log_debug("Codec = [%d]", codec);
+ *is_wide_band = (codec == BT_MSBC_CODEC_ID) ? true : false;
+ } else if (pa_streq("nrec", property) && nrec) {
+ dbus_message_iter_next(&dict_entry);
+ dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
+ if (dbus_message_iter_get_arg_type(&dict_entry_val) != DBUS_TYPE_BOOLEAN)
+ continue;
+ dbus_message_iter_get_basic(&dict_entry_val, nrec);
+ pa_log_debug("nrec= [%d]", *nrec);
+ }
+ }
+ dbus_message_iter_next(&reply_iter_entry);
+ }
+
+
+ dbus_message_unref(reply);
+ return 0;
+}
+
+/* only for bt device, which have sco profile */
+int pa_tz_device_sco_open(pa_tz_device *device) {
+ pa_tz_profile *profile;
+
+ pa_assert(device);
+ pa_assert(device->dbus_conn);
+
+ pa_log_info("BT SCO Open for device(%u)", device->id);
+ if (pa_streq(device->type, DEVICE_TYPE_BT) == false) {
+ pa_log_error("Not BT device");
+ return -1;
+ }
+ if ((profile = _get_profile(device, DEVICE_PROFILE_BT_SCO)) == NULL) {
+ pa_log_error("No BT SCO profile");
+ return -1;
+ }
+
+ if (profile->sco_opened) {
+ pa_log_warn("SCO already opened");
+ return -1;
+ }
+
+ if (method_call_bt_sco(device->dbus_conn, true) < 0) {
+ pa_log_error("Failed to bt sco on");
+ return -1;
+ }
+
+ profile->sco_opened = true;
+ _set_active_profile(device, DEVICE_PROFILE_BT_SCO, false);
+ pa_tz_device_dump_info(profile->device, PA_LOG_DEBUG);
+ pa_log_info("BT SCO Open - SUCCESS");
+
+ return 0;
+}
+
+/* only for bt device, which have sco profile */
+int pa_tz_device_sco_close(pa_tz_device *device) {
+ pa_tz_profile *profile;
+ pa_assert(device);
+
+ pa_log_info("BT SCO Close for device(%u)", device->id);
+
+ if (pa_streq(device->type, DEVICE_TYPE_BT) == false) {
+ pa_log_error("Not BT device");
+ return -1;
+ }
+ if ((profile = _get_profile(device, DEVICE_PROFILE_BT_SCO)) == NULL) {
+ pa_log_error("No BT SCO profile");
+ return -1;
+ }
+
+ if (profile->sco_opened == false) {
+ pa_log_warn("SCO not opened");
+ return -1;
+ }
+
+ if (method_call_bt_sco(device->dbus_conn, false) < 0) {
+ pa_log_error("Failed to bt sco on");
+ return -1;
+ }
+
+ profile->sco_opened = false;
+ if (pa_tz_device_have_profile(device, DEVICE_PROFILE_BT_A2DP))
+ _set_active_profile(device, DEVICE_PROFILE_BT_A2DP, false);
+ pa_tz_device_dump_info(profile->device, PA_LOG_DEBUG);
+ pa_log_info("BT SCO Close - Success");
+
+ return 0;
+}
+
+/* only for bt device, which have sco profile */
+int pa_tz_device_sco_get_property(pa_tz_device *device, bool *is_wide_band, bool *nrec) {
+ pa_assert(device);
+
+ pa_log_info("BT SCO get property for device(%u)", device->id);
+ if (pa_streq(device->type, DEVICE_TYPE_BT) == false) {
+ pa_log_error("Not BT device");
+ return -1;
+ }
+ if ((_get_profile(device, DEVICE_PROFILE_BT_SCO)) == NULL) {
+ pa_log_error("No BT SCO profile");
+ return -1;
+ }
+
+ if (method_call_bt_sco_get_property(device->dbus_conn, is_wide_band, nrec) < 0) {
+ pa_log_error("Failed to get BT SCO Property");
+ return -1;
+ }
+
+ pa_log_info("BT SCO Get Property - Success, is wide band : %s, nrec : %s", pa_yes_no(is_wide_band), pa_yes_no(nrec));
+
+ return 0;
+}
+
+/* only for bt device */
+int pa_tz_device_sco_get_status(pa_tz_device *device, dm_device_bt_sco_status_t *status) {
+ pa_tz_profile *profile;
+ pa_assert(device);
+
+ pa_log_info("BT SCO get status for device(%u)", device->id);
+ if (pa_streq(device->type, DEVICE_TYPE_BT) == false) {
+ pa_log_error("Not BT device");
+ return -1;
+ }
+ if (status == NULL) {
+ pa_log_error("invalid parameter");
+ return -1;
+ }
+
+ if ((profile = _get_profile(device, DEVICE_PROFILE_BT_SCO))) {
+ if (profile->sco_opened == false)
+ *status = DM_DEVICE_BT_SCO_STATUS_CONNECTED;
+ else
+ *status = DM_DEVICE_BT_SCO_STATUS_OPENED;
+ } else {
+ *status = DM_DEVICE_BT_SCO_STATUS_DISCONNECTED;
+ }
+
+ pa_log_debug("BT SCO Get Status, %d", *status);
+ return 0;
+}
+