+ string dir;
+ string suffix;
+ string::size_type slash;
+ string::size_type dash;
+ string::size_type postfix;
+
+ /* find last slash */
+
+ if ((slash = path.find_last_of ('/')) == string::npos) {
+ return "";
+ }
+
+ dir = path.substr (0, slash+1);
+
+ /* '-' is not a legal character for the NAME part of the path */
+
+ if ((dash = path.find_last_of ('-')) == string::npos) {
+ return "";
+ }
+
+ suffix = path.substr (dash+1);
+
+ // Suffix is now everything after the dash. Now we need to eliminate
+ // the nnnnn part, which is done by either finding a '%' or a '.'
+
+ postfix = suffix.find_last_of ("%");
+ if (postfix == string::npos) {
+ postfix = suffix.find_last_of ('.');
+ }
+
+ if (postfix != string::npos) {
+ suffix = suffix.substr (postfix);
+ } else {
+ error << "Logic error in Session::change_audio_path_by_name(), please report to the developers" << endl;
+ return "";
+ }
+
+ const uint32_t limit = 10000;
+ char buf[PATH_MAX+1];
+
+ for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
+
+ snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
+
+ if (access (buf, F_OK) != 0) {
+ path = buf;
+ break;
+ }
+ path = "";
+ }
+
+ if (path == "") {
+ error << "FATAL ERROR! Could not find a " << endl;
+ }
+
+ }
+
+ return path;
+}
+
+string
+Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool destructive)
+{
+ string spath;
+ uint32_t cnt;
+ char buf[PATH_MAX+1];
+ const uint32_t limit = 10000;
+ string legalized;
+
+ buf[0] = '\0';
+ legalized = legalize_for_path (name);
+
+ /* find a "version" of the file 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;
+ uint32_t existing = 0;
+
+ for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
+
+ spath = (*i).path;
+
+ spath += sound_dir (false);
+
+ if (destructive) {
+ if (nchan < 2) {
+ snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
+ } else if (nchan == 2) {
+ if (chan == 0) {
+ snprintf (buf, sizeof(buf), "%s/T%04d-%s%%L.wav", spath.c_str(), cnt, legalized.c_str());
+ } else {
+ snprintf (buf, sizeof(buf), "%s/T%04d-%s%%R.wav", spath.c_str(), cnt, legalized.c_str());
+ }
+ } else if (nchan < 26) {
+ snprintf (buf, sizeof(buf), "%s/T%04d-%s%%%c.wav", spath.c_str(), cnt, legalized.c_str(), 'a' + chan);
+ } else {
+ snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
+ }
+
+ } else {
+
+ spath += '/';
+ spath += legalized;
+
+ if (nchan < 2) {
+ snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
+ } else if (nchan == 2) {
+ if (chan == 0) {
+ snprintf (buf, sizeof(buf), "%s-%u%%L.wav", spath.c_str(), cnt);
+ } else {
+ snprintf (buf, sizeof(buf), "%s-%u%%R.wav", spath.c_str(), cnt);
+ }
+ } else if (nchan < 26) {
+ snprintf (buf, sizeof(buf), "%s-%u%%%c.wav", spath.c_str(), cnt, 'a' + chan);
+ } else {
+ snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
+ }
+ }
+
+ if (g_file_test (buf, G_FILE_TEST_EXISTS)) {
+ existing++;
+ }
+
+ }
+
+ if (existing == 0) {
+ break;
+ }
+
+ if (cnt > limit) {
+ error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
+ destroy ();
+ throw failed_constructor();
+ }
+ }
+
+ /* we now have a unique name for the file, but figure out where to
+ actually put it.
+ */
+
+ string foo = buf;
+
+ spath = discover_best_sound_dir ();
+ spath += '/';
+
+ string::size_type pos = foo.find_last_of ('/');
+
+ if (pos == string::npos) {
+ spath += foo;
+ } else {
+ spath += foo.substr (pos + 1);
+ }
+
+ return spath;
+}
+
+boost::shared_ptr<AudioFileSource>
+Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
+{
+ string spath = audio_path_from_name (ds.name(), ds.n_channels().get(DataType::AUDIO), chan, destructive);
+ return boost::dynamic_pointer_cast<AudioFileSource> (
+ SourceFactory::createWritable (DataType::AUDIO, *this, spath, destructive, frame_rate()));
+}
+
+// FIXME: _terrible_ code duplication
+string
+Session::change_midi_path_by_name (string path, string oldname, string newname, bool destructive)
+{
+ string look_for;
+ string old_basename = PBD::basename_nosuffix (oldname);
+ string new_legalized = legalize_for_path (newname);
+
+ /* note: we know (or assume) the old path is already valid */
+
+ if (destructive) {
+
+ /* destructive file sources have a name of the form:
+
+ /path/to/Tnnnn-NAME(%[LR])?.wav
+
+ the task here is to replace NAME with the new name.
+ */
+