1 /*-
2 * Copyright (c) 2008 Jannis Pohlmann <jannis@xfce.org>
3 * Copyright (c) 2020 - 2021 Rozhuk Ivan <rozhuk.im@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21
22 #include <sys/param.h>
23 #include <sys/types.h>
24 #include <inttypes.h>
25
26 #include "gtk-mixer.h"
27
28 #define GM_CMB_DEVS_COLUMN_NAME 0
29 #define GM_CMB_DEVS_COLUMN_CARD 1
30
31
32 static void
gtk_mixer_devs_combo_changed(GtkWidget * combo,gpointer user_data __unused)33 gtk_mixer_devs_combo_changed(GtkWidget *combo, gpointer user_data __unused) {
34 GtkTreeIter iter;
35 GtkListStore *list_store = g_object_get_data(G_OBJECT(combo),
36 "__gtk_mixer_devs_combo_list_store");
37 gmp_dev_p dev_new = NULL;
38 gmp_dev_p dev_old = g_object_get_data(G_OBJECT(combo),
39 "__gtk_mixer_devs_combo_current");
40
41 if (NULL == list_store)
42 return;
43 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) {
44 gtk_tree_model_get(GTK_TREE_MODEL(list_store), &iter,
45 GM_CMB_DEVS_COLUMN_CARD, &dev_new, -1);
46 }
47
48 /* Init/uninit here, before other get notification. */
49 gmp_dev_init(dev_new);
50 g_object_set_data(G_OBJECT(combo),
51 "__gtk_mixer_devs_combo_current", dev_new);
52 gmp_dev_uninit(dev_old);
53 }
54
55 static void
gtk_mixer_devs_combo_destroy(GtkWidget * combo __unused,gpointer user_data)56 gtk_mixer_devs_combo_destroy(GtkWidget *combo __unused, gpointer user_data) {
57 GtkListStore *list_store = user_data;
58
59 gtk_list_store_clear(list_store);
60 g_object_unref(list_store);
61 }
62
63 GtkWidget *
gtk_mixer_devs_combo_create(void)64 gtk_mixer_devs_combo_create(void) {
65 GtkWidget *combo;
66 GtkListStore *list_store;
67 GtkCellRenderer *renderer;
68
69 combo = gtk_combo_box_new();
70
71 list_store = gtk_list_store_new(2, G_TYPE_STRING,
72 G_TYPE_POINTER);
73 g_object_set_data(G_OBJECT(combo),
74 "__gtk_mixer_devs_combo_list_store", list_store);
75 gtk_combo_box_set_model(GTK_COMBO_BOX(combo),
76 GTK_TREE_MODEL(list_store));
77
78 g_signal_connect(combo, "changed",
79 G_CALLBACK(gtk_mixer_devs_combo_changed), NULL);
80 g_signal_connect(combo, "destroy",
81 G_CALLBACK(gtk_mixer_devs_combo_destroy), list_store);
82
83 renderer = gtk_cell_renderer_text_new();
84 g_object_set(G_OBJECT(renderer), "ellipsize",
85 PANGO_ELLIPSIZE_END, NULL);
86 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE);
87 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo), renderer,
88 "text", GM_CMB_DEVS_COLUMN_NAME);
89
90 return (combo);
91 }
92
93 gmp_dev_p
gtk_mixer_devs_combo_cur_get(GtkWidget * combo)94 gtk_mixer_devs_combo_cur_get(GtkWidget *combo) {
95
96 if (NULL == combo)
97 return (NULL);
98 return (g_object_get_data(G_OBJECT(combo),
99 "__gtk_mixer_devs_combo_current"));
100 }
101
102 void
gtk_mixer_devs_combo_cur_set(GtkWidget * combo,gmp_dev_p dev)103 gtk_mixer_devs_combo_cur_set(GtkWidget *combo,
104 gmp_dev_p dev) {
105 gmp_dev_p device_cur = NULL;
106 GtkTreeIter iter;
107 gboolean valid_iter;
108 GtkListStore *list_store = g_object_get_data(G_OBJECT(combo),
109 "__gtk_mixer_devs_combo_list_store");
110
111 if (NULL == dev || NULL == list_store) {
112 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
113 return;
114 }
115 valid_iter = gtk_tree_model_get_iter_first(
116 GTK_TREE_MODEL(list_store), &iter);
117 while (valid_iter) {
118 gtk_tree_model_get(GTK_TREE_MODEL(list_store),
119 &iter, GM_CMB_DEVS_COLUMN_CARD, &device_cur, -1);
120 if (device_cur == dev) {
121 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo),
122 &iter);
123 break;
124 }
125 valid_iter = gtk_tree_model_iter_next(
126 GTK_TREE_MODEL(list_store), &iter);
127 }
128 }
129
130 static inline void
gtk_mixer_devs_combo_dev_descr(gmp_dev_p dev,char * buf,size_t buf_size)131 gtk_mixer_devs_combo_dev_descr(gmp_dev_p dev, char *buf, size_t buf_size) {
132
133 if (NULL == buf || 0 == buf_size)
134 return;
135 if (NULL == dev) {
136 buf[0] = 0x00;
137 return;
138 }
139 snprintf(buf, buf_size,
140 "%s: %s (%s)%s",
141 dev->plugin->descr->name,
142 dev->description,
143 dev->name,
144 ((gmp_dev_is_default(dev)) ? " [default]" : ""));
145 }
146
147 void
gtk_mixer_devs_combo_dev_list_set(GtkWidget * combo,gmp_dev_list_p dev_list)148 gtk_mixer_devs_combo_dev_list_set(GtkWidget *combo, gmp_dev_list_p dev_list) {
149 gmp_dev_p dev = NULL;
150 GtkTreeIter iter;
151 GtkListStore *list_store = g_object_get_data(G_OBJECT(combo),
152 "__gtk_mixer_devs_combo_list_store");
153 char display_name[256];
154
155 if (NULL == list_store)
156 return;
157
158 gtk_list_store_clear(list_store);
159 if (NULL == dev_list)
160 return;
161 for (size_t i = 0; i < dev_list->count; i ++) {
162 gtk_list_store_append(list_store, &iter);
163 dev = &dev_list->devs[i];
164 gtk_mixer_devs_combo_dev_descr(dev,
165 display_name, sizeof(display_name));
166 gtk_list_store_set(list_store, &iter,
167 GM_CMB_DEVS_COLUMN_CARD, dev,
168 GM_CMB_DEVS_COLUMN_NAME, display_name, -1);
169 }
170 }
171 void
gtk_mixer_devs_combo_update(GtkWidget * combo)172 gtk_mixer_devs_combo_update(GtkWidget *combo) {
173 gmp_dev_p dev = NULL;
174 GtkTreeIter iter;
175 gboolean valid_iter;
176 GtkListStore *list_store = g_object_get_data(G_OBJECT(combo),
177 "__gtk_mixer_devs_combo_list_store");
178 char display_name[256];
179
180 if (NULL == list_store)
181 return;
182
183 valid_iter = gtk_tree_model_get_iter_first(
184 GTK_TREE_MODEL(list_store), &iter);
185 while (valid_iter) {
186 gtk_tree_model_get(GTK_TREE_MODEL(list_store),
187 &iter, GM_CMB_DEVS_COLUMN_CARD, &dev, -1);
188 gtk_mixer_devs_combo_dev_descr(dev,
189 display_name, sizeof(display_name));
190 gtk_list_store_set(list_store, &iter,
191 GM_CMB_DEVS_COLUMN_NAME, display_name, -1);
192 valid_iter = gtk_tree_model_iter_next(
193 GTK_TREE_MODEL(list_store), &iter);
194 }
195 }
196