From cc18cf3516cd67a1eec0f1e7ed188969c0c646f1 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 7 Jun 2007 23:12:04 +0000 Subject: Write MIDI files to interchange/sessionname/midifiles (for real this time). git-svn-id: svn://localhost/ardour2/trunk@1979 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/directory_names.h | 1 + libs/ardour/ardour/session.h | 3 + libs/ardour/ardour/session_directory.h | 7 ++ libs/ardour/directory_names.cc | 1 + libs/ardour/session.cc | 10 +- libs/ardour/session_directory.cc | 7 ++ libs/ardour/session_state.cc | 177 +++++++++++++++++++++++++++++++++ libs/ardour/smf_source.cc | 2 +- 8 files changed, 201 insertions(+), 7 deletions(-) (limited to 'libs/ardour') diff --git a/libs/ardour/ardour/directory_names.h b/libs/ardour/ardour/directory_names.h index 8fdec60e9c..25f468b15f 100644 --- a/libs/ardour/ardour/directory_names.h +++ b/libs/ardour/ardour/directory_names.h @@ -10,6 +10,7 @@ extern const char* const old_sound_dir_name; extern const char* const sound_dir_name; extern const char* const midi_dir_name; extern const char* const dead_sound_dir_name; +extern const char* const dead_midi_dir_name; extern const char* const interchange_dir_name; extern const char* const peak_dir_name; extern const char* const export_dir_name; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 035a2bde1d..84c334f590 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -257,6 +257,7 @@ class Session : public PBD::StatefulDestructible sigc::signal DirtyChanged; std::string sound_dir (bool with_path = true) const; + std::string midi_dir (bool with_path = true) const; std::string peak_dir () const; std::string automation_dir () const; @@ -1554,7 +1555,9 @@ class Session : public PBD::StatefulDestructible string old_sound_dir (bool with_path = true) const; string discover_best_sound_dir (bool destructive = false); + string discover_best_midi_dir (); int ensure_sound_dir (string, string&); + int ensure_midi_dir (string, string&); void refresh_disk_space (); mutable gint _playback_load; diff --git a/libs/ardour/ardour/session_directory.h b/libs/ardour/ardour/session_directory.h index 7662894042..41667a6807 100644 --- a/libs/ardour/ardour/session_directory.h +++ b/libs/ardour/ardour/session_directory.h @@ -73,6 +73,13 @@ public: * session. */ const path dead_sound_path () const; + + /** + * @return The absolute path to the directory that midi + * files are moved to when they are no longer part of the + * session. + */ + const path dead_midi_path () const; /** * @return The absolute path to the directory that audio diff --git a/libs/ardour/directory_names.cc b/libs/ardour/directory_names.cc index d78d32f740..dfd794a2a9 100644 --- a/libs/ardour/directory_names.cc +++ b/libs/ardour/directory_names.cc @@ -9,6 +9,7 @@ const char* const sound_dir_name = X_("audiofiles"); const char* const midi_dir_name = X_("midifiles"); const char* const peak_dir_name = X_("peaks"); const char* const dead_sound_dir_name = X_("dead_sounds"); +const char* const dead_midi_dir_name = X_("dead_midi"); const char* const interchange_dir_name = X_("interchange"); const char* const export_dir_name = X_("export"); const char* const templates_dir_name = X_("templates"); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index ed1947451b..7ba1e2dfb7 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -3135,8 +3135,7 @@ Session::midi_path_from_name (string name) spath = (*i).path; - // FIXME: different directory from audio? - spath += sound_dir(false) + "/" + legalized; + spath += midi_dir(false) + "/" + legalized; snprintf (buf, sizeof(buf), "%s-%u.mid", spath.c_str(), cnt); @@ -3161,8 +3160,7 @@ Session::midi_path_from_name (string name) string foo = buf; - // FIXME: different directory than audio? - spath = discover_best_sound_dir (); + spath = discover_best_midi_dir (); spath += '/'; string::size_type pos = foo.find_last_of ('/'); @@ -3179,9 +3177,9 @@ Session::midi_path_from_name (string name) boost::shared_ptr Session::create_midi_source_for_session (MidiDiskstream& ds) { - string spath = midi_path_from_name (ds.name()); + string mpath = midi_path_from_name (ds.name()); - return boost::dynamic_pointer_cast (SourceFactory::createWritable (DataType::MIDI, *this, spath, false, frame_rate())); + return boost::dynamic_pointer_cast (SourceFactory::createWritable (DataType::MIDI, *this, mpath, false, frame_rate())); } diff --git a/libs/ardour/session_directory.cc b/libs/ardour/session_directory.cc index 0b778d85ca..99a252ecb5 100644 --- a/libs/ardour/session_directory.cc +++ b/libs/ardour/session_directory.cc @@ -130,6 +130,12 @@ SessionDirectory::dead_sound_path () const return path(m_root_path) /= dead_sound_dir_name; } +const path +SessionDirectory::dead_midi_path () const +{ + return path(m_root_path) /= dead_midi_dir_name; +} + const path SessionDirectory::export_path () const { @@ -145,6 +151,7 @@ SessionDirectory::sub_directories () const tmp_paths.push_back ( midi_path () ); tmp_paths.push_back ( peak_path () ); tmp_paths.push_back ( dead_sound_path () ); + tmp_paths.push_back ( dead_midi_path () ); tmp_paths.push_back ( export_path () ); return tmp_paths; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 8d9bb55b59..793093cf70 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -1707,6 +1707,44 @@ Session::ensure_sound_dir (string path, string& result) return 0; } +int +Session::ensure_midi_dir (string path, string& result) +{ + string dead; + + /* Ensure that the parent directory exists */ + + 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 */ + + result = path; + result += '/'; + result += midi_dir_name; + + 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_midi_dir_name; + + if (g_mkdir_with_parents (dead.c_str(), 0775)) { + error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg; + return -1; + } + + /* callers expect this to be terminated ... */ + + result += '/'; + return 0; +} + string Session::discover_best_sound_dir (bool destructive) { @@ -1815,6 +1853,114 @@ Session::discover_best_sound_dir (bool destructive) return result; } +string +Session::discover_best_midi_dir () +{ + vector::iterator i; + string result; + + /* handle common case without system calls */ + + if (session_dirs.size() == 1) { + return midi_dir(); + } + + /* OK, here's the algorithm we're following here: + + We want to select which directory to use for + the next file source to be created. Ideally, + we'd like to use a round-robin process so as to + get maximum performance benefits from splitting + the files across multiple disks. + + However, in situations without much diskspace, an + RR approach may end up filling up a filesystem + with new files while others still have space. + Its therefore important to pay some attention to + the freespace in the filesystem holding each + directory as well. However, if we did that by + itself, we'd keep creating new files in the file + system with the most space until it was as full + as all others, thus negating any performance + benefits of this RAID-1 like approach. + + So, we use a user-configurable space threshold. If + there are at least 2 filesystems with more than this + much space available, we use RR selection between them. + If not, then we pick the filesystem with the most space. + + This gets a good balance between the two + approaches. + */ + + refresh_disk_space (); + + int free_enough = 0; + + for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { + if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) { + free_enough++; + } + } + + if (free_enough >= 2) { + + bool found_it = false; + + /* use RR selection process, ensuring that the one + picked works OK. + */ + + i = last_rr_session_dir; + + do { + if (++i == session_dirs.end()) { + i = session_dirs.begin(); + } + + if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) { + if (ensure_midi_dir ((*i).path, result) == 0) { + last_rr_session_dir = i; + found_it = true; + break; + } + } + + } while (i != last_rr_session_dir); + + if (!found_it) { + result = midi_dir(); + } + + } else { + + /* pick FS with the most freespace (and that + seems to actually work ...) + */ + + vector sorted; + space_and_path_ascending_cmp cmp; + + sorted = session_dirs; + sort (sorted.begin(), sorted.end(), cmp); + + for (i = sorted.begin(); i != sorted.end(); ++i) { + if (ensure_midi_dir ((*i).path, result) == 0) { + last_rr_session_dir = i; + break; + } + } + + /* if the above fails, fall back to the most simplistic solution */ + + if (i == sorted.end()) { + return midi_dir(); + } + } + + return result; +} + int Session::load_playlists (const XMLNode& node) { @@ -1974,6 +2120,33 @@ Session::sound_dir (bool with_path) const return res; } +string +Session::midi_dir (bool with_path) const +{ + string res; + string full; + + if (with_path) { + res = _path; + } else { + full = _path; + } + + res += interchange_dir_name; + res += '/'; + res += legalize_for_path (_name); + res += '/'; + res += midi_dir_name; + + if (with_path) { + full = res; + } else { + full += res; + } + + return res; +} + string Session::peak_dir () const { @@ -2518,6 +2691,8 @@ struct RegionCounter { int Session::cleanup_sources (Session::cleanup_report& rep) { + // FIXME: needs adaptation to midi + vector > dead_sources; vector > playlists_tbd; PathScanner scanner; @@ -2777,6 +2952,8 @@ Session::cleanup_sources (Session::cleanup_report& rep) int Session::cleanup_trash_sources (Session::cleanup_report& rep) { + // FIXME: needs adaptation for MIDI + vector::iterator i; string dead_sound_dir; struct dirent* dentry; diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 9ecb961f19..11b62e488f 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -795,7 +795,7 @@ SMFSource::load_model(bool lock) time += ev.time; ev.time = time; if (ret > 0) { // didn't skip (meta) event - cerr << "ADDING EVENT TO MODEL: " << ev.time << endl; + //cerr << "ADDING EVENT TO MODEL: " << ev.time << endl; _model->append(ev); } } -- cgit v1.2.3