Fix bumping .mid file name (snapshots & playlist copy)
[ardour.git] / libs / ardour / session.cc
index 764e05c3e888df858a3d57abb3a1a493038c6ab2..8814d019780528f03d681eee0211f5cf4dfec77b 100644 (file)
@@ -380,8 +380,12 @@ Session::Session (AudioEngine &eng,
                 */
 
                if (!mix_template.empty()) {
-                       if (load_state (_current_snapshot_name)) {
-                               throw SessionException (_("Failed to load template/snapshot state"));
+                       try {
+                               if (load_state (_current_snapshot_name)) {
+                                       throw SessionException (_("Failed to load template/snapshot state"));
+                               }
+                       } catch (PBD::unknown_enumeration& e) {
+                               throw SessionException (_("Failed to parse template/snapshot state"));
                        }
                        store_recent_templates (mix_template);
                }
@@ -510,8 +514,16 @@ Session::Session (AudioEngine &eng,
 
        ensure_subdirs (); // archived or zipped sessions may lack peaks/ analysis/ etc
 
-       _is_new = false;
+       if (!mix_template.empty ()) {
+               /* ::create() unsets _is_new after creating the session.
+                * But for templated sessions, the sample-rate is initially unset
+                * (not read from template), so we need to save it (again).
+                */
+               _is_new = true;
+       }
+
        session_loaded ();
+       _is_new = false;
 
        BootMessage (_("Session loading complete"));
 }
@@ -1487,6 +1499,33 @@ Session::reset_monitor_section ()
        }
 }
 
+int
+Session::add_master_bus (ChanCount const& count)
+{
+       if (master_out ()) {
+               return -1;
+       }
+
+       RouteList rl;
+
+       boost::shared_ptr<Route> r (new Route (*this, _("Master"), PresentationInfo::MasterOut, DataType::AUDIO));
+       if (r->init ()) {
+               return -1;
+       }
+
+       BOOST_MARK_ROUTE(r);
+
+       {
+               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+               r->input()->ensure_io (count, false, this);
+               r->output()->ensure_io (count, false, this);
+       }
+
+       rl.push_back (r);
+       add_routes (rl, false, false, false, PresentationInfo::max_order);
+       return 0;
+}
+
 void
 Session::hookup_io ()
 {
@@ -2518,11 +2557,13 @@ Session::count_existing_track_channels (ChanCount& in, ChanCount& out)
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        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_auditioner()) {
-                       in  += tr->n_inputs();
-                       out += tr->n_outputs();
+               boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
+               if (!tr) {
+                       continue;
                }
+               assert (!tr->is_auditioner()); // XXX remove me
+               in  += tr->n_inputs();
+               out += tr->n_outputs();
        }
 }
 
@@ -3085,7 +3126,8 @@ Session::ensure_stripable_sort_order ()
 
        for (StripableList::iterator si = sl.begin(); si != sl.end(); ++si) {
                boost::shared_ptr<Stripable> s (*si);
-               if (s->is_monitor () || s->is_auditioner ()) {
+               assert (!s->is_auditioner ()); // XXX remove me
+               if (s->is_monitor ()) {
                        continue;
                }
                if (order != s->presentation_info().order()) {
@@ -3577,11 +3619,7 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
                }
        }
 
-       /* auditioner and monitor routes are not part of the order */
-       if (auditioner) {
-               assert (n_routes > 0);
-               --n_routes;
-       }
+       /* monitor is not part of the order */
        if (_monitor_out) {
                assert (n_routes > 0);
                --n_routes;
@@ -4259,7 +4297,8 @@ Session::muted () const
        StripableList all;
        get_stripables (all);
        for (StripableList::const_iterator i = all.begin(); i != all.end(); ++i) {
-               if ((*i)->is_auditioner() || (*i)->is_monitor()) {
+               assert (!(*i)->is_auditioner()); // XXX remove me
+               if ((*i)->is_monitor()) {
                        continue;
                }
                boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(*i);
@@ -4283,7 +4322,8 @@ Session::cancel_all_mute ()
        std::vector<boost::weak_ptr<AutomationControl> > muted;
        boost::shared_ptr<ControlList> cl (new ControlList);
        for (StripableList::const_iterator i = all.begin(); i != all.end(); ++i) {
-               if ((*i)->is_auditioner() || (*i)->is_monitor()) {
+               assert (!(*i)->is_auditioner());
+               if ((*i)->is_monitor()) {
                        continue;
                }
                boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (*i);
@@ -4594,10 +4634,11 @@ Session::reassign_track_numbers ()
        StateProtector sp (this);
 
        for (RouteList::iterator i = r.begin(); i != r.end(); ++i) {
+               assert (!(*i)->is_auditioner());
                if (boost::dynamic_pointer_cast<Track> (*i)) {
                        (*i)->set_track_number(++tn);
                }
-               else if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_auditioner()) {
+               else if (!(*i)->is_master() && !(*i)->is_monitor()) {
                        (*i)->set_track_number(--bn);
                }
        }
@@ -5236,15 +5277,10 @@ Session::new_audio_source_path (const string& base, uint32_t nchan, uint32_t cha
 string
 Session::new_midi_source_path (const string& base, bool need_lock)
 {
-       uint32_t cnt;
-       char buf[PATH_MAX+1];
-       const uint32_t limit = 10000;
-       string legalized;
        string possible_path;
        string possible_name;
 
-       buf[0] = '\0';
-       legalized = legalize_for_path (base);
+       possible_name = legalize_for_path (base);
 
        // Find a "version" of the file name that doesn't exist in any of the possible directories.
        std::vector<string> sdirs = source_search_path(DataType::MIDI);
@@ -5259,17 +5295,15 @@ Session::new_midi_source_path (const string& base, bool need_lock)
         */
        std::reverse(sdirs.begin(), sdirs.end());
 
-       for (cnt = 1; cnt <= limit; ++cnt) {
+       while (true) {
+               possible_name = bump_name_once (possible_name, '-');
 
                vector<space_and_path>::iterator i;
                uint32_t existing = 0;
 
                for (vector<string>::const_iterator i = sdirs.begin(); i != sdirs.end(); ++i) {
 
-                       snprintf (buf, sizeof(buf), "%s-%u.mid", legalized.c_str(), cnt);
-                       possible_name = buf;
-
-                       possible_path = Glib::build_filename (*i, possible_name);
+                       possible_path = Glib::build_filename (*i, possible_name + ".mid");
 
                        if (Glib::file_test (possible_path, Glib::FILE_TEST_EXISTS)) {
                                existing++;
@@ -5280,17 +5314,17 @@ Session::new_midi_source_path (const string& base, bool need_lock)
                        }
                }
 
-               if (existing == 0) {
-                       break;
-               }
-
-               if (cnt > limit) {
+               if (possible_path.size () >= PATH_MAX) {
                        error << string_compose(
-                                       _("There are already %1 recordings for %2, which I consider too many."),
-                                       limit, base) << endmsg;
+                                       _("There are already many recordings for %1, resulting in a too long file-path %2."),
+                                       base, possible_path) << endmsg;
                        destroy ();
                        return 0;
                }
+
+               if (existing == 0) {
+                       break;
+               }
        }
 
        /* No need to "find best location" for software/app-based RAID, because
@@ -5472,7 +5506,7 @@ Session::registered_lua_functions ()
                        if (!i.key ().isString ()) { assert(0); continue; }
                        rv.push_back (i.key ().cast<std::string> ());
                }
-       } catch (luabridge::LuaException const& e) { }
+       } catch (...) { }
        return rv;
 }
 
@@ -5488,7 +5522,7 @@ Session::try_run_lua (pframes_t nframes)
        if (_n_lua_scripts == 0) return;
        Glib::Threads::Mutex::Lock tm (lua_lock, Glib::Threads::TRY_LOCK);
        if (tm.locked ()) {
-               try { (*_lua_run)(nframes); } catch (luabridge::LuaException const& e) { }
+               try { (*_lua_run)(nframes); } catch (...) { }
                lua.collect_garbage_step ();
        }
 }
@@ -5620,7 +5654,12 @@ Session::setup_lua ()
                _lua_cleanup = new luabridge::LuaRef(lua_sess["cleanup"]);
        } catch (luabridge::LuaException const& e) {
                fatal << string_compose (_("programming error: %1"),
-                               X_("Failed to setup Lua interpreter"))
+                               std::string ("Failed to setup session Lua interpreter") + e.what ())
+                       << endmsg;
+               abort(); /*NOTREACHED*/
+       } catch (...) {
+               fatal << string_compose (_("programming error: %1"),
+                               X_("Failed to setup session Lua interpreter"))
                        << endmsg;
                abort(); /*NOTREACHED*/
        }
@@ -5646,6 +5685,11 @@ Session::scripts_changed ()
                }
                _n_lua_scripts = cnt;
        } catch (luabridge::LuaException const& e) {
+               fatal << string_compose (_("programming error: %1"),
+                               std::string ("Indexing Lua Session Scripts failed.") + e.what ())
+                       << endmsg;
+               abort(); /*NOTREACHED*/
+       } catch (...) {
                fatal << string_compose (_("programming error: %1"),
                                X_("Indexing Lua Session Scripts failed."))
                        << endmsg;
@@ -6412,19 +6456,15 @@ Session::nbusses () const
 }
 
 uint32_t
-Session::nstripables (bool with_auditioner_and_monitor) const
+Session::nstripables (bool with_monitor) const
 {
        uint32_t rv = routes.reader()->size ();
        rv += _vca_manager->vcas ().size ();
 
-       if (with_auditioner_and_monitor) {
+       if (with_monitor) {
                return rv;
        }
 
-       if (auditioner) {
-               assert (rv > 0);
-               --rv;
-       }
        if (_monitor_out) {
                assert (rv > 0);
                --rv;
@@ -6555,9 +6595,8 @@ Session::get_tracks () const
 
        for (RouteList::const_iterator r = rl->begin(); r != rl->end(); ++r) {
                if (boost::dynamic_pointer_cast<Track> (*r)) {
-                       if (!(*r)->is_auditioner()) {
-                               tl->push_back (*r);
-                       }
+                       assert (!(*r)->is_auditioner()); // XXX remove me
+                       tl->push_back (*r);
                }
        }
        return tl;
@@ -6901,7 +6940,8 @@ Session::post_playback_latency ()
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_auditioner() && ((*i)->active())) {
+               assert (!(*i)->is_auditioner()); // XXX remove me
+               if ((*i)->active()) {
                        _worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ());
                }
        }
@@ -7007,7 +7047,8 @@ 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_auditioner() && ((*i)->active())) {
+               assert (!(*i)->is_auditioner()); // XXX remove me
+               if ((*i)->active()) {
                        framecnt_t tl;
                        if ((*i)->signal_latency () != (tl = (*i)->update_signal_latency ())) {
                                some_track_latency_changed = true;