merge from thirdparty rubberband 1.3 @ 4901
[ardour2.git] / libs / ardour / session_events.cc
blob20e7309c02c04002841525b303487fd8af15f5b6
1 /*
2 Copyright (C) 1999-2004 Paul Davis
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.
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.
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.
20 #include <cmath>
21 #include <unistd.h>
23 #include <ardour/timestamps.h>
25 #include <pbd/error.h>
26 #include <glibmm/thread.h>
28 #include <ardour/ardour.h>
29 #include <ardour/session.h>
30 #include <ardour/audio_diskstream.h>
32 #include "i18n.h"
34 using namespace ARDOUR;
35 using namespace PBD;
37 MultiAllocSingleReleasePool Session::Event::pool ("event", sizeof (Session::Event), 512);
39 static const char* event_names[] = {
40 "SetTransportSpeed",
41 "SetDiskstreamSpeed",
42 "Locate",
43 "LocateRoll",
44 "LocateRollLocate",
45 "SetLoop",
46 "PunchIn",
47 "PunchOut",
48 "RangeStop",
49 "RangeLocate",
50 "Overwrite",
51 "SetSlaveSource",
52 "Audition",
53 "InputConfigurationChange",
54 "SetAudioRange",
55 "SetMusicRange",
56 "SetPlayRange",
57 "StopOnce",
58 "AutoLoop"
61 void
62 Session::add_event (nframes_t frame, Event::Type type, nframes_t target_frame)
64 Event* ev = new Event (type, Event::Add, frame, target_frame, 0);
65 queue_event (ev);
68 void
69 Session::remove_event (nframes_t frame, Event::Type type)
71 Event* ev = new Event (type, Event::Remove, frame, 0, 0);
72 queue_event (ev);
75 void
76 Session::replace_event (Event::Type type, nframes_t frame, nframes_t target)
78 Event* ev = new Event (type, Event::Replace, frame, target, 0);
79 queue_event (ev);
82 void
83 Session::clear_events (Event::Type type)
85 Event* ev = new Event (type, Event::Clear, 0, 0, 0);
86 queue_event (ev);
90 void
91 Session::dump_events () const
93 cerr << "EVENT DUMP" << endl;
94 for (Events::const_iterator i = events.begin(); i != events.end(); ++i) {
95 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
97 cerr << "Next event: ";
99 if ((Events::const_iterator) next_event == events.end()) {
100 cerr << "none" << endl;
101 } else {
102 cerr << "at " << (*next_event)->action_frame << ' '
103 << (*next_event)->type << " target = "
104 << (*next_event)->target_frame << endl;
106 cerr << "Immediate events pending:\n";
107 for (Events::const_iterator i = immediate_events.begin(); i != immediate_events.end(); ++i) {
108 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
110 cerr << "END EVENT_DUMP" << endl;
113 void
114 Session::queue_event (Event* ev)
116 if (_state_of_the_state & Loading) {
117 merge_event (ev);
118 } else {
119 pending_events.write (&ev, 1);
123 void
124 Session::merge_event (Event* ev)
126 switch (ev->action) {
127 case Event::Remove:
128 _remove_event (ev);
129 delete ev;
130 return;
132 case Event::Replace:
133 _replace_event (ev);
134 return;
136 case Event::Clear:
137 _clear_event_type (ev->type);
138 delete ev;
139 return;
141 case Event::Add:
142 break;
145 /* try to handle immediate events right here */
147 if (ev->action_frame == 0) {
148 process_event (ev);
149 return;
152 switch (ev->type) {
153 case Event::AutoLoop:
154 case Event::StopOnce:
155 _clear_event_type (ev->type);
156 break;
158 default:
159 for (Events::iterator i = events.begin(); i != events.end(); ++i) {
160 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
161 error << string_compose(_("Session: cannot have two events of type %1 at the same frame (%2)."),
162 event_names[ev->type], ev->action_frame) << endmsg;
163 return;
168 events.insert (events.begin(), ev);
169 events.sort (Event::compare);
170 next_event = events.begin();
171 set_next_event ();
174 bool
175 Session::_replace_event (Event* ev)
177 // returns true when we deleted the passed in event
178 bool ret = false;
179 Events::iterator i;
181 /* private, used only for events that can only exist once in the queue */
183 for (i = events.begin(); i != events.end(); ++i) {
184 if ((*i)->type == ev->type) {
185 (*i)->action_frame = ev->action_frame;
186 (*i)->target_frame = ev->target_frame;
187 if ((*i) == ev) {
188 ret = true;
190 delete ev;
191 break;
195 if (i == events.end()) {
196 events.insert (events.begin(), ev);
199 events.sort (Event::compare);
200 next_event = events.end();
201 set_next_event ();
203 return ret;
206 bool
207 Session::_remove_event (Session::Event* ev)
209 // returns true when we deleted the passed in event
210 bool ret = false;
211 Events::iterator i;
213 for (i = events.begin(); i != events.end(); ++i) {
214 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
215 if ((*i) == ev) {
216 ret = true;
219 delete *i;
220 if (i == next_event) {
221 ++next_event;
223 events.erase (i);
224 break;
228 if (i != events.end()) {
229 set_next_event ();
232 return ret;
235 void
236 Session::_clear_event_type (Event::Type type)
238 Events::iterator i, tmp;
240 for (i = events.begin(); i != events.end(); ) {
242 tmp = i;
243 ++tmp;
245 if ((*i)->type == type) {
246 delete *i;
247 if (i == next_event) {
248 ++next_event;
250 events.erase (i);
253 i = tmp;
256 for (i = immediate_events.begin(); i != immediate_events.end(); ) {
258 tmp = i;
259 ++tmp;
261 if ((*i)->type == type) {
262 delete *i;
263 immediate_events.erase (i);
266 i = tmp;
269 set_next_event ();
272 void
273 Session::set_next_event ()
275 if (events.empty()) {
276 next_event = events.end();
277 return;
280 if (next_event == events.end()) {
281 next_event = events.begin();
284 if ((*next_event)->action_frame > _transport_frame) {
285 next_event = events.begin();
288 for (; next_event != events.end(); ++next_event) {
289 if ((*next_event)->action_frame >= _transport_frame) {
290 break;
295 void
296 Session::process_event (Event* ev)
298 bool remove = true;
299 bool del = true;
301 /* if we're in the middle of a state change (i.e. waiting
302 for the butler thread to complete the non-realtime
303 part of the change), we'll just have to queue this
304 event for a time when the change is complete.
307 if (non_realtime_work_pending()) {
309 /* except locates, which we have the capability to handle */
311 if (ev->type != Event::Locate) {
312 immediate_events.insert (immediate_events.end(), ev);
313 _remove_event (ev);
314 return;
318 switch (ev->type) {
319 case Event::SetLoop:
320 set_play_loop (ev->yes_or_no);
321 break;
323 case Event::AutoLoop:
324 if (play_loop) {
325 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
327 remove = false;
328 del = false;
329 break;
331 case Event::Locate:
332 if (ev->yes_or_no) {
333 // cerr << "forced locate to " << ev->target_frame << endl;
334 locate (ev->target_frame, false, true, false);
335 } else {
336 // cerr << "soft locate to " << ev->target_frame << endl;
337 start_locate (ev->target_frame, false, true, false);
339 break;
341 case Event::LocateRoll:
342 if (ev->yes_or_no) {
343 // cerr << "forced locate to+roll " << ev->target_frame << endl;
344 locate (ev->target_frame, true, true, false);
345 } else {
346 // cerr << "soft locate to+roll " << ev->target_frame << endl;
347 start_locate (ev->target_frame, true, true, false);
349 break;
351 case Event::LocateRollLocate:
352 // locate is handled by ::request_roll_at_and_return()
353 _requested_return_frame = ev->target_frame;
354 cerr << "Set RRF " << ev->target_frame << endl;
355 request_locate (ev->target2_frame, true);
356 break;
359 case Event::SetTransportSpeed:
360 set_transport_speed (ev->speed, ev->yes_or_no);
361 break;
363 case Event::PunchIn:
364 // cerr << "PunchIN at " << transport_frame() << endl;
365 if (Config->get_punch_in() && record_status() == Enabled) {
366 enable_record ();
368 remove = false;
369 del = false;
370 break;
372 case Event::PunchOut:
373 // cerr << "PunchOUT at " << transport_frame() << endl;
374 if (Config->get_punch_out()) {
375 step_back_from_record ();
377 remove = false;
378 del = false;
379 break;
381 case Event::StopOnce:
382 if (!non_realtime_work_pending()) {
383 stop_transport (ev->yes_or_no);
384 _clear_event_type (Event::StopOnce);
386 remove = false;
387 del = false;
388 break;
390 case Event::RangeStop:
391 if (!non_realtime_work_pending()) {
392 stop_transport (ev->yes_or_no);
394 remove = false;
395 del = false;
396 break;
398 case Event::RangeLocate:
399 start_locate (ev->target_frame, true, true, false);
400 remove = false;
401 del = false;
402 break;
404 case Event::Overwrite:
405 overwrite_some_buffers (static_cast<AudioDiskstream*>(ev->ptr));
406 break;
408 case Event::SetDiskstreamSpeed:
409 set_diskstream_speed (static_cast<AudioDiskstream*> (ev->ptr), ev->speed);
410 break;
412 case Event::SetSlaveSource:
413 set_slave_source (ev->slave);
414 break;
416 case Event::Audition:
417 set_audition (ev->region);
418 // drop reference to region
419 ev->region.reset ();
420 break;
422 case Event::InputConfigurationChange:
423 post_transport_work = PostTransportWork (post_transport_work | PostTransportInputChange);
424 schedule_butler_transport_work ();
425 break;
427 case Event::SetAudioRange:
428 current_audio_range = ev->audio_range;
429 setup_auto_play ();
430 break;
432 case Event::SetPlayRange:
433 set_play_range (ev->yes_or_no);
434 break;
436 default:
437 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
438 /*NOTREACHED*/
439 break;
442 if (remove) {
443 del = del && !_remove_event (ev);
446 if (del) {
447 delete ev;