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