monster commit: transport mgmt changes from 2.X (omnibus edition); make slave use...
[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 #include <glibmm/thread.h>
28
29 #include "ardour/ardour.h"
30 #include "ardour/audio_diskstream.h"
31 #include "ardour/butler.h"
32 #include "ardour/session.h"
33
34 #include "i18n.h"
35
36 using namespace std;
37 using namespace ARDOUR;
38 using namespace PBD;
39
40 MultiAllocSingleReleasePool Session::Event::pool ("event", sizeof (Session::Event), 512);
41
42 void
43 Session::add_event (nframes_t frame, Event::Type type, nframes_t target_frame)
44 {
45         Event* ev = new Event (type, Event::Add, frame, target_frame, 0);
46         queue_event (ev);
47 }
48
49 void
50 Session::remove_event (nframes_t frame, Event::Type type)
51 {
52         Event* ev = new Event (type, Event::Remove, frame, 0, 0);
53         queue_event (ev);
54 }
55
56 void
57 Session::replace_event (Event::Type type, nframes_t frame, nframes_t target)
58 {
59         Event* ev = new Event (type, Event::Replace, frame, target, 0);
60         queue_event (ev);
61 }
62
63 void
64 Session::clear_events (Event::Type type)
65 {
66         Event* ev = new Event (type, Event::Clear, 0, 0, 0);
67         queue_event (ev);
68 }
69
70
71 void
72 Session::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 Session::queue_event (Event* ev)
96 {
97         if (_state_of_the_state & Loading) {
98                 merge_event (ev);
99         } else {
100                 pending_events.write (&ev, 1);
101         }
102 }
103
104 void
105 Session::merge_event (Event* ev)
106 {
107         switch (ev->action) {
108         case Event::Remove:
109                 _remove_event (ev);
110                 delete ev;
111                 return;
112
113         case Event::Replace:
114                 _replace_event (ev);
115                 return;
116
117         case Event::Clear:
118                 _clear_event_type (ev->type);
119                 delete ev;
120                 return;
121
122         case Event::Add:
123                 break;
124         }
125
126         /* try to handle immediate events right here */
127
128         if (ev->action_frame == 0) {
129                 process_event (ev);
130                 return;
131         }
132
133         switch (ev->type) {
134         case Event::AutoLoop:
135         case Event::StopOnce:
136                 _clear_event_type (ev->type);
137                 break;
138
139         default:
140                 for (Events::iterator i = events.begin(); i != events.end(); ++i) {
141                         if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
142                           error << string_compose(_("Session: cannot have two events of type %1 at the same frame (%2)."),
143                                                   enum_2_string (ev->type), ev->action_frame) << endmsg;
144                                 return;
145                         }
146                 }
147         }
148
149         events.insert (events.begin(), ev);
150         events.sort (Event::compare);
151         next_event = events.begin();
152         set_next_event ();
153 }
154
155 /** @return true when @a ev is deleted. */
156 bool
157 Session::_replace_event (Event* ev)
158 {
159         bool ret = false;
160         Events::iterator i;
161
162         /* private, used only for events that can only exist once in the queue */
163
164         for (i = events.begin(); i != events.end(); ++i) {
165                 if ((*i)->type == ev->type) {
166                         (*i)->action_frame = ev->action_frame;
167                         (*i)->target_frame = ev->target_frame;
168                         if ((*i) == ev) {
169                                 ret = true;
170                         }
171                         delete ev;
172                         break;
173                 }
174         }
175
176         if (i == events.end()) {
177                 events.insert (events.begin(), ev);
178         }
179
180         events.sort (Event::compare);
181         next_event = events.end();
182         set_next_event ();
183
184         return ret;
185 }
186
187 /** @return true when @a ev is deleted. */
188 bool
189 Session::_remove_event (Session::Event* ev)
190 {
191         bool ret = false;
192         Events::iterator i;
193
194         for (i = events.begin(); i != events.end(); ++i) {
195                 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
196                         if ((*i) == ev) {
197                                 ret = true;
198                         }
199
200                         delete *i;
201                         if (i == next_event) {
202                                 ++next_event;
203                         }
204                         events.erase (i);
205                         break;
206                 }
207         }
208
209         if (i != events.end()) {
210                 set_next_event ();
211         }
212
213         return ret;
214 }
215
216 void
217 Session::_clear_event_type (Event::Type type)
218 {
219         Events::iterator i, tmp;
220
221         for (i = events.begin(); i != events.end(); ) {
222
223                 tmp = i;
224                 ++tmp;
225
226                 if ((*i)->type == type) {
227                         delete *i;
228                         if (i == next_event) {
229                                 ++next_event;
230                         }
231                         events.erase (i);
232                 }
233
234                 i = tmp;
235         }
236
237         for (i = immediate_events.begin(); i != immediate_events.end(); ) {
238
239                 tmp = i;
240                 ++tmp;
241
242                 if ((*i)->type == type) {
243                         delete *i;
244                         immediate_events.erase (i);
245                 }
246
247                 i = tmp;
248         }
249
250         set_next_event ();
251 }
252
253 void
254 Session::set_next_event ()
255 {
256         if (events.empty()) {
257                 next_event = events.end();
258                 return;
259         }
260
261         if (next_event == events.end()) {
262                 next_event = events.begin();
263         }
264
265         if ((*next_event)->action_frame > _transport_frame) {
266                 next_event = events.begin();
267         }
268
269         for (; next_event != events.end(); ++next_event) {
270                 if ((*next_event)->action_frame >= _transport_frame) {
271                         break;
272                 }
273         }
274 }
275
276 void
277 Session::process_event (Event* ev)
278 {
279         bool remove = true;
280         bool del = true;
281
282         /* if we're in the middle of a state change (i.e. waiting
283            for the butler thread to complete the non-realtime
284            part of the change), we'll just have to queue this
285            event for a time when the change is complete.
286         */
287
288         if (non_realtime_work_pending()) {
289
290                 /* except locates, which we have the capability to handle */
291
292                 if (ev->type != Event::Locate) {
293                         immediate_events.insert (immediate_events.end(), ev);
294                         _remove_event (ev);
295                         return;
296                 }
297         }
298
299         //printf("Processing event: %s\n", event_names[ev->type]);
300
301         switch (ev->type) {
302         case Event::SetLoop:
303                 set_play_loop (ev->yes_or_no);
304                 break;
305
306         case Event::AutoLoop:
307                 if (play_loop) {
308                         start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
309                 }
310                 remove = false;
311                 del = false;
312                 break;
313
314         case Event::Locate:
315                 if (ev->yes_or_no) {
316                         // cerr << "forced locate to " << ev->target_frame << endl;
317                         locate (ev->target_frame, false, true, false);
318                 } else {
319                         // cerr << "soft locate to " << ev->target_frame << endl;
320                         start_locate (ev->target_frame, false, true, false);
321                 }
322                 _send_timecode_update = true;
323                 break;
324
325         case Event::LocateRoll:
326                 if (ev->yes_or_no) {
327                         // cerr << "forced locate to+roll " << ev->target_frame << endl;
328                         locate (ev->target_frame, true, true, false);
329                 } else {
330                         // cerr << "soft locate to+roll " << ev->target_frame << endl;
331                         start_locate (ev->target_frame, true, true, false);
332                 }
333                 _send_timecode_update = true;
334                 break;
335
336         case Event::LocateRollLocate:
337                 // locate is handled by ::request_roll_at_and_return()
338                 _requested_return_frame = ev->target_frame;
339                 request_locate (ev->target2_frame, true);
340                 break;
341
342
343         case Event::SetTransportSpeed:
344                 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
345                 break;
346
347         case Event::PunchIn:
348                 // cerr << "PunchIN at " << transport_frame() << endl;
349                 if (config.get_punch_in() && record_status() == Enabled) {
350                         enable_record ();
351                 }
352                 remove = false;
353                 del = false;
354                 break;
355
356         case Event::PunchOut:
357                 // cerr << "PunchOUT at " << transport_frame() << endl;
358                 if (config.get_punch_out()) {
359                         step_back_from_record ();
360                 }
361                 remove = false;
362                 del = false;
363                 break;
364
365         case Event::StopOnce:
366                 if (!non_realtime_work_pending()) {
367                         stop_transport (ev->yes_or_no);
368                         _clear_event_type (Event::StopOnce);
369                 }
370                 remove = false;
371                 del = false;
372                 break;
373
374         case Event::RangeStop:
375                 if (!non_realtime_work_pending()) {
376                         stop_transport (ev->yes_or_no);
377                 }
378                 remove = false;
379                 del = false;
380                 break;
381
382         case Event::RangeLocate:
383                 start_locate (ev->target_frame, true, true, false);
384                 remove = false;
385                 del = false;
386                 break;
387
388         case Event::Overwrite:
389                 overwrite_some_buffers (static_cast<Diskstream*>(ev->ptr));
390                 break;
391
392         case Event::SetDiskstreamSpeed:
393                 set_diskstream_speed (static_cast<Diskstream*> (ev->ptr), ev->speed);
394                 break;
395
396         case Event::SetSlaveSource:
397                 set_slave_source (ev->slave);
398                 break;
399
400         case Event::Audition:
401                 set_audition (ev->region);
402                 // drop reference to region
403                 ev->region.reset ();
404                 break;
405
406         case Event::InputConfigurationChange:
407                 add_post_transport_work (PostTransportInputChange);
408                 _butler->schedule_transport_work ();
409                 break;
410
411         case Event::SetPlayAudioRange:
412                 set_play_range (ev->audio_range, (ev->speed == 1.0f));
413                 break;
414
415         default:
416           fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
417                 /*NOTREACHED*/
418                 break;
419         };
420
421         if (remove) {
422                 del = del && !_remove_event (ev);
423         }
424
425         if (del) {
426                 delete ev;
427         }
428 }