Update the gain widget to support updating direct monitor mix controls

The 4th Gen Solo and 2i2 have controls to set custom Mix A/B gains
when Direct Monitor is enabled. Update those controls when the Mix A/B
gains are updated so that they are remembered.
This commit is contained in:
Geoffrey D. Bennett
2024-02-09 09:30:14 +10:30
parent b9af5dfaf3
commit 8c06e7aff7

View File

@@ -2,10 +2,13 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include "gtkdial.h"
#include "stringhelper.h"
#include "widget-gain.h"
struct gain {
struct alsa_elem *elem;
struct alsa_elem *direct_monitor_elem;
struct alsa_elem *monitor_mix_elem[2];
GtkWidget *vbox;
GtkWidget *dial;
GtkWidget *label;
@@ -15,8 +18,28 @@ struct gain {
static void gain_changed(GtkWidget *widget, struct gain *data) {
int value = gtk_dial_get_value(GTK_DIAL(data->dial));
alsa_set_elem_value(data->elem, value);
// check if there is a corresponding Direct Monitor Mix control to
// update as well
// Direct Monitor control?
if (!data->direct_monitor_elem)
return;
// Direct Monitor enabled?
int direct_monitor = alsa_get_elem_value(data->direct_monitor_elem);
if (!direct_monitor)
return;
// Get the corresponding Mix control
struct alsa_elem *monitor_mix = data->monitor_mix_elem[direct_monitor - 1];
if (!monitor_mix)
return;
// Update it
alsa_set_elem_value(monitor_mix, value);
}
static void gain_updated(
@@ -56,6 +79,70 @@ static void gain_updated(
gtk_label_set_text(GTK_LABEL(data->label), s);
}
// 4th Gen Solo and 2i2 have Mix & Direct Monitor controls which
// interact. If direct monitor is enabled and the Mix A/B controls are
// changed, then the Monitor Mix Playback Volume controls are changed
// too so that the mix settings are restored when direct monitor is
// later enabled again.
static void find_direct_monitor_controls(struct gain *data) {
struct alsa_elem *elem = data->elem;
GArray *elems = elem->card->elems;
// Card has no direct monitor control?
struct alsa_elem *direct_monitor_elem = get_elem_by_prefix(
elems,
"Direct Monitor Playback"
);
if (!direct_monitor_elem)
return;
// Card has no mixer?
if (strncmp(elem->name, "Mix ", 4) != 0 ||
!strstr(elem->name, "Playback Volume"))
return;
char mix_letter = elem->name[4];
int input_num = get_num_from_string(elem->name);
// Find the Monitor Mix control for the 4th Gen Solo
if (strstr(direct_monitor_elem->name, "Switch")) {
char s[80];
sprintf(
s,
"Monitor Mix %c Input %02d Playback Volume",
mix_letter, input_num
);
struct alsa_elem *monitor_mix_elem = get_elem_by_name(elems, s);
if (!monitor_mix_elem)
return;
data->direct_monitor_elem = direct_monitor_elem;
data->monitor_mix_elem[0] = monitor_mix_elem;
// Find the Monitor Mix controls for the 4th Gen 2i2
} else if (strstr(direct_monitor_elem->name, "Enum")) {
for (int i = 0; i <= 1; i++) {
char s[80];
sprintf(
s,
"Monitor %d Mix %c Input %02d Playback Volume",
i + 1, mix_letter, input_num
);
struct alsa_elem *monitor_mix_elem = get_elem_by_name(elems, s);
if (!monitor_mix_elem)
return;
data->direct_monitor_elem = direct_monitor_elem;
data->monitor_mix_elem[i] = monitor_mix_elem;
}
} else {
fprintf(stderr, "Couldn't find direct monitor mix control\n");
}
}
//GList *make_gain_alsa_elem(struct alsa_elem *elem) {
GtkWidget *make_gain_alsa_elem(
struct alsa_elem *elem,
@@ -63,7 +150,7 @@ GtkWidget *make_gain_alsa_elem(
int widget_taper,
int can_control
) {
struct gain *data = g_malloc(sizeof(struct gain));
struct gain *data = calloc(1, sizeof(struct gain));
data->elem = elem;
data->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_hexpand(data->vbox, TRUE);
@@ -110,6 +197,8 @@ GtkWidget *make_gain_alsa_elem(
data->zero_is_off = zero_is_off;
find_direct_monitor_controls(data);
g_signal_connect(
data->dial, "value-changed", G_CALLBACK(gain_changed), data
);