2 * Copyright (C) 1999-2019 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2006-2007 Jesse Chappell <jesse@essej.net>
4 * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
5 * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
6 * Copyright (C) 2008-2009 Hans Baier <hansfbaier@googlemail.com>
7 * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <boost/msm/back/state_machine.hpp>
30 #include <boost/msm/front/state_machine_def.hpp>
32 #include "pbd/error.h"
33 #include "pbd/enumwriter.h"
35 #include <glibmm/threads.h>
37 #include "ardour/audioengine.h"
38 #include "ardour/auditioner.h"
39 #include "ardour/butler.h"
40 #include "ardour/cycle_timer.h"
41 #include "ardour/debug.h"
42 #include "ardour/disk_reader.h"
43 #include "ardour/graph.h"
44 #include "ardour/port.h"
45 #include "ardour/process_thread.h"
46 #include "ardour/scene_changer.h"
47 #include "ardour/session.h"
48 #include "ardour/transport_master.h"
49 #include "ardour/transport_master_manager.h"
50 #include "ardour/ticker.h"
51 #include "ardour/types.h"
52 #include "ardour/vca.h"
53 #include "ardour/vca_manager.h"
55 #include "midi++/mmc.h"
59 using namespace ARDOUR;
64 namespace msm = boost::msm;
65 namespace mpl = boost::mpl;
67 namespace TransportState
73 /* front-end: define the FSM structure */
74 struct TransportFSM : public msm::front::state_machine_def<TransportFSM>
78 struct Stopped : public msm::front::state<>
80 template <class Event,class FSM> void
81 on_entry (Event const&, FSM&)
83 std::cout << "entering: Stopped" << std::endl;
85 template <class Event,class FSM> void
86 on_exit (Event const&, FSM&)
88 std::cout << "leaving: Stopped" << std::endl;
92 struct Playing : public msm::front::state<>
94 template <class Event,class FSM> void
95 on_entry (Event const&, FSM&)
97 std::cout << "entering: Playing" << std::endl;
100 template <class Event,class FSM> void
101 on_exit (Event const&, FSM&)
103 std::cout << "leaving: Playing" << std::endl;
107 /* the initial state */
108 typedef Stopped initial_state;
110 /* transition actions */
111 void start_playback (play const&)
113 std::cout << "player::start_playback\n";
116 void stop_playback (stop const&)
118 std::cout << "player::stop_playback\n";
121 typedef TransportFSM _t; // makes transition table cleaner
123 struct transition_table : mpl::vector<
124 // Start Event Next Action Guard
125 // +---------+-------------+---------+---------------------+----------------------+
126 a_row < Stopped , play , Playing , &_t::start_playback >,
127 _row < Stopped , stop , Stopped >,
128 // +---------+-------------+---------+---------------------+----------------------+
129 a_row < Playing , stop , Stopped , &_t::stop_playback >
130 // +---------+-------------+---------+---------------------+----------------------+
134 typedef msm::back::state_machine<TransportFSM> transport_fsm;
140 t.process_event (play());
141 t.process_event (stop());
147 /** Called by the audio engine when there is work to be done with JACK.
148 * @param nframes Number of samples to process.
152 Session::process (pframes_t nframes)
154 samplepos_t transport_at_start = _transport_sample;
158 if (processing_blocked()) {
163 if (non_realtime_work_pending()) {
164 if (!_butler->transport_work_requested ()) {
169 _engine.main_thread()->get_buffers ();
171 (this->*process_function) (nframes);
173 /* realtime-safe meter-position and processor-order changes
175 * ideally this would be done in
176 * Route::process_output_buffers() but various functions
177 * callig it hold a _processor_lock reader-lock
179 boost::shared_ptr<RouteList> r = routes.reader ();
180 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
181 if ((*i)->apply_processor_changes_rt()) {
182 _rt_emit_pending = true;
185 if (_rt_emit_pending) {
186 if (!_rt_thread_active) {
187 emit_route_signals ();
189 if (pthread_mutex_trylock (&_rt_emit_mutex) == 0) {
190 pthread_cond_signal (&_rt_emit_cond);
191 pthread_mutex_unlock (&_rt_emit_mutex);
192 _rt_emit_pending = false;
196 _engine.main_thread()->drop_buffers ();
198 /* deliver MIDI clock. Note that we need to use the transport sample
199 * position at the start of process(), not the value at the end of
200 * it. We may already have ticked() because of a transport state
201 * change, for example.
205 if (!_silent && !_engine.freewheeling() && Config->get_send_midi_clock() && (transport_speed() == 1.0f || transport_speed() == 0.0f) && midi_clock->has_midi_port()) {
206 midi_clock->tick (transport_at_start, nframes);
209 _scene_changer->run (transport_at_start, transport_at_start + nframes);
212 /* don't bother with a message */
215 SendFeedback (); /* EMIT SIGNAL */
219 Session::fail_roll (pframes_t nframes)
221 return no_roll (nframes);
225 Session::no_roll (pframes_t nframes)
229 samplepos_t end_sample = _transport_sample + nframes; // FIXME: varispeed + no_roll ??
231 boost::shared_ptr<RouteList> r = routes.reader ();
234 _click_io->silence (nframes);
237 ltc_tx_send_time_code_for_cycle (_transport_sample, end_sample, _target_transport_speed, _transport_speed, nframes);
239 VCAList v = _vca_manager->vcas ();
240 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
241 (*i)->automation_run (_transport_sample, nframes);
244 if (_process_graph) {
245 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
246 _process_graph->routes_no_roll( nframes, _transport_sample, end_sample, non_realtime_work_pending());
248 PT_TIMING_CHECK (10);
249 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
251 if ((*i)->is_auditioner()) {
255 if ((*i)->no_roll (nframes, _transport_sample, end_sample, non_realtime_work_pending())) {
256 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
261 PT_TIMING_CHECK (11);
268 /** @param need_butler to be set to true by this method if it needs the butler,
269 * otherwise it must be left alone.
272 Session::process_routes (pframes_t nframes, bool& need_butler)
274 boost::shared_ptr<RouteList> r = routes.reader ();
276 const samplepos_t start_sample = _transport_sample;
277 const samplepos_t end_sample = _transport_sample + floor (nframes * _transport_speed);
279 VCAList v = _vca_manager->vcas ();
280 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
281 (*i)->automation_run (start_sample, nframes);
284 _global_locate_pending = locate_pending ();
286 if (_process_graph) {
287 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
288 if (_process_graph->process_routes (nframes, start_sample, end_sample, need_butler) < 0) {
294 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
298 if ((*i)->is_auditioner()) {
304 if ((ret = (*i)->roll (nframes, start_sample, end_sample, b)) < 0) {
310 DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 rolled and needs butler\n", (*i)->name()));
320 Session::get_track_statistics ()
325 boost::shared_ptr<RouteList> rl = routes.reader();
326 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
328 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
330 if (!tr || tr->is_private_route()) {
334 pworst = min (pworst, tr->playback_buffer_load());
335 cworst = min (cworst, tr->capture_buffer_load());
338 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
339 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
341 if (actively_recording()) {
347 Session::compute_audible_delta (samplepos_t& pos_and_delta) const
349 if (_transport_speed == 0.0 || _count_in_samples > 0 || _remaining_latency_preroll > 0) {
350 /* cannot compute audible delta, because the session is
351 generating silence that does not correspond to the timeline,
352 but is instead filling playback buffers to manage latency
355 DEBUG_TRACE (DEBUG::Slave, string_compose ("still adjusting for latency (%1) and/or count-in (%2) or stopped %1\n", _remaining_latency_preroll, _count_in_samples, _transport_speed));
359 pos_and_delta -= _transport_sample;
363 /** Process callback used when the auditioner is not active */
365 Session::process_with_events (pframes_t nframes)
370 pframes_t this_nframes;
371 samplepos_t end_sample;
372 bool session_needs_butler = false;
373 samplecnt_t samples_moved;
375 /* make sure the auditioner is silent */
378 auditioner->silence (nframes);
381 /* handle any pending events */
383 while (pending_events.read (&ev, 1) == 1) {
387 /* if we are not in the middle of a state change,
388 and there are immediate events queued up,
392 while (!non_realtime_work_pending() && !immediate_events.empty()) {
393 SessionEvent *ev = immediate_events.front ();
394 immediate_events.pop_front ();
397 /* only count-in when going to roll at speed 1.0 */
398 if (_transport_speed != 1.0 && _count_in_samples > 0) {
399 _count_in_samples = 0;
401 if (_transport_speed == 0.0) {
402 _remaining_latency_preroll = 0;
405 assert (_count_in_samples == 0 || _remaining_latency_preroll == 0 || _count_in_samples == _remaining_latency_preroll);
407 DEBUG_TRACE (DEBUG::Transport, string_compose ("Running count in/latency preroll of %1 & %2\n", _count_in_samples, _remaining_latency_preroll));
409 while (_count_in_samples > 0 || _remaining_latency_preroll > 0) {
412 if (_remaining_latency_preroll > 0) {
413 ns = std::min ((samplecnt_t)nframes, _remaining_latency_preroll);
415 ns = std::min ((samplecnt_t)nframes, _count_in_samples);
418 boost::shared_ptr<RouteList> r = routes.reader ();
419 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
420 samplecnt_t route_offset = (*i)->playback_latency ();
421 if (_remaining_latency_preroll > route_offset + ns) {
422 /* route will no-roll for complete pre-roll cycle */
425 if (_remaining_latency_preroll > route_offset) {
426 /* route may need partial no-roll and partial roll from
427 * (_transport_sample - _remaining_latency_preroll) .. +ns.
428 * shorten and split the cycle.
430 ns = std::min (ns, (_remaining_latency_preroll - route_offset));
434 if (_count_in_samples > 0) {
435 run_click (_transport_sample - _count_in_samples, ns);
436 assert (_count_in_samples >= ns);
437 _count_in_samples -= ns;
440 if (_remaining_latency_preroll > 0) {
441 if (_count_in_samples == 0) {
442 click (_transport_sample - _remaining_latency_preroll, ns);
444 if (process_routes (ns, session_needs_butler)) {
451 if (_remaining_latency_preroll > 0) {
452 assert (_remaining_latency_preroll >= ns);
453 _remaining_latency_preroll -= ns;
458 /* process events.. */
459 if (!events.empty() && next_event != events.end()) {
460 SessionEvent* this_event = *next_event;
461 Events::iterator the_next_one = next_event;
464 while (this_event && this_event->action_sample == _transport_sample) {
465 process_event (this_event);
466 if (the_next_one == events.end()) {
469 this_event = *the_next_one;
479 _engine.split_cycle (ns);
483 /* Decide on what to do with quarter-frame MTC during this cycle */
485 bool const was_sending_qf_mtc = _send_qf_mtc;
486 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
488 if (_transport_speed != 0) {
490 Config->get_send_mtc () &&
491 _transport_speed >= (1 - tolerance) &&
492 _transport_speed <= (1 + tolerance)
495 if (_send_qf_mtc && !was_sending_qf_mtc) {
496 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
497 _send_timecode_update = true;
500 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (sample_rate () / 4)) {
501 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
502 a quarter of a second since we sent anything at all, so send a full MTC update
505 _send_timecode_update = true;
508 _pframes_since_last_mtc += nframes;
511 /* Events caused a transport change (or we re-started sending
512 * MTC), so send an MTC Full Frame (Timecode) message. This
513 * is sent whether rolling or not, to give slaves an idea of
514 * ardour time on locates (and allow slow slaves to position
515 * and prepare for rolling)
517 if (_send_timecode_update) {
518 send_full_time_code (_transport_sample, nframes);
521 if (!process_can_proceed()) {
526 if (events.empty() || next_event == events.end()) {
527 try_run_lua (nframes); // also during export ?? ->move to process_without_events()
528 /* lua scripts may inject events */
529 while (_n_lua_scripts > 0 && pending_events.read (&ev, 1) == 1) {
532 if (events.empty() || next_event == events.end()) {
533 process_without_events (nframes);
538 assert (_transport_speed == 0 || _transport_speed == 1.0 || _transport_speed == -1.0);
540 samples_moved = (samplecnt_t) nframes * _transport_speed;
541 DEBUG_TRACE (DEBUG::Transport, string_compose ("plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
543 end_sample = _transport_sample + samples_moved;
546 SessionEvent* this_event;
547 Events::iterator the_next_one;
549 if (!process_can_proceed()) {
554 if (!_exporting && config.get_external_sync()) {
555 if (!follow_transport_master (nframes)) {
556 ltc_tx_send_time_code_for_cycle (_transport_sample, end_sample, _target_transport_speed, _transport_speed, nframes);
561 if (_transport_speed == 0) {
566 if (!_exporting && !timecode_transmission_suspended()) {
567 send_midi_time_code_for_cycle (_transport_sample, end_sample, nframes);
570 ltc_tx_send_time_code_for_cycle (_transport_sample, end_sample, _target_transport_speed, _transport_speed, nframes);
572 samplepos_t stop_limit = compute_stop_limit ();
574 if (maybe_stop (stop_limit)) {
579 this_event = *next_event;
580 the_next_one = next_event;
583 /* yes folks, here it is, the actual loop where we really truly
589 this_nframes = nframes; /* real (jack) time relative */
590 samples_moved = (samplecnt_t) floor (_transport_speed * nframes); /* transport relative */
591 DEBUG_TRACE (DEBUG::Transport, string_compose ("sub-loop plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
593 /* running an event, position transport precisely to its time */
594 if (this_event && this_event->action_sample <= end_sample && this_event->action_sample >= _transport_sample) {
595 /* this isn't quite right for reverse play */
596 samples_moved = (samplecnt_t) (this_event->action_sample - _transport_sample);
597 DEBUG_TRACE (DEBUG::Transport, string_compose ("sub-loop2 plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
598 this_nframes = abs (floor(samples_moved / _transport_speed));
601 try_run_lua (this_nframes);
605 click (_transport_sample, this_nframes);
607 if (process_routes (this_nframes, session_needs_butler)) {
612 get_track_statistics ();
614 nframes -= this_nframes;
616 if (samples_moved < 0) {
617 decrement_transport_position (-samples_moved);
618 DEBUG_TRACE (DEBUG::Transport, string_compose ("DEcrement transport by %1 to %2\n", samples_moved, _transport_sample));
619 } else if (samples_moved) {
620 increment_transport_position (samples_moved);
621 DEBUG_TRACE (DEBUG::Transport, string_compose ("INcrement transport by %1 to %2\n", samples_moved, _transport_sample));
623 DEBUG_TRACE (DEBUG::Transport, "no transport motion\n");
626 maybe_stop (stop_limit);
630 _engine.split_cycle (this_nframes);
633 /* now handle this event and all others scheduled for the same time */
635 while (this_event && this_event->action_sample == _transport_sample) {
636 process_event (this_event);
638 if (the_next_one == events.end()) {
641 this_event = *the_next_one;
646 /* if an event left our state changing, do the right thing */
648 if (nframes && non_realtime_work_pending()) {
653 /* this is necessary to handle the case of seamless looping */
654 end_sample = _transport_sample + floor (nframes * _transport_speed);
659 } /* implicit release of route lock */
661 if (session_needs_butler) {
662 DEBUG_TRACE (DEBUG::Butler, "p-with-events: session needs butler, call it\n");
668 Session::transport_locked () const
670 if (!locate_pending() && (!config.get_external_sync() || (transport_master()->ok() && transport_master()->locked()))) {
678 Session::process_without_events (pframes_t nframes)
680 bool session_needs_butler = false;
681 samplecnt_t samples_moved;
683 if (!process_can_proceed()) {
688 if (!_exporting && config.get_external_sync()) {
689 if (!follow_transport_master (nframes)) {
690 ltc_tx_send_time_code_for_cycle (_transport_sample, _transport_sample, 0, 0 , nframes);
695 assert (_transport_speed == 0 || _transport_speed == 1.0 || _transport_speed == -1.0);
697 if (_transport_speed == 0) {
701 samples_moved = (samplecnt_t) nframes * _transport_speed;
702 DEBUG_TRACE (DEBUG::Transport, string_compose ("no-events, plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
705 if (!_exporting && !timecode_transmission_suspended()) {
706 send_midi_time_code_for_cycle (_transport_sample, _transport_sample + samples_moved, nframes);
709 ltc_tx_send_time_code_for_cycle (_transport_sample, _transport_sample + samples_moved, _target_transport_speed, _transport_speed, nframes);
711 samplepos_t const stop_limit = compute_stop_limit ();
713 if (maybe_stop (stop_limit)) {
718 if (maybe_sync_start (nframes)) {
722 click (_transport_sample, nframes);
724 if (process_routes (nframes, session_needs_butler)) {
729 get_track_statistics ();
731 if (samples_moved < 0) {
732 decrement_transport_position (-samples_moved);
733 DEBUG_TRACE (DEBUG::Transport, string_compose ("DEcrement transport by %1 to %2\n", samples_moved, _transport_sample));
734 } else if (samples_moved) {
735 increment_transport_position (samples_moved);
736 DEBUG_TRACE (DEBUG::Transport, string_compose ("INcrement transport by %1 to %2\n", samples_moved, _transport_sample));
738 DEBUG_TRACE (DEBUG::Transport, "no transport motion\n");
741 maybe_stop (stop_limit);
743 if (session_needs_butler) {
744 DEBUG_TRACE (DEBUG::Butler, "p-without-events: session needs butler, call it\n");
749 /** Process callback used when the auditioner is active.
750 * @param nframes number of samples to process.
753 Session::process_audition (pframes_t nframes)
756 boost::shared_ptr<RouteList> r = routes.reader ();
758 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
759 if (!(*i)->is_auditioner()) {
760 (*i)->silence (nframes);
764 /* run the auditioner, and if it says we need butler service, ask for it */
766 if (auditioner->play_audition (nframes) > 0) {
767 DEBUG_TRACE (DEBUG::Butler, "auditioner needs butler, call it\n");
771 /* if using a monitor section, run it because otherwise we don't hear anything */
773 if (_monitor_out && auditioner->needs_monitor()) {
774 _monitor_out->monitor_run (_transport_sample, _transport_sample + nframes, nframes);
777 /* handle pending events */
779 while (pending_events.read (&ev, 1) == 1) {
783 /* if we are not in the middle of a state change,
784 and there are immediate events queued up,
788 while (!non_realtime_work_pending() && !immediate_events.empty()) {
789 SessionEvent *ev = immediate_events.front ();
790 immediate_events.pop_front ();
794 if (!auditioner->auditioning()) {
795 /* auditioner no longer active, so go back to the normal process callback */
796 process_function = &Session::process_with_events;
801 Session::maybe_sync_start (pframes_t & nframes)
803 pframes_t sync_offset;
805 if (!waiting_for_sync_offset) {
809 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
811 /* generate silence up to the sync point, then
812 adjust nframes + offset to reflect whatever
816 no_roll (sync_offset);
817 nframes -= sync_offset;
818 Port::increment_global_port_buffer_offset (sync_offset);
819 waiting_for_sync_offset = false;
822 return true; // done, nothing left to process
827 /* sync offset point is not within this process()
828 cycle, so just generate silence. and don't bother
829 with any fancy stuff here, just the minimal silence.
834 if (Config->get_locate_while_waiting_for_sync()) {
835 DEBUG_TRACE (DEBUG::Transport, "micro-locate while waiting for sync\n");
836 if (micro_locate (nframes)) {
837 /* XXX ERROR !!! XXX */
841 return true; // done, nothing left to process
848 Session::queue_event (SessionEvent* ev)
850 if (deletion_in_progress ()) {
852 } else if (loading ()) {
855 Glib::Threads::Mutex::Lock lm (rb_write_lock);
856 pending_events.write (&ev, 1);
861 Session::set_next_event ()
863 if (events.empty()) {
864 next_event = events.end();
868 if (next_event == events.end()) {
869 next_event = events.begin();
872 if ((*next_event)->action_sample > _transport_sample) {
873 next_event = events.begin();
876 for (; next_event != events.end(); ++next_event) {
877 if ((*next_event)->action_sample >= _transport_sample) {
884 Session::process_event (SessionEvent* ev)
889 /* if we're in the middle of a state change (i.e. waiting
890 for the butler thread to complete the non-realtime
891 part of the change), we'll just have to queue this
892 event for a time when the change is complete.
895 if (non_realtime_work_pending()) {
897 /* except locates, which we have the capability to handle */
899 if (ev->type != SessionEvent::Locate) {
900 immediate_events.insert (immediate_events.end(), ev);
906 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_sample));
909 case SessionEvent::SetLoop:
910 set_play_loop (ev->yes_or_no, ev->speed);
913 case SessionEvent::AutoLoop:
915 /* roll after locate, do not flush, set "with loop"
916 true only if we are seamless looping
918 start_locate (ev->target_sample, true, false, Config->get_seamless_loop());
924 case SessionEvent::Locate:
925 if (ev->yes_or_no) { /* force locate */
926 /* args: do not roll after locate, do flush, not with loop */
927 locate (ev->target_sample, false, true, false);
929 /* args: do not roll after locate, do flush, not with loop */
930 start_locate (ev->target_sample, false, true, false);
932 _send_timecode_update = true;
935 case SessionEvent::LocateRoll:
937 /* args: roll after locate, do flush, not with loop */
938 locate (ev->target_sample, true, true, false);
940 /* args: roll after locate, do flush, not with loop */
941 start_locate (ev->target_sample, true, true, false);
943 _send_timecode_update = true;
946 case SessionEvent::Skip:
947 if (Config->get_skip_playback()) {
948 start_locate (ev->target_sample, true, true, false);
949 _send_timecode_update = true;
955 case SessionEvent::LocateRollLocate:
956 // locate is handled by ::request_roll_at_and_return()
957 _requested_return_sample = ev->target_sample;
958 request_locate (ev->target2_sample, true);
962 case SessionEvent::SetTransportSpeed:
963 set_transport_speed (ev->speed, ev->target_sample, ev->yes_or_no, ev->second_yes_or_no, ev->third_yes_or_no);
966 case SessionEvent::SetTransportMaster:
967 TransportMasterManager::instance().set_current (ev->transport_master);
970 case SessionEvent::PunchIn:
971 // cerr << "PunchIN at " << transport_sample() << endl;
972 if (config.get_punch_in() && record_status() == Enabled) {
979 case SessionEvent::PunchOut:
980 // cerr << "PunchOUT at " << transport_sample() << endl;
981 if (config.get_punch_out()) {
982 step_back_from_record ();
988 case SessionEvent::StopOnce:
989 if (!non_realtime_work_pending()) {
990 _clear_event_type (SessionEvent::StopOnce);
991 stop_transport (ev->yes_or_no);
997 case SessionEvent::RangeStop:
998 if (!non_realtime_work_pending()) {
999 stop_transport (ev->yes_or_no);
1005 case SessionEvent::RangeLocate:
1006 /* args: roll after locate, do flush, not with loop */
1007 start_locate (ev->target_sample, true, true, false);
1012 case SessionEvent::Overwrite:
1013 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1016 case SessionEvent::Audition:
1017 set_audition (ev->region);
1018 // drop reference to region
1019 ev->region.reset ();
1022 case SessionEvent::SetPlayAudioRange:
1023 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1026 case SessionEvent::CancelPlayAudioRange:
1030 case SessionEvent::RealTimeOperation:
1032 del = false; // other side of RT request needs to clean up
1035 case SessionEvent::AdjustPlaybackBuffering:
1036 schedule_playback_buffering_adjustment ();
1039 case SessionEvent::AdjustCaptureBuffering:
1040 schedule_capture_buffering_adjustment ();
1043 case SessionEvent::SetTimecodeTransmission:
1044 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1048 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1049 abort(); /*NOTREACHED*/
1054 del = del && !_remove_event (ev);
1063 Session::compute_stop_limit () const
1065 if (!Config->get_stop_at_session_end ()) {
1066 return max_samplepos;
1069 if (config.get_external_sync()) {
1070 return max_samplepos;
1073 bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1074 bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1076 if (actively_recording ()) {
1077 /* permanently recording */
1078 return max_samplepos;
1079 } else if (punching_in && !punching_out) {
1080 /* punching in but never out */
1081 return max_samplepos;
1082 } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_sample()) {
1083 /* punching in and punching out after session end */
1084 return max_samplepos;
1087 return current_end_sample ();
1092 /* dedicated thread for signal emission.
1094 * while sending cross-thread signals from the process thread
1095 * is fine in general, PBD::Signal's use of boost::function and
1096 * boost:bind can produce a vast overhead which is not
1097 * acceptable for low latency.
1099 * This works around the issue by moving the boost overhead
1100 * out of the RT thread. The overall load is probably higher but
1101 * the realtime thread remains unaffected.
1105 Session::emit_route_signals ()
1107 // TODO use RAII to allow using these signals in other places
1108 BatchUpdateStart(); /* EMIT SIGNAL */
1109 boost::shared_ptr<RouteList> r = routes.reader ();
1110 for (RouteList::const_iterator ci = r->begin(); ci != r->end(); ++ci) {
1111 (*ci)->emit_pending_signals ();
1113 BatchUpdateEnd(); /* EMIT SIGNAL */
1117 Session::emit_thread_start ()
1119 if (_rt_thread_active) {
1122 _rt_thread_active = true;
1124 if (pthread_create (&_rt_emit_thread, NULL, emit_thread, this)) {
1125 _rt_thread_active = false;
1130 Session::emit_thread_terminate ()
1132 if (!_rt_thread_active) {
1135 _rt_thread_active = false;
1137 if (pthread_mutex_lock (&_rt_emit_mutex) == 0) {
1138 pthread_cond_signal (&_rt_emit_cond);
1139 pthread_mutex_unlock (&_rt_emit_mutex);
1143 pthread_join (_rt_emit_thread, &status);
1147 Session::emit_thread (void *arg)
1149 Session *s = static_cast<Session *>(arg);
1150 s->emit_thread_run ();
1156 Session::emit_thread_run ()
1158 pthread_mutex_lock (&_rt_emit_mutex);
1159 while (_rt_thread_active) {
1160 emit_route_signals();
1161 pthread_cond_wait (&_rt_emit_cond, &_rt_emit_mutex);
1163 pthread_mutex_unlock (&_rt_emit_mutex);
1167 Session::follow_transport_master (pframes_t nframes)
1169 TransportMasterManager& tmm (TransportMasterManager::instance());
1172 samplepos_t slave_transport_sample;
1173 sampleoffset_t delta;
1175 if (tmm.master_invalid_this_cycle()) {
1176 DEBUG_TRACE (DEBUG::Slave, "session told not to use the transport master this cycle\n");
1180 slave_speed = tmm.get_current_speed_in_process_context();
1181 slave_transport_sample = tmm.get_current_position_in_process_context ();
1183 track_transport_master (slave_speed, slave_transport_sample);
1185 /* transport sample may have been moved during ::track_transport_master() */
1187 delta = _transport_sample - slave_transport_sample;
1189 DEBUG_TRACE (DEBUG::Slave, string_compose ("session at %1, master at %2, delta: %3 res: %4\n", _transport_sample, slave_transport_sample, delta, tmm.current()->resolution()));
1191 if (transport_master_tracking_state == Running) {
1193 if (!actively_recording() && abs (delta) > tmm.current()->resolution()) {
1194 DEBUG_TRACE (DEBUG::Slave, string_compose ("current slave delta %1 greater than slave resolution %2\n", delta, tmm.current()->resolution()));
1195 if (micro_locate (-delta) != 0) {
1196 DEBUG_TRACE (DEBUG::Slave, "micro-locate didn't work, set no disk output true\n");
1198 /* run routes as normal, but no disk output */
1199 DiskReader::set_no_disk_output (true);
1204 if (transport_master_tracking_state == Running) {
1205 /* speed is set, we're locked, and good to go */
1206 DiskReader::set_no_disk_output (false);
1212 /* don't move at all */
1213 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
1219 Session::track_transport_master (float slave_speed, samplepos_t slave_transport_sample)
1221 boost::shared_ptr<TransportMaster> master (TransportMasterManager::instance().current());
1225 DEBUG_TRACE (DEBUG::Slave, string_compose ("session has master tracking state as %1\n", transport_master_tracking_state));
1227 if (slave_speed != 0.0f) {
1229 /* slave is running */
1231 switch (transport_master_tracking_state) {
1233 master_wait_end = slave_transport_sample + worst_latency_preroll() + master->seekahead_distance ();
1234 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1, now WAITING\n", master_wait_end));
1235 /* we can call locate() here because we are in process context */
1236 if (micro_locate (master_wait_end - _transport_sample) != 0) {
1237 locate (master_wait_end, false, false);
1239 transport_master_tracking_state = Waiting;
1246 if (transport_master_tracking_state == Waiting) {
1248 DEBUG_TRACE (DEBUG::Slave, string_compose ("master currently at %1, waiting to pass %2\n", slave_transport_sample, master_wait_end));
1250 if (slave_transport_sample >= master_wait_end) {
1252 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_sample, _transport_sample));
1254 transport_master_tracking_state = Running;
1256 /* now perform a "micro-seek" within the disk buffers to realign ourselves
1257 precisely with the master.
1260 if (micro_locate (slave_transport_sample - _transport_sample) != 0) {
1261 cerr << "cannot micro-seek\n";
1267 if (transport_master_tracking_state == Running && _transport_speed == 0.0f) {
1268 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
1272 } else { // slave_speed is 0
1274 /* slave has stopped */
1276 if (_transport_speed != 0.0f) {
1277 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 sample %2 tf %3\n", slave_speed, slave_transport_sample, _transport_sample));
1281 if (slave_transport_sample != _transport_sample) {
1282 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_sample));
1283 force_locate (slave_transport_sample, false);
1286 reset_slave_state();
1291 Session::reset_slave_state ()
1293 transport_master_tracking_state = Stopped;
1294 DiskReader::set_no_disk_output (false);