mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-09-20 00:11:31 +00:00
settings: Add more runtime settings
Move settings defaults initialization to the settings file. Expose clock.rate, clock.allowed-rates and clock.quantum as runtime settings.
This commit is contained in:
parent
5cff20eba4
commit
1b06d4d7c4
|
@ -40,7 +40,6 @@
|
|||
#include <spa/utils/string.h>
|
||||
#include <spa/debug/format.h>
|
||||
#include <spa/debug/types.h>
|
||||
#include <spa/utils/json.h>
|
||||
|
||||
#include <pipewire/impl.h>
|
||||
#include <pipewire/private.h>
|
||||
|
@ -52,19 +51,6 @@
|
|||
PW_LOG_TOPIC_EXTERN(log_context);
|
||||
#define PW_LOG_TOPIC_DEFAULT log_context
|
||||
|
||||
#define DEFAULT_CLOCK_RATE 48000u
|
||||
#define DEFAULT_CLOCK_QUANTUM 1024u
|
||||
#define DEFAULT_CLOCK_MIN_QUANTUM 32u
|
||||
#define DEFAULT_CLOCK_MAX_QUANTUM 8192u
|
||||
#define DEFAULT_CLOCK_POWER_OF_TWO_QUANTUM true
|
||||
#define DEFAULT_VIDEO_WIDTH 640
|
||||
#define DEFAULT_VIDEO_HEIGHT 480
|
||||
#define DEFAULT_VIDEO_RATE_NUM 25u
|
||||
#define DEFAULT_VIDEO_RATE_DENOM 1u
|
||||
#define DEFAULT_LINK_MAX_BUFFERS 64u
|
||||
#define DEFAULT_MEM_WARN_MLOCK false
|
||||
#define DEFAULT_MEM_ALLOW_MLOCK true
|
||||
|
||||
/** \cond */
|
||||
struct impl {
|
||||
struct pw_context this;
|
||||
|
@ -115,101 +101,6 @@ static void fill_properties(struct pw_context *context)
|
|||
pw_properties_set(properties, PW_KEY_CORE_NAME, context->core->info.name);
|
||||
}
|
||||
|
||||
static uint32_t get_default_int(struct pw_properties *properties, const char *name, uint32_t def)
|
||||
{
|
||||
uint32_t val;
|
||||
const char *str;
|
||||
if ((str = pw_properties_get(properties, name)) != NULL)
|
||||
val = atoi(str);
|
||||
else {
|
||||
val = def;
|
||||
pw_properties_setf(properties, name, "%d", val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static bool get_default_bool(struct pw_properties *properties, const char *name, bool def)
|
||||
{
|
||||
bool val;
|
||||
const char *str;
|
||||
if ((str = pw_properties_get(properties, name)) != NULL)
|
||||
val = pw_properties_parse_bool(str);
|
||||
else {
|
||||
val = def;
|
||||
pw_properties_set(properties, name, val ? "true" : "false");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static bool rates_contains(uint32_t *rates, uint32_t n_rates, uint32_t rate)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < n_rates; i++)
|
||||
if (rates[i] == rate)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t parse_clock_rate(struct pw_properties *properties, const char *name,
|
||||
uint32_t *rates, uint32_t def)
|
||||
{
|
||||
const char *str;
|
||||
uint32_t count = 0, r;
|
||||
struct spa_json it[2];
|
||||
char v[256];
|
||||
|
||||
if ((str = pw_properties_get(properties, name)) == NULL)
|
||||
goto fallback;
|
||||
|
||||
spa_json_init(&it[0], str, strlen(str));
|
||||
if (spa_json_enter_array(&it[0], &it[1]) <= 0)
|
||||
spa_json_init(&it[1], str, strlen(str));
|
||||
|
||||
while (spa_json_get_string(&it[1], v, sizeof(v)-1) > 0 &&
|
||||
count < MAX_RATES) {
|
||||
if (spa_atou32(v, &r, 0))
|
||||
rates[count++] = r;
|
||||
}
|
||||
if (count == 0 ||!rates_contains(rates, count, def))
|
||||
goto fallback;
|
||||
|
||||
return count;
|
||||
fallback:
|
||||
rates[0] = def;
|
||||
pw_properties_setf(properties, name, "[ %u ]", def);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void fill_defaults(struct pw_context *this)
|
||||
{
|
||||
struct pw_properties *p = this->properties;
|
||||
struct settings *d = &this->defaults;
|
||||
|
||||
d->clock_rate = get_default_int(p, "default.clock.rate", DEFAULT_CLOCK_RATE);
|
||||
d->n_clock_rates = parse_clock_rate(p, "default.clock.allowed-rates", d->clock_rates, d->clock_rate);
|
||||
d->clock_quantum = get_default_int(p, "default.clock.quantum", DEFAULT_CLOCK_QUANTUM);
|
||||
d->clock_min_quantum = get_default_int(p, "default.clock.min-quantum", DEFAULT_CLOCK_MIN_QUANTUM);
|
||||
d->clock_max_quantum = get_default_int(p, "default.clock.max-quantum", DEFAULT_CLOCK_MAX_QUANTUM);
|
||||
d->video_size.width = get_default_int(p, "default.video.width", DEFAULT_VIDEO_WIDTH);
|
||||
d->video_size.height = get_default_int(p, "default.video.height", DEFAULT_VIDEO_HEIGHT);
|
||||
d->video_rate.num = get_default_int(p, "default.video.rate.num", DEFAULT_VIDEO_RATE_NUM);
|
||||
d->video_rate.denom = get_default_int(p, "default.video.rate.denom", DEFAULT_VIDEO_RATE_DENOM);
|
||||
|
||||
d->log_level = get_default_int(p, "log.level", pw_log_level);
|
||||
d->clock_power_of_two_quantum = get_default_bool(p, "clock.power-of-two-quantum",
|
||||
DEFAULT_CLOCK_POWER_OF_TWO_QUANTUM);
|
||||
d->link_max_buffers = get_default_int(p, "link.max-buffers", DEFAULT_LINK_MAX_BUFFERS);
|
||||
d->mem_warn_mlock = get_default_bool(p, "mem.warn-mlock", DEFAULT_MEM_WARN_MLOCK);
|
||||
d->mem_allow_mlock = get_default_bool(p, "mem.allow-mlock", DEFAULT_MEM_ALLOW_MLOCK);
|
||||
|
||||
d->clock_max_quantum = SPA_CLAMP(d->clock_max_quantum,
|
||||
CLOCK_MIN_QUANTUM, CLOCK_MAX_QUANTUM);
|
||||
d->clock_min_quantum = SPA_CLAMP(d->clock_min_quantum,
|
||||
CLOCK_MIN_QUANTUM, d->clock_max_quantum);
|
||||
d->clock_quantum = SPA_CLAMP(d->clock_quantum,
|
||||
d->clock_min_quantum, d->clock_max_quantum);
|
||||
}
|
||||
|
||||
static int try_load_conf(struct pw_context *this, const char *conf_prefix,
|
||||
const char *conf_name, struct pw_properties *conf)
|
||||
{
|
||||
|
@ -291,6 +182,7 @@ static void init_plugin_loader(struct impl *impl)
|
|||
*
|
||||
* \param main_loop the main loop to use
|
||||
* \param properties extra properties for the context, ownership it taken
|
||||
*
|
||||
* \return a newly allocated context object
|
||||
*/
|
||||
SPA_EXPORT
|
||||
|
@ -415,7 +307,7 @@ struct pw_context *pw_context_new(struct pw_loop *main_loop,
|
|||
pw_log_info("%p: mlockall succeeded", impl);
|
||||
}
|
||||
|
||||
fill_defaults(this);
|
||||
pw_settings_init(this);
|
||||
this->settings = this->defaults;
|
||||
|
||||
pr = pw_properties_copy(properties);
|
||||
|
@ -500,7 +392,7 @@ struct pw_context *pw_context_new(struct pw_loop *main_loop,
|
|||
|
||||
context_set_freewheel(this, false);
|
||||
|
||||
pw_settings_init(this);
|
||||
pw_settings_expose(this);
|
||||
|
||||
pw_log_debug("%p: created", this);
|
||||
|
||||
|
@ -1148,6 +1040,15 @@ static int fraction_compare(const struct spa_fraction *a, const struct spa_fract
|
|||
return fa < fb ? -1 : (fa > fb ? 1 : 0);
|
||||
}
|
||||
|
||||
static bool rates_contains(uint32_t *rates, uint32_t n_rates, uint32_t rate)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < n_rates; i++)
|
||||
if (rates[i] == rate)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int pw_context_recalc_graph(struct pw_context *context, const char *reason)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF(context, struct impl, this);
|
||||
|
|
|
@ -1261,7 +1261,8 @@ bool pw_log_is_default(void);
|
|||
void pw_log_init(void);
|
||||
void pw_log_deinit(void);
|
||||
|
||||
int pw_settings_init(struct pw_context *context);
|
||||
void pw_settings_init(struct pw_context *context);
|
||||
int pw_settings_expose(struct pw_context *context);
|
||||
void pw_settings_clean(struct pw_context *context);
|
||||
|
||||
/** \endcond */
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <spa/monitor/device.h>
|
||||
#include <spa/monitor/utils.h>
|
||||
#include <spa/pod/filter.h>
|
||||
#include <spa/utils/json.h>
|
||||
|
||||
#include <pipewire/impl.h>
|
||||
#include <pipewire/private.h>
|
||||
|
@ -39,6 +40,19 @@
|
|||
|
||||
#define NAME "settings"
|
||||
|
||||
#define DEFAULT_CLOCK_RATE 48000u
|
||||
#define DEFAULT_CLOCK_QUANTUM 1024u
|
||||
#define DEFAULT_CLOCK_MIN_QUANTUM 32u
|
||||
#define DEFAULT_CLOCK_MAX_QUANTUM 8192u
|
||||
#define DEFAULT_CLOCK_POWER_OF_TWO_QUANTUM true
|
||||
#define DEFAULT_VIDEO_WIDTH 640
|
||||
#define DEFAULT_VIDEO_HEIGHT 480
|
||||
#define DEFAULT_VIDEO_RATE_NUM 25u
|
||||
#define DEFAULT_VIDEO_RATE_DENOM 1u
|
||||
#define DEFAULT_LINK_MAX_BUFFERS 64u
|
||||
#define DEFAULT_MEM_WARN_MLOCK false
|
||||
#define DEFAULT_MEM_ALLOW_MLOCK true
|
||||
|
||||
struct impl {
|
||||
struct pw_context *context;
|
||||
struct pw_impl_metadata *metadata;
|
||||
|
@ -53,6 +67,81 @@ static void metadata_destroy(void *data)
|
|||
impl->metadata = NULL;
|
||||
}
|
||||
|
||||
static uint32_t get_default_int(struct pw_properties *properties, const char *name, uint32_t def)
|
||||
{
|
||||
uint32_t val;
|
||||
const char *str;
|
||||
if ((str = pw_properties_get(properties, name)) != NULL)
|
||||
val = atoi(str);
|
||||
else {
|
||||
val = def;
|
||||
pw_properties_setf(properties, name, "%d", val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static bool get_default_bool(struct pw_properties *properties, const char *name, bool def)
|
||||
{
|
||||
bool val;
|
||||
const char *str;
|
||||
if ((str = pw_properties_get(properties, name)) != NULL)
|
||||
val = pw_properties_parse_bool(str);
|
||||
else {
|
||||
val = def;
|
||||
pw_properties_set(properties, name, val ? "true" : "false");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static bool uint32_array_contains(uint32_t *vals, uint32_t n_vals, uint32_t val)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < n_vals; i++)
|
||||
if (vals[i] == val)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t parse_uint32_array(const char *str, uint32_t *vals, uint32_t max, uint32_t def)
|
||||
{
|
||||
uint32_t count = 0, r;
|
||||
struct spa_json it[2];
|
||||
char v[256];
|
||||
|
||||
spa_json_init(&it[0], str, strlen(str));
|
||||
if (spa_json_enter_array(&it[0], &it[1]) <= 0)
|
||||
spa_json_init(&it[1], str, strlen(str));
|
||||
|
||||
while (spa_json_get_string(&it[1], v, sizeof(v)-1) > 0 &&
|
||||
count < max) {
|
||||
if (spa_atou32(v, &r, 0))
|
||||
vals[count++] = r;
|
||||
}
|
||||
if (!uint32_array_contains(vals, count, def))
|
||||
count = 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
static uint32_t parse_clock_rate(struct pw_properties *properties, const char *name,
|
||||
uint32_t *rates, uint32_t def)
|
||||
{
|
||||
const char *str;
|
||||
uint32_t count = 0;
|
||||
|
||||
if ((str = pw_properties_get(properties, name)) == NULL)
|
||||
return 0;
|
||||
|
||||
count = parse_uint32_array(str, rates, MAX_RATES, def);
|
||||
if (count == 0)
|
||||
goto fallback;
|
||||
|
||||
return count;
|
||||
fallback:
|
||||
rates[0] = def;
|
||||
pw_properties_setf(properties, name, "[ %u ]", def);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int metadata_property(void *data, uint32_t subject, const char *key,
|
||||
const char *type, const char *value)
|
||||
{
|
||||
|
@ -69,6 +158,22 @@ static int metadata_property(void *data, uint32_t subject, const char *key,
|
|||
if (spa_streq(key, "log.level")) {
|
||||
v = value ? atoi(value) : 3;
|
||||
pw_log_set_level(v);
|
||||
} else if (spa_streq(key, "clock.rate")) {
|
||||
v = value ? atoi(value) : 0;
|
||||
s->clock_rate = v == 0 ? d->clock_rate : v;
|
||||
recalc = true;
|
||||
} else if (spa_streq(key, "clock.allowed-rates")) {
|
||||
s->n_clock_rates = parse_uint32_array(value,
|
||||
s->clock_rates, MAX_RATES, s->clock_rate);
|
||||
if (s->n_clock_rates == 0) {
|
||||
s->n_clock_rates = d->n_clock_rates;
|
||||
memcpy(s->clock_rates, d->clock_rates, MAX_RATES * sizeof(uint32_t));
|
||||
}
|
||||
recalc = true;
|
||||
} else if (spa_streq(key, "clock.quantum")) {
|
||||
v = value ? atoi(value) : 0;
|
||||
s->clock_quantum = v == 0 ? d->clock_quantum : v;
|
||||
recalc = true;
|
||||
} else if (spa_streq(key, "clock.min-quantum")) {
|
||||
v = value ? atoi(value) : 0;
|
||||
s->clock_min_quantum = v == 0 ? d->clock_min_quantum : v;
|
||||
|
@ -98,23 +203,70 @@ static const struct pw_impl_metadata_events metadata_events = {
|
|||
.property = metadata_property,
|
||||
};
|
||||
|
||||
static void init_defaults(struct impl *impl)
|
||||
void pw_settings_init(struct pw_context *this)
|
||||
{
|
||||
struct settings *s = &impl->context->settings;
|
||||
struct pw_properties *p = this->properties;
|
||||
struct settings *d = &this->defaults;
|
||||
|
||||
pw_impl_metadata_set_propertyf(impl->metadata,
|
||||
d->clock_rate = get_default_int(p, "default.clock.rate", DEFAULT_CLOCK_RATE);
|
||||
d->n_clock_rates = parse_clock_rate(p, "default.clock.allowed-rates", d->clock_rates, d->clock_rate);
|
||||
d->clock_quantum = get_default_int(p, "default.clock.quantum", DEFAULT_CLOCK_QUANTUM);
|
||||
d->clock_min_quantum = get_default_int(p, "default.clock.min-quantum", DEFAULT_CLOCK_MIN_QUANTUM);
|
||||
d->clock_max_quantum = get_default_int(p, "default.clock.max-quantum", DEFAULT_CLOCK_MAX_QUANTUM);
|
||||
d->video_size.width = get_default_int(p, "default.video.width", DEFAULT_VIDEO_WIDTH);
|
||||
d->video_size.height = get_default_int(p, "default.video.height", DEFAULT_VIDEO_HEIGHT);
|
||||
d->video_rate.num = get_default_int(p, "default.video.rate.num", DEFAULT_VIDEO_RATE_NUM);
|
||||
d->video_rate.denom = get_default_int(p, "default.video.rate.denom", DEFAULT_VIDEO_RATE_DENOM);
|
||||
|
||||
d->log_level = get_default_int(p, "log.level", pw_log_level);
|
||||
d->clock_power_of_two_quantum = get_default_bool(p, "clock.power-of-two-quantum",
|
||||
DEFAULT_CLOCK_POWER_OF_TWO_QUANTUM);
|
||||
d->link_max_buffers = get_default_int(p, "link.max-buffers", DEFAULT_LINK_MAX_BUFFERS);
|
||||
d->mem_warn_mlock = get_default_bool(p, "mem.warn-mlock", DEFAULT_MEM_WARN_MLOCK);
|
||||
d->mem_allow_mlock = get_default_bool(p, "mem.allow-mlock", DEFAULT_MEM_ALLOW_MLOCK);
|
||||
|
||||
d->clock_max_quantum = SPA_CLAMP(d->clock_max_quantum,
|
||||
CLOCK_MIN_QUANTUM, CLOCK_MAX_QUANTUM);
|
||||
d->clock_min_quantum = SPA_CLAMP(d->clock_min_quantum,
|
||||
CLOCK_MIN_QUANTUM, d->clock_max_quantum);
|
||||
d->clock_quantum = SPA_CLAMP(d->clock_quantum,
|
||||
d->clock_min_quantum, d->clock_max_quantum);
|
||||
}
|
||||
|
||||
static void expose_settings(struct pw_context *context, struct pw_impl_metadata *metadata)
|
||||
{
|
||||
struct settings *s = &context->settings;
|
||||
uint32_t i, o;
|
||||
char rates[MAX_RATES*16] = "";
|
||||
|
||||
pw_impl_metadata_set_propertyf(metadata,
|
||||
PW_ID_CORE, "log.level", "", "%d", s->log_level);
|
||||
pw_impl_metadata_set_propertyf(impl->metadata,
|
||||
pw_impl_metadata_set_propertyf(metadata,
|
||||
PW_ID_CORE, "clock.rate", "", "%d", s->clock_rate);
|
||||
for (i = 0, o = 0; i < s->n_clock_rates; i++) {
|
||||
int r = snprintf(rates+o, sizeof(rates)-o, "%s%d", i == 0 ? "" : ", ",
|
||||
s->clock_rates[i]);
|
||||
if (r < 0 || o + r >= (int)sizeof(rates)) {
|
||||
snprintf(rates, sizeof(rates), "%d", s->clock_rate);
|
||||
break;
|
||||
}
|
||||
o += r;
|
||||
}
|
||||
pw_impl_metadata_set_propertyf(metadata,
|
||||
PW_ID_CORE, "clock.allowed-rates", "", "[ %s ]", rates);
|
||||
pw_impl_metadata_set_propertyf(metadata,
|
||||
PW_ID_CORE, "clock.quantum", "", "%d", s->clock_quantum);
|
||||
pw_impl_metadata_set_propertyf(metadata,
|
||||
PW_ID_CORE, "clock.min-quantum", "", "%d", s->clock_min_quantum);
|
||||
pw_impl_metadata_set_propertyf(impl->metadata,
|
||||
pw_impl_metadata_set_propertyf(metadata,
|
||||
PW_ID_CORE, "clock.max-quantum", "", "%d", s->clock_max_quantum);
|
||||
pw_impl_metadata_set_propertyf(impl->metadata,
|
||||
pw_impl_metadata_set_propertyf(metadata,
|
||||
PW_ID_CORE, "clock.force-quantum", "", "%d", s->clock_force_quantum);
|
||||
pw_impl_metadata_set_propertyf(impl->metadata,
|
||||
pw_impl_metadata_set_propertyf(metadata,
|
||||
PW_ID_CORE, "clock.force-rate", "", "%d", s->clock_force_rate);
|
||||
}
|
||||
|
||||
int pw_settings_init(struct pw_context *context)
|
||||
int pw_settings_expose(struct pw_context *context)
|
||||
{
|
||||
struct impl *impl;
|
||||
|
||||
|
@ -127,7 +279,7 @@ int pw_settings_init(struct pw_context *context)
|
|||
if (impl->metadata == NULL)
|
||||
goto error_free;
|
||||
|
||||
init_defaults(impl);
|
||||
expose_settings(context, impl->metadata);
|
||||
|
||||
pw_impl_metadata_add_listener(impl->metadata,
|
||||
&impl->metadata_listener,
|
||||
|
|
Loading…
Reference in a new issue