diff options
Diffstat (limited to 'libs/ardour/session.cc')
-rw-r--r-- | libs/ardour/session.cc | 196 |
1 files changed, 85 insertions, 111 deletions
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 1006c0f90b..0e4a10f76b 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -36,6 +36,7 @@ #include <boost/algorithm/string/erase.hpp> +#include "pbd/convert.h" #include "pbd/error.h" #include "pbd/boost_debug.h" #include "pbd/pathscanner.h" @@ -3366,30 +3367,6 @@ Session::count_sources_by_origin (const string& path) return cnt; } -/** Return the full path (in some session directory) for a new within-session source. - * \a name must be a session-unique name that does not contain slashes - * (e.g. as returned by new_*_source_name) - */ -string -Session::new_source_path_from_name (DataType type, const string& name) -{ - assert(name.find("/") == string::npos); - - SessionDirectory sdir(get_best_session_directory_for_new_source()); - - std::string p; - if (type == DataType::AUDIO) { - p = sdir.sound_path(); - } else if (type == DataType::MIDI) { - p = sdir.midi_path(); - } else { - error << "Unknown source type, unable to create file path" << endmsg; - return ""; - } - - return Glib::build_filename (p, name); -} - string Session::peak_path (string base) const { @@ -3398,18 +3375,20 @@ Session::peak_path (string base) const /** Return a unique name based on \a base for a new internal audio source */ string -Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t chan, bool destructive) +Session::new_audio_source_path (const string& base, uint32_t nchan, uint32_t chan, bool destructive, bool take_required) { uint32_t cnt; - char buf[PATH_MAX+1]; - const uint32_t limit = 10000; + string possible_name; + const uint32_t limit = 9999; // arbitrary limit on number of files with the same basic name string legalized; string ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO); + bool some_related_source_name_exists = false; - buf[0] = '\0'; + possible_name[0] = '\0'; legalized = legalize_for_path (base); // Find a "version" of the base name that doesn't exist in any of the possible directories. + for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) { vector<space_and_path>::iterator i; @@ -3417,47 +3396,37 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { - if (destructive) { - - if (nchan < 2) { - snprintf (buf, sizeof(buf), "T%04d-%s%s", - cnt, legalized.c_str(), ext.c_str()); - } else if (nchan == 2) { - if (chan == 0) { - snprintf (buf, sizeof(buf), "T%04d-%s%%L%s", - cnt, legalized.c_str(), ext.c_str()); - } else { - snprintf (buf, sizeof(buf), "T%04d-%s%%R%s", - cnt, legalized.c_str(), ext.c_str()); - } - } else if (nchan < 26) { - snprintf (buf, sizeof(buf), "T%04d-%s%%%c%s", - cnt, legalized.c_str(), 'a' + chan, ext.c_str()); - } else { - snprintf (buf, sizeof(buf), "T%04d-%s%s", - cnt, legalized.c_str(), ext.c_str()); - } + ostringstream sstr; + if (destructive) { + sstr << 'T'; + sstr << setfill ('0') << setw (4) << cnt; + sstr << legalized; } else { - - if (nchan < 2) { - snprintf (buf, sizeof(buf), "%s-%u%s", legalized.c_str(), cnt, ext.c_str()); - } else if (nchan == 2) { - if (chan == 0) { - snprintf (buf, sizeof(buf), "%s-%u%%L%s", legalized.c_str(), cnt, ext.c_str()); - } else { - snprintf (buf, sizeof(buf), "%s-%u%%R%s", legalized.c_str(), cnt, ext.c_str()); - } - } else if (nchan < 26) { - snprintf (buf, sizeof(buf), "%s-%u%%%c%s", legalized.c_str(), cnt, 'a' + chan, ext.c_str()); - } else { - snprintf (buf, sizeof(buf), "%s-%u%s", legalized.c_str(), cnt, ext.c_str()); + sstr << legalized; + + if (take_required || some_related_source_name_exists) { + sstr << '-'; + sstr << cnt; } } + + if (nchan == 2) { + if (chan == 0) { + sstr << "%L"; + } else { + sstr << "%R"; + } + } else if (nchan > 2 && nchan < 26) { + sstr << '%'; + sstr << 'a' + chan; + } - SessionDirectory sdir((*i).path); + sstr << ext; - string spath = sdir.sound_path(); + possible_name = sstr.str(); + SessionDirectory sdir((*i).path); + const string spath = sdir.sound_path(); /* note that we search *without* the extension so that we don't end up both "Audio 1-1.wav" and "Audio 1-1.caf" @@ -3465,7 +3434,7 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha a file format change. */ - if (matching_unsuffixed_filename_exists_in (spath, buf)) { + if (matching_unsuffixed_filename_exists_in (spath, possible_name)) { existing++; break; } @@ -3479,7 +3448,7 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha * notions of their removability. */ - string possible_path = Glib::build_filename (spath, buf); + string possible_path = Glib::build_filename (spath, possible_name); if (audio_source_by_path_and_channel (possible_path, chan)) { existing++; @@ -3491,6 +3460,8 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha break; } + some_related_source_name_exists = true; + if (cnt > limit) { error << string_compose( _("There are already %1 recordings for %2, which I consider too many."), @@ -3500,32 +3471,31 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha } } - return Glib::path_get_basename (buf); -} + /* We've established that the new name does not exist in any session + * directory, so now find out which one we should use for this new + * audio source. + */ -/** Create a new within-session audio source */ -boost::shared_ptr<AudioFileSource> -Session::create_audio_source_for_session (size_t n_chans, string const & n, uint32_t chan, bool destructive) -{ - const string name = new_audio_source_name (n, n_chans, chan, destructive); - const string path = new_source_path_from_name(DataType::AUDIO, name); + SessionDirectory sdir (get_best_session_directory_for_new_audio()); + + std::string s = Glib::build_filename (sdir.sound_path(), possible_name); - return boost::dynamic_pointer_cast<AudioFileSource> ( - SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate())); + return s; } /** Return a unique name based on \a owner_name for a new internal MIDI source */ string -Session::new_midi_source_name (const string& owner_name) +Session::new_midi_source_path (const string& base) { uint32_t cnt; char buf[PATH_MAX+1]; const uint32_t limit = 10000; string legalized; + string possible_path; string possible_name; buf[0] = '\0'; - legalized = legalize_for_path (owner_name); + legalized = legalize_for_path (base); // Find a "version" of the file name that doesn't exist in any of the possible directories. @@ -3533,7 +3503,7 @@ Session::new_midi_source_name (const string& owner_name) vector<space_and_path>::iterator i; uint32_t existing = 0; - + for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { SessionDirectory sdir((*i).path); @@ -3541,7 +3511,7 @@ Session::new_midi_source_name (const string& owner_name) snprintf (buf, sizeof(buf), "%s-%u.mid", legalized.c_str(), cnt); possible_name = buf; - std::string possible_path = Glib::build_filename (sdir.midi_path(), possible_name); + possible_path = Glib::build_filename (sdir.midi_path(), possible_name); if (Glib::file_test (possible_path, Glib::FILE_TEST_EXISTS)) { existing++; @@ -3559,31 +3529,47 @@ Session::new_midi_source_name (const string& owner_name) if (cnt > limit) { error << string_compose( _("There are already %1 recordings for %2, which I consider too many."), - limit, owner_name) << endmsg; + limit, base) << endmsg; destroy (); - throw failed_constructor(); + return 0; } } - return possible_name; + /* No need to "find best location" for software/app-based RAID, because + MIDI is so small that we always put it in the same place. + */ + + return possible_path; } +/** Create a new within-session audio source */ +boost::shared_ptr<AudioFileSource> +Session::create_audio_source_for_session (size_t n_chans, string const & base, uint32_t chan, bool destructive) +{ + const string path = new_audio_source_path (base, n_chans, chan, destructive, true); + + if (!path.empty()) { + return boost::dynamic_pointer_cast<AudioFileSource> ( + SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate())); + } else { + throw failed_constructor (); + } +} + /** Create a new within-session MIDI source */ boost::shared_ptr<MidiSource> Session::create_midi_source_for_session (string const & basic_name) { - std::string name; - - if (name.empty()) { - name = new_midi_source_name (basic_name); + const string path = new_midi_source_path (basic_name); + + if (!path.empty()) { + return boost::dynamic_pointer_cast<SMFSource> ( + SourceFactory::createWritable ( + DataType::MIDI, *this, path, false, frame_rate())); + } else { + throw failed_constructor (); } - - const string path = new_source_path_from_name (DataType::MIDI, name); - - return boost::dynamic_pointer_cast<SMFSource> ( - SourceFactory::createWritable ( - DataType::MIDI, *this, path, false, frame_rate())); } /** Create a new within-session MIDI source */ @@ -3617,7 +3603,7 @@ Session::create_midi_source_by_stealing_name (boost::shared_ptr<Track> track) return boost::shared_ptr<MidiSource>(); } - const string path = new_source_path_from_name (DataType::MIDI, name); + const string path = new_midi_source_path (name); return boost::dynamic_pointer_cast<SMFSource> ( SourceFactory::createWritable ( @@ -4123,18 +4109,13 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end, boost::shared_ptr<Region> result; boost::shared_ptr<Playlist> playlist; boost::shared_ptr<AudioFileSource> fsource; - uint32_t x; - char buf[PATH_MAX+1]; ChanCount diskstream_channels (track.n_channels()); framepos_t position; framecnt_t this_chunk; framepos_t to_do; BufferSet buffers; - SessionDirectory sdir(get_best_session_directory_for_new_source ()); - const string sound_dir = sdir.sound_path(); framepos_t len = end - start; bool need_block_size_reset = false; - string ext; ChanCount const max_proc = track.max_processor_streams (); if (end <= start) { @@ -4155,29 +4136,22 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end, goto out; } - ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO); - for (uint32_t chan_n = 0; chan_n < diskstream_channels.n_audio(); ++chan_n) { - for (x = 0; x < 99999; ++x) { - snprintf (buf, sizeof(buf), "%s/%s-%d-bounce-%" PRIu32 "%s", sound_dir.c_str(), playlist->name().c_str(), chan_n, x+1, ext.c_str()); - if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) { - break; - } - } - - if (x == 99999) { - error << string_compose (_("too many bounced versions of playlist \"%1\""), playlist->name()) << endmsg; + string base_name = string_compose ("%1-%2-bounce", playlist->name(), chan_n); + string path = new_audio_source_path (base_name, diskstream_channels.n_audio(), chan_n, false, true); + + if (path.empty()) { goto out; } try { fsource = boost::dynamic_pointer_cast<AudioFileSource> ( - SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate())); + SourceFactory::createWritable (DataType::AUDIO, *this, path, false, frame_rate())); } catch (failed_constructor& err) { - error << string_compose (_("cannot create new audio file \"%1\" for %2"), buf, track.name()) << endmsg; + error << string_compose (_("cannot create new audio file \"%1\" for %2"), path, track.name()) << endmsg; goto out; } |