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/session.h>
30 #include <ardour/audio_diskstream.h>
34 using namespace ARDOUR;
37 MultiAllocSingleReleasePool Session::Event::pool ("event", sizeof (Session::Event), 512);
39 static const char* event_names[] = {
52 "InputConfigurationChange",
61 Session::add_event (nframes_t frame, Event::Type type, nframes_t target_frame)
63 Event* ev = new Event (type, Event::Add, frame, target_frame, 0);
68 Session::remove_event (nframes_t frame, Event::Type type)
70 Event* ev = new Event (type, Event::Remove, frame, 0, 0);
75 Session::replace_event (Event::Type type, nframes_t frame, nframes_t target)
77 Event* ev = new Event (type, Event::Replace, frame, target, 0);
82 Session::clear_events (Event::Type type)
84 Event* ev = new Event (type, Event::Clear, 0, 0, 0);
90 Session::dump_events () const
92 cerr << "EVENT DUMP" << endl;
93 for (Events::const_iterator i = events.begin(); i != events.end(); ++i) {
94 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
96 cerr << "Next event: ";
98 if ((Events::const_iterator) next_event == events.end()) {
99 cerr << "none" << endl;
101 cerr << "at " << (*next_event)->action_frame << ' '
102 << (*next_event)->type << " target = "
103 << (*next_event)->target_frame << endl;
105 cerr << "Immediate events pending:\n";
106 for (Events::const_iterator i = immediate_events.begin(); i != immediate_events.end(); ++i) {
107 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
109 cerr << "END EVENT_DUMP" << endl;
113 Session::queue_event (Event* ev)
115 if (_state_of_the_state & Loading) {
118 pending_events.write (&ev, 1);
123 Session::merge_event (Event* ev)
125 switch (ev->action) {
136 _clear_event_type (ev->type);
144 /* try to handle immediate events right here */
146 if (ev->action_frame == 0) {
152 case Event::AutoLoop:
153 case Event::StopOnce:
154 _clear_event_type (ev->type);
158 for (Events::iterator i = events.begin(); i != events.end(); ++i) {
159 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
160 error << string_compose(_("Session: cannot have two events of type %1 at the same frame (%2)."),
161 event_names[ev->type], ev->action_frame) << endmsg;
167 events.insert (events.begin(), ev);
168 events.sort (Event::compare);
169 next_event = events.begin();
173 /** @return true when @a ev is deleted. */
175 Session::_replace_event (Event* ev)
180 /* private, used only for events that can only exist once in the queue */
182 for (i = events.begin(); i != events.end(); ++i) {
183 if ((*i)->type == ev->type) {
184 (*i)->action_frame = ev->action_frame;
185 (*i)->target_frame = ev->target_frame;
194 if (i == events.end()) {
195 events.insert (events.begin(), ev);
198 events.sort (Event::compare);
199 next_event = events.end();
205 /** @return true when @a ev is deleted. */
207 Session::_remove_event (Session::Event* ev)
212 for (i = events.begin(); i != events.end(); ++i) {
213 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
219 if (i == next_event) {
227 if (i != events.end()) {
235 Session::_clear_event_type (Event::Type type)
237 Events::iterator i, tmp;
239 for (i = events.begin(); i != events.end(); ) {
244 if ((*i)->type == type) {
246 if (i == next_event) {
255 for (i = immediate_events.begin(); i != immediate_events.end(); ) {
260 if ((*i)->type == type) {
262 immediate_events.erase (i);
272 Session::set_next_event ()
274 if (events.empty()) {
275 next_event = events.end();
279 if (next_event == events.end()) {
280 next_event = events.begin();
283 if ((*next_event)->action_frame > _transport_frame) {
284 next_event = events.begin();
287 for (; next_event != events.end(); ++next_event) {
288 if ((*next_event)->action_frame >= _transport_frame) {
295 Session::process_event (Event* ev)
300 /* if we're in the middle of a state change (i.e. waiting
301 for the butler thread to complete the non-realtime
302 part of the change), we'll just have to queue this
303 event for a time when the change is complete.
306 if (non_realtime_work_pending()) {
308 /* except locates, which we have the capability to handle */
310 if (ev->type != Event::Locate) {
311 immediate_events.insert (immediate_events.end(), ev);
317 //printf("Processing event: %s\n", event_names[ev->type]);
321 set_play_loop (ev->yes_or_no);
324 case Event::AutoLoop:
326 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
334 // cerr << "forced locate to " << ev->target_frame << endl;
335 locate (ev->target_frame, false, true, false);
337 // cerr << "soft locate to " << ev->target_frame << endl;
338 start_locate (ev->target_frame, false, true, false);
340 _send_smpte_update = true;
343 case Event::LocateRoll:
345 // cerr << "forced locate to+roll " << ev->target_frame << endl;
346 locate (ev->target_frame, true, true, false);
348 // cerr << "soft locate to+roll " << ev->target_frame << endl;
349 start_locate (ev->target_frame, true, true, false);
351 _send_smpte_update = true;
354 case Event::SetTransportSpeed:
355 set_transport_speed (ev->speed, ev->yes_or_no);
359 // cerr << "PunchIN at " << transport_frame() << endl;
360 if (Config->get_punch_in() && record_status() == Enabled) {
367 case Event::PunchOut:
368 // cerr << "PunchOUT at " << transport_frame() << endl;
369 if (Config->get_punch_out()) {
370 step_back_from_record ();
376 case Event::StopOnce:
377 if (!non_realtime_work_pending()) {
378 stop_transport (ev->yes_or_no);
379 _clear_event_type (Event::StopOnce);
385 case Event::RangeStop:
386 if (!non_realtime_work_pending()) {
387 stop_transport (ev->yes_or_no);
393 case Event::RangeLocate:
394 start_locate (ev->target_frame, true, true, false);
399 case Event::Overwrite:
400 overwrite_some_buffers (static_cast<Diskstream*>(ev->ptr));
403 case Event::SetDiskstreamSpeed:
404 set_diskstream_speed (static_cast<Diskstream*> (ev->ptr), ev->speed);
407 case Event::SetSlaveSource:
408 set_slave_source (ev->slave);
411 case Event::Audition:
412 set_audition (ev->region);
413 // drop reference to region
417 case Event::InputConfigurationChange:
418 post_transport_work = PostTransportWork (post_transport_work | PostTransportInputChange);
419 schedule_butler_transport_work ();
422 case Event::SetAudioRange:
423 current_audio_range = ev->audio_range;
427 case Event::SetPlayRange:
428 set_play_range (ev->yes_or_no);
432 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
438 del = del && !_remove_event (ev);