mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
bluez: fix a2dp source
Actually compile the codec config and declare the config as extern or else it's just all 0. Only acquire the transport when ACTIVE. Implement transport state_change signal and acquire the transport when going to pending/active. Try to acquire the transport before we expose the device if we can. Force device expose when we get the device ServicesResolved=1 property update. Free transport when the rfcomm is closed. Implement various DBus signals to detect dynamic property updates.
This commit is contained in:
parent
c348790ca1
commit
6cfddde39c
6 changed files with 213 additions and 34 deletions
|
|
@ -284,15 +284,15 @@ static inline int a2dp_sbc_get_frequency(a2dp_sbc_t *config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const a2dp_sbc_t bluez_a2dp_sbc;
|
extern const a2dp_sbc_t bluez_a2dp_sbc;
|
||||||
#if ENABLE_MP3
|
#if ENABLE_MP3
|
||||||
const a2dp_mpeg_t bluez_a2dp_mpeg;
|
extern const a2dp_mpeg_t bluez_a2dp_mpeg;
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_AAC
|
#if ENABLE_AAC
|
||||||
const a2dp_aac_t bluez_a2dp_aac;
|
extern const a2dp_aac_t bluez_a2dp_aac;
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_APTX
|
#if ENABLE_APTX
|
||||||
const a2dp_aptx_t bluez_a2dp_aptx;
|
extern const a2dp_aptx_t bluez_a2dp_aptx;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
|
@ -375,7 +376,8 @@ static void decode_sbc_data(struct impl *this, uint8_t *src, size_t src_size)
|
||||||
this->sample_count += data[0].chunk->size / port->frame_size;
|
this->sample_count += data[0].chunk->size / port->frame_size;
|
||||||
|
|
||||||
/* add the buffer to the queue */
|
/* add the buffer to the queue */
|
||||||
spa_log_debug(this->log, "data decoded successfully for buffer_id=%d", buffer->id);
|
spa_log_debug(this->log, "data decoded %d successfully for buffer_id=%d",
|
||||||
|
data[0].chunk->size, buffer->id);
|
||||||
spa_list_append(&port->ready, &buffer->link);
|
spa_list_append(&port->ready, &buffer->link);
|
||||||
|
|
||||||
spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_BUFFER);
|
spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_BUFFER);
|
||||||
|
|
@ -432,24 +434,19 @@ stop:
|
||||||
spa_loop_remove_source(this->data_loop, &this->source);
|
spa_loop_remove_source(this->data_loop, &this->source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_start(struct impl *this)
|
static int transport_start(struct impl *this)
|
||||||
{
|
{
|
||||||
int res, val;
|
int res, val;
|
||||||
|
|
||||||
if (this->started)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (this->transport == NULL)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
spa_log_debug(this->log, "a2dp-source %p: start", this);
|
|
||||||
|
|
||||||
if ((res = spa_bt_transport_acquire(this->transport, false)) < 0)
|
if ((res = spa_bt_transport_acquire(this->transport, false)) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
sbc_init_a2dp(&this->sbc, 0, this->transport->configuration,
|
sbc_init_a2dp(&this->sbc, 0, this->transport->configuration,
|
||||||
this->transport->configuration_len);
|
this->transport->configuration_len);
|
||||||
|
|
||||||
|
val = fcntl(this->transport->fd, F_GETFL);
|
||||||
|
fcntl(this->transport->fd, F_SETFL, val | O_NONBLOCK);
|
||||||
|
|
||||||
val = FILL_FRAMES * this->transport->write_mtu;
|
val = FILL_FRAMES * this->transport->write_mtu;
|
||||||
if (setsockopt(this->transport->fd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) < 0)
|
if (setsockopt(this->transport->fd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) < 0)
|
||||||
spa_log_warn(this->log, "a2dp-source %p: SO_SNDBUF %m", this);
|
spa_log_warn(this->log, "a2dp-source %p: SO_SNDBUF %m", this);
|
||||||
|
|
@ -472,11 +469,30 @@ static int do_start(struct impl *this)
|
||||||
spa_loop_add_source(this->data_loop, &this->source);
|
spa_loop_add_source(this->data_loop, &this->source);
|
||||||
|
|
||||||
this->sample_count = 0;
|
this->sample_count = 0;
|
||||||
this->started = true;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_start(struct impl *this)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if (this->started)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (this->transport == NULL)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
spa_log_debug(this->log, "a2dp-source %p: start", this);
|
||||||
|
|
||||||
|
if (this->transport->state == SPA_BT_TRANSPORT_STATE_ACTIVE)
|
||||||
|
res = transport_start(this);
|
||||||
|
|
||||||
|
this->started = true;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_remove_source(struct spa_loop *loop,
|
static int do_remove_source(struct spa_loop *loop,
|
||||||
bool async,
|
bool async,
|
||||||
uint32_t seq,
|
uint32_t seq,
|
||||||
|
|
@ -1039,9 +1055,20 @@ static void transport_destroy(void *data)
|
||||||
this->transport = NULL;
|
this->transport = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void transport_state_changed(void *data, enum spa_bt_transport_state old,
|
||||||
|
enum spa_bt_transport_state state)
|
||||||
|
{
|
||||||
|
struct impl *this = data;
|
||||||
|
if (state >= SPA_BT_TRANSPORT_STATE_PENDING && old < SPA_BT_TRANSPORT_STATE_PENDING) {
|
||||||
|
if (this->started)
|
||||||
|
transport_start(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct spa_bt_transport_events transport_events = {
|
static const struct spa_bt_transport_events transport_events = {
|
||||||
SPA_VERSION_BT_TRANSPORT_EVENTS,
|
SPA_VERSION_BT_TRANSPORT_EVENTS,
|
||||||
.destroy = transport_destroy,
|
.destroy = transport_destroy,
|
||||||
|
.state_changed = transport_state_changed,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int impl_get_interface(struct spa_handle *handle, uint32_t type, void **interface)
|
static int impl_get_interface(struct spa_handle *handle, uint32_t type, void **interface)
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,8 @@ static int emit_source_node(struct impl *this)
|
||||||
snprintf(transport, 16, "%p", t);
|
snprintf(transport, 16, "%p", t);
|
||||||
items[0] = SPA_DICT_ITEM_INIT("bluez5.transport", transport);
|
items[0] = SPA_DICT_ITEM_INIT("bluez5.transport", transport);
|
||||||
|
|
||||||
|
spa_bt_transport_acquire(t, true);
|
||||||
|
|
||||||
info = SPA_DEVICE_OBJECT_INFO_INIT();
|
info = SPA_DEVICE_OBJECT_INFO_INIT();
|
||||||
info.type = SPA_TYPE_INTERFACE_Node;
|
info.type = SPA_TYPE_INTERFACE_Node;
|
||||||
info.factory = &spa_a2dp_source_factory;
|
info.factory = &spa_a2dp_source_factory;
|
||||||
|
|
|
||||||
|
|
@ -434,13 +434,16 @@ static int adapter_update_props(struct spa_bt_adapter *adapter,
|
||||||
|
|
||||||
while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
|
while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
|
||||||
const char *uuid;
|
const char *uuid;
|
||||||
|
enum spa_bt_profile profile;
|
||||||
|
|
||||||
dbus_message_iter_get_basic(&iter, &uuid);
|
dbus_message_iter_get_basic(&iter, &uuid);
|
||||||
|
|
||||||
spa_log_debug(monitor->log, "adapter %p: add UUID=%s", adapter, uuid);
|
profile = spa_bt_profile_from_uuid(uuid);
|
||||||
|
|
||||||
adapter->profiles |= spa_bt_profile_from_uuid(uuid);
|
|
||||||
|
|
||||||
|
if (profile && (adapter->profiles & profile) == 0) {
|
||||||
|
spa_log_debug(monitor->log, "adapter %p: add UUID=%s", adapter, uuid);
|
||||||
|
adapter->profiles |= profile;
|
||||||
|
}
|
||||||
dbus_message_iter_next(&iter);
|
dbus_message_iter_next(&iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -615,7 +618,7 @@ static int device_stop_timer(struct spa_bt_device *device)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_profiles(struct spa_bt_device *device)
|
static int device_check_profiles(struct spa_bt_device *device, bool force)
|
||||||
{
|
{
|
||||||
struct spa_bt_monitor *monitor = device->monitor;
|
struct spa_bt_monitor *monitor = device->monitor;
|
||||||
uint32_t connected_profiles = device->connected_profiles;
|
uint32_t connected_profiles = device->connected_profiles;
|
||||||
|
|
@ -634,7 +637,7 @@ static int check_profiles(struct spa_bt_device *device)
|
||||||
device_remove(monitor, device);
|
device_remove(monitor, device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((device->profiles & connected_profiles) == device->profiles) {
|
else if (force || (device->profiles & connected_profiles) == device->profiles) {
|
||||||
device_stop_timer(device);
|
device_stop_timer(device);
|
||||||
device_add(monitor, device);
|
device_add(monitor, device);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -651,7 +654,7 @@ static void device_set_connected(struct spa_bt_device *device, int connected)
|
||||||
device->connected = connected;
|
device->connected = connected;
|
||||||
|
|
||||||
if (connected)
|
if (connected)
|
||||||
check_profiles(device);
|
device_check_profiles(device, false);
|
||||||
else
|
else
|
||||||
device_stop_timer(device);
|
device_stop_timer(device);
|
||||||
}
|
}
|
||||||
|
|
@ -659,7 +662,7 @@ static void device_set_connected(struct spa_bt_device *device, int connected)
|
||||||
static int device_connect_profile(struct spa_bt_device *device, enum spa_bt_profile profile)
|
static int device_connect_profile(struct spa_bt_device *device, enum spa_bt_profile profile)
|
||||||
{
|
{
|
||||||
device->connected_profiles |= profile;
|
device->connected_profiles |= profile;
|
||||||
check_profiles(device);
|
device_check_profiles(device, false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -720,7 +723,7 @@ static int device_update_props(struct spa_bt_device *device,
|
||||||
|
|
||||||
dbus_message_iter_get_basic(&it[1], &value);
|
dbus_message_iter_get_basic(&it[1], &value);
|
||||||
|
|
||||||
spa_log_debug(monitor->log, "device %p: %s=%d", device, key, value);
|
spa_log_debug(monitor->log, "device %p: %s=%08x", device, key, value);
|
||||||
|
|
||||||
if (strcmp(key, "Class") == 0)
|
if (strcmp(key, "Class") == 0)
|
||||||
device->bluetooth_class = value;
|
device->bluetooth_class = value;
|
||||||
|
|
@ -764,6 +767,10 @@ static int device_update_props(struct spa_bt_device *device,
|
||||||
else if (strcmp(key, "Blocked") == 0) {
|
else if (strcmp(key, "Blocked") == 0) {
|
||||||
device->blocked = value;
|
device->blocked = value;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(key, "ServicesResolved") == 0) {
|
||||||
|
if (value)
|
||||||
|
device_check_profiles(device, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(key, "UUIDs") == 0) {
|
else if (strcmp(key, "UUIDs") == 0) {
|
||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
|
|
@ -775,13 +782,15 @@ static int device_update_props(struct spa_bt_device *device,
|
||||||
|
|
||||||
while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
|
while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
|
||||||
const char *uuid;
|
const char *uuid;
|
||||||
|
enum spa_bt_profile profile;
|
||||||
|
|
||||||
dbus_message_iter_get_basic(&iter, &uuid);
|
dbus_message_iter_get_basic(&iter, &uuid);
|
||||||
|
|
||||||
spa_log_debug(monitor->log, "device %p: add UUID=%s", device, uuid);
|
profile = spa_bt_profile_from_uuid(uuid);
|
||||||
|
if (profile && (device->profiles & profile) == 0) {
|
||||||
device->profiles |= spa_bt_profile_from_uuid(uuid);
|
spa_log_debug(monitor->log, "device %p: add UUID=%s", device, uuid);
|
||||||
|
device->profiles |= profile;
|
||||||
|
}
|
||||||
dbus_message_iter_next(&iter);
|
dbus_message_iter_next(&iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -821,9 +830,26 @@ static struct spa_bt_transport *transport_create(struct spa_bt_monitor *monitor,
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
static void transport_set_state(struct spa_bt_transport *transport, enum spa_bt_transport_state state)
|
||||||
|
{
|
||||||
|
struct spa_bt_monitor *monitor = transport->monitor;
|
||||||
|
enum spa_bt_transport_state old = transport->state;
|
||||||
|
|
||||||
|
if (old != state) {
|
||||||
|
transport->state = state;
|
||||||
|
spa_log_debug(monitor->log, "transport %p: %s state changed %d -> %d",
|
||||||
|
transport, transport->path, old, state);
|
||||||
|
spa_bt_transport_emit_state_changed(transport, old, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void transport_free(struct spa_bt_transport *transport)
|
static void transport_free(struct spa_bt_transport *transport)
|
||||||
{
|
{
|
||||||
|
struct spa_bt_monitor *monitor = transport->monitor;
|
||||||
|
|
||||||
|
spa_log_debug(monitor->log, "transport %p: free %s", transport, transport->path);
|
||||||
|
|
||||||
|
transport_set_state(transport, SPA_BT_TRANSPORT_STATE_IDLE);
|
||||||
|
|
||||||
spa_bt_transport_emit_destroy(transport);
|
spa_bt_transport_emit_destroy(transport);
|
||||||
|
|
||||||
|
|
@ -877,7 +903,7 @@ static int transport_update_props(struct spa_bt_transport *transport,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(key, "State") == 0) {
|
else if (strcmp(key, "State") == 0) {
|
||||||
transport->state = spa_bt_transport_state_from_string(value);
|
transport_set_state(transport, spa_bt_transport_state_from_string(value));
|
||||||
}
|
}
|
||||||
else if (strcmp(key, "Device") == 0) {
|
else if (strcmp(key, "Device") == 0) {
|
||||||
transport->device = device_find(monitor, value);
|
transport->device = device_find(monitor, value);
|
||||||
|
|
@ -960,7 +986,6 @@ static int transport_acquire(void *data, bool optional)
|
||||||
spa_log_error(monitor->log, "Transport %s() failed for transport %s (%s)",
|
spa_log_error(monitor->log, "Transport %s() failed for transport %s (%s)",
|
||||||
method, transport->path, err.message);
|
method, transport->path, err.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbus_error_free(&err);
|
dbus_error_free(&err);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
@ -1117,7 +1142,7 @@ static DBusHandlerResult endpoint_clear_configuration(DBusConnection *conn, DBus
|
||||||
|
|
||||||
transport_free(transport);
|
transport_free(transport);
|
||||||
if (device != NULL)
|
if (device != NULL)
|
||||||
check_profiles(device);
|
device_check_profiles(device, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((r = dbus_message_new_method_return(m)) == NULL)
|
if ((r = dbus_message_new_method_return(m)) == NULL)
|
||||||
|
|
@ -1424,7 +1449,10 @@ static void rfcomm_event(struct spa_source *source)
|
||||||
spa_log_error(monitor->log, "RFCOMM write error: %s", strerror(errno));
|
spa_log_error(monitor->log, "RFCOMM write error: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
transport_free(t);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1724,6 +1752,8 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
|
||||||
|
|
||||||
sco_listen(t);
|
sco_listen(t);
|
||||||
|
|
||||||
|
spa_log_debug(monitor->log, "Transport %s available for profile %s", t->path, handler);
|
||||||
|
|
||||||
if ((r = dbus_message_new_method_return(m)) == NULL)
|
if ((r = dbus_message_new_method_return(m)) == NULL)
|
||||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||||
if (!dbus_connection_send(conn, r, NULL))
|
if (!dbus_connection_send(conn, r, NULL))
|
||||||
|
|
@ -1775,7 +1805,7 @@ static DBusHandlerResult profile_request_disconnection(DBusConnection *conn, DBu
|
||||||
if (t->profile == profile)
|
if (t->profile == profile)
|
||||||
transport_free(t);
|
transport_free(t);
|
||||||
}
|
}
|
||||||
check_profiles(d);
|
device_check_profiles(d, false);
|
||||||
|
|
||||||
if ((r = dbus_message_new_method_return(m)) == NULL)
|
if ((r = dbus_message_new_method_return(m)) == NULL)
|
||||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||||
|
|
@ -2039,6 +2069,120 @@ static void get_managed_objects(struct spa_bt_monitor *monitor)
|
||||||
dbus_message_unref(m);
|
dbus_message_unref(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *user_data)
|
||||||
|
{
|
||||||
|
struct spa_bt_monitor *monitor = user_data;
|
||||||
|
DBusError err;
|
||||||
|
|
||||||
|
dbus_error_init(&err);
|
||||||
|
|
||||||
|
if (dbus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged")) {
|
||||||
|
spa_log_debug(monitor->log, "Name owner changed %s", dbus_message_get_path(m));
|
||||||
|
} else if (dbus_message_is_signal(m, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded")) {
|
||||||
|
spa_log_debug(monitor->log, "interfaces added %s", dbus_message_get_path(m));
|
||||||
|
} else if (dbus_message_is_signal(m, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved")) {
|
||||||
|
spa_log_debug(monitor->log, "interfaces removed %s", dbus_message_get_path(m));
|
||||||
|
} else if (dbus_message_is_signal(m, "org.freedesktop.DBus.Properties", "PropertiesChanged")) {
|
||||||
|
DBusMessageIter it[2];
|
||||||
|
const char *iface, *path;
|
||||||
|
|
||||||
|
if (!dbus_message_iter_init(m, &it[0]) ||
|
||||||
|
strcmp(dbus_message_get_signature(m), "sa{sv}as") != 0) {
|
||||||
|
spa_log_error(monitor->log, "Invalid signature found in PropertiesChanged");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
path = dbus_message_get_path(m);
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&it[0], &iface);
|
||||||
|
dbus_message_iter_next(&it[0]);
|
||||||
|
dbus_message_iter_recurse(&it[0], &it[1]);
|
||||||
|
|
||||||
|
if (strcmp(iface, BLUEZ_ADAPTER_INTERFACE) == 0) {
|
||||||
|
struct spa_bt_adapter *a;
|
||||||
|
|
||||||
|
a = adapter_find(monitor, path);
|
||||||
|
if (a == NULL) {
|
||||||
|
spa_log_warn(monitor->log,
|
||||||
|
"Properties changed in unknown adapter %s", path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
spa_log_debug(monitor->log, "Properties changed in adapter %s", path);
|
||||||
|
|
||||||
|
adapter_update_props(a, &it[1], NULL);
|
||||||
|
}
|
||||||
|
else if (strcmp(iface, BLUEZ_DEVICE_INTERFACE) == 0) {
|
||||||
|
struct spa_bt_device *d;
|
||||||
|
|
||||||
|
d = device_find(monitor, path);
|
||||||
|
if (d == NULL) {
|
||||||
|
spa_log_warn(monitor->log,
|
||||||
|
"Properties changed in unknown device %s", path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
spa_log_debug(monitor->log, "Properties changed in device %s", path);
|
||||||
|
|
||||||
|
device_update_props(d, &it[1], NULL);
|
||||||
|
}
|
||||||
|
else if (strcmp(iface, BLUEZ_MEDIA_TRANSPORT_INTERFACE) == 0) {
|
||||||
|
struct spa_bt_transport *transport;
|
||||||
|
|
||||||
|
transport = transport_find(monitor, path);
|
||||||
|
if (transport == NULL) {
|
||||||
|
spa_log_warn(monitor->log,
|
||||||
|
"Properties changed in unknown transport %s", path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
spa_log_debug(monitor->log, "Properties changed in transport %s", path);
|
||||||
|
|
||||||
|
transport_update_props(transport, &it[1], NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_filters(struct spa_bt_monitor *this)
|
||||||
|
{
|
||||||
|
DBusError err;
|
||||||
|
|
||||||
|
dbus_error_init(&err);
|
||||||
|
|
||||||
|
if (!dbus_connection_add_filter(this->conn, filter_cb, this, NULL)) {
|
||||||
|
spa_log_error(this->log, "failed to add filter function");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_bus_add_match(this->conn,
|
||||||
|
"type='signal',sender='org.freedesktop.DBus',"
|
||||||
|
"interface='org.freedesktop.DBus',member='NameOwnerChanged',"
|
||||||
|
"arg0='" BLUEZ_SERVICE "'", &err);
|
||||||
|
dbus_bus_add_match(this->conn,
|
||||||
|
"type='signal',sender='" BLUEZ_SERVICE "',"
|
||||||
|
"interface='org.freedesktop.DBus.ObjectManager',member='InterfacesAdded'", &err);
|
||||||
|
dbus_bus_add_match(this->conn,
|
||||||
|
"type='signal',sender='" BLUEZ_SERVICE "',"
|
||||||
|
"interface='org.freedesktop.DBus.ObjectManager',member='InterfacesRemoved'", &err);
|
||||||
|
dbus_bus_add_match(this->conn,
|
||||||
|
"type='signal',sender='" BLUEZ_SERVICE "',"
|
||||||
|
"interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',"
|
||||||
|
"arg0='" BLUEZ_ADAPTER_INTERFACE "'", &err);
|
||||||
|
dbus_bus_add_match(this->conn,
|
||||||
|
"type='signal',sender='" BLUEZ_SERVICE "',"
|
||||||
|
"interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',"
|
||||||
|
"arg0='" BLUEZ_DEVICE_INTERFACE "'", &err);
|
||||||
|
dbus_bus_add_match(this->conn,
|
||||||
|
"type='signal',sender='" BLUEZ_SERVICE "',"
|
||||||
|
"interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',"
|
||||||
|
"arg0='" BLUEZ_MEDIA_TRANSPORT_INTERFACE "'", &err);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
dbus_error_free(&err);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
impl_monitor_set_callbacks(struct spa_monitor *monitor,
|
impl_monitor_set_callbacks(struct spa_monitor *monitor,
|
||||||
const struct spa_monitor_callbacks *callbacks,
|
const struct spa_monitor_callbacks *callbacks,
|
||||||
|
|
@ -2053,6 +2197,7 @@ impl_monitor_set_callbacks(struct spa_monitor *monitor,
|
||||||
this->callbacks = SPA_CALLBACKS_INIT(callbacks, data);
|
this->callbacks = SPA_CALLBACKS_INIT(callbacks, data);
|
||||||
|
|
||||||
if (callbacks) {
|
if (callbacks) {
|
||||||
|
add_filters(this);
|
||||||
get_managed_objects(this);
|
get_managed_objects(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,8 @@ struct spa_bt_transport_events {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
|
||||||
void (*destroy) (void *data);
|
void (*destroy) (void *data);
|
||||||
|
void (*state_changed) (void *data, enum spa_bt_transport_state old,
|
||||||
|
enum spa_bt_transport_state state);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct spa_bt_transport_implementation {
|
struct spa_bt_transport_implementation {
|
||||||
|
|
@ -220,9 +222,11 @@ struct spa_bt_transport {
|
||||||
struct spa_callbacks impl;
|
struct spa_callbacks impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define spa_bt_transport_emit(t,m,v,...) spa_hook_list_call(&(t)->listener_list, \
|
#define spa_bt_transport_emit(t,m,v,...) spa_hook_list_call(&(t)->listener_list, \
|
||||||
struct spa_bt_transport_events, m, v, ##__VA_ARGS__)
|
struct spa_bt_transport_events, \
|
||||||
#define spa_bt_transport_emit_destroy(t) spa_bt_transport_emit(t, destroy, 0)
|
m, v, ##__VA_ARGS__)
|
||||||
|
#define spa_bt_transport_emit_destroy(t) spa_bt_transport_emit(t, destroy, 0)
|
||||||
|
#define spa_bt_transport_emit_state_changed(t,...) spa_bt_transport_emit(t, state_changed, 0, __VA_ARGS__)
|
||||||
|
|
||||||
#define spa_bt_transport_add_listener(t,listener,events,data) \
|
#define spa_bt_transport_add_listener(t,listener,events,data) \
|
||||||
spa_hook_list_append(&(t)->listener_list, listener, events, data)
|
spa_hook_list_append(&(t)->listener_list, listener, events, data)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
bluez5_sources = ['plugin.c',
|
bluez5_sources = ['plugin.c',
|
||||||
|
'a2dp-codecs.c',
|
||||||
'a2dp-sink.c',
|
'a2dp-sink.c',
|
||||||
'a2dp-source.c',
|
'a2dp-source.c',
|
||||||
'bluez5-device.c',
|
'bluez5-device.c',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue