ardour
session_transport.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 1999-2003 Paul Davis
3 
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.
8 
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.
13 
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.
17 
18 */
19 
20 #ifdef WAF_BUILD
21 #include "libardour-config.h"
22 #endif
23 
24 #include <cmath>
25 #include <cerrno>
26 #include <unistd.h>
27 
28 #include "pbd/undo.h"
29 #include "pbd/error.h"
30 #include "pbd/enumwriter.h"
31 #include "pbd/pthread_utils.h"
32 #include "pbd/memento_command.h"
33 #include "pbd/stacktrace.h"
34 
35 #include "midi++/mmc.h"
36 #include "midi++/port.h"
37 
38 #include "ardour/audioengine.h"
39 #include "ardour/auditioner.h"
40 #include "ardour/butler.h"
41 #include "ardour/click.h"
42 #include "ardour/debug.h"
43 #include "ardour/location.h"
44 #include "ardour/profile.h"
45 #include "ardour/scene_changer.h"
46 #include "ardour/session.h"
47 #include "ardour/slave.h"
48 #include "ardour/operations.h"
49 
50 #include "i18n.h"
51 
52 using namespace std;
53 using namespace ARDOUR;
54 using namespace PBD;
55 
56 void
57 Session::add_post_transport_work (PostTransportWork ptw)
58 {
59  PostTransportWork oldval;
60  PostTransportWork newval;
61  int tries = 0;
62 
63  while (tries < 8) {
64  oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
65  newval = PostTransportWork (oldval | ptw);
66  if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
67  /* success */
68  return;
69  }
70  }
71 
72  error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
73 }
74 
75 void
76 Session::request_input_change_handling ()
77 {
78  if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
79  SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
80  queue_event (ev);
81  }
82 }
83 
84 void
85 Session::request_sync_source (Slave* new_slave)
86 {
87  SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
88  bool seamless;
89 
90  seamless = Config->get_seamless_loop ();
91 
92  if (dynamic_cast<Engine_Slave*>(new_slave)) {
93  /* JACK cannot support seamless looping at present */
94  Config->set_seamless_loop (false);
95  } else {
96  /* reset to whatever the value was before we last switched slaves */
97  Config->set_seamless_loop (_was_seamless);
98  }
99 
100  /* save value of seamless from before the switch */
101  _was_seamless = seamless;
102 
103  ev->slave = new_slave;
104  DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
105  queue_event (ev);
106 }
107 
108 void
109 Session::request_transport_speed (double speed, bool as_default)
110 {
111  SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
112  ev->third_yes_or_no = true;
113  DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
114  queue_event (ev);
115 }
116 
121 void
122 Session::request_transport_speed_nonzero (double speed, bool as_default)
123 {
124  if (speed == 0) {
125  speed = DBL_EPSILON;
126  }
127 
128  request_transport_speed (speed, as_default);
129 }
130 
131 void
132 Session::request_track_speed (Track* tr, double speed)
133 {
134  SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
135  ev->set_ptr (tr);
136  queue_event (ev);
137 }
138 
139 void
140 Session::request_stop (bool abort, bool clear_state)
141 {
142  SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
143  DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, audible %3 transport %4 abort = %1, clear state = %2\n", abort, clear_state, audible_frame(), _transport_frame));
144  queue_event (ev);
145 }
146 
147 void
148 Session::request_locate (framepos_t target_frame, bool with_roll)
149 {
150  SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
151  DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
152  queue_event (ev);
153 }
154 
155 void
156 Session::force_locate (framepos_t target_frame, bool with_roll)
157 {
158  SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
159  DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
160  queue_event (ev);
161 }
162 
163 void
164 Session::request_play_loop (bool yn, bool change_transport_roll)
165 {
166  SessionEvent* ev;
167  Location *location = _locations->auto_loop_location();
168  double target_speed;
169 
170  if (location == 0 && yn) {
171  error << _("Cannot loop - no loop range defined")
172  << endmsg;
173  return;
174  }
175 
176  if (change_transport_roll) {
177  if (transport_rolling()) {
178  /* start looping at current speed */
179  target_speed = transport_speed ();
180  } else {
181  /* currently stopped */
182  if (yn) {
183  /* start looping at normal speed */
184  target_speed = 1.0;
185  } else {
186  target_speed = 0.0;
187  }
188  }
189  } else {
190  /* leave the speed alone */
191  target_speed = transport_speed ();
192  }
193 
194  ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
195  DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
196  queue_event (ev);
197 
198  if (yn) {
199  if (!change_transport_roll) {
200  if (!transport_rolling()) {
201  /* we're not changing transport state, but we do want
202  to set up position for the new loop. Don't
203  do this if we're rolling already.
204  */
205  request_locate (location->start(), false);
206  }
207  }
208  } else {
209  if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
210  // request an immediate locate to refresh the tracks
211  // after disabling looping
212  request_locate (_transport_frame-1, false);
213  }
214  }
215 }
216 
217 void
218 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
219 {
220  SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
221  if (range) {
222  ev->audio_range = *range;
223  } else {
224  ev->audio_range.clear ();
225  }
226  DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
227  queue_event (ev);
228 }
229 
230 void
231 Session::request_cancel_play_range ()
232 {
233  SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
234  queue_event (ev);
235 }
236 
237 
238 void
239 Session::realtime_stop (bool abort, bool clear_state)
240 {
241  DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
243 
244  /* assume that when we start, we'll be moving forwards */
245 
246  if (_transport_speed < 0.0f) {
247  todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
248  _default_transport_speed = 1.0;
249  } else {
250  todo = PostTransportWork (todo | PostTransportStop);
251  }
252 
253  /* call routes */
254 
255  boost::shared_ptr<RouteList> r = routes.reader ();
256 
257  for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
258  (*i)->realtime_handle_transport_stopped ();
259  }
260 
261  DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
262 
263  /* the duration change is not guaranteed to have happened, but is likely */
264 
265  todo = PostTransportWork (todo | PostTransportDuration);
266 
267  if (abort) {
268  todo = PostTransportWork (todo | PostTransportAbort);
269  }
270 
271  if (clear_state) {
272  todo = PostTransportWork (todo | PostTransportClearSubstate);
273  }
274 
275  if (todo) {
276  add_post_transport_work (todo);
277  }
278 
279  _clear_event_type (SessionEvent::StopOnce);
280  _clear_event_type (SessionEvent::RangeStop);
281  _clear_event_type (SessionEvent::RangeLocate);
282 
283  /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
284  disable_record (true, (!Config->get_latched_record_enable() && clear_state));
285 
286  reset_slave_state ();
287 
288  _transport_speed = 0;
289  _target_transport_speed = 0;
290 
291  g_atomic_int_set (&_playback_load, 100);
292  g_atomic_int_set (&_capture_load, 100);
293 
294  if (config.get_use_video_sync()) {
295  waiting_for_sync_offset = true;
296  }
297 
298  transport_sub_state = 0;
299 }
300 
301 void
302 Session::realtime_locate ()
303 {
304  boost::shared_ptr<RouteList> r = routes.reader ();
305  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
306  (*i)->realtime_locate ();
307  }
308 }
309 
310 void
311 Session::butler_transport_work ()
312 {
313  restart:
314  bool finished;
315  PostTransportWork ptw;
316  boost::shared_ptr<RouteList> r = routes.reader ();
317 
318  int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
319  finished = true;
320  ptw = post_transport_work();
321 
322  DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
323 
324  if (ptw & PostTransportAdjustPlaybackBuffering) {
325  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
327  if (tr) {
329  /* and refill those buffers ... */
330  }
331  (*i)->non_realtime_locate (_transport_frame);
332  }
333 
334  }
335 
336  if (ptw & PostTransportAdjustCaptureBuffering) {
337  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
339  if (tr) {
341  }
342  }
343  }
344 
345  if (ptw & PostTransportCurveRealloc) {
346  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
347  (*i)->curve_reallocate();
348  }
349  }
350 
351  if (ptw & PostTransportInputChange) {
352  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
354  if (tr) {
356  }
357  }
358  }
359 
360  if (ptw & PostTransportSpeed) {
361  non_realtime_set_speed ();
362  }
363 
364  if (ptw & PostTransportReverse) {
365 
366  clear_clicks();
367  cumulative_rf_motion = 0;
368  reset_rf_scale (0);
369 
370  /* don't seek if locate will take care of that in non_realtime_stop() */
371 
372  if (!(ptw & PostTransportLocate)) {
373 
374  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
375  (*i)->non_realtime_locate (_transport_frame);
376 
377  if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
378  /* new request, stop seeking, and start again */
379  g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
380  goto restart;
381  }
382  }
383  }
384  }
385 
386  if (ptw & PostTransportLocate) {
387  DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
388  non_realtime_locate ();
389  }
390 
391  if (ptw & PostTransportStop) {
392  non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
393  if (!finished) {
394  g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
395  goto restart;
396  }
397  }
398 
399  if (ptw & PostTransportOverWrite) {
400  non_realtime_overwrite (on_entry, finished);
401  if (!finished) {
402  g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
403  goto restart;
404  }
405  }
406 
407  if (ptw & PostTransportAudition) {
408  non_realtime_set_audition ();
409  }
410 
411  g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
412 
413  DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
414  DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
415 }
416 
417 void
418 Session::non_realtime_set_speed ()
419 {
420  boost::shared_ptr<RouteList> rl = routes.reader();
421  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
423  if (tr) {
424  tr->non_realtime_set_speed ();
425  }
426  }
427 }
428 
429 void
430 Session::non_realtime_overwrite (int on_entry, bool& finished)
431 {
432  boost::shared_ptr<RouteList> rl = routes.reader();
433  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
435  if (tr && tr->pending_overwrite ()) {
437  }
438  if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
439  finished = false;
440  return;
441  }
442  }
443 }
444 
445 
446 void
447 Session::non_realtime_locate ()
448 {
449  DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
450 
451  if (Config->get_loop_is_mode() && get_play_loop()) {
452 
453  Location *loc = _locations->auto_loop_location();
454 
455  if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
456  /* jumped out of loop range: stop tracks from looping,
457  but leave loop (mode) enabled.
458  */
459  set_track_loop (false);
460 
461  } else if (loc && Config->get_seamless_loop() &&
462  ((loc->start() <= _transport_frame) ||
463  (loc->end() > _transport_frame) ) ) {
464 
465  /* jumping to start of loop. This might have been done before but it is
466  * idempotent and cheap. Doing it here ensures that when we start playback
467  * outside the loop we still flip tracks into the magic seamless mode
468  * when needed.
469  */
470  set_track_loop (true);
471 
472  } else if (loc) {
473  set_track_loop (false);
474  }
475 
476  } else {
477 
478  /* no more looping .. should have been noticed elsewhere */
479  }
480 
481 
482  boost::shared_ptr<RouteList> rl = routes.reader();
483  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
484  (*i)->non_realtime_locate (_transport_frame);
485  }
486 
487  _scene_changer->locate (_transport_frame);
488 
489  /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
490  rather than clearing them so that the RT thread has to spend time constructing
491  them (in Session::click).
492  */
493  clear_clicks ();
494 }
495 
496 void
497 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
498 {
499  struct tm* now;
500  time_t xnow;
501  bool did_record;
502  bool saved;
503  PostTransportWork ptw = post_transport_work();
504 
505  did_record = false;
506  saved = false;
507 
508  boost::shared_ptr<RouteList> rl = routes.reader();
509  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
511  if (tr && tr->get_captured_frames () != 0) {
512  did_record = true;
513  break;
514  }
515  }
516 
517  /* stop and locate are merged here because they share a lot of common stuff */
518 
519  time (&xnow);
520  now = localtime (&xnow);
521 
522  if (auditioner) {
523  auditioner->cancel_audition ();
524  }
525 
526  cumulative_rf_motion = 0;
527  reset_rf_scale (0);
528 
529  if (did_record) {
530  begin_reversible_command (Operations::capture);
531  _have_captured = true;
532  }
533 
534  DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
535 
536  if (abort && did_record) {
537  /* no reason to save the session file when we remove sources
538  */
539  _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
540  }
541 
542  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
544  if (tr) {
545  tr->transport_stopped_wallclock (*now, xnow, abort);
546  }
547  }
548 
549  if (abort && did_record) {
550  _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
551  }
552 
553  boost::shared_ptr<RouteList> r = routes.reader ();
554 
555  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
556  if (!(*i)->is_auditioner()) {
557  (*i)->set_pending_declick (0);
558  }
559  }
560 
561  if (did_record) {
562  commit_reversible_command ();
563  /* increase take name */
564  if (config.get_track_name_take () && !config.get_take_name ().empty()) {
565  string newname = config.get_take_name();
566  config.set_take_name(bump_name_number (newname));
567  }
568  }
569 
570  if (_engine.running()) {
571  PostTransportWork ptw = post_transport_work ();
572  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
573  (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
574  }
575  update_latency_compensation ();
576  }
577 
578  bool const auto_return_enabled =
579  (!config.get_external_sync() && (config.get_auto_return() || abort));
580 
581  if (auto_return_enabled ||
582  (ptw & PostTransportLocate) ||
583  (_requested_return_frame >= 0) ||
584  synced_to_engine()) {
585 
586  if (pending_locate_flush) {
587  flush_all_inserts ();
588  }
589 
590  if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
591  !(ptw & PostTransportLocate)) {
592 
593  /* no explicit locate queued */
594 
595  bool do_locate = false;
596 
597  if (_requested_return_frame >= 0) {
598 
599  /* explicit return request pre-queued in event list. overrides everything else */
600 
601  _transport_frame = _requested_return_frame;
602  do_locate = true;
603 
604  } else {
605  if (config.get_auto_return()) {
606 
607  if (play_loop) {
608 
609  /* don't try to handle loop play when synced to JACK */
610 
611  if (!synced_to_engine()) {
612 
613  Location *location = _locations->auto_loop_location();
614 
615  if (location != 0) {
616  _transport_frame = location->start();
617  } else {
618  _transport_frame = _last_roll_location;
619  }
620  do_locate = true;
621  }
622 
623  } else if (_play_range) {
624 
625  /* return to start of range */
626 
627  if (!current_audio_range.empty()) {
628  _transport_frame = current_audio_range.front().start;
629  do_locate = true;
630  }
631 
632  } else {
633 
634  /* regular auto-return */
635 
636  _transport_frame = _last_roll_location;
637  do_locate = true;
638  }
639  } else if (abort) {
640 
641  _transport_frame = _last_roll_location;
642  do_locate = true;
643  }
644  }
645 
646  _requested_return_frame = -1;
647 
648  if (do_locate) {
649  _engine.transport_locate (_transport_frame);
650  }
651  }
652 
653  }
654 
655  clear_clicks();
656 
657  /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
658  */
659 
660  if (ptw & PostTransportClearSubstate) {
661  unset_play_range ();
662  if (!Config->get_loop_is_mode()) {
663  unset_play_loop ();
664  }
665  }
666 
667  /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
668 
669  DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
670  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
671  DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
672  (*i)->non_realtime_locate (_transport_frame);
673 
674  if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
675  finished = false;
676  /* we will be back */
677  return;
678  }
679  }
680 
681  have_looped = false;
682 
683  /* don't bother with this stuff if we're disconnected from the engine,
684  because there will be no process callbacks to deliver stuff from
685  */
686 
687  if (_engine.connected() && !_engine.freewheeling()) {
688  // need to queue this in the next RT cycle
689  _send_timecode_update = true;
690 
691  if (!dynamic_cast<MTC_Slave*>(_slave)) {
692  send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
693 
694  /* This (::non_realtime_stop()) gets called by main
695  process thread, which will lead to confusion
696  when calling AsyncMIDIPort::write().
697 
698  Something must be done. XXX
699  */
700  send_mmc_locate (_transport_frame);
701  }
702  }
703 
704  if ((ptw & PostTransportLocate) && get_record_enabled()) {
705  /* This is scheduled by realtime_stop(), which is also done
706  * when a slave requests /locate/ for an initial sync.
707  * We can't hold up the slave for long with a save() here,
708  * without breaking its initial sync cycle.
709  *
710  * save state only if there's no slave or if it's not yet locked.
711  */
712  if (!_slave || !_slave->locked()) {
713  DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
714  SaveSessionRequested (_current_snapshot_name);
715  saved = true;
716  }
717  }
718 
719  /* always try to get rid of this */
720 
721  remove_pending_capture_state ();
722 
723  /* save the current state of things if appropriate */
724 
725  if (did_record && !saved) {
726  SaveSessionRequested (_current_snapshot_name);
727  }
728 
729  if (ptw & PostTransportStop) {
730  unset_play_range ();
731  if (!Config->get_loop_is_mode()) {
732  unset_play_loop ();
733  }
734  }
735 
736  PositionChanged (_transport_frame); /* EMIT SIGNAL */
737  DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
738  TransportStateChange (); /* EMIT SIGNAL */
739 
740  /* and start it up again if relevant */
741 
742  if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
743  request_transport_speed (1.0);
744  }
745 
746  /* Even if we didn't do a pending locate roll this time, we don't want it hanging
747  around for next time.
748  */
749  pending_locate_roll = false;
750 }
751 
752 void
753 Session::check_declick_out ()
754 {
755  bool locate_required = transport_sub_state & PendingLocate;
756 
757  /* this is called after a process() iteration. if PendingDeclickOut was set,
758  it means that we were waiting to declick the output (which has just been
759  done) before maybe doing something else. this is where we do that "something else".
760 
761  note: called from the audio thread.
762  */
763 
764  if (transport_sub_state & PendingDeclickOut) {
765 
766  if (locate_required) {
767  start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
768  transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
769  } else {
770  if (!(transport_sub_state & StopPendingCapture)) {
771  stop_transport (pending_abort);
772  transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
773  }
774  }
775 
776  } else if (transport_sub_state & PendingLoopDeclickOut) {
777  /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
778  transport_sub_state &= ~PendingLoopDeclickOut;
779  }
780 }
781 
782 void
783 Session::unset_play_loop ()
784 {
785  if (play_loop) {
786  play_loop = false;
787  clear_events (SessionEvent::AutoLoop);
788  clear_events (SessionEvent::AutoLoopDeclick);
789  set_track_loop (false);
790 
791 
792  if (Config->get_seamless_loop()) {
793  /* likely need to flush track buffers: this will locate us to wherever we are */
794  add_post_transport_work (PostTransportLocate);
795  _butler->schedule_transport_work ();
796  }
797  }
798 }
799 
800 void
801 Session::set_track_loop (bool yn)
802 {
803  Location* loc = _locations->auto_loop_location ();
804 
805  if (!loc) {
806  yn = false;
807  }
808 
809  boost::shared_ptr<RouteList> rl = routes.reader ();
810 
811  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
813  if (tr && !tr->hidden()) {
814  tr->set_loop (yn ? loc : 0);
815  }
816  }
817 }
818 
819 void
820 Session::set_play_loop (bool yn, double speed)
821 {
822  /* Called from event-handling context */
823 
824  Location *loc;
825 
826  if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
827  /* nothing to do, or can't change loop status while recording */
828  return;
829  }
830 
831  if (yn && Config->get_seamless_loop() && synced_to_engine()) {
833  _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
834  "Recommend changing the configured options"), PROGRAM_NAME)
835  << endmsg;
836  return;
837  }
838 
839  if (yn) {
840 
841  play_loop = true;
842  have_looped = false;
843 
844  if (loc) {
845 
846  unset_play_range ();
847 
848  if (Config->get_seamless_loop()) {
849  if (!Config->get_loop_is_mode()) {
850  /* set all tracks to use internal looping */
851  set_track_loop (true);
852  } else {
853  /* we will do this in the locate to the start OR when we hit the end
854  * of the loop for the first time
855  */
856  }
857  } else {
858  /* set all tracks to NOT use internal looping */
859  set_track_loop (false);
860  }
861 
862  /* Put the delick and loop events in into the event list. The declick event will
863  cause a de-clicking fade-out just before the end of the loop, and it will also result
864  in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
865  */
866 
867  framepos_t dcp;
868  framecnt_t dcl;
869  auto_loop_declick_range (loc, dcp, dcl);
870  merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
871  merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
872 
873  /* if requested to roll, locate to start of loop and
874  * roll but ONLY if we're not already rolling.
875 
876  args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
877  */
878 
879  if (Config->get_loop_is_mode()) {
880  /* loop IS a transport mode: if already
881  rolling, do not locate to loop start.
882  */
883  if (!transport_rolling() && (speed != 0.0)) {
884  start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
885  }
886  } else {
887  if (speed != 0.0) {
888  start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
889  }
890  }
891  }
892 
893  } else {
894 
895  unset_play_loop ();
896  }
897 
898  DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
899  TransportStateChange ();
900 }
901 void
902 Session::flush_all_inserts ()
903 {
904  boost::shared_ptr<RouteList> r = routes.reader ();
905 
906  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
907  (*i)->flush_processors ();
908  }
909 }
910 
911 void
912 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
913 {
914  if (target_frame < 0) {
915  error << _("Locate called for negative sample position - ignored") << endmsg;
916  return;
917  }
918 
919  if (synced_to_engine()) {
920 
921  double sp;
922  framepos_t pos;
923 
924  _slave->speed_and_position (sp, pos);
925 
926  if (target_frame != pos) {
927 
928  if (config.get_jack_time_master()) {
929  /* actually locate now, since otherwise jack_timebase_callback
930  will use the incorrect _transport_frame and report an old
931  and incorrect time to Jack transport
932  */
933  locate (target_frame, with_roll, with_flush, with_loop, force);
934  }
935 
936  /* tell JACK to change transport position, and we will
937  follow along later in ::follow_slave()
938  */
939 
940  _engine.transport_locate (target_frame);
941 
942  if (sp != 1.0f && with_roll) {
943  _engine.transport_start ();
944  }
945 
946  }
947 
948  } else {
949  locate (target_frame, with_roll, with_flush, with_loop, force);
950  }
951 }
952 
953 int
954 Session::micro_locate (framecnt_t distance)
955 {
956  boost::shared_ptr<RouteList> rl = routes.reader();
957  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
959  if (tr && !tr->can_internal_playback_seek (distance)) {
960  return -1;
961  }
962  }
963 
964  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
966  if (tr) {
967  tr->internal_playback_seek (distance);
968  }
969  }
970 
971  _transport_frame += distance;
972  return 0;
973 }
974 
976 void
977 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_seamless_loop, bool force, bool with_mmc)
978 {
979  bool need_butler = false;
980 
981  /* Locates for seamless looping are fairly different from other
982  * locates. They assume that the diskstream buffers for each track
983  * already have the correct data in them, and thus there is no need to
984  * actually tell the tracks to locate. What does need to be done,
985  * though, is all the housekeeping that is associated with non-linear
986  * changes in the value of _transport_frame.
987  */
988 
989  DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 seamless %4 force %5 mmc %6\n",
990  target_frame, with_roll, with_flush, for_seamless_loop, force, with_mmc));
991 
992  if (actively_recording() && !for_seamless_loop) {
993  return;
994  }
995 
996  if (!force && _transport_frame == target_frame && !loop_changing && !for_seamless_loop) {
997  if (with_roll) {
998  set_transport_speed (1.0, 0, false);
999  }
1000  loop_changing = false;
1001  Located (); /* EMIT SIGNAL */
1002  return;
1003  }
1004 
1005  if (_transport_speed && !for_seamless_loop) {
1006  /* Schedule a declick. We'll be called again when its done.
1007  We only do it this way for ordinary locates, not those
1008  due to **seamless** loops.
1009  */
1010 
1011  if (!(transport_sub_state & PendingDeclickOut)) {
1012  transport_sub_state |= (PendingDeclickOut|PendingLocate);
1013  pending_locate_frame = target_frame;
1014  pending_locate_roll = with_roll;
1015  pending_locate_flush = with_flush;
1016  return;
1017  }
1018  }
1019 
1020  // Update Timecode time
1021  // [DR] FIXME: find out exactly where this should go below
1022  _transport_frame = target_frame;
1023  _last_roll_or_reversal_location = target_frame;
1024  timecode_time(_transport_frame, transmitting_timecode_time);
1025  outbound_mtc_timecode_frame = _transport_frame;
1026  next_quarter_frame_to_send = 0;
1027 
1028  /* do "stopped" stuff if:
1029  *
1030  * we are rolling AND
1031  * no autoplay in effect AND
1032  * we're not going to keep rolling after the locate AND
1033  * !(playing a loop with JACK sync)
1034  *
1035  */
1036 
1037  bool transport_was_stopped = !transport_rolling();
1038 
1039  if (transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop)) {
1040  realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1041  transport_was_stopped = true;
1042  } else {
1043  /* otherwise tell the world that we located */
1044  realtime_locate ();
1045  }
1046 
1047  if (force || !for_seamless_loop || loop_changing) {
1048 
1049  PostTransportWork todo = PostTransportLocate;
1050 
1051  if (with_roll && transport_was_stopped) {
1052  todo = PostTransportWork (todo | PostTransportRoll);
1053  }
1054 
1055  add_post_transport_work (todo);
1056  need_butler = true;
1057 
1058  } else {
1059 
1060  /* this is functionally what clear_clicks() does but with a tentative lock */
1061 
1062  Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1063 
1064  if (clickm.locked()) {
1065 
1066  for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1067  delete *i;
1068  }
1069 
1070  clicks.clear ();
1071  }
1072  }
1073 
1074  if (with_roll) {
1075  /* switch from input if we're going to roll */
1076  if (Config->get_monitoring_model() == HardwareMonitoring) {
1077  set_track_monitor_input_status (!config.get_auto_input());
1078  }
1079  } else {
1080  /* otherwise we're going to stop, so do the opposite */
1081  if (Config->get_monitoring_model() == HardwareMonitoring) {
1082  set_track_monitor_input_status (true);
1083  }
1084  }
1085 
1086  /* cancel looped playback if transport pos outside of loop range */
1087  if (play_loop) {
1088 
1089  Location* al = _locations->auto_loop_location();
1090 
1091  if (al) {
1092  if (_transport_frame < al->start() || _transport_frame > al->end()) {
1093 
1094  // located outside the loop: cancel looping directly, this is called from event handling context
1095 
1096  have_looped = false;
1097 
1098  if (!Config->get_loop_is_mode()) {
1099  set_play_loop (false, _transport_speed);
1100  } else {
1101  if (Config->get_seamless_loop()) {
1102  /* this will make the non_realtime_locate() in the butler
1103  which then causes seek() in tracks actually do the right
1104  thing.
1105  */
1106  set_track_loop (false);
1107  }
1108  }
1109 
1110  } else if (_transport_frame == al->start()) {
1111 
1112  // located to start of loop - this is looping, basically
1113 
1114  if (for_seamless_loop) {
1115 
1116  if (!have_looped) {
1117  /* first time */
1118  if (_last_roll_location != al->start()) {
1119  /* didn't start at loop start - playback must have
1120  * started before loop since we've now hit the loop
1121  * end.
1122  */
1123  add_post_transport_work (PostTransportLocate);
1124  need_butler = true;
1125  }
1126 
1127  }
1128 
1129  // this is only necessary for seamless looping
1130 
1131  boost::shared_ptr<RouteList> rl = routes.reader();
1132 
1133  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1135 
1136  if (tr && tr->record_enabled ()) {
1137  // tell it we've looped, so it can deal with the record state
1138  tr->transport_looped (_transport_frame);
1139  }
1140  }
1141  }
1142 
1143  have_looped = true;
1144  TransportLooped(); // EMIT SIGNAL
1145  }
1146  }
1147  }
1148 
1149  if (need_butler) {
1150  _butler->schedule_transport_work ();
1151  }
1152 
1153  loop_changing = false;
1154 
1155  _send_timecode_update = true;
1156 
1157  if (with_mmc) {
1158  send_mmc_locate (_transport_frame);
1159  }
1160 
1161  _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1162  Located (); /* EMIT SIGNAL */
1163 }
1164 
1169 void
1170 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1171 {
1172  DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1173  speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1174 
1175  if (_transport_speed == speed) {
1176  if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1177  _default_transport_speed = 1.0;
1178  }
1179  return;
1180  }
1181 
1182  if (actively_recording() && speed != 1.0 && speed != 0.0) {
1183  /* no varispeed during recording */
1184  DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1185  _transport_speed, _transport_frame));
1186  return;
1187  }
1188 
1189  _target_transport_speed = fabs(speed);
1190 
1191  /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1192  and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1193  */
1194 
1195  if (speed > 0) {
1196  speed = min (8.0, speed);
1197  } else if (speed < 0) {
1198  speed = max (-8.0, speed);
1199  }
1200 
1201  if (transport_rolling() && speed == 0.0) {
1202 
1203  /* we are rolling and we want to stop */
1204 
1205  if (Config->get_monitoring_model() == HardwareMonitoring) {
1206  set_track_monitor_input_status (true);
1207  }
1208 
1209  if (synced_to_engine ()) {
1210  if (clear_state) {
1211  /* do this here because our response to the slave won't
1212  take care of it.
1213  */
1214  _play_range = false;
1215  unset_play_loop ();
1216  }
1217  _engine.transport_stop ();
1218  } else {
1219  bool const auto_return_enabled = (!config.get_external_sync() && (config.get_auto_return() || abort));
1220 
1221  if (!auto_return_enabled) {
1222  _requested_return_frame = destination_frame;
1223  }
1224 
1225  stop_transport (abort);
1226  }
1227 
1228  if (!Config->get_loop_is_mode()) {
1229  unset_play_loop ();
1230  }
1231 
1232  } else if (transport_stopped() && speed == 1.0) {
1233 
1234  /* we are stopped and we want to start rolling at speed 1 */
1235 
1236  if (Config->get_loop_is_mode() && play_loop) {
1237 
1238  Location *location = _locations->auto_loop_location();
1239 
1240  if (location != 0) {
1241  if (_transport_frame != location->start()) {
1242 
1243  if (Config->get_seamless_loop()) {
1244  /* force tracks to do their thing */
1245  set_track_loop (true);
1246  }
1247 
1248  /* jump to start and then roll from there */
1249 
1250  request_locate (location->start(), true);
1251  return;
1252  }
1253  }
1254  }
1255 
1256  if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1257  set_track_monitor_input_status (false);
1258  }
1259 
1260  if (synced_to_engine()) {
1261  _engine.transport_start ();
1262  } else {
1263  start_transport ();
1264  }
1265 
1266  } else {
1267 
1268  /* not zero, not 1.0 ... varispeed */
1269 
1270  if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1271  warning << string_compose (
1272  _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1273  PROGRAM_NAME)
1274  << endmsg;
1275  return;
1276  }
1277 
1278  if (actively_recording()) {
1279  return;
1280  }
1281 
1282  if (speed > 0.0 && _transport_frame == current_end_frame()) {
1283  return;
1284  }
1285 
1286  if (speed < 0.0 && _transport_frame == 0) {
1287  return;
1288  }
1289 
1290  clear_clicks ();
1291 
1292  /* if we are reversing relative to the current speed, or relative to the speed
1293  before the last stop, then we have to do extra work.
1294  */
1295 
1297 
1298  if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1299  todo = PostTransportWork (todo | PostTransportReverse);
1300  _last_roll_or_reversal_location = _transport_frame;
1301  }
1302 
1303  _last_transport_speed = _transport_speed;
1304  _transport_speed = speed;
1305 
1306  if (as_default) {
1307  _default_transport_speed = speed;
1308  }
1309 
1310  boost::shared_ptr<RouteList> rl = routes.reader();
1311  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1313  if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1314  todo = PostTransportWork (todo | PostTransportSpeed);
1315  }
1316  }
1317 
1318  if (todo) {
1319  add_post_transport_work (todo);
1320  _butler->schedule_transport_work ();
1321  }
1322 
1323  DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1324 
1325  /* throttle signal emissions.
1326  * when slaved [_last]_transport_speed
1327  * usually changes every cycle (tiny amounts due to DLL).
1328  * Emitting a signal every cycle is overkill and unwarranted.
1329  *
1330  * Using _last_transport_speed is not acceptable,
1331  * since it allows for large changes over a long period
1332  * of time. Hence we introduce a dedicated variable to keep track
1333  *
1334  * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1335  * for TransportStateChange() here is the ShuttleControl display.
1336  */
1337  if (fabsf(_signalled_varispeed - speed) > .002f
1338  // still, signal hard changes to 1.0 and 0.0:
1339  || ( speed == 1.f && _signalled_varispeed != 1.f)
1340  || ( speed == 0.f && _signalled_varispeed != 0.f)
1341  )
1342  {
1343  TransportStateChange (); /* EMIT SIGNAL */
1344  _signalled_varispeed = speed;
1345  }
1346  }
1347 }
1348 
1349 
1351 void
1352 Session::stop_transport (bool abort, bool clear_state)
1353 {
1354  if (_transport_speed == 0.0f) {
1355  return;
1356  }
1357 
1358  if (!get_transport_declick_required()) {
1359 
1360  /* stop has not yet been scheduled */
1361 
1362  boost::shared_ptr<RouteList> rl = routes.reader();
1363  framepos_t stop_target = audible_frame();
1364 
1365  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1367  if (tr) {
1368  tr->prepare_to_stop (_transport_frame, stop_target);
1369  }
1370  }
1371 
1372  SubState new_bits;
1373 
1374  if (actively_recording() && /* we are recording */
1375  worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1376 
1377  /* we need to capture the audio that is still somewhere in the pipeline between
1378  wherever it was generated and the process callback. This means that even though
1379  the user (or something else) has asked us to stop, we have to roll
1380  past this point and then reset the playhead/transport location to
1381  the position at which the stop was requested.
1382 
1383  we still need playback to "stop" now, however, which is why we schedule
1384  a declick below.
1385  */
1386 
1387  DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1388  _transport_frame, _worst_input_latency,
1389  _transport_frame + _worst_input_latency,
1390  abort));
1391 
1392  SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1393  _transport_frame + _worst_input_latency,
1394  0, 0, abort);
1395 
1396  merge_event (ev);
1397 
1398  /* request a declick at the start of the next process cycle() so that playback ceases.
1399  It will remain silent until we actually stop (at the StopOnce event somewhere in
1400  the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1401  does not stop the transport too early.
1402  */
1403  new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1404 
1405  } else {
1406 
1407  /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1408 
1409  new_bits = PendingDeclickOut;
1410  }
1411 
1412 
1413  /* we'll be called again after the declick */
1414  transport_sub_state = SubState (transport_sub_state|new_bits);
1415  pending_abort = abort;
1416 
1417  return;
1418 
1419  } else {
1420 
1421  /* declick was scheduled, but we've been called again, which means it is really time to stop
1422 
1423  XXX: we should probably split this off into its own method and call it explicitly.
1424  */
1425 
1426  realtime_stop (abort, clear_state);
1427  _butler->schedule_transport_work ();
1428  }
1429 }
1430 
1432 void
1433 Session::start_transport ()
1434 {
1435  DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1436 
1437  _last_roll_location = _transport_frame;
1438  _last_roll_or_reversal_location = _transport_frame;
1439 
1440  have_looped = false;
1441 
1442  /* if record status is Enabled, move it to Recording. if its
1443  already Recording, move it to Disabled.
1444  */
1445 
1446  switch (record_status()) {
1447  case Enabled:
1448  if (!config.get_punch_in()) {
1449  enable_record ();
1450  }
1451  break;
1452 
1453  case Recording:
1454  if (!play_loop) {
1455  disable_record (false);
1456  }
1457  break;
1458 
1459  default:
1460  break;
1461  }
1462 
1463  transport_sub_state |= PendingDeclickIn;
1464 
1465  _transport_speed = _default_transport_speed;
1466  _target_transport_speed = _transport_speed;
1467 
1468  boost::shared_ptr<RouteList> rl = routes.reader();
1469  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1471  if (tr) {
1472  tr->realtime_set_speed (tr->speed(), true);
1473  }
1474  }
1475 
1476  if (!_engine.freewheeling()) {
1477  Timecode::Time time;
1478  timecode_time_subframes (_transport_frame, time);
1479  if (!dynamic_cast<MTC_Slave*>(_slave)) {
1480  send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1481  }
1482  }
1483 
1484  DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1485  TransportStateChange (); /* EMIT SIGNAL */
1486 }
1487 
1491 void
1492 Session::post_transport ()
1493 {
1494  PostTransportWork ptw = post_transport_work ();
1495 
1496  if (ptw & PostTransportAudition) {
1497  if (auditioner && auditioner->auditioning()) {
1498  process_function = &Session::process_audition;
1499  } else {
1500  process_function = &Session::process_with_events;
1501  }
1502  }
1503 
1504  if (ptw & PostTransportStop) {
1505 
1506  transport_sub_state = 0;
1507  }
1508 
1509  if (ptw & PostTransportLocate) {
1510 
1511  if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1512  start_transport ();
1513  } else {
1514  transport_sub_state = 0;
1515  }
1516  }
1517 
1518  set_next_event ();
1519  /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1520  know were handled ?
1521  */
1522  set_post_transport_work (PostTransportWork (0));
1523 }
1524 
1525 void
1526 Session::reset_rf_scale (framecnt_t motion)
1527 {
1528  cumulative_rf_motion += motion;
1529 
1530  if (cumulative_rf_motion < 4 * _current_frame_rate) {
1531  rf_scale = 1;
1532  } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1533  rf_scale = 4;
1534  } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1535  rf_scale = 10;
1536  } else {
1537  rf_scale = 100;
1538  }
1539 
1540  if (motion != 0) {
1541  set_dirty();
1542  }
1543 }
1544 
1545 void
1546 Session::use_sync_source (Slave* new_slave)
1547 {
1548  /* Runs in process() context */
1549 
1550  bool non_rt_required = false;
1551 
1552  /* XXX this deletion is problematic because we're in RT context */
1553 
1554  delete _slave;
1555  _slave = new_slave;
1556 
1557  DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1558 
1559  // need to queue this for next process() cycle
1560  _send_timecode_update = true;
1561 
1562  boost::shared_ptr<RouteList> rl = routes.reader();
1563  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1565  if (tr && !tr->hidden()) {
1566  if (tr->realtime_set_speed (tr->speed(), true)) {
1567  non_rt_required = true;
1568  }
1569  tr->set_slaved (_slave != 0);
1570  }
1571  }
1572 
1573  if (non_rt_required) {
1574  add_post_transport_work (PostTransportSpeed);
1575  _butler->schedule_transport_work ();
1576  }
1577 
1578  set_dirty();
1579 }
1580 
1581 void
1582 Session::drop_sync_source ()
1583 {
1584  request_sync_source (0);
1585 }
1586 
1587 void
1588 Session::switch_to_sync_source (SyncSource src)
1589 {
1590  Slave* new_slave;
1591 
1592  DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1593 
1594  switch (src) {
1595  case MTC:
1596  if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1597  return;
1598  }
1599 
1600  try {
1601  new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1602  }
1603 
1604  catch (failed_constructor& err) {
1605  return;
1606  }
1607  break;
1608 
1609  case LTC:
1610  if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1611  return;
1612  }
1613 
1614  try {
1615  new_slave = new LTC_Slave (*this);
1616  }
1617 
1618  catch (failed_constructor& err) {
1619  return;
1620  }
1621 
1622  break;
1623 
1624  case MIDIClock:
1625  if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1626  return;
1627  }
1628 
1629  try {
1630  new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1631  }
1632 
1633  catch (failed_constructor& err) {
1634  return;
1635  }
1636  break;
1637 
1638  case Engine:
1639  if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1640  return;
1641  }
1642 
1643  if (config.get_video_pullup() != 0.0f) {
1644  return;
1645  }
1646 
1647  new_slave = new Engine_Slave (*AudioEngine::instance());
1648  break;
1649 
1650  default:
1651  new_slave = 0;
1652  break;
1653  };
1654 
1655  request_sync_source (new_slave);
1656 }
1657 
1658 void
1659 Session::set_track_speed (Track* track, double speed)
1660 {
1661  if (track->realtime_set_speed (speed, false)) {
1662  add_post_transport_work (PostTransportSpeed);
1663  _butler->schedule_transport_work ();
1664  set_dirty ();
1665  }
1666 }
1667 
1668 void
1669 Session::unset_play_range ()
1670 {
1671  _play_range = false;
1672  _clear_event_type (SessionEvent::RangeStop);
1673  _clear_event_type (SessionEvent::RangeLocate);
1674 }
1675 
1676 void
1677 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1678 {
1679  SessionEvent* ev;
1680 
1681  /* Called from event-processing context */
1682 
1683  unset_play_range ();
1684 
1685  if (range.empty()) {
1686  /* _play_range set to false in unset_play_range()
1687  */
1688  if (!leave_rolling) {
1689  /* stop transport */
1690  SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1691  merge_event (ev);
1692  }
1693  return;
1694  }
1695 
1696  _play_range = true;
1697 
1698  /* cancel loop play */
1699  unset_play_loop ();
1700 
1701  list<AudioRange>::size_type sz = range.size();
1702 
1703  if (sz > 1) {
1704 
1705  list<AudioRange>::iterator i = range.begin();
1706  list<AudioRange>::iterator next;
1707 
1708  while (i != range.end()) {
1709 
1710  next = i;
1711  ++next;
1712 
1713  /* locating/stopping is subject to delays for declicking.
1714  */
1715 
1716  framepos_t requested_frame = i->end;
1717 
1718  if (requested_frame > current_block_size) {
1719  requested_frame -= current_block_size;
1720  } else {
1721  requested_frame = 0;
1722  }
1723 
1724  if (next == range.end()) {
1725  ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1726  } else {
1727  ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1728  }
1729 
1730  merge_event (ev);
1731 
1732  i = next;
1733  }
1734 
1735  } else if (sz == 1) {
1736 
1737  ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1738  merge_event (ev);
1739 
1740  }
1741 
1742  /* save range so we can do auto-return etc. */
1743 
1744  current_audio_range = range;
1745 
1746  /* now start rolling at the right place */
1747 
1748  ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1749  merge_event (ev);
1750 
1751  DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
1752  TransportStateChange ();
1753 }
1754 
1755 void
1756 Session::request_bounded_roll (framepos_t start, framepos_t end)
1757 {
1758  AudioRange ar (start, end, 0);
1759  list<AudioRange> lar;
1760 
1761  lar.push_back (ar);
1762  request_play_range (&lar, true);
1763 }
1764 
1765 void
1766 Session::set_requested_return_frame (framepos_t return_to)
1767 {
1768  _requested_return_frame = return_to;
1769 }
1770 
1771 void
1772 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1773 {
1774  SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1775  ev->target2_frame = start;
1776  queue_event (ev);
1777 }
1778 
1779 void
1780 Session::engine_halted ()
1781 {
1782  bool ignored;
1783 
1784  /* there will be no more calls to process(), so
1785  we'd better clean up for ourselves, right now.
1786 
1787  but first, make sure the butler is out of
1788  the picture.
1789  */
1790 
1791  if (_butler) {
1792  g_atomic_int_set (&_butler->should_do_transport_work, 0);
1793  set_post_transport_work (PostTransportWork (0));
1794  _butler->stop ();
1795  }
1796 
1797  realtime_stop (false, true);
1798  non_realtime_stop (false, 0, ignored);
1799  transport_sub_state = 0;
1800 
1801  DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
1802  TransportStateChange (); /* EMIT SIGNAL */
1803 }
1804 
1805 
1806 void
1807 Session::xrun_recovery ()
1808 {
1809  ++_xrun_count;
1810 
1811  Xrun (_transport_frame); /* EMIT SIGNAL */
1812 
1813  if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1814 
1815  /* it didn't actually halt, but we need
1816  to handle things in the same way.
1817  */
1818 
1819  engine_halted();
1820  }
1821 }
1822 
1823 void
1824 Session::route_processors_changed (RouteProcessorChange c)
1825 {
1826  if (ignore_route_processor_changes) {
1827  return;
1828  }
1829 
1830  if (c.type == RouteProcessorChange::MeterPointChange) {
1831  set_dirty ();
1832  return;
1833  }
1834 
1835  if (c.type == RouteProcessorChange::RealTimeChange) {
1836  set_dirty ();
1837  return;
1838  }
1839 
1840  update_latency_compensation ();
1841  resort_routes ();
1842 
1843  set_dirty ();
1844 }
1845 
1846 void
1847 Session::allow_auto_play (bool yn)
1848 {
1849  auto_play_legal = yn;
1850 }
1851 
1852 bool
1853 Session::maybe_stop (framepos_t limit)
1854 {
1855  if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1856  if (synced_to_engine () && config.get_jack_time_master ()) {
1857  _engine.transport_stop ();
1858  } else if (!synced_to_engine ()) {
1859  stop_transport ();
1860  }
1861  return true;
1862  }
1863  return false;
1864 }
1865 
1866 void
1867 Session::send_mmc_locate (framepos_t t)
1868 {
1869  if (t < 0) {
1870  return;
1871  }
1872 
1873  if (!_engine.freewheeling()) {
1874  Timecode::Time time;
1875  timecode_time_subframes (t, time);
1876  send_immediate_mmc (MIDI::MachineControlCommand (time));
1877  }
1878 }
1879 
1884 void
1885 Session::request_suspend_timecode_transmission ()
1886 {
1887  SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1888  queue_event (ev);
1889 }
1890 
1891 void
1892 Session::request_resume_timecode_transmission ()
1893 {
1894  SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
1895  queue_event (ev);
1896 }
1897 
1898 bool
1899 Session::timecode_transmission_suspended () const
1900 {
1901  return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
1902 }
bool pending_overwrite() const
Definition: track.cc:753
SyncSource
Definition: types.h:498
void transport_looped(framepos_t)
Definition: track.cc:735
#define enum_2_string(e)
Definition: enumwriter.h:97
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
int overwrite_existing_buffers()
Definition: track.cc:717
void adjust_capture_buffering()
Definition: track.cc:886
bool hidden() const
Definition: track.cc:674
framecnt_t get_captured_frames(uint32_t n=0) const
Definition: track.cc:723
JACK does monitoring.
Definition: types.h:381
tuple f
Definition: signals.py:35
void set_ptr(void *p)
framepos_t end() const
Definition: location.h:72
Definition: Beats.hpp:239
LIBPBD_API Transmitter error
LIBPBD_API Transmitter warning
void non_realtime_input_change()
Definition: track.cc:692
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
std::list< AudioRange > audio_range
framepos_t target2_frame
Definition: session_event.h:87
#define _(Text)
Definition: i18n.h:11
void non_realtime_set_speed()
Definition: track.cc:711
void prepare_to_stop(framepos_t, framepos_t)
Definition: track.cc:765
#define X_(Text)
Definition: i18n.h:13
int64_t framecnt_t
Definition: types.h:76
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
int internal_playback_seek(framecnt_t)
Definition: track.cc:686
Definition: amp.h:29
The Slave interface can be used to sync ARDOURs tempo to an external source like MTC, MIDI Clock, etc.
Definition: slave.h:62
#define DEBUG_TRACE(bits, str)
Definition: debug.h:55
bool record_enabled() const
Definition: track.cc:215
int64_t framepos_t
Definition: types.h:66
void transport_stopped_wallclock(struct tm &, time_t, bool)
Definition: track.cc:747
LIBARDOUR_API uint64_t Transport
Definition: debug.cc:41
LIBARDOUR_API uint64_t Slave
Definition: debug.cc:42
LIBARDOUR_API std::string bump_name_number(const std::string &s)
Definition: utils.cc:200
int can_internal_playback_seek(framecnt_t)
Definition: track.cc:680
void adjust_playback_buffering()
Definition: track.cc:878
Definition: debug.h:30
bool realtime_set_speed(double, bool)
Definition: track.cc:741
void set_slaved(bool)
Definition: track.cc:771
LIBARDOUR_API uint64_t MTC
Definition: debug.cc:39
int set_loop(Location *)
Definition: track.cc:729
framepos_t start() const
Definition: location.h:71
LIBARDOUR_API GQuark capture
Definition: operations.cc:24
LIBARDOUR_API uint64_t LTC
Definition: debug.cc:40
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
double speed() const
Definition: track.cc:759