1 /*-
2  * Copyright (c) 2008 Jannis Pohlmann <jannis@xfce.org>
3  * Copyright (c) 2012 Guido Berhoerster <guido+xfce@berhoerster.name>
4  * Copyright (c) 2020 - 2021 Rozhuk Ivan <rozhuk.im@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 
23 #include <sys/param.h>
24 #include <sys/types.h>
25 #include <inttypes.h>
26 
27 #include "gtk-mixer.h"
28 
29 
30 typedef struct gtk_mixer_window_s {
31 	GtkWidget *window;
32 
33 	/* Current window state. */
34 	gint width;
35 	gint height;
36 
37 	GtkWidget *soundcard_combo;
38 	GtkWidget *makedef_button;
39 
40 	/* Active mixer control set. */
41 	GtkWidget *mixer_container;
42 } gm_window_t, *gm_window_p;
43 
44 
45 static void
gtk_mixer_window_soundcard_changed(GtkWidget * combo __unused,gpointer user_data)46 gtk_mixer_window_soundcard_changed(GtkWidget *combo __unused,
47     gpointer user_data) {
48 	gm_window_p gm_win = user_data;
49 	char title[256];
50 	gmp_dev_p dev;
51 
52 	/* Update mixer controls for the active sound card */
53 	dev = gtk_mixer_devs_combo_cur_get(gm_win->soundcard_combo);
54 	if (NULL != dev) {
55 		snprintf(title, sizeof(title),
56 		    "%s - %s", _("Audio Mixer"),
57 		    dev->description);
58 		gtk_window_set_title(GTK_WINDOW(gm_win->window), title);
59 		gtk_widget_set_sensitive(gm_win->makedef_button,
60 		    (dev->plugin->descr->can_set_default_device &&
61 		     0 == gmp_dev_is_default(dev)));
62 	} else {
63 		gtk_window_set_title(GTK_WINDOW(gm_win->window), _("Audio Mixer"));
64 		gtk_widget_set_sensitive(gm_win->makedef_button, FALSE);
65 	}
66 	/* Update the MixerContainer containing the controls. */
67 	gtk_mixer_container_dev_set(gm_win->mixer_container, dev);
68 }
69 
70 static void
gtk_mixer_makedef_button(GtkButton * button __unused,gpointer user_data)71 gtk_mixer_makedef_button(GtkButton *button __unused, gpointer user_data) {
72 	gm_window_p gm_win = user_data;
73 	gmp_dev_p dev;
74 
75 	dev = gtk_mixer_devs_combo_cur_get(gm_win->soundcard_combo);
76 	if (NULL == dev)
77 		return;
78 	gmp_dev_set_default(dev);
79 	gtk_mixer_devs_combo_update(gm_win->soundcard_combo);
80 }
81 
82 static void
gtk_mixer_window_destroy(GtkWidget * window __unused,gpointer user_data)83 gtk_mixer_window_destroy(GtkWidget *window __unused, gpointer user_data) {
84 	gm_window_p gm_win = user_data;
85 
86 	//g_object_set(G_OBJECT(gm_win->preferences), "window-width",
87 	//    gm_win->current_width, "window-height", gm_win->current_height,
88 	//    NULL);
89 
90 	free(gm_win);
91 }
92 
93 GtkWidget *
gtk_mixer_window_create(void)94 gtk_mixer_window_create(void) {
95 	gm_window_p gm_win;
96 	GtkWidget *label, *vbox, *hbox, *mixer_frame;
97 
98 	gm_win = calloc(1, sizeof(gm_window_t));
99 	if (NULL == gm_win)
100 		return (NULL);
101 	gm_win->window = gtk_dialog_new();
102 	g_object_set_data(G_OBJECT(gm_win->window), "__gtk_mixer_window",
103 	    (void*)gm_win);
104 	g_signal_connect(gm_win->window, "destroy",
105 	    G_CALLBACK(gtk_main_quit), gm_win);
106 
107 	gm_win->height = 350;
108 	gm_win->width = 500;
109 #if 0
110 	g_object_get(gm_win->preferences, "window-width",
111 	    &gm_win->width, "window-height", &gm_win->height,
112 #endif
113 
114 	/* Configure the main window. */
115 	gtk_window_set_type_hint(GTK_WINDOW(gm_win->window),
116 	    GDK_WINDOW_TYPE_HINT_NORMAL);
117 	gtk_window_set_icon_name(GTK_WINDOW(gm_win->window), APP_ICON_NAME);
118 	gtk_window_set_title(GTK_WINDOW(gm_win->window), _("Audio Mixer"));
119 	gtk_window_set_default_size(GTK_WINDOW(gm_win->window),
120 	    gm_win->width, gm_win->height);
121 	gtk_window_set_position(GTK_WINDOW(gm_win->window), GTK_WIN_POS_CENTER);
122 	g_signal_connect(gm_win->window, "destroy",
123 	    G_CALLBACK(gtk_mixer_window_destroy), gm_win);
124 
125 	vbox = gtk_dialog_get_content_area(GTK_DIALOG(gm_win->window));
126 	gtk_widget_show(vbox);
127 
128 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, (BORDER_WIDTH * 2));
129 	gtk_container_set_border_width(GTK_CONTAINER(hbox), BORDER_WIDTH);
130 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
131 	gtk_widget_show(hbox);
132 
133 	/* Top line. */
134 	label = gtk_label_new_with_mnemonic(_("Sound _card:"));
135 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
136 	gtk_widget_show(label);
137 
138 	gm_win->soundcard_combo = gtk_mixer_devs_combo_create();
139 	g_signal_connect(gm_win->soundcard_combo, "changed",
140 	    G_CALLBACK(gtk_mixer_window_soundcard_changed), gm_win);
141 	gtk_box_pack_start(
142 	    GTK_BOX(hbox), gm_win->soundcard_combo, TRUE, TRUE, 0);
143 	gtk_label_set_mnemonic_widget(
144 	    GTK_LABEL(label), gm_win->soundcard_combo);
145 	gtk_widget_show(gm_win->soundcard_combo);
146 
147 	gm_win->makedef_button = gtk_button_new_from_icon_name("audio-card",
148 	    GTK_ICON_SIZE_BUTTON);
149 	gtk_widget_set_tooltip_text(gm_win->makedef_button, "Make default");
150 	gtk_box_pack_start(GTK_BOX(hbox), gm_win->makedef_button,
151 	    FALSE, TRUE, 0);
152 	g_signal_connect(gm_win->makedef_button, "clicked",
153 	    G_CALLBACK(gtk_mixer_makedef_button), gm_win);
154 	gtk_widget_show(gm_win->makedef_button);
155 
156 	/* Frame with tabs. */
157 	mixer_frame = gtk_frame_new(NULL);
158 	gtk_frame_set_shadow_type(GTK_FRAME(mixer_frame),
159 	    GTK_SHADOW_NONE);
160 	gtk_container_set_border_width(GTK_CONTAINER(mixer_frame),
161 	    BORDER_WIDTH);
162 	gtk_box_pack_start(GTK_BOX(vbox), mixer_frame, TRUE, TRUE, 0);
163 	gtk_widget_show(mixer_frame);
164 
165 	gm_win->mixer_container = gtk_mixer_container_create();
166 	gtk_container_add(GTK_CONTAINER(mixer_frame),
167 	    gm_win->mixer_container);
168 	gtk_widget_show(gm_win->mixer_container);
169 
170 	/* Update mixer controls for the active sound card. */
171 	gtk_mixer_window_soundcard_changed(NULL, gm_win);
172 
173 	return (gm_win->window);
174 }
175 
176 gulong
gtk_mixer_window_connect_dev_changed(GtkWidget * window,GCallback c_handler,gpointer data)177 gtk_mixer_window_connect_dev_changed(GtkWidget *window,
178     GCallback c_handler, gpointer data) {
179 	gm_window_p gm_win = g_object_get_data(G_OBJECT(window),
180 	    "__gtk_mixer_window");
181 
182 	if (NULL == gm_win)
183 		return (0);
184 
185 	return (g_signal_connect(gm_win->soundcard_combo, "changed",
186 	    c_handler, data));
187 }
188 
189 gmp_dev_p
gtk_mixer_window_dev_cur_get(GtkWidget * window)190 gtk_mixer_window_dev_cur_get(GtkWidget *window) {
191 	gm_window_p gm_win = g_object_get_data(G_OBJECT(window),
192 	    "__gtk_mixer_window");
193 
194 	if (NULL == gm_win)
195 		return (0);
196 	return (gtk_mixer_devs_combo_cur_get(gm_win->soundcard_combo));
197 }
198 
199 void
gtk_mixer_window_dev_cur_set(GtkWidget * window,gmp_dev_p dev)200 gtk_mixer_window_dev_cur_set(GtkWidget *window, gmp_dev_p dev) {
201 	gm_window_p gm_win = g_object_get_data(G_OBJECT(window),
202 	    "__gtk_mixer_window");
203 
204 	if (NULL == gm_win)
205 		return;
206 	gtk_mixer_devs_combo_cur_set(gm_win->soundcard_combo, dev);
207 }
208 
209 void
gtk_mixer_window_dev_list_update(GtkWidget * window,gmp_dev_list_p dev_list)210 gtk_mixer_window_dev_list_update(GtkWidget *window, gmp_dev_list_p dev_list) {
211 	gmp_dev_p dev;
212 	gm_window_p gm_win = g_object_get_data(G_OBJECT(window),
213 	    "__gtk_mixer_window");
214 
215 	if (NULL == gm_win)
216 		return;
217 
218 	/* Update dev list only if it can be changed. */
219 	dev = gtk_mixer_devs_combo_cur_get(gm_win->soundcard_combo);
220 	if (NULL != dev_list) {
221 		gtk_mixer_devs_combo_dev_list_set(gm_win->soundcard_combo,
222 		    dev_list);
223 	}
224 	if (NULL != dev &&
225 	    dev->plugin->descr->can_set_default_device) {
226 		gtk_mixer_devs_combo_update(gm_win->soundcard_combo);
227 		gtk_widget_set_sensitive(gm_win->makedef_button,
228 		    (0 == gmp_dev_is_default(dev)));
229 	}
230 }
231 
232 void
gtk_mixer_window_lines_update(GtkWidget * window)233 gtk_mixer_window_lines_update(GtkWidget *window) {
234 	gm_window_p gm_win = g_object_get_data(G_OBJECT(window),
235 	    "__gtk_mixer_window");
236 
237 	if (NULL == gm_win)
238 		return;
239 	gtk_mixer_container_update(gm_win->mixer_container);
240 }
241