substantive changes to the logic and safety for naming of (audio/MIDI) sources, especially when created via import
This commit is contained in:
parent
08a1409b1f
commit
74bc0c8468
@ -1262,7 +1262,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||
int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::Track>&, bool add_channel_suffix);
|
||||
|
||||
int finish_bringing_in_material (boost::shared_ptr<ARDOUR::Region> region, uint32_t, uint32_t, framepos_t& pos, Editing::ImportMode mode,
|
||||
boost::shared_ptr<ARDOUR::Track>& existing_track);
|
||||
boost::shared_ptr<ARDOUR::Track>& existing_track, const std::string& new_track_name);
|
||||
|
||||
boost::shared_ptr<ARDOUR::AudioTrack> get_nth_selected_audio_track (int nth) const;
|
||||
boost::shared_ptr<ARDOUR::MidiTrack> get_nth_selected_midi_track (int nth) const;
|
||||
|
@ -657,7 +657,8 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
|
||||
uint32_t input_chan = 0;
|
||||
uint32_t output_chan = 0;
|
||||
bool use_timestamp;
|
||||
|
||||
vector<string> track_names;
|
||||
|
||||
use_timestamp = (pos == -1);
|
||||
|
||||
// kludge (for MIDI we're abusing "channel" for "track" here)
|
||||
@ -694,6 +695,11 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
|
||||
|
||||
regions.push_back (r);
|
||||
|
||||
/* if we're creating a new track, name it after the cleaned-up
|
||||
* and "merged" region name.
|
||||
*/
|
||||
|
||||
track_names.push_back (region_name);
|
||||
|
||||
} else if (target_regions == -1 || target_regions > 1) {
|
||||
|
||||
@ -724,29 +730,26 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
|
||||
region_name = (*x)->name();
|
||||
}
|
||||
|
||||
switch (sources.size()) {
|
||||
/* zero and one channel handled
|
||||
by previous if() condition
|
||||
*/
|
||||
case 2:
|
||||
if (sources.size() == 2) {
|
||||
if (n == 0) {
|
||||
region_name += "-L";
|
||||
} else {
|
||||
region_name += "-R";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
region_name += (char) '-';
|
||||
region_name += (char) ('1' + n);
|
||||
break;
|
||||
} else if (sources.size() > 2) {
|
||||
region_name += string_compose ("-%1", n+1);
|
||||
}
|
||||
|
||||
track_names.push_back (region_name);
|
||||
|
||||
} else {
|
||||
if (fs) {
|
||||
region_name = region_name_from_path (fs->path(), false, false, sources.size(), n);
|
||||
} else{
|
||||
} else {
|
||||
region_name = (*x)->name();
|
||||
}
|
||||
|
||||
track_names.push_back (PBD::basename_nosuffix (paths[n]));
|
||||
}
|
||||
|
||||
PropertyList plist;
|
||||
@ -798,6 +801,12 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
|
||||
framepos_t rlen = 0;
|
||||
|
||||
begin_reversible_command (Operations::insert_file);
|
||||
|
||||
/* we only use tracks names when importing to new tracks, but we
|
||||
* require that one is defined for every region, just to keep
|
||||
* the API simpler.
|
||||
*/
|
||||
assert (regions.size() == track_names.size());
|
||||
|
||||
for (vector<boost::shared_ptr<Region> >::iterator r = regions.begin(); r != regions.end(); ++r, ++n) {
|
||||
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (*r);
|
||||
@ -830,9 +839,8 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
|
||||
pos = get_preferred_edit_position ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_bringing_in_material (*r, input_chan, output_chan, pos, mode, track);
|
||||
|
||||
finish_bringing_in_material (*r, input_chan, output_chan, pos, mode, track, track_names[n]);
|
||||
|
||||
rlen = (*r)->length();
|
||||
|
||||
@ -859,7 +867,7 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
|
||||
|
||||
int
|
||||
Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t in_chans, uint32_t out_chans, framepos_t& pos,
|
||||
ImportMode mode, boost::shared_ptr<Track>& existing_track)
|
||||
ImportMode mode, boost::shared_ptr<Track>& existing_track, const string& new_track_name)
|
||||
{
|
||||
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
|
||||
boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(region);
|
||||
@ -916,7 +924,11 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
|
||||
existing_track = mt.front();
|
||||
}
|
||||
|
||||
existing_track->set_name (region->name());
|
||||
if (!new_track_name.empty()) {
|
||||
existing_track->set_name (new_track_name);
|
||||
} else {
|
||||
existing_track->set_name (region->name());
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<Playlist> playlist = existing_track->playlist();
|
||||
|
@ -85,6 +85,10 @@ public:
|
||||
void existence_check ();
|
||||
virtual void prevent_deletion ();
|
||||
|
||||
/** Rename the file on disk referenced by this source to \param newname
|
||||
*/
|
||||
int rename (const std::string& name);
|
||||
|
||||
protected:
|
||||
FileSource (Session& session, DataType type,
|
||||
const std::string& path,
|
||||
|
@ -195,10 +195,10 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||
std::string peak_path (std::string) const;
|
||||
|
||||
std::string peak_path_from_audio_path (std::string) const;
|
||||
std::string new_audio_source_name (const std::string&, uint32_t nchans, uint32_t chan, bool destructive);
|
||||
std::string new_midi_source_name (const std::string&);
|
||||
std::string new_source_path_from_name (DataType type, const std::string&);
|
||||
std::string new_audio_source_path (const std::string&, uint32_t nchans, uint32_t chan, bool destructive, bool take_required);
|
||||
std::string new_midi_source_path (const std::string&);
|
||||
RouteList new_route_from_template (uint32_t how_many, const std::string& template_path, const std::string& name);
|
||||
std::vector<std::string> get_paths_for_new_sources (bool allow_replacing, const std::string& import_file_path, uint32_t channels);
|
||||
|
||||
void process (pframes_t nframes);
|
||||
|
||||
@ -526,8 +526,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||
|
||||
boost::shared_ptr<Region> find_whole_file_parent (boost::shared_ptr<Region const>) const;
|
||||
|
||||
std::string path_from_region_name (DataType type, std::string name, std::string identifier);
|
||||
|
||||
boost::shared_ptr<Region> XMLRegionFactory (const XMLNode&, bool full);
|
||||
boost::shared_ptr<AudioRegion> XMLAudioRegionFactory (const XMLNode&, bool full);
|
||||
boost::shared_ptr<MidiRegion> XMLMidiRegionFactory (const XMLNode&, bool full);
|
||||
@ -1433,7 +1431,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||
|
||||
bool no_questions_about_missing_files;
|
||||
|
||||
std::string get_best_session_directory_for_new_source ();
|
||||
std::string get_best_session_directory_for_new_audio ();
|
||||
|
||||
mutable gint _playback_load;
|
||||
mutable gint _capture_load;
|
||||
|
@ -47,15 +47,6 @@ public:
|
||||
|
||||
virtual ~SMFSource ();
|
||||
|
||||
/** Rename the file on disk referenced by this source to \param newname
|
||||
*
|
||||
* This method exists only for MIDI file sources, not for audio, which
|
||||
* can never be renamed. It exists for MIDI so that we can get
|
||||
* consistent and sane region/source numbering when regions are added
|
||||
* manually (which never happens with audio).
|
||||
*/
|
||||
int rename (const std::string& name);
|
||||
|
||||
bool safe_file_extension (const std::string& path) const {
|
||||
return safe_midi_file_extension(path);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "pbd/stl_delete.h"
|
||||
#include "pbd/strsplit.h"
|
||||
#include "pbd/shortpath.h"
|
||||
#include "pbd/stacktrace.h"
|
||||
#include "pbd/enumwriter.h"
|
||||
|
||||
#include <sndfile.h>
|
||||
|
@ -739,4 +739,3 @@ Diskstream::disengage_record_enable ()
|
||||
{
|
||||
g_atomic_int_set (&_record_enabled, 0);
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,7 @@ FileSource::move_to_trash (const string& trash_dir_name)
|
||||
|
||||
if (move_dependents_to_trash() != 0) {
|
||||
/* try to back out */
|
||||
rename (newpath.c_str(), _path.c_str());
|
||||
::rename (newpath.c_str(), _path.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -581,3 +581,28 @@ FileSource::is_stub () const
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
FileSource::rename (const string& newpath)
|
||||
{
|
||||
Glib::Threads::Mutex::Lock lm (_lock);
|
||||
string oldpath = _path;
|
||||
|
||||
// Test whether newpath exists, if yes notify the user but continue.
|
||||
if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
|
||||
error << string_compose (_("Programming error! %1 tried to rename a file over another file! It's safe to continue working, but please report this to the developers."), PROGRAM_NAME) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Glib::file_test (oldpath.c_str(), Glib::FILE_TEST_EXISTS)) {
|
||||
/* rename only needed if file exists on disk */
|
||||
if (::rename (oldpath.c_str(), newpath.c_str()) != 0) {
|
||||
error << string_compose (_("cannot rename file %1 to %2 (%3)"), oldpath, newpath, strerror(errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_name = Glib::path_get_basename (newpath);
|
||||
_path = newpath;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -59,10 +59,9 @@ Filter::make_new_sources (boost::shared_ptr<Region> region, SourceList& nsrcs, s
|
||||
}
|
||||
}
|
||||
|
||||
string path = session.path_from_region_name (region->data_type(),
|
||||
PBD::basename_nosuffix (names[i]), string (""));
|
||||
string path = session.new_audio_source_path (name, region->n_channels(), i, false, false);
|
||||
|
||||
if (path.length() == 0) {
|
||||
if (path.empty()) {
|
||||
error << string_compose (_("filter: error creating name for new file based on %1"), region->name())
|
||||
<< endmsg;
|
||||
return -1;
|
||||
|
@ -116,78 +116,31 @@ open_importable_source (const string& path, framecnt_t samplerate, ARDOUR::SrcQu
|
||||
}
|
||||
}
|
||||
|
||||
static std::string
|
||||
get_non_existent_filename (HeaderFormat hf, DataType type, const bool allow_replacing, const std::string& destdir, const std::string& basename, uint channel, uint channels)
|
||||
{
|
||||
char buf[PATH_MAX+1];
|
||||
bool goodfile = false;
|
||||
string base = basename;
|
||||
string ext = native_header_format_extension (hf, type);
|
||||
uint32_t cnt = 1;
|
||||
|
||||
do {
|
||||
|
||||
if (type == DataType::AUDIO && channels == 2) {
|
||||
if (channel == 0) {
|
||||
if (cnt == 1) {
|
||||
snprintf (buf, sizeof(buf), "%s-L%s", base.c_str(), ext.c_str());
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf), "%s-%d-L%s", base.c_str(), cnt, ext.c_str());
|
||||
}
|
||||
} else {
|
||||
if (cnt == 1) {
|
||||
snprintf (buf, sizeof(buf), "%s-R%s", base.c_str(), ext.c_str());
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf), "%s-%d-R%s", base.c_str(), cnt, ext.c_str());
|
||||
}
|
||||
}
|
||||
} else if (channels > 1) {
|
||||
if (cnt == 1) {
|
||||
snprintf (buf, sizeof(buf), "%s-c%d%s", base.c_str(), channel, ext.c_str());
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf), "%s-%d-c%d%s", base.c_str(), cnt, channel, ext.c_str());
|
||||
}
|
||||
} else {
|
||||
if (cnt == 1) {
|
||||
snprintf (buf, sizeof(buf), "%s%s", base.c_str(), ext.c_str());
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf), "%s-%d%s", base.c_str(), cnt, ext.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
string tempname = destdir + "/" + buf;
|
||||
|
||||
if (!allow_replacing && Glib::file_test (tempname, Glib::FILE_TEST_EXISTS)) {
|
||||
|
||||
cnt++;
|
||||
|
||||
} else {
|
||||
|
||||
goodfile = true;
|
||||
}
|
||||
|
||||
} while (!goodfile);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static vector<string>
|
||||
get_paths_for_new_sources (HeaderFormat hf, const bool allow_replacing, const string& import_file_path, const string& session_dir, uint channels)
|
||||
vector<string>
|
||||
Session::get_paths_for_new_sources (bool /*allow_replacing*/, const string& import_file_path, uint32_t channels)
|
||||
{
|
||||
vector<string> new_paths;
|
||||
const string basename = basename_nosuffix (import_file_path);
|
||||
|
||||
SessionDirectory sdir(session_dir);
|
||||
|
||||
for (uint n = 0; n < channels; ++n) {
|
||||
|
||||
const DataType type = SMFSource::safe_midi_file_extension (import_file_path) ? DataType::MIDI : DataType::AUDIO;
|
||||
string filepath;
|
||||
|
||||
std::string filepath = (type == DataType::MIDI)
|
||||
? sdir.midi_path() : sdir.sound_path();
|
||||
switch (type) {
|
||||
case DataType::MIDI:
|
||||
filepath = new_midi_source_path (basename);
|
||||
break;
|
||||
case DataType::AUDIO:
|
||||
filepath = new_audio_source_path (basename, channels, n, false, false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (filepath.empty()) {
|
||||
error << string_compose (_("Cannot find new filename for imported file %1"), import_file_path) << endmsg;
|
||||
return vector<string>();
|
||||
}
|
||||
|
||||
filepath = Glib::build_filename (filepath,
|
||||
get_non_existent_filename (hf, type, allow_replacing, filepath, basename, n, channels));
|
||||
new_paths.push_back (filepath);
|
||||
}
|
||||
|
||||
@ -274,12 +227,12 @@ write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status,
|
||||
{
|
||||
const framecnt_t nframes = ResampledImportableSource::blocksize;
|
||||
boost::shared_ptr<AudioFileSource> afs;
|
||||
uint channels = source->channels();
|
||||
uint32_t channels = source->channels();
|
||||
|
||||
boost::scoped_array<float> data(new float[nframes * channels]);
|
||||
vector<boost::shared_array<Sample> > channel_data;
|
||||
|
||||
for (uint n = 0; n < channels; ++n) {
|
||||
for (uint32_t n = 0; n < channels; ++n) {
|
||||
channel_data.push_back(boost::shared_array<Sample>(new Sample[nframes]));
|
||||
}
|
||||
|
||||
@ -323,14 +276,14 @@ write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status,
|
||||
progress_multiplier = 0.5;
|
||||
progress_base = 0.5;
|
||||
}
|
||||
|
||||
uint read_count = 0;
|
||||
|
||||
framecnt_t read_count = 0;
|
||||
|
||||
while (!status.cancel) {
|
||||
|
||||
framecnt_t nread, nfread;
|
||||
uint x;
|
||||
uint chn;
|
||||
uint32_t x;
|
||||
uint32_t chn;
|
||||
|
||||
if ((nread = source->read (data.get(), nframes)) == 0) {
|
||||
break;
|
||||
@ -513,10 +466,7 @@ Session::import_files (ImportStatus& status)
|
||||
}
|
||||
}
|
||||
|
||||
vector<string> new_paths = get_paths_for_new_sources (config.get_native_file_header_format(),
|
||||
status.replace_existing_source, *p,
|
||||
get_best_session_directory_for_new_source (),
|
||||
channels);
|
||||
vector<string> new_paths = get_paths_for_new_sources (status.replace_existing_source, *p, channels);
|
||||
Sources newfiles;
|
||||
framepos_t natural_position = source ? source->natural_position() : 0;
|
||||
|
||||
|
@ -1234,9 +1234,9 @@ MidiDiskstream::steal_write_source_name ()
|
||||
*/
|
||||
|
||||
try {
|
||||
string new_name = _session.new_midi_source_name (name());
|
||||
string new_path = _session.new_midi_source_path (name());
|
||||
|
||||
if (_write_source->rename (new_name)) {
|
||||
if (_write_source->rename (new_path)) {
|
||||
return string();
|
||||
}
|
||||
} catch (...) {
|
||||
|
@ -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) {
|
||||
|
||||
ostringstream sstr;
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
sstr << ext;
|
||||
|
||||
possible_name = sstr.str();
|
||||
SessionDirectory sdir((*i).path);
|
||||
|
||||
string spath = sdir.sound_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());
|
||||
|
||||
return boost::dynamic_pointer_cast<AudioFileSource> (
|
||||
SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate()));
|
||||
std::string s = Glib::build_filename (sdir.sound_path(), possible_name);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1830,41 +1830,6 @@ Session::get_sources_as_xml ()
|
||||
return *node;
|
||||
}
|
||||
|
||||
string
|
||||
Session::path_from_region_name (DataType type, string name, string identifier)
|
||||
{
|
||||
char buf[PATH_MAX+1];
|
||||
uint32_t n;
|
||||
SessionDirectory sdir(get_best_session_directory_for_new_source());
|
||||
std::string source_dir = ((type == DataType::AUDIO)
|
||||
? sdir.sound_path() : sdir.midi_path());
|
||||
|
||||
string ext = native_header_format_extension (config.get_native_file_header_format(), type);
|
||||
|
||||
for (n = 0; n < 999999; ++n) {
|
||||
if (identifier.length()) {
|
||||
snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
|
||||
identifier.c_str(), n, ext.c_str());
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
|
||||
n, ext.c_str());
|
||||
}
|
||||
|
||||
std::string source_path = Glib::build_filename (source_dir, buf);
|
||||
|
||||
if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
|
||||
return source_path;
|
||||
}
|
||||
}
|
||||
|
||||
error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
|
||||
name, identifier)
|
||||
<< endmsg;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Session::load_sources (const XMLNode& node)
|
||||
{
|
||||
@ -2053,7 +2018,7 @@ Session::refresh_disk_space ()
|
||||
}
|
||||
|
||||
string
|
||||
Session::get_best_session_directory_for_new_source ()
|
||||
Session::get_best_session_directory_for_new_audio ()
|
||||
{
|
||||
vector<space_and_path>::iterator i;
|
||||
string result = _session_dir->root_path();
|
||||
|
@ -718,34 +718,3 @@ SMFSource::prevent_deletion ()
|
||||
_flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy));
|
||||
}
|
||||
|
||||
int
|
||||
SMFSource::rename (const string& newname)
|
||||
{
|
||||
Glib::Threads::Mutex::Lock lm (_lock);
|
||||
string oldpath = _path;
|
||||
string newpath = _session.new_source_path_from_name (DataType::MIDI, newname);
|
||||
|
||||
if (newpath.empty()) {
|
||||
error << string_compose (_("programming error: %1"), "cannot generate a changed file path") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Test whether newpath exists, if yes notify the user but continue.
|
||||
if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
|
||||
error << string_compose (_("Programming error! %1 tried to rename a file over another file! It's safe to continue working, but please report this to the developers."), PROGRAM_NAME) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Glib::file_test (oldpath.c_str(), Glib::FILE_TEST_EXISTS)) {
|
||||
/* rename only needed if file exists on disk */
|
||||
if (::rename (oldpath.c_str(), newpath.c_str()) != 0) {
|
||||
error << string_compose (_("cannot rename file %1 to %2 (%3)"), oldpath, newpath, strerror(errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_name = Glib::path_get_basename (newpath);
|
||||
_path = newpath;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user