diff --git a/src/alsa.c b/src/alsa.c index 6b55dfb..9fc12d6 100644 --- a/src/alsa.c +++ b/src/alsa.c @@ -116,6 +116,20 @@ int is_elem_routing_snk(struct alsa_elem *elem) { 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 // 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) { - if (!elem->widget) + if (!elem || !elem->callbacks) return; - if (!elem->widget_callback) - return; - elem->widget_callback(elem); + + for (GList *l = elem->callbacks; l; l = l->next) { + 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( diff --git a/src/alsa.h b/src/alsa.h index 2013d29..f04b44b 100644 --- a/src/alsa.h +++ b/src/alsa.h @@ -17,7 +17,7 @@ struct alsa_card; // typedef for callbacks to update widgets when the alsa element // 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 // 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 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 int port_category; @@ -103,6 +109,12 @@ struct routing_snk { 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 struct alsa_elem { @@ -125,15 +137,8 @@ struct alsa_elem { // TODO: move this to struct routing_snk? int lr_num; - // the primary GTK widget and callback function for this ALSA - // control element - GtkWidget *widget; - AlsaElemCallback *widget_callback; - - // text label for volume controls - // handle for routing controls - // second button for dual controls - GtkWidget *widget2; + // the callback functions for this ALSA control element + GList *callbacks; // for boolean buttons, the two 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 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 int alsa_get_elem_type(struct alsa_elem *elem); char *alsa_get_elem_name(struct alsa_elem *elem); diff --git a/src/iface-mixer.c b/src/iface-mixer.c index 2dada67..ded58b8 100644 --- a/src/iface-mixer.c +++ b/src/iface-mixer.c @@ -92,18 +92,19 @@ static void add_speaker_switching_controls( if (!speaker_switching) return; - make_dual_boolean_alsa_elems(speaker_switching, "Off", "On", "Main", "Alt"); - GtkWidget *b = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); + GtkWidget *w = make_dual_boolean_alsa_elems( + speaker_switching, + "Speaker Switching", + "Off", "On", "Main", "Alt" + ); + gtk_widget_set_tooltip_text( - b, + w, "Speaker Switching lets you swap between two pairs of " "monitoring speakers very easily." ); - GtkWidget *l = gtk_label_new("Speaker Switching"); - gtk_box_append(GTK_BOX(global_controls), b); - 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); + + gtk_box_append(GTK_BOX(global_controls), w); } static void add_talkback_controls( @@ -119,19 +120,20 @@ static void add_talkback_controls( if (!talkback) return; - make_dual_boolean_alsa_elems(talkback, "Disabled", "Enabled", "Off", "On"); - GtkWidget *b = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); + GtkWidget *w = make_dual_boolean_alsa_elems( + talkback, + "Talkback", + "Disabled", "Enabled", "Off", "On" + ); + gtk_widget_set_tooltip_text( - b, + w, "Talkback lets you add another channel (usually the talkback " "mic) to a mix with a button push, usually to talk to " "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(b), l); - gtk_box_append(GTK_BOX(b), talkback->widget); - gtk_box_append(GTK_BOX(b), talkback->widget2); + + gtk_box_append(GTK_BOX(global_controls), w); } 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" ); 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) { w = make_boolean_alsa_elem( elem, "*audio-volume-medium", "*audio-volume-low" diff --git a/src/routing-lines.c b/src/routing-lines.c index 502d94e..77c6d90 100644 --- a/src/routing-lines.c +++ b/src/routing-lines.c @@ -258,7 +258,7 @@ static void get_snk_center( double *x, 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)) (*y)++; } diff --git a/src/widget-boolean.c b/src/widget-boolean.c index bfcd804..c9c78e8 100644 --- a/src/widget-boolean.c +++ b/src/widget-boolean.c @@ -3,32 +3,42 @@ #include "widget-boolean.h" +struct boolean { + struct alsa_elem *elem; + GtkWidget *button; +}; + static void button_clicked(GtkWidget *widget, struct alsa_elem *elem) { int value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); 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) return; if (*text == '*') { 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 { - 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); - gtk_widget_set_sensitive(elem->widget, is_writable); + gtk_widget_set_sensitive(data->button, is_writable); 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( @@ -36,23 +46,24 @@ GtkWidget *make_boolean_alsa_elem( const char *disabled_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( - button, "clicked", G_CALLBACK(button_clicked), elem + data->button, "clicked", G_CALLBACK(button_clicked), elem ); - elem->widget = button; - elem->widget_callback = toggle_button_updated; + alsa_elem_add_callback(elem, toggle_button_updated, data); elem->bool_text[0] = disabled_text; elem->bool_text[1] = enabled_text; // find the maximum width and height of both possible labels int max_width = 0, max_height = 0; 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(); - gtk_widget_get_preferred_size(button, size, NULL); + gtk_widget_get_preferred_size(data->button, size, NULL); if (size->width > max_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 // 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; } diff --git a/src/widget-combo.c b/src/widget-combo.c index 127709a..ccce1f7 100644 --- a/src/widget-combo.c +++ b/src/widget-combo.c @@ -3,15 +3,25 @@ #include "widget-combo.h" -static void combo_box_changed(GtkWidget *widget, struct alsa_elem *elem) { - int value = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); +struct combo { + 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); - 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 @@ -29,23 +39,26 @@ static void combo_box_center_text(GtkComboBoxText *widget) { } GtkWidget *make_combo_box_alsa_elem(struct alsa_elem *elem) { - GtkWidget *combo_box = gtk_combo_box_text_new(); - combo_box_center_text(GTK_COMBO_BOX_TEXT(combo_box)); + struct combo *data = g_malloc(sizeof(struct combo)); + 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); for (int i = 0; i < count; 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( - 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; } diff --git a/src/widget-dual.c b/src/widget-dual.c index 95f1bb4..51f09a2 100644 --- a/src/widget-dual.c +++ b/src/widget-dual.c @@ -3,18 +3,28 @@ #include "widget-dual.h" -static void dual_button_clicked(GtkWidget *widget, struct alsa_elem *elem) { - int value1 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(elem->widget)); - int value2 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(elem->widget2)); +struct dual_button { + struct alsa_elem *elem; + 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; - 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 // 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 value1 = !!value; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elem->widget), value1); - gtk_button_set_label(GTK_BUTTON(elem->widget), elem->bool_text[value1]); - gtk_widget_set_sensitive(elem->widget2, value1); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->button1), value1); + gtk_button_set_label(GTK_BUTTON(data->button1), elem->bool_text[value1]); + gtk_widget_set_sensitive(data->button2, value1); if (value1) { 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(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: // first button disables/enables the feature // second button switches between the two enabled states -void make_dual_boolean_alsa_elems( +GtkWidget *make_dual_boolean_alsa_elems( struct alsa_elem *elem, + const char *label_text, const char *disabled_text_1, const char *enabled_text_1, const char *disabled_text_2, const char *enabled_text_2 ) { - GtkWidget *button1 = gtk_toggle_button_new(); - GtkWidget *button2 = gtk_toggle_button_new(); + struct dual_button *data = g_malloc(sizeof(struct dual_button)); + data->elem = elem; + data->button1 = gtk_toggle_button_new(); + data->button2 = gtk_toggle_button_new(); g_signal_connect( - button1, "clicked", G_CALLBACK(dual_button_clicked), elem + data->button1, "clicked", G_CALLBACK(dual_button_clicked), data ); g_signal_connect( - button2, "clicked", G_CALLBACK(dual_button_clicked), elem + data->button2, "clicked", G_CALLBACK(dual_button_clicked), data ); - elem->widget = button1; - elem->widget2 = button2; - elem->widget_callback = dual_button_updated; + alsa_elem_add_callback(elem, dual_button_updated, data); elem->bool_text[0] = disabled_text_1; elem->bool_text[1] = enabled_text_1; elem->bool_text[2] = disabled_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; } diff --git a/src/widget-dual.h b/src/widget-dual.h index 2add820..ab8e2b1 100644 --- a/src/widget-dual.h +++ b/src/widget-dual.h @@ -9,8 +9,9 @@ // buttons: // first button disables/enables the feature // 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, + const char *label_text, const char *disabled_text_1, const char *enabled_text_1, const char *disabled_text_2, diff --git a/src/widget-gain.c b/src/widget-gain.c index 6b75a08..afcab48 100644 --- a/src/widget-gain.c +++ b/src/widget-gain.c @@ -4,18 +4,30 @@ #include "gtkdial.h" #include "widget-gain.h" -static void gain_changed(GtkWidget *widget, struct alsa_elem *elem) { - int value = gtk_dial_get_value(GTK_DIAL(widget)); +struct gain { + 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); - gtk_widget_set_sensitive(elem->widget, is_writable); + gtk_widget_set_sensitive(data->dial, is_writable); 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]; float scale = (float)(elem->max_dB - elem->min_dB) / @@ -28,39 +40,38 @@ static void gain_updated(struct alsa_elem *elem) { else 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 *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - gtk_widget_set_hexpand(vbox, TRUE); + struct gain *data = g_malloc(sizeof(struct gain)); + 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( - elem->min_val, elem->max_val, 1 - ); + data->dial = gtk_dial_new_with_range(elem->min_val, elem->max_val, 1); // 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_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( - 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); - elem->widget2 = label; + alsa_elem_add_callback(elem, gain_updated, data); - gain_updated(elem); + gain_updated(elem, data); - gtk_box_append(GTK_BOX(vbox), dial); - gtk_box_append(GTK_BOX(vbox), label); + gtk_box_append(GTK_BOX(data->vbox), data->dial); + gtk_box_append(GTK_BOX(data->vbox), data->label); - return vbox; + return data->vbox; } diff --git a/src/widget-label.c b/src/widget-label.c index 9af9fb2..814e1c5 100644 --- a/src/widget-label.c +++ b/src/widget-label.c @@ -3,21 +3,29 @@ #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)); - 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 *label = gtk_label_new(NULL); - gtk_widget_set_halign(label, GTK_ALIGN_CENTER); - gtk_widget_set_valign(label, GTK_ALIGN_CENTER); + struct label *data = g_malloc(sizeof(struct label)); + data->label = gtk_label_new(NULL); - elem->widget = label; - elem->widget_callback = label_updated; + gtk_widget_set_halign(data->label, GTK_ALIGN_CENTER); + 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; } diff --git a/src/window-routing.c b/src/window-routing.c index fdf5b82..12d1a50 100644 --- a/src/window-routing.c +++ b/src/window-routing.c @@ -642,8 +642,7 @@ static void setup_src_drag(struct routing_src *r_src) { } static void setup_snk_drag(struct routing_snk *r_snk) { - struct alsa_elem *elem = r_snk->elem; - GtkWidget *box = elem->widget; + GtkWidget *box = r_snk->box_widget; // handle drags on the box 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 GtkDropTarget *dest = gtk_drop_target_new(G_TYPE_INT, GDK_ACTION_COPY); 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, "enter", G_CALLBACK(snk_drop_enter), 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; // 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"); GtkWidget *label = gtk_label_new(name); 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) { gtk_box_append(GTK_BOX(box), socket); gtk_widget_set_margin_start(box, 5); @@ -777,7 +776,7 @@ static void make_snk_routing_widget( 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; 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); make_snk_routing_widget(r_snk, name, GTK_ORIENTATION_VERTICAL); 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 ); @@ -810,7 +809,7 @@ static void make_routing_alsa_elem(struct routing_snk *r_snk) { snprintf(name, 10, "%d", elem->lr_num); make_snk_routing_widget(r_snk, name, GTK_ORIENTATION_VERTICAL); 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 ); @@ -828,7 +827,7 @@ static void make_routing_alsa_elem(struct routing_snk *r_snk) { free(name); 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 ); @@ -848,14 +847,14 @@ static void make_routing_alsa_elem(struct routing_snk *r_snk) { free(name); 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 ); } else { 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(