#include <pulsecore/namereg.h>
#include <pulsecore/shared.h>
#include <pulsecore/dynarray.h>
+#include <pulsecore/proplist-util.h>
#include <vconf.h>
#include <vconf-keys.h>
#define DEVICE_API_NULL "null"
#define DEVICE_API_ACM "acm"
#define DEVICE_API_RAOP "raop"
+#define DEVICE_API_TUNNEL "tunnel"
#define DEVICE_BUS_USB "usb"
#define DEVICE_CLASS_SOUND "sound"
#define DEVICE_CLASS_MONITOR "monitor"
return pa_safe_streq(pa_proplist_gets(prop, PA_PROP_DEVICE_API), DEVICE_API_RAOP);
}
+static bool pulse_device_is_tunnel(pa_object *pdevice) {
+ pa_proplist *prop = pulse_device_get_proplist(pdevice);
+
+ if (!prop)
+ return false;
+
+ return pa_safe_streq(pa_proplist_gets(prop, PA_PROP_DEVICE_API), DEVICE_API_TUNNEL);
+}
static bool pulse_device_is_tizenaudio(pa_object *pdevice) {
if (!pdevice)
return pa_proplist_gets(prop, "bluez.path");
else if (pulse_device_is_raop(pdevice))
return pa_proplist_gets(prop, PA_PROP_DEVICE_STRING);
+ else if (pulse_device_is_tunnel(pdevice))
+ return pa_proplist_gets(prop, PA_PROP_DEVICE_DESCRIPTION);
else
return NULL;
}
}
}
+static void handle_tunnel_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) {
+ dm_device_direction_t direction;
+ pa_tz_device *device;
+ const char *system_id;
+
+ pa_assert(pdevice);
+ pa_assert(dm);
+
+ pa_log_info("Handle TUNNEL pulse device");
+
+ direction = pulse_device_get_direction(pdevice);
+ system_id = pulse_device_get_system_id(pdevice);
+
+ if (is_loaded) {
+ pa_tz_device_new_data data;
+
+ pa_proplist *prop = pulse_device_get_proplist(pdevice);
+ const char *name = pa_proplist_gets(prop, PA_PROP_DEVICE_DESCRIPTION);
+
+ pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, dm->dbus_conn);
+ _fill_new_data_basic(&data, DEVICE_TYPE_NETWORK, direction, false, dm);
+ pa_tz_device_new_data_set_name(&data, name);
+ pa_tz_device_new_data_set_system_id(&data, system_id);
+ if (direction == DM_DEVICE_DIRECTION_OUT)
+ pa_tz_device_new_data_add_sink(&data, DEVICE_ROLE_TUNNEL, PA_SINK(pdevice));
+ else
+ pa_tz_device_new_data_add_source(&data, DEVICE_ROLE_TUNNEL, PA_SOURCE(pdevice));
+ pa_tz_device_new(&data);
+ pa_tz_device_new_data_done(&data);
+ } else {
+ if (!(device = device_list_get_device(dm, DEVICE_TYPE_NETWORK, NULL, system_id)))
+ pa_log_warn("Can't get REMOTE device for %s", system_id);
+ else
+ pa_tz_device_free(device);
+ }
+}
+
static void handle_acm_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) {
pa_tz_device *device;
} else if (pulse_device_is_raop(PA_OBJECT(sink))) {
handle_raop_pulse_device(PA_OBJECT(sink), false, dm);
return PA_HOOK_OK;
+ } else if (pulse_device_is_tunnel(PA_OBJECT(sink))) {
+ if (pa_proplist_has_remote_name(sink->proplist)) {
+ if (pa_proplist_remote_is_allowed(sink->proplist)) {
+ pa_log_info("allowed sink is unlinked, update to deny now");
+ pa_sink_update_proplist_remote_access_permission(sink, false);
+ } else {
+ pa_log_info("denied sink is unlinked, nothing to do");
+ }
+ } else {
+ pa_log_warn("tunnel but not remote....ignore this");
+ }
+ return PA_HOOK_OK;
} else if (pulse_device_is_acm(PA_OBJECT(sink))) {
handle_acm_pulse_device(PA_OBJECT(sink), 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_tunnel(PA_OBJECT(source))) {
+ if (pa_proplist_has_remote_name(source->proplist)) {
+ if (pa_proplist_remote_is_allowed(source->proplist)) {
+ pa_log_info("allowed source is unlinked, update to deny now");
+ pa_source_update_proplist_remote_access_permission(source, false);
+ } else {
+ pa_log_info("denied source is unlinked, nothing to do");
+ }
+ } else {
+ pa_log_warn("tunnel but not remote....ignore this");
+ }
+ 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;
return PA_HOOK_OK;
}
+static pa_hook_result_t source_proplist_changed(pa_core *core, pa_source *source, pa_device_manager *dm) {
+ pa_core_assert_ref(core);
+ pa_source_assert_ref(source);
+
+ if (pulse_device_is_tunnel(PA_OBJECT(source)) &&
+ pa_proplist_has_remote_name(source->proplist)) {
+ /* FIXME : skip if no changes */
+ pulse_device_set_use_internal_codec(PA_OBJECT(source), false);
+ handle_tunnel_pulse_device(PA_OBJECT(source), pa_proplist_remote_is_allowed(source->proplist), dm);
+ }
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_proplist_changed(pa_core *core, pa_sink *sink, pa_device_manager *dm) {
+ pa_core_assert_ref(core);
+ pa_sink_assert_ref(sink);
+
+ if (pulse_device_is_tunnel(PA_OBJECT(sink)) &&
+ pa_proplist_has_remote_name(sink->proplist)) {
+ /* FIXME : skip if no changes */
+ pulse_device_set_use_internal_codec(PA_OBJECT(sink), false);
+ handle_tunnel_pulse_device(PA_OBJECT(sink), pa_proplist_remote_is_allowed(sink->proplist), dm);
+ }
+ return PA_HOOK_OK;
+}
+
/*
Build params for load sink or source, and load it.
*/
dm->sink_put_hook_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+10, (pa_hook_cb_t) sink_put_hook_callback, dm);
dm->sink_unlink_hook_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_EARLY, (pa_hook_cb_t) sink_unlink_hook_callback, dm);
dm->sink_state_changed_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_source_state_changed_hook_cb, dm);
+ dm->sink_proplist_changed_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_proplist_changed, 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_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->source_state_changed_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_source_state_changed_hook_cb, dm);
+ dm->source_proplist_changed_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) source_proplist_changed, 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);
pa_hook_slot_free(dm->comm_hook_device_state_changed_slot);
if (dm->comm_hook_device_running_changed_slot)
pa_hook_slot_free(dm->comm_hook_device_running_changed_slot);
+
if (dm->sink_put_hook_slot)
pa_hook_slot_free(dm->sink_put_hook_slot);
if (dm->sink_unlink_hook_slot)
pa_hook_slot_free(dm->sink_unlink_hook_slot);
if (dm->sink_state_changed_slot)
pa_hook_slot_free(dm->sink_state_changed_slot);
+ if (dm->sink_proplist_changed_slot)
+ pa_hook_slot_free(dm->sink_proplist_changed_slot);
+
if (dm->source_put_hook_slot)
pa_hook_slot_free(dm->source_put_hook_slot);
if (dm->source_unlink_hook_slot)
pa_hook_slot_free(dm->source_unlink_hook_slot);
if (dm->source_state_changed_slot)
pa_hook_slot_free(dm->source_state_changed_slot);
+ if (dm->source_proplist_changed_slot)
+ pa_hook_slot_free(dm->source_proplist_changed_slot);
if (dm->hal_interface)
pa_hal_interface_unref(dm->hal_interface);