Replace thinning static state with parameter.
[ardour.git] / libs / ardour / session_state.cc
index cfd6b9c1e01348671f86f285b0c1713fda0ea187..8463b92503b84736b4e0d2a1e9b369ecb78b728d 100644 (file)
@@ -96,6 +96,7 @@
 #include "ardour/midi_track.h"
 #include "ardour/pannable.h"
 #include "ardour/playlist_factory.h"
+#include "ardour/playlist_source.h"
 #include "ardour/port.h"
 #include "ardour/processor.h"
 #include "ardour/proxy_controllable.h"
@@ -315,10 +316,9 @@ Session::post_engine_init ()
                
                initialize_latencies ();
                
+               _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
+               _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
                _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
-               _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
-               
-               
                
        } catch (AudioEngine::PortRegistrationFailure& err) {
                /* handle this one in a different way than all others, so that its clear what happened */
@@ -333,8 +333,8 @@ Session::post_engine_init ()
        // send_full_time_code (0);
        _engine.transport_locate (0);
 
-       _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
-       _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
+       send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
+       send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
 
        MIDI::Name::MidiPatchManager::instance().set_session (this);
 
@@ -512,7 +512,7 @@ Session::create (const string& session_template, BusProfile* bus_profile)
 
                                /* Copy plugin state files from template to new session */
                                std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
-                               copy_files (template_plugins, plugins_dir ());
+                               copy_recurse (template_plugins, plugins_dir ());
                                
                                return 0;
 
@@ -1852,7 +1852,10 @@ Session::load_sources (const XMLNode& node)
 {
        XMLNodeList nlist;
        XMLNodeConstIterator niter;
-       boost::shared_ptr<Source> source;
+       boost::shared_ptr<Source> source; /* don't need this but it stops some
+                                          * versions of gcc complaining about
+                                          * discarded return values.
+                                          */
 
        nlist = node.children();
 
@@ -1869,9 +1872,15 @@ Session::load_sources (const XMLNode& node)
 
                         int user_choice;
 
+                       if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
+                               error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
+                                                        PROGRAM_NAME) << endmsg;
+                               return -1;
+                       }
+
                         if (!no_questions_about_missing_files) {
-                                user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
-                        } else {
+                               user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
+                       } else {
                                 user_choice = -2;
                         }
 
@@ -1899,14 +1908,30 @@ Session::load_sources (const XMLNode& node)
                                switch (err.type) {
 
                                case DataType::AUDIO:
-                                       warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
                                        source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
                                        break;
 
                                case DataType::MIDI:
-                                       warning << string_compose (_("A MIDI file is missing. %1 cannot currently recover from missing MIDI files"),
-                                                                    PROGRAM_NAME) << endmsg;
-                                       return -1;
+                                       /* The MIDI file is actually missing so
+                                        * just create a new one in the same
+                                        * location. Do not announce its
+                                        */
+                                       string fullpath;
+
+                                       if (!Glib::path_is_absolute (err.path)) {
+                                               fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
+                                       } else {
+                                               /* this should be an unrecoverable error: we would be creating a MIDI file outside
+                                                  the session tree.
+                                               */
+                                               return -1;
+                                       }
+                                       /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
+                                       source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
+                                       /* reset ID to match the missing one */
+                                       source->set_id (**niter);
+                                       /* Now we can announce it */
+                                       SourceFactory::SourceCreated (source);
                                        break;
                                }
                                 break;
@@ -1930,7 +1955,7 @@ Session::XMLSourceFactory (const XMLNode& node)
        }
 
        catch (failed_constructor& err) {
-               error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
+               error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
                return boost::shared_ptr<Source>();
        }
 }
@@ -1991,7 +2016,7 @@ Session::save_template (string template_name)
                return -1;
        }
 
-       copy_files (plugins_dir(), template_plugin_state_path);
+       copy_recurse (plugins_dir(), template_plugin_state_path);
 
        return 0;
 }
@@ -2586,6 +2611,7 @@ Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
 void
 Session::cleanup_regions ()
 {
+       bool removed = false;
        const RegionFactory::RegionMap& regions (RegionFactory::regions());
 
        for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
@@ -2593,10 +2619,24 @@ Session::cleanup_regions ()
                uint32_t used = playlists->region_use_count (i->second);
 
                if (used == 0 && !i->second->automatic ()) {
+                       removed = true;
                        RegionFactory::map_remove (i->second);
                }
        }
 
+       if (removed) {
+               // re-check to remove parent references of compound regions
+               for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
+                       if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
+                               continue;
+                       }
+                       assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
+                       if (0 == playlists->region_use_count (i->second)) {
+                               RegionFactory::map_remove (i->second);
+                       }
+               }
+       }
+
        /* dump the history list */
        _history.clear ();
 
@@ -3457,12 +3497,12 @@ Session::config_changed (std::string p, bool ours)
                listen_position_changed ();
        } else if (p == "solo-control-is-listen-control") {
                solo_control_mode_changed ();
+       } else if (p == "solo-mute-gain") {
+               _solo_cut_control->Changed();
        } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
                last_timecode_valid = false;
        } else if (p == "playback-buffer-seconds") {
                AudioSource::allocate_working_buffers (frame_rate());
-       } else if (p == "automation-thinning-factor") {
-               Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
        } else if (p == "ltc-source-port") {
                reconnect_ltc_input ();
        } else if (p == "ltc-sink-port") {