c86a868e56ffacf92d7d87abae47f3f2a2febd94
[ardour.git] / libs / ardour / session_transport.cc
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 #include <cmath>
21 #include <cerrno>
22 #include <unistd.h>
23
24 #include <sigc++/bind.h>
25 #include <sigc++/retype.h>
26
27 #include <pbd/undo.h>
28 #include <pbd/error.h>
29 #include <glibmm/thread.h>
30 #include <pbd/pthread_utils.h>
31 #include <pbd/memento_command.h>
32 #include <pbd/stacktrace.h>
33
34 #include <midi++/mmc.h>
35 #include <midi++/port.h>
36
37 #include <ardour/ardour.h>
38 #include <ardour/audioengine.h>
39 #include <ardour/session.h>
40 #include <ardour/audio_diskstream.h>
41 #include <ardour/auditioner.h>
42 #include <ardour/slave.h>
43 #include <ardour/location.h>
44
45 #include "i18n.h"
46
47 using namespace std;
48 using namespace ARDOUR;
49 using namespace sigc;
50 using namespace PBD;
51
52 void
53 Session::request_input_change_handling ()
54 {
55         if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
56                 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
57                 queue_event (ev);
58         } 
59 }
60
61 void
62 Session::request_slave_source (SlaveSource src)
63 {
64         Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, 0, 0.0);
65
66         if (src == JACK) {
67                 /* could set_seamless_loop() be disposed of entirely?*/
68                 Config->set_seamless_loop (false);
69         } else {
70                 Config->set_seamless_loop (true);
71         }
72         ev->slave = src;
73         queue_event (ev);
74 }
75
76 void
77 Session::request_transport_speed (float speed)
78 {
79         Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
80         queue_event (ev);
81 }
82
83 void
84 Session::request_diskstream_speed (Diskstream& ds, float speed)
85 {
86         Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
87         ev->set_ptr (&ds);
88         queue_event (ev);
89 }
90
91 void
92 Session::request_stop (bool abort)
93 {
94         Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
95         queue_event (ev);
96 }
97
98 void
99 Session::request_locate (nframes_t target_frame, bool with_roll)
100 {
101         Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
102         queue_event (ev);
103 }
104
105 void
106 Session::force_locate (nframes_t target_frame, bool with_roll)
107 {
108         Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
109         queue_event (ev);
110 }
111
112 void
113 Session::request_play_loop (bool yn)
114 {
115         Event* ev;      
116         Location *location = _locations.auto_loop_location();
117
118         if (location == 0 && yn) {
119                 error << _("Cannot loop - no loop range defined")
120                       << endmsg;
121                 return;
122         }
123
124         ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn);
125         queue_event (ev);
126
127         if (!yn && Config->get_seamless_loop() && transport_rolling()) {
128                 // request an immediate locate to refresh the diskstreams
129                 // after disabling looping
130                 request_locate (_transport_frame-1, false);
131         }
132 }
133
134 void
135 Session::realtime_stop (bool abort)
136 {
137         /* assume that when we start, we'll be moving forwards */
138         
139         // FIXME: where should this really be? [DR]
140         //send_full_time_code();
141         deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame);
142         deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
143
144         if (_transport_speed < 0.0f) {
145                 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
146         } else {
147                 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
148         }
149
150         if (actively_recording()) {
151
152                 /* move the transport position back to where the
153                    request for a stop was noticed. we rolled
154                    past that point to pick up delayed input.
155                 */
156
157 #ifndef LEAVE_TRANSPORT_UNADJUSTED
158                 decrement_transport_position (_worst_output_latency);
159 #endif
160
161                 /* the duration change is not guaranteed to have happened, but is likely */
162
163                 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
164         }
165
166         if (abort) {
167                 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
168         }
169
170         _clear_event_type (Event::StopOnce);
171         _clear_event_type (Event::RangeStop);
172         _clear_event_type (Event::RangeLocate);
173
174         disable_record (true);
175
176         reset_slave_state ();
177                 
178         _transport_speed = 0;
179
180         if (Config->get_use_video_sync()) {
181                 waiting_for_sync_offset = true;
182         }
183
184         transport_sub_state = ((Config->get_slave_source() == None && Config->get_auto_return()) ? AutoReturning : 0);
185 }
186
187 void
188 Session::butler_transport_work ()
189 {
190   restart:
191         bool finished;
192         boost::shared_ptr<RouteList> r = routes.reader ();
193         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
194
195         int on_entry = g_atomic_int_get (&butler_should_do_transport_work);
196         finished = true;
197
198         if (post_transport_work & PostTransportCurveRealloc) {
199                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
200                         (*i)->curve_reallocate();
201                 }
202         }
203
204         if (post_transport_work & PostTransportInputChange) {
205                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
206                         (*i)->non_realtime_input_change ();
207                 }
208         }
209
210         if (post_transport_work & PostTransportSpeed) {
211                 non_realtime_set_speed ();
212         }
213
214         if (post_transport_work & PostTransportReverse) {
215
216
217                 clear_clicks();
218                 cumulative_rf_motion = 0;
219                 reset_rf_scale (0);
220
221                 /* don't seek if locate will take care of that in non_realtime_stop() */
222
223                 if (!(post_transport_work & PostTransportLocate)) {
224                         
225                         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
226                                 if (!(*i)->hidden()) {
227                                         if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
228                                                 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
229                                         }
230                                         else {
231                                                 (*i)->seek (_transport_frame);
232                                         }
233                                 }
234                                 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
235                                         /* new request, stop seeking, and start again */
236                                         g_atomic_int_dec_and_test (&butler_should_do_transport_work);
237                                         goto restart;
238                                 }
239                         }
240                 }
241         }
242         
243         if (post_transport_work & PostTransportLocate) {
244                 non_realtime_locate ();
245         }
246
247         if (post_transport_work & PostTransportStop) {
248                 non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
249                 if (!finished) {
250                         g_atomic_int_dec_and_test (&butler_should_do_transport_work);
251                         goto restart;
252                 }
253         }
254
255         if (post_transport_work & PostTransportOverWrite) {
256                 non_realtime_overwrite (on_entry, finished);
257                 if (!finished) {
258                         g_atomic_int_dec_and_test (&butler_should_do_transport_work);
259                         goto restart;
260                 }
261         }
262
263         if (post_transport_work & PostTransportAudition) {
264                 non_realtime_set_audition ();
265         }
266         
267         g_atomic_int_dec_and_test (&butler_should_do_transport_work);
268 }
269
270 void
271 Session::non_realtime_set_speed ()
272 {
273         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
274
275         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
276                 (*i)->non_realtime_set_speed ();
277         }
278 }
279
280 void
281 Session::non_realtime_overwrite (int on_entry, bool& finished)
282 {
283         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
284
285         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
286                 if ((*i)->pending_overwrite) {
287                         (*i)->overwrite_existing_buffers ();
288                 }
289                 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
290                         finished = false;
291                         return;
292                 }
293         }
294 }
295
296         
297 void
298 Session::non_realtime_locate ()
299 {
300         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
301
302         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
303                 (*i)->non_realtime_locate (_transport_frame);
304         }
305 }
306
307
308 void
309 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
310 {
311         struct tm* now;
312         time_t     xnow;
313         bool       did_record;
314         bool       saved;
315
316         did_record = false;
317         saved = false;
318
319         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
320         
321         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
322                 if ((*i)->get_captured_frames () != 0) {
323                         did_record = true;
324                         break;
325                 }
326         }
327
328         /* stop and locate are merged here because they share a lot of common stuff */
329         
330         time (&xnow);
331         now = localtime (&xnow);
332
333         if (auditioner) {
334                 auditioner->cancel_audition ();
335         }
336
337         clear_clicks();
338         cumulative_rf_motion = 0;
339         reset_rf_scale (0);
340
341         if (did_record) {
342                 begin_reversible_command ("capture");
343                 
344                 Location* loc = _locations.end_location();
345                 bool change_end = false;
346                 
347                 if (_transport_frame < loc->end()) {
348
349                         /* stopped recording before current end */
350
351                         if (_end_location_is_free) {
352
353                                 /* first capture for this session, move end back to where we are */
354
355                                 change_end = true;
356                         } 
357
358                 } else if (_transport_frame > loc->end()) {
359                         
360                         /* stopped recording after the current end, extend it */
361
362                         change_end = true;
363                 }
364                 
365                 if (change_end) {
366                         XMLNode &before = loc->get_state();
367                         loc->set_end(_transport_frame);
368                         XMLNode &after = loc->get_state();
369                         add_command (new MementoCommand<Location>(*loc, &before, &after));
370                 }
371
372                 _end_location_is_free = false;
373                 _have_captured = true;
374         }
375
376         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
377                 (*i)->transport_stopped (*now, xnow, abort);
378         }
379         
380         boost::shared_ptr<RouteList> r = routes.reader ();
381
382         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
383                 if (!(*i)->is_hidden()) {
384                         (*i)->set_pending_declick (0);
385                 }
386         }
387         
388         if (did_record) {
389                 commit_reversible_command ();
390         }       
391         
392         if (_engine.running()) {
393                 update_latency_compensation (true, abort);
394         }
395
396         if ((Config->get_slave_source() == None && Config->get_auto_return()) || 
397             (post_transport_work & PostTransportLocate) || 
398             (_requested_return_frame >= 0) ||
399             synced_to_jack()) {
400                 
401                 if (pending_locate_flush) {
402                         flush_all_inserts ();
403                 }
404                 
405                 if (((Config->get_slave_source() == None && Config->get_auto_return()) || 
406                      synced_to_jack() ||
407                      _requested_return_frame >= 0) &&
408                     !(post_transport_work & PostTransportLocate)) {
409
410                         bool do_locate = false;
411
412                         if (_requested_return_frame >= 0) {
413                                 _transport_frame = _requested_return_frame;
414                                 _requested_return_frame = -1;
415                                 do_locate = true;
416                         } else {
417                                 _transport_frame = last_stop_frame;
418                                 _requested_return_frame = -1;
419                         }
420
421                         if (synced_to_jack() && !play_loop) {
422                                 do_locate = true;
423                         }
424                         
425                         if (do_locate) {
426                                 // cerr << "non-realtimestop: transport locate to " << _transport_frame << endl;
427                                 _engine.transport_locate (_transport_frame);
428                         }
429                 } 
430
431 #ifndef LEAVE_TRANSPORT_UNADJUSTED
432         }
433 #endif
434
435                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
436                         if (!(*i)->hidden()) {
437                                 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
438                                         (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
439                                 }
440                                 else {
441                                         (*i)->seek (_transport_frame);
442                                 }
443                         }
444                         if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
445                                 finished = false;
446                                 /* we will be back */
447                                 return;
448                         }
449                 }
450
451 #ifdef LEAVE_TRANSPORT_UNADJUSTED
452         }
453 #endif
454
455         if (_requested_return_frame < 0) {
456                 last_stop_frame = _transport_frame;
457         } else {
458                 last_stop_frame = _requested_return_frame;
459                 _requested_return_frame = -1;
460         }
461
462         if (did_record) {
463
464                 /* XXX its a little odd that we're doing this here
465                    when realtime_stop(), which has already executed,
466                    will have done this.
467                    JLC - so let's not because it seems unnecessary and breaks loop record
468                 */
469 #if 0
470                 if (!Config->get_latched_record_enable()) {
471                         g_atomic_int_set (&_record_status, Disabled);
472                 } else {
473                         g_atomic_int_set (&_record_status, Enabled);
474                 }
475                 RecordStateChanged (); /* emit signal */
476 #endif
477         }
478         
479         if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
480                 /* capture start has been changed, so save pending state */
481                 save_state ("", true);
482                 saved = true;
483         }
484
485         /* always try to get rid of this */
486
487         remove_pending_capture_state ();
488         
489         /* save the current state of things if appropriate */
490
491         if (did_record && !saved) {
492                 save_state (_current_snapshot_name);
493         }
494
495         if (post_transport_work & PostTransportDuration) {
496                 DurationChanged (); /* EMIT SIGNAL */
497         }
498
499         if (post_transport_work & PostTransportStop) { 
500                 _play_range = false;
501
502                 /* do not turn off autoloop on stop */
503                 
504         }
505
506         nframes_t tf = _transport_frame;
507
508         PositionChanged (tf); /* EMIT SIGNAL */
509         TransportStateChange (); /* EMIT SIGNAL */
510
511         /* and start it up again if relevant */
512
513         if ((post_transport_work & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
514                 request_transport_speed (1.0);
515                 pending_locate_roll = false;
516         }
517 }
518
519 void
520 Session::check_declick_out ()
521 {
522         bool locate_required = transport_sub_state & PendingLocate;
523
524         /* this is called after a process() iteration. if PendingDeclickOut was set,
525            it means that we were waiting to declick the output (which has just been
526            done) before doing something else. this is where we do that "something else".
527            
528            note: called from the audio thread.
529         */
530
531         if (transport_sub_state & PendingDeclickOut) {
532
533                 if (locate_required) {
534                         start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
535                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
536                 } else {
537                         stop_transport (pending_abort);
538                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
539                 }
540         }
541 }
542
543 void
544 Session::set_play_loop (bool yn)
545 {
546         /* Called from event-handling context */
547         
548         if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
549                 return;
550         }
551         
552         set_dirty();
553
554         if (yn && Config->get_seamless_loop() && synced_to_jack()) {
555                 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
556                              "Recommend changing the configured options")
557                         << endmsg;
558                 return;
559         }
560
561         
562         if ((play_loop = yn)) {
563
564                 Location *loc;
565
566                 
567                 if ((loc = _locations.auto_loop_location()) != 0) {
568
569                         if (Config->get_seamless_loop()) {
570                                 // set all diskstreams to use internal looping
571                                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
572                                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
573                                         if (!(*i)->hidden()) {
574                                                 (*i)->set_loop (loc);
575                                         }
576                                 }
577                         }
578                         else {
579                                 // set all diskstreams to NOT use internal looping
580                                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
581                                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
582                                         if (!(*i)->hidden()) {
583                                                 (*i)->set_loop (0);
584                                         }
585                                 }
586                         }
587                         
588                         /* stick in the loop event */
589                         
590                         Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
591                         merge_event (event);
592
593                         /* locate to start of loop and roll if current pos is outside of the loop range */
594                         if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
595                                 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
596                                 merge_event (event);
597                         }
598                         else {
599                                 // locate to current position (+ 1 to force reload)
600                                 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
601                                 merge_event (event);
602                         }
603                 }
604
605
606
607         } else {
608                 clear_events (Event::AutoLoop);
609
610                 // set all diskstreams to NOT use internal looping
611                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
612                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
613                         if (!(*i)->hidden()) {
614                                 (*i)->set_loop (0);
615                         }
616                 }
617                 
618         }
619 }
620
621 void
622 Session::flush_all_inserts ()
623 {
624         boost::shared_ptr<RouteList> r = routes.reader ();
625
626         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
627                 (*i)->flush_processors ();
628         }
629 }
630
631 void
632 Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
633 {
634         if (synced_to_jack()) {
635
636                 float sp;
637                 nframes_t pos;
638
639                 _slave->speed_and_position (sp, pos);
640
641                 if (target_frame != pos) {
642
643                         /* tell JACK to change transport position, and we will
644                            follow along later in ::follow_slave()
645                         */
646
647                         _engine.transport_locate (target_frame);
648
649                         if (sp != 1.0f && with_roll) {
650                                 _engine.transport_start ();
651                         }
652
653                 }
654
655         } else {
656
657                 locate (target_frame, with_roll, with_flush, with_loop);
658         }
659 }
660
661 void
662 Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
663 {
664         if (actively_recording() && !with_loop) {
665                 return;
666         }
667
668         if (_transport_frame == target_frame && !loop_changing && !with_loop) {
669                 if (with_roll) {
670                         set_transport_speed (1.0, false);
671                 }
672                 loop_changing = false;
673                 return;
674         }
675
676         // Update SMPTE time
677         // [DR] FIXME: find out exactly where this should go below
678         _transport_frame = target_frame;
679         smpte_time(_transport_frame, transmitting_smpte_time);
680         outbound_mtc_smpte_frame = _transport_frame;
681         next_quarter_frame_to_send = 0;
682
683         if (_transport_speed && (!with_loop || loop_changing)) {
684                 /* schedule a declick. we'll be called again when its done */
685
686                 if (!(transport_sub_state & PendingDeclickOut)) {
687                         transport_sub_state |= (PendingDeclickOut|PendingLocate);
688                         pending_locate_frame = target_frame;
689                         pending_locate_roll = with_roll;
690                         pending_locate_flush = with_flush;
691                         return;
692                 } 
693         }
694
695         if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
696                 realtime_stop (false);
697         } 
698
699         if ( !with_loop || loop_changing) {
700
701                 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
702                 
703                 if (with_roll) {
704                         post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
705                 }
706
707                 schedule_butler_transport_work ();
708
709         } else {
710
711                 /* this is functionally what clear_clicks() does but with a tentative lock */
712
713                 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
714         
715                 if (clickm.locked()) {
716                         
717                         for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
718                                 delete *i;
719                         }
720                 
721                         clicks.clear ();
722                 }
723         }
724
725         if (with_roll) {
726                 /* switch from input if we're going to roll */
727                 if (Config->get_monitoring_model() == HardwareMonitoring) {
728
729                         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
730
731                         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
732                                 if ((*i)->record_enabled ()) {
733                                         //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
734                                         (*i)->monitor_input (!Config->get_auto_input());
735                                 }
736                         }
737                 }
738         } else {
739                 /* otherwise we're going to stop, so do the opposite */
740                 if (Config->get_monitoring_model() == HardwareMonitoring) {
741                         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
742
743                         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
744                                 if ((*i)->record_enabled ()) {
745                                         //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
746                                         (*i)->monitor_input (true);
747                                 }
748                         }
749                 }
750         }
751
752         /* cancel looped playback if transport pos outside of loop range */
753         if (play_loop) {
754                 Location* al = _locations.auto_loop_location();
755                 
756                 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
757                         // cancel looping directly, this is called from event handling context
758                         set_play_loop (false);
759                 }
760                 else if (al && _transport_frame == al->start()) {
761                         if (with_loop) {
762                                 // this is only necessary for seamless looping
763
764                                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
765                                 
766                                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
767                                         if ((*i)->record_enabled ()) {
768                                                 // tell it we've looped, so it can deal with the record state
769                                                 (*i)->transport_looped(_transport_frame);
770                                         }
771                                 }
772                         }
773
774                         TransportLooped(); // EMIT SIGNAL
775                 }
776         }
777         
778         loop_changing = false;
779
780         _send_smpte_update = true;
781 }
782
783 /** Set the transport speed.
784  * @param speed New speed
785  * @param abort
786  */
787 void
788 Session::set_transport_speed (float speed, bool abort)
789 {
790         if (_transport_speed == speed) {
791                 return;
792         }
793
794         if (speed > 0) {
795                 speed = min (8.0f, speed);
796         } else if (speed < 0) {
797                 speed = max (-8.0f, speed);
798         }
799
800         if (transport_rolling() && speed == 0.0) {
801
802                 /* we are rolling and we want to stop */
803
804                 if (Config->get_monitoring_model() == HardwareMonitoring)
805                 {
806                         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
807
808                         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
809                                 if ((*i)->record_enabled ()) {
810                                         //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
811                                         (*i)->monitor_input (true);     
812                                 }
813                         }
814                 }
815
816                 if (synced_to_jack ()) {
817                         _engine.transport_stop ();
818                 } else {
819                         stop_transport (abort);
820                 }
821                 
822         } else if (transport_stopped() && speed == 1.0) {
823
824                 /* we are stopped and we want to start rolling at speed 1 */
825
826                 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
827                         return;
828                 }
829
830                 if (Config->get_monitoring_model() == HardwareMonitoring) {
831
832                         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
833
834                         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
835                                 if (Config->get_auto_input() && (*i)->record_enabled ()) {
836                                         //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
837                                         (*i)->monitor_input (false);    
838                                 }
839                         }
840                 }
841
842                 if (synced_to_jack()) {
843                         _engine.transport_start ();
844                 } else {
845                         start_transport ();
846                 }
847
848         } else {
849
850                 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
851                         return;
852                 }
853
854                 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
855                         warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
856                                 << endmsg;
857                         return;
858                 }
859
860                 if (actively_recording()) {
861                         return;
862                 }
863
864                 if (speed > 0.0f && _transport_frame == current_end_frame()) {
865                         return;
866                 }
867
868                 if (speed < 0.0f && _transport_frame == 0) {
869                         return;
870                 }
871                 
872                 clear_clicks ();
873
874                 /* if we are reversing relative to the current speed, or relative to the speed
875                    before the last stop, then we have to do extra work.
876                 */
877
878                 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
879                         post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
880                 }
881                 
882                 _last_transport_speed = _transport_speed;
883                 _transport_speed = speed;
884                 
885                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
886                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
887                         if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
888                                 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
889                         }
890                 }
891                 
892                 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
893                         schedule_butler_transport_work ();
894                 }
895         }
896 }
897
898
899 /** Stop the transport.  */
900 void
901 Session::stop_transport (bool abort)
902 {
903         if (_transport_speed == 0.0f) {
904                 return;
905         }
906         
907         if (actively_recording() && !(transport_sub_state & StopPendingCapture) && 
908             _worst_output_latency > current_block_size) 
909         {
910                 
911                 /* we need to capture the audio that has still not yet been received by the system
912                    at the time the stop is requested, so we have to roll past that time.
913
914                    we want to declick before stopping, so schedule the autostop for one
915                    block before the actual end. we'll declick in the subsequent block,
916                    and then we'll really be stopped.
917                 */
918                 
919                 Event *ev = new Event (Event::StopOnce, Event::Replace, 
920                                        _transport_frame + _worst_output_latency - current_block_size,
921                                        0, 0, abort);
922                 
923                 merge_event (ev);
924                 transport_sub_state |= StopPendingCapture;
925                 pending_abort = abort;
926                 return;
927         } 
928
929
930         if ((transport_sub_state & PendingDeclickOut) == 0) {
931                 transport_sub_state |= PendingDeclickOut;
932                 /* we'll be called again after the declick */
933                 pending_abort = abort;
934                 return;
935         }
936
937         realtime_stop (abort);
938         schedule_butler_transport_work ();
939 }
940
941 void
942 Session::start_transport ()
943 {
944         _last_roll_location = _transport_frame;
945
946         /* if record status is Enabled, move it to Recording. if its
947            already Recording, move it to Disabled. 
948         */
949
950         switch (record_status()) {
951         case Enabled:
952                 if (!Config->get_punch_in()) {
953                         enable_record ();
954                 }
955                 break;
956
957         case Recording:
958                 if (!play_loop) {
959                         disable_record (false);
960                 }
961                 break;
962
963         default:
964                 break;
965         }
966
967         if (!synced_to_jack() || _exporting) {
968                 actually_start_transport ();
969         } else {
970                 waiting_to_start = true;
971         }
972 }
973
974 void
975 Session::actually_start_transport ()
976 {
977         waiting_to_start = false;
978
979         transport_sub_state |= PendingDeclickIn;
980         _transport_speed = 1.0;
981         
982         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
983         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
984                 (*i)->realtime_set_speed ((*i)->speed(), true);
985         }
986
987         deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
988
989         TransportStateChange (); /* EMIT SIGNAL */
990 }
991
992 /** Do any transport work in the audio thread that needs to be done after the
993  * transport thread is finished.  Audio thread, realtime safe.
994  */
995 void
996 Session::post_transport ()
997 {
998         if (post_transport_work & PostTransportAudition) {
999                 if (auditioner && auditioner->active()) {
1000                         process_function = &Session::process_audition;
1001                 } else {
1002                         process_function = &Session::process_with_events;
1003                 }
1004         }
1005
1006         if (post_transport_work & PostTransportStop) {
1007
1008                 transport_sub_state = 0;
1009         }
1010
1011         if (post_transport_work & PostTransportLocate) {
1012
1013                 if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
1014                         start_transport ();
1015                         
1016                 } else {
1017                         transport_sub_state = 0;
1018                 }
1019         }
1020
1021         set_next_event ();
1022
1023         post_transport_work = PostTransportWork (0);
1024 }
1025
1026 void
1027 Session::reset_rf_scale (nframes_t motion)
1028 {
1029         cumulative_rf_motion += motion;
1030
1031         if (cumulative_rf_motion < 4 * _current_frame_rate) {
1032                 rf_scale = 1;
1033         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1034                 rf_scale = 4;
1035         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1036                 rf_scale = 10;
1037         } else {
1038                 rf_scale = 100;
1039         }
1040
1041         if (motion != 0) {
1042                 set_dirty();
1043         }
1044 }
1045
1046 void
1047 Session::set_slave_source (SlaveSource src)
1048 {
1049         bool reverse = false;
1050         bool non_rt_required = false;
1051
1052         if (_transport_speed) {
1053                 error << _("please stop the transport before adjusting slave settings") << endmsg;
1054                 return;
1055         }
1056
1057 //      if (src == JACK && Config->get_jack_time_master()) {
1058 //              return;
1059 //      }
1060         
1061         if (_slave) {
1062                 delete _slave;
1063                 _slave = 0;
1064         }
1065
1066         if (_transport_speed < 0.0) {
1067                 reverse = true;
1068         }
1069
1070         switch (src) {
1071         case None:
1072                 stop_transport ();
1073                 break;
1074                 
1075         case MTC:
1076                 if (_mtc_port) {
1077                         try {
1078                                 _slave = new MTC_Slave (*this, *_mtc_port);
1079                         }
1080
1081                         catch (failed_constructor& err) {
1082                                 return;
1083                         }
1084
1085                 } else {
1086                         error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1087                         return;
1088                 }
1089                 _desired_transport_speed = _transport_speed;
1090                 break;
1091                 
1092         case JACK:
1093                 _slave = new JACK_Slave (_engine.jack());
1094                 _desired_transport_speed = _transport_speed;
1095                 break;
1096         };
1097
1098         Config->set_slave_source (src);
1099         
1100         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1101         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1102                 if (!(*i)->hidden()) {
1103                         if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1104                                 non_rt_required = true;
1105                         }
1106                         (*i)->set_slaved (_slave);
1107                 }
1108         }
1109
1110         if (reverse) {
1111                 reverse_diskstream_buffers ();
1112         }
1113
1114         if (non_rt_required) {
1115                 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1116                 schedule_butler_transport_work ();
1117         }
1118
1119         set_dirty();
1120 }
1121
1122 void
1123 Session::reverse_diskstream_buffers ()
1124 {
1125         post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1126         schedule_butler_transport_work ();
1127 }
1128
1129 void
1130 Session::set_diskstream_speed (Diskstream* stream, float speed)
1131 {
1132         if (stream->realtime_set_speed (speed, false)) {
1133                 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1134                 schedule_butler_transport_work ();
1135                 set_dirty ();
1136         }
1137 }
1138
1139 void
1140 Session::set_audio_range (list<AudioRange>& range)
1141 {
1142         Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1143         ev->audio_range = range;
1144         queue_event (ev);
1145 }
1146
1147 void
1148 Session::request_play_range (bool yn)
1149 {
1150         Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1151         queue_event (ev);
1152 }
1153
1154 void
1155 Session::set_play_range (bool yn)
1156 {
1157         /* Called from event-processing context */
1158
1159         if (_play_range != yn) {
1160                 _play_range = yn;
1161                 setup_auto_play ();
1162
1163                 if (!_play_range) {
1164                         /* stop transport */
1165                         Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1166                         merge_event (ev);
1167                 }
1168         }
1169 }
1170
1171 void
1172 Session::setup_auto_play ()
1173 {
1174         /* Called from event-processing context */
1175
1176         Event* ev;
1177         
1178         _clear_event_type (Event::RangeStop);
1179         _clear_event_type (Event::RangeLocate);
1180
1181         if (!_play_range) {
1182                 return;
1183         }
1184
1185         list<AudioRange>::size_type sz = current_audio_range.size();
1186         
1187         if (sz > 1) {
1188                 
1189                 list<AudioRange>::iterator i = current_audio_range.begin(); 
1190                 list<AudioRange>::iterator next;
1191                 
1192                 while (i != current_audio_range.end()) {
1193                         
1194                         next = i;
1195                         ++next;
1196                         
1197                         /* locating/stopping is subject to delays for declicking.
1198                          */
1199                         
1200                         nframes_t requested_frame = (*i).end;
1201                         
1202                         if (requested_frame > current_block_size) {
1203                                 requested_frame -= current_block_size;
1204                         } else {
1205                                 requested_frame = 0;
1206                         }
1207                         
1208                         if (next == current_audio_range.end()) {
1209                                 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1210                         } else {
1211                                 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1212                         }
1213                         
1214                         merge_event (ev);
1215                         
1216                         i = next;
1217                 }
1218                 
1219         } else if (sz == 1) {
1220                 
1221                 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1222                 merge_event (ev);
1223                 
1224         } 
1225
1226         /* now start rolling at the right place */
1227         
1228         ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1229         merge_event (ev);
1230 }
1231
1232 void
1233 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1234 {
1235         Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0);
1236         ev->target2_frame = start;
1237         queue_event (ev);
1238 }
1239
1240 void
1241 Session::request_bounded_roll (nframes_t start, nframes_t end)
1242 {
1243         request_stop ();
1244         Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0);
1245         queue_event (ev);
1246         request_locate (start, true);
1247 }
1248
1249 void
1250 Session::engine_halted ()
1251 {
1252         bool ignored;
1253
1254         /* there will be no more calls to process(), so
1255            we'd better clean up for ourselves, right now.
1256
1257            but first, make sure the butler is out of 
1258            the picture.
1259         */
1260
1261         g_atomic_int_set (&butler_should_do_transport_work, 0);
1262         post_transport_work = PostTransportWork (0);
1263         stop_butler ();
1264         
1265         realtime_stop (false);
1266         non_realtime_stop (false, 0, ignored);
1267         transport_sub_state = 0;
1268
1269         TransportStateChange (); /* EMIT SIGNAL */
1270 }
1271
1272
1273 void
1274 Session::xrun_recovery ()
1275 {
1276         Xrun (transport_frame()); //EMIT SIGNAL
1277
1278         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1279
1280                 /* it didn't actually halt, but we need
1281                    to handle things in the same way.
1282                 */
1283
1284                 engine_halted();
1285         } 
1286 }
1287
1288 void
1289 Session::update_latency_compensation (bool with_stop, bool abort)
1290 {
1291         bool update_jack = false;
1292
1293         if (_state_of_the_state & Deletion) {
1294                 return;
1295         }
1296
1297         _worst_track_latency = 0;
1298
1299         boost::shared_ptr<RouteList> r = routes.reader ();
1300
1301         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1302                 
1303                 if (with_stop) {
1304                         (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate), 
1305                                                         (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1306                 }
1307                 
1308                 nframes_t old_latency = (*i)->signal_latency ();
1309                 nframes_t track_latency = (*i)->update_total_latency ();
1310                 
1311                 if (old_latency != track_latency) {
1312                         (*i)->update_port_total_latencies ();
1313                         update_jack = true;
1314                 }
1315
1316                 if (!(*i)->is_hidden() && ((*i)->active())) {
1317                         _worst_track_latency = max (_worst_track_latency, track_latency);
1318                 }
1319         } 
1320
1321         if (update_jack) {
1322                 _engine.update_total_latencies ();
1323         }
1324
1325         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1326                 (*i)->set_latency_delay (_worst_track_latency);
1327         }
1328
1329         set_worst_io_latencies ();
1330
1331         /* reflect any changes in latencies into capture offsets
1332         */
1333         
1334         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1335
1336         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1337                 (*i)->set_capture_offset ();
1338         }
1339 }
1340
1341 void
1342 Session::allow_auto_play (bool yn)
1343 {
1344         auto_play_legal = yn;
1345 }
1346
1347 void
1348 Session::reset_jack_connection (jack_client_t* jack)
1349 {
1350         JACK_Slave* js;
1351
1352         if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1353                 js->reset_client (jack);
1354         }
1355 }