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 #ifndef __UNDO_CHANNEL_SEND_ACTION_H__
21 #define __UNDO_CHANNEL_SEND_ACTION_H__
22 
23 #include "actions/undoable_action.h"
24 #include "audio/channel_send.h"
25 #include "audio/port_connections_manager.h"
26 
27 /**
28  * @addtogroup actions
29  *
30  * @{
31  */
32 
33 typedef enum ChannelSendActionType
34 {
35   CHANNEL_SEND_ACTION_CONNECT_STEREO,
36   CHANNEL_SEND_ACTION_CONNECT_MIDI,
37   CHANNEL_SEND_ACTION_CONNECT_SIDECHAIN,
38   CHANNEL_SEND_ACTION_CHANGE_AMOUNT,
39   CHANNEL_SEND_ACTION_CHANGE_PORTS,
40   CHANNEL_SEND_ACTION_DISCONNECT,
41 } ChannelSendActionType;
42 
43 static const cyaml_strval_t
44   channel_send_action_type_strings[] =
45 {
46   { "Connect stereo",
47     CHANNEL_SEND_ACTION_CONNECT_STEREO },
48   { "Connect MIDI",
49     CHANNEL_SEND_ACTION_CONNECT_MIDI },
50   { "Connect sidechain",
51     CHANNEL_SEND_ACTION_CONNECT_SIDECHAIN },
52   { "Change amount",
53     CHANNEL_SEND_ACTION_CHANGE_AMOUNT },
54   { "Change ports",
55     CHANNEL_SEND_ACTION_CHANGE_PORTS },
56   { "Disconnect",
57     CHANNEL_SEND_ACTION_DISCONNECT },
58 };
59 
60 /**
61  * Action for channel send changes.
62  */
63 typedef struct ChannelSendAction
64 {
65   UndoableAction  parent_instance;
66 
67   ChannelSend *   send_before;
68 
69   float            amount;
70 
71   /** Target port identifiers. */
72   PortIdentifier * l_id;
73   PortIdentifier * r_id;
74   PortIdentifier * midi_id;
75 
76   /** A clone of the port connections at the
77    * start of the action. */
78   PortConnectionsManager * connections_mgr_before;
79 
80   /** A clone of the port connections after
81    * applying the action. */
82   PortConnectionsManager * connections_mgr_after;
83 
84   /** Action type. */
85   ChannelSendActionType type;
86 
87 } ChannelSendAction;
88 
89 static const cyaml_schema_field_t
90   channel_send_action_fields_schema[] =
91 {
92   YAML_FIELD_MAPPING_EMBEDDED (
93     ChannelSendAction, parent_instance,
94     undoable_action_fields_schema),
95   YAML_FIELD_ENUM (
96     ChannelSendAction, type,
97     channel_send_action_type_strings),
98   YAML_FIELD_MAPPING_PTR (
99     ChannelSendAction, send_before,
100     channel_send_fields_schema),
101   YAML_FIELD_MAPPING_PTR_OPTIONAL (
102     ChannelSendAction,
103     connections_mgr_before,
104     port_connections_manager_fields_schema),
105   YAML_FIELD_MAPPING_PTR_OPTIONAL (
106     ChannelSendAction,
107     connections_mgr_after,
108     port_connections_manager_fields_schema),
109 
110   CYAML_FIELD_END
111 };
112 
113 static const cyaml_schema_value_t
114   channel_send_action_schema =
115 {
116   CYAML_VALUE_MAPPING (
117     CYAML_FLAG_POINTER, ChannelSendAction,
118     channel_send_action_fields_schema),
119 };
120 
121 void
122 channel_send_action_init_loaded (
123   ChannelSendAction * self);
124 
125 /**
126  * Creates a new action.
127  *
128  * @param port MIDI port, if connecting MIDI.
129  * @param stereo Stereo ports, if connecting audio.
130  * @param port_connections_mgr Port connections
131  *   manager at the start of the action, if needed.
132  */
133 WARN_UNUSED_RESULT
134 UndoableAction *
135 channel_send_action_new (
136   ChannelSend *         send,
137   ChannelSendActionType type,
138   Port *                port,
139   StereoPorts *         stereo,
140   float                 amount,
141   const PortConnectionsManager * port_connections_mgr,
142   GError **             error);
143 
144 #define channel_send_action_new_disconnect( \
145   send,error) \
146   channel_send_action_new ( \
147     send, CHANNEL_SEND_ACTION_DISCONNECT, NULL, NULL, \
148     0.f, PORT_CONNECTIONS_MGR, error)
149 
150 #define channel_send_action_new_connect_midi( \
151   send,midi,error) \
152   channel_send_action_new ( \
153     send, CHANNEL_SEND_ACTION_CONNECT_MIDI, midi, \
154     NULL, 0.f, PORT_CONNECTIONS_MGR, error)
155 
156 #define channel_send_action_new_connect_audio( \
157   send,stereo,error) \
158   channel_send_action_new ( \
159     send, CHANNEL_SEND_ACTION_CONNECT_STEREO, NULL, \
160     stereo, 0.f, PORT_CONNECTIONS_MGR, error)
161 
162 #define channel_send_action_new_connect_sidechain( \
163   send,stereo,error) \
164   channel_send_action_new ( \
165     send, CHANNEL_SEND_ACTION_CONNECT_SIDECHAIN, \
166     NULL, stereo, 0.f, PORT_CONNECTIONS_MGR, error)
167 
168 #define channel_send_action_new_change_amount( \
169   send,amt,error) \
170   channel_send_action_new ( \
171     send, CHANNEL_SEND_ACTION_CHANGE_AMOUNT, NULL, \
172     NULL, amt, NULL, error)
173 
174 NONNULL
175 ChannelSendAction *
176 channel_send_action_clone (
177   const ChannelSendAction * src);
178 
179 /**
180  * Wrapper to create action and perform it.
181  *
182  * @param port_connections_mgr Port connections
183  *   manager at the start of the action, if needed.
184  */
185 bool
186 channel_send_action_perform (
187   ChannelSend *         send,
188   ChannelSendActionType type,
189   Port *                port,
190   StereoPorts *         stereo,
191   float                 amount,
192   const PortConnectionsManager * port_connections_mgr,
193   GError **             error);
194 
195 #define channel_send_action_perform_disconnect( \
196   send,error) \
197   channel_send_action_perform ( \
198     send, CHANNEL_SEND_ACTION_DISCONNECT, NULL, NULL, \
199     0.f, PORT_CONNECTIONS_MGR, error)
200 
201 #define channel_send_action_perform_connect_midi( \
202   send,midi,error) \
203   channel_send_action_perform ( \
204     send, CHANNEL_SEND_ACTION_CONNECT_MIDI, midi, \
205     NULL, 0.f, PORT_CONNECTIONS_MGR, error)
206 
207 #define channel_send_action_perform_connect_audio( \
208   send,stereo,error) \
209   channel_send_action_perform ( \
210     send, CHANNEL_SEND_ACTION_CONNECT_STEREO, NULL, \
211     stereo, 0.f, PORT_CONNECTIONS_MGR, error)
212 
213 #define channel_send_action_perform_connect_sidechain( \
214   send,stereo,error) \
215   channel_send_action_perform ( \
216     send, CHANNEL_SEND_ACTION_CONNECT_SIDECHAIN, \
217     NULL, stereo, 0.f, PORT_CONNECTIONS_MGR, error)
218 
219 #define channel_send_action_perform_change_amount( \
220   send,amt,error) \
221   channel_send_action_perform ( \
222     send, CHANNEL_SEND_ACTION_CHANGE_AMOUNT, NULL, \
223     NULL, amt, NULL, error)
224 
225 int
226 channel_send_action_do (
227   ChannelSendAction * self,
228   GError **           error);
229 
230 int
231 channel_send_action_undo (
232   ChannelSendAction * self,
233   GError **           error);
234 
235 char *
236 channel_send_action_stringize (
237   ChannelSendAction * self);
238 
239 void
240 channel_send_action_free (
241   ChannelSendAction * self);
242 
243 /**
244  * @}
245  */
246 
247 #endif
248