" <arg name=\"mask_flags\" direction=\"in\" type=\"i\"/>\n" \
" <arg name=\"ConnectedDeviceList\" direction=\"out\" type=\"a(isiis)\"/>\n" \
" </method>\n" \
- " <method name=\"IsStreamOnDevice\">\n" \
- " <arg name=\"stream_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"is_on\" direction=\"out\" type=\"b\"/>\n" \
+ " <method name=\"IsStreamOnDevice\">\n" \
+ " <arg name=\"stream_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"is_on\" direction=\"out\" type=\"b\"/>\n" \
" </method>\n" \
" <method name='GetBTA2DPStatus'>" \
" <arg type='b' name='is_bt_on' direction='out'/>" \
" <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n" \
" <arg name=\"role\" direction=\"in\" type=\"s\"/>\n" \
" </method>\n" \
+ " <method name=\"UnloadSink\">\n" \
+ " <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n" \
+ " <arg name=\"role\" direction=\"in\" type=\"s\"/>\n" \
+ " </method>\n" \
+ " <method name=\"DumpDeviceList\">\n" \
+ " </method>\n" \
" <method name=\"TestStatusChange\">\n" \
" <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n" \
" <arg name=\"status\" direction=\"in\" type=\"i\"/>\n" \
static void handle_is_stream_on_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
static void handle_get_bt_a2dp_status(DBusConnection *conn, DBusMessage *msg, void *userdata);
static void handle_load_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_unload_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_dump_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata);
static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name);
METHOD_HANDLER_IS_STREAM_ON_DEVICE,
METHOD_HANDLER_GET_BT_A2DP_STATUS,
METHOD_HANDLER_LOAD_SINK,
+ METHOD_HANDLER_UNLOAD_SINK,
+ METHOD_HANDLER_DUMP_DEVICE_LIST,
METHOD_HANDLER_STATUS_TEST,
METHOD_HANDLER_MAX
};
[METHOD_HANDLER_LOAD_SINK] = {
.method_name = "LoadSink",
.receive_cb = handle_load_sink},
+ [METHOD_HANDLER_UNLOAD_SINK] = {
+ .method_name = "UnloadSink",
+ .receive_cb = handle_unload_sink},
+ [METHOD_HANDLER_DUMP_DEVICE_LIST] = {
+ .method_name = "DumpDeviceList",
+ .receive_cb = handle_dump_device_list},
[METHOD_HANDLER_STATUS_TEST] = {
.method_name = "TestStatusChange",
.receive_cb = handle_test_device_status_change},
return NULL;
}
args_buf = pa_strbuf_new();
- pa_strbuf_printf(args_buf, "device=hw:%s \n", alsa_device_name);
+ pa_strbuf_printf(args_buf, "device=hw:%s ", alsa_device_name);
if (params) {
- pa_strbuf_printf(args_buf, "%s\n", params);
+ pa_strbuf_printf(args_buf, "%s", params);
}
strncpy(args, pa_strbuf_tostring_free(args_buf), DEVICE_PARAM_STRING_MAX);
} else {
pa_dynarray *ctypes;
struct composite_type *ctype;
struct device_type_info *type_info;
- const char *device_string, *role;
+ const char *device_string, *role, *param;
uint32_t type_idx;
pa_device_type_t pdt;
+ pa_idxset *file_infos;
+ pa_hashmap *pcm_devices;
+ void *state;
pa_assert(pdevice);
+ pa_assert(dm);
+
+ pa_log_info("pulse device get belongs type");
if (pulse_device_is_monitor(pdevice))
return NULL;
ctypes = pa_dynarray_new(pa_xfree);
- if (pa_sink_isinstance(pdevice))
+ if (pa_sink_isinstance(pdevice)) {
pdt = PA_DEVICE_TYPE_SINK;
- else
+ file_infos = dm->file_map->playback;
+ } else {
pdt = PA_DEVICE_TYPE_SOURCE;
+ file_infos = dm->file_map->capture;
+ }
+ /* iterate "device-types" in device-map.json */
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) {
+ if (pdt == PA_DEVICE_TYPE_SINK)
+ pcm_devices = type_info->playback_devices;
+ else
+ pcm_devices = type_info->capture_devices;
+ if (pcm_devices == NULL)
+ continue;
+ /* iterate "{playback,capture}-devices" in specific device-type */
+ PA_HASHMAP_FOREACH_KV(role, device_string, pcm_devices, state) {
+ if (pulse_device_same_device_string(pdevice, device_string) == false)
+ continue;
+ param = _file_infos_get_param(file_infos, device_string, role);
+ if (pulse_device_params_is_equal(pdevice, param) == false)
+ continue;
+ /* Found type.role which is matching with pulse_device */
ctype = pa_xmalloc0(sizeof(struct composite_type));
ctype->type = type_info->type;
ctype->role = role;
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;
+ const char *device_string, *role, *param;
void *state;
+ pa_idxset *file_infos;
pa_assert(data);
pa_assert(type_info);
return -1;
}
+ file_infos = dm->file_map->playback;
+ if (file_infos == NULL) {
+ pa_log_error("No playback pcm device config");
+ return -1;
+ }
+
PA_HASHMAP_FOREACH_KV(role, device_string, type_info->playback_devices, state) {
- sink = _core_get_sink(dm->core, device_string, NULL);
+ param = _file_infos_get_param(file_infos, device_string, role);
+ sink = _core_get_sink(dm->core, device_string, param);
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_log_warn("No matching sink for %s %s", device_string, role);
}
return 0;
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;
+ const char *device_string, *role, *param;
void *state;
+ pa_idxset *file_infos;
pa_assert(data);
pa_assert(type_info);
return -1;
}
+ file_infos = dm->file_map->capture;
+ if (file_infos == NULL) {
+ pa_log_error("No capture pcm device config");
+ return -1;
+ }
+
PA_HASHMAP_FOREACH_KV(role, device_string, type_info->capture_devices, state) {
- source = _core_get_source(dm->core, device_string, NULL);
+ param = _file_infos_get_param(file_infos, device_string, role);
+ source = _core_get_source(dm->core, device_string, param);
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_warn("No matching source for %s %s", device_string, role);
}
return 0;
return NULL;
}
+static void unload_device(pa_core *c, bool is_sink, const char *device_string) {
+ pa_assert(c);
+ pa_assert(device_string);
+
+ pa_log_info("Unload %s Device : String'%s'", is_sink ? "Playback" : "Capture", device_string);
+
+ if (is_sink) {
+ pa_sink *sink = _core_get_sink(c, device_string, NULL);
+ if (sink == NULL) {
+ pa_log_warn("No matching sink");
+ return;
+ }
+ pa_module_unload(c, sink->module, true);
+ } else {
+ pa_source *source = _core_get_source(c, device_string, NULL);
+ if (source == NULL) {
+ pa_log_warn("No matching source");
+ return;
+ }
+ pa_module_unload(c, source->module, true);
+ }
+}
+
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;
}
PA_HASHMAP_FOREACH_KV(role, device_string, pcm_devices, state) {
- params = _file_infos_get_param(file_infos, device_string, role);
- if (params == NULL) {
- pa_log_error("Failed to get param for %s", device_string);
+ /* skip duplicate load */
+ if (is_playback && _core_get_sink(dm->core, device_string, NULL)) {
+ pa_log_debug("Already loaded %s", device_string);
continue;
}
- /* Check duplicate load */
- if (is_playback && _core_get_sink(dm->core, device_string, params)) {
- pa_log_debug("Already loaded %s %s", device_string, params);
+ if (!is_playback && _core_get_source(dm->core, device_string, NULL)) {
+ pa_log_debug("Already loaded %s", device_string);
continue;
}
- if (!is_playback && _core_get_source(dm->core, device_string, params)) {
- pa_log_debug("Already loaded %s %s", device_string, params);
+
+ params = _file_infos_get_param(file_infos, device_string, role);
+ if (params == NULL) {
+ pa_log_error("Failed to get param for %s", device_string);
continue;
}
if (!(load_device(dm->core, is_playback, device_string, params))) {
return 0;
}
-
static void handle_get_connected_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
pa_device_manager *dm;
DBusMessage *reply = NULL;
dbus_message_unref(reply);
}
+static void handle_unload_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ char *type, *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, &type,
+ DBUS_TYPE_STRING, &role,
+ DBUS_TYPE_INVALID));
+
+ pa_device_manager_unload_sink(dm, type, role);
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_dump_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ pa_tz_device *device;
+ uint32_t device_idx;
+ DBusMessage *reply = NULL;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dm = (pa_device_manager *) userdata;
+
+ PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
+ pa_tz_device_dump_info(device, PA_LOG_INFO);
+ }
+ 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 *type;
pa_log_warn("There is no forwarding device");
}
-int pa_device_manager_load_sink(pa_device_manager *dm, const char *type, const char *role) {
+pa_sink* pa_device_manager_load_sink(pa_device_manager *dm, const char *type, const char *role) {
const char *device_string, *params;
struct device_type_info *type_info;
struct device_file_info *file_info;
pa_assert(dm);
pa_assert(dm->device_list);
+ pa_assert(type);
+ pa_assert(role);
pa_log_info("Load Sink for '%s.%s'", type, role);
PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
if (pa_streq(type, pa_tz_device_get_type(device))) {
- if (pa_tz_device_get_sink(device, role) == NULL) {
+ if (pa_tz_device_get_sink(device, role)) {
pa_log_warn("Proper sink for '%s.%s' already loaded", type, role);
- return -1;
+ return NULL;
}
}
}
if (!(type_info = _device_manager_get_type_info(dm->type_infos, type))) {
pa_log_error("No type map for %s", type);
- return -1;
+ return NULL;
}
if (type_info->playback_devices == NULL) {
goto fail;
}
- if ((sink = load_device(dm->core, PA_DEVICE_TYPE_SINK, device_string, params))) {
+ if ((sink = load_device(dm->core, true, device_string, params))) {
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 fail;
}
- return 0;
+ return sink;
fail:
- return -1;
+ return NULL;
+}
+
+void pa_device_manager_unload_sink(pa_device_manager *dm, const char *type, const char *role) {
+ const char *device_string;
+ struct device_type_info *type_info;
+
+ pa_assert(dm);
+ pa_assert(dm->device_list);
+ pa_assert(type);
+ pa_assert(role);
+
+ pa_log_info("Unload Sink for '%s.%s'", type, role);
+
+ if (!(type_info = _device_manager_get_type_info(dm->type_infos, type))) {
+ pa_log_error("No type map for %s", type);
+ return;
+ }
+
+ if (type_info->playback_devices == NULL) {
+ pa_log_error("No playback devices for %s", type_info->type);
+ return;
+ }
+
+ if (!(device_string = pa_hashmap_get(type_info->playback_devices, role))) {
+ pa_log_error("No device-string for '%s.%s'", type, role);
+ return;
+ }
+
+ unload_device(dm->core, true, device_string);
}
-int pa_device_manager_load_source(pa_device_manager *dm, const char *type, const char *role) {
+pa_source* pa_device_manager_load_source(pa_device_manager *dm, const char *type, const char *role) {
const char *device_string, *params;
struct device_type_info *type_info;
struct device_file_info *file_info;
uint32_t device_idx;
pa_assert(dm);
+ pa_assert(dm->device_list);
+ pa_assert(type);
+ pa_assert(role);
pa_log_info("Load Source for '%s.%s'", type, role);
PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
if (pa_streq(type, pa_tz_device_get_type(device))) {
- if (pa_tz_device_get_source(device, role) == NULL) {
+ if (pa_tz_device_get_source(device, role)) {
pa_log_warn("Proper source for '%s.%s' already loaded", type, role);
- return -1;
+ return NULL;
}
}
}
if (!(type_info = _device_manager_get_type_info(dm->type_infos, type))) {
pa_log_error("No type map for %s", type);
- return -1;
+ return NULL;
}
if (type_info->capture_devices == NULL) {
goto fail;
}
- if ((source = load_device(dm->core, PA_DEVICE_TYPE_SOURCE, device_string, params))) {
+ if ((source = load_device(dm->core, false, device_string, params))) {
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 fail;
}
- return 0;
+ return source;
fail:
- return -1;
+ return NULL;
+}
+
+void pa_device_manager_unload_source(pa_device_manager *dm, const char *type, const char *role) {
+ const char *device_string;
+ struct device_type_info *type_info;
+
+ pa_assert(dm);
+ pa_assert(dm->device_list);
+ pa_assert(type);
+ pa_assert(role);
+
+ pa_log_info("Unload Source for '%s.%s'", type, role);
+
+ if (!(type_info = _device_manager_get_type_info(dm->type_infos, type))) {
+ pa_log_error("No type map for %s", type);
+ return;
+ }
+
+ if (type_info->capture_devices == NULL) {
+ pa_log_error("No capture devices for %s", type_info->type);
+ return;
+ }
+
+ if (!(device_string = pa_hashmap_get(type_info->capture_devices, role))) {
+ pa_log_error("No device-string for '%s.%s'", type, role);
+ return;
+ }
+
+ unload_device(dm->core, false, device_string);
}
static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_tz_device_hook_data_for_conn_changed *data, pa_device_manager *dm) {