Update alsa interface and gain widget to support linear volume
# Conflicts: # src/alsa.c
This commit is contained in:
@@ -231,7 +231,7 @@ static void alsa_parse_comment_node(
|
|||||||
err = snd_config_get_integer(node, &dbmin);
|
err = snd_config_get_integer(node, &dbmin);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
fatal_alsa_error("snd_config_get_integer error", err);
|
fatal_alsa_error("snd_config_get_integer error", err);
|
||||||
elem->min_dB = dbmin / 100;
|
elem->min_cdB = dbmin;
|
||||||
} else if (strcmp(key, "dbmax") == 0) {
|
} else if (strcmp(key, "dbmax") == 0) {
|
||||||
if (type != SND_CONFIG_TYPE_INTEGER) {
|
if (type != SND_CONFIG_TYPE_INTEGER) {
|
||||||
printf("dbmax type not integer\n");
|
printf("dbmax type not integer\n");
|
||||||
@@ -241,7 +241,7 @@ static void alsa_parse_comment_node(
|
|||||||
err = snd_config_get_integer(node, &dbmax);
|
err = snd_config_get_integer(node, &dbmax);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
fatal_alsa_error("snd_config_get_integer error", err);
|
fatal_alsa_error("snd_config_get_integer error", err);
|
||||||
elem->max_dB = dbmax / 100;
|
elem->max_cdB = dbmax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/alsa.c
16
src/alsa.c
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
|
#include <alsa/sound/uapi/tlv.h>
|
||||||
|
|
||||||
#include "alsa.h"
|
#include "alsa.h"
|
||||||
#include "scarlett2-firmware.h"
|
#include "scarlett2-firmware.h"
|
||||||
@@ -361,7 +362,7 @@ static void alsa_get_elem_tlv(struct alsa_elem *elem) {
|
|||||||
unsigned int tlv[MAX_TLV_RANGE_SIZE];
|
unsigned int tlv[MAX_TLV_RANGE_SIZE];
|
||||||
unsigned int *dbrec;
|
unsigned int *dbrec;
|
||||||
int ret;
|
int ret;
|
||||||
long min_dB, max_dB;
|
long min_cdB, max_cdB;
|
||||||
|
|
||||||
snd_ctl_elem_id_alloca(&elem_id);
|
snd_ctl_elem_id_alloca(&elem_id);
|
||||||
snd_ctl_elem_id_set_numid(elem_id, elem->numid);
|
snd_ctl_elem_id_set_numid(elem_id, elem->numid);
|
||||||
@@ -370,29 +371,30 @@ static void alsa_get_elem_tlv(struct alsa_elem *elem) {
|
|||||||
elem->card->handle, elem_id, tlv, sizeof(tlv)
|
elem->card->handle, elem_id, tlv, sizeof(tlv)
|
||||||
);
|
);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "TLV read error %d\n", ret);
|
fprintf(stderr, "TLV read error: %s\n", snd_strerror(ret));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = snd_tlv_parse_dB_info(tlv, sizeof(tlv), &dbrec);
|
ret = snd_tlv_parse_dB_info(tlv, sizeof(tlv), &dbrec);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
fprintf(stderr, "TLV parse error %d\n", ret);
|
fprintf(stderr, "TLV parse error: %s\n", snd_strerror(ret));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int min_val = snd_ctl_elem_info_get_min(elem_info);
|
int min_val = snd_ctl_elem_info_get_min(elem_info);
|
||||||
int max_val = snd_ctl_elem_info_get_max(elem_info);
|
int max_val = snd_ctl_elem_info_get_max(elem_info);
|
||||||
|
|
||||||
ret = snd_tlv_get_dB_range(tlv, min_val, max_val, &min_dB, &max_dB);
|
ret = snd_tlv_get_dB_range(dbrec, min_val, max_val, &min_cdB, &max_cdB);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
fprintf(stderr, "TLV range error %d\n", ret);
|
fprintf(stderr, "TLV range error: %s\n", snd_strerror(ret));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
elem->min_val = min_val;
|
elem->min_val = min_val;
|
||||||
elem->max_val = max_val;
|
elem->max_val = max_val;
|
||||||
elem->min_dB = min_dB / 100;
|
elem->dB_type = dbrec[SNDRV_CTL_TLVO_TYPE];
|
||||||
elem->max_dB = max_dB / 100;
|
elem->min_cdB = min_cdB;
|
||||||
|
elem->max_cdB = max_cdB;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void alsa_get_elem(struct alsa_card *card, int numid) {
|
static void alsa_get_elem(struct alsa_card *card, int numid) {
|
||||||
|
|||||||
@@ -126,11 +126,12 @@ struct alsa_elem {
|
|||||||
int count;
|
int count;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
// for gain/volume elements, the dB range and step
|
// for gain/volume elements, the value range, dB type, and dB range
|
||||||
int min_val;
|
int min_val;
|
||||||
int max_val;
|
int max_val;
|
||||||
int min_dB;
|
int dB_type;
|
||||||
int max_dB;
|
int min_cdB;
|
||||||
|
int max_cdB;
|
||||||
|
|
||||||
// for routing sinks
|
// for routing sinks
|
||||||
int is_routing_snk;
|
int is_routing_snk;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "gtkdial.h"
|
#include "gtkdial.h"
|
||||||
#include "stringhelper.h"
|
#include "stringhelper.h"
|
||||||
#include "widget-gain.h"
|
#include "widget-gain.h"
|
||||||
|
#include "db.h"
|
||||||
|
|
||||||
struct gain {
|
struct gain {
|
||||||
struct alsa_elem *elem;
|
struct alsa_elem *elem;
|
||||||
@@ -56,16 +57,31 @@ static void gain_updated(
|
|||||||
|
|
||||||
char s[20];
|
char s[20];
|
||||||
char *p = s;
|
char *p = s;
|
||||||
float value = (float)alsa_value * data->scale + elem->min_dB;
|
float value;
|
||||||
|
int min_db = round(elem->min_cdB / 100.0);
|
||||||
|
int max_db = round(elem->max_cdB / 100.0);
|
||||||
|
|
||||||
if (value > elem->max_dB)
|
if (elem->dB_type == SND_CTL_TLVT_DB_LINEAR) {
|
||||||
value = elem->max_dB;
|
value = linear_value_to_db(
|
||||||
else if (value < elem->min_dB)
|
alsa_value,
|
||||||
value = elem->min_dB;
|
elem->min_val,
|
||||||
|
elem->max_val,
|
||||||
|
min_db,
|
||||||
|
max_db
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
value = ((float)(alsa_value - elem->min_val)) * data->scale + (elem->min_cdB / 100.0);
|
||||||
|
if (value > max_db)
|
||||||
|
value = max_db;
|
||||||
|
else if (value < min_db)
|
||||||
|
value = min_db;
|
||||||
|
}
|
||||||
|
|
||||||
if (data->zero_is_off && alsa_value == 0) {
|
if (data->zero_is_off && value == min_db) {
|
||||||
p += sprintf(p, "−∞");
|
p += sprintf(p, "−∞");
|
||||||
} else {
|
} else {
|
||||||
|
if (data->scale <= 0.5)
|
||||||
|
value = round(value * 10) / 10;
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
p += sprintf(p, "−");
|
p += sprintf(p, "−");
|
||||||
else if (value > 0)
|
else if (value > 0)
|
||||||
@@ -159,20 +175,42 @@ GtkWidget *make_gain_alsa_elem(
|
|||||||
gtk_widget_set_valign(data->vbox, GTK_ALIGN_START);
|
gtk_widget_set_valign(data->vbox, GTK_ALIGN_START);
|
||||||
gtk_widget_set_vexpand(data->vbox, TRUE);
|
gtk_widget_set_vexpand(data->vbox, TRUE);
|
||||||
|
|
||||||
data->scale = (float)(elem->max_dB - elem->min_dB) /
|
gboolean is_linear = elem->dB_type == SND_CTL_TLVT_DB_LINEAR;
|
||||||
(elem->max_val - elem->min_val);
|
double step;
|
||||||
|
|
||||||
|
if (is_linear) {
|
||||||
|
data->scale = 0.5;
|
||||||
|
step = 0.5;
|
||||||
|
} else {
|
||||||
|
data->scale = (float)(elem->max_cdB - elem->min_cdB) / 100.0 /
|
||||||
|
(elem->max_val - elem->min_val);
|
||||||
|
step = 1;
|
||||||
|
}
|
||||||
data->dial = gtk_dial_new_with_range(
|
data->dial = gtk_dial_new_with_range(
|
||||||
elem->min_val,
|
elem->min_val,
|
||||||
elem->max_val,
|
elem->max_val,
|
||||||
1,
|
step,
|
||||||
3 / data->scale
|
3 / data->scale
|
||||||
);
|
);
|
||||||
|
|
||||||
// calculate 0dB value
|
// calculate 0dB value
|
||||||
int zero_db_value = (int)((0 - elem->min_dB) / data->scale + elem->min_val);
|
int zero_db_value;
|
||||||
|
|
||||||
|
if (is_linear) {
|
||||||
|
zero_db_value = cdb_to_linear_value(
|
||||||
|
0,
|
||||||
|
elem->min_val,
|
||||||
|
elem->max_val,
|
||||||
|
elem->min_cdB,
|
||||||
|
elem->max_cdB
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
zero_db_value =
|
||||||
|
(int)((0 - elem->min_cdB) / 100.0 / data->scale + elem->min_val);
|
||||||
|
}
|
||||||
|
|
||||||
gtk_dial_set_zero_db(GTK_DIAL(data->dial), zero_db_value);
|
gtk_dial_set_zero_db(GTK_DIAL(data->dial), zero_db_value);
|
||||||
|
gtk_dial_set_is_linear(GTK_DIAL(data->dial), is_linear);
|
||||||
|
|
||||||
// convert from widget_taper to gtk_dial_taper
|
// convert from widget_taper to gtk_dial_taper
|
||||||
int gtk_dial_taper;
|
int gtk_dial_taper;
|
||||||
|
|||||||
Reference in New Issue
Block a user