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