mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-06 13:30:01 -05:00
media-session: add config files
Remove -e and -d options Manage modules in media-session.conf Add alsa-monitor.conf that can match node/device properties with a regex and update properties on it. All previous configuration and more cane be done with this.
This commit is contained in:
parent
389a125488
commit
24c68b0067
6 changed files with 383 additions and 154 deletions
|
|
@ -27,6 +27,7 @@
|
|||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
#include <spa/utils/hook.h>
|
||||
#include <spa/utils/names.h>
|
||||
#include <spa/utils/keys.h>
|
||||
#include <spa/utils/json.h>
|
||||
#include <spa/param/props.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/pod/parser.h>
|
||||
|
|
@ -55,6 +57,8 @@
|
|||
|
||||
#include "reserve.c"
|
||||
|
||||
#define SESSION_CONF "alsa-monitor.conf"
|
||||
|
||||
#define DEFAULT_JACK_SECONDS 1
|
||||
|
||||
struct node {
|
||||
|
|
@ -102,6 +106,7 @@ struct device {
|
|||
unsigned int first:1;
|
||||
unsigned int appeared:1;
|
||||
unsigned int probed:1;
|
||||
unsigned int use_acp:1;
|
||||
struct spa_list node_list;
|
||||
};
|
||||
|
||||
|
|
@ -109,6 +114,8 @@ struct impl {
|
|||
struct sm_media_session *session;
|
||||
struct spa_hook session_listener;
|
||||
|
||||
struct pw_properties *conf;
|
||||
|
||||
DBusConnection *conn;
|
||||
|
||||
struct spa_handle *handle;
|
||||
|
|
@ -120,8 +127,6 @@ struct impl {
|
|||
|
||||
struct spa_source *jack_timeout;
|
||||
struct pw_proxy *jack_device;
|
||||
|
||||
unsigned int use_acp:1;
|
||||
};
|
||||
|
||||
#undef NAME
|
||||
|
|
@ -192,6 +197,111 @@ static const struct sm_object_methods node_methods = {
|
|||
.release = node_release,
|
||||
};
|
||||
|
||||
static bool find_match(struct spa_json *arr, struct pw_properties *props)
|
||||
{
|
||||
struct spa_json it[1];
|
||||
|
||||
while (spa_json_enter_object(arr, &it[0]) > 0) {
|
||||
char key[256], val[1024];
|
||||
const char *str, *value;
|
||||
int match = 0, fail = 0;
|
||||
int len;
|
||||
|
||||
while (spa_json_get_string(&it[0], key, sizeof(key)-1) > 0) {
|
||||
bool success = false;
|
||||
|
||||
if ((len = spa_json_next(&it[0], &value)) <= 0)
|
||||
break;
|
||||
|
||||
if (key[0] == '#')
|
||||
continue;
|
||||
|
||||
str = pw_properties_get(props, key);
|
||||
if (spa_json_is_null(value, len)) {
|
||||
success = str == NULL;
|
||||
}
|
||||
else if (spa_json_is_string(value, len)) {
|
||||
spa_json_parse_string(value, SPA_MIN(len, 1024), val);
|
||||
value = val;
|
||||
len = strlen(val);
|
||||
}
|
||||
if (str != NULL) {
|
||||
if (value[0] == '~') {
|
||||
regex_t preg;
|
||||
if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) {
|
||||
if (regexec(&preg, str, 0, NULL, 0) == 0)
|
||||
success = true;
|
||||
regfree(&preg);
|
||||
}
|
||||
} else if (strncmp(str, value, len) == 0) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
match++;
|
||||
pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value);
|
||||
}
|
||||
else
|
||||
fail++;
|
||||
}
|
||||
if (match > 0 && fail == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int apply_matches(struct impl *impl, struct pw_properties *props)
|
||||
{
|
||||
const char *rules, *val;
|
||||
struct spa_json it[4], actions;;
|
||||
|
||||
if ((rules = pw_properties_get(impl->conf, "rules")) == NULL)
|
||||
return 0;
|
||||
|
||||
spa_json_init(&it[0], rules, strlen(rules));
|
||||
if (spa_json_enter_array(&it[0], &it[1]) < 0)
|
||||
return 0;
|
||||
|
||||
while (spa_json_enter_object(&it[1], &it[2]) > 0) {
|
||||
char key[64];
|
||||
bool have_match = false, have_actions = false;
|
||||
|
||||
while (spa_json_get_string(&it[2], key, sizeof(key)-1) > 0) {
|
||||
if (strcmp(key, "matches") == 0) {
|
||||
if (spa_json_enter_array(&it[2], &it[3]) < 0)
|
||||
break;
|
||||
|
||||
have_match = find_match(&it[3], props);
|
||||
}
|
||||
else if (strcmp(key, "actions") == 0) {
|
||||
if (spa_json_enter_object(&it[2], &actions) > 0)
|
||||
have_actions = true;
|
||||
}
|
||||
else if (spa_json_next(&it[2], &val) <= 0)
|
||||
break;
|
||||
}
|
||||
if (!have_match || !have_actions)
|
||||
continue;
|
||||
|
||||
while (spa_json_get_string(&actions, key, sizeof(key)-1) > 0) {
|
||||
int len;
|
||||
pw_log_debug("action %s", key);
|
||||
if (strcmp(key, "update-props") == 0) {
|
||||
if ((len = spa_json_next(&actions, &val)) <= 0)
|
||||
continue;
|
||||
if (!spa_json_is_object(val, len))
|
||||
continue;
|
||||
len = spa_json_container_len(&actions, val, len);
|
||||
|
||||
pw_properties_update_string(props, val, len);
|
||||
}
|
||||
else if (spa_json_next(&actions, &val) <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct node *alsa_create_node(struct device *device, uint32_t id,
|
||||
const struct spa_device_object_info *info)
|
||||
{
|
||||
|
|
@ -314,6 +424,9 @@ static struct node *alsa_create_node(struct device *device, uint32_t id,
|
|||
node->impl = impl;
|
||||
node->device = device;
|
||||
node->id = id;
|
||||
|
||||
apply_matches(impl, node->props);
|
||||
|
||||
node->snode = sm_media_session_create_node(impl->session,
|
||||
"adapter",
|
||||
&node->props->dict);
|
||||
|
|
@ -517,11 +630,10 @@ static int update_device_props(struct device *device)
|
|||
|
||||
static void set_profile(struct device *device, int index)
|
||||
{
|
||||
struct impl *impl = device->impl;
|
||||
char buf[1024];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
|
||||
|
||||
if (impl->use_acp)
|
||||
if (device->use_acp)
|
||||
return;
|
||||
|
||||
pw_log_debug("%p: set profile %d id:%d", device, index, device->device_id);
|
||||
|
|
@ -795,7 +907,7 @@ static struct device *alsa_create_device(struct impl *impl, uint32_t id,
|
|||
{
|
||||
struct device *device;
|
||||
int res;
|
||||
const char *str, *card, *factory_name, *name;
|
||||
const char *str, *card;
|
||||
|
||||
pw_log_debug("new device %u", id);
|
||||
|
||||
|
|
@ -810,12 +922,6 @@ static struct device *alsa_create_device(struct impl *impl, uint32_t id,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (impl->use_acp)
|
||||
factory_name = SPA_NAME_API_ALSA_ACP_DEVICE;
|
||||
else
|
||||
factory_name = info->factory_name;
|
||||
|
||||
device->factory_name = strdup(factory_name);
|
||||
device->impl = impl;
|
||||
device->id = id;
|
||||
device->props = pw_properties_new_dict(info->props);
|
||||
|
|
@ -826,23 +932,14 @@ static struct device *alsa_create_device(struct impl *impl, uint32_t id,
|
|||
device->pending_profile = 1;
|
||||
spa_list_append(&impl->device_list, &device->link);
|
||||
|
||||
name = pw_properties_get(device->props, "device.name");
|
||||
apply_matches(impl, device->props);
|
||||
|
||||
if ((str = pw_properties_get(impl->session->props, "alsa.soft-mixer")) != NULL &&
|
||||
(strcmp(str, "*") == 0 ||
|
||||
(name != NULL && strstr(str, name) != NULL))) {
|
||||
pw_properties_set(device->props, "api.alsa.soft-mixer", "true");
|
||||
}
|
||||
if ((str = pw_properties_get(impl->session->props, "alsa.no-auto-port")) != NULL &&
|
||||
(strcmp(str, "*") == 0 ||
|
||||
(name != NULL && strstr(str, name) != NULL))) {
|
||||
pw_properties_set(device->props, "api.acp.auto-port", "false");
|
||||
}
|
||||
if ((str = pw_properties_get(impl->session->props, "alsa.no-auto-profile")) != NULL &&
|
||||
(strcmp(str, "*") == 0 ||
|
||||
(name != NULL && strstr(str, name) != NULL))) {
|
||||
pw_properties_set(device->props, "api.acp.auto-profile", "false");
|
||||
}
|
||||
str = pw_properties_get(device->props, "api.alsa.use-acp");
|
||||
device->use_acp = str ? pw_properties_parse_bool(str) : true;
|
||||
if (device->use_acp)
|
||||
device->factory_name = strdup(SPA_NAME_API_ALSA_ACP_DEVICE);
|
||||
else
|
||||
device->factory_name = strdup(info->factory_name);
|
||||
|
||||
if (impl->conn &&
|
||||
(card = spa_dict_lookup(info->props, SPA_KEY_API_ALSA_CARD)) != NULL) {
|
||||
|
|
@ -941,6 +1038,7 @@ static void session_destroy(void *data)
|
|||
spa_hook_remove(&impl->listener);
|
||||
pw_proxy_destroy(impl->jack_device);
|
||||
pw_unload_spa_handle(impl->handle);
|
||||
pw_properties_free(impl->conf);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
|
|
@ -954,7 +1052,6 @@ int sm_alsa_monitor_start(struct sm_media_session *session)
|
|||
struct pw_context *context = session->context;
|
||||
struct impl *impl;
|
||||
void *iface;
|
||||
const char *str;
|
||||
int res;
|
||||
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
|
|
@ -962,9 +1059,15 @@ int sm_alsa_monitor_start(struct sm_media_session *session)
|
|||
return -errno;
|
||||
|
||||
impl->session = session;
|
||||
impl->conf = pw_properties_new(NULL, NULL);
|
||||
if (impl->conf == NULL) {
|
||||
free(impl);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ((str = pw_properties_get(session->props, "alsa.use-acp")) != NULL)
|
||||
impl->use_acp = pw_properties_parse_bool(str);
|
||||
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 (session->dbus_connection)
|
||||
impl->conn = spa_dbus_connection_get(session->dbus_connection);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue