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:
@@ -2,10 +2,13 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include "gtkdial.h"
|
#include "gtkdial.h"
|
||||||
|
#include "stringhelper.h"
|
||||||
#include "widget-gain.h"
|
#include "widget-gain.h"
|
||||||
|
|
||||||
struct gain {
|
struct gain {
|
||||||
struct alsa_elem *elem;
|
struct alsa_elem *elem;
|
||||||
|
struct alsa_elem *direct_monitor_elem;
|
||||||
|
struct alsa_elem *monitor_mix_elem[2];
|
||||||
GtkWidget *vbox;
|
GtkWidget *vbox;
|
||||||
GtkWidget *dial;
|
GtkWidget *dial;
|
||||||
GtkWidget *label;
|
GtkWidget *label;
|
||||||
@@ -15,8 +18,28 @@ struct gain {
|
|||||||
|
|
||||||
static void gain_changed(GtkWidget *widget, struct gain *data) {
|
static void gain_changed(GtkWidget *widget, struct gain *data) {
|
||||||
int value = gtk_dial_get_value(GTK_DIAL(data->dial));
|
int value = gtk_dial_get_value(GTK_DIAL(data->dial));
|
||||||
|
|
||||||
alsa_set_elem_value(data->elem, value);
|
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(
|
static void gain_updated(
|
||||||
@@ -56,6 +79,70 @@ static void gain_updated(
|
|||||||
gtk_label_set_text(GTK_LABEL(data->label), s);
|
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) {
|
//GList *make_gain_alsa_elem(struct alsa_elem *elem) {
|
||||||
GtkWidget *make_gain_alsa_elem(
|
GtkWidget *make_gain_alsa_elem(
|
||||||
struct alsa_elem *elem,
|
struct alsa_elem *elem,
|
||||||
@@ -63,7 +150,7 @@ GtkWidget *make_gain_alsa_elem(
|
|||||||
int widget_taper,
|
int widget_taper,
|
||||||
int can_control
|
int can_control
|
||||||
) {
|
) {
|
||||||
struct gain *data = g_malloc(sizeof(struct gain));
|
struct gain *data = calloc(1, sizeof(struct gain));
|
||||||
data->elem = elem;
|
data->elem = elem;
|
||||||
data->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
data->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
gtk_widget_set_hexpand(data->vbox, TRUE);
|
gtk_widget_set_hexpand(data->vbox, TRUE);
|
||||||
@@ -110,6 +197,8 @@ GtkWidget *make_gain_alsa_elem(
|
|||||||
|
|
||||||
data->zero_is_off = zero_is_off;
|
data->zero_is_off = zero_is_off;
|
||||||
|
|
||||||
|
find_direct_monitor_controls(data);
|
||||||
|
|
||||||
g_signal_connect(
|
g_signal_connect(
|
||||||
data->dial, "value-changed", G_CALLBACK(gain_changed), data
|
data->dial, "value-changed", G_CALLBACK(gain_changed), data
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user