permanently mark Delivery processors on master/monitor/audition as immune to solo...
[ardour.git] / libs / ardour / session.cc
index d7a71ff0c5f3064673fa0f8ad8c9752c45a529e4..90e58098906c2ee39c326e2d7604b06b51dacd26 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 1999-2004 Paul Davis
+    Copyright (C) 1999-2010 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #include <unistd.h>
 #include <limits.h>
 
-
 #include <glibmm/thread.h>
 #include <glibmm/miscutils.h>
 #include <glibmm/fileutils.h>
-#include <glibmm/thread.h>
 
 #include "pbd/error.h"
 #include "pbd/boost_debug.h"
@@ -54,6 +52,7 @@
 #include "ardour/audioplaylist.h"
 #include "ardour/audioregion.h"
 #include "ardour/auditioner.h"
+#include "ardour/buffer_manager.h"
 #include "ardour/buffer_set.h"
 #include "ardour/bundle.h"
 #include "ardour/butler.h"
@@ -72,6 +71,7 @@
 #include "ardour/midi_track.h"
 #include "ardour/midi_ui.h"
 #include "ardour/named_selection.h"
+#include "ardour/process_thread.h"
 #include "ardour/playlist.h"
 #include "ardour/plugin_insert.h"
 #include "ardour/port_insert.h"
@@ -131,9 +131,6 @@ Session::Session (AudioEngine &eng,
        : _engine (eng),
          _target_transport_speed (0.0),
          _requested_return_frame (-1),
-         _scratch_buffers(new BufferSet()),
-         _silent_buffers(new BufferSet()),
-         _mix_buffers(new BufferSet()),
          mmc (0),
          _mmc_port (default_mmc_port),
          _mtc_port (default_mtc_port),
@@ -232,6 +229,7 @@ Session::destroy ()
 
        Stateful::loading_state_version = 0;
 
+       _butler->drop_references ();
        delete _butler;
        delete midi_control_ui;
 
@@ -245,10 +243,6 @@ Session::destroy ()
 
        clear_clicks ();
 
-       delete _scratch_buffers;
-       delete _silent_buffers;
-       delete _mix_buffers;
-
        /* clear out any pending dead wood from RCU managed objects */
 
        routes.flush ();
@@ -718,9 +712,9 @@ Session::hookup_io ()
 void
 Session::playlist_length_changed ()
 {
-       /* we can't just increase end_location->end() if pl->get_maximum_extent()
+       /* we can't just increase session_range_location->end() if pl->get_maximum_extent()
           if larger. if the playlist used to be the longest playlist,
-          and its now shorter, we have to decrease end_location->end(). hence,
+          and its now shorter, we have to decrease session_range_location->end(). hence,
           we have to iterate over all diskstreams and check the
           playlists currently in use.
        */
@@ -960,11 +954,8 @@ Session::handle_locations_changed (Locations::LocationList& locations)
                        set_loop = true;
                }
 
-               if (location->is_start()) {
-                       start_location = location;
-               }
-               if (location->is_end()) {
-                       end_location = location;
+               if (location->is_session_range()) {
+                       _session_range_location = location;
                }
        }
 
@@ -1043,9 +1034,7 @@ Session::disable_record (bool rt_context, bool force)
 void
 Session::step_back_from_record ()
 {
-       /* XXX really atomic compare+swap here */
-       if (g_atomic_int_get (&_record_status) == Recording) {
-               g_atomic_int_set (&_record_status, Enabled);
+       if (g_atomic_int_compare_and_exchange (&_record_status, Recording, Enabled)) {
 
                if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
                        boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
@@ -1197,12 +1186,7 @@ Session::set_block_size (nframes_t nframes)
        {
                current_block_size = nframes;
 
-               ensure_buffers(_scratch_buffers->available());
-
-               delete [] _gain_automation_buffer;
-               _gain_automation_buffer = new gain_t[nframes];
-
-               allocate_pan_automation_buffers (nframes, _npan_buffers, true);
+               ensure_buffers ();
 
                boost::shared_ptr<RouteList> r = routes.reader ();
 
@@ -2245,7 +2229,7 @@ Session::route_solo_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
                delta = -1;
        }
 
-       /* now mod the solo level of all other routes except master & control outs
+       /* now mod the solo level of all other routes except master/control outs/auditioner
           so that they will be silent if appropriate.
        */
 
@@ -2263,18 +2247,6 @@ Session::route_solo_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
                } 
        }
 
-       /* make sure master is never muted by solo */
-
-       if (_master_out && route != _master_out && _master_out->soloed_by_others() == 0 && !_master_out->soloed()) {
-               _master_out->mod_solo_by_others (1);
-       }
-       /* ditto for control outs make sure master is never muted by solo */
-
-       if (_monitor_out && route != _monitor_out && _monitor_out && _monitor_out->soloed_by_others() == 0) {
-               _monitor_out->mod_solo_by_others (1);
-       }
-
        solo_update_disabled = false;
        update_route_solo_state (r);
        SoloChanged (); /* EMIT SIGNAL */
@@ -2300,7 +2272,11 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
                }
 
                 if (!(*i)->is_hidden() && (*i)->listening()) {
-                        listeners++;
+                        if (Config->get_solo_control_is_listen_control()) {
+                                listeners++;
+                        } else {
+                                (*i)->set_listen (false, this);
+                        }
                 }
        }
 
@@ -2379,8 +2355,8 @@ Session::find_current_end ()
 
        nframes_t max = get_maximum_extent ();
 
-       if (max > end_location->end()) {
-               end_location->set_end (max);
+       if (max > _session_range_location->end()) {
+               _session_range_location->set_end (max);
                set_dirty();
                DurationChanged(); /* EMIT SIGNAL */
        }
@@ -3101,35 +3077,6 @@ Session::graph_reordered ()
        }
 }
 
-void
-Session::add_processor (Processor* processor)
-{
-       /* Session does not own Processors (they belong to a Route) but we do want to track
-          the arrival and departure of port inserts, sends and returns for naming
-          purposes.
-       */
-       processor->DropReferences.connect_same_thread (*this, boost::bind (&Session::remove_processor, this, processor));
-       set_dirty();
-}
-
-void
-Session::remove_processor (Processor* processor)
-{
-       Send* send;
-       Return* retrn;
-       PortInsert* port_insert;
-
-       if ((port_insert = dynamic_cast<PortInsert *> (processor)) != 0) {
-               insert_bitset[port_insert->bit_slot()] = false;
-       } else if ((send = dynamic_cast<Send *> (processor)) != 0) {
-               send_bitset[send->bit_slot()] = false;
-       } else if ((retrn = dynamic_cast<Return *> (processor)) != 0) {
-               return_bitset[retrn->bit_slot()] = false;
-       }
-
-       set_dirty();
-}
-
 nframes_t
 Session::available_capture_duration ()
 {
@@ -3232,18 +3179,7 @@ Session::tempo_map_changed (const PropertyChange&)
 void
 Session::ensure_buffers (ChanCount howmany)
 {
-       if (current_block_size == 0) {
-               return; // too early? (is this ok?)
-       }
-
-       for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
-               size_t count = std::max(_scratch_buffers->available().get(*t), howmany.get(*t));
-               _scratch_buffers->ensure_buffers (*t, count, _engine.raw_buffer_size(*t));
-               _mix_buffers->ensure_buffers (*t, count, _engine.raw_buffer_size(*t));
-               _silent_buffers->ensure_buffers (*t, count, _engine.raw_buffer_size(*t));
-       }
-
-       allocate_pan_automation_buffers (current_block_size, howmany.n_audio(), false);
+        BufferManager::ensure_buffers (howmany);
 }
 
 void
@@ -3350,6 +3286,31 @@ Session::mark_insert_id (uint32_t id)
        insert_bitset[id] = true;
 }
 
+void
+Session::unmark_send_id (uint32_t id)
+{
+       if (id < send_bitset.size()) {
+                send_bitset[id] = false;
+        }
+}
+
+void
+Session::unmark_return_id (uint32_t id)
+{
+       if (id < return_bitset.size()) {
+                return_bitset[id] = false;
+        }
+}
+
+void
+Session::unmark_insert_id (uint32_t id)
+{
+       if (id < insert_bitset.size()) {
+                insert_bitset[id] = false;
+        }
+}
+
+
 /* Named Selection management */
 
 boost::shared_ptr<NamedSelection>
@@ -3437,31 +3398,6 @@ Session::route_name_internal (string n) const
        return false;
 }
 
-void
-Session::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force)
-{
-       if (!force && howmany <= _npan_buffers) {
-               return;
-       }
-
-       if (_pan_automation_buffer) {
-
-               for (uint32_t i = 0; i < _npan_buffers; ++i) {
-                       delete [] _pan_automation_buffer[i];
-               }
-
-               delete [] _pan_automation_buffer;
-       }
-
-       _pan_automation_buffer = new pan_t*[howmany];
-
-       for (uint32_t i = 0; i < howmany; ++i) {
-               _pan_automation_buffer[i] = new pan_t[nframes];
-       }
-
-       _npan_buffers = howmany;
-}
-
 int
 Session::freeze_all (InterThreadInfo& itt)
 {
@@ -3647,9 +3583,23 @@ Session::write_one_track (AudioTrack& track, nframes_t start, nframes_t end,
        return result;
 }
 
+gain_t*
+Session::gain_automation_buffer() const
+{
+        return ProcessThread::gain_automation_buffer ();
+}
+
+pan_t**
+Session::pan_automation_buffer() const
+{
+        return ProcessThread::pan_automation_buffer ();
+}
+
 BufferSet&
 Session::get_silent_buffers (ChanCount count)
 {
+        return ProcessThread::get_silent_buffers (count);
+#if 0
        assert(_silent_buffers->available() >= count);
        _silent_buffers->set_count(count);
 
@@ -3660,11 +3610,14 @@ Session::get_silent_buffers (ChanCount count)
        }
 
        return *_silent_buffers;
+#endif
 }
 
 BufferSet&
 Session::get_scratch_buffers (ChanCount count)
 {
+        return ProcessThread::get_scratch_buffers (count);
+#if 0
        if (count != ChanCount::ZERO) {
                assert(_scratch_buffers->available() >= count);
                _scratch_buffers->set_count(count);
@@ -3673,14 +3626,18 @@ Session::get_scratch_buffers (ChanCount count)
        }
 
        return *_scratch_buffers;
+#endif
 }
 
 BufferSet&
 Session::get_mix_buffers (ChanCount count)
 {
+        return ProcessThread::get_mix_buffers (count);
+#if 0
        assert(_mix_buffers->available() >= count);
        _mix_buffers->set_count(count);
        return *_mix_buffers;
+#endif
 }
 
 uint32_t