first vaguely working version using PresentationInfo
[ardour.git] / libs / ardour / session_state.cc
index 95eb36c07f4ec6fb617d12f20b214a8fac01f438..5b10389a3f620f0a058db2719f4d91adacf3e8b3 100644 (file)
@@ -61,7 +61,6 @@
 
 #include "evoral/SMF.hpp"
 
-#include "pbd/boost_debug.h"
 #include "pbd/basename.h"
 #include "pbd/controllable_descriptor.h"
 #include "pbd/debug.h"
@@ -83,6 +82,7 @@
 #include "ardour/audiofilesource.h"
 #include "ardour/audioregion.h"
 #include "ardour/automation_control.h"
+#include "ardour/boost_debug.h"
 #include "ardour/butler.h"
 #include "ardour/control_protocol_manager.h"
 #include "ardour/directory_names.h"
 #include "ardour/tempo.h"
 #include "ardour/ticker.h"
 #include "ardour/user_bundle.h"
+#include "ardour/vca.h"
+#include "ardour/vca_manager.h"
 
 #include "control_protocol/control_protocol.h"
 
@@ -171,6 +173,7 @@ Session::pre_engine_init (string fullpath)
        set_next_event ();
        _all_route_group->set_active (true, this);
        interpolation.add_channel_to (0, 0);
+       _vca_manager = new VCAManager (*this);
 
        if (config.get_use_video_sync()) {
                waiting_for_sync_offset = true;
@@ -248,9 +251,11 @@ Session::post_engine_init ()
                delete _tempo_map;
                _tempo_map = new TempoMap (_current_frame_rate);
                _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
+               _tempo_map->MetricPositionChanged.connect_same_thread (*this, boost::bind (&Session::gui_tempo_map_changed, this));
 
                /* MidiClock requires a tempo map */
 
+               delete midi_clock;
                midi_clock = new MidiClockTicker ();
                midi_clock->set_session (this);
 
@@ -623,7 +628,7 @@ Session::create (const string& session_template, BusProfile* bus_profile)
 
        _state_of_the_state = Clean;
 
-        /* set up Master Out and Control Out if necessary */
+        /* set up Master Out and Monitor Out if necessary */
 
         if (bus_profile) {
 
@@ -632,14 +637,14 @@ Session::create (const string& session_template, BusProfile* bus_profile)
 
                 // Waves Tracks: always create master bus for Tracks
                 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
-                       boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
+                       boost::shared_ptr<Route> r (new Route (*this, _("Master"), PresentationInfo::MasterOut, DataType::AUDIO));
                         if (r->init ()) {
                                 return -1;
                         }
-#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
-                       // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
-#endif
-                       {
+
+                        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);
@@ -653,7 +658,7 @@ Session::create (const string& session_template, BusProfile* bus_profile)
                }
 
                if (!rl.empty()) {
-                       add_routes (rl, false, false, false);
+                       add_routes (rl, false, false, false, PresentationInfo::max_order);
                }
 
                // Waves Tracks: Skip this. Always use autoconnection for Tracks
@@ -758,6 +763,8 @@ Session::remove_state (string snapshot_name)
 int
 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
 {
+       DEBUG_TRACE (DEBUG::Locale, string_compose ("Session::save_state locale '%1'\n", setlocale (LC_NUMERIC, NULL)));
+
        XMLTree tree;
        std::string xml_path(_session_dir->root_path());
 
@@ -948,7 +955,7 @@ Session::load_state (string snapshot_name)
                return -1;
        }
 
-       XMLNode& root (*state_tree->root());
+       XMLNode const & root (*state_tree->root());
 
        if (root.name() != X_("Session")) {
                error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
@@ -957,7 +964,7 @@ Session::load_state (string snapshot_name)
                return -1;
        }
 
-       const XMLProperty* prop;
+       XMLProperty const * prop;
 
        if ((prop = root.property ("version")) == 0) {
                /* no version implies very old version of Ardour */
@@ -1001,7 +1008,7 @@ Session::load_state (string snapshot_name)
 int
 Session::load_options (const XMLNode& node)
 {
-       LocaleGuard lg (X_("C"));
+       LocaleGuard lg;
        config.set_variables (node);
        return 0;
 }
@@ -1034,6 +1041,7 @@ Session::get_template()
 XMLNode&
 Session::state (bool full_state)
 {
+       LocaleGuard lg;
        XMLNode* node = new XMLNode("Session");
        XMLNode* child;
 
@@ -1092,6 +1100,11 @@ Session::state (bool full_state)
        snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
        node->add_property ("event-counter", buf);
 
+       /* save the VCA counter */
+
+       snprintf (buf, sizeof (buf), "%" PRIu32, VCA::get_next_vca_number());
+       node->add_property ("vca-counter", buf);
+
        /* various options */
 
        list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
@@ -1206,6 +1219,8 @@ Session::state (bool full_state)
                }
        }
 
+       node->add_child_nocopy (_vca_manager->get_state());
+
        child = node->add_child ("Routes");
        {
                boost::shared_ptr<RouteList> r = routes.reader ();
@@ -1295,9 +1310,10 @@ Session::get_control_protocol_state ()
 int
 Session::set_state (const XMLNode& node, int version)
 {
+       LocaleGuard lg;
        XMLNodeList nlist;
        XMLNode* child;
-       const XMLProperty* prop;
+       XMLProperty const * prop;
        int ret = -1;
 
        _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
@@ -1349,6 +1365,14 @@ Session::set_state (const XMLNode& node, int version)
                Evoral::init_event_id_counter (atoi (prop->value()));
        }
 
+       if ((prop = node.property (X_("vca-counter"))) != 0) {
+               uint32_t x;
+               sscanf (prop->value().c_str(), "%" PRIu32, &x);
+               VCA::set_next_vca_number (x);
+       } else {
+               VCA::set_next_vca_number (1);
+       }
+
        if ((child = find_named_node (node, "MIDIPorts")) != 0) {
                _midi_ports->set_midi_port_states (child->children());
        }
@@ -1451,6 +1475,10 @@ Session::set_state (const XMLNode& node, int version)
                }
        }
 
+       if ((child = find_named_node (node, VCAManager::xml_node_name)) != 0) {
+               _vca_manager->set_state (*child, version);
+       }
+
        if ((child = find_named_node (node, "Routes")) == 0) {
                error << _("Session: XML state has no routes section") << endmsg;
                goto out;
@@ -1458,6 +1486,10 @@ Session::set_state (const XMLNode& node, int version)
                goto out;
        }
 
+       /* Now that we have Routes and masters loaded, connect them if appropriate */
+
+       Slavable::Assign (_vca_manager); /* EMIT SIGNAL */
+
        /* our diskstreams list is no longer needed as they are now all owned by their Route */
        _diskstreams_2X.clear ();
 
@@ -1561,7 +1593,7 @@ Session::load_routes (const XMLNode& node, int version)
 
        BootMessage (_("Tracks/busses loaded;  Adding to Session"));
 
-       add_routes (new_routes, false, false, false);
+       add_routes (new_routes, false, false, false, PresentationInfo::max_order);
 
        BootMessage (_("Finished adding tracks/busses"));
 
@@ -1580,7 +1612,7 @@ Session::XMLRouteFactory (const XMLNode& node, int version)
        XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
 
        DataType type = DataType::AUDIO;
-       const XMLProperty* prop = node.property("default-type");
+       XMLProperty const * prop = node.property("default-type");
 
        if (prop) {
                type = DataType (prop->value());
@@ -1606,24 +1638,15 @@ Session::XMLRouteFactory (const XMLNode& node, int version)
                         return ret;
                 }
 
-#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
-                // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
-#endif
+                BOOST_MARK_TRACK (track);
                 ret = track;
 
        } else {
-               enum Route::Flag flags = Route::Flag(0);
-               const XMLProperty* prop = node.property("flags");
-               if (prop) {
-                       flags = Route::Flag (string_2_enum (prop->value(), flags));
-               }
-
+               PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
                boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
 
                 if (r->init () == 0 && r->set_state (node, version) == 0) {
-#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
-                        // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
-#endif
+                       BOOST_MARK_ROUTE (r);
                         ret = r;
                 }
        }
@@ -1646,7 +1669,7 @@ Session::XMLRouteFactory_2X (const XMLNode& node, int version)
        }
 
        DataType type = DataType::AUDIO;
-       const XMLProperty* prop = node.property("default-type");
+       XMLProperty const * prop = node.property("default-type");
 
        if (prop) {
                type = DataType (prop->value());
@@ -1684,24 +1707,15 @@ Session::XMLRouteFactory_2X (const XMLNode& node, int version)
 
                track->set_diskstream (*i);
 
-#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
-                // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
-#endif
+               BOOST_MARK_TRACK (track);
                 ret = track;
 
        } else {
-               enum Route::Flag flags = Route::Flag(0);
-               const XMLProperty* prop = node.property("flags");
-               if (prop) {
-                       flags = Route::Flag (string_2_enum (prop->value(), flags));
-               }
-
+               PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
                boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
 
                 if (r->init () == 0 && r->set_state (node, version) == 0) {
-#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
-                        // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
-#endif
+                       BOOST_MARK_ROUTE (r);
                         ret = r;
                 }
        }
@@ -1723,7 +1737,7 @@ Session::load_regions (const XMLNode& node)
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
                if ((region = XMLRegionFactory (**niter, false)) == 0) {
                        error << _("Session: cannot create Region from XML description.");
-                       const XMLProperty *name = (**niter).property("name");
+                       XMLProperty const * name = (**niter).property("name");
 
                        if (name) {
                                error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
@@ -1741,7 +1755,7 @@ Session::load_compounds (const XMLNode& node)
 {
        XMLNodeList calist = node.children();
        XMLNodeConstIterator caiter;
-       XMLProperty *caprop;
+       XMLProperty const * caprop;
 
        for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
                XMLNode* ca = *caiter;
@@ -1788,7 +1802,7 @@ Session::load_nested_sources (const XMLNode& node)
                        /* it may already exist, so don't recreate it unnecessarily
                         */
 
-                       XMLProperty* prop = (*niter)->property (X_("id"));
+                       XMLProperty const * prop = (*niter)->property (X_("id"));
                        if (!prop) {
                                error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
                                continue;
@@ -1812,7 +1826,7 @@ Session::load_nested_sources (const XMLNode& node)
 boost::shared_ptr<Region>
 Session::XMLRegionFactory (const XMLNode& node, bool full)
 {
-       const XMLProperty* type = node.property("type");
+       XMLProperty const * type = node.property("type");
 
        try {
 
@@ -1841,7 +1855,7 @@ Session::XMLRegionFactory (const XMLNode& node, bool full)
 boost::shared_ptr<AudioRegion>
 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
 {
-       const XMLProperty* prop;
+       XMLProperty const * prop;
        boost::shared_ptr<Source> source;
        boost::shared_ptr<AudioSource> as;
        SourceList sources;
@@ -1960,7 +1974,7 @@ Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
 boost::shared_ptr<MidiRegion>
 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
 {
-       const XMLProperty* prop;
+       XMLProperty const * prop;
        boost::shared_ptr<Source> source;
        boost::shared_ptr<MidiSource> ms;
        SourceList sources;
@@ -2792,7 +2806,7 @@ Session::find_all_sources (string path, set<string>& result)
 
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
 
-               XMLProperty* prop;
+               XMLProperty const * prop;
 
                if ((prop = (*niter)->property (X_("type"))) == 0) {
                        continue;
@@ -3399,7 +3413,7 @@ Session::controllable_by_descriptor (const ControllableDescriptor& desc)
        }
 
        case ControllableDescriptor::RemoteControlID:
-               r = route_by_remote_id (desc.rid());
+               r = get_remote_nth_route (desc.rid());
                break;
 
        case ControllableDescriptor::SelectionCount:
@@ -3855,7 +3869,7 @@ Session::config_changed (std::string p, bool ours)
        } else if (p == "solo-control-is-listen-control") {
                solo_control_mode_changed ();
        } else if (p == "solo-mute-gain") {
-               _solo_cut_control->Changed();
+               _solo_cut_control->Changed (true, Controllable::NoGroup);
        } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
                last_timecode_valid = false;
        } else if (p == "playback-buffer-seconds") {
@@ -4229,27 +4243,29 @@ Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFo
 
        /* sample rate */
 
-       const XMLProperty* prop;
-       if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
+       XMLProperty const * prop;
+       XMLNode const * root (tree.root());
+
+       if ((prop = root->property (X_("sample-rate"))) != 0) {
                sample_rate = atoi (prop->value());
                found_sr = true;
        }
 
-       const XMLNodeList& children (tree.root()->children());
+       const XMLNodeList& children (root->children());
        for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
                const XMLNode* child = *c;
                if (child->name() == "Config") {
                        const XMLNodeList& options (child->children());
                        for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
-                               const XMLNode* option = *oc;
-                               const XMLProperty* name = option->property("name");
+                               XMLNode const * option = *oc;
+                               XMLProperty const * name = option->property("name");
 
                                if (!name) {
                                        continue;
                                }
 
                                if (name->value() == "native-file-data-format") {
-                                       const XMLProperty* value = option->property ("value");
+                                       XMLProperty const * value = option->property ("value");
                                        if (value) {
                                                SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
                                                data_format = fmt;
@@ -4281,7 +4297,7 @@ Session::get_snapshot_from_instant (const std::string& session_dir)
                return "";
        }
 
-       const XMLProperty* prop;
+       XMLProperty const * prop;
        XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
        if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
                return prop->value();