Remove Session::create_session_directory as it is no longer used
[ardour.git] / libs / ardour / session_state.cc
index dfa95161a9b0021eff9f747a17126a58777e8067..e58f2324e34f4a0eb96467916e2b53f318322f42 100644 (file)
@@ -17,6 +17,9 @@
     
 */
 
+#define __STDC_FORMAT_MACROS 1
+#include <stdint.h>
+
 #include <algorithm>
 #include <fstream>
 #include <string>
 #include <ardour/audioengine.h>
 #include <ardour/configuration.h>
 #include <ardour/session.h>
+#include <ardour/buffer.h>
 #include <ardour/audio_diskstream.h>
+#include <ardour/midi_diskstream.h>
 #include <ardour/utils.h>
 #include <ardour/audioplaylist.h>
+#include <ardour/midi_playlist.h>
+#include <ardour/smf_source.h>
 #include <ardour/audiofilesource.h>
 #include <ardour/silentfilesource.h>
 #include <ardour/sndfilesource.h>
+#include <ardour/midi_source.h>
 #include <ardour/sndfile_helpers.h>
 #include <ardour/auditioner.h>
 #include <ardour/export.h>
 #include <ardour/slave.h>
 #include <ardour/tempo.h>
 #include <ardour/audio_track.h>
+#include <ardour/midi_track.h>
 #include <ardour/cycle_timer.h>
 #include <ardour/utils.h>
 #include <ardour/named_selection.h>
 #include <ardour/version.h>
 #include <ardour/location.h>
 #include <ardour/audioregion.h>
+#include <ardour/midi_region.h>
 #include <ardour/crossfade.h>
 #include <ardour/control_protocol_manager.h>
 #include <ardour/region_factory.h>
 #include <ardour/source_factory.h>
 #include <ardour/playlist_factory.h>
-
+#include <ardour/filename_extensions.h>
+#include <ardour/directory_names.h>
 #include <control_protocol/control_protocol.h>
 
 #include "i18n.h"
@@ -185,10 +196,10 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        first_file_data_format_reset = true;
        first_file_header_format_reset = true;
        butler_thread = (pthread_t) 0;
-       midi_thread = (pthread_t) 0;
+       //midi_thread = (pthread_t) 0;
 
        AudioDiskstream::allocate_working_buffers();
-       
+
        /* default short fade = 15ms */
 
        Crossfade::set_short_xfade_length ((nframes_t) floor (Config->get_short_xfade_seconds() * frame_rate()));
@@ -247,11 +258,11 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        PlaylistFactory::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
        Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
        NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
-        AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
+       AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
 
        Controllable::Destroyed.connect (mem_fun (*this, &Session::remove_controllable));
 
-       IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
+       IO::MoreChannels.connect (mem_fun (*this, &Session::ensure_buffers));
 
        /* stop IO objects from doing stuff until we're ready for them */
 
@@ -276,9 +287,9 @@ Session::second_stage_init (bool new_session)
                return -1;
        }
 
-       if (start_midi_thread ()) {
+       /*if (start_midi_thread ()) {
                return -1;
-       }
+       }*/
 
        // set_state() will call setup_raid_path(), but if it's a new session we need
        // to call setup_raid_path() here.
@@ -329,7 +340,7 @@ Session::second_stage_init (bool new_session)
                return -1;
        }
 
-       send_full_time_code ();
+       //send_full_time_code ();
        _engine.transport_locate (0);
        deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
        deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
@@ -402,6 +413,7 @@ Session::setup_raid_path (string path)
                fspath += sound_dir (false);
                
                AudioFileSource::set_search_path (fspath);
+               SMFSource::set_search_path (fspath); // FIXME: should be different
 
                return;
        }
@@ -445,115 +457,46 @@ Session::setup_raid_path (string path)
        /* set the AudioFileSource search path */
 
        AudioFileSource::set_search_path (fspath);
+       SMFSource::set_search_path (fspath); // FIXME: should be different
 
        /* reset the round-robin soundfile path thingie */
 
        last_rr_session_dir = session_dirs.begin();
 }
 
-int
-Session::create (bool& new_session, string* mix_template, nframes_t initial_length)
+void
+Session::initialize_start_and_end_locations (nframes_t start, nframes_t end)
 {
-       string dir;
-
-       if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
-               error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
-               return -1;
-       }
-
-       dir = peak_dir ();
-
-       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
-               error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-               return -1;
-       }
-
-       /* if this is is an existing session with an old "sounds" directory, just use it. see Session::sound_dir() for more details */
-
-       if (!Glib::file_test (old_sound_dir(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
-
-               dir = sound_dir ();
-               
-               if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
-                       error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
-       }
-
-       dir = dead_sound_dir ();
-
-       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
-               error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-               return -1;
-       }
-
-       dir = automation_dir ();
-
-       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
-               error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-               return -1;
-       }
-
-       dir = export_dir ();
-
-       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
-               error << string_compose(_("Session: cannot create session export dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-               return -1;
-       }
-
-
-       /* check new_session so we don't overwrite an existing one */
-
-       if (mix_template) {
-               std::string in_path = *mix_template;
-
-               ifstream in(in_path.c_str());
-
-               if (in){
-                       string out_path = _path;
-                       out_path += _name;
-                       out_path += _statefile_suffix;
-
-                       ofstream out(out_path.c_str());
-
-                       if (out){
-                               out << in.rdbuf();
-
-                               // okay, session is set up.  Treat like normal saved
-                               // session from now on.
-
-                               new_session = false;
-                               return 0;
-
-                       } else {
-                               error << string_compose (_("Could not open %1 for writing mix template"), out_path) 
-                                       << endmsg;
-                               return -1;
-                       }
-
-               } else {
-                       error << string_compose (_("Could not open mix template %1 for reading"), in_path) 
-                               << endmsg;
-                       return -1;
-               }
-
-       }
-
-       /* set initial start + end point */
-
-       start_location->set_end (0);
+       start_location->set_end (start);
        _locations.add (start_location);
 
-       end_location->set_end (initial_length);
+       end_location->set_end (end);
        _locations.add (end_location);
+}
 
+bool
+Session::create_session_file ()
+{
        _state_of_the_state = Clean;
 
        if (save_state (_current_snapshot_name)) {
-               return -1;
+               error << "Could not create new session file" << endmsg;
+               return false;
        }
+       return true;
+}
 
-       return 0;
+bool
+Session::create_session_file_from_template (const string& template_path)
+{
+       string out_path = _path + _name + statefile_suffix;
+
+       if(!copy_file (template_path, out_path)) {
+               error << string_compose (_("Could not use session template %1 to create new session."), template_path) 
+                       << endmsg;
+               return false;
+       }
+       return true;
 }
 
 int
@@ -565,15 +508,22 @@ Session::load_diskstreams (const XMLNode& node)
        clist = node.children();
 
        for (citer = clist.begin(); citer != clist.end(); ++citer) {
-               
 
                try {
-                       boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
-                       add_diskstream (dstream);
+                       /* diskstreams added automatically by DiskstreamCreated handler */
+                       if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
+                               boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
+                               add_diskstream (dstream);
+                       } else if ((*citer)->name() == "MidiDiskstream") {
+                               boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
+                               add_diskstream (dstream);
+                       } else {
+                               error << _("Session: unknown diskstream type in XML") << endmsg;
+                       }
                } 
                
                catch (failed_constructor& err) {
-                       error << _("Session: could not load diskstream via XML state")                        << endmsg;
+                       error << _("Session: could not load diskstream via XML state") << endmsg;
                        return -1;
                }
        }
@@ -581,6 +531,14 @@ Session::load_diskstreams (const XMLNode& node)
        return 0;
 }
 
+void
+Session::maybe_write_autosave()
+{
+        if (dirty() && record_status() != Recording) {
+                save_state("", true);
+        }
+}
+
 void
 Session::remove_pending_capture_state ()
 {
@@ -588,11 +546,53 @@ Session::remove_pending_capture_state ()
 
        xml_path = _path;
        xml_path += _current_snapshot_name;
-       xml_path += _pending_suffix;
+       xml_path += pending_suffix;
 
        unlink (xml_path.c_str());
 }
 
+/** Rename a state file.
+ * @param snapshot_name Snapshot name.
+ */
+void
+Session::rename_state (string old_name, string new_name)
+{
+       if (old_name == _current_snapshot_name || old_name == _name) {
+               /* refuse to rename the current snapshot or the "main" one */
+               return;
+       }
+       
+       const string old_xml_path = _path + old_name + statefile_suffix;
+       const string new_xml_path = _path + new_name + statefile_suffix;
+
+       if (rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
+               error << string_compose(_("could not rename snapshot %1 to %2"), old_name, new_name) << endmsg;
+       }
+}
+
+/** Remove a state file.
+ * @param snapshot_name Snapshot name.
+ */
+void
+Session::remove_state (string snapshot_name)
+{
+       if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
+               /* refuse to remove the current snapshot or the "main" one */
+               return;
+       }
+       
+       const string xml_path = _path + snapshot_name + statefile_suffix;
+
+       /* make a backup copy of the state file */
+       const string bak_path = xml_path + ".bak";
+       if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
+               copy_file (xml_path, bak_path);
+       }
+
+       /* and delete it */
+       unlink (xml_path.c_str());
+}
+
 int
 Session::save_state (string snapshot_name, bool pending)
 {
@@ -618,10 +618,12 @@ Session::save_state (string snapshot_name, bool pending)
 
        if (!pending) {
 
+               /* proper save: use statefile_suffix (.ardour in English) */
                xml_path = _path;
                xml_path += snapshot_name;
-               xml_path += _statefile_suffix;
+               xml_path += statefile_suffix;
 
+               /* make a backup copy of the old file */
                bak_path = xml_path;
                bak_path += ".bak";
                
@@ -631,9 +633,10 @@ Session::save_state (string snapshot_name, bool pending)
 
        } else {
 
+               /* pending save: use pending_suffix (.pending in English) */
                xml_path = _path;
                xml_path += snapshot_name;
-               xml_path += _pending_suffix;
+               xml_path += pending_suffix;
 
        }
 
@@ -643,7 +646,7 @@ Session::save_state (string snapshot_name, bool pending)
        tmp_path += snapshot_name;
        tmp_path += ".tmp";
 
-       cerr << "actually writing state\n";
+       // cerr << "actually writing state to " << xml_path << endl;
 
        if (!tree.write (tmp_path)) {
                error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
@@ -703,9 +706,9 @@ Session::load_state (string snapshot_name)
 
        xmlpath = _path;
        xmlpath += snapshot_name;
-       xmlpath += _pending_suffix;
+       xmlpath += pending_suffix;
 
-       if (!access (xmlpath.c_str(), F_OK)) {
+       if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
 
                /* there is pending state from a crashed capture attempt */
 
@@ -718,10 +721,10 @@ Session::load_state (string snapshot_name)
 
                xmlpath = _path;
                xmlpath += snapshot_name;
-               xmlpath += _statefile_suffix;
+               xmlpath += statefile_suffix;
        }
-
-       if (access (xmlpath.c_str(), F_OK)) {
+       
+       if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
                error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
                return 1;
        }
@@ -763,8 +766,10 @@ Session::load_state (string snapshot_name)
        if (is_old) {
                string backup_path;
 
-               backup_path = xmlpath;
-               backup_path += ".1";
+               backup_path = _path;
+               backup_path += snapshot_name;
+               backup_path += "-1";
+               backup_path += statefile_suffix;
 
                info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
                                        xmlpath, backup_path) 
@@ -899,9 +904,9 @@ Session::state(bool full_state)
        child = node->add_child ("Sources");
 
        if (full_state) {
-               Glib::Mutex::Lock sl (audio_source_lock);
+               Glib::Mutex::Lock sl (source_lock);
 
-               for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
+               for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
                        
                        /* Don't save information about AudioFileSources that are empty */
                        
@@ -909,8 +914,8 @@ Session::state(bool full_state)
 
                        if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
 
-                               /* destructive file sources are OK if they are empty, because
-                                  we will re-use them every time.
+                               /* Don't save sources that are empty, unless they're destructive (which are OK
+                                  if they are empty, because we will re-use them every time.)
                                */
 
                                if (!fs->destructive()) {
@@ -929,7 +934,7 @@ Session::state(bool full_state)
        if (full_state) { 
                Glib::Mutex::Lock rl (region_lock);
 
-               for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
+               for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
                        
                        /* only store regions not attached to playlists */
 
@@ -1307,12 +1312,26 @@ Session::XMLRouteFactory (const XMLNode& node)
                return boost::shared_ptr<Route> ((Route*) 0);
        }
 
-       if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
-               boost::shared_ptr<Route> x (new AudioTrack (*this, node));
-               return x;
+       bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
+       
+       DataType type = DataType::AUDIO;
+       const XMLProperty* prop = node.property("default-type");
+       if (prop)
+               type = DataType(prop->value());
+       
+       assert(type != DataType::NIL);
+
+       if (has_diskstream) {
+               if (type == DataType::AUDIO) {
+                       boost::shared_ptr<Route> ret (new AudioTrack (*this, node));
+                       return ret;
+               } else {
+                       boost::shared_ptr<Route> ret (new MidiTrack (*this, node));
+                       return ret;
+               }
        } else {
-               boost::shared_ptr<Route> x (new Route (*this, node));
-               return x;
+               boost::shared_ptr<Route> ret (new Route (*this, node));
+               return ret;
        }
 }
 
@@ -1321,7 +1340,7 @@ Session::load_regions (const XMLNode& node)
 {
        XMLNodeList nlist;
        XMLNodeConstIterator niter;
-       boost::shared_ptr<AudioRegion> region;
+       boost::shared_ptr<Region> region;
 
        nlist = node.children();
 
@@ -1336,8 +1355,32 @@ Session::load_regions (const XMLNode& node)
        return 0;
 }
 
-boost::shared_ptr<AudioRegion>
+boost::shared_ptr<Region>
 Session::XMLRegionFactory (const XMLNode& node, bool full)
+{
+       const XMLProperty* type = node.property("type");
+
+       try {
+       
+       if ( !type || type->value() == "audio" ) {
+
+               return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
+       
+       } else if (type->value() == "midi") {
+               
+               return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
+
+       }
+       
+       } catch (failed_constructor& err) {
+               return boost::shared_ptr<Region> ();
+       }
+
+       return boost::shared_ptr<Region> ();
+}
+
+boost::shared_ptr<AudioRegion>
+Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
 {
        const XMLProperty* prop;
        boost::shared_ptr<Source> source;
@@ -1428,14 +1471,66 @@ Session::XMLRegionFactory (const XMLNode& node, bool full)
        }
 }
 
+boost::shared_ptr<MidiRegion>
+Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
+{
+       const XMLProperty* prop;
+       boost::shared_ptr<Source> source;
+       boost::shared_ptr<MidiSource> ms;
+       MidiRegion::SourceList sources;
+       uint32_t nchans = 1;
+       
+       if (node.name() != X_("Region")) {
+               return boost::shared_ptr<MidiRegion>();
+       }
+
+       if ((prop = node.property (X_("channels"))) != 0) {
+               nchans = atoi (prop->value().c_str());
+       }
+
+       // Multiple midi channels?  that's just crazy talk
+       assert(nchans == 1);
+
+       if ((prop = node.property (X_("source-0"))) == 0) {
+               if ((prop = node.property ("source")) == 0) {
+                       error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
+                       return boost::shared_ptr<MidiRegion>();
+               }
+       }
+
+       PBD::ID s_id (prop->value());
+
+       if ((source = source_by_id (s_id)) == 0) {
+               error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
+               return boost::shared_ptr<MidiRegion>();
+       }
+
+       ms = boost::dynamic_pointer_cast<MidiSource>(source);
+       if (!ms) {
+               error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
+               return boost::shared_ptr<MidiRegion>();
+       }
+
+       sources.push_back (ms);
+
+       try {
+               boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
+               return region;
+       }
+
+       catch (failed_constructor& err) {
+               return boost::shared_ptr<MidiRegion>();
+       }
+}
+
 XMLNode&
 Session::get_sources_as_xml ()
 
 {
        XMLNode* node = new XMLNode (X_("Sources"));
-       Glib::Mutex::Lock lm (audio_source_lock);
+       Glib::Mutex::Lock lm (source_lock);
 
-       for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
+       for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
                node->add_child_nocopy (i->second->get_state());
        }
 
@@ -1459,7 +1554,7 @@ Session::path_from_region_name (string name, string identifier)
                        snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
                }
 
-               if (!g_file_test (buf, G_FILE_TEST_EXISTS)) {
+               if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
                        return buf;
                }
        }
@@ -1543,7 +1638,7 @@ Session::save_template (string template_name)
 
        xml_path = dir;
        xml_path += template_name;
-       xml_path += _template_suffix;
+       xml_path += template_suffix;
 
        ifstream in(xml_path.c_str());
        
@@ -1565,8 +1660,8 @@ Session::save_template (string template_name)
 int
 Session::rename_template (string old_name, string new_name) 
 {
-       string old_path = template_dir() + old_name + _template_suffix;
-       string new_path = template_dir() + new_name + _template_suffix;
+       string old_path = template_dir() + old_name + template_suffix;
+       string new_path = template_dir() + new_name + template_suffix;
 
        return rename (old_path.c_str(), new_path.c_str());
 }
@@ -1576,7 +1671,7 @@ Session::delete_template (string name)
 {
        string template_path = template_dir();
        template_path += name;
-       template_path += _template_suffix;
+       template_path += template_suffix;
 
        return remove (template_path.c_str());
 }
@@ -1808,7 +1903,6 @@ Session::load_unused_playlists (const XMLNode& node)
        return 0;
 }
 
-
 boost::shared_ptr<Playlist>
 Session::XMLPlaylistFactory (const XMLNode& node)
 {
@@ -2072,8 +2166,8 @@ Session::load_route_groups (const XMLNode& node, bool edit)
 static bool
 state_file_filter (const string &str, void *arg)
 {
-       return (str.length() > strlen(Session::statefile_suffix()) &&
-               str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
+       return (str.length() > strlen(statefile_suffix) &&
+               str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
 }
 
 struct string_cmp {
@@ -2336,8 +2430,8 @@ Session::global_record_enable_memento (void* src)
 static bool
 template_filter (const string &str, void *arg)
 {
-       return (str.length() > strlen(Session::template_suffix()) &&
-               str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
+       return (str.length() > strlen(template_suffix) &&
+               str.find (template_suffix) == (str.length() - strlen (template_suffix)));
 }
 
 void
@@ -2501,7 +2595,7 @@ Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_th
 
        this_snapshot_path = _path;
        this_snapshot_path += _current_snapshot_name;
-       this_snapshot_path += _statefile_suffix;
+       this_snapshot_path += statefile_suffix;
 
        for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
 
@@ -2580,9 +2674,9 @@ Session::cleanup_sources (Session::cleanup_report& rep)
        rep.paths.clear ();
        rep.space = 0;
 
-       for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
+       for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
                
-               AudioSourceList::iterator tmp;
+               SourceMap::iterator tmp;
 
                tmp = i;
                ++tmp;
@@ -2636,7 +2730,7 @@ Session::cleanup_sources (Session::cleanup_report& rep)
        /*  add our current source list
         */
        
-       for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
+       for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
                boost::shared_ptr<AudioFileSource> fs;
                
                if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
@@ -2644,6 +2738,9 @@ Session::cleanup_sources (Session::cleanup_report& rep)
                } 
        }
 
+       char tmppath1[PATH_MAX+1];
+       char tmppath2[PATH_MAX+1];
+       
        for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
 
                used = false;
@@ -2651,7 +2748,10 @@ Session::cleanup_sources (Session::cleanup_report& rep)
 
                for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
 
-                       if (spath == *i) {
+                       realpath(spath.c_str(), tmppath1);
+                       realpath((*i).c_str(),  tmppath2);
+
+                       if (strcmp(tmppath1, tmppath2) == 0) {
                                used = true;
                                break;
                        }
@@ -3103,15 +3203,11 @@ Session::config_changed (const char* parameter_name)
 
        } else if (PARAM_IS ("use-video-sync")) {
 
-               if (transport_stopped()) {
-                       if (Config->get_use_video_sync()) {
-                               waiting_for_sync_offset = true;
-                       }
-               }
+               waiting_for_sync_offset = Config->get_use_video_sync();
 
        } else if (PARAM_IS ("mmc-control")) {
 
-               poke_midi_thread ();
+               //poke_midi_thread ();
 
        } else if (PARAM_IS ("mmc-device-id")) {
 
@@ -3121,7 +3217,7 @@ Session::config_changed (const char* parameter_name)
 
        } else if (PARAM_IS ("midi-control")) {
                
-               poke_midi_thread ();
+               //poke_midi_thread ();
 
        } else if (PARAM_IS ("raid-path")) {