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 "pbd/enumwriter.h"
27 #include <glibmm/thread.h>
29 #include "ardour/ardour.h"
30 #include "ardour/audio_diskstream.h"
31 #include "ardour/butler.h"
32 #include "ardour/debug.h"
33 #include "ardour/session.h"
38 using namespace ARDOUR;
41 MultiAllocSingleReleasePool Session::Event::pool ("event", sizeof (Session::Event), 512);
44 Session::add_event (nframes_t frame, Event::Type type, nframes_t target_frame)
46 Event* ev = new Event (type, Event::Add, frame, target_frame, 0);
51 Session::remove_event (nframes_t frame, Event::Type type)
53 Event* ev = new Event (type, Event::Remove, frame, 0, 0);
58 Session::replace_event (Event::Type type, nframes_t frame, nframes_t target)
60 Event* ev = new Event (type, Event::Replace, frame, target, 0);
65 Session::clear_events (Event::Type type)
67 Event* ev = new Event (type, Event::Clear, 0, 0, 0);
73 Session::dump_events () const
75 cerr << "EVENT DUMP" << endl;
76 for (Events::const_iterator i = events.begin(); i != events.end(); ++i) {
77 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
79 cerr << "Next event: ";
81 if ((Events::const_iterator) next_event == events.end()) {
82 cerr << "none" << endl;
84 cerr << "at " << (*next_event)->action_frame << ' '
85 << (*next_event)->type << " target = "
86 << (*next_event)->target_frame << endl;
88 cerr << "Immediate events pending:\n";
89 for (Events::const_iterator i = immediate_events.begin(); i != immediate_events.end(); ++i) {
90 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
92 cerr << "END EVENT_DUMP" << endl;
96 Session::queue_event (Event* ev)
98 if (_state_of_the_state & Loading) {
101 pending_events.write (&ev, 1);
106 Session::merge_event (Event* ev)
108 switch (ev->action) {
119 _clear_event_type (ev->type);
127 /* try to handle immediate events right here */
129 if (ev->action_frame == 0) {
135 case Event::AutoLoop:
136 case Event::StopOnce:
137 _clear_event_type (ev->type);
141 for (Events::iterator i = events.begin(); i != events.end(); ++i) {
142 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
143 error << string_compose(_("Session: cannot have two events of type %1 at the same frame (%2)."),
144 enum_2_string (ev->type), ev->action_frame) << endmsg;
150 events.insert (events.begin(), ev);
151 events.sort (Event::compare);
152 next_event = events.begin();
156 /** @return true when @a ev is deleted. */
158 Session::_replace_event (Event* ev)
163 /* private, used only for events that can only exist once in the queue */
165 for (i = events.begin(); i != events.end(); ++i) {
166 if ((*i)->type == ev->type) {
167 (*i)->action_frame = ev->action_frame;
168 (*i)->target_frame = ev->target_frame;
177 if (i == events.end()) {
178 events.insert (events.begin(), ev);
181 events.sort (Event::compare);
182 next_event = events.end();
188 /** @return true when @a ev is deleted. */
190 Session::_remove_event (Session::Event* ev)
195 for (i = events.begin(); i != events.end(); ++i) {
196 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
202 if (i == next_event) {
210 if (i != events.end()) {
218 Session::_clear_event_type (Event::Type type)
220 Events::iterator i, tmp;
222 for (i = events.begin(); i != events.end(); ) {
227 if ((*i)->type == type) {
229 if (i == next_event) {
238 for (i = immediate_events.begin(); i != immediate_events.end(); ) {
243 if ((*i)->type == type) {
245 immediate_events.erase (i);
255 Session::set_next_event ()
257 if (events.empty()) {
258 next_event = events.end();
262 if (next_event == events.end()) {
263 next_event = events.begin();
266 if ((*next_event)->action_frame > _transport_frame) {
267 next_event = events.begin();
270 for (; next_event != events.end(); ++next_event) {
271 if ((*next_event)->action_frame >= _transport_frame) {
278 Session::process_event (Event* ev)
283 /* if we're in the middle of a state change (i.e. waiting
284 for the butler thread to complete the non-realtime
285 part of the change), we'll just have to queue this
286 event for a time when the change is complete.
289 if (non_realtime_work_pending()) {
291 /* except locates, which we have the capability to handle */
293 if (ev->type != Event::Locate) {
294 immediate_events.insert (immediate_events.end(), ev);
300 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
304 set_play_loop (ev->yes_or_no);
307 case Event::AutoLoop:
309 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
317 // cerr << "forced locate to " << ev->target_frame << endl;
318 locate (ev->target_frame, false, true, false);
320 // cerr << "soft locate to " << ev->target_frame << endl;
321 start_locate (ev->target_frame, false, true, false);
323 _send_timecode_update = true;
326 case Event::LocateRoll:
328 // cerr << "forced locate to+roll " << ev->target_frame << endl;
329 locate (ev->target_frame, true, true, false);
331 // cerr << "soft locate to+roll " << ev->target_frame << endl;
332 start_locate (ev->target_frame, true, true, false);
334 _send_timecode_update = true;
337 case Event::LocateRollLocate:
338 // locate is handled by ::request_roll_at_and_return()
339 _requested_return_frame = ev->target_frame;
340 request_locate (ev->target2_frame, true);
344 case Event::SetTransportSpeed:
345 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
349 // cerr << "PunchIN at " << transport_frame() << endl;
350 if (config.get_punch_in() && record_status() == Enabled) {
357 case Event::PunchOut:
358 // cerr << "PunchOUT at " << transport_frame() << endl;
359 if (config.get_punch_out()) {
360 step_back_from_record ();
366 case Event::StopOnce:
367 if (!non_realtime_work_pending()) {
368 stop_transport (ev->yes_or_no);
369 _clear_event_type (Event::StopOnce);
375 case Event::RangeStop:
376 if (!non_realtime_work_pending()) {
377 stop_transport (ev->yes_or_no);
383 case Event::RangeLocate:
384 start_locate (ev->target_frame, true, true, false);
389 case Event::Overwrite:
390 overwrite_some_buffers (static_cast<Diskstream*>(ev->ptr));
393 case Event::SetDiskstreamSpeed:
394 set_diskstream_speed (static_cast<Diskstream*> (ev->ptr), ev->speed);
397 case Event::SetSyncSource:
398 use_sync_source (ev->sync_source);
401 case Event::Audition:
402 set_audition (ev->region);
403 // drop reference to region
407 case Event::InputConfigurationChange:
408 add_post_transport_work (PostTransportInputChange);
409 _butler->schedule_transport_work ();
412 case Event::SetPlayAudioRange:
413 set_play_range (ev->audio_range, (ev->speed == 1.0f));
417 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
423 del = del && !_remove_event (ev);