Merge branch 'master' into windows
[ardour.git] / libs / ardour / session.cc
index 0e03efa9458d7bae99dfae688edbb9b1d1d59685..428a5e52744b36e8df4e88472bceb8ff138faa92 100644 (file)
@@ -44,8 +44,8 @@
 #include "pbd/stacktrace.h"
 #include "pbd/file_utils.h"
 #include "pbd/convert.h"
-#include "pbd/strsplit.h"
 #include "pbd/unwind.h"
+#include "pbd/search_path.h"
 
 #include "ardour/amp.h"
 #include "ardour/analyser.h"
@@ -140,6 +140,7 @@ Session::Session (AudioEngine &eng,
        , _butler (new Butler (*this))
        , _post_transport_work (0)
        , _send_timecode_update (false)
+       , ltc_enc_buf(0)
        , _all_route_group (new RouteGroup (*this, "all"))
        , routes (new RouteList)
        , _total_free_4k_blocks (0)
@@ -1598,7 +1599,7 @@ Session::find_route_name (string const & base, uint32_t& id, char* name, size_t
                }
 
                ++id;
-
+               
        } while (id < (UINT_MAX-1));
 
        return false;
@@ -1615,7 +1616,7 @@ Session::count_existing_track_channels (ChanCount& in, ChanCount& out)
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
-               if (tr && !tr->is_hidden()) {
+               if (tr && !tr->is_auditioner()) {
                        in  += tr->n_inputs();
                        out += tr->n_outputs();
                }
@@ -2037,12 +2038,13 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
 }
 
 RouteList
-Session::new_route_from_template (uint32_t how_many, const std::string& template_path)
+Session::new_route_from_template (uint32_t how_many, const std::string& template_path, const std::string& name_base)
 {
        RouteList ret;
        uint32_t control_id;
        XMLTree tree;
        uint32_t number = 0;
+       const uint32_t being_added = how_many;
 
        if (!tree.read (template_path.c_str())) {
                return ret;
@@ -2062,13 +2064,29 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
                node_copy.remove_property_recursively (X_("id"));
 
                try {
-                       string const route_name = node_copy.property(X_("name"))->value ();
-                       
-                       /* generate a new name by adding a number to the end of the template name */
                        char name[32];
-                       if (!find_route_name (route_name.c_str(), ++number, name, sizeof(name), true)) {
-                               fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
-                               /*NOTREACHED*/
+
+                       if (!name_base.empty()) {
+
+                               /* if we're adding more than one routes, force
+                                * all the names of the new routes to be
+                                * numbered, via the final parameter.
+                                */
+
+                               if (!find_route_name (name_base.c_str(), ++number, name, sizeof(name), (being_added > 1))) {
+                                       fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
+                                       /*NOTREACHDE*/
+                               }
+
+                       } else {
+
+                               string const route_name  = node_copy.property(X_("name"))->value ();
+                       
+                               /* generate a new name by adding a number to the end of the template name */
+                               if (!find_route_name (route_name.c_str(), ++number, name, sizeof(name), true)) {
+                                       fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
+                                       /*NOTREACHED*/
+                               }
                        }
 
                        /* set this name in the XML description that we are about to use */
@@ -2229,7 +2247,7 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
                */
 
                if (!r->has_order_key (EditorSort)) {
-                       if (r->is_hidden()) {
+                       if (r->is_auditioner()) {
                                /* use an arbitrarily high value */
                                r->set_order_key (EditorSort, UINT_MAX);
                                r->set_order_key (MixerSort, UINT_MAX);
@@ -2454,7 +2472,7 @@ Session::route_listen_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
                        /* new listen: disable all other listen */
                        boost::shared_ptr<RouteList> r = routes.reader ();
                        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
+                               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
                                        continue;
                                }
                                (*i)->set_listen (false, this);
@@ -2536,7 +2554,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                /* new solo: disable all other solos, but not the group if its solo-enabled */
 
                for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                       if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden() ||
+                       if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() ||
                            (leave_group_alone && ((*i)->route_group() == rg))) {
                                continue;
                        }
@@ -2556,7 +2574,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                bool via_sends_only;
                bool in_signal_flow;
 
-               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden() ||
+               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() ||
                    (leave_group_alone && ((*i)->route_group() == rg))) {
                        continue;
                }
@@ -2645,11 +2663,11 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
        }
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_hidden() && (*i)->self_soloed()) {
+               if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_auditioner() && (*i)->self_soloed()) {
                        something_soloed = true;
                }
 
-               if (!(*i)->is_hidden() && (*i)->listening_via_monitor()) {
+               if (!(*i)->is_auditioner() && (*i)->listening_via_monitor()) {
                        if (Config->get_solo_control_is_listen_control()) {
                                listeners++;
                        } else {
@@ -4152,11 +4170,18 @@ Session::get_silent_buffers (ChanCount count)
 }
 
 BufferSet&
-Session::get_scratch_buffers (ChanCount count)
+Session::get_scratch_buffers (ChanCount count, bool silence)
+{
+       return ProcessThread::get_scratch_buffers (count, silence);
+}
+
+BufferSet&
+Session::get_route_buffers (ChanCount count, bool silence)
 {
-       return ProcessThread::get_scratch_buffers (count);
+       return ProcessThread::get_route_buffers (count, silence);
 }
 
+
 BufferSet&
 Session::get_mix_buffers (ChanCount count)
 {
@@ -4402,18 +4427,18 @@ Session::end_time_changed (framepos_t old)
        }
 }
 
-string
+std::vector<std::string>
 Session::source_search_path (DataType type) const
 {
-       vector<string> s;
+       Searchpath sp;
 
        if (session_dirs.size() == 1) {
                switch (type) {
                case DataType::AUDIO:
-                       s.push_back (_session_dir->sound_path());
+                       sp.push_back (_session_dir->sound_path());
                        break;
                case DataType::MIDI:
-                       s.push_back (_session_dir->midi_path());
+                       sp.push_back (_session_dir->midi_path());
                        break;
                }
        } else {
@@ -4421,10 +4446,10 @@ Session::source_search_path (DataType type) const
                        SessionDirectory sdir (i->path);
                        switch (type) {
                        case DataType::AUDIO:
-                               s.push_back (sdir.sound_path());
+                               sp.push_back (sdir.sound_path());
                                break;
                        case DataType::MIDI:
-                               s.push_back (sdir.midi_path());
+                               sp.push_back (sdir.midi_path());
                                break;
                        }
                }
@@ -4433,49 +4458,30 @@ Session::source_search_path (DataType type) const
        if (type == DataType::AUDIO) {
                const string sound_path_2X = _session_dir->sound_path_2X();
                if (Glib::file_test (sound_path_2X, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
-                       if (find (s.begin(), s.end(), sound_path_2X) == s.end()) {
-                               s.push_back (sound_path_2X);
+                       if (find (sp.begin(), sp.end(), sound_path_2X) == sp.end()) {
+                               sp.push_back (sound_path_2X);
                        }
                }
        }
 
-       /* now check the explicit (possibly user-specified) search path
-        */
-
-       vector<string> dirs;
+       // now check the explicit (possibly user-specified) search path
 
        switch (type) {
        case DataType::AUDIO:
-               split (config.get_audio_search_path (), dirs, ':');
+               sp += Searchpath(config.get_audio_search_path ());
                break;
        case DataType::MIDI:
-               split (config.get_midi_search_path (), dirs, ':');
+               sp += Searchpath(config.get_midi_search_path ());
                break;
        }
 
-       for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
-               if (find (s.begin(), s.end(), *i) == s.end()) {
-                       s.push_back (*i);
-               }
-       }
-       
-       string search_path;
-
-       for (vector<string>::iterator si = s.begin(); si != s.end(); ++si) {
-               if (!search_path.empty()) {
-                       search_path += ':';
-               }
-               search_path += *si;
-       }
-
-       return search_path;
+       return sp;
 }
 
 void
 Session::ensure_search_path_includes (const string& path, DataType type)
 {
-       string search_path;
-       vector<string> dirs;
+       Searchpath sp;
 
        if (path == ".") {
                return;
@@ -4483,16 +4489,14 @@ Session::ensure_search_path_includes (const string& path, DataType type)
 
        switch (type) {
        case DataType::AUDIO:
-               search_path = config.get_audio_search_path ();
+               sp += Searchpath(config.get_audio_search_path ());
                break;
        case DataType::MIDI:
-               search_path = config.get_midi_search_path ();
+               sp += Searchpath (config.get_midi_search_path ());
                break;
        }
 
-       split (search_path, dirs, ':');
-
-       for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
+       for (vector<std::string>::iterator i = sp.begin(); i != sp.end(); ++i) {
                /* No need to add this new directory if it has the same inode as
                   an existing one; checking inode rather than name prevents duplicated
                   directories when we are using symlinks.
@@ -4504,18 +4508,14 @@ Session::ensure_search_path_includes (const string& path, DataType type)
                }
        }
 
-       if (!search_path.empty()) {
-               search_path += ':';
-       }
-
-       search_path += path;
+       sp += path;
 
        switch (type) {
        case DataType::AUDIO:
-               config.set_audio_search_path (search_path);
+               config.set_audio_search_path (sp.to_string());
                break;
        case DataType::MIDI:
-               config.set_midi_search_path (search_path);
+               config.set_midi_search_path (sp.to_string());
                break;
        }
 }
@@ -4604,7 +4604,7 @@ Session::post_playback_latency ()
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_hidden() && ((*i)->active())) {
+               if (!(*i)->is_auditioner() && ((*i)->active())) {
                        _worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ());
                }
        }
@@ -4710,7 +4710,7 @@ Session::update_latency_compensation (bool force_whole_graph)
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_hidden() && ((*i)->active())) {
+               if (!(*i)->is_auditioner() && ((*i)->active())) {
                        framecnt_t tl;
                        if ((*i)->signal_latency () != (tl = (*i)->update_signal_latency ())) {
                                some_track_latency_changed = true;