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