}
static void transport_free(pa_bluetooth_transport *t) {
+ unsigned i;
+
pa_assert(t);
+ for (i = 0; i < PA_BLUETOOTH_TRANSPORT_HOOK_MAX; i++)
+ pa_hook_done(&t->hooks[i]);
+
pa_xfree(t->path);
pa_xfree(t->config);
pa_xfree(t);
dbus_bool_t value;
dbus_message_iter_get_basic(&variant_i, &value);
- if (pa_streq(key, "NREC"))
+ if (pa_streq(key, "NREC") && t->nrec != value) {
t->nrec = value;
+ pa_log_debug("Transport %s: Property 'NREC' changed to %s.", t->path, t->nrec ? "True" : "False");
+ pa_hook_fire(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED], NULL);
+ }
break;
}
return NULL;
}
-const pa_bluetooth_transport* pa_bluetooth_discovery_get_transport(pa_bluetooth_discovery *y, const char *path) {
+pa_bluetooth_transport* pa_bluetooth_discovery_get_transport(pa_bluetooth_discovery *y, const char *path) {
pa_bluetooth_device *d;
pa_bluetooth_transport *t;
void *state = NULL;
static pa_bluetooth_transport *transport_new(pa_bluetooth_discovery *y, const char *path, enum profile p, const uint8_t *config, int size) {
pa_bluetooth_transport *t;
+ unsigned i;
t = pa_xnew0(pa_bluetooth_transport, 1);
t->y = y;
memcpy(t->config, config, size);
}
+ for (i = 0; i < PA_BLUETOOTH_TRANSPORT_HOOK_MAX; i++)
+ pa_hook_init(&t->hooks[i], t);
+
return t;
}
PROFILE_OFF
};
+/* Hook data: pa_bluetooth_transport pointer. */
+typedef enum pa_bluetooth_transport_hook {
+ PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED, /* Call data: NULL. */
+ PA_BLUETOOTH_TRANSPORT_HOOK_MAX
+} pa_bluetooth_transport_hook_t;
+
struct pa_bluetooth_transport {
pa_bluetooth_discovery *y;
char *path;
uint8_t *config;
int config_size;
pa_bool_t nrec;
+
+ pa_hook hooks[PA_BLUETOOTH_TRANSPORT_HOOK_MAX];
};
/* This enum is shared among Audio, Headset, AudioSink, and AudioSource, although not all values are acceptable in all profiles */
const pa_bluetooth_device* pa_bluetooth_discovery_get_by_path(pa_bluetooth_discovery *d, const char* path);
const pa_bluetooth_device* pa_bluetooth_discovery_get_by_address(pa_bluetooth_discovery *d, const char* address);
-const pa_bluetooth_transport* pa_bluetooth_discovery_get_transport(pa_bluetooth_discovery *y, const char *path);
+pa_bluetooth_transport* pa_bluetooth_discovery_get_transport(pa_bluetooth_discovery *y, const char *path);
const pa_bluetooth_transport* pa_bluetooth_device_get_transport(const pa_bluetooth_device *d, enum profile profile);
int pa_bluetooth_transport_acquire(const pa_bluetooth_transport *t, const char *accesstype, size_t *imtu, size_t *omtu);
void (*sco_source_set_volume)(pa_source *s);
pa_hook_slot *sink_state_changed_slot;
pa_hook_slot *source_state_changed_slot;
+ pa_hook_slot *nrec_changed_slot;
};
struct bluetooth_msg {
pa_source_volume_changed(u->source, &v);
}
}
- } else if (dbus_message_is_signal(m, "org.bluez.MediaTransport", "PropertyChanged")) {
- DBusMessageIter arg_i;
- pa_bluetooth_transport *t;
- pa_bool_t nrec;
-
- t = (pa_bluetooth_transport *) pa_bluetooth_discovery_get_transport(u->discovery, u->transport);
- pa_assert(t);
-
- if (!dbus_message_iter_init(m, &arg_i)) {
- pa_log("Failed to parse PropertyChanged: %s", err.message);
- goto fail;
- }
-
- nrec = t->nrec;
-
- if (pa_bluetooth_transport_parse_property(t, &arg_i) < 0)
- goto fail;
-
- if (nrec != t->nrec) {
- pa_log_debug("dbus: property 'NREC' changed to value '%s'", t->nrec ? "True" : "False");
- pa_proplist_sets(u->source->proplist, "bluetooth.nrec", t->nrec ? "1" : "0");
- }
} else if (dbus_message_is_signal(m, "org.bluez.HandsfreeGateway", "PropertyChanged")) {
const char *key;
DBusMessageIter iter;
return PA_HOOK_OK;
}
+static pa_hook_result_t nrec_changed_cb(pa_bluetooth_transport *t, void *call_data, struct userdata *u) {
+ pa_proplist *p;
+
+ pa_assert(t);
+ pa_assert(u);
+
+ p = pa_proplist_new();
+ pa_proplist_sets(p, "bluetooth.nrec", t->nrec ? "1" : "0");
+ pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, p);
+ pa_proplist_free(p);
+
+ return PA_HOOK_OK;
+}
+
static void connect_ports(struct userdata *u, void *sink_or_source_new_data, pa_direction_t direction) {
union {
pa_sink_new_data *sink_new_data;
if ((u->profile == PROFILE_HSP) || (u->profile == PROFILE_HFGW)) {
if (u->transport) {
- const pa_bluetooth_transport *t;
+ pa_bluetooth_transport *t;
t = pa_bluetooth_discovery_get_transport(u->discovery, u->transport);
pa_assert(t);
pa_proplist_sets(u->source->proplist, "bluetooth.nrec", t->nrec ? "1" : "0");
+
+ if (!u->hsp.nrec_changed_slot)
+ u->hsp.nrec_changed_slot = pa_hook_connect(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) nrec_changed_cb, u);
} else
pa_proplist_sets(u->source->proplist, "bluetooth.nrec", (u->hsp.pcm_capabilities.flags & BT_PCM_FLAG_NREC) ? "1" : "0");
}
u->hsp.source_state_changed_slot = NULL;
}
+ if (u->hsp.nrec_changed_slot) {
+ pa_hook_slot_free(u->hsp.nrec_changed_slot);
+ u->hsp.nrec_changed_slot = NULL;
+ }
+
if (u->sink) {
if (u->profile == PROFILE_HSP) {
k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink);