1 /*
2 * Copyright (C) 2020 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/channel.h"
21 #include "audio/track.h"
22 #include "gui/backend/event.h"
23 #include "gui/backend/event_manager.h"
24 #include "gui/widgets/channel_slot.h"
25 #include "gui/widgets/plugin_strip_expander.h"
26 #include "project.h"
27 #include "settings/settings.h"
28 #include "utils/gtk.h"
29 #include "zrythm_app.h"
30
31 #include <gtk/gtk.h>
32 #include <glib/gi18n.h>
33
34 #define PLUGIN_STRIP_EXPANDER_WIDGET_TYPE \
35 (plugin_strip_expander_widget_get_type ())
G_DEFINE_TYPE(PluginStripExpanderWidget,plugin_strip_expander_widget,EXPANDER_BOX_WIDGET_TYPE)36 G_DEFINE_TYPE (
37 PluginStripExpanderWidget,
38 plugin_strip_expander_widget,
39 EXPANDER_BOX_WIDGET_TYPE)
40
41 /**
42 * Queues a redraw of the given slot.
43 */
44 void
45 plugin_strip_expander_widget_redraw_slot (
46 PluginStripExpanderWidget * self,
47 int slot)
48 {
49 switch (self->slot_type)
50 {
51 case PLUGIN_SLOT_INSERT:
52 case PLUGIN_SLOT_MIDI_FX:
53 gtk_widget_queue_draw (
54 GTK_WIDGET (self->slots[slot]));
55 break;
56 default:
57 break;
58 }
59 }
60
61 /**
62 * Unsets state flags and redraws the widget at the
63 * given slot.
64 *
65 * @param slot Slot, or -1 for all slots.
66 * @param set True to set, false to unset.
67 */
68 void
plugin_strip_expander_widget_set_state_flags(PluginStripExpanderWidget * self,int slot,GtkStateFlags flags,bool set)69 plugin_strip_expander_widget_set_state_flags (
70 PluginStripExpanderWidget * self,
71 int slot,
72 GtkStateFlags flags,
73 bool set)
74 {
75 switch (self->slot_type)
76 {
77 case PLUGIN_SLOT_INSERT:
78 case PLUGIN_SLOT_MIDI_FX:
79 if (slot == -1)
80 {
81 for (int i = 0; i < STRIP_SIZE; i++)
82 {
83 plugin_strip_expander_widget_set_state_flags (
84 self, i, flags, set);
85 }
86 }
87 else
88 {
89 channel_slot_widget_set_state_flags (
90 self->slots[slot], flags, set);
91 }
92 break;
93 default:
94 break;
95 }
96 }
97
98 /**
99 * Refreshes each field.
100 */
101 void
plugin_strip_expander_widget_refresh(PluginStripExpanderWidget * self)102 plugin_strip_expander_widget_refresh (
103 PluginStripExpanderWidget * self)
104 {
105 for (int i = 0; i < STRIP_SIZE; i++)
106 {
107 switch (self->slot_type)
108 {
109 case PLUGIN_SLOT_INSERT:
110 {
111 Channel * ch =
112 track_get_channel (self->track);
113 Plugin * pl = ch->inserts[i];
114 plugin_strip_expander_widget_set_state_flags (
115 self, i,
116 GTK_STATE_FLAG_SELECTED,
117 pl && plugin_is_selected (pl));
118 gtk_widget_queue_draw (
119 GTK_WIDGET (self->slots[i]));
120 }
121 break;
122 case PLUGIN_SLOT_MIDI_FX:
123 {
124 Channel * ch =
125 track_get_channel (self->track);
126 Plugin * pl = ch->midi_fx[i];
127 plugin_strip_expander_widget_set_state_flags (
128 self, i,
129 GTK_STATE_FLAG_SELECTED,
130 pl && plugin_is_selected (pl));
131 gtk_widget_queue_draw (
132 GTK_WIDGET (self->slots[i]));
133 }
134 break;
135 default:
136 break;
137 }
138 }
139 }
140
141 static void
on_reveal_changed(ExpanderBoxWidget * expander_box,bool revealed,PluginStripExpanderWidget * self)142 on_reveal_changed (
143 ExpanderBoxWidget * expander_box,
144 bool revealed,
145 PluginStripExpanderWidget * self)
146 {
147 if (self->position == PSE_POSITION_CHANNEL)
148 {
149 Channel * ch =
150 track_get_channel (self->track);
151 if (self->slot_type == PLUGIN_SLOT_INSERT)
152 {
153 g_settings_set_boolean (
154 S_UI_MIXER, "inserts-expanded",
155 revealed);
156 EVENTS_PUSH (
157 ET_MIXER_CHANNEL_INSERTS_EXPANDED_CHANGED,
158 ch);
159 }
160 else if (self->slot_type ==
161 PLUGIN_SLOT_MIDI_FX)
162 {
163 g_settings_set_boolean (
164 S_UI_MIXER, "midi-fx-expanded",
165 revealed);
166 EVENTS_PUSH (
167 ET_MIXER_CHANNEL_MIDI_FX_EXPANDED_CHANGED,
168 ch);
169 }
170 }
171 }
172
173 /**
174 * Sets up the PluginStripExpanderWidget.
175 */
176 void
plugin_strip_expander_widget_setup(PluginStripExpanderWidget * self,PluginSlotType slot_type,PluginStripExpanderPosition position,Track * track)177 plugin_strip_expander_widget_setup (
178 PluginStripExpanderWidget * self,
179 PluginSlotType slot_type,
180 PluginStripExpanderPosition position,
181 Track * track)
182 {
183 /* set name and icon */
184 char fullstr[200];
185 bool is_midi = false;
186 switch (slot_type)
187 {
188 case PLUGIN_SLOT_INSERT:
189 strcpy (fullstr, _("Inserts"));
190 is_midi =
191 track &&
192 track->out_signal_type == TYPE_EVENT;
193 break;
194 case PLUGIN_SLOT_MIDI_FX:
195 strcpy (fullstr, "MIDI FX");
196 is_midi = true;
197 break;
198 default:
199 g_return_if_reached ();
200 break;
201 }
202 expander_box_widget_set_label (
203 Z_EXPANDER_BOX_WIDGET (self),
204 fullstr);
205
206 if (is_midi)
207 {
208 expander_box_widget_set_icon_name (
209 Z_EXPANDER_BOX_WIDGET (self),
210 "midi-insert");
211 }
212 else
213 {
214 expander_box_widget_set_icon_name (
215 Z_EXPANDER_BOX_WIDGET (self),
216 "audio-insert");
217 }
218
219 if (track != self->track ||
220 slot_type != self->slot_type ||
221 position != self->position)
222 {
223 /* remove children */
224 z_gtk_container_destroy_all_children (
225 GTK_CONTAINER (self->box));
226
227 Channel * ch = track_get_channel (track);
228 g_return_if_fail (ch);
229 for (int i = 0; i < STRIP_SIZE; i++)
230 {
231 GtkBox * strip_box =
232 GTK_BOX (
233 gtk_box_new (
234 GTK_ORIENTATION_HORIZONTAL, 0));
235 self->strip_boxes[i] = strip_box;
236
237 switch (slot_type)
238 {
239 case PLUGIN_SLOT_INSERT:
240 case PLUGIN_SLOT_MIDI_FX:
241 {
242 ChannelSlotWidget * csw =
243 channel_slot_widget_new (
244 i, track, slot_type,
245 position ==
246 PSE_POSITION_CHANNEL);
247 self->slots[i] = csw;
248 gtk_box_pack_start (
249 strip_box, GTK_WIDGET (csw), 1, 1, 0);
250 }
251 break;
252 default:
253 g_warn_if_reached ();
254 break;
255 }
256
257 gtk_box_pack_start (
258 self->box,
259 GTK_WIDGET (strip_box), 0, 1, 0);
260 gtk_widget_show_all (
261 GTK_WIDGET (strip_box));
262 }
263 }
264
265 self->track = track;
266 self->slot_type = slot_type;
267 self->position = position;
268
269 switch (position)
270 {
271 case PSE_POSITION_INSPECTOR:
272 gtk_widget_set_size_request (
273 GTK_WIDGET (self->scroll), -1, 124);
274 break;
275 case PSE_POSITION_CHANNEL:
276 gtk_widget_set_size_request (
277 GTK_WIDGET (self->scroll), -1, 68);
278 if (slot_type == PLUGIN_SLOT_INSERT ||
279 slot_type == PLUGIN_SLOT_MIDI_FX)
280 {
281 expander_box_widget_set_reveal_callback (
282 Z_EXPANDER_BOX_WIDGET (self),
283 (ExpanderBoxRevealFunc)
284 on_reveal_changed, self);
285 }
286 break;
287 }
288
289 plugin_strip_expander_widget_refresh (self);
290 }
291
292 static void
plugin_strip_expander_widget_class_init(PluginStripExpanderWidgetClass * klass)293 plugin_strip_expander_widget_class_init (
294 PluginStripExpanderWidgetClass * klass)
295 {
296 }
297
298 static void
plugin_strip_expander_widget_init(PluginStripExpanderWidget * self)299 plugin_strip_expander_widget_init (
300 PluginStripExpanderWidget * self)
301 {
302 self->scroll =
303 GTK_SCROLLED_WINDOW (
304 gtk_scrolled_window_new (
305 NULL, NULL));
306 gtk_widget_set_vexpand (
307 GTK_WIDGET (self->scroll), 1);
308 gtk_widget_set_visible (
309 GTK_WIDGET (self->scroll), 1);
310 gtk_scrolled_window_set_shadow_type (
311 self->scroll, GTK_SHADOW_ETCHED_IN);
312
313 self->viewport =
314 GTK_VIEWPORT (
315 gtk_viewport_new (NULL, NULL));
316 gtk_widget_set_visible (
317 GTK_WIDGET (self->viewport), 1);
318 gtk_container_add (
319 GTK_CONTAINER (self->scroll),
320 GTK_WIDGET (self->viewport));
321
322 self->box =
323 GTK_BOX (
324 gtk_box_new (GTK_ORIENTATION_VERTICAL, 0));
325 gtk_widget_set_visible (
326 GTK_WIDGET (self->box), 1);
327 gtk_container_add (
328 GTK_CONTAINER (self->viewport),
329 GTK_WIDGET (self->box));
330
331 expander_box_widget_add_content (
332 Z_EXPANDER_BOX_WIDGET (self),
333 GTK_WIDGET (self->scroll));
334 }
335