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 <boost/msm/back/state_machine.hpp>
26 #include <boost/msm/front/state_machine_def.hpp>
28 #include "pbd/error.h"
29 #include "pbd/enumwriter.h"
31 #include <glibmm/threads.h>
33 #include "ardour/audioengine.h"
34 #include "ardour/auditioner.h"
35 #include "ardour/butler.h"
36 #include "ardour/cycle_timer.h"
37 #include "ardour/debug.h"
38 #include "ardour/disk_reader.h"
39 #include "ardour/graph.h"
40 #include "ardour/port.h"
41 #include "ardour/process_thread.h"
42 #include "ardour/scene_changer.h"
43 #include "ardour/session.h"
44 #include "ardour/transport_master.h"
45 #include "ardour/transport_master_manager.h"
46 #include "ardour/ticker.h"
47 #include "ardour/types.h"
48 #include "ardour/vca.h"
49 #include "ardour/vca_manager.h"
51 #include "midi++/mmc.h"
55 using namespace ARDOUR;
60 namespace msm = boost::msm;
61 namespace mpl = boost::mpl;
63 namespace TransportState
69 /* front-end: define the FSM structure */
70 struct TransportFSM : public msm::front::state_machine_def<TransportFSM>
74 struct Stopped : public msm::front::state<>
76 template <class Event,class FSM> void
77 on_entry (Event const&, FSM&)
79 std::cout << "entering: Stopped" << std::endl;
81 template <class Event,class FSM> void
82 on_exit (Event const&, FSM&)
84 std::cout << "leaving: Stopped" << std::endl;
88 struct Playing : public msm::front::state<>
90 template <class Event,class FSM> void
91 on_entry (Event const&, FSM&)
93 std::cout << "entering: Playing" << std::endl;
96 template <class Event,class FSM> void
97 on_exit (Event const&, FSM&)
99 std::cout << "leaving: Playing" << std::endl;
103 /* the initial state */
104 typedef Stopped initial_state;
106 /* transition actions */
107 void start_playback (play const&)
109 std::cout << "player::start_playback\n";
112 void stop_playback (stop const&)
114 std::cout << "player::stop_playback\n";
117 typedef TransportFSM _t; // makes transition table cleaner
119 struct transition_table : mpl::vector<
120 // Start Event Next Action Guard
121 // +---------+-------------+---------+---------------------+----------------------+
122 a_row < Stopped , play , Playing , &_t::start_playback >,
123 _row < Stopped , stop , Stopped >,
124 // +---------+-------------+---------+---------------------+----------------------+
125 a_row < Playing , stop , Stopped , &_t::stop_playback >
126 // +---------+-------------+---------+---------------------+----------------------+
130 typedef msm::back::state_machine<TransportFSM> transport_fsm;
136 t.process_event (play());
137 t.process_event (stop());
143 /** Called by the audio engine when there is work to be done with JACK.
144 * @param nframes Number of samples to process.
148 Session::process (pframes_t nframes)
150 samplepos_t transport_at_start = _transport_sample;
154 if (processing_blocked()) {
159 if (non_realtime_work_pending()) {
160 if (!_butler->transport_work_requested ()) {
165 _engine.main_thread()->get_buffers ();
167 (this->*process_function) (nframes);
169 /* realtime-safe meter-position and processor-order changes
171 * ideally this would be done in
172 * Route::process_output_buffers() but various functions
173 * callig it hold a _processor_lock reader-lock
175 boost::shared_ptr<RouteList> r = routes.reader ();
176 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
177 if ((*i)->apply_processor_changes_rt()) {
178 _rt_emit_pending = true;
181 if (_rt_emit_pending) {
182 if (!_rt_thread_active) {
183 emit_route_signals ();
185 if (pthread_mutex_trylock (&_rt_emit_mutex) == 0) {
186 pthread_cond_signal (&_rt_emit_cond);
187 pthread_mutex_unlock (&_rt_emit_mutex);
188 _rt_emit_pending = false;
192 _engine.main_thread()->drop_buffers ();
194 /* deliver MIDI clock. Note that we need to use the transport sample
195 * position at the start of process(), not the value at the end of
196 * it. We may already have ticked() because of a transport state
197 * change, for example.
201 if (!_silent && !_engine.freewheeling() && Config->get_send_midi_clock() && (transport_speed() == 1.0f || transport_speed() == 0.0f) && midi_clock->has_midi_port()) {
202 midi_clock->tick (transport_at_start, nframes);
205 _scene_changer->run (transport_at_start, transport_at_start + nframes);
208 /* don't bother with a message */
211 SendFeedback (); /* EMIT SIGNAL */
215 Session::fail_roll (pframes_t nframes)
217 return no_roll (nframes);
221 Session::no_roll (pframes_t nframes)
225 samplepos_t end_sample = _transport_sample + nframes; // FIXME: varispeed + no_roll ??
227 boost::shared_ptr<RouteList> r = routes.reader ();
230 _click_io->silence (nframes);
233 ltc_tx_send_time_code_for_cycle (_transport_sample, end_sample, _target_transport_speed, _transport_speed, nframes);
235 VCAList v = _vca_manager->vcas ();
236 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
237 (*i)->automation_run (_transport_sample, nframes);
240 if (_process_graph) {
241 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
242 _process_graph->routes_no_roll( nframes, _transport_sample, end_sample, non_realtime_work_pending());
244 PT_TIMING_CHECK (10);
245 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
247 if ((*i)->is_auditioner()) {
251 if ((*i)->no_roll (nframes, _transport_sample, end_sample, non_realtime_work_pending())) {
252 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
257 PT_TIMING_CHECK (11);
264 /** @param need_butler to be set to true by this method if it needs the butler,
265 * otherwise it must be left alone.
268 Session::process_routes (pframes_t nframes, bool& need_butler)
270 boost::shared_ptr<RouteList> r = routes.reader ();
272 const samplepos_t start_sample = _transport_sample;
273 const samplepos_t end_sample = _transport_sample + floor (nframes * _transport_speed);
275 VCAList v = _vca_manager->vcas ();
276 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
277 (*i)->automation_run (start_sample, nframes);
280 _global_locate_pending = locate_pending ();
282 if (_process_graph) {
283 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
284 if (_process_graph->process_routes (nframes, start_sample, end_sample, need_butler) < 0) {
290 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
294 if ((*i)->is_auditioner()) {
300 if ((ret = (*i)->roll (nframes, start_sample, end_sample, b)) < 0) {
306 DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 rolled and needs butler\n", (*i)->name()));
316 Session::get_track_statistics ()
321 boost::shared_ptr<RouteList> rl = routes.reader();
322 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
324 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
326 if (!tr || tr->is_private_route()) {
330 pworst = min (pworst, tr->playback_buffer_load());
331 cworst = min (cworst, tr->capture_buffer_load());
334 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
335 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
337 if (actively_recording()) {
343 Session::compute_audible_delta (samplepos_t& pos_and_delta) const
345 if (_transport_speed == 0.0 || _count_in_samples > 0 || _remaining_latency_preroll > 0) {
346 /* cannot compute audible delta, because the session is
347 generating silence that does not correspond to the timeline,
348 but is instead filling playback buffers to manage latency
351 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));
355 pos_and_delta -= _transport_sample;
359 /** Process callback used when the auditioner is not active */
361 Session::process_with_events (pframes_t nframes)
366 pframes_t this_nframes;
367 samplepos_t end_sample;
368 bool session_needs_butler = false;
369 samplecnt_t samples_moved;
371 /* make sure the auditioner is silent */
374 auditioner->silence (nframes);
377 /* handle any pending events */
379 while (pending_events.read (&ev, 1) == 1) {
383 /* if we are not in the middle of a state change,
384 and there are immediate events queued up,
388 while (!non_realtime_work_pending() && !immediate_events.empty()) {
389 SessionEvent *ev = immediate_events.front ();
390 immediate_events.pop_front ();
393 /* only count-in when going to roll at speed 1.0 */
394 if (_transport_speed != 1.0 && _count_in_samples > 0) {
395 _count_in_samples = 0;
397 if (_transport_speed == 0.0) {
398 _remaining_latency_preroll = 0;
401 assert (_count_in_samples == 0 || _remaining_latency_preroll == 0 || _count_in_samples == _remaining_latency_preroll);
403 DEBUG_TRACE (DEBUG::Transport, string_compose ("Running count in/latency preroll of %1 & %2\n", _count_in_samples, _remaining_latency_preroll));
405 while (_count_in_samples > 0 || _remaining_latency_preroll > 0) {
408 if (_remaining_latency_preroll > 0) {
409 ns = std::min ((samplecnt_t)nframes, _remaining_latency_preroll);
411 ns = std::min ((samplecnt_t)nframes, _count_in_samples);
414 boost::shared_ptr<RouteList> r = routes.reader ();
415 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
416 samplecnt_t route_offset = (*i)->playback_latency ();
417 if (_remaining_latency_preroll > route_offset + ns) {
418 /* route will no-roll for complete pre-roll cycle */
421 if (_remaining_latency_preroll > route_offset) {
422 /* route may need partial no-roll and partial roll from
423 * (_transport_sample - _remaining_latency_preroll) .. +ns.
424 * shorten and split the cycle.
426 ns = std::min (ns, (_remaining_latency_preroll - route_offset));
430 if (_count_in_samples > 0) {
431 run_click (_transport_sample - _count_in_samples, ns);
432 assert (_count_in_samples >= ns);
433 _count_in_samples -= ns;
436 if (_remaining_latency_preroll > 0) {
437 if (_count_in_samples == 0) {
438 click (_transport_sample - _remaining_latency_preroll, ns);
440 if (process_routes (ns, session_needs_butler)) {
447 if (_remaining_latency_preroll > 0) {
448 assert (_remaining_latency_preroll >= ns);
449 _remaining_latency_preroll -= ns;
454 /* process events.. */
455 if (!events.empty() && next_event != events.end()) {
456 SessionEvent* this_event = *next_event;
457 Events::iterator the_next_one = next_event;
460 while (this_event && this_event->action_sample == _transport_sample) {
461 process_event (this_event);
462 if (the_next_one == events.end()) {
465 this_event = *the_next_one;
475 _engine.split_cycle (ns);
479 /* Decide on what to do with quarter-frame MTC during this cycle */
481 bool const was_sending_qf_mtc = _send_qf_mtc;
482 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
484 if (_transport_speed != 0) {
486 Config->get_send_mtc () &&
487 _transport_speed >= (1 - tolerance) &&
488 _transport_speed <= (1 + tolerance)
491 if (_send_qf_mtc && !was_sending_qf_mtc) {
492 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
493 _send_timecode_update = true;
496 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (sample_rate () / 4)) {
497 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
498 a quarter of a second since we sent anything at all, so send a full MTC update
501 _send_timecode_update = true;
504 _pframes_since_last_mtc += nframes;
507 /* Events caused a transport change (or we re-started sending
508 * MTC), so send an MTC Full Frame (Timecode) message. This
509 * is sent whether rolling or not, to give slaves an idea of
510 * ardour time on locates (and allow slow slaves to position
511 * and prepare for rolling)
513 if (_send_timecode_update) {
514 send_full_time_code (_transport_sample, nframes);
517 if (!process_can_proceed()) {
522 if (events.empty() || next_event == events.end()) {
523 try_run_lua (nframes); // also during export ?? ->move to process_without_events()
524 /* lua scripts may inject events */
525 while (_n_lua_scripts > 0 && pending_events.read (&ev, 1) == 1) {
528 if (events.empty() || next_event == events.end()) {
529 process_without_events (nframes);
534 assert (_transport_speed == 0 || _transport_speed == 1.0 || _transport_speed == -1.0);
536 samples_moved = (samplecnt_t) nframes * _transport_speed;
537 DEBUG_TRACE (DEBUG::Transport, string_compose ("plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
539 end_sample = _transport_sample + samples_moved;
542 SessionEvent* this_event;
543 Events::iterator the_next_one;
545 if (!process_can_proceed()) {
550 if (!_exporting && config.get_external_sync()) {
551 if (!follow_transport_master (nframes)) {
552 ltc_tx_send_time_code_for_cycle (_transport_sample, end_sample, _target_transport_speed, _transport_speed, nframes);
557 if (_transport_speed == 0) {
562 if (!_exporting && !timecode_transmission_suspended()) {
563 send_midi_time_code_for_cycle (_transport_sample, end_sample, nframes);
566 ltc_tx_send_time_code_for_cycle (_transport_sample, end_sample, _target_transport_speed, _transport_speed, nframes);
568 samplepos_t stop_limit = compute_stop_limit ();
570 if (maybe_stop (stop_limit)) {
575 this_event = *next_event;
576 the_next_one = next_event;
579 /* yes folks, here it is, the actual loop where we really truly
585 this_nframes = nframes; /* real (jack) time relative */
586 samples_moved = (samplecnt_t) floor (_transport_speed * nframes); /* transport relative */
587 DEBUG_TRACE (DEBUG::Transport, string_compose ("sub-loop plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
589 /* running an event, position transport precisely to its time */
590 if (this_event && this_event->action_sample <= end_sample && this_event->action_sample >= _transport_sample) {
591 /* this isn't quite right for reverse play */
592 samples_moved = (samplecnt_t) (this_event->action_sample - _transport_sample);
593 DEBUG_TRACE (DEBUG::Transport, string_compose ("sub-loop2 plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
594 this_nframes = abs (floor(samples_moved / _transport_speed));
597 try_run_lua (this_nframes);
601 click (_transport_sample, this_nframes);
603 if (process_routes (this_nframes, session_needs_butler)) {
608 get_track_statistics ();
610 nframes -= this_nframes;
612 if (samples_moved < 0) {
613 decrement_transport_position (-samples_moved);
614 DEBUG_TRACE (DEBUG::Transport, string_compose ("DEcrement transport by %1 to %2\n", samples_moved, _transport_sample));
615 } else if (samples_moved) {
616 increment_transport_position (samples_moved);
617 DEBUG_TRACE (DEBUG::Transport, string_compose ("INcrement transport by %1 to %2\n", samples_moved, _transport_sample));
619 DEBUG_TRACE (DEBUG::Transport, "no transport motion\n");
622 maybe_stop (stop_limit);
626 _engine.split_cycle (this_nframes);
629 /* now handle this event and all others scheduled for the same time */
631 while (this_event && this_event->action_sample == _transport_sample) {
632 process_event (this_event);
634 if (the_next_one == events.end()) {
637 this_event = *the_next_one;
642 /* if an event left our state changing, do the right thing */
644 if (nframes && non_realtime_work_pending()) {
649 /* this is necessary to handle the case of seamless looping */
650 end_sample = _transport_sample + floor (nframes * _transport_speed);
655 } /* implicit release of route lock */
657 if (session_needs_butler) {
658 DEBUG_TRACE (DEBUG::Butler, "p-with-events: session needs butler, call it\n");
664 Session::transport_locked () const
666 if (!locate_pending() && (!config.get_external_sync() || (transport_master()->ok() && transport_master()->locked()))) {
674 Session::process_without_events (pframes_t nframes)
676 bool session_needs_butler = false;
677 samplecnt_t samples_moved;
679 if (!process_can_proceed()) {
684 if (!_exporting && config.get_external_sync()) {
685 if (!follow_transport_master (nframes)) {
686 ltc_tx_send_time_code_for_cycle (_transport_sample, _transport_sample, 0, 0 , nframes);
691 assert (_transport_speed == 0 || _transport_speed == 1.0 || _transport_speed == -1.0);
693 if (_transport_speed == 0) {
697 samples_moved = (samplecnt_t) nframes * _transport_speed;
698 DEBUG_TRACE (DEBUG::Transport, string_compose ("no-events, plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
701 if (!_exporting && !timecode_transmission_suspended()) {
702 send_midi_time_code_for_cycle (_transport_sample, _transport_sample + samples_moved, nframes);
705 ltc_tx_send_time_code_for_cycle (_transport_sample, _transport_sample + samples_moved, _target_transport_speed, _transport_speed, nframes);
707 samplepos_t const stop_limit = compute_stop_limit ();
709 if (maybe_stop (stop_limit)) {
714 if (maybe_sync_start (nframes)) {
718 click (_transport_sample, nframes);
720 if (process_routes (nframes, session_needs_butler)) {
725 get_track_statistics ();
727 if (samples_moved < 0) {
728 decrement_transport_position (-samples_moved);
729 DEBUG_TRACE (DEBUG::Transport, string_compose ("DEcrement transport by %1 to %2\n", samples_moved, _transport_sample));
730 } else if (samples_moved) {
731 increment_transport_position (samples_moved);
732 DEBUG_TRACE (DEBUG::Transport, string_compose ("INcrement transport by %1 to %2\n", samples_moved, _transport_sample));
734 DEBUG_TRACE (DEBUG::Transport, "no transport motion\n");
737 maybe_stop (stop_limit);
739 if (session_needs_butler) {
740 DEBUG_TRACE (DEBUG::Butler, "p-without-events: session needs butler, call it\n");
745 /** Process callback used when the auditioner is active.
746 * @param nframes number of samples to process.
749 Session::process_audition (pframes_t nframes)
752 boost::shared_ptr<RouteList> r = routes.reader ();
754 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
755 if (!(*i)->is_auditioner()) {
756 (*i)->silence (nframes);
760 /* run the auditioner, and if it says we need butler service, ask for it */
762 if (auditioner->play_audition (nframes) > 0) {
763 DEBUG_TRACE (DEBUG::Butler, "auditioner needs butler, call it\n");
767 /* if using a monitor section, run it because otherwise we don't hear anything */
769 if (_monitor_out && auditioner->needs_monitor()) {
770 _monitor_out->monitor_run (_transport_sample, _transport_sample + nframes, nframes);
773 /* handle pending events */
775 while (pending_events.read (&ev, 1) == 1) {
779 /* if we are not in the middle of a state change,
780 and there are immediate events queued up,
784 while (!non_realtime_work_pending() && !immediate_events.empty()) {
785 SessionEvent *ev = immediate_events.front ();
786 immediate_events.pop_front ();
790 if (!auditioner->auditioning()) {
791 /* auditioner no longer active, so go back to the normal process callback */
792 process_function = &Session::process_with_events;
797 Session::maybe_sync_start (pframes_t & nframes)
799 pframes_t sync_offset;
801 if (!waiting_for_sync_offset) {
805 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
807 /* generate silence up to the sync point, then
808 adjust nframes + offset to reflect whatever
812 no_roll (sync_offset);
813 nframes -= sync_offset;
814 Port::increment_global_port_buffer_offset (sync_offset);
815 waiting_for_sync_offset = false;
818 return true; // done, nothing left to process
823 /* sync offset point is not within this process()
824 cycle, so just generate silence. and don't bother
825 with any fancy stuff here, just the minimal silence.
830 if (Config->get_locate_while_waiting_for_sync()) {
831 DEBUG_TRACE (DEBUG::Transport, "micro-locate while waiting for sync\n");
832 if (micro_locate (nframes)) {
833 /* XXX ERROR !!! XXX */
837 return true; // done, nothing left to process
844 Session::queue_event (SessionEvent* ev)
846 if (_state_of_the_state & Deletion) {
848 } else if (_state_of_the_state & Loading) {
851 Glib::Threads::Mutex::Lock lm (rb_write_lock);
852 pending_events.write (&ev, 1);
857 Session::set_next_event ()
859 if (events.empty()) {
860 next_event = events.end();
864 if (next_event == events.end()) {
865 next_event = events.begin();
868 if ((*next_event)->action_sample > _transport_sample) {
869 next_event = events.begin();
872 for (; next_event != events.end(); ++next_event) {
873 if ((*next_event)->action_sample >= _transport_sample) {
880 Session::process_event (SessionEvent* ev)
885 /* if we're in the middle of a state change (i.e. waiting
886 for the butler thread to complete the non-realtime
887 part of the change), we'll just have to queue this
888 event for a time when the change is complete.
891 if (non_realtime_work_pending()) {
893 /* except locates, which we have the capability to handle */
895 if (ev->type != SessionEvent::Locate) {
896 immediate_events.insert (immediate_events.end(), ev);
902 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_sample));
905 case SessionEvent::SetLoop:
906 set_play_loop (ev->yes_or_no, ev->speed);
909 case SessionEvent::AutoLoop:
911 /* roll after locate, do not flush, set "with loop"
912 true only if we are seamless looping
914 start_locate (ev->target_sample, true, false, Config->get_seamless_loop());
920 case SessionEvent::Locate:
921 if (ev->yes_or_no) { /* force locate */
922 /* args: do not roll after locate, do flush, not with loop */
923 locate (ev->target_sample, false, true, false);
925 /* args: do not roll after locate, do flush, not with loop */
926 start_locate (ev->target_sample, false, true, false);
928 _send_timecode_update = true;
931 case SessionEvent::LocateRoll:
933 /* args: roll after locate, do flush, not with loop */
934 locate (ev->target_sample, true, true, false);
936 /* args: roll after locate, do flush, not with loop */
937 start_locate (ev->target_sample, true, true, false);
939 _send_timecode_update = true;
942 case SessionEvent::Skip:
943 if (Config->get_skip_playback()) {
944 start_locate (ev->target_sample, true, true, false);
945 _send_timecode_update = true;
951 case SessionEvent::LocateRollLocate:
952 // locate is handled by ::request_roll_at_and_return()
953 _requested_return_sample = ev->target_sample;
954 request_locate (ev->target2_sample, true);
958 case SessionEvent::SetTransportSpeed:
959 set_transport_speed (ev->speed, ev->target_sample, ev->yes_or_no, ev->second_yes_or_no, ev->third_yes_or_no);
962 case SessionEvent::SetTransportMaster:
963 TransportMasterManager::instance().set_current (ev->transport_master);
966 case SessionEvent::PunchIn:
967 // cerr << "PunchIN at " << transport_sample() << endl;
968 if (config.get_punch_in() && record_status() == Enabled) {
975 case SessionEvent::PunchOut:
976 // cerr << "PunchOUT at " << transport_sample() << endl;
977 if (config.get_punch_out()) {
978 step_back_from_record ();
984 case SessionEvent::StopOnce:
985 if (!non_realtime_work_pending()) {
986 _clear_event_type (SessionEvent::StopOnce);
987 stop_transport (ev->yes_or_no);
993 case SessionEvent::RangeStop:
994 if (!non_realtime_work_pending()) {
995 stop_transport (ev->yes_or_no);
1001 case SessionEvent::RangeLocate:
1002 /* args: roll after locate, do flush, not with loop */
1003 start_locate (ev->target_sample, true, true, false);
1008 case SessionEvent::Overwrite:
1009 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1012 case SessionEvent::Audition:
1013 set_audition (ev->region);
1014 // drop reference to region
1015 ev->region.reset ();
1018 case SessionEvent::SetPlayAudioRange:
1019 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1022 case SessionEvent::CancelPlayAudioRange:
1026 case SessionEvent::RealTimeOperation:
1028 del = false; // other side of RT request needs to clean up
1031 case SessionEvent::AdjustPlaybackBuffering:
1032 schedule_playback_buffering_adjustment ();
1035 case SessionEvent::AdjustCaptureBuffering:
1036 schedule_capture_buffering_adjustment ();
1039 case SessionEvent::SetTimecodeTransmission:
1040 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1044 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1045 abort(); /*NOTREACHED*/
1050 del = del && !_remove_event (ev);
1059 Session::compute_stop_limit () const
1061 if (!Config->get_stop_at_session_end ()) {
1062 return max_samplepos;
1065 if (config.get_external_sync()) {
1066 return max_samplepos;
1069 bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1070 bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1072 if (actively_recording ()) {
1073 /* permanently recording */
1074 return max_samplepos;
1075 } else if (punching_in && !punching_out) {
1076 /* punching in but never out */
1077 return max_samplepos;
1078 } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_sample()) {
1079 /* punching in and punching out after session end */
1080 return max_samplepos;
1083 return current_end_sample ();
1088 /* dedicated thread for signal emission.
1090 * while sending cross-thread signals from the process thread
1091 * is fine in general, PBD::Signal's use of boost::function and
1092 * boost:bind can produce a vast overhead which is not
1093 * acceptable for low latency.
1095 * This works around the issue by moving the boost overhead
1096 * out of the RT thread. The overall load is probably higher but
1097 * the realtime thread remains unaffected.
1101 Session::emit_route_signals ()
1103 // TODO use RAII to allow using these signals in other places
1104 BatchUpdateStart(); /* EMIT SIGNAL */
1105 boost::shared_ptr<RouteList> r = routes.reader ();
1106 for (RouteList::const_iterator ci = r->begin(); ci != r->end(); ++ci) {
1107 (*ci)->emit_pending_signals ();
1109 BatchUpdateEnd(); /* EMIT SIGNAL */
1113 Session::emit_thread_start ()
1115 if (_rt_thread_active) {
1118 _rt_thread_active = true;
1120 if (pthread_create (&_rt_emit_thread, NULL, emit_thread, this)) {
1121 _rt_thread_active = false;
1126 Session::emit_thread_terminate ()
1128 if (!_rt_thread_active) {
1131 _rt_thread_active = false;
1133 if (pthread_mutex_lock (&_rt_emit_mutex) == 0) {
1134 pthread_cond_signal (&_rt_emit_cond);
1135 pthread_mutex_unlock (&_rt_emit_mutex);
1139 pthread_join (_rt_emit_thread, &status);
1143 Session::emit_thread (void *arg)
1145 Session *s = static_cast<Session *>(arg);
1146 s->emit_thread_run ();
1152 Session::emit_thread_run ()
1154 pthread_mutex_lock (&_rt_emit_mutex);
1155 while (_rt_thread_active) {
1156 emit_route_signals();
1157 pthread_cond_wait (&_rt_emit_cond, &_rt_emit_mutex);
1159 pthread_mutex_unlock (&_rt_emit_mutex);
1163 Session::follow_transport_master (pframes_t nframes)
1165 TransportMasterManager& tmm (TransportMasterManager::instance());
1168 samplepos_t slave_transport_sample;
1169 sampleoffset_t delta;
1171 if (tmm.master_invalid_this_cycle()) {
1172 DEBUG_TRACE (DEBUG::Slave, "session told not to use the transport master this cycle\n");
1176 slave_speed = tmm.get_current_speed_in_process_context();
1177 slave_transport_sample = tmm.get_current_position_in_process_context ();
1179 track_transport_master (slave_speed, slave_transport_sample);
1181 /* transport sample may have been moved during ::track_transport_master() */
1183 delta = _transport_sample - slave_transport_sample;
1185 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()));
1187 if (transport_master_tracking_state == Running) {
1189 if (!actively_recording() && abs (delta) > tmm.current()->resolution()) {
1190 DEBUG_TRACE (DEBUG::Slave, string_compose ("current slave delta %1 greater than slave resolution %2\n", delta, tmm.current()->resolution()));
1191 if (micro_locate (-delta) != 0) {
1192 DEBUG_TRACE (DEBUG::Slave, "micro-locate didn't work, set no disk output true\n");
1194 /* run routes as normal, but no disk output */
1195 DiskReader::set_no_disk_output (true);
1200 if (transport_master_tracking_state == Running) {
1201 /* speed is set, we're locked, and good to go */
1202 DiskReader::set_no_disk_output (false);
1208 /* don't move at all */
1209 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
1215 Session::track_transport_master (float slave_speed, samplepos_t slave_transport_sample)
1217 boost::shared_ptr<TransportMaster> master (TransportMasterManager::instance().current());
1221 DEBUG_TRACE (DEBUG::Slave, string_compose ("session has master tracking state as %1\n", transport_master_tracking_state));
1223 if (slave_speed != 0.0f) {
1225 /* slave is running */
1227 switch (transport_master_tracking_state) {
1229 master_wait_end = slave_transport_sample + worst_latency_preroll() + master->seekahead_distance ();
1230 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1, now WAITING\n", master_wait_end));
1231 /* we can call locate() here because we are in process context */
1232 if (micro_locate (master_wait_end - _transport_sample) != 0) {
1233 locate (master_wait_end, false, false);
1235 transport_master_tracking_state = Waiting;
1242 if (transport_master_tracking_state == Waiting) {
1244 DEBUG_TRACE (DEBUG::Slave, string_compose ("master currently at %1, waiting to pass %2\n", slave_transport_sample, master_wait_end));
1246 if (slave_transport_sample >= master_wait_end) {
1248 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_sample, _transport_sample));
1250 transport_master_tracking_state = Running;
1252 /* now perform a "micro-seek" within the disk buffers to realign ourselves
1253 precisely with the master.
1256 if (micro_locate (slave_transport_sample - _transport_sample) != 0) {
1257 cerr << "cannot micro-seek\n";
1263 if (transport_master_tracking_state == Running && _transport_speed == 0.0f) {
1264 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
1268 } else { // slave_speed is 0
1270 /* slave has stopped */
1272 if (_transport_speed != 0.0f) {
1273 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 sample %2 tf %3\n", slave_speed, slave_transport_sample, _transport_sample));
1277 if (slave_transport_sample != _transport_sample) {
1278 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_sample));
1279 force_locate (slave_transport_sample, false);
1282 reset_slave_state();
1287 Session::reset_slave_state ()
1289 transport_master_tracking_state = Stopped;
1290 DiskReader::set_no_disk_output (false);