bluez5: move bluez-hardware.conf loading to the plugin

It's not really the responsibility of the session manager to load the
bluez5 device quirks, and it's easier for eg. Wireplumber if it doesn't
need to do it.

Move loading bluez-hardware.conf to be the responsibility of the bluez5
spa plugin, similarly as the alsa plugin deals with the ACP database.

Put the configuration to share/spa-0.2/bluez5, mirroring the plugin
directory structure in lib/spa-0.2/bluez5.
This commit is contained in:
Pauli Virtanen 2021-09-18 12:32:29 +03:00 committed by Wim Taymans
parent 6168067cb2
commit cae1554449
6 changed files with 84 additions and 28 deletions

View file

@ -54,6 +54,7 @@ else
endif
spa_plugindir = pipewire_libdir / spa_name
spa_datadir = pipewire_datadir / spa_name
alsadatadir = pipewire_datadir / 'alsa-card-profile' / 'mixer'
@ -198,6 +199,7 @@ cdata.set_quoted('PACKAGE_VERSION', pipewire_version)
cdata.set_quoted('MODULEDIR', modules_install_dir)
cdata.set_quoted('PIPEWIRE_CONFIG_DIR', pipewire_configdir)
cdata.set_quoted('PLUGINDIR', spa_plugindir)
cdata.set_quoted('SPADATADIR', spa_datadir)
# FIXME: --with-memory-alignment],[8,N,malloc,pagesize (default is 32)]) option
cdata.set('MEMORY_ALIGNMENT_MALLOC', 1)
cdata.set_quoted('PA_ALSA_PATHS_DIR', alsadatadir / 'paths')
@ -467,6 +469,7 @@ if meson.version().version_compare('>=0.58.0')
devenv.set('PIPEWIRE_MODULE_DIR', builddir / 'src' / 'modules')
devenv.set('SPA_PLUGIN_DIR', builddir / 'spa' / 'plugins')
devenv.set('SPA_DATA_DIR', builddir / 'spa' / 'plugins')
devenv.set('GST_PLUGIN_PATH', builddir / 'src'/ 'gst')

View file

@ -32,6 +32,10 @@ bluez5_sources = ['plugin.c',
'bluez5-device.c',
'bluez5-dbus.c']
bluez5_data = ['bluez-hardware.conf']
install_data(bluez5_data, install_dir : spa_datadir / 'bluez5')
if not get_option('bluez5-backend-hsp-native').disabled() or not get_option('bluez5-backend-hfp-native').disabled()
if libusb_dep.found()
bluez5_deps += libusb_dep

View file

@ -31,7 +31,12 @@
#include <sys/socket.h>
#include <fcntl.h>
#include <regex.h>
#include <limits.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <bluetooth/bluetooth.h>
@ -163,6 +168,63 @@ static int parse_force_flag(const struct spa_dict *info, const char *key)
return (strcmp(str, "true") == 0 || atoi(str)) ? 1 : 0;
}
static void load_quirks(struct spa_bt_quirks *this, const char *str, size_t len)
{
struct spa_json data = SPA_JSON_INIT(str, len);
struct spa_json rules;
char key[1024];
if (spa_json_enter_object(&data, &rules) <= 0)
spa_json_init(&rules, str, len);
while (spa_json_get_string(&rules, key, sizeof(key)-1)) {
int sz;
const char *value;
if ((sz = spa_json_next(&rules, &value)) <= 0)
break;
if (!spa_json_is_container(value, sz))
continue;
sz = spa_json_container_len(&rules, value, sz);
if (spa_streq(key, "bluez5.features.kernel") && !this->kernel_rules)
this->kernel_rules = strndup(value, sz);
else if (spa_streq(key, "bluez5.features.adapter") && !this->adapter_rules)
this->adapter_rules = strndup(value, sz);
else if (spa_streq(key, "bluez5.features.device") && !this->device_rules)
this->device_rules = strndup(value, sz);
}
}
static int load_conf(struct spa_bt_quirks *this, const char *path)
{
char *data;
struct stat sbuf;
int fd = -1;
spa_log_debug(this->log, NAME ": loading %s", path);
if ((fd = open(path, O_CLOEXEC | O_RDONLY)) < 0)
goto fail;
if (fstat(fd, &sbuf) < 0)
goto fail;
if ((data = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
goto fail;
close(fd);
load_quirks(this, data, sbuf.st_size);
munmap(data, sbuf.st_size);
return 0;
fail:
if (fd >= 0)
close(fd);
return -errno;
}
struct spa_bt_quirks *spa_bt_quirks_create(const struct spa_dict *info, struct spa_log *log)
{
struct spa_bt_quirks *this;
@ -183,15 +245,22 @@ struct spa_bt_quirks *spa_bt_quirks_create(const struct spa_dict *info, struct s
this->force_msbc = parse_force_flag(info, "bluez5.enable-msbc");
this->force_hw_volume = parse_force_flag(info, "bluez5.enable-hw-volume");
str = spa_dict_lookup(info, "bluez5.features.kernel");
this->kernel_rules = str ? strdup(str) : NULL;
str = spa_dict_lookup(info, "bluez5.features.adapter");
this->adapter_rules = str ? strdup(str) : NULL;
str = spa_dict_lookup(info, "bluez5.features.device");
this->device_rules = str ? strdup(str) : NULL;
if ((str = spa_dict_lookup(info, "bluez5.hardware-database")) != NULL) {
spa_log_debug(this->log, NAME ": loading session manager provided data");
load_quirks(this, str, strlen(str));
} else {
char path[PATH_MAX];
const char *dir = getenv("SPA_DATA_DIR");
if (dir == NULL)
dir = SPADATADIR;
if (spa_scnprintf(path, sizeof(path), "%s/bluez5/bluez-hardware.conf", dir) >= 0)
load_conf(this, path);
}
if (!(this->kernel_rules && this->adapter_rules && this->device_rules))
spa_log_info(this->log, NAME " failed to find data from bluez-hardware.conf");
spa_log_warn(this->log, NAME ": failed to load bluez-hardware.conf");
return this;
}

View file

@ -1,5 +1,4 @@
conf_files = [
[ 'bluez-hardware.conf', 'bluez-hardware.conf' ],
[ 'bluez-monitor.conf', 'bluez-monitor.conf' ],
[ 'v4l2-monitor.conf', 'v4l2-monitor.conf' ],
[ 'media-session.conf', 'media-session.conf' ],

View file

@ -719,9 +719,7 @@ int sm_bluez5_monitor_start(struct sm_media_session *session)
{
int res;
struct impl *impl;
const char *key, *str;
struct pw_properties *hw_features = NULL;
void *state = NULL;
const char *str;
impl = calloc(1, sizeof(struct impl));
if (impl == NULL) {
@ -737,16 +735,9 @@ int sm_bluez5_monitor_start(struct sm_media_session *session)
res = -errno;
goto out_free;
}
if ((hw_features = pw_properties_new(NULL, NULL)) == NULL) {
res = -errno;
goto out_free;
}
if ((res = sm_media_session_load_conf(impl->session,
SESSION_CONF, impl->conf)) < 0)
pw_log_info("can't load "SESSION_CONF" config: %s", spa_strerror(res));
if ((res = sm_media_session_load_conf(impl->session,
FEATURES_CONF, hw_features)) < 0)
pw_log_info("can't load "FEATURES_CONF" config: %s", spa_strerror(res));
if ((impl->props = pw_properties_new(NULL, NULL)) == NULL) {
res = -errno;
@ -757,15 +748,6 @@ int sm_bluez5_monitor_start(struct sm_media_session *session)
pw_properties_set(impl->props, "api.bluez5.connection-info", "true");
while ((key = pw_properties_iterate(hw_features, &state)) != NULL) {
if (strncmp(key, "bluez5.features.", strlen("bluez5.features.")) != 0)
continue;
if ((str = pw_properties_get(hw_features, key)) != NULL)
pw_properties_set(impl->props, key, str);
}
pw_properties_free(hw_features);
sm_media_session_add_listener(session, &impl->session_listener,
&session_events, impl);
return 0;
@ -773,7 +755,6 @@ int sm_bluez5_monitor_start(struct sm_media_session *session)
out_free:
pw_properties_free(impl->conf);
pw_properties_free(impl->props);
pw_properties_free(hw_features);
free(impl);
out:
return res;