1 /*
2  * Copyright (C) 2018-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 /**
21  * \file
22  *
23  * Undoable actions.
24  */
25 
26 #ifndef __UNDO_UNDOABLE_ACTION_H__
27 #define __UNDO_UNDOABLE_ACTION_H__
28 
29 #include <stdbool.h>
30 
31 #include "utils/yaml.h"
32 
33 typedef struct AudioClip AudioClip;
34 typedef struct PortConnectionsManager
35   PortConnectionsManager;
36 
37 /**
38  * @addtogroup actions
39  *
40  * @{
41  */
42 
43 #define UNDOABLE_ACTION_SCHEMA_VERSION 1
44 
45 /**
46  * Type of UndoableAction.
47  */
48 typedef enum UndoableActionType
49 {
50   /* ---- Track/Channel ---- */
51   UA_TRACKLIST_SELECTIONS,
52 
53   UA_CHANNEL_SEND,
54 
55   /* ---- end ---- */
56 
57   UA_MIXER_SELECTIONS,
58   UA_ARRANGER_SELECTIONS,
59 
60   /* ---- connections ---- */
61 
62   UA_MIDI_MAPPING,
63   UA_PORT_CONNECTION,
64   UA_PORT,
65 
66   /* ---- end ---- */
67 
68   /* ---- range ---- */
69 
70   UA_RANGE,
71 
72   /* ---- end ---- */
73 
74   UA_TRANSPORT,
75 
76 } UndoableActionType;
77 
78 static const cyaml_strval_t
79 undoable_action_type_strings[] =
80 {
81   { "Tracklist selections",
82     UA_TRACKLIST_SELECTIONS },
83   { "Channel send", UA_CHANNEL_SEND },
84   { "Mixer selections", UA_MIXER_SELECTIONS },
85   { "Arranger selections", UA_ARRANGER_SELECTIONS },
86   { "MIDI mapping", UA_MIDI_MAPPING },
87   { "Port connection", UA_PORT_CONNECTION },
88   { "Port", UA_PORT },
89   { "Range", UA_RANGE },
90   { "Transport", UA_TRANSPORT },
91 };
92 
93 /**
94  * Base struct to be inherited by implementing
95  * undoable actions.
96  */
97 typedef struct UndoableAction
98 {
99   int                schema_version;
100 
101   /** Undoable action type. */
102   UndoableActionType  type;
103 
104   /**
105    * Index in the stack.
106    *
107    * Used during deserialization.
108    */
109   int                 stack_idx;
110 
111   /**
112    * Number of actions to perform.
113    *
114    * This is used to group multiple actions into
115    * one logical action (eg, create a group track
116    * and route multiple tracks to it).
117    *
118    * To be set on the last action being performed.
119    */
120   int                 num_actions;
121 } UndoableAction;
122 
123 static const cyaml_schema_field_t
124   undoable_action_fields_schema[] =
125 {
126   YAML_FIELD_INT (UndoableAction, schema_version),
127   YAML_FIELD_ENUM (
128     UndoableAction, type,
129     undoable_action_type_strings),
130   YAML_FIELD_INT (
131     UndoableAction, stack_idx),
132   YAML_FIELD_INT (
133     UndoableAction, num_actions),
134 
135   CYAML_FIELD_END
136 };
137 
138 static const cyaml_schema_value_t
139   undoable_action_schema =
140 {
141   CYAML_VALUE_MAPPING (CYAML_FLAG_POINTER,
142     UndoableAction, undoable_action_fields_schema),
143 };
144 
145 NONNULL
146 void
147 undoable_action_init_loaded (
148   UndoableAction * self);
149 
150 /**
151  * Initializer to be used by implementing actions.
152  */
153 NONNULL
154 void
155 undoable_action_init (
156   UndoableAction *   self,
157   UndoableActionType type);
158 
159 /**
160  * Returns whether the action requires pausing
161  * the engine.
162  */
163 NONNULL
164 bool
165 undoable_action_needs_pause (
166   UndoableAction * self);
167 
168 /**
169  * Checks whether the action can contain an audio
170  * clip.
171  *
172  * No attempt is made to remove unnused files from
173  * the pool for actions that can't contain audio
174  * clips.
175  */
176 NONNULL
177 bool
178 undoable_action_can_contain_clip (
179   UndoableAction * self);
180 
181 
182 /**
183  * Checks whether the action actually contains or
184  * refers to the given audio clip.
185  */
186 NONNULL
187 bool
188 undoable_action_contains_clip (
189   UndoableAction * self,
190   AudioClip *      clip);
191 
192 /**
193  * Sets the number of actions for this action.
194  *
195  * This should be set on the last action to be
196  * performed.
197  */
198 NONNULL
199 void
200 undoable_action_set_num_actions (
201   UndoableAction * self,
202   int              num_actions);
203 
204 /**
205  * To be used by actions that save/load port
206  * connections.
207  *
208  * @param _do True if doing/performing, false if
209  *   undoing.
210  * @param before Pointer to the connections before.
211  * @param after Pointer to the connections after.
212  */
213 NONNULL_ARGS (1)
214 void
215 undoable_action_save_or_load_port_connections (
216   UndoableAction *          self,
217   bool                      _do,
218   PortConnectionsManager ** before,
219   PortConnectionsManager ** after);
220 
221 /**
222  * Performs the action.
223  *
224  * @note Only to be called by undo manager.
225  *
226  * @return Non-zero if errors occurred.
227  */
228 NONNULL_ARGS (1)
229 int
230 undoable_action_do (
231   UndoableAction * self,
232   GError **        error);
233 
234 /**
235  * Undoes the action.
236  *
237  * @return Non-zero if errors occurred.
238  */
239 NONNULL_ARGS (1)
240 int
241 undoable_action_undo (
242   UndoableAction * self,
243   GError **        error);
244 
245 void
246 undoable_action_free (
247   UndoableAction * self);
248 
249 /**
250  * Stringizes the action to be used in Undo/Redo
251  * buttons.
252  *
253  * The string MUST be free'd using g_free().
254  */
255 NONNULL
256 char *
257 undoable_action_to_string (
258   UndoableAction * ua);
259 
260 /**
261  * @}
262  */
263 
264 #endif
265