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.
23 #include "ardour/timestamps.h"
25 #include "pbd/error.h"
26 #include <glibmm/thread.h>
28 #include "ardour/ardour.h"
29 #include "ardour/audio_diskstream.h"
30 #include "ardour/butler.h"
31 #include "ardour/session.h"
36 using namespace ARDOUR;
39 MultiAllocSingleReleasePool Session::Event::pool ("event", sizeof (Session::Event), 512);
41 static const char* event_names[] = {
55 "InputConfigurationChange",
64 Session::add_event (nframes_t frame, Event::Type type, nframes_t target_frame)
66 Event* ev = new Event (type, Event::Add, frame, target_frame, 0);
71 Session::remove_event (nframes_t frame, Event::Type type)
73 Event* ev = new Event (type, Event::Remove, frame, 0, 0);
78 Session::replace_event (Event::Type type, nframes_t frame, nframes_t target)
80 Event* ev = new Event (type, Event::Replace, frame, target, 0);
85 Session::clear_events (Event::Type type)
87 Event* ev = new Event (type, Event::Clear, 0, 0, 0);
93 Session::dump_events () const
95 cerr << "EVENT DUMP" << endl;
96 for (Events::const_iterator i = events.begin(); i != events.end(); ++i) {
97 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
99 cerr << "Next event: ";
101 if ((Events::const_iterator) next_event == events.end()) {
102 cerr << "none" << endl;
104 cerr << "at " << (*next_event)->action_frame << ' '
105 << (*next_event)->type << " target = "
106 << (*next_event)->target_frame << endl;
108 cerr << "Immediate events pending:\n";
109 for (Events::const_iterator i = immediate_events.begin(); i != immediate_events.end(); ++i) {
110 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
112 cerr << "END EVENT_DUMP" << endl;
116 Session::queue_event (Event* ev)
118 if (_state_of_the_state & Loading) {
121 pending_events.write (&ev, 1);
126 Session::merge_event (Event* ev)
128 switch (ev->action) {
139 _clear_event_type (ev->type);
147 /* try to handle immediate events right here */
149 if (ev->action_frame == 0) {
155 case Event::AutoLoop:
156 case Event::StopOnce:
157 _clear_event_type (ev->type);
161 for (Events::iterator i = events.begin(); i != events.end(); ++i) {
162 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
163 error << string_compose(_("Session: cannot have two events of type %1 at the same frame (%2)."),
164 event_names[ev->type], ev->action_frame) << endmsg;
170 events.insert (events.begin(), ev);
171 events.sort (Event::compare);
172 next_event = events.begin();
176 /** @return true when @a ev is deleted. */
178 Session::_replace_event (Event* ev)
183 /* private, used only for events that can only exist once in the queue */
185 for (i = events.begin(); i != events.end(); ++i) {
186 if ((*i)->type == ev->type) {
187 (*i)->action_frame = ev->action_frame;
188 (*i)->target_frame = ev->target_frame;
197 if (i == events.end()) {
198 events.insert (events.begin(), ev);
201 events.sort (Event::compare);
202 next_event = events.end();
208 /** @return true when @a ev is deleted. */
210 Session::_remove_event (Session::Event* ev)
215 for (i = events.begin(); i != events.end(); ++i) {
216 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
222 if (i == next_event) {
230 if (i != events.end()) {
238 Session::_clear_event_type (Event::Type type)
240 Events::iterator i, tmp;
242 for (i = events.begin(); i != events.end(); ) {
247 if ((*i)->type == type) {
249 if (i == next_event) {
258 for (i = immediate_events.begin(); i != immediate_events.end(); ) {
263 if ((*i)->type == type) {
265 immediate_events.erase (i);
275 Session::set_next_event ()
277 if (events.empty()) {
278 next_event = events.end();
282 if (next_event == events.end()) {
283 next_event = events.begin();
286 if ((*next_event)->action_frame > _transport_frame) {
287 next_event = events.begin();
290 for (; next_event != events.end(); ++next_event) {
291 if ((*next_event)->action_frame >= _transport_frame) {
298 Session::process_event (Event* ev)
303 /* if we're in the middle of a state change (i.e. waiting
304 for the butler thread to complete the non-realtime
305 part of the change), we'll just have to queue this
306 event for a time when the change is complete.
309 if (non_realtime_work_pending()) {
311 /* except locates, which we have the capability to handle */
313 if (ev->type != Event::Locate) {
314 immediate_events.insert (immediate_events.end(), ev);
320 //printf("Processing event: %s\n", event_names[ev->type]);
324 set_play_loop (ev->yes_or_no);
327 case Event::AutoLoop:
329 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
337 // cerr << "forced locate to " << ev->target_frame << endl;
338 locate (ev->target_frame, false, true, false);
340 // cerr << "soft locate to " << ev->target_frame << endl;
341 start_locate (ev->target_frame, false, true, false);
343 _send_smpte_update = true;
346 case Event::LocateRoll:
348 // cerr << "forced locate to+roll " << ev->target_frame << endl;
349 locate (ev->target_frame, true, true, false);
351 // cerr << "soft locate to+roll " << ev->target_frame << endl;
352 start_locate (ev->target_frame, true, true, false);
354 _send_smpte_update = true;
357 case Event::LocateRollLocate:
358 // locate is handled by ::request_roll_at_and_return()
359 _requested_return_frame = ev->target_frame;
360 request_locate (ev->target2_frame, true);
364 case Event::SetTransportSpeed:
365 set_transport_speed (ev->speed, ev->yes_or_no);
369 // cerr << "PunchIN at " << transport_frame() << endl;
370 if (config.get_punch_in() && record_status() == Enabled) {
377 case Event::PunchOut:
378 // cerr << "PunchOUT at " << transport_frame() << endl;
379 if (config.get_punch_out()) {
380 step_back_from_record ();
386 case Event::StopOnce:
387 if (!non_realtime_work_pending()) {
388 stop_transport (ev->yes_or_no);
389 _clear_event_type (Event::StopOnce);
395 case Event::RangeStop:
396 if (!non_realtime_work_pending()) {
397 stop_transport (ev->yes_or_no);
403 case Event::RangeLocate:
404 start_locate (ev->target_frame, true, true, false);
409 case Event::Overwrite:
410 overwrite_some_buffers (static_cast<Diskstream*>(ev->ptr));
413 case Event::SetDiskstreamSpeed:
414 set_diskstream_speed (static_cast<Diskstream*> (ev->ptr), ev->speed);
417 case Event::SetSlaveSource:
418 set_slave_source (ev->slave);
421 case Event::Audition:
422 set_audition (ev->region);
423 // drop reference to region
427 case Event::InputConfigurationChange:
428 post_transport_work = PostTransportWork (post_transport_work | PostTransportInputChange);
429 _butler->schedule_transport_work ();
432 case Event::SetAudioRange:
433 current_audio_range = ev->audio_range;
437 case Event::SetPlayRange:
438 set_play_range (ev->yes_or_no);
442 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
448 del = del && !_remove_event (ev);