This repository has been archived on 2025-09-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
alsa-scarlett-gui/src/widget-boolean.c
Geoffrey D. Bennett 3f7a4c2063 Allow for boolean controls that are backwards
Gen 1 has playback controls (0 = off, 1 = on), not mute controls
(0 = not muted, 1 = muted) like the Gen 2+ do.
2024-03-31 03:29:10 +10:30

105 lines
2.9 KiB
C

// SPDX-FileCopyrightText: 2022-2024 Geoffrey D. Bennett <g@b4.vu>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "widget-boolean.h"
struct boolean {
struct alsa_elem *elem;
int backwards;
GtkWidget *button;
guint source;
const char *text[2];
};
static void button_clicked(GtkWidget *widget, struct boolean *data) {
int value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
alsa_set_elem_value(data->elem, value ^ data->backwards);
}
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(button), icon);
} else {
gtk_button_set_label(GTK_BUTTON(button), text);
}
}
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(data->button, is_writable);
int value = !!alsa_get_elem_value(elem) ^ data->backwards;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->button), value);
toggle_button_set_text(data->button, data->text[value]);
}
static gboolean update_toggle_button(struct boolean *data) {
toggle_button_updated(data->elem, data);
return G_SOURCE_CONTINUE;
}
static void on_destroy(struct boolean *data) {
if (data->source)
g_source_remove(data->source);
g_free(data);
}
GtkWidget *make_boolean_alsa_elem(
struct alsa_elem *elem,
const char *disabled_text,
const char *enabled_text
) {
struct boolean *data = g_malloc0(sizeof(struct boolean));
data->elem = elem;
data->button = gtk_toggle_button_new();
g_signal_connect(
data->button, "clicked", G_CALLBACK(button_clicked), data
);
alsa_elem_add_callback(elem, toggle_button_updated, data);
data->text[0] = disabled_text;
data->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(data->button, data->text[i]);
GtkRequisition *size = gtk_requisition_new();
gtk_widget_get_preferred_size(data->button, size, NULL);
if (size->width > max_width)
max_width = size->width;
if (size->height > max_height)
max_height = size->height;
}
// 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(data->button, max_width, max_height);
toggle_button_updated(elem, data);
// periodically update volatile controls
if (alsa_get_elem_volatile(elem))
data->source =
g_timeout_add_seconds(1, (GSourceFunc)update_toggle_button, data);
g_object_weak_ref(G_OBJECT(data->button), (GWeakNotify)on_destroy, data);
return data->button;
}