move Session::Event into SessionEvent class; add SessionEventManager (Session IS...
[ardour.git] / libs / ardour / session_events.cc
1 /*
2     Copyright (C) 1999-2004 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <cmath>
21 #include <unistd.h>
22
23 #include "ardour/timestamps.h"
24
25 #include "pbd/error.h"
26 #include "pbd/enumwriter.h"
27
28 #include "ardour/ardour.h"
29 #include "ardour/audio_diskstream.h"
30 #include "ardour/butler.h"
31 #include "ardour/debug.h"
32 #include "ardour/session_event.h"
33
34 #include "i18n.h"
35
36 using namespace std;
37 using namespace ARDOUR;
38 using namespace PBD;
39
40 MultiAllocSingleReleasePool SessionEvent::pool ("event", sizeof (SessionEvent), 512);
41
42 void
43 SessionEventManager::add_event (nframes64_t frame, SessionEvent::Type type, nframes64_t target_frame)
44 {
45         SessionEvent* ev = new SessionEvent (type, SessionEvent::Add, frame, target_frame, 0);
46         queue_event (ev);
47 }
48
49 void
50 SessionEventManager::remove_event (nframes64_t frame, SessionEvent::Type type)
51 {
52         SessionEvent* ev = new SessionEvent (type, SessionEvent::Remove, frame, 0, 0);
53         queue_event (ev);
54 }
55
56 void
57 SessionEventManager::replace_event (SessionEvent::Type type, nframes64_t frame, nframes64_t target)
58 {
59         SessionEvent* ev = new SessionEvent (type, SessionEvent::Replace, frame, target, 0);
60         queue_event (ev);
61 }
62
63 void
64 SessionEventManager::clear_events (SessionEvent::Type type)
65 {
66         SessionEvent* ev = new SessionEvent (type, SessionEvent::Clear, 0, 0, 0);
67         queue_event (ev);
68 }
69
70
71 void
72 SessionEventManager::dump_events () const
73 {
74         cerr << "EVENT DUMP" << endl;
75         for (Events::const_iterator i = events.begin(); i != events.end(); ++i) {
76                 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
77         }
78         cerr << "Next event: ";
79
80         if ((Events::const_iterator) next_event == events.end()) {
81                 cerr << "none" << endl;
82         } else {
83                 cerr << "at " << (*next_event)->action_frame << ' '
84                      << (*next_event)->type << " target = "
85                      << (*next_event)->target_frame << endl;
86         }
87         cerr << "Immediate events pending:\n";
88         for (Events::const_iterator i = immediate_events.begin(); i != immediate_events.end(); ++i) {
89                 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
90         }
91         cerr << "END EVENT_DUMP" << endl;
92 }
93
94 void
95 SessionEventManager::merge_event (SessionEvent* ev)
96 {
97         switch (ev->action) {
98         case SessionEvent::Remove:
99                 _remove_event (ev);
100                 delete ev;
101                 return;
102
103         case SessionEvent::Replace:
104                 _replace_event (ev);
105                 return;
106
107         case SessionEvent::Clear:
108                 _clear_event_type (ev->type);
109                 delete ev;
110                 return;
111
112         case SessionEvent::Add:
113                 break;
114         }
115
116         /* try to handle immediate events right here */
117
118         if (ev->action_frame == 0) {
119                 process_event (ev);
120                 return;
121         }
122
123         switch (ev->type) {
124         case SessionEvent::AutoLoop:
125         case SessionEvent::StopOnce:
126                 _clear_event_type (ev->type);
127                 break;
128
129         default:
130                 for (Events::iterator i = events.begin(); i != events.end(); ++i) {
131                         if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
132                           error << string_compose(_("Session: cannot have two events of type %1 at the same frame (%2)."),
133                                                   enum_2_string (ev->type), ev->action_frame) << endmsg;
134                                 return;
135                         }
136                 }
137         }
138
139         events.insert (events.begin(), ev);
140         events.sort (SessionEvent::compare);
141         next_event = events.begin();
142         set_next_event ();
143 }
144
145 /** @return true when @a ev is deleted. */
146 bool
147 SessionEventManager::_replace_event (SessionEvent* ev)
148 {
149         bool ret = false;
150         Events::iterator i;
151
152         /* private, used only for events that can only exist once in the queue */
153
154         for (i = events.begin(); i != events.end(); ++i) {
155                 if ((*i)->type == ev->type) {
156                         (*i)->action_frame = ev->action_frame;
157                         (*i)->target_frame = ev->target_frame;
158                         if ((*i) == ev) {
159                                 ret = true;
160                         }
161                         delete ev;
162                         break;
163                 }
164         }
165
166         if (i == events.end()) {
167                 events.insert (events.begin(), ev);
168         }
169
170         events.sort (SessionEvent::compare);
171         next_event = events.end();
172         set_next_event ();
173
174         return ret;
175 }
176
177 /** @return true when @a ev is deleted. */
178 bool
179 SessionEventManager::_remove_event (SessionEvent* ev)
180 {
181         bool ret = false;
182         Events::iterator i;
183
184         for (i = events.begin(); i != events.end(); ++i) {
185                 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
186                         if ((*i) == ev) {
187                                 ret = true;
188                         }
189
190                         delete *i;
191                         if (i == next_event) {
192                                 ++next_event;
193                         }
194                         events.erase (i);
195                         break;
196                 }
197         }
198
199         if (i != events.end()) {
200                 set_next_event ();
201         }
202
203         return ret;
204 }
205
206 void
207 SessionEventManager::_clear_event_type (SessionEvent::Type type)
208 {
209         Events::iterator i, tmp;
210
211         for (i = events.begin(); i != events.end(); ) {
212
213                 tmp = i;
214                 ++tmp;
215
216                 if ((*i)->type == type) {
217                         delete *i;
218                         if (i == next_event) {
219                                 ++next_event;
220                         }
221                         events.erase (i);
222                 }
223
224                 i = tmp;
225         }
226
227         for (i = immediate_events.begin(); i != immediate_events.end(); ) {
228
229                 tmp = i;
230                 ++tmp;
231
232                 if ((*i)->type == type) {
233                         delete *i;
234                         immediate_events.erase (i);
235                 }
236
237                 i = tmp;
238         }
239
240         set_next_event ();
241 }
242