1 /*
2 * Copyright (C) 2020-2021 Alexandros Theodotou <alex at zrythm dot org>
3 *
4 * This file is part of Zrythm
5 *
6 * Zrythm is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Zrythm 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
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "audio/track.h"
21 #include "gui/widgets/balance_control.h"
22 #include "gui/widgets/center_dock.h"
23 #include "gui/widgets/fader.h"
24 #include "gui/widgets/fader_controls_expander.h"
25 #include "gui/widgets/fader_buttons.h"
26 #include "gui/widgets/inspector_track.h"
27 #include "gui/widgets/left_dock_edge.h"
28 #include "gui/widgets/main_window.h"
29 #include "gui/widgets/meter.h"
30 #include "project.h"
31 #include "utils/flags.h"
32 #include "utils/gtk.h"
33 #include "utils/math.h"
34 #include "utils/resources.h"
35 #include "utils/ui.h"
36 #include "zrythm_app.h"
37
38 #include <glib/gi18n.h>
39
G_DEFINE_TYPE(FaderButtonsWidget,fader_buttons_widget,GTK_TYPE_BUTTON_BOX)40 G_DEFINE_TYPE (
41 FaderButtonsWidget,
42 fader_buttons_widget,
43 GTK_TYPE_BUTTON_BOX)
44
45 static void
46 on_record_toggled (
47 GtkToggleButton * btn,
48 FaderButtonsWidget * self)
49 {
50 Track * track = self->track;
51 if (track)
52 {
53 if (!track_is_selected (track))
54 {
55 track_select (
56 track, F_SELECT, F_EXCLUSIVE,
57 F_PUBLISH_EVENTS);
58 }
59 track_set_recording (
60 track,
61 gtk_toggle_button_get_active (btn), 1);
62 }
63 }
64
65 static void
on_solo_toggled(GtkToggleButton * btn,FaderButtonsWidget * self)66 on_solo_toggled (
67 GtkToggleButton * btn,
68 FaderButtonsWidget * self)
69 {
70 Track * track = self->track;
71 if (track)
72 {
73 track_set_soloed (
74 self->track,
75 gtk_toggle_button_get_active (btn),
76 F_TRIGGER_UNDO, F_AUTO_SELECT,
77 F_PUBLISH_EVENTS);
78 }
79 }
80
81 static void
on_mute_toggled(GtkToggleButton * btn,FaderButtonsWidget * self)82 on_mute_toggled (
83 GtkToggleButton * btn,
84 FaderButtonsWidget * self)
85 {
86 Track * track = self->track;
87 if (track)
88 {
89 track_set_muted (
90 self->track,
91 gtk_toggle_button_get_active (btn),
92 F_TRIGGER_UNDO, F_AUTO_SELECT,
93 F_PUBLISH_EVENTS);
94 }
95 }
96
97 static void
on_listen_toggled(GtkToggleButton * btn,FaderButtonsWidget * self)98 on_listen_toggled (
99 GtkToggleButton * btn,
100 FaderButtonsWidget * self)
101 {
102 Track * track = self->track;
103 if (track)
104 {
105 track_set_listened (
106 self->track,
107 gtk_toggle_button_get_active (btn),
108 F_TRIGGER_UNDO, F_AUTO_SELECT,
109 F_PUBLISH_EVENTS);
110 }
111 }
112
113 static void
on_mono_compat_toggled(GtkToggleButton * btn,FaderButtonsWidget * self)114 on_mono_compat_toggled (
115 GtkToggleButton * btn,
116 FaderButtonsWidget * self)
117 {
118 Track * track = self->track;
119 if (track)
120 {
121 if (!track_is_selected (track))
122 {
123 track_select (
124 track, F_SELECT, F_EXCLUSIVE,
125 F_PUBLISH_EVENTS);
126 }
127 channel_set_mono_compat_enabled (
128 track->channel,
129 gtk_toggle_button_get_active (btn),
130 F_PUBLISH_EVENTS);
131 }
132 }
133
134 void
fader_buttons_widget_block_signal_handlers(FaderButtonsWidget * self)135 fader_buttons_widget_block_signal_handlers (
136 FaderButtonsWidget * self)
137 {
138 #if 0
139 g_debug (
140 "blocking signal handlers for %s...",
141 self->track->name);
142 #endif
143
144 g_signal_handler_block (
145 self->mono_compat,
146 self->mono_compat_toggled_handler_id);
147 g_signal_handler_block (
148 self->solo,
149 self->solo_toggled_handler_id);
150 g_signal_handler_block (
151 self->mute,
152 self->mute_toggled_handler_id);
153 g_signal_handler_block (
154 self->listen,
155 self->listen_toggled_handler_id);
156 g_signal_handler_block (
157 self->record,
158 self->record_toggled_handler_id);
159 }
160
161 void
fader_buttons_widget_unblock_signal_handlers(FaderButtonsWidget * self)162 fader_buttons_widget_unblock_signal_handlers (
163 FaderButtonsWidget * self)
164 {
165 #if 0
166 g_debug (
167 "unblocking signal handlers for %s...",
168 self->track->name);
169 #endif
170
171 g_signal_handler_unblock (
172 self->mono_compat,
173 self->mono_compat_toggled_handler_id);
174 g_signal_handler_unblock (
175 self->solo,
176 self->solo_toggled_handler_id);
177 g_signal_handler_unblock (
178 self->mute,
179 self->mute_toggled_handler_id);
180 g_signal_handler_unblock (
181 self->listen,
182 self->listen_toggled_handler_id);
183 g_signal_handler_unblock (
184 self->record,
185 self->record_toggled_handler_id);
186 }
187
188 void
fader_buttons_widget_refresh(FaderButtonsWidget * self,Track * track)189 fader_buttons_widget_refresh (
190 FaderButtonsWidget * self,
191 Track * track)
192 {
193 self->track = track;
194
195 if (track)
196 {
197 fader_buttons_widget_block_signal_handlers (
198 self);
199 if (track_type_has_mono_compat_switch (
200 track->type))
201 {
202 gtk_toggle_button_set_active (
203 self->mono_compat,
204 channel_get_mono_compat_enabled (
205 track->channel));
206 gtk_widget_set_visible (
207 GTK_WIDGET (self->mono_compat), true);
208 }
209 else
210 {
211 gtk_widget_set_visible (
212 GTK_WIDGET (self->mono_compat), false);
213 }
214 gtk_toggle_button_set_active (
215 self->mute, track_get_muted (track));
216 if (track_type_can_record (track->type))
217 {
218 gtk_widget_set_visible (
219 GTK_WIDGET (self->record), true);
220 gtk_toggle_button_set_active (
221 self->record,
222 track_get_recording (track));
223 }
224 else
225 {
226 gtk_widget_set_visible (
227 GTK_WIDGET (self->record), false);
228 }
229 gtk_toggle_button_set_active (
230 self->solo, track_get_soloed (track));
231 gtk_toggle_button_set_active (
232 self->listen, track_get_listened (track));
233 fader_buttons_widget_unblock_signal_handlers (
234 self);
235 }
236 }
237
238 static void
on_btn_right_click(GtkGestureMultiPress * gesture,gint n_press,gdouble x_dbl,gdouble y_dbl,FaderButtonsWidget * self)239 on_btn_right_click (
240 GtkGestureMultiPress * gesture,
241 gint n_press,
242 gdouble x_dbl,
243 gdouble y_dbl,
244 FaderButtonsWidget * self)
245 {
246 GtkWidget * widget =
247 gtk_event_controller_get_widget (
248 GTK_EVENT_CONTROLLER (gesture));
249
250 Fader * fader =
251 track_get_fader (self->track, true);
252
253 GtkWidget * menu = gtk_menu_new();
254 GtkWidget * menuitem =
255 GTK_WIDGET (CREATE_MIDI_LEARN_MENU_ITEM);
256
257 Port * port = NULL;
258 if (widget == GTK_WIDGET (self->mute))
259 {
260 port = fader->mute;
261 }
262 else if (widget == GTK_WIDGET (self->solo))
263 {
264 port = fader->solo;
265 }
266 else if (widget == GTK_WIDGET (self->listen))
267 {
268 port = fader->listen;
269 }
270 else if (widget == GTK_WIDGET (self->mono_compat))
271 {
272 port = fader->mono_compat_enabled;
273 }
274 else if (widget == GTK_WIDGET (self->record))
275 {
276 port = self->track->recording;
277 }
278
279 g_signal_connect (
280 menuitem, "activate",
281 G_CALLBACK (ui_bind_midi_cc_item_activate_cb),
282 port);
283 gtk_menu_shell_append (
284 GTK_MENU_SHELL (menu), menuitem);
285
286 gtk_widget_show_all (menu);
287 gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
288 }
289
290 static void
fader_buttons_finalize(FaderButtonsWidget * self)291 fader_buttons_finalize (
292 FaderButtonsWidget * self)
293 {
294 g_debug ("finalizing...");
295
296 G_OBJECT_CLASS (
297 fader_buttons_widget_parent_class)->
298 finalize (G_OBJECT (self));
299
300 g_debug ("done");
301 }
302
303 static void
fader_buttons_widget_init(FaderButtonsWidget * self)304 fader_buttons_widget_init (
305 FaderButtonsWidget * self)
306 {
307 gtk_widget_init_template (GTK_WIDGET (self));
308
309 /* add css classes */
310 GtkStyleContext * context =
311 gtk_widget_get_style_context (
312 GTK_WIDGET (self->record));
313 gtk_style_context_add_class (
314 context, "record-button");
315 context =
316 gtk_widget_get_style_context (
317 GTK_WIDGET (self->solo));
318 gtk_style_context_add_class (
319 context, "solo-button");
320
321 self->mono_compat_toggled_handler_id =
322 g_signal_connect (
323 G_OBJECT (self->mono_compat), "toggled",
324 G_CALLBACK (on_mono_compat_toggled), self);
325 self->solo_toggled_handler_id =
326 g_signal_connect (
327 G_OBJECT (self->solo), "toggled",
328 G_CALLBACK (on_solo_toggled), self);
329 self->mute_toggled_handler_id =
330 g_signal_connect (
331 G_OBJECT (self->mute), "toggled",
332 G_CALLBACK (on_mute_toggled), self);
333 self->listen_toggled_handler_id =
334 g_signal_connect (
335 G_OBJECT (self->listen), "toggled",
336 G_CALLBACK (on_listen_toggled), self);
337 self->record_toggled_handler_id =
338 g_signal_connect (
339 G_OBJECT (self->record), "toggled",
340 G_CALLBACK (on_record_toggled), self);
341
342 /* add right click menus */
343 GtkGestureMultiPress * mp;
344
345 #define ADD_RIGHT_CLICK_CB(widget) \
346 mp = \
347 GTK_GESTURE_MULTI_PRESS ( \
348 gtk_gesture_multi_press_new ( \
349 GTK_WIDGET (widget))); \
350 gtk_gesture_single_set_button ( \
351 GTK_GESTURE_SINGLE (mp), \
352 GDK_BUTTON_SECONDARY); \
353 g_signal_connect ( \
354 G_OBJECT (mp), "pressed", \
355 G_CALLBACK (on_btn_right_click), self)
356
357 ADD_RIGHT_CLICK_CB (self->mute);
358 ADD_RIGHT_CLICK_CB (self->solo);
359 ADD_RIGHT_CLICK_CB (self->listen);
360 ADD_RIGHT_CLICK_CB (self->mono_compat);
361 ADD_RIGHT_CLICK_CB (self->record);
362
363 #undef ADD_RIGHT_CLICK_CB
364 }
365
366 static void
fader_buttons_widget_class_init(FaderButtonsWidgetClass * _klass)367 fader_buttons_widget_class_init (
368 FaderButtonsWidgetClass * _klass)
369 {
370 GtkWidgetClass * klass =
371 GTK_WIDGET_CLASS (_klass);
372 resources_set_class_template (
373 klass, "fader_buttons.ui");
374
375 #define BIND_CHILD(x) \
376 gtk_widget_class_bind_template_child ( \
377 klass, FaderButtonsWidget, x)
378
379 BIND_CHILD (mono_compat);
380 BIND_CHILD (solo);
381 BIND_CHILD (mute);
382 BIND_CHILD (listen);
383 BIND_CHILD (record);
384 BIND_CHILD (e);
385
386 #undef BIND_CHILD
387
388 GObjectClass * oklass =
389 G_OBJECT_CLASS (klass);
390 oklass->finalize =
391 (GObjectFinalizeFunc)
392 fader_buttons_finalize;
393 }
394