Fix the interchange/ directory structure for snapshots
[ardour.git] / libs / ardour / session_state.cc
index 6cddfb026ae8d22e713ee9b8419caf6160d76f07..d721eecce9ce160d25f1da5812f313c8a21c793b 100644 (file)
@@ -114,7 +114,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        */
 
        _name = _current_snapshot_name = snapshot_name;
-       setup_raid_path (_path);
 
        _current_frame_rate = _engine.frame_rate ();
        _tempo_map = new TempoMap (_current_frame_rate);
@@ -222,6 +221,18 @@ Session::first_stage_init (string fullpath, string snapshot_name)
 
        process_function = &Session::process_with_events;
 
+       if (Config->get_use_video_sync()) {
+               waiting_for_sync_offset = true;
+       } else {
+               waiting_for_sync_offset = false;
+       }
+
+       _current_frame_rate = 48000;
+       _base_frame_rate = 48000;
+
+       smpte_frames_per_second = 30;
+       video_pullup = 0.0;
+       smpte_drop_frames = false;
        last_smpte_when = 0;
        _smpte_offset = 0;
        _smpte_offset_negative = true;
@@ -257,6 +268,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        /* default SMPTE type is 30 FPS, non-drop */
 
        set_smpte_type (30.0, false);
+       set_video_pullup (0.0);
 
        _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
 
@@ -289,7 +301,6 @@ Session::second_stage_init (bool new_session)
 
        if (!new_session) {
                if (load_state (_current_snapshot_name)) {
-                       cerr << "load state failed\n";
                        return -1;
                }
                remove_empty_sounds ();
@@ -303,10 +314,14 @@ Session::second_stage_init (bool new_session)
                return -1;
        }
 
+       // set_state() will call setup_raid_path(), but if it's a new session we need
+       // to call setup_raid_path() here.
        if (state_tree) {
                if (set_state (*state_tree->root())) {
                        return -1;
                }
+       } else {
+               setup_raid_path(_path);
        }
 
        /* we can't save till after ::when_engine_running() is called,
@@ -351,7 +366,6 @@ Session::second_stage_init (bool new_session)
                _end_location_is_free = false;
        }
        
-        restore_history(_current_snapshot_name);
        return 0;
 }
 
@@ -416,16 +430,7 @@ Session::setup_raid_path (string path)
                if (fspath[fspath.length()-1] != '/') {
                        fspath += '/';
                }
-               fspath += sound_dir_name;
-               fspath += ':';
-
-               /* tape dir */
-
-               fspath += sp.path;
-               if (fspath[fspath.length()-1] != '/') {
-                       fspath += '/';
-               }
-               fspath += tape_dir_name;
+               fspath += sound_dir (false);
                
                AudioFileSource::set_search_path (fspath);
 
@@ -446,16 +451,7 @@ Session::setup_raid_path (string path)
                if (fspath[fspath.length()-1] != '/') {
                        fspath += '/';
                }
-               fspath += sound_dir_name;
-               fspath += ':';
-
-               /* add tape dir to file search path */
-
-               fspath += sp.path;
-               if (fspath[fspath.length()-1] != '/') {
-                       fspath += '/';
-               }
-               fspath += tape_dir_name;
+               fspath += sound_dir (false);
                fspath += ':';
 
                remaining = remaining.substr (colon+1);
@@ -471,15 +467,9 @@ Session::setup_raid_path (string path)
                if (fspath[fspath.length()-1] != '/') {
                        fspath += '/';
                }
-               fspath += sound_dir_name;
+               fspath += sound_dir (false);
                fspath += ':';
 
-               fspath += sp.path;
-               if (fspath[fspath.length()-1] != '/') {
-                       fspath += '/';
-               }
-               fspath += tape_dir_name;
-
                session_dirs.push_back (sp);
        }
 
@@ -496,123 +486,91 @@ int
 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
 {
        string dir;
-       
-       if (mkdir (_path.c_str(), 0755) < 0) {
-               if (errno == EEXIST) {
-                       new_session = false;
-               } else {
-                       error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
-                       return -1;
-               }
-       } else {
-               new_session = true;
+
+       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 (mkdir (dir.c_str(), 0755) < 0) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
+       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;
        }
 
        dir = sound_dir ();
 
-       if (mkdir (dir.c_str(), 0755) < 0) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
-       }
-
-       dir = tape_dir ();
-
-       if (mkdir (dir.c_str(), 0755) < 0) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
+       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 (mkdir (dir.c_str(), 0755) < 0) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
+       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 (mkdir (dir.c_str(), 0755) < 0) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
+       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;
        }
 
-       
+
        /* check new_session so we don't overwrite an existing one */
-       
+
        if (mix_template) {
-               if (new_session){
-                       std::string in_path = *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;
 
-                       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;
+                               error << string_compose (_("Could not open %1 for writing mix template"), out_path) 
+                                       << endmsg;
                                return -1;
                        }
-                       
-                       
+
                } else {
-                       warning << _("Session already exists.  Not overwriting") << endmsg;
+                       error << string_compose (_("Could not open mix template %1 for reading"), in_path) 
+                               << endmsg;
                        return -1;
                }
+
        }
 
-       if (new_session) {
+       /* set initial start + end point */
 
-               /* set initial start + end point */
+       start_location->set_end (0);
+       _locations.add (start_location);
 
-               start_location->set_end (0);
-               _locations.add (start_location);
+       end_location->set_end (initial_length);
+       _locations.add (end_location);
 
-               end_location->set_end (initial_length);
-               _locations.add (end_location);
-               
-               _state_of_the_state = Clean;
+       _state_of_the_state = Clean;
 
-               if (save_state (_current_snapshot_name)) {
-                        save_history (_current_snapshot_name);
-                       return -1;
-               }
+       if (save_state (_current_snapshot_name)) {
+               save_history (_current_snapshot_name);
+               return -1;
        }
 
        return 0;
@@ -696,6 +654,8 @@ Session::save_state (string snapshot_name, bool pending)
 
        }
 
+       cerr << "actually writing state\n";
+
        if (!tree.write (xml_path)) {
                error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
 
@@ -910,6 +870,11 @@ Session::load_options (const XMLNode& node)
                        rf_speed = atof (prop->value().c_str());
                }
        }
+       if ((child = find_named_node (node, "video-pullup")) != 0) {
+               if ((prop = child->property ("val")) != 0) {
+                       set_video_pullup( atof (prop->value().c_str()) );
+               }
+       }
        if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
                if ((prop = child->property ("val")) != 0) {
                        set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
@@ -1164,6 +1129,10 @@ Session::get_options () const
        child = opthead->add_child ("rf-speed");
        child->add_property ("val", buf);
 
+       snprintf (buf, sizeof(buf)-1, "%.4f", video_pullup);
+       child = opthead->add_child ("video-pullup");
+       child->add_property ("val", buf);
+       
        snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
        child = opthead->add_child ("smpte-frames-per-second");
        child->add_property ("val", buf);
@@ -1510,6 +1479,8 @@ Session::set_state (const XMLNode& node)
                _name = prop->value ();
        }
 
+       setup_raid_path(_path);
+
        if ((prop = node.property (X_("id-counter"))) != 0) {
                uint64_t x;
                sscanf (prop->value().c_str(), "%" PRIu64, &x);
@@ -1906,13 +1877,12 @@ Session::load_sources (const XMLNode& node)
 boost::shared_ptr<Source>
 Session::XMLSourceFactory (const XMLNode& node)
 {
-
        if (node.name() != "Source") {
                return boost::shared_ptr<Source>();
        }
 
        try {
-               return SourceFactory::create (node);
+               return SourceFactory::create (*this, node);
        }
        
        catch (failed_constructor& err) {
@@ -1937,7 +1907,7 @@ Session::save_template (string template_name)
        if ((dp = opendir (dir.c_str()))) {
                closedir (dp);
        } else {
-               if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
+               if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
                        error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
                        return -1;
                }
@@ -2017,11 +1987,9 @@ Session::ensure_sound_dir (string path, string& result)
 
        /* Ensure that the parent directory exists */
        
-       if (mkdir (path.c_str(), 0775)) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (path.c_str(), 0775)) {
+               error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
+               return -1;
        }
        
        /* Ensure that the sounds directory exists */
@@ -2030,33 +1998,27 @@ Session::ensure_sound_dir (string path, string& result)
        result += '/';
        result += sound_dir_name;
        
-       if (mkdir (result.c_str(), 0775)) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (result.c_str(), 0775)) {
+               error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
+               return -1;
        }
 
        dead = path;
        dead += '/';
        dead += dead_sound_dir_name;
        
-       if (mkdir (dead.c_str(), 0775)) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (dead.c_str(), 0775)) {
+               error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
+               return -1;
        }
 
        peak = path;
        peak += '/';
        peak += peak_dir_name;
        
-       if (mkdir (peak.c_str(), 0775)) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (peak.c_str(), 0775)) {
+               error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
+               return -1;
        }
        
        /* callers expect this to be terminated ... */
@@ -2071,12 +2033,6 @@ Session::discover_best_sound_dir (bool destructive)
        vector<space_and_path>::iterator i;
        string result;
 
-       /* destructive files all go into the same place */
-
-       if (destructive) {
-               return tape_dir();
-       }
-
        /* handle common case without system calls */
 
        if (session_dirs.size() == 1) {
@@ -2282,20 +2238,41 @@ Session::dead_sound_dir () const
 }
 
 string
-Session::sound_dir () const
+Session::sound_dir (bool with_path) const
 {
-       string res = _path;
+       /* support old session structure */
+
+       struct stat statbuf;
+       string old_nopath;
+       string old_withpath;
+
+       old_nopath += old_sound_dir_name;
+       old_nopath += '/';
+       
+       old_withpath = _path;
+       old_withpath += old_sound_dir_name;
+       old_withpath += '/';
+
+       if (stat (old_withpath.c_str(), &statbuf) == 0) {
+               if (with_path)
+                       return old_withpath;
+               
+               return old_nopath;
+       }
+
+       string res;
+
+       if (with_path) {
+               res = _path;
+       }
+
+       res += interchange_dir_name;
+       res += '/';
+       res += legalize_for_path (_name);
+       res += '/';
        res += sound_dir_name;
        res += '/';
-       return res;
-}
 
-string
-Session::tape_dir () const
-{
-       string res = _path;
-       res += tape_dir_name;
-       res += '/';
        return res;
 }
 
@@ -3292,8 +3269,7 @@ Session::save_history (string snapshot_name)
     XMLTree tree;
     string xml_path;
     string bak_path;
-
-
+    
     tree.set_root (&history.get_state());
 
     if (snapshot_name.empty()) {
@@ -3301,7 +3277,6 @@ Session::save_history (string snapshot_name)
     }
 
     xml_path = _path + snapshot_name + ".history"; 
-    cerr << "Saving history to " << xml_path << endmsg;
 
     bak_path = xml_path + ".bak";
 
@@ -3312,6 +3287,8 @@ Session::save_history (string snapshot_name)
         return -1;
     }
 
+    cerr << "actually writing history\n";
+
     if (!tree.write (xml_path))
     {
         error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;