diff --git a/meson.build b/meson.build index ea35ac674..fe805a373 100644 --- a/meson.build +++ b/meson.build @@ -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') diff --git a/src/daemon/media-session.d/bluez-hardware.conf b/spa/plugins/bluez5/bluez-hardware.conf similarity index 100% rename from src/daemon/media-session.d/bluez-hardware.conf rename to spa/plugins/bluez5/bluez-hardware.conf diff --git a/spa/plugins/bluez5/meson.build b/spa/plugins/bluez5/meson.build index 6e763f2df..d8b881be2 100644 --- a/spa/plugins/bluez5/meson.build +++ b/spa/plugins/bluez5/meson.build @@ -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 diff --git a/spa/plugins/bluez5/quirks.c b/spa/plugins/bluez5/quirks.c index 14e4c335c..37079fc54 100644 --- a/spa/plugins/bluez5/quirks.c +++ b/spa/plugins/bluez5/quirks.c @@ -31,7 +31,12 @@ #include #include #include +#include #include +#include +#include +#include +#include #include @@ -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; } diff --git a/src/daemon/media-session.d/meson.build b/src/daemon/media-session.d/meson.build index ef6acfa55..db4e41e4e 100644 --- a/src/daemon/media-session.d/meson.build +++ b/src/daemon/media-session.d/meson.build @@ -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' ], diff --git a/src/examples/media-session/bluez-monitor.c b/src/examples/media-session/bluez-monitor.c index 2b74f52da..59c9baa44 100644 --- a/src/examples/media-session/bluez-monitor.c +++ b/src/examples/media-session/bluez-monitor.c @@ -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;