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 /**
21  * \file
22  *
23  * Undo manager.
24  */
25 
26 #ifndef __UNDO_UNDO_MANAGER_H__
27 #define __UNDO_UNDO_MANAGER_H__
28 
29 #include "actions/undo_stack.h"
30 
31 #include "zix/sem.h"
32 
33 typedef struct AudioClip AudioClip;
34 
35 /**
36  * @addtogroup actions
37  *
38  * @{
39  */
40 
41 #define UNDO_MANAGER_SCHEMA_VERSION 1
42 
43 #define UNDO_MANAGER (PROJECT->undo_manager)
44 
45 /**
46  * Undo manager.
47  */
48 typedef struct UndoManager
49 {
50   int           schema_version;
51 
52   UndoStack *   undo_stack;
53   UndoStack *   redo_stack;
54 
55   /** Semaphore for performing actions. */
56   ZixSem        action_sem;
57 } UndoManager;
58 
59 static const cyaml_schema_field_t
60   undo_manager_fields_schema[] =
61 {
62   YAML_FIELD_INT (UndoManager, schema_version),
63   YAML_FIELD_MAPPING_PTR (
64     UndoManager, undo_stack,
65     undo_stack_fields_schema),
66   YAML_FIELD_MAPPING_PTR (
67     UndoManager, redo_stack,
68     undo_stack_fields_schema),
69 
70   CYAML_FIELD_END
71 };
72 
73 static const cyaml_schema_value_t
74   undo_manager_schema =
75 {
76   YAML_VALUE_PTR (
77     UndoManager, undo_manager_fields_schema),
78 };
79 
80 /**
81  * Inits the undo manager by populating the
82  * undo/redo stacks.
83  */
84 NONNULL
85 void
86 undo_manager_init_loaded (
87   UndoManager * self);
88 
89 /**
90  * Inits the undo manager by creating the undo/redo
91  * stacks.
92  */
93 WARN_UNUSED_RESULT
94 UndoManager *
95 undo_manager_new (void);
96 
97 /**
98  * Undo last action.
99  */
100 NONNULL_ARGS (1)
101 int
102 undo_manager_undo (
103   UndoManager * self,
104   GError **     error);
105 
106 /**
107  * Redo last undone action.
108  */
109 NONNULL_ARGS (1)
110 int
111 undo_manager_redo (
112   UndoManager * self,
113   GError **     error);
114 
115 /**
116  * Performs the action and pushes it to the undo
117  * stack.
118  *
119  * @return Non-zero if error.
120  */
121 NONNULL_ARGS (1,2)
122 int
123 undo_manager_perform (
124   UndoManager *    self,
125   UndoableAction * action,
126   GError **        error);
127 
128 /**
129  * Second and last argument given must be a
130  * GError **.
131  */
132 #define UNDO_MANAGER_PERFORM_AND_PROPAGATE_ERR( \
133   action,err,...) \
134   { \
135   g_return_val_if_fail ( \
136     router_is_processing_thread (ROUTER) \
137     == false, false); \
138   UndoableAction * ua = \
139     action (__VA_ARGS__); \
140   if (ua) \
141     { \
142       int ret = \
143         undo_manager_perform ( \
144           UNDO_MANAGER, ua, err); \
145       if (ret == 0) \
146         return true; \
147     } \
148   return false; \
149   }
150 
151 /**
152  * Returns whether the given clip is used by any
153  * stack.
154  */
155 NONNULL
156 bool
157 undo_manager_contains_clip (
158   UndoManager * self,
159   AudioClip *   clip);
160 
161 /**
162  * Returns the last performed action, or NULL if
163  * the stack is empty.
164  */
165 NONNULL
166 UndoableAction *
167 undo_manager_get_last_action (
168   UndoManager * self);
169 
170 /**
171  * Clears the undo and redo stacks.
172  */
173 NONNULL
174 void
175 undo_manager_clear_stacks (
176   UndoManager * self,
177   bool          free);
178 
179 NONNULL
180 UndoManager *
181 undo_manager_clone (
182   const UndoManager * src);
183 
184 NONNULL
185 void
186 undo_manager_free (
187   UndoManager * self);
188 
189 /**
190  * @}
191  */
192 
193 #endif
194