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
[] = {
53 "InputConfigurationChange",
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);
69 Session::remove_event (nframes_t frame
, Event::Type type
)
71 Event
* ev
= new Event (type
, Event::Remove
, frame
, 0, 0);
76 Session::replace_event (Event::Type type
, nframes_t frame
, nframes_t target
)
78 Event
* ev
= new Event (type
, Event::Replace
, frame
, target
, 0);
83 Session::clear_events (Event::Type type
)
85 Event
* ev
= new Event (type
, Event::Clear
, 0, 0, 0);
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
;
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
;
114 Session::queue_event (Event
* ev
)
116 if (_state_of_the_state
& Loading
) {
119 pending_events
.write (&ev
, 1);
124 Session::merge_event (Event
* ev
)
126 switch (ev
->action
) {
137 _clear_event_type (ev
->type
);
145 /* try to handle immediate events right here */
147 if (ev
->action_frame
== 0) {
153 case Event::AutoLoop
:
154 case Event::StopOnce
:
155 _clear_event_type (ev
->type
);
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
;
168 events
.insert (events
.begin(), ev
);
169 events
.sort (Event::compare
);
170 next_event
= events
.begin();
175 Session::_replace_event (Event
* ev
)
177 // returns true when we deleted the passed in event
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
;
195 if (i
== events
.end()) {
196 events
.insert (events
.begin(), ev
);
199 events
.sort (Event::compare
);
200 next_event
= events
.end();
207 Session::_remove_event (Session::Event
* ev
)
209 // returns true when we deleted the passed in event
213 for (i
= events
.begin(); i
!= events
.end(); ++i
) {
214 if ((*i
)->type
== ev
->type
&& (*i
)->action_frame
== ev
->action_frame
) {
220 if (i
== next_event
) {
228 if (i
!= events
.end()) {
236 Session::_clear_event_type (Event::Type type
)
238 Events::iterator i
, tmp
;
240 for (i
= events
.begin(); i
!= events
.end(); ) {
245 if ((*i
)->type
== type
) {
247 if (i
== next_event
) {
256 for (i
= immediate_events
.begin(); i
!= immediate_events
.end(); ) {
261 if ((*i
)->type
== type
) {
263 immediate_events
.erase (i
);
273 Session::set_next_event ()
275 if (events
.empty()) {
276 next_event
= events
.end();
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
) {
296 Session::process_event (Event
* ev
)
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
);
320 set_play_loop (ev
->yes_or_no
);
323 case Event::AutoLoop
:
325 start_locate (ev
->target_frame
, true, false, Config
->get_seamless_loop());
333 // cerr << "forced locate to " << ev->target_frame << endl;
334 locate (ev
->target_frame
, false, true, false);
336 // cerr << "soft locate to " << ev->target_frame << endl;
337 start_locate (ev
->target_frame
, false, true, false);
341 case Event::LocateRoll
:
343 // cerr << "forced locate to+roll " << ev->target_frame << endl;
344 locate (ev
->target_frame
, true, true, false);
346 // cerr << "soft locate to+roll " << ev->target_frame << endl;
347 start_locate (ev
->target_frame
, true, true, false);
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);
359 case Event::SetTransportSpeed
:
360 set_transport_speed (ev
->speed
, ev
->yes_or_no
);
364 // cerr << "PunchIN at " << transport_frame() << endl;
365 if (Config
->get_punch_in() && record_status() == Enabled
) {
372 case Event::PunchOut
:
373 // cerr << "PunchOUT at " << transport_frame() << endl;
374 if (Config
->get_punch_out()) {
375 step_back_from_record ();
381 case Event::StopOnce
:
382 if (!non_realtime_work_pending()) {
383 stop_transport (ev
->yes_or_no
);
384 _clear_event_type (Event::StopOnce
);
390 case Event::RangeStop
:
391 if (!non_realtime_work_pending()) {
392 stop_transport (ev
->yes_or_no
);
398 case Event::RangeLocate
:
399 start_locate (ev
->target_frame
, true, true, false);
404 case Event::Overwrite
:
405 overwrite_some_buffers (static_cast<AudioDiskstream
*>(ev
->ptr
));
408 case Event::SetDiskstreamSpeed
:
409 set_diskstream_speed (static_cast<AudioDiskstream
*> (ev
->ptr
), ev
->speed
);
412 case Event::SetSlaveSource
:
413 set_slave_source (ev
->slave
);
416 case Event::Audition
:
417 set_audition (ev
->region
);
418 // drop reference to region
422 case Event::InputConfigurationChange
:
423 post_transport_work
= PostTransportWork (post_transport_work
| PostTransportInputChange
);
424 schedule_butler_transport_work ();
427 case Event::SetAudioRange
:
428 current_audio_range
= ev
->audio_range
;
432 case Event::SetPlayRange
:
433 set_play_range (ev
->yes_or_no
);
437 fatal
<< string_compose(_("Programming error: illegal event type in process_event (%1)"), ev
->type
) << endmsg
;
443 del
= del
&& !_remove_event (ev
);