Re-enable creation of stereo bundles for system IO, so that the mixer strip
[ardour.git] / libs / ardour / session.cc
index 67ea01b8bfdf0402de53afaa68f5dd51b9028a1a..ed5ff668aad41d122f9584ac59f258d38b38e13f 100644 (file)
 #include <pbd/stacktrace.h>
 #include <pbd/file_utils.h>
 
-#include <ardour/audioengine.h>
-#include <ardour/configuration.h>
-#include <ardour/session.h>
-#include <ardour/session_directory.h>
-#include <ardour/session_metadata.h>
-#include <ardour/utils.h>
+#include <ardour/analyser.h>
+#include <ardour/audio_buffer.h>
 #include <ardour/audio_diskstream.h>
+#include <ardour/audio_track.h>
+#include <ardour/audioengine.h>
+#include <ardour/audiofilesource.h>
 #include <ardour/audioplaylist.h>
 #include <ardour/audioregion.h>
-#include <ardour/audiofilesource.h>
+#include <ardour/auditioner.h>
+#include <ardour/buffer_set.h>
+#include <ardour/bundle.h>
+#include <ardour/click.h>
+#include <ardour/configuration.h>
+#include <ardour/crossfade.h>
+#include <ardour/cycle_timer.h>
+#include <ardour/data_type.h>
+#include <ardour/filename_extensions.h>
+#include <ardour/internal_send.h>
+#include <ardour/io_processor.h>
 #include <ardour/midi_diskstream.h>
 #include <ardour/midi_playlist.h>
 #include <ardour/midi_region.h>
-#include <ardour/smf_source.h>
-#include <ardour/auditioner.h>
-#include <ardour/recent_sessions.h>
-#include <ardour/io_processor.h>
-#include <ardour/send.h>
-#include <ardour/processor.h>
-#include <ardour/plugin_insert.h>
-#include <ardour/port_insert.h>
-#include <ardour/slave.h>
-#include <ardour/tempo.h>
-#include <ardour/audio_track.h>
 #include <ardour/midi_track.h>
-#include <ardour/cycle_timer.h>
 #include <ardour/named_selection.h>
-#include <ardour/crossfade.h>
 #include <ardour/playlist.h>
-#include <ardour/click.h>
-#include <ardour/data_type.h>
-#include <ardour/buffer_set.h>
-#include <ardour/source_factory.h>
+#include <ardour/plugin_insert.h>
+#include <ardour/port_insert.h>
+#include <ardour/processor.h>
+#include <ardour/recent_sessions.h>
 #include <ardour/region_factory.h>
-#include <ardour/filename_extensions.h>
+#include <ardour/route_group.h>
+#include <ardour/send.h>
+#include <ardour/session.h>
 #include <ardour/session_directory.h>
+#include <ardour/session_directory.h>
+#include <ardour/session_metadata.h>
+#include <ardour/slave.h>
+#include <ardour/smf_source.h>
+#include <ardour/source_factory.h>
 #include <ardour/tape_file_matcher.h>
-#include <ardour/analyser.h>
-#include <ardour/bundle.h>
-
-#ifdef HAVE_LIBLO
-#include <ardour/osc.h>
-#endif
+#include <ardour/tempo.h>
+#include <ardour/utils.h>
 
 #include "i18n.h"
 
@@ -120,6 +119,7 @@ Session::Session (AudioEngine &eng,
                  string mix_template)
 
        : _engine (eng),
+         _requested_return_frame (-1),
          _scratch_buffers(new BufferSet()),
          _silent_buffers(new BufferSet()),
          _mix_buffers(new BufferSet()),
@@ -141,6 +141,7 @@ Session::Session (AudioEngine &eng,
          routes (new RouteList),
          auditioner ((Auditioner*) 0),
          _total_free_4k_blocks (0),
+         _bundles (new BundleList),
          _bundle_xml_node (0),
          _click_io ((IO*) 0),
          click_data (0),
@@ -201,6 +202,7 @@ Session::Session (AudioEngine &eng,
                  nframes_t initial_length)
 
        : _engine (eng),
+         _requested_return_frame (-1),
          _scratch_buffers(new BufferSet()),
          _silent_buffers(new BufferSet()),
          _mix_buffers(new BufferSet()),
@@ -222,6 +224,7 @@ Session::Session (AudioEngine &eng,
          routes (new RouteList),
          auditioner ((Auditioner *) 0),
          _total_free_4k_blocks (0),
+         _bundles (new BundleList),
          _bundle_xml_node (0),
          _click_io ((IO *) 0),
          click_data (0),
@@ -589,64 +592,66 @@ Session::when_engine_running ()
                // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
        }
 
-       /* Create a set of Bundle objects that map
-          to the physical outputs currently available
-       */
-
        BootMessage (_("Set up standard connections"));
 
-       /* ONE: MONO */
+       /* Create a set of Bundle objects that map
+          to the physical I/O currently available.  We create both
+          mono and stereo bundles, so that the common cases of mono
+          and stereo tracks get bundles to put in their mixer strip
+          in / out menus.  There may be a nicer way of achieving that;
+          it doesn't really scale that well to higher channel counts */
 
        for (uint32_t np = 0; np < n_physical_outputs; ++np) {
                char buf[32];
                snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
 
                shared_ptr<Bundle> c (new Bundle (buf, true));
-               c->set_nchannels (1);
+               c->add_channel (_("mono"));
                c->set_port (0, _engine.get_nth_physical_output (DataType::AUDIO, np));
 
                add_bundle (c);
        }
 
+       for (uint32_t np = 0; np < n_physical_outputs; np += 2) {
+               if (np + 1 < n_physical_outputs) {
+                       char buf[32];
+                       snprintf (buf, sizeof(buf), _("out %" PRIu32 "+%" PRIu32), np + 1, np + 2);
+                       shared_ptr<Bundle> c (new Bundle (buf, true));
+                       c->add_channel (_("L"));
+                       c->set_port (0, _engine.get_nth_physical_output (DataType::AUDIO, np));
+                       c->add_channel (_("R"));
+                       c->set_port (1, _engine.get_nth_physical_output (DataType::AUDIO, np + 1));
+
+                       add_bundle (c);
+               }
+       }
+
        for (uint32_t np = 0; np < n_physical_inputs; ++np) {
                char buf[32];
                snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
 
                shared_ptr<Bundle> c (new Bundle (buf, false));
-               c->set_nchannels (1);
+               c->add_channel (_("mono"));
                c->set_port (0, _engine.get_nth_physical_input (DataType::AUDIO, np));
 
                add_bundle (c);
        }
 
-       /* TWO: STEREO */
-
-       for (uint32_t np = 0; np < n_physical_outputs; np +=2) {
-               char buf[32];
-               snprintf (buf, sizeof (buf), _("out %" PRIu32 "+%" PRIu32), np+1, np+2);
-
-               shared_ptr<Bundle> c (new Bundle (buf, true));
-               c->set_nchannels (2);
-               c->set_port (0, _engine.get_nth_physical_output (DataType::AUDIO, np));
-               c->set_port (1, _engine.get_nth_physical_output (DataType::AUDIO, np + 1));
-
-               add_bundle (c);
-       }
-
-       for (uint32_t np = 0; np < n_physical_inputs; np +=2) {
-               char buf[32];
-               snprintf (buf, sizeof (buf), _("in %" PRIu32 "+%" PRIu32), np+1, np+2);
+       for (uint32_t np = 0; np < n_physical_inputs; np += 2) {
+               if (np + 1 < n_physical_inputs) {
+                       char buf[32];
+                       snprintf (buf, sizeof(buf), _("in %" PRIu32 "+%" PRIu32), np + 1, np + 2);
 
-               shared_ptr<Bundle> c (new Bundle (buf, false));
-               c->set_nchannels (2);
-               c->set_port (0, _engine.get_nth_physical_input (DataType::AUDIO, np));
-               c->set_port (1, _engine.get_nth_physical_input (DataType::AUDIO, np + 1));
+                       shared_ptr<Bundle> c (new Bundle (buf, false));
+                       c->add_channel (_("L"));
+                       c->set_port (0, _engine.get_nth_physical_input (DataType::AUDIO, np));
+                       c->add_channel (_("R"));
+                       c->set_port (1, _engine.get_nth_physical_input (DataType::AUDIO, np + 1));
 
-               add_bundle (c);
+                       add_bundle (c);
+               }
        }
 
-       /* THREE MASTER */
-
        if (_master_out) {
 
                /* create master/control ports */
@@ -728,15 +733,6 @@ Session::when_engine_running ()
        BootMessage (_("Connect to engine"));
 
        _engine.set_session (this);
-
-#ifdef HAVE_LIBLO
-       /* and to OSC */
-
-       BootMessage (_("OSC startup"));
-
-       osc->set_session (*this);
-#endif
-
 }
 
 void
@@ -1253,16 +1249,16 @@ Session::audible_frame () const
                /* MOVING */
 
                /* check to see if we have passed the first guaranteed
-                  audible frame past our last stopping position. if not,
-                  the return that last stopping point because in terms
+                  audible frame past our last start position. if not,
+                  return that last start point because in terms
                   of audible frames, we have not moved yet.
                */
 
                if (_transport_speed > 0.0f) {
 
                        if (!play_loop || !have_looped) {
-                               if (tf < last_stop_frame + offset) {
-                                       return last_stop_frame;
+                               if (tf < _last_roll_location + offset) {
+                                       return _last_roll_location;
                                        
                                }
                        } 
@@ -1275,8 +1271,8 @@ Session::audible_frame () const
 
                        /* XXX wot? no backward looping? */
 
-                       if (tf > last_stop_frame - offset) {
-                               return last_stop_frame;
+                       if (tf > _last_roll_location - offset) {
+                               return _last_roll_location;
                        } else {
                                /* backwards */
                                ret += offset;
@@ -1863,7 +1859,7 @@ Session::set_remote_control_ids ()
 }
 
 
-Session::RouteList
+RouteList
 Session::new_audio_route (int input_channels, int output_channels, uint32_t how_many)
 {
        char bus_name[32];
@@ -2016,13 +2012,6 @@ Session::add_routes (RouteList& new_routes, bool save)
                if ((*x)->is_control()) {
                        _control_out = (*x);
                }
-
-               /* only busses get automatic bundles formed */
-
-               if (!boost::dynamic_pointer_cast<Track> (*x)) {
-                       add_bundle ((*x)->bundle_for_inputs());
-                       add_bundle ((*x)->bundle_for_outputs());
-               }
        }
 
        if (_control_out && IO::connecting_legal) {
@@ -3733,6 +3722,8 @@ Session::add_processor (Processor* processor)
                _plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
        } else if ((send = dynamic_cast<Send *> (processor)) != 0) {
                _sends.insert (_sends.begin(), send);
+       } else if (dynamic_cast<InternalSend *> (processor) != 0) {
+               /* relax */
        } else {
                fatal << _("programming error: unknown type of Insert created!") << endmsg;
                /*NOTREACHED*/
@@ -3758,6 +3749,8 @@ Session::remove_processor (Processor* processor)
                }
        } else if ((plugin_insert = dynamic_cast<PluginInsert *> (processor)) != 0) {
                _plugin_inserts.remove (plugin_insert);
+       } else if (dynamic_cast<InternalSend *> (processor) != 0) {
+               /* relax */
        } else if ((send = dynamic_cast<Send *> (processor)) != 0) {
                list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
                if (x != _sends.end()) {
@@ -3811,8 +3804,9 @@ void
 Session::add_bundle (shared_ptr<Bundle> bundle)
 {
        {
-               Glib::Mutex::Lock guard (bundle_lock);
-               _bundles.push_back (bundle);
+               RCUWriter<BundleList> writer (_bundles);
+               boost::shared_ptr<BundleList> b = writer.get_copy ();
+               b->push_back (bundle);
        }
 
        BundleAdded (bundle); /* EMIT SIGNAL */
@@ -3826,11 +3820,12 @@ Session::remove_bundle (shared_ptr<Bundle> bundle)
        bool removed = false;
 
        {
-               Glib::Mutex::Lock guard (bundle_lock);
-               BundleList::iterator i = find (_bundles.begin(), _bundles.end(), bundle);
+               RCUWriter<BundleList> writer (_bundles);
+               boost::shared_ptr<BundleList> b = writer.get_copy ();
+               BundleList::iterator i = find (b->begin(), b->end(), bundle);
 
-               if (i != _bundles.end()) {
-                       _bundles.erase (i);
+               if (i != b->end()) {
+                       b->erase (i);
                        removed = true;
                }
        }
@@ -3845,9 +3840,9 @@ Session::remove_bundle (shared_ptr<Bundle> bundle)
 shared_ptr<Bundle>
 Session::bundle_by_name (string name) const
 {
-       Glib::Mutex::Lock lm (bundle_lock);
-
-       for (BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
+       boost::shared_ptr<BundleList> b = _bundles.reader ();
+       
+       for (BundleList::const_iterator i = b->begin(); i != b->end(); ++i) {
                if ((*i)->name() == name) {
                        return* i;
                }
@@ -4340,12 +4335,4 @@ Session::sync_order_keys (const char* base)
        Route::SyncOrderKeys (base); // EMIT SIGNAL
 }
 
-void
-Session::foreach_bundle (sigc::slot<void, boost::shared_ptr<Bundle> > sl)
-{
-       Glib::Mutex::Lock lm (bundle_lock);
-       for (BundleList::iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
-               sl (*i);
-       }
-}