Merge branch 'master' into cairocanvas
[ardour.git] / libs / ardour / session.cc
index 4be42c769ada52882c164d87ace9d8dd120e5001..d93d689459dfae4197aeb9bf3c6b104140ccbe71 100644 (file)
@@ -257,18 +257,43 @@ Session::Session (AudioEngine &eng,
        , _step_editors (0)
        , _suspend_timecode_transmission (0)
        ,  _speakers (new Speakers)
+       , _order_hint (0)
        , ignore_route_processor_changes (false)
+       , _midi_ports (0)
+       , _mmc (0)
 {
        uint32_t sr = 0;
 
        pre_engine_init (fullpath);
        
        if (_is_new) {
+               if (ensure_engine (sr)) {
+                       destroy ();
+                       throw failed_constructor ();
+               }
+
                if (create (mix_template, bus_profile)) {
                        destroy ();
                        throw failed_constructor ();
                }
+
+               /* if a mix template was provided, then ::create() will
+                * have copied it into the session and we need to load it
+                * so that we have the state ready for ::set_state()
+                * after the engine is started.
+                *
+                * Note that we do NOT try to get the sample rate from
+                * the template at this time, though doing so would
+                * be easy if we decided this was an appropriate part
+                * of a template.
+                */
+
+               if (!mix_template.empty() && load_state (_current_snapshot_name)) {
+                       throw failed_constructor ();
+               }
+
        } else {
+
                if (load_state (_current_snapshot_name)) {
                        throw failed_constructor ();
                }
@@ -284,11 +309,11 @@ Session::Session (AudioEngine &eng,
                                sr = atoi (prop->value());
                        }
                }
-       }
 
-       if (ensure_engine (sr)) {
-               destroy ();
-               throw failed_constructor ();
+               if (ensure_engine (sr)) {
+                       destroy ();
+                       throw failed_constructor ();
+               }
        }
 
        if (post_engine_init ()) {
@@ -361,6 +386,50 @@ Session::ensure_engine (uint32_t desired_sample_rate)
                return -1;
        }
 
+       return immediately_post_engine ();
+
+}
+
+int
+Session::immediately_post_engine ()
+{
+       /* Do various initializations that should take place directly after we
+        * know that the engine is running, but before we either create a
+        * session or set state for an existing one.
+        */
+        
+       if (how_many_dsp_threads () > 1) {
+               /* For now, only create the graph if we are using >1 DSP threads, as
+                  it is a bit slower than the old code with 1 thread.
+               */
+               _process_graph.reset (new Graph (*this));
+       }
+
+       /* every time we reconnect, recompute worst case output latencies */
+
+       _engine.Running.connect_same_thread (*this, boost::bind (&Session::initialize_latencies, this));
+
+       if (synced_to_engine()) {
+               _engine.transport_stop ();
+       }
+
+       if (config.get_jack_time_master()) {
+               _engine.transport_locate (_transport_frame);
+       }
+
+       try {
+               BootMessage (_("Set up LTC"));
+               setup_ltc ();
+               BootMessage (_("Set up Click"));
+               setup_click ();
+               BootMessage (_("Set up standard connections"));
+               setup_bundles ();
+       }
+
+       catch (failed_constructor& err) {
+               return -1;
+       }
+
        return 0;
 }
 
@@ -474,9 +543,9 @@ Session::destroy ()
        /* not strictly necessary, but doing it here allows the shared_ptr debugging to work */
        playlists.reset ();
 
-       delete _mmc;
-       delete _midi_ports;
-       delete _locations;
+       delete _mmc; _mmc = 0;
+       delete _midi_ports; _midi_ports = 0;
+       delete _locations; _locations = 0;
 
        DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n");
 
@@ -490,10 +559,10 @@ Session::setup_ltc ()
 {
        XMLNode* child = 0;
        
-       _ltc_input.reset (new IO (*this, _("LTC In"), IO::Input));
-       _ltc_output.reset (new IO (*this, _("LTC Out"), IO::Output));
+       _ltc_input.reset (new IO (*this, X_("LTC In"), IO::Input));
+       _ltc_output.reset (new IO (*this, X_("LTC Out"), IO::Output));
        
-       if (state_tree && (child = find_named_node (*state_tree->root(), "LTC-In")) != 0) {
+       if (state_tree && (child = find_named_node (*state_tree->root(), X_("LTC In"))) != 0) {
                _ltc_input->set_state (*(child->children().front()), Stateful::loading_state_version);
        } else {
                {
@@ -503,7 +572,7 @@ Session::setup_ltc ()
                reconnect_ltc_input ();
        }
        
-       if (state_tree && (child = find_named_node (*state_tree->root(), "LTC-Out")) != 0) {
+       if (state_tree && (child = find_named_node (*state_tree->root(), X_("LTC Out"))) != 0) {
                _ltc_output->set_state (*(child->children().front()), Stateful::loading_state_version);
        } else {
                {
@@ -517,21 +586,30 @@ Session::setup_ltc ()
         * IO style of NAME/TYPE-{in,out}N
         */
        
-       _ltc_input->nth (0)->set_name (_("LTC-in"));
-       _ltc_output->nth (0)->set_name (_("LTC-out"));
+       _ltc_input->nth (0)->set_name (X_("LTC-in"));
+       _ltc_output->nth (0)->set_name (X_("LTC-out"));
 }
 
 void
 Session::setup_click ()
 {
-       XMLNode* child = 0;
-
        _clicking = false;
-       _click_io.reset (new ClickIO (*this, "click"));
+       _click_io.reset (new ClickIO (*this, X_("Click")));
        _click_gain.reset (new Amp (*this));
        _click_gain->activate ();
+       if (state_tree) {
+               setup_click_state (state_tree->root());
+       } else {
+               setup_click_state (0);
+       }
+}
+
+void
+Session::setup_click_state (const XMLNode* node)
+{      
+       const XMLNode* child = 0;
        
-       if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
+       if (node && (child = find_named_node (*node, "Click")) != 0) {
                
                /* existing state for Click */
                int c = 0;
@@ -683,81 +761,6 @@ Session::setup_bundles ()
 
 }
 
-int
-Session::when_engine_running ()
-{
-       /* every time we reconnect, recompute worst case output latencies */
-
-       _engine.Running.connect_same_thread (*this, boost::bind (&Session::initialize_latencies, this));
-
-       if (synced_to_jack()) {
-               _engine.transport_stop ();
-       }
-
-       if (config.get_jack_time_master()) {
-               _engine.transport_locate (_transport_frame);
-       }
-
-
-       try {
-               BootMessage (_("Set up LTC"));
-               setup_ltc ();
-               BootMessage (_("Set up Click"));
-               setup_click ();
-               BootMessage (_("Set up standard connections"));
-               setup_bundles ();
-       }
-
-       catch (failed_constructor& err) {
-               return -1;
-       }
-
-       BootMessage (_("Setup signal flow and plugins"));
-
-       /* Reset all panners */
-
-       Delivery::reset_panners ();
-
-       /* this will cause the CPM to instantiate any protocols that are in use
-        * (or mandatory), which will pass it this Session, and then call
-        * set_state() on each instantiated protocol to match stored state.
-        */
-
-       ControlProtocolManager::instance().set_session (this);
-
-       /* This must be done after the ControlProtocolManager set_session above,
-          as it will set states for ports which the ControlProtocolManager creates.
-       */
-
-       // XXX set state of MIDI::Port's
-       // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
-
-       /* And this must be done after the MIDI::Manager::set_port_states as
-        * it will try to make connections whose details are loaded by set_port_states.
-        */
-
-       hookup_io ();
-
-       /* Let control protocols know that we are now all connected, so they
-        * could start talking to surfaces if they want to.
-        */
-
-       ControlProtocolManager::instance().midi_connectivity_established ();
-
-       if (_is_new && !no_auto_connect()) {
-               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
-               auto_connect_master_bus ();
-       }
-
-       _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
-
-        /* update latencies */
-
-        initialize_latencies ();
-
-       return 0;
-}
-
 void
 Session::auto_connect_master_bus ()
 {
@@ -802,6 +805,12 @@ Session::remove_monitor_section ()
        /* force reversion to Solo-In-Place */
        Config->set_solo_control_is_listen_control (false);
 
+       /* if we are auditioning, cancel it ... this is a workaround
+          to a problem (auditioning does not execute the process graph,
+          which is needed to remove routes when using >1 core for processing)
+       */
+       cancel_audition ();
+
        {
                /* Hold process lock while doing this so that we don't hear bits and
                 * pieces of audio as we work on each route.
@@ -832,6 +841,10 @@ Session::remove_monitor_section ()
 
        remove_route (_monitor_out);
        auto_connect_master_bus ();
+
+       if (auditioner) {
+               auditioner->connect ();
+       }
 }
 
 void
@@ -917,14 +930,14 @@ Session::add_monitor_section ()
                        
                        /* Monitor bus is audio only */
 
-                       uint32_t mod = n_physical_outputs.get (DataType::AUDIO);
-                       uint32_t limit = _monitor_out->n_outputs().get (DataType::AUDIO);
                        vector<string> outputs[DataType::num_types];
 
                        for (uint32_t i = 0; i < DataType::num_types; ++i) {
                                _engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
                        }
-                       
+
+                       uint32_t mod = outputs[DataType::AUDIO].size();
+                       uint32_t limit = _monitor_out->n_outputs().get (DataType::AUDIO);
                        
                        if (mod != 0) {
                                
@@ -976,6 +989,10 @@ Session::add_monitor_section ()
                        (*x)->enable_monitor_send ();
                }
        }
+
+       if (auditioner) {
+               auditioner->connect ();
+       }
 }
 
 void
@@ -1428,7 +1445,7 @@ Session::audible_frame () const
                offset = current_block_size;
        }
 
-       if (synced_to_jack()) {
+       if (synced_to_engine()) {
                tf = _engine.transport_frame();
        } else {
                tf = _transport_frame;
@@ -1697,7 +1714,7 @@ Session::resort_routes_using (boost::shared_ptr<RouteList> r)
                DEBUG_TRACE (DEBUG::Graph, "Routes resorted, order follows:\n");
                for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                        DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 signal order %2\n",
-                                                                  (*i)->name(), (*i)->order_key (MixerSort)));
+                                                                  (*i)->name(), (*i)->order_key ()));
                }
 #endif
 
@@ -1982,9 +1999,9 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing
                        for (uint32_t i = output_start.get(*t); i < route->n_outputs().get(*t); ++i) {
                                string port;
 
-                               if ((*t) == DataType::MIDI || Config->get_output_auto_connect() & AutoConnectPhysical) {
+                               if ((*t) == DataType::MIDI && (Config->get_output_auto_connect() & AutoConnectPhysical)) {
                                        port = physoutputs[(out_offset.get(*t) + i) % nphysical_out];
-                               } else if ((*t) == DataType::AUDIO && Config->get_output_auto_connect() & AutoConnectMaster) {
+                               } else if ((*t) == DataType::AUDIO && (Config->get_output_auto_connect() & AutoConnectMaster)) {
                                         /* master bus is audio only */
                                        if (_master_out && _master_out->n_inputs().get(*t) > 0) {
                                                port = _master_out->input()->ports().port(*t,
@@ -2333,6 +2350,11 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
         ChanCount existing_outputs;
        uint32_t order = next_control_id();
 
+       if (_order_hint != 0) {
+               order = _order_hint;
+               _order_hint = 0;
+       }
+
         count_existing_track_channels (existing_inputs, existing_outputs);
 
        {
@@ -2394,15 +2416,13 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
                   ID in most situations.
                */
 
-               if (!r->has_order_key (EditorSort)) {
+               if (!r->has_order_key ()) {
                        if (r->is_auditioner()) {
                                /* use an arbitrarily high value */
-                               r->set_order_key (EditorSort, UINT_MAX);
-                               r->set_order_key (MixerSort, UINT_MAX);
+                               r->set_order_key (UINT_MAX);
                        } else {
                                DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("while adding, set %1 to order key %2\n", r->name(), order));
-                               r->set_order_key (EditorSort, order);
-                               r->set_order_key (MixerSort, order);
+                               r->set_order_key (order);
                                order++;
                        }
                }
@@ -3713,7 +3733,7 @@ Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::
        if (b->is_monitor()) {
                return false;
        }
-       return a->order_key (MixerSort) < b->order_key (MixerSort);
+       return a->order_key () < b->order_key ();
 }
 
 bool
@@ -4925,8 +4945,7 @@ Session::notify_remote_id_change ()
        }
 
        switch (Config->get_remote_model()) {
-       case MixerSort:
-       case EditorSort:
+       case MixerOrdered:
                Route::RemoteControlIDChange (); /* EMIT SIGNAL */
                break;
        default:
@@ -4935,7 +4954,7 @@ Session::notify_remote_id_change ()
 }
 
 void
-Session::sync_order_keys (RouteSortOrderKey sort_key_changed)
+Session::sync_order_keys ()
 {
        if (deletion_in_progress()) {
                return;
@@ -4947,9 +4966,9 @@ Session::sync_order_keys (RouteSortOrderKey sort_key_changed)
           opportunity to keep them in sync if they wish to.
        */
 
-       DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("Sync Order Keys, based on %1\n", enum_2_string (sort_key_changed)));
+       DEBUG_TRACE (DEBUG::OrderKeys, "Sync Order Keys.\n");
 
-       Route::SyncOrderKeys (sort_key_changed); /* EMIT SIGNAL */
+       Route::SyncOrderKeys (); /* EMIT SIGNAL */
 
        DEBUG_TRACE (DEBUG::OrderKeys, "\tsync done\n");
 }