mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-05 10:08:15 +02:00
m-mixer-api: add configurable support for the cubic volume scale
This is also what pulseaudio uses, so now the volumes in wpctl match what pulseaudio tools report and they make a lot more sense from the user's POV
This commit is contained in:
parent
1547bc9c5c
commit
c7e32a638a
4 changed files with 110 additions and 9 deletions
|
|
@ -37,12 +37,15 @@ else
|
|||
wireplumber_data_dir = join_paths(get_option('prefix'), get_option('datadir'), 'wireplumber')
|
||||
endif
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
glib_req_version = '>= 2.58'
|
||||
gobject_dep = dependency('gobject-2.0', version : glib_req_version)
|
||||
gmodule_dep = dependency('gmodule-2.0', version : glib_req_version)
|
||||
gio_dep = dependency('gio-2.0', version : glib_req_version)
|
||||
giounix_dep = dependency('gio-unix-2.0', version : glib_req_version)
|
||||
pipewire_dep = dependency('libpipewire-0.3', version: '>= 0.3.20')
|
||||
mathlib = cc.find_library('m')
|
||||
|
||||
if get_option('system-lua')
|
||||
lua_dep = dependency('lua', version: ['>=5.3.0', '<5.4.0'], required: false)
|
||||
|
|
@ -85,7 +88,6 @@ common_flags = [
|
|||
'-Wold-style-declaration',
|
||||
'-Wunused-result',
|
||||
]
|
||||
cc = meson.get_compiler('c')
|
||||
add_project_arguments(cc.get_supported_arguments(common_flags), language: 'c')
|
||||
|
||||
have_audiofade = cc.compiles('''
|
||||
|
|
|
|||
|
|
@ -174,5 +174,5 @@ shared_library(
|
|||
c_args : [common_c_args, '-DG_LOG_DOMAIN="m-mixer-api"'],
|
||||
install : true,
|
||||
install_dir : wireplumber_module_dir,
|
||||
dependencies : [wp_dep, pipewire_dep],
|
||||
dependencies : [wp_dep, pipewire_dep, mathlib],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
*/
|
||||
|
||||
#include <wp/wp.h>
|
||||
#include <math.h>
|
||||
#include <pipewire/pipewire.h>
|
||||
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/param/audio/raw.h>
|
||||
|
||||
|
|
@ -43,6 +43,9 @@ struct _WpMixerApi
|
|||
WpObjectManager *om;
|
||||
GHashTable *node_infos;
|
||||
guint32 seq;
|
||||
|
||||
/* properties */
|
||||
gint scale;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -52,16 +55,75 @@ enum {
|
|||
N_SIGNALS
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SCALE,
|
||||
};
|
||||
|
||||
static guint signals[N_SIGNALS] = {0};
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpMixerApi, wp_mixer_api, WP, MIXER_API, WpPlugin)
|
||||
G_DEFINE_TYPE (WpMixerApi, wp_mixer_api, WP_TYPE_PLUGIN)
|
||||
|
||||
enum {
|
||||
SCALE_LINEAR,
|
||||
SCALE_CUBIC,
|
||||
};
|
||||
|
||||
static GType
|
||||
wp_mixer_api_volume_scale_enum_get_type (void)
|
||||
{
|
||||
static volatile gsize gtype_id = 0;
|
||||
static const GEnumValue values[] = {
|
||||
{ (gint) SCALE_LINEAR, "SCALE_LINEAR", "linear" },
|
||||
{ (gint) SCALE_CUBIC, "SCALE_CUBIC", "cubic" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
if (g_once_init_enter (>ype_id)) {
|
||||
GType new_type = g_enum_register_static (
|
||||
g_intern_static_string ("WpMixerApiVolumeScale"), values);
|
||||
g_once_init_leave (>ype_id, new_type);
|
||||
}
|
||||
return (GType) gtype_id;
|
||||
}
|
||||
|
||||
static void
|
||||
wp_mixer_api_init (WpMixerApi * self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
wp_mixer_api_get_property (GObject * object, guint property_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpMixerApi *self = WP_MIXER_API (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SCALE:
|
||||
g_value_set_enum (value, self->scale);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_mixer_api_set_property (GObject * object, guint property_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpMixerApi *self = WP_MIXER_API (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SCALE:
|
||||
self->scale = g_value_get_enum (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
node_info_fill (struct node_info * info, WpSpaPod * props)
|
||||
{
|
||||
|
|
@ -293,6 +355,28 @@ wp_mixer_api_disable (WpPlugin * plugin)
|
|||
g_clear_pointer (&self->node_infos, g_hash_table_unref);
|
||||
}
|
||||
|
||||
static inline gdouble
|
||||
volume_from_linear (float vol, gint scale)
|
||||
{
|
||||
if (vol <= 0.0f)
|
||||
return 0.0;
|
||||
else if (scale == SCALE_CUBIC)
|
||||
return cbrt(vol);
|
||||
else
|
||||
return vol;
|
||||
}
|
||||
|
||||
static inline float
|
||||
volume_to_linear (gdouble vol, gint scale)
|
||||
{
|
||||
if (vol <= 0.0f)
|
||||
return 0.0;
|
||||
else if (scale == SCALE_CUBIC)
|
||||
return vol * vol * vol;
|
||||
else
|
||||
return vol;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wp_mixer_api_set_volume (WpMixerApi * self, guint32 id, GVariant * vvolume)
|
||||
{
|
||||
|
|
@ -310,7 +394,7 @@ wp_mixer_api_set_volume (WpMixerApi * self, guint32 id, GVariant * vvolume)
|
|||
gdouble val = g_variant_get_double (vvolume);
|
||||
new_volume = info->volume;
|
||||
for (uint i = 0; i < new_volume.channels; i++)
|
||||
new_volume.values[i] = val;
|
||||
new_volume.values[i] = volume_to_linear (val, self->scale);
|
||||
}
|
||||
else if (g_variant_is_of_type (vvolume, G_VARIANT_TYPE_VARDICT)) {
|
||||
GVariantIter iter;
|
||||
|
|
@ -323,7 +407,7 @@ wp_mixer_api_set_volume (WpMixerApi * self, guint32 id, GVariant * vvolume)
|
|||
if (g_variant_lookup (vvolume, "volume", "d", &val)) {
|
||||
new_volume = info->volume;
|
||||
for (uint i = 0; i < new_volume.channels; i++)
|
||||
new_volume.values[i] = val;
|
||||
new_volume.values[i] = volume_to_linear (val, self->scale);
|
||||
}
|
||||
|
||||
if (g_variant_lookup (vvolume, "channelVolumes", "a{sv}", &iter)) {
|
||||
|
|
@ -356,7 +440,7 @@ wp_mixer_api_set_volume (WpMixerApi * self, guint32 id, GVariant * vvolume)
|
|||
}
|
||||
|
||||
if (g_variant_lookup (v, "volume", "d", &val)) {
|
||||
new_volume.values[index] = val;
|
||||
new_volume.values[index] = volume_to_linear (val, self->scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -423,7 +507,8 @@ wp_mixer_api_get_volume (WpMixerApi * self, guint32 id)
|
|||
g_variant_builder_add (&b, "{sv}", "base", g_variant_new_double (info->base));
|
||||
g_variant_builder_add (&b, "{sv}", "step", g_variant_new_double (info->step));
|
||||
g_variant_builder_add (&b, "{sv}", "volume", g_variant_new_double (
|
||||
(info->volume.channels > 0) ? info->volume.values[0] : info->svolume));
|
||||
volume_from_linear ((info->volume.channels > 0) ?
|
||||
info->volume.values[0] : info->svolume, self->scale)));
|
||||
|
||||
for (guint i = 0; i < info->volume.channels; i++) {
|
||||
gchar index_str[10];
|
||||
|
|
@ -431,7 +516,8 @@ wp_mixer_api_get_volume (WpMixerApi * self, guint32 id)
|
|||
G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
|
||||
|
||||
g_variant_builder_add (&b_vol_nested, "{sv}",
|
||||
"volume", g_variant_new_double (info->volume.values[i]));
|
||||
"volume", g_variant_new_double (
|
||||
volume_from_linear (info->volume.values[i], self->scale)));
|
||||
|
||||
if (i < info->map.channels) {
|
||||
WpSpaIdValue v =
|
||||
|
|
@ -456,11 +542,20 @@ wp_mixer_api_get_volume (WpMixerApi * self, guint32 id)
|
|||
static void
|
||||
wp_mixer_api_class_init (WpMixerApiClass * klass)
|
||||
{
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
WpPluginClass *plugin_class = (WpPluginClass *) klass;
|
||||
|
||||
object_class->set_property = wp_mixer_api_set_property;
|
||||
object_class->get_property = wp_mixer_api_get_property;
|
||||
|
||||
plugin_class->enable = wp_mixer_api_enable;
|
||||
plugin_class->disable = wp_mixer_api_disable;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SCALE,
|
||||
g_param_spec_enum ("scale", "scale", "scale",
|
||||
wp_mixer_api_volume_scale_enum_get_type (),
|
||||
SCALE_LINEAR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
signals[ACTION_SET_VOLUME] = g_signal_new_class_handler (
|
||||
"set-volume", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
|
|
|
|||
|
|
@ -1101,7 +1101,11 @@ main (gint argc, gchar **argv)
|
|||
return 1;
|
||||
}
|
||||
g_ptr_array_add (ctl.apis, wp_plugin_find (ctl.core, "default-nodes-api"));
|
||||
g_ptr_array_add (ctl.apis, wp_plugin_find (ctl.core, "mixer-api"));
|
||||
g_ptr_array_add (ctl.apis, ({
|
||||
WpPlugin *p = wp_plugin_find (ctl.core, "mixer-api");
|
||||
g_object_set (G_OBJECT (p), "scale", 1 /* cubic */, NULL);
|
||||
p;
|
||||
}));
|
||||
|
||||
/* connect */
|
||||
if (!wp_core_connect (ctl.core)) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue