Remove widgets from struct alsa_elem and add data to callbacks

Rather than having widget/widget2/widget_callback fields in the struct
alsa_elem, have a list of callbacks and allow private data to be
passed to callbacks.
This commit is contained in:
Geoffrey D. Bennett
2023-12-03 04:53:34 +10:30
parent d56a1d34ff
commit 47034d7901
11 changed files with 222 additions and 126 deletions

View File

@@ -116,6 +116,20 @@ int is_elem_routing_snk(struct alsa_elem *elem) {
return 0; return 0;
} }
// add a callback to the list of callbacks for this element
void alsa_elem_add_callback(
struct alsa_elem *elem,
AlsaElemCallback *callback,
void *data
) {
struct alsa_elem_callback *cb = calloc(1, sizeof(struct alsa_elem_callback));
cb->callback = callback;
cb->data = data;
elem->callbacks = g_list_append(elem->callbacks, cb);
}
// //
// alsa snd_ctl_elem_*() mediation functions // alsa snd_ctl_elem_*() mediation functions
// for simulated elements, fake the ALSA element // for simulated elements, fake the ALSA element
@@ -401,11 +415,17 @@ static void alsa_get_elem_list(struct alsa_card *card) {
} }
static void alsa_elem_change(struct alsa_elem *elem) { static void alsa_elem_change(struct alsa_elem *elem) {
if (!elem->widget) if (!elem || !elem->callbacks)
return; return;
if (!elem->widget_callback)
return; for (GList *l = elem->callbacks; l; l = l->next) {
elem->widget_callback(elem); struct alsa_elem_callback *cb = (struct alsa_elem_callback *)l->data;
if (!cb || !cb->callback)
continue;
cb->callback(elem, cb->data);
}
} }
static gboolean alsa_card_callback( static gboolean alsa_card_callback(

View File

@@ -17,7 +17,7 @@ struct alsa_card;
// typedef for callbacks to update widgets when the alsa element // typedef for callbacks to update widgets when the alsa element
// notifies of a change // notifies of a change
typedef void (AlsaElemCallback)(struct alsa_elem *); typedef void (AlsaElemCallback)(struct alsa_elem *, void *);
// port categories for routing_src and routing_snk entries // port categories for routing_src and routing_snk entries
// must match the level meter ordering from the driver // must match the level meter ordering from the driver
@@ -92,6 +92,12 @@ struct routing_snk {
// pointer back to the element this entry is associated with // pointer back to the element this entry is associated with
struct alsa_elem *elem; struct alsa_elem *elem;
// box widget on the routing page
GtkWidget *box_widget;
// socket widget on the routing page
GtkWidget *socket_widget;
// PC_DSP, PC_MIX, PC_PCM, or PC_HW // PC_DSP, PC_MIX, PC_PCM, or PC_HW
int port_category; int port_category;
@@ -103,6 +109,12 @@ struct routing_snk {
GtkWidget *mixer_label_bottom; GtkWidget *mixer_label_bottom;
}; };
// hold one callback & its data
struct alsa_elem_callback {
AlsaElemCallback *callback;
void *data;
};
// entry in alsa_card elems (ALSA control elements) array // entry in alsa_card elems (ALSA control elements) array
struct alsa_elem { struct alsa_elem {
@@ -125,15 +137,8 @@ struct alsa_elem {
// TODO: move this to struct routing_snk? // TODO: move this to struct routing_snk?
int lr_num; int lr_num;
// the primary GTK widget and callback function for this ALSA // the callback functions for this ALSA control element
// control element GList *callbacks;
GtkWidget *widget;
AlsaElemCallback *widget_callback;
// text label for volume controls
// handle for routing controls
// second button for dual controls
GtkWidget *widget2;
// for boolean buttons, the two possible texts // for boolean buttons, the two possible texts
// for dual buttons, the four possible texts // for dual buttons, the four possible texts
@@ -203,6 +208,13 @@ struct alsa_elem *get_elem_by_prefix(GArray *elems, char *prefix);
int get_max_elem_by_name(GArray *elems, char *prefix, char *needle); int get_max_elem_by_name(GArray *elems, char *prefix, char *needle);
int is_elem_routing_snk(struct alsa_elem *elem); int is_elem_routing_snk(struct alsa_elem *elem);
// add callback to alsa_elem callback list
void alsa_elem_add_callback(
struct alsa_elem *elem,
AlsaElemCallback *callback,
void *data
);
// alsa snd_ctl_elem_*() functions // alsa snd_ctl_elem_*() functions
int alsa_get_elem_type(struct alsa_elem *elem); int alsa_get_elem_type(struct alsa_elem *elem);
char *alsa_get_elem_name(struct alsa_elem *elem); char *alsa_get_elem_name(struct alsa_elem *elem);

View File

@@ -92,18 +92,19 @@ static void add_speaker_switching_controls(
if (!speaker_switching) if (!speaker_switching)
return; return;
make_dual_boolean_alsa_elems(speaker_switching, "Off", "On", "Main", "Alt"); GtkWidget *w = make_dual_boolean_alsa_elems(
GtkWidget *b = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); speaker_switching,
"Speaker Switching",
"Off", "On", "Main", "Alt"
);
gtk_widget_set_tooltip_text( gtk_widget_set_tooltip_text(
b, w,
"Speaker Switching lets you swap between two pairs of " "Speaker Switching lets you swap between two pairs of "
"monitoring speakers very easily." "monitoring speakers very easily."
); );
GtkWidget *l = gtk_label_new("Speaker Switching");
gtk_box_append(GTK_BOX(global_controls), b); gtk_box_append(GTK_BOX(global_controls), w);
gtk_box_append(GTK_BOX(b), l);
gtk_box_append(GTK_BOX(b), speaker_switching->widget);
gtk_box_append(GTK_BOX(b), speaker_switching->widget2);
} }
static void add_talkback_controls( static void add_talkback_controls(
@@ -119,19 +120,20 @@ static void add_talkback_controls(
if (!talkback) if (!talkback)
return; return;
make_dual_boolean_alsa_elems(talkback, "Disabled", "Enabled", "Off", "On"); GtkWidget *w = make_dual_boolean_alsa_elems(
GtkWidget *b = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); talkback,
"Talkback",
"Disabled", "Enabled", "Off", "On"
);
gtk_widget_set_tooltip_text( gtk_widget_set_tooltip_text(
b, w,
"Talkback lets you add another channel (usually the talkback " "Talkback lets you add another channel (usually the talkback "
"mic) to a mix with a button push, usually to talk to " "mic) to a mix with a button push, usually to talk to "
"musicians, and without using an additional mic channel." "musicians, and without using an additional mic channel."
); );
GtkWidget *l = gtk_label_new("Talkback");
gtk_box_append(GTK_BOX(global_controls), b); gtk_box_append(GTK_BOX(global_controls), w);
gtk_box_append(GTK_BOX(b), l);
gtk_box_append(GTK_BOX(b), talkback->widget);
gtk_box_append(GTK_BOX(b), talkback->widget2);
} }
static GtkWidget *create_global_box(GtkWidget *grid, int *x, int orient) { static GtkWidget *create_global_box(GtkWidget *grid, int *x, int orient) {
@@ -502,7 +504,7 @@ static void create_output_controls(
elem, "*audio-volume-high", "*audio-volume-muted" elem, "*audio-volume-high", "*audio-volume-muted"
); );
gtk_widget_set_tooltip_text(w, "Mute HW controlled outputs"); gtk_widget_set_tooltip_text(w, "Mute HW controlled outputs");
gtk_grid_attach(GTK_GRID(output_grid), elem->widget, 0, 2, 1, 1); gtk_grid_attach(GTK_GRID(output_grid), w, 0, 2, 1, 1);
} else if (strcmp(elem->name, "Dim Playback Switch") == 0) { } else if (strcmp(elem->name, "Dim Playback Switch") == 0) {
w = make_boolean_alsa_elem( w = make_boolean_alsa_elem(
elem, "*audio-volume-medium", "*audio-volume-low" elem, "*audio-volume-medium", "*audio-volume-low"

View File

@@ -258,7 +258,7 @@ static void get_snk_center(
double *x, double *x,
double *y double *y
) { ) {
get_widget_center(r_snk->elem->widget2, parent, x, y); get_widget_center(r_snk->socket_widget, parent, x, y);
if (IS_MIXER(r_snk->port_category)) if (IS_MIXER(r_snk->port_category))
(*y)++; (*y)++;
} }

View File

@@ -3,32 +3,42 @@
#include "widget-boolean.h" #include "widget-boolean.h"
struct boolean {
struct alsa_elem *elem;
GtkWidget *button;
};
static void button_clicked(GtkWidget *widget, struct alsa_elem *elem) { static void button_clicked(GtkWidget *widget, struct alsa_elem *elem) {
int value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); int value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
alsa_set_elem_value(elem, value); alsa_set_elem_value(elem, value);
} }
static void toggle_button_set_text(struct alsa_elem *elem, const char *text) { static void toggle_button_set_text(GtkWidget *button, const char *text) {
if (!text) if (!text)
return; return;
if (*text == '*') { if (*text == '*') {
GtkWidget *icon = gtk_image_new_from_icon_name(text + 1); GtkWidget *icon = gtk_image_new_from_icon_name(text + 1);
gtk_button_set_child(GTK_BUTTON(elem->widget), icon); gtk_button_set_child(GTK_BUTTON(button), icon);
} else { } else {
gtk_button_set_label(GTK_BUTTON(elem->widget), text); gtk_button_set_label(GTK_BUTTON(button), text);
} }
} }
static void toggle_button_updated(struct alsa_elem *elem) { static void toggle_button_updated(
struct alsa_elem *elem,
void *private
) {
struct boolean *data = private;
int is_writable = alsa_get_elem_writable(elem); int is_writable = alsa_get_elem_writable(elem);
gtk_widget_set_sensitive(elem->widget, is_writable); gtk_widget_set_sensitive(data->button, is_writable);
int value = !!alsa_get_elem_value(elem); int value = !!alsa_get_elem_value(elem);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elem->widget), value); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->button), value);
toggle_button_set_text(elem, elem->bool_text[value]); toggle_button_set_text(data->button, elem->bool_text[value]);
} }
GtkWidget *make_boolean_alsa_elem( GtkWidget *make_boolean_alsa_elem(
@@ -36,23 +46,24 @@ GtkWidget *make_boolean_alsa_elem(
const char *disabled_text, const char *disabled_text,
const char *enabled_text const char *enabled_text
) { ) {
GtkWidget *button = gtk_toggle_button_new(); struct boolean *data = g_malloc(sizeof(struct boolean));
data->elem = elem;
data->button = gtk_toggle_button_new();
g_signal_connect( g_signal_connect(
button, "clicked", G_CALLBACK(button_clicked), elem data->button, "clicked", G_CALLBACK(button_clicked), elem
); );
elem->widget = button; alsa_elem_add_callback(elem, toggle_button_updated, data);
elem->widget_callback = toggle_button_updated;
elem->bool_text[0] = disabled_text; elem->bool_text[0] = disabled_text;
elem->bool_text[1] = enabled_text; elem->bool_text[1] = enabled_text;
// find the maximum width and height of both possible labels // find the maximum width and height of both possible labels
int max_width = 0, max_height = 0; int max_width = 0, max_height = 0;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
toggle_button_set_text(elem, elem->bool_text[i]); toggle_button_set_text(data->button, elem->bool_text[i]);
GtkRequisition *size = gtk_requisition_new(); GtkRequisition *size = gtk_requisition_new();
gtk_widget_get_preferred_size(button, size, NULL); gtk_widget_get_preferred_size(data->button, size, NULL);
if (size->width > max_width) if (size->width > max_width)
max_width = size->width; max_width = size->width;
@@ -62,9 +73,9 @@ GtkWidget *make_boolean_alsa_elem(
// set the widget minimum size to the maximum label size so that the // set the widget minimum size to the maximum label size so that the
// widget doesn't change size when the label changes // widget doesn't change size when the label changes
gtk_widget_set_size_request(button, max_width, max_height); gtk_widget_set_size_request(data->button, max_width, max_height);
toggle_button_updated(elem); toggle_button_updated(elem, data);
return button; return data->button;
} }

View File

@@ -3,15 +3,25 @@
#include "widget-combo.h" #include "widget-combo.h"
static void combo_box_changed(GtkWidget *widget, struct alsa_elem *elem) { struct combo {
int value = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); struct alsa_elem *elem;
GtkWidget *combo_box;
};
alsa_set_elem_value(elem, value); static void combo_box_changed(GtkWidget *widget, struct combo *data) {
int value = gtk_combo_box_get_active(GTK_COMBO_BOX(data->combo_box));
alsa_set_elem_value(data->elem, value);
} }
static void combo_box_updated(struct alsa_elem *elem) { static void combo_box_updated(
struct alsa_elem *elem,
void *private
) {
struct combo *data = private;
int value = alsa_get_elem_value(elem); int value = alsa_get_elem_value(elem);
gtk_combo_box_set_active(GTK_COMBO_BOX(elem->widget), value); gtk_combo_box_set_active(GTK_COMBO_BOX(data->combo_box), value);
} }
// Center-align text in the combo box // Center-align text in the combo box
@@ -29,23 +39,26 @@ static void combo_box_center_text(GtkComboBoxText *widget) {
} }
GtkWidget *make_combo_box_alsa_elem(struct alsa_elem *elem) { GtkWidget *make_combo_box_alsa_elem(struct alsa_elem *elem) {
GtkWidget *combo_box = gtk_combo_box_text_new(); struct combo *data = g_malloc(sizeof(struct combo));
combo_box_center_text(GTK_COMBO_BOX_TEXT(combo_box)); data->elem = elem;
data->combo_box = gtk_combo_box_text_new();
combo_box_center_text(GTK_COMBO_BOX_TEXT(data->combo_box));
int count = alsa_get_item_count(elem); int count = alsa_get_item_count(elem);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
const char *text = alsa_get_item_name(elem, i); const char *text = alsa_get_item_name(elem, i);
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo_box), NULL, text); gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(data->combo_box), NULL, text);
} }
g_signal_connect( g_signal_connect(
combo_box, "changed", G_CALLBACK(combo_box_changed), elem data->combo_box, "changed", G_CALLBACK(combo_box_changed), data
); );
elem->widget = combo_box;
elem->widget_callback = combo_box_updated;
combo_box_updated(elem); alsa_elem_add_callback(elem, combo_box_updated, data);
return combo_box; combo_box_updated(elem, data);
return data->combo_box;
} }

View File

@@ -3,18 +3,28 @@
#include "widget-dual.h" #include "widget-dual.h"
static void dual_button_clicked(GtkWidget *widget, struct alsa_elem *elem) { struct dual_button {
int value1 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(elem->widget)); struct alsa_elem *elem;
int value2 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(elem->widget2)); GtkWidget *button1;
GtkWidget *button2;
};
static void dual_button_clicked(GtkWidget *widget, struct dual_button *data) {
int value1 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->button1));
int value2 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->button2));
int value = value1 ? value2 + 1 : 0; int value = value1 ? value2 + 1 : 0;
alsa_set_elem_value(elem, value); alsa_set_elem_value(data->elem, value);
gtk_widget_set_sensitive(elem->widget2, value1); gtk_widget_set_sensitive(data->button2, value1);
} }
static void dual_button_updated(struct alsa_elem *elem) { static void dual_button_updated(
struct alsa_elem *elem,
void *private
) {
struct dual_button *data = private;
// value (from ALSA control) is 0/1/2 // value (from ALSA control) is 0/1/2
// value1 (first button) is 0/1/1 // value1 (first button) is 0/1/1
@@ -22,14 +32,14 @@ static void dual_button_updated(struct alsa_elem *elem) {
int value = alsa_get_elem_value(elem); int value = alsa_get_elem_value(elem);
int value1 = !!value; int value1 = !!value;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elem->widget), value1); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->button1), value1);
gtk_button_set_label(GTK_BUTTON(elem->widget), elem->bool_text[value1]); gtk_button_set_label(GTK_BUTTON(data->button1), elem->bool_text[value1]);
gtk_widget_set_sensitive(elem->widget2, value1); gtk_widget_set_sensitive(data->button2, value1);
if (value1) { if (value1) {
int value2 = value - 1; int value2 = value - 1;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elem->widget2), value2); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->button2), value2);
gtk_button_set_label( gtk_button_set_label(
GTK_BUTTON(elem->widget2), elem->bool_text[value2 + 2] GTK_BUTTON(data->button2), elem->bool_text[value2 + 2]
); );
} }
} }
@@ -38,31 +48,40 @@ static void dual_button_updated(struct alsa_elem *elem) {
// buttons: // buttons:
// first button disables/enables the feature // first button disables/enables the feature
// second button switches between the two enabled states // second button switches between the two enabled states
void make_dual_boolean_alsa_elems( GtkWidget *make_dual_boolean_alsa_elems(
struct alsa_elem *elem, struct alsa_elem *elem,
const char *label_text,
const char *disabled_text_1, const char *disabled_text_1,
const char *enabled_text_1, const char *enabled_text_1,
const char *disabled_text_2, const char *disabled_text_2,
const char *enabled_text_2 const char *enabled_text_2
) { ) {
GtkWidget *button1 = gtk_toggle_button_new(); struct dual_button *data = g_malloc(sizeof(struct dual_button));
GtkWidget *button2 = gtk_toggle_button_new(); data->elem = elem;
data->button1 = gtk_toggle_button_new();
data->button2 = gtk_toggle_button_new();
g_signal_connect( g_signal_connect(
button1, "clicked", G_CALLBACK(dual_button_clicked), elem data->button1, "clicked", G_CALLBACK(dual_button_clicked), data
); );
g_signal_connect( g_signal_connect(
button2, "clicked", G_CALLBACK(dual_button_clicked), elem data->button2, "clicked", G_CALLBACK(dual_button_clicked), data
); );
elem->widget = button1; alsa_elem_add_callback(elem, dual_button_updated, data);
elem->widget2 = button2;
elem->widget_callback = dual_button_updated;
elem->bool_text[0] = disabled_text_1; elem->bool_text[0] = disabled_text_1;
elem->bool_text[1] = enabled_text_1; elem->bool_text[1] = enabled_text_1;
elem->bool_text[2] = disabled_text_2; elem->bool_text[2] = disabled_text_2;
elem->bool_text[3] = enabled_text_2; elem->bool_text[3] = enabled_text_2;
gtk_button_set_label(GTK_BUTTON(elem->widget2), disabled_text_2); gtk_button_set_label(GTK_BUTTON(data->button2), disabled_text_2);
dual_button_updated(elem); dual_button_updated(elem, data);
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
GtkWidget *label = gtk_label_new(label_text);
gtk_box_append(GTK_BOX(box), label);
gtk_box_append(GTK_BOX(box), GTK_WIDGET(data->button1));
gtk_box_append(GTK_BOX(box), GTK_WIDGET(data->button2));
return box;
} }

View File

@@ -9,8 +9,9 @@
// buttons: // buttons:
// first button disables/enables the feature // first button disables/enables the feature
// second button switches between the two features states // second button switches between the two features states
void make_dual_boolean_alsa_elems( GtkWidget *make_dual_boolean_alsa_elems(
struct alsa_elem *alsa_elem, struct alsa_elem *alsa_elem,
const char *label_text,
const char *disabled_text_1, const char *disabled_text_1,
const char *enabled_text_1, const char *enabled_text_1,
const char *disabled_text_2, const char *disabled_text_2,

View File

@@ -4,18 +4,30 @@
#include "gtkdial.h" #include "gtkdial.h"
#include "widget-gain.h" #include "widget-gain.h"
static void gain_changed(GtkWidget *widget, struct alsa_elem *elem) { struct gain {
int value = gtk_dial_get_value(GTK_DIAL(widget)); struct alsa_elem *elem;
GtkWidget *vbox;
GtkWidget *dial;
GtkWidget *label;
};
alsa_set_elem_value(elem, value); 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);
} }
static void gain_updated(struct alsa_elem *elem) { static void gain_updated(
struct alsa_elem *elem,
void *private
) {
struct gain *data = private;
int is_writable = alsa_get_elem_writable(elem); int is_writable = alsa_get_elem_writable(elem);
gtk_widget_set_sensitive(elem->widget, is_writable); gtk_widget_set_sensitive(data->dial, is_writable);
int alsa_value = alsa_get_elem_value(elem); int alsa_value = alsa_get_elem_value(elem);
gtk_dial_set_value(GTK_DIAL(elem->widget), alsa_value); gtk_dial_set_value(GTK_DIAL(data->dial), alsa_value);
char s[20]; char s[20];
float scale = (float)(elem->max_dB - elem->min_dB) / float scale = (float)(elem->max_dB - elem->min_dB) /
@@ -28,39 +40,38 @@ static void gain_updated(struct alsa_elem *elem) {
else else
snprintf(s, 20, "%.0fdB", value); snprintf(s, 20, "%.0fdB", value);
gtk_label_set_text(GTK_LABEL(elem->widget2), s); gtk_label_set_text(GTK_LABEL(data->label), s);
} }
//GList *make_gain_alsa_elem(struct alsa_elem *elem) {
GtkWidget *make_gain_alsa_elem(struct alsa_elem *elem) { GtkWidget *make_gain_alsa_elem(struct alsa_elem *elem) {
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); struct gain *data = g_malloc(sizeof(struct gain));
gtk_widget_set_hexpand(vbox, TRUE); data->elem = elem;
data->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_hexpand(data->vbox, TRUE);
GtkWidget *dial = gtk_dial_new_with_range( data->dial = gtk_dial_new_with_range(elem->min_val, elem->max_val, 1);
elem->min_val, elem->max_val, 1
);
// calculate 0dB value from min/max dB and min/max value // calculate 0dB value from min/max dB and min/max value
float scale = (float)(elem->max_dB - elem->min_dB) / float scale = (float)(elem->max_dB - elem->min_dB) /
(elem->max_val - elem->min_val); (elem->max_val - elem->min_val);
int zero_db_value = (int)((0 - elem->min_dB) / scale + 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_dial_set_zero_db(GTK_DIAL(data->dial), zero_db_value);
gtk_widget_set_vexpand(dial, TRUE); data->label = gtk_label_new(NULL);
gtk_widget_set_vexpand(data->dial, TRUE);
g_signal_connect( g_signal_connect(
dial, "value-changed", G_CALLBACK(gain_changed), elem data->dial, "value-changed", G_CALLBACK(gain_changed), data
); );
elem->widget = dial;
elem->widget_callback = gain_updated;
GtkWidget *label = gtk_label_new(NULL); alsa_elem_add_callback(elem, gain_updated, data);
elem->widget2 = label;
gain_updated(elem); gain_updated(elem, data);
gtk_box_append(GTK_BOX(vbox), dial); gtk_box_append(GTK_BOX(data->vbox), data->dial);
gtk_box_append(GTK_BOX(vbox), label); gtk_box_append(GTK_BOX(data->vbox), data->label);
return vbox; return data->vbox;
} }

View File

@@ -3,21 +3,29 @@
#include "widget-label.h" #include "widget-label.h"
static void label_updated(struct alsa_elem *elem) { struct label {
struct alsa_elem *elem;
GtkWidget *label;
};
static void label_updated(struct alsa_elem *elem, void *private) {
struct label *data = private;
const char *text = alsa_get_item_name(elem, alsa_get_elem_value(elem)); const char *text = alsa_get_item_name(elem, alsa_get_elem_value(elem));
gtk_label_set_text(GTK_LABEL(elem->widget), text); gtk_label_set_text(GTK_LABEL(data->label), text);
} }
GtkWidget *make_label_alsa_elem(struct alsa_elem *elem) { GtkWidget *make_label_alsa_elem(struct alsa_elem *elem) {
GtkWidget *label = gtk_label_new(NULL); struct label *data = g_malloc(sizeof(struct label));
gtk_widget_set_halign(label, GTK_ALIGN_CENTER); data->label = gtk_label_new(NULL);
gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
elem->widget = label; gtk_widget_set_halign(data->label, GTK_ALIGN_CENTER);
elem->widget_callback = label_updated; gtk_widget_set_valign(data->label, GTK_ALIGN_CENTER);
label_updated(elem); alsa_elem_add_callback(elem, label_updated, data);
return label; label_updated(elem, data);
return data->label;
} }

View File

@@ -642,8 +642,7 @@ static void setup_src_drag(struct routing_src *r_src) {
} }
static void setup_snk_drag(struct routing_snk *r_snk) { static void setup_snk_drag(struct routing_snk *r_snk) {
struct alsa_elem *elem = r_snk->elem; GtkWidget *box = r_snk->box_widget;
GtkWidget *box = elem->widget;
// handle drags on the box // handle drags on the box
GtkDragSource *source = gtk_drag_source_new(); GtkDragSource *source = gtk_drag_source_new();
@@ -670,7 +669,7 @@ static void setup_snk_drag(struct routing_snk *r_snk) {
// set the box as a drop target // set the box as a drop target
GtkDropTarget *dest = gtk_drop_target_new(G_TYPE_INT, GDK_ACTION_COPY); GtkDropTarget *dest = gtk_drop_target_new(G_TYPE_INT, GDK_ACTION_COPY);
gtk_widget_add_controller(box, GTK_EVENT_CONTROLLER(dest)); gtk_widget_add_controller(box, GTK_EVENT_CONTROLLER(dest));
g_signal_connect(dest, "drop", G_CALLBACK(dropped_on_snk), elem); g_signal_connect(dest, "drop", G_CALLBACK(dropped_on_snk), r_snk->elem);
g_signal_connect(dest, "accept", G_CALLBACK(snk_drop_accept), r_snk); g_signal_connect(dest, "accept", G_CALLBACK(snk_drop_accept), r_snk);
g_signal_connect(dest, "enter", G_CALLBACK(snk_drop_enter), r_snk); g_signal_connect(dest, "enter", G_CALLBACK(snk_drop_enter), r_snk);
g_signal_connect(dest, "leave", G_CALLBACK(snk_drop_leave), r_snk); g_signal_connect(dest, "leave", G_CALLBACK(snk_drop_leave), r_snk);
@@ -747,11 +746,11 @@ static void make_snk_routing_widget(
struct alsa_elem *elem = r_snk->elem; struct alsa_elem *elem = r_snk->elem;
// create a box, a "socket", and a label // create a box, a "socket", and a label
GtkWidget *box = elem->widget = gtk_box_new(orientation, 5); GtkWidget *box = r_snk->box_widget = gtk_box_new(orientation, 5);
gtk_widget_add_css_class(box, "route-label"); gtk_widget_add_css_class(box, "route-label");
GtkWidget *label = gtk_label_new(name); GtkWidget *label = gtk_label_new(name);
gtk_box_append(GTK_BOX(box), label); gtk_box_append(GTK_BOX(box), label);
GtkWidget *socket = elem->widget2 = make_socket_widget(); GtkWidget *socket = r_snk->socket_widget = make_socket_widget();
if (orientation == GTK_ORIENTATION_VERTICAL) { if (orientation == GTK_ORIENTATION_VERTICAL) {
gtk_box_append(GTK_BOX(box), socket); gtk_box_append(GTK_BOX(box), socket);
gtk_widget_set_margin_start(box, 5); gtk_widget_set_margin_start(box, 5);
@@ -777,7 +776,7 @@ static void make_snk_routing_widget(
setup_snk_drag(r_snk); setup_snk_drag(r_snk);
} }
static void routing_updated(struct alsa_elem *elem) { static void routing_updated(struct alsa_elem *elem, void *data) {
struct alsa_card *card = elem->card; struct alsa_card *card = elem->card;
update_mixer_labels(card); update_mixer_labels(card);
@@ -797,7 +796,7 @@ static void make_routing_alsa_elem(struct routing_snk *r_snk) {
snprintf(name, 10, "%d", elem->lr_num); snprintf(name, 10, "%d", elem->lr_num);
make_snk_routing_widget(r_snk, name, GTK_ORIENTATION_VERTICAL); make_snk_routing_widget(r_snk, name, GTK_ORIENTATION_VERTICAL);
gtk_grid_attach( gtk_grid_attach(
GTK_GRID(card->routing_dsp_in_grid), elem->widget, GTK_GRID(card->routing_dsp_in_grid), r_snk->box_widget,
r_snk->port_num + 1, 0, 1, 1 r_snk->port_num + 1, 0, 1, 1
); );
@@ -810,7 +809,7 @@ static void make_routing_alsa_elem(struct routing_snk *r_snk) {
snprintf(name, 10, "%d", elem->lr_num); snprintf(name, 10, "%d", elem->lr_num);
make_snk_routing_widget(r_snk, name, GTK_ORIENTATION_VERTICAL); make_snk_routing_widget(r_snk, name, GTK_ORIENTATION_VERTICAL);
gtk_grid_attach( gtk_grid_attach(
GTK_GRID(card->routing_mixer_in_grid), elem->widget, GTK_GRID(card->routing_mixer_in_grid), r_snk->box_widget,
r_snk->port_num + 1, 0, 1, 1 r_snk->port_num + 1, 0, 1, 1
); );
@@ -828,7 +827,7 @@ static void make_routing_alsa_elem(struct routing_snk *r_snk) {
free(name); free(name);
gtk_grid_attach( gtk_grid_attach(
GTK_GRID(card->routing_pcm_out_grid), elem->widget, GTK_GRID(card->routing_pcm_out_grid), r_snk->box_widget,
0, r_snk->port_num + 1, 1, 1 0, r_snk->port_num + 1, 1, 1
); );
@@ -848,14 +847,14 @@ static void make_routing_alsa_elem(struct routing_snk *r_snk) {
free(name); free(name);
gtk_grid_attach( gtk_grid_attach(
GTK_GRID(card->routing_hw_out_grid), elem->widget, GTK_GRID(card->routing_hw_out_grid), r_snk->box_widget,
0, r_snk->port_num + 1, 1, 1 0, r_snk->port_num + 1, 1, 1
); );
} else { } else {
printf("invalid port category %d\n", r_snk->port_category); printf("invalid port category %d\n", r_snk->port_category);
} }
elem->widget_callback = routing_updated; alsa_elem_add_callback(elem, routing_updated, NULL);
} }
static void add_routing_widgets( static void add_routing_widgets(