added mutable keyword to gints used in glib atomic operations to satisfy compiler...
[ardour.git] / libs / ardour / session_transport.cc
index 82b067a288c54fe23782955479ad33413cf13fe9..db15b64c325221f8758d176848b408a86e205cc8 100644 (file)
@@ -27,7 +27,7 @@
 
 #include <pbd/undo.h>
 #include <pbd/error.h>
-#include <pbd/lockmonitor.h>
+#include <glibmm/thread.h>
 #include <pbd/pthread_utils.h>
 
 #include <midi++/mmc.h>
@@ -165,22 +165,11 @@ Session::realtime_stop (bool abort)
                decrement_transport_position (_worst_output_latency);
 #endif
 
-               if (_transport_frame > current_end_frame()) {
-                       
-                       /* first capture resets end location; later captures can only extend the length */
-
-                       if (_end_location_is_free) {
-                               end_location->set_end (_transport_frame);
-                               _end_location_is_free = false;
-                       } else if (_transport_frame > end_location->start()) {
-                               end_location->set_end (_transport_frame);
-                       }
+               /* the duration change is not guaranteed to have happened, but is likely */
 
-                       post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
-               }
+               post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
        }
 
-
        if (abort) {
                post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
        }
@@ -189,7 +178,7 @@ Session::realtime_stop (bool abort)
        _clear_event_type (Event::RangeStop);
        _clear_event_type (Event::RangeLocate);
 
-       disable_record ();
+       disable_record (true);
 
        reset_slave_state ();
                
@@ -201,8 +190,8 @@ Session::realtime_stop (bool abort)
 void
 Session::butler_transport_work ()
 {
-       RWLockMonitor rm (route_lock, false, __LINE__, __FILE__);
-       RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
+       Glib::RWLock::ReaderLock rm (route_lock);
+       Glib::RWLock::ReaderLock dsm (diskstream_lock);
                
        if (post_transport_work & PostTransportCurveRealloc) {
                for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
@@ -251,13 +240,13 @@ Session::butler_transport_work ()
                non_realtime_set_audition ();
        }
 
-       atomic_dec (&butler_should_do_transport_work);
+       g_atomic_int_dec_and_test (&butler_should_do_transport_work);
 }
 
 void
 Session::non_realtime_set_speed ()
 {
-       RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
+       Glib::RWLock::ReaderLock lm (diskstream_lock);
 
        for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->non_realtime_set_speed ();
@@ -267,7 +256,7 @@ Session::non_realtime_set_speed ()
 void
 Session::non_realtime_overwrite ()
 {
-       RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
+       Glib::RWLock::ReaderLock lm (diskstream_lock);
 
        for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if ((*i)->pending_overwrite) {
@@ -282,9 +271,9 @@ Session::non_realtime_stop (bool abort)
        struct tm* now;
        time_t     xnow;
        bool       did_record;
-
+       
        did_record = false;
-
+       
        for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if ((*i)->get_captured_frames () != 0) {
                        did_record = true;
@@ -307,21 +296,34 @@ Session::non_realtime_stop (bool abort)
 
        if (did_record) {
                begin_reversible_command ("capture");
-
+               
                Location* loc = _locations.end_location();
+               bool change_end = false;
 
-               if (loc && !_have_captured) {
-                               
-                       /* first capture.
-                          
-                          note: later captures that extend the session length get
-                          handled because of playlist length changes.
-                       */
+               if (_transport_frame < loc->end()) {
+
+                       /* stopped recording before current end */
+
+                       if (_end_location_is_free) {
+
+                               /* first capture for this session, move end back to where we are */
+
+                               change_end = true;
+                       } 
+
+               } else if (_transport_frame > loc->end()) {
                        
-                 add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
-                 add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
+                       /* stopped recording after the current end, extend it */
+
+                       change_end = true;
+               }
+               
+               if (change_end) {
+                       add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
+                       add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
                }
 
+               _end_location_is_free = false;
                _have_captured = true;
        }
 
@@ -386,8 +388,18 @@ Session::non_realtime_stop (bool abort)
        deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
 
        if (did_record) {
-               atomic_set (&_record_status, Disabled);
-               RecordDisabled (); /* EMIT SIGNAL */
+
+               /* XXX its a little odd that we're doing this here
+                  when realtime_stop(), which has already executed,
+                  will have done this.
+               */
+
+               if (!Config->get_latched_record_enable()) {
+                       g_atomic_int_set (&_record_status, Disabled);
+               } else {
+                       g_atomic_int_set (&_record_status, Enabled);
+               }
+               RecordStateChanged (); /* emit signal */
        }
        
        if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
@@ -395,8 +407,12 @@ Session::non_realtime_stop (bool abort)
                save_state ("", true);
        }
 
-       /* save the current state of things if appropriate */
+        /* always try to get rid of this */
+
+        remove_pending_capture_state ();
        
+       /* save the current state of things if appropriate */
+
        if (did_record) {
                save_state (_current_snapshot_name);
        }
@@ -609,7 +625,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
 
                /* this is functionally what clear_clicks() does but with a tentative lock */
 
-               TentativeRWLockMonitor clickm (click_lock, true, __LINE__, __FILE__);
+               Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
        
                if (clickm.locked()) {
                        
@@ -628,10 +644,10 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
                           a non-tentative rwlock here,  because the action must occur.
                           The rarity and short potential lock duration makes this "OK"
                        */
-                       RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
+                       Glib::RWLock::ReaderLock dsm (diskstream_lock);
                        for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
-                                       cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
+                                       //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (!auto_input);
                                }
                        }
@@ -643,10 +659,10 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
                           a non-tentative rwlock here,  because the action must occur.
                           The rarity and short potential lock duration makes this "OK"
                        */
-                       RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
+                       Glib::RWLock::ReaderLock dsm (diskstream_lock);
                        for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
-                                       cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
+                                       //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (true);
                                }
                        }
@@ -687,7 +703,7 @@ Session::set_transport_speed (float speed, bool abort)
                           a non-tentative rwlock here,  because the action must occur.
                           The rarity and short potential lock duration makes this "OK"
                        */
-                       RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
+                       Glib::RWLock::ReaderLock dsm (diskstream_lock);
                        for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
@@ -704,12 +720,16 @@ Session::set_transport_speed (float speed, bool abort)
 
        } else if (transport_stopped() && speed == 1.0) {
 
+               if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
+                       return;
+               }
+
                if (Config->get_use_hardware_monitoring()) {
                        /* Even though this is called from RT context we are using
                           a non-tentative rwlock here,  because the action must occur.
                           The rarity and short potential lock duration makes this "OK"
                        */
-                       RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
+                       Glib::RWLock::ReaderLock dsm (diskstream_lock);
                        for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if (auto_input && (*i)->record_enabled ()) {
                                        //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
@@ -726,6 +746,10 @@ Session::set_transport_speed (float speed, bool abort)
 
        } else {
 
+               if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
+                       return;
+               }
+
                if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
                        warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
                                << endmsg;
@@ -825,7 +849,7 @@ Session::start_transport ()
                break;
 
        case Recording:
-               disable_record ();
+               disable_record (false);
                break;
 
        default:
@@ -922,17 +946,17 @@ Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
        bool reverse = false;
        bool non_rt_required = false;
 
+       if (src == _slave_type) {
+               return 0;
+       } 
+
        if (_transport_speed) {
                error << _("please stop the transport before adjusting slave settings") << endmsg;
                /* help out non-MVC friendly UI's by telling them the slave type changed */
-                ControlChanged (SlaveType); /* EMIT SIGNAL */
+               ControlChanged (SlaveType); /* EMIT SIGNAL */
                return 0;
        }
 
-       if (src == _slave_type) {
-               return 0;
-       } 
-
 //     if (src == JACK && Config->get_jack_time_master()) {
 //             return -1;
 //     }
@@ -1132,7 +1156,7 @@ Session::engine_halted ()
           the picture.
        */
 
-       atomic_set (&butler_should_do_transport_work, 0);
+       g_atomic_int_set (&butler_should_do_transport_work, 0);
        post_transport_work = PostTransportWork (0);
        stop_butler ();
        
@@ -1168,8 +1192,8 @@ Session::update_latency_compensation (bool with_stop, bool abort)
                return;
        }
 
-       RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
-       RWLockMonitor lm2 (diskstream_lock, false, __LINE__, __FILE__);
+       Glib::RWLock::ReaderLock lm (route_lock);
+       Glib::RWLock::ReaderLock lm2 (diskstream_lock);
        _worst_track_latency = 0;
 
        for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {