1 /*
2  * Copyright (C) 2019-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 #ifndef __UNDO_MIXER_SELECTIONS_ACTION_H__
21 #define __UNDO_MIXER_SELECTIONS_ACTION_H__
22 
23 #include "audio/automation_track.h"
24 #include "audio/port_connections_manager.h"
25 #include "actions/undoable_action.h"
26 #include "gui/backend/mixer_selections.h"
27 #include "utils/yaml.h"
28 
29 typedef struct Plugin Plugin;
30 typedef struct Track Track;
31 typedef struct MixerSelections MixerSelections;
32 
33 typedef enum MixerSelectionsActionType
34 {
35   /** Duplicate from existing plugins. */
36   MIXER_SELECTIONS_ACTION_COPY,
37   /** Create new from clipboard. */
38   MIXER_SELECTIONS_ACTION_PASTE,
39   /** Create new from PluginSetting. */
40   MIXER_SELECTIONS_ACTION_CREATE,
41   MIXER_SELECTIONS_ACTION_DELETE,
42   MIXER_SELECTIONS_ACTION_MOVE,
43 } MixerSelectionsActionType;
44 
45 static const cyaml_strval_t
46 mixer_selections_action_type_strings[] =
47 {
48   { "Copy", MIXER_SELECTIONS_ACTION_COPY },
49   { "Paste", MIXER_SELECTIONS_ACTION_PASTE },
50   { "Create", MIXER_SELECTIONS_ACTION_CREATE },
51   { "Delete", MIXER_SELECTIONS_ACTION_DELETE },
52   { "Move", MIXER_SELECTIONS_ACTION_MOVE },
53 };
54 
55 /**
56  * Restrict selections to a channel.
57  */
58 typedef struct MixerSelectionsAction
59 {
60   UndoableAction   parent_instance;
61 
62   MixerSelectionsActionType type;
63 
64   /** Type of starting slot to move plugins to. */
65   PluginSlotType   slot_type;
66 
67   /**
68    * Starting target slot.
69    *
70    * The rest of the slots will start from this so
71    * they can be calculated when doing/undoing.
72    */
73   int              to_slot;
74 
75   /** To track position. */
76   unsigned int     to_track_name_hash;
77 
78   /** Whether the plugins will be copied/moved into
79    * a new channel, if applicable. */
80   bool             new_channel;
81 
82   /** Number of plugins to create, when creating
83    * new plugins. */
84   int              num_plugins;
85 
86   /**
87    * PluginSetting to use when creating.
88    */
89   PluginSetting *  setting;
90 
91   /**
92    * Clone of mixer selections at start.
93    */
94   MixerSelections * ms_before;
95 
96   /**
97    * Deleted plugins (ie, plugins replaced during
98    * move/copy).
99    *
100    * Used during undo to bring them back.
101    */
102   MixerSelections * deleted_ms;
103 
104   /**
105    * Automation tracks associated with the deleted
106    * plugins.
107    *
108    * These are used when undoing so we can readd
109    * the automation events, if applicable.
110    */
111   AutomationTrack * deleted_ats[16000];
112   int               num_deleted_ats;
113 
114   /**
115    * Automation tracks associated with the plugins.
116    *
117    * These are used when undoing so we can readd
118    * the automation events, if applicable.
119    */
120   AutomationTrack * ats[16000];
121   int               num_ats;
122 
123   /** A clone of the port connections at the
124    * start of the action. */
125   PortConnectionsManager * connections_mgr_before;
126 
127   /** A clone of the port connections after
128    * applying the action. */
129   PortConnectionsManager * connections_mgr_after;
130 } MixerSelectionsAction;
131 
132 static const cyaml_schema_field_t
133   mixer_selections_action_fields_schema[] =
134 {
135   YAML_FIELD_MAPPING_EMBEDDED (
136     MixerSelectionsAction, parent_instance,
137     undoable_action_fields_schema),
138   YAML_FIELD_ENUM (
139     MixerSelectionsAction, type,
140     mixer_selections_action_type_strings),
141   YAML_FIELD_ENUM (
142     MixerSelectionsAction, slot_type,
143     plugin_slot_type_strings),
144   YAML_FIELD_INT (
145     MixerSelectionsAction, to_slot),
146   YAML_FIELD_UINT (
147     MixerSelectionsAction, to_track_name_hash),
148   YAML_FIELD_INT (
149     MixerSelectionsAction, new_channel),
150   YAML_FIELD_INT (
151     MixerSelectionsAction, num_plugins),
152   YAML_FIELD_MAPPING_PTR_OPTIONAL (
153     MixerSelectionsAction, setting,
154     plugin_setting_fields_schema),
155   YAML_FIELD_MAPPING_PTR_OPTIONAL (
156     MixerSelectionsAction, ms_before,
157     mixer_selections_fields_schema),
158   YAML_FIELD_MAPPING_PTR_OPTIONAL (
159     MixerSelectionsAction, deleted_ms,
160     mixer_selections_fields_schema),
161   YAML_FIELD_FIXED_SIZE_PTR_ARRAY_VAR_COUNT (
162     MixerSelectionsAction, ats,
163     automation_track_schema),
164   YAML_FIELD_FIXED_SIZE_PTR_ARRAY_VAR_COUNT (
165     MixerSelectionsAction, deleted_ats,
166     automation_track_schema),
167   YAML_FIELD_MAPPING_PTR_OPTIONAL (
168     MixerSelectionsAction,
169     connections_mgr_before,
170     port_connections_manager_fields_schema),
171   YAML_FIELD_MAPPING_PTR_OPTIONAL (
172     MixerSelectionsAction,
173     connections_mgr_after,
174     port_connections_manager_fields_schema),
175 
176   CYAML_FIELD_END
177 };
178 
179 static const cyaml_schema_value_t
180   mixer_selections_action_schema =
181 {
182   YAML_VALUE_PTR (
183     MixerSelectionsAction,
184     mixer_selections_action_fields_schema),
185 };
186 
187 void
188 mixer_selections_action_init_loaded (
189   MixerSelectionsAction * self);
190 
191 /**
192  * Create a new action.
193  *
194  * @param ms The mixer selections before the action
195  *   is performed.
196  * @param slot_type Target slot type.
197  * @param to_track_name_hash Target track name hash,
198  *   or 0 for new channel.
199  * @param to_slot Target slot.
200  * @param setting The plugin setting, if creating
201  *   plugins.
202  * @param num_plugins The number of plugins to create,
203  *   if creating plugins.
204  */
205 WARN_UNUSED_RESULT
206 UndoableAction *
207 mixer_selections_action_new (
208   MixerSelections *         ms,
209   const PortConnectionsManager * connections_mgr,
210   MixerSelectionsActionType type,
211   PluginSlotType            slot_type,
212   unsigned int              to_track_name_hash,
213   int                       to_slot,
214   PluginSetting *           setting,
215   int                       num_plugins,
216   GError **                 error);
217 
218 #define mixer_selections_action_new_create( \
219   slot_type,to_tr,to_slot,setting,num_plugins, \
220   error) \
221   mixer_selections_action_new ( \
222     NULL, NULL, MIXER_SELECTIONS_ACTION_CREATE, \
223     slot_type, to_tr, to_slot, setting, \
224     num_plugins, error)
225 
226 #define mixer_selections_action_new_copy( \
227   ms,port_connections_mgr,slot_type, \
228   to_tr,to_slot,error) \
229   mixer_selections_action_new ( \
230     ms, port_connections_mgr, \
231     MIXER_SELECTIONS_ACTION_COPY, slot_type, \
232     to_tr, to_slot, NULL, 0, error)
233 
234 #define mixer_selections_action_new_paste( \
235   ms,port_connections_mgr,slot_type, \
236   to_tr,to_slot,error) \
237   mixer_selections_action_new ( \
238     ms, port_connections_mgr, \
239     MIXER_SELECTIONS_ACTION_PASTE, slot_type, \
240     to_tr, to_slot, NULL, 0, error)
241 
242 #define mixer_selections_action_new_move( \
243   ms,port_connections_mgr,slot_type, \
244   to_tr,to_slot,error) \
245   mixer_selections_action_new ( \
246     ms, port_connections_mgr, \
247     MIXER_SELECTIONS_ACTION_MOVE, slot_type, \
248     to_tr, to_slot, NULL, 0, error)
249 
250 #define mixer_selections_action_new_delete( \
251   ms,port_connections_mgr,error) \
252   mixer_selections_action_new ( \
253     ms, port_connections_mgr, \
254     MIXER_SELECTIONS_ACTION_DELETE, 0, \
255     0, 0, NULL, 0, error)
256 
257 NONNULL
258 MixerSelectionsAction *
259 mixer_selections_action_clone (
260   const MixerSelectionsAction * src);
261 
262 bool
263 mixer_selections_action_perform (
264   MixerSelections *         ms,
265   const PortConnectionsManager * connections_mgr,
266   MixerSelectionsActionType type,
267   PluginSlotType            slot_type,
268   unsigned int              to_track_name_hash,
269   int                       to_slot,
270   PluginSetting *           setting,
271   int                       num_plugins,
272   GError **                 error);
273 
274 #define mixer_selections_action_perform_create( \
275   slot_type,to_tr,to_slot,setting,num_plugins, \
276   error) \
277   mixer_selections_action_perform ( \
278     NULL, NULL, MIXER_SELECTIONS_ACTION_CREATE, \
279     slot_type, to_tr, to_slot, setting, \
280     num_plugins, error)
281 
282 #define mixer_selections_action_perform_copy( \
283   ms,port_connections_mgr,slot_type, \
284   to_tr,to_slot,error) \
285   mixer_selections_action_perform ( \
286     ms, port_connections_mgr, \
287     MIXER_SELECTIONS_ACTION_COPY, slot_type, \
288     to_tr, to_slot, NULL, 0, error)
289 
290 #define mixer_selections_action_perform_paste( \
291   ms,port_connections_mgr,slot_type, \
292   to_tr,to_slot,error) \
293   mixer_selections_action_perform ( \
294     ms, port_connections_mgr, \
295     MIXER_SELECTIONS_ACTION_PASTE, slot_type, \
296     to_tr, to_slot, NULL, 0, error)
297 
298 #define mixer_selections_action_perform_move( \
299   ms,port_connections_mgr,slot_type, \
300   to_tr,to_slot,error) \
301   mixer_selections_action_perform ( \
302     ms, port_connections_mgr, \
303     MIXER_SELECTIONS_ACTION_MOVE, slot_type, \
304     to_tr, to_slot, NULL, 0, error)
305 
306 #define mixer_selections_action_perform_delete( \
307   ms,port_connections_mgr,error) \
308   mixer_selections_action_perform ( \
309     ms, port_connections_mgr, \
310     MIXER_SELECTIONS_ACTION_DELETE, 0, \
311     0, 0, NULL, 0, error)
312 
313 int
314 mixer_selections_action_do (
315   MixerSelectionsAction * self,
316   GError **               error);
317 
318 int
319 mixer_selections_action_undo (
320   MixerSelectionsAction * self,
321   GError **               error);
322 
323 char *
324 mixer_selections_action_stringize (
325   MixerSelectionsAction * self);
326 
327 void
328 mixer_selections_action_free (
329   MixerSelectionsAction * self);
330 
331 #endif
332