Remove hard-coded values from widget-gain.c and widget-volume.c
Update alsa-sim.c and alsa.c to read the TLV info, and update the gain and volume widgets to use that info rather than hard-coding the min/max values.
This commit is contained in:
@@ -151,6 +151,42 @@ static void alsa_parse_comment_node(
|
|||||||
elem->type = SND_CTL_ELEM_TYPE_INTEGER;
|
elem->type = SND_CTL_ELEM_TYPE_INTEGER;
|
||||||
} else if (strcmp(key, "item") == 0) {
|
} else if (strcmp(key, "item") == 0) {
|
||||||
alsa_parse_enum_items(node, elem);
|
alsa_parse_enum_items(node, elem);
|
||||||
|
} else if (strcmp(key, "range") == 0) {
|
||||||
|
if (type != SND_CONFIG_TYPE_STRING) {
|
||||||
|
printf("range type not string\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *range;
|
||||||
|
err = snd_config_get_string(node, &range);
|
||||||
|
if (err < 0)
|
||||||
|
fatal_alsa_error("snd_config_get_string error", err);
|
||||||
|
|
||||||
|
// Parse the range string and update elem->min_val and elem->max_val
|
||||||
|
int min_val, max_val;
|
||||||
|
if (sscanf(range, "%d - %d", &min_val, &max_val) == 2) {
|
||||||
|
elem->min_val = min_val;
|
||||||
|
elem->max_val = max_val;
|
||||||
|
}
|
||||||
|
} else if (strcmp(key, "dbmin") == 0) {
|
||||||
|
if (type != SND_CONFIG_TYPE_INTEGER) {
|
||||||
|
printf("dbmin type not integer\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long dbmin;
|
||||||
|
err = snd_config_get_integer(node, &dbmin);
|
||||||
|
if (err < 0)
|
||||||
|
fatal_alsa_error("snd_config_get_integer error", err);
|
||||||
|
elem->min_dB = dbmin / 100;
|
||||||
|
} else if (strcmp(key, "dbmax") == 0) {
|
||||||
|
if (type != SND_CONFIG_TYPE_INTEGER) {
|
||||||
|
printf("dbmax type not integer\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long dbmax;
|
||||||
|
err = snd_config_get_integer(node, &dbmax);
|
||||||
|
if (err < 0)
|
||||||
|
fatal_alsa_error("snd_config_get_integer error", err);
|
||||||
|
elem->max_dB = dbmax / 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
50
src/alsa.c
50
src/alsa.c
@@ -7,6 +7,8 @@
|
|||||||
#include "stringhelper.h"
|
#include "stringhelper.h"
|
||||||
#include "window-iface.h"
|
#include "window-iface.h"
|
||||||
|
|
||||||
|
#define MAX_TLV_RANGE_SIZE 256
|
||||||
|
|
||||||
// names for the port categories
|
// names for the port categories
|
||||||
const char *port_category_names[PC_COUNT] = {
|
const char *port_category_names[PC_COUNT] = {
|
||||||
"Hardware Outputs",
|
"Hardware Outputs",
|
||||||
@@ -340,6 +342,54 @@ static void alsa_get_elem_list(struct alsa_card *card) {
|
|||||||
if (strstr(alsa_elem.name, "Channel Map"))
|
if (strstr(alsa_elem.name, "Channel Map"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// get TLV info if it's a volume control
|
||||||
|
if (alsa_elem.type == SND_CTL_ELEM_TYPE_INTEGER) {
|
||||||
|
snd_ctl_elem_info_t *elem_info;
|
||||||
|
|
||||||
|
snd_ctl_elem_info_alloca(&elem_info);
|
||||||
|
snd_ctl_elem_info_set_numid(elem_info, alsa_elem.numid);
|
||||||
|
snd_ctl_elem_info(card->handle, elem_info);
|
||||||
|
|
||||||
|
if (snd_ctl_elem_info_is_tlv_readable(elem_info)) {
|
||||||
|
snd_ctl_elem_id_t *elem_id;
|
||||||
|
unsigned int tlv[MAX_TLV_RANGE_SIZE];
|
||||||
|
unsigned int *dbrec;
|
||||||
|
int ret;
|
||||||
|
long min_dB, max_dB;
|
||||||
|
|
||||||
|
snd_ctl_elem_id_alloca(&elem_id);
|
||||||
|
snd_ctl_elem_id_set_numid(elem_id, alsa_elem.numid);
|
||||||
|
|
||||||
|
ret = snd_ctl_elem_tlv_read(
|
||||||
|
card->handle, elem_id, tlv, sizeof(tlv)
|
||||||
|
);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "TLV read error %d\n", ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snd_tlv_parse_dB_info(tlv, sizeof(tlv), &dbrec);
|
||||||
|
if (ret <= 0) {
|
||||||
|
fprintf(stderr, "TLV parse error %d\n", ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int min_val = snd_ctl_elem_info_get_min(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);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "TLV range error %d\n", ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
alsa_elem.min_val = min_val;
|
||||||
|
alsa_elem.max_val = max_val;
|
||||||
|
alsa_elem.min_dB = min_dB / 100;
|
||||||
|
alsa_elem.max_dB = max_dB / 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (card->elems->len <= alsa_elem.numid)
|
if (card->elems->len <= alsa_elem.numid)
|
||||||
g_array_set_size(card->elems, alsa_elem.numid + 1);
|
g_array_set_size(card->elems, alsa_elem.numid + 1);
|
||||||
g_array_index(card->elems, struct alsa_elem, alsa_elem.numid) = alsa_elem;
|
g_array_index(card->elems, struct alsa_elem, alsa_elem.numid) = alsa_elem;
|
||||||
|
|||||||
@@ -115,6 +115,12 @@ struct alsa_elem {
|
|||||||
int type;
|
int type;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
|
// for gain/volume elements, the dB range and step
|
||||||
|
int min_val;
|
||||||
|
int max_val;
|
||||||
|
int min_dB;
|
||||||
|
int max_dB;
|
||||||
|
|
||||||
// for the number (or translated letter; A = 1) in the item name
|
// for the number (or translated letter; A = 1) in the item name
|
||||||
// TODO: move this to struct routing_snk?
|
// TODO: move this to struct routing_snk?
|
||||||
int lr_num;
|
int lr_num;
|
||||||
|
|||||||
@@ -4,11 +4,6 @@
|
|||||||
#include "gtkdial.h"
|
#include "gtkdial.h"
|
||||||
#include "widget-gain.h"
|
#include "widget-gain.h"
|
||||||
|
|
||||||
// gain controls -80dB - +6dB, 0.5dB steps
|
|
||||||
#define DIAL_MIN_VALUE 0
|
|
||||||
#define DIAL_MAX_VALUE 172
|
|
||||||
#define DIAL_ZERO_DB_VALUE 160
|
|
||||||
|
|
||||||
static void gain_changed(GtkWidget *widget, struct alsa_elem *elem) {
|
static void gain_changed(GtkWidget *widget, struct alsa_elem *elem) {
|
||||||
int value = gtk_dial_get_value(GTK_DIAL(widget));
|
int value = gtk_dial_get_value(GTK_DIAL(widget));
|
||||||
|
|
||||||
@@ -23,7 +18,10 @@ static void gain_updated(struct alsa_elem *elem) {
|
|||||||
gtk_dial_set_value(GTK_DIAL(elem->widget), value);
|
gtk_dial_set_value(GTK_DIAL(elem->widget), value);
|
||||||
|
|
||||||
char s[20];
|
char s[20];
|
||||||
snprintf(s, 20, "%.1f", (value / 2.0) - 80);
|
float scale = (float)(elem->max_dB - elem->min_dB) /
|
||||||
|
(elem->max_val - elem->min_val);
|
||||||
|
|
||||||
|
snprintf(s, 20, "%.1f", value * scale + elem->min_dB);
|
||||||
gtk_label_set_text(GTK_LABEL(elem->widget2), s);
|
gtk_label_set_text(GTK_LABEL(elem->widget2), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,9 +30,15 @@ GtkWidget *make_gain_alsa_elem(struct alsa_elem *elem) {
|
|||||||
gtk_widget_set_hexpand(vbox, TRUE);
|
gtk_widget_set_hexpand(vbox, TRUE);
|
||||||
|
|
||||||
GtkWidget *dial = gtk_dial_new_with_range(
|
GtkWidget *dial = gtk_dial_new_with_range(
|
||||||
DIAL_MIN_VALUE, DIAL_MAX_VALUE, 1
|
elem->min_val, elem->max_val, 1
|
||||||
);
|
);
|
||||||
gtk_dial_set_zero_db(GTK_DIAL(dial), DIAL_ZERO_DB_VALUE);
|
|
||||||
|
// calculate 0dB value from min/max dB and min/max value
|
||||||
|
float scale = (float)(elem->max_dB - elem->min_dB) /
|
||||||
|
(elem->max_val - elem->min_val);
|
||||||
|
int zero_db_value = (int)((0 - elem->min_dB) / scale + elem->min_val);
|
||||||
|
|
||||||
|
gtk_dial_set_zero_db(GTK_DIAL(dial), zero_db_value);
|
||||||
|
|
||||||
gtk_widget_set_vexpand(dial, TRUE);
|
gtk_widget_set_vexpand(dial, TRUE);
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,6 @@
|
|||||||
#include "gtkdial.h"
|
#include "gtkdial.h"
|
||||||
#include "widget-volume.h"
|
#include "widget-volume.h"
|
||||||
|
|
||||||
// volume controls -127dB - 0dB
|
|
||||||
#define DIAL_MIN_VALUE 0
|
|
||||||
#define DIAL_MAX_VALUE 127
|
|
||||||
#define DIAL_ZERO_DB_VALUE 127
|
|
||||||
|
|
||||||
static void volume_changed(GtkWidget *widget, struct alsa_elem *elem) {
|
static void volume_changed(GtkWidget *widget, struct alsa_elem *elem) {
|
||||||
int value = gtk_dial_get_value(GTK_DIAL(widget));
|
int value = gtk_dial_get_value(GTK_DIAL(widget));
|
||||||
|
|
||||||
@@ -23,7 +18,10 @@ static void volume_updated(struct alsa_elem *elem) {
|
|||||||
gtk_dial_set_value(GTK_DIAL(elem->widget), value);
|
gtk_dial_set_value(GTK_DIAL(elem->widget), value);
|
||||||
|
|
||||||
char s[20];
|
char s[20];
|
||||||
snprintf(s, 20, "%ddB", value - 127);
|
float scale = (float)(elem->max_dB - elem->min_dB) /
|
||||||
|
(elem->max_val - elem->min_val);
|
||||||
|
|
||||||
|
snprintf(s, 20, "%ddB", (int)(value * scale + elem->min_dB));
|
||||||
gtk_label_set_text(GTK_LABEL(elem->widget2), s);
|
gtk_label_set_text(GTK_LABEL(elem->widget2), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,9 +30,15 @@ GtkWidget *make_volume_alsa_elem(struct alsa_elem *elem) {
|
|||||||
gtk_widget_set_hexpand(vbox, TRUE);
|
gtk_widget_set_hexpand(vbox, TRUE);
|
||||||
|
|
||||||
GtkWidget *dial = gtk_dial_new_with_range(
|
GtkWidget *dial = gtk_dial_new_with_range(
|
||||||
DIAL_MIN_VALUE, DIAL_MAX_VALUE, 1
|
elem->min_val, elem->max_val, 1
|
||||||
);
|
);
|
||||||
gtk_dial_set_zero_db(GTK_DIAL(dial), DIAL_ZERO_DB_VALUE);
|
|
||||||
|
// calculate 0dB value from min/max dB and min/max value
|
||||||
|
float scale = (float)(elem->max_dB - elem->min_dB) /
|
||||||
|
(elem->max_val - elem->min_val);
|
||||||
|
int zero_db_value = (int)((0 - elem->min_dB) / scale + elem->min_val);
|
||||||
|
|
||||||
|
gtk_dial_set_zero_db(GTK_DIAL(dial), zero_db_value);
|
||||||
|
|
||||||
gtk_widget_set_vexpand(dial, TRUE);
|
gtk_widget_set_vexpand(dial, TRUE);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user