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