2 Copyright (C) 1999-2002 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.
25 #include "pbd/error.h"
26 #include "pbd/enumwriter.h"
28 #include <glibmm/thread.h>
30 #include "ardour/ardour.h"
31 #include "ardour/audioengine.h"
32 #include "ardour/auditioner.h"
33 #include "ardour/butler.h"
34 #include "ardour/debug.h"
35 #include "ardour/process_thread.h"
36 #include "ardour/session.h"
37 #include "ardour/slave.h"
38 #include "ardour/timestamps.h"
39 #include "ardour/graph.h"
40 #include "ardour/audio_port.h"
42 #include "midi++/manager.h"
43 #include "midi++/mmc.h"
47 using namespace ARDOUR
;
51 /** Called by the audio engine when there is work to be done with JACK.
52 * @param nframes Number of frames to process.
56 Session::process (pframes_t nframes
)
58 MIDI::Manager::instance()->cycle_start(nframes
);
62 if (processing_blocked()) {
67 if (non_realtime_work_pending()) {
68 if (!_butler
->transport_work_requested ()) {
73 _engine
.main_thread()->get_buffers ();
75 (this->*process_function
) (nframes
);
77 _engine
.main_thread()->drop_buffers ();
79 // the ticker is for sending time information like MidiClock
80 framepos_t transport_frames
= transport_frame();
81 Timecode::BBT_Time transport_bbt
;
82 bbt_time(transport_frames
, transport_bbt
);
83 Timecode::Time transport_timecode
;
84 timecode_time(transport_frames
, transport_timecode
);
85 tick (transport_frames
, transport_bbt
, transport_timecode
); /* EMIT SIGNAL */
87 SendFeedback (); /* EMIT SIGNAL */
89 MIDI::Manager::instance()->cycle_end();
93 Session::fail_roll (pframes_t nframes
)
95 return no_roll (nframes
);
99 Session::no_roll (pframes_t nframes
)
101 framepos_t end_frame
= _transport_frame
+ nframes
; // FIXME: varispeed + no_roll ??
103 bool declick
= get_transport_declick_required();
104 boost::shared_ptr
<RouteList
> r
= routes
.reader ();
107 _click_io
->silence (nframes
);
110 if (route_graph
->threads_in_use() > 0) {
111 DEBUG_TRACE(DEBUG::ProcessThreads
,"calling graph/no-roll\n");
112 route_graph
->routes_no_roll( nframes
, _transport_frame
, end_frame
, non_realtime_work_pending(), actively_recording(), declick
);
114 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
116 if ((*i
)->is_hidden()) {
120 (*i
)->set_pending_declick (declick
);
122 if ((*i
)->no_roll (nframes
, _transport_frame
, end_frame
, non_realtime_work_pending(),
123 actively_recording(), declick
)) {
124 error
<< string_compose(_("Session: error in no roll for %1"), (*i
)->name()) << endmsg
;
135 Session::process_routes (pframes_t nframes
, bool& need_butler
)
138 int declick
= get_transport_declick_required();
139 bool rec_monitors
= get_rec_monitors_input();
140 boost::shared_ptr
<RouteList
> r
= routes
.reader ();
142 if (transport_sub_state
& StopPendingCapture
) {
143 /* force a declick out */
147 record_active
= actively_recording(); // || (get_record_enabled() && get_punch_in());
149 const framepos_t start_frame
= _transport_frame
;
150 const framepos_t end_frame
= _transport_frame
+ floor (nframes
* _transport_speed
);
152 /* XXX this is hack to force use of the graph even if we are only
153 using 1 thread. its needed because otherwise when we remove
154 tracks, the graph never gets updated.
156 if (1 || route_graph
->threads_in_use() > 0) {
157 DEBUG_TRACE(DEBUG::ProcessThreads
,"calling graph/process-routes\n");
158 route_graph
->process_routes( nframes
, start_frame
, end_frame
, declick
, record_active
, rec_monitors
, need_butler
);
161 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
165 if ((*i
)->is_hidden()) {
169 (*i
)->set_pending_declick (declick
);
171 if ((ret
= (*i
)->roll (nframes
, start_frame
, end_frame
, declick
, record_active
, rec_monitors
, need_butler
)) < 0) {
182 Session::silent_process_routes (pframes_t nframes
, bool& need_butler
)
184 bool record_active
= actively_recording();
185 int declick
= get_transport_declick_required();
186 bool rec_monitors
= get_rec_monitors_input();
187 boost::shared_ptr
<RouteList
> r
= routes
.reader ();
189 if (transport_sub_state
& StopPendingCapture
) {
190 /* force a declick out */
194 const framepos_t start_frame
= _transport_frame
;
195 const framepos_t end_frame
= _transport_frame
+ lrintf(nframes
* _transport_speed
);
197 /* XXX this is hack to force use of the graph even if we are only
198 using 1 thread. its needed because otherwise when we remove
199 tracks, the graph never gets updated.
201 if (1 || route_graph
->threads_in_use() > 0) {
202 route_graph
->silent_process_routes( nframes
, start_frame
, end_frame
, record_active
, rec_monitors
, need_butler
);
204 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
208 if ((*i
)->is_hidden()) {
212 if ((ret
= (*i
)->silent_roll (nframes
, start_frame
, end_frame
, record_active
, rec_monitors
, need_butler
)) < 0) {
223 Session::get_track_statistics ()
228 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
229 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
231 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
233 if (!tr
|| tr
->hidden()) {
237 pworst
= min (pworst
, tr
->playback_buffer_load());
238 cworst
= min (cworst
, tr
->capture_buffer_load());
241 g_atomic_int_set (&_playback_load
, (uint32_t) floor (pworst
* 100.0f
));
242 g_atomic_int_set (&_capture_load
, (uint32_t) floor (cworst
* 100.0f
));
244 if (actively_recording()) {
249 /** Process callback used when the auditioner is not active */
251 Session::process_with_events (pframes_t nframes
)
254 pframes_t this_nframes
;
255 framepos_t end_frame
;
256 bool session_needs_butler
= false;
257 framepos_t stop_limit
;
258 framecnt_t frames_moved
;
260 /* make sure the auditioner is silent */
263 auditioner
->silence (nframes
);
266 /* handle any pending events */
268 while (pending_events
.read (&ev
, 1) == 1) {
272 /* if we are not in the middle of a state change,
273 and there are immediate events queued up,
277 while (!non_realtime_work_pending() && !immediate_events
.empty()) {
278 SessionEvent
*ev
= immediate_events
.front ();
279 immediate_events
.pop_front ();
283 /* Decide on what to do with quarter-frame MTC during this cycle */
285 bool const was_sending_qf_mtc
= _send_qf_mtc
;
286 double const tolerance
= Config
->get_mtc_qf_speed_tolerance() / 100.0;
288 if (_transport_speed
!= 0) {
290 Config
->get_send_mtc () &&
291 _transport_speed
>= (1 - tolerance
) &&
292 _transport_speed
<= (1 + tolerance
)
295 if (_send_qf_mtc
&& !was_sending_qf_mtc
) {
296 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
297 _send_timecode_update
= true;
300 if (Config
->get_send_mtc() && !_send_qf_mtc
&& _pframes_since_last_mtc
> (frame_rate () / 4)) {
301 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
302 a quarter of a second since we sent anything at all, so send a full MTC update
305 _send_timecode_update
= true;
308 _pframes_since_last_mtc
+= nframes
;
311 /* Events caused a transport change (or we re-started sending
312 * MTC), so send an MTC Full Frame (Timecode) message. This
313 * is sent whether rolling or not, to give slaves an idea of
314 * ardour time on locates (and allow slow slaves to position
315 * and prepare for rolling)
317 if (_send_timecode_update
) {
318 send_full_time_code (_transport_frame
);
321 if (!process_can_proceed()) {
326 if (events
.empty() || next_event
== events
.end()) {
327 process_without_events (nframes
);
331 if (_transport_speed
== 1.0) {
332 frames_moved
= (framecnt_t
) nframes
;
334 interpolation
.set_target_speed (fabs(_target_transport_speed
));
335 interpolation
.set_speed (fabs(_transport_speed
));
336 frames_moved
= (framecnt_t
) interpolation
.interpolate (0, nframes
, 0, 0);
339 end_frame
= _transport_frame
+ frames_moved
;
342 SessionEvent
* this_event
;
343 Events::iterator the_next_one
;
345 if (!process_can_proceed()) {
350 if (!_exporting
&& _slave
) {
351 if (!follow_slave (nframes
)) {
356 if (_transport_speed
== 0) {
361 if (!_exporting
&& !timecode_transmission_suspended()) {
362 send_midi_time_code_for_cycle (_transport_frame
, end_frame
, nframes
);
365 if (actively_recording()) {
366 stop_limit
= max_framepos
;
369 if (Config
->get_stop_at_session_end()) {
370 stop_limit
= current_end_frame();
372 stop_limit
= max_framepos
;
376 if (maybe_stop (stop_limit
)) {
381 this_event
= *next_event
;
382 the_next_one
= next_event
;
385 /* yes folks, here it is, the actual loop where we really truly
391 this_nframes
= nframes
; /* real (jack) time relative */
392 frames_moved
= (framecnt_t
) floor (_transport_speed
* nframes
); /* transport relative */
394 /* running an event, position transport precisely to its time */
395 if (this_event
&& this_event
->action_frame
<= end_frame
&& this_event
->action_frame
>= _transport_frame
) {
396 /* this isn't quite right for reverse play */
397 frames_moved
= (framecnt_t
) (this_event
->action_frame
- _transport_frame
);
398 this_nframes
= abs (floor(frames_moved
/ _transport_speed
));
403 click (_transport_frame
, this_nframes
);
405 if (process_routes (this_nframes
, session_needs_butler
)) {
410 get_track_statistics ();
412 nframes
-= this_nframes
;
414 if (frames_moved
< 0) {
415 decrement_transport_position (-frames_moved
);
417 increment_transport_position (frames_moved
);
420 maybe_stop (stop_limit
);
421 check_declick_out ();
424 _engine
.split_cycle (this_nframes
);
426 /* now handle this event and all others scheduled for the same time */
428 while (this_event
&& this_event
->action_frame
== _transport_frame
) {
429 process_event (this_event
);
431 if (the_next_one
== events
.end()) {
434 this_event
= *the_next_one
;
439 /* if an event left our state changing, do the right thing */
441 if (nframes
&& non_realtime_work_pending()) {
446 /* this is necessary to handle the case of seamless looping */
447 end_frame
= _transport_frame
+ floor (nframes
* _transport_speed
);
452 } /* implicit release of route lock */
454 if (session_needs_butler
) {
460 Session::reset_slave_state ()
462 average_slave_delta
= 1800;
463 delta_accumulator_cnt
= 0;
464 have_first_delta_accumulator
= false;
465 _slave_state
= Stopped
;
469 Session::transport_locked () const
473 if (!locate_pending() && (!config
.get_external_sync() || (sl
&& sl
->ok() && sl
->locked()))) {
481 Session::follow_slave (pframes_t nframes
)
484 framepos_t slave_transport_frame
;
485 framecnt_t this_delta
;
490 config
.set_external_sync (false);
494 _slave
->speed_and_position (slave_speed
, slave_transport_frame
);
496 DEBUG_TRACE (DEBUG::Slave
, string_compose ("Slave position %1 speed %2\n", slave_transport_frame
, slave_speed
));
498 if (!_slave
->locked()) {
499 DEBUG_TRACE (DEBUG::Slave
, "slave not locked\n");
503 if (slave_transport_frame
> _transport_frame
) {
504 this_delta
= slave_transport_frame
- _transport_frame
;
507 this_delta
= _transport_frame
- slave_transport_frame
;
511 if (_slave
->starting()) {
515 if (_slave
->is_always_synced() || config
.get_timecode_source_is_synced()) {
517 /* if the TC source is synced, then we assume that its
518 speed is binary: 0.0 or 1.0
521 if (slave_speed
!= 0.0f
) {
527 /* if we are chasing and the average delta between us and the
528 master gets too big, we want to switch to silent
529 motion. so keep track of that here.
532 if (_slave_state
== Running
) {
533 calculate_moving_average_of_slave_delta(dir
, this_delta
);
537 track_slave_state (slave_speed
, slave_transport_frame
, this_delta
);
539 DEBUG_TRACE (DEBUG::Slave
, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
540 _slave_state
, slave_transport_frame
, slave_speed
, this_delta
, average_slave_delta
));
543 if (_slave_state
== Running
&& !_slave
->is_always_synced() && !config
.get_timecode_source_is_synced()) {
545 if (_transport_speed
!= 0.0f
) {
548 note that average_dir is +1 or -1
553 if (average_slave_delta
== 0) {
557 delta
= average_slave_delta
;
558 delta
*= average_dir
;
562 if (slave_speed
!= 0.0) {
563 DEBUG_TRACE (DEBUG::Slave
, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
564 (int) (dir
* this_delta
),
568 slave_transport_frame
,
569 average_slave_delta
));
573 if (_slave
->give_slave_full_control_over_transport_speed()) {
574 set_transport_speed (slave_speed
, false, false);
575 //std::cout << "set speed = " << slave_speed << "\n";
577 float adjusted_speed
= slave_speed
+ (1.5 * (delta
/ float(_current_frame_rate
)));
578 request_transport_speed (adjusted_speed
);
579 DEBUG_TRACE (DEBUG::Slave
, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
580 delta
, adjusted_speed
, adjusted_speed
/slave_speed
, _transport_speed
,
585 if ((framecnt_t
) abs(average_slave_delta
) > _slave
->resolution()) {
586 cerr
<< "average slave delta greater than slave resolution (" << _slave
->resolution() << "), going to silent motion\n";
594 if (_slave_state
== Running
&& !non_realtime_work_pending()) {
595 /* speed is set, we're locked, and good to go */
600 DEBUG_TRACE (DEBUG::Slave
, "silent motion\n")
601 follow_slave_silently (nframes
, slave_speed
);
604 /* don't move at all */
605 DEBUG_TRACE (DEBUG::Slave
, "no roll\n")
611 Session::calculate_moving_average_of_slave_delta (int dir
, framecnt_t this_delta
)
613 if (delta_accumulator_cnt
>= delta_accumulator_size
) {
614 have_first_delta_accumulator
= true;
615 delta_accumulator_cnt
= 0;
618 if (delta_accumulator_cnt
!= 0 || this_delta
< _current_frame_rate
) {
619 delta_accumulator
[delta_accumulator_cnt
++] = (framecnt_t
) dir
* (framecnt_t
) this_delta
;
622 if (have_first_delta_accumulator
) {
623 average_slave_delta
= 0L;
624 for (int i
= 0; i
< delta_accumulator_size
; ++i
) {
625 average_slave_delta
+= delta_accumulator
[i
];
627 average_slave_delta
/= (int32_t) delta_accumulator_size
;
628 if (average_slave_delta
< 0L) {
630 average_slave_delta
= abs(average_slave_delta
);
638 Session::track_slave_state (float slave_speed
, framepos_t slave_transport_frame
, framecnt_t this_delta
)
640 if (slave_speed
!= 0.0f
) {
642 /* slave is running */
644 switch (_slave_state
) {
646 if (_slave
->requires_seekahead()) {
647 slave_wait_end
= slave_transport_frame
+ _slave
->seekahead_distance ();
648 DEBUG_TRACE (DEBUG::Slave
, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end
));
649 /* we can call locate() here because we are in process context */
650 locate (slave_wait_end
, false, false);
651 _slave_state
= Waiting
;
655 _slave_state
= Running
;
657 Location
* al
= _locations
->auto_loop_location();
659 if (al
&& play_loop
&& (slave_transport_frame
< al
->start() || slave_transport_frame
> al
->end())) {
661 request_play_loop(false);
664 if (slave_transport_frame
!= _transport_frame
) {
665 locate (slave_transport_frame
, false, false);
675 if (_slave_state
== Waiting
) {
677 DEBUG_TRACE (DEBUG::Slave
, string_compose ("slave waiting at %1\n", slave_transport_frame
));
679 if (slave_transport_frame
>= slave_wait_end
) {
681 DEBUG_TRACE (DEBUG::Slave
, string_compose ("slave start at %1 vs %2\n", slave_transport_frame
, _transport_frame
));
683 _slave_state
= Running
;
685 /* now perform a "micro-seek" within the disk buffers to realign ourselves
686 precisely with the master.
691 framecnt_t frame_delta
= slave_transport_frame
- _transport_frame
;
693 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
694 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
695 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
696 if (tr
&& !tr
->can_internal_playback_seek (frame_delta
)) {
703 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
704 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
706 tr
->internal_playback_seek (frame_delta
);
709 _transport_frame
+= frame_delta
;
712 cerr
<< "cannot micro-seek\n";
716 memset (delta_accumulator
, 0, sizeof (int32_t) * delta_accumulator_size
);
717 average_slave_delta
= 0L;
722 if (_slave_state
== Running
&& _transport_speed
== 0.0f
) {
723 DEBUG_TRACE (DEBUG::Slave
, "slave starts transport\n");
727 } else { // slave_speed is 0
729 /* slave has stopped */
731 if (_transport_speed
!= 0.0f
) {
732 DEBUG_TRACE (DEBUG::Slave
, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed
, slave_transport_frame
, _transport_frame
));
736 if (slave_transport_frame
!= _transport_frame
) {
737 DEBUG_TRACE (DEBUG::Slave
, string_compose ("slave stopped, move to %1\n", slave_transport_frame
));
738 force_locate (slave_transport_frame
, false);
741 _slave_state
= Stopped
;
746 Session::follow_slave_silently (pframes_t nframes
, float slave_speed
)
748 if (slave_speed
&& _transport_speed
) {
750 /* something isn't right, but we should move with the master
756 silent_process_routes (nframes
, need_butler
);
758 get_track_statistics ();
764 int32_t frames_moved
= (int32_t) floor (_transport_speed
* nframes
);
766 if (frames_moved
< 0) {
767 decrement_transport_position (-frames_moved
);
769 increment_transport_position (frames_moved
);
772 framepos_t stop_limit
;
774 if (actively_recording()) {
775 stop_limit
= max_framepos
;
777 if (Config
->get_stop_at_session_end()) {
778 stop_limit
= current_end_frame();
780 stop_limit
= max_framepos
;
784 maybe_stop (stop_limit
);
789 Session::process_without_events (pframes_t nframes
)
791 bool session_needs_butler
= false;
792 framepos_t stop_limit
;
793 framecnt_t frames_moved
;
795 if (!process_can_proceed()) {
800 if (!_exporting
&& _slave
) {
801 if (!follow_slave (nframes
)) {
806 if (_transport_speed
== 0) {
811 if (_transport_speed
== 1.0) {
812 frames_moved
= (framecnt_t
) nframes
;
814 interpolation
.set_target_speed (fabs(_target_transport_speed
));
815 interpolation
.set_speed (fabs(_transport_speed
));
816 frames_moved
= (framecnt_t
) interpolation
.interpolate (0, nframes
, 0, 0);
819 if (!_exporting
&& !timecode_transmission_suspended()) {
820 send_midi_time_code_for_cycle (_transport_frame
, _transport_frame
+ frames_moved
, nframes
);
823 if (actively_recording()) {
824 stop_limit
= max_framepos
;
826 if (Config
->get_stop_at_session_end()) {
827 stop_limit
= current_end_frame();
829 stop_limit
= max_framepos
;
833 if (maybe_stop (stop_limit
)) {
838 if (maybe_sync_start (nframes
)) {
842 click (_transport_frame
, nframes
);
844 if (process_routes (nframes
, session_needs_butler
)) {
849 get_track_statistics ();
851 /* XXX: I'm not sure whether this is correct, but at least it
852 matches process_with_events, so that this new frames_moved
853 is -ve when transport speed is -ve. This means that the
854 transport position is updated correctly when we are in
855 reverse. It seems a bit wrong that we're not using the
856 interpolator to compute this.
859 frames_moved
= (framecnt_t
) floor (_transport_speed
* nframes
);
861 if (frames_moved
< 0) {
862 decrement_transport_position (-frames_moved
);
864 increment_transport_position (frames_moved
);
867 maybe_stop (stop_limit
);
868 check_declick_out ();
870 if (session_needs_butler
) {
875 /** Process callback used when the auditioner is active.
876 * @param nframes number of frames to process.
879 Session::process_audition (pframes_t nframes
)
882 boost::shared_ptr
<RouteList
> r
= routes
.reader ();
884 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
885 if (!(*i
)->is_hidden()) {
886 (*i
)->silence (nframes
);
890 /* run the auditioner, and if it says we need butler service, ask for it */
892 if (auditioner
->play_audition (nframes
) > 0) {
896 /* if using a monitor section, run it because otherwise we don't hear anything */
898 if (auditioner
->needs_monitor()) {
899 _monitor_out
->passthru (_transport_frame
, _transport_frame
+ nframes
, nframes
, false);
902 /* handle pending events */
904 while (pending_events
.read (&ev
, 1) == 1) {
908 /* if we are not in the middle of a state change,
909 and there are immediate events queued up,
913 while (!non_realtime_work_pending() && !immediate_events
.empty()) {
914 SessionEvent
*ev
= immediate_events
.front ();
915 immediate_events
.pop_front ();
919 if (!auditioner
->auditioning()) {
920 /* auditioner no longer active, so go back to the normal process callback */
921 process_function
= &Session::process_with_events
;
926 Session::maybe_sync_start (pframes_t
& nframes
)
928 pframes_t sync_offset
;
930 if (!waiting_for_sync_offset
) {
934 if (_engine
.get_sync_offset (sync_offset
) && sync_offset
< nframes
) {
936 /* generate silence up to the sync point, then
937 adjust nframes + offset to reflect whatever
941 no_roll (sync_offset
);
942 nframes
-= sync_offset
;
943 Port::increment_global_port_buffer_offset (sync_offset
);
944 waiting_for_sync_offset
= false;
947 return true; // done, nothing left to process
952 /* sync offset point is not within this process()
953 cycle, so just generate silence. and don't bother
954 with any fancy stuff here, just the minimal silence.
959 if (Config
->get_locate_while_waiting_for_sync()) {
960 if (micro_locate (nframes
)) {
961 /* XXX ERROR !!! XXX */
965 return true; // done, nothing left to process
972 Session::queue_event (SessionEvent
* ev
)
974 if (_state_of_the_state
& Deletion
) {
976 } else if (_state_of_the_state
& Loading
) {
979 pending_events
.write (&ev
, 1);
984 Session::set_next_event ()
986 if (events
.empty()) {
987 next_event
= events
.end();
991 if (next_event
== events
.end()) {
992 next_event
= events
.begin();
995 if ((*next_event
)->action_frame
> _transport_frame
) {
996 next_event
= events
.begin();
999 for (; next_event
!= events
.end(); ++next_event
) {
1000 if ((*next_event
)->action_frame
>= _transport_frame
) {
1007 Session::process_event (SessionEvent
* ev
)
1012 /* if we're in the middle of a state change (i.e. waiting
1013 for the butler thread to complete the non-realtime
1014 part of the change), we'll just have to queue this
1015 event for a time when the change is complete.
1018 if (non_realtime_work_pending()) {
1020 /* except locates, which we have the capability to handle */
1022 if (ev
->type
!= SessionEvent::Locate
) {
1023 immediate_events
.insert (immediate_events
.end(), ev
);
1029 DEBUG_TRACE (DEBUG::SessionEvents
, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev
->type
), _transport_frame
));
1032 case SessionEvent::SetLoop
:
1033 set_play_loop (ev
->yes_or_no
);
1036 case SessionEvent::AutoLoop
:
1038 start_locate (ev
->target_frame
, true, false, Config
->get_seamless_loop());
1044 case SessionEvent::Locate
:
1045 if (ev
->yes_or_no
) {
1046 // cerr << "forced locate to " << ev->target_frame << endl;
1047 locate (ev
->target_frame
, false, true, false);
1049 // cerr << "soft locate to " << ev->target_frame << endl;
1050 start_locate (ev
->target_frame
, false, true, false);
1052 _send_timecode_update
= true;
1055 case SessionEvent::LocateRoll
:
1056 if (ev
->yes_or_no
) {
1057 // cerr << "forced locate to+roll " << ev->target_frame << endl;
1058 locate (ev
->target_frame
, true, true, false);
1060 // cerr << "soft locate to+roll " << ev->target_frame << endl;
1061 start_locate (ev
->target_frame
, true, true, false);
1063 _send_timecode_update
= true;
1066 case SessionEvent::LocateRollLocate
:
1067 // locate is handled by ::request_roll_at_and_return()
1068 _requested_return_frame
= ev
->target_frame
;
1069 request_locate (ev
->target2_frame
, true);
1073 case SessionEvent::SetTransportSpeed
:
1074 set_transport_speed (ev
->speed
, ev
->yes_or_no
, ev
->second_yes_or_no
);
1077 case SessionEvent::PunchIn
:
1078 // cerr << "PunchIN at " << transport_frame() << endl;
1079 if (config
.get_punch_in() && record_status() == Enabled
) {
1086 case SessionEvent::PunchOut
:
1087 // cerr << "PunchOUT at " << transport_frame() << endl;
1088 if (config
.get_punch_out()) {
1089 step_back_from_record ();
1095 case SessionEvent::StopOnce
:
1096 if (!non_realtime_work_pending()) {
1097 stop_transport (ev
->yes_or_no
);
1098 _clear_event_type (SessionEvent::StopOnce
);
1104 case SessionEvent::RangeStop
:
1105 if (!non_realtime_work_pending()) {
1106 stop_transport (ev
->yes_or_no
);
1112 case SessionEvent::RangeLocate
:
1113 start_locate (ev
->target_frame
, true, true, false);
1118 case SessionEvent::Overwrite
:
1119 overwrite_some_buffers (static_cast<Track
*>(ev
->ptr
));
1122 case SessionEvent::SetTrackSpeed
:
1123 set_track_speed (static_cast<Track
*> (ev
->ptr
), ev
->speed
);
1126 case SessionEvent::SetSyncSource
:
1127 use_sync_source (ev
->slave
);
1130 case SessionEvent::Audition
:
1131 set_audition (ev
->region
);
1132 // drop reference to region
1133 ev
->region
.reset ();
1136 case SessionEvent::InputConfigurationChange
:
1137 add_post_transport_work (PostTransportInputChange
);
1138 _butler
->schedule_transport_work ();
1141 case SessionEvent::SetPlayAudioRange
:
1142 set_play_range (ev
->audio_range
, (ev
->speed
== 1.0f
));
1145 case SessionEvent::RealTimeOperation
:
1147 del
= false; // other side of RT request needs to clean up
1150 case SessionEvent::AdjustPlaybackBuffering
:
1151 schedule_playback_buffering_adjustment ();
1154 case SessionEvent::AdjustCaptureBuffering
:
1155 schedule_capture_buffering_adjustment ();
1158 case SessionEvent::SetTimecodeTransmission
:
1159 g_atomic_int_set (&_suspend_timecode_transmission
, ev
->yes_or_no
? 0 : 1);
1163 fatal
<< string_compose(_("Programming error: illegal event type in process_event (%1)"), ev
->type
) << endmsg
;
1169 del
= del
&& !_remove_event (ev
);