Write MIDI files to interchange/sessionname/midifiles (for real this time).

git-svn-id: svn://localhost/ardour2/trunk@1979 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2007-06-07 23:12:04 +00:00
parent b17a003d0a
commit cc18cf3516
8 changed files with 201 additions and 7 deletions

View file

@ -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;

View file

@ -257,6 +257,7 @@ class Session : public PBD::StatefulDestructible
sigc::signal<void> 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;

View file

@ -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

View file

@ -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");

View file

@ -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<MidiSource>
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<SMFSource> (SourceFactory::createWritable (DataType::MIDI, *this, spath, false, frame_rate()));
return boost::dynamic_pointer_cast<SMFSource> (SourceFactory::createWritable (DataType::MIDI, *this, mpath, false, frame_rate()));
}

View file

@ -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;

View file

@ -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<space_and_path>::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<space_and_path> 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<boost::shared_ptr<Source> > dead_sources;
vector<boost::shared_ptr<Playlist> > 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<space_and_path>::iterator i;
string dead_sound_dir;
struct dirent* dentry;

View file

@ -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);
}
}