summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour.menus.in1
-rw-r--r--gtk2_ardour/ardour_ui.cc68
-rw-r--r--gtk2_ardour/ardour_ui.h1
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc4
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/ardour/session_directory.h7
-rw-r--r--libs/ardour/midi_source.cc3
-rw-r--r--libs/ardour/midi_stretch.cc4
-rw-r--r--libs/ardour/session_directory.cc7
-rw-r--r--libs/ardour/session_state.cc147
-rw-r--r--libs/ardour/smf_source.cc4
-rw-r--r--libs/evoral/evoral/Sequence.hpp2
-rw-r--r--libs/evoral/src/Sequence.cpp35
13 files changed, 263 insertions, 21 deletions
diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in
index 417c3b552a..56c6c6052d 100644
--- a/gtk2_ardour/ardour.menus.in
+++ b/gtk2_ardour/ardour.menus.in
@@ -16,6 +16,7 @@
<separator/>
<menuitem action='Save'/>
<menuitem action='SaveAs'/>
+ <menuitem action='Rename'/>
<menuitem action='Snapshot'/>
<menuitem action='SaveTemplate'/>
<menu name='Metadata' action='Metadata'>
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 01321c21f2..9e34ac0641 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -2120,7 +2120,6 @@ ARDOUR_UI::snapshot_session (bool switch_to_it)
prompter.set_name ("Prompter");
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
prompter.set_title (_("Take Snapshot"));
- prompter.set_title (_("Take Snapshot"));
prompter.set_prompt (_("Name of new snapshot"));
if (!switch_to_it) {
@@ -2185,6 +2184,73 @@ ARDOUR_UI::snapshot_session (bool switch_to_it)
}
}
+/** Ask the user for the name of a new shapshot and then take it.
+ */
+
+void
+ARDOUR_UI::rename_session ()
+{
+ if (!_session) {
+ return;
+ }
+
+ ArdourPrompter prompter (true);
+ string name;
+
+ prompter.set_name ("Prompter");
+ prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
+ prompter.set_title (_("Rename Session"));
+ prompter.set_prompt (_("New session name"));
+
+ again:
+ switch (prompter.run()) {
+ case RESPONSE_ACCEPT:
+ {
+ prompter.get_result (name);
+
+ bool do_rename = (name.length() != 0);
+
+ if (do_rename) {
+ if (name.find ('/') != string::npos) {
+ MessageDialog msg (_("To ensure compatibility with various systems\n"
+ "session names may not contain a '/' character"));
+ msg.run ();
+ goto again;
+ }
+ if (name.find ('\\') != string::npos) {
+ MessageDialog msg (_("To ensure compatibility with various systems\n"
+ "session names may not contain a '\\' character"));
+ msg.run ();
+ goto again;
+ }
+
+ switch (_session->rename (name)) {
+ case -1: {
+ MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
+ msg.set_position (WIN_POS_MOUSE);
+ msg.run ();
+ goto again;
+ break;
+ }
+ case 0:
+ break;
+ default: {
+ MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
+ msg.set_position (WIN_POS_MOUSE);
+ msg.run ();
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
void
ARDOUR_UI::save_state (const string & name, bool switch_to_it)
{
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 047262ec00..b288961d71 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -578,6 +578,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
guint32 last_key_press_time;
void snapshot_session (bool switch_to_it);
+ void rename_session ();
Mixer_UI *mixer;
int create_mixer ();
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index 712eb0aa3e..1379de83c8 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -147,6 +147,10 @@ ARDOUR_UI::install_actions ()
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act);
+ act = ActionManager::register_action (main_actions, X_("Rename"), _("Rename..."), sigc::mem_fun(*this, &ARDOUR_UI::rename_session));
+ ActionManager::session_sensitive_actions.push_back (act);
+ ActionManager::write_sensitive_actions.push_back (act);
+
act = ActionManager::register_action (main_actions, X_("SaveTemplate"), _("Save Template..."), sigc::mem_fun(*this, &ARDOUR_UI::save_template));
ActionManager::session_sensitive_actions.push_back (act);
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 6b9010642c..1daa82dc48 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -372,6 +372,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void remove_state (std::string snapshot_name);
void rename_state (std::string old_name, std::string new_name);
void remove_pending_capture_state ();
+ int rename (const std::string&);
static int rename_template (std::string old_name, std::string new_name);
static int delete_template (std::string name);
diff --git a/libs/ardour/ardour/session_directory.h b/libs/ardour/ardour/session_directory.h
index 49ef879ea1..16d7115aee 100644
--- a/libs/ardour/ardour/session_directory.h
+++ b/libs/ardour/ardour/session_directory.h
@@ -36,6 +36,11 @@ public:
SessionDirectory (const PBD::sys::path& session_path);
/**
+ * Change the root path of this SessionDirectory object
+ */
+ SessionDirectory& operator= (const std::string& path);
+
+ /**
* @return the absolute path to the root directory of the session
*/
const PBD::sys::path root_path() const { return m_root_path; }
@@ -124,7 +129,7 @@ protected:
const std::vector<PBD::sys::path> sub_directories () const;
/// The path to the root of the session directory.
- const PBD::sys::path m_root_path;
+ PBD::sys::path m_root_path;
};
} // namespace ARDOUR
diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc
index 4c7abd22d8..56d31ddee7 100644
--- a/libs/ardour/midi_source.cc
+++ b/libs/ardour/midi_source.cc
@@ -265,6 +265,7 @@ framecnt_t
MidiSource::midi_write (MidiRingBuffer<framepos_t>& source, framepos_t source_start, framecnt_t duration)
{
Glib::Mutex::Lock lm (_lock);
+ cerr << "MidiSource calling write unlocked\n";
const framecnt_t ret = write_unlocked (source, source_start, duration);
_last_write_end += duration;
return ret;
@@ -310,7 +311,7 @@ void
MidiSource::mark_streaming_write_completed ()
{
if (_model) {
- _model->end_write(false);
+ _model->end_write (false);
}
_writing = false;
diff --git a/libs/ardour/midi_stretch.cc b/libs/ardour/midi_stretch.cc
index 4d893d526e..4dfab65fd4 100644
--- a/libs/ardour/midi_stretch.cc
+++ b/libs/ardour/midi_stretch.cc
@@ -103,8 +103,8 @@ MidiStretch::run (boost::shared_ptr<Region> r, Progress* progress)
new_model->append(ev, Evoral::next_event_id());
}
- new_model->end_write();
- new_model->set_edited(true);
+ new_model->end_write ();
+ new_model->set_edited (true);
new_src->copy_interpolation_from (src);
diff --git a/libs/ardour/session_directory.cc b/libs/ardour/session_directory.cc
index 8996b74f61..36a01fb77d 100644
--- a/libs/ardour/session_directory.cc
+++ b/libs/ardour/session_directory.cc
@@ -37,6 +37,13 @@ SessionDirectory::SessionDirectory (const path& session_path)
}
+SessionDirectory&
+SessionDirectory::operator= (const std::string& newpath)
+{
+ m_root_path = newpath;
+ return *this;
+}
+
bool
SessionDirectory::create ()
{
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 8022c7670c..c8323047eb 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -48,6 +48,8 @@
#include <sys/mount.h>
#endif
+#include <glib.h>
+
#include <glibmm.h>
#include <glibmm/thread.h>
@@ -817,7 +819,7 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot
} else {
- if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
+ if (::rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
error << string_compose (_("could not rename temporary session file %1 to %2"),
tmp_path.to_string(), xml_path.to_string()) << endmsg;
sys::remove (tmp_path);
@@ -2950,7 +2952,7 @@ Session::cleanup_sources (CleanupReport& rep)
peakpath, _path, strerror (errno))
<< endmsg;
/* try to back out */
- rename (newpath.c_str(), _path.c_str());
+ ::rename (newpath.c_str(), _path.c_str());
goto out;
}
}
@@ -3654,3 +3656,144 @@ Session::solo_cut_control() const
return _solo_cut_control;
}
+
+int
+Session::rename (const std::string& new_name)
+{
+ string legal_name = legalize_for_path (new_name);
+ string newpath;
+ string oldstr;
+ string newstr;
+ bool first = true;
+
+#define RENAME ::rename
+
+ /* Rename:
+
+ * session directory
+ * interchange subdirectory
+ * session file
+ * session history
+
+ * Backup files are left unchanged and not renamed.
+ */
+
+ /* pass one: not 100% safe check that the new directory names don't
+ * already exist ...
+ */
+
+ for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
+ vector<string> v;
+
+ oldstr = (*i).path;
+
+ /* this is a stupid hack because Glib::path_get_dirname() is
+ * lexical-only, and so passing it /a/b/c/ gives a different
+ * result than passing it /a/b/c ...
+ */
+
+ if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
+ oldstr = oldstr.substr (0, oldstr.length() - 1);
+ }
+
+ string base = Glib::path_get_dirname (oldstr);
+ string p = Glib::path_get_basename (oldstr);
+
+ newstr = Glib::build_filename (base, legal_name);
+
+ if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
+ return -1;
+ }
+ }
+
+ /* Session dirs */
+
+ for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
+ vector<string> v;
+
+ oldstr = (*i).path;
+
+ /* this is a stupid hack because Glib::path_get_dirname() is
+ * lexical-only, and so passing it /a/b/c/ gives a different
+ * result than passing it /a/b/c ...
+ */
+
+ if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
+ oldstr = oldstr.substr (0, oldstr.length() - 1);
+ }
+
+ string base = Glib::path_get_dirname (oldstr);
+ string p = Glib::path_get_basename (oldstr);
+
+ newstr = Glib::build_filename (base, legal_name);
+
+ cerr << "Rename " << oldstr << " => " << newstr << endl;
+
+ if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
+ return 1;
+ }
+
+ if (first) {
+ (*_session_dir) = newstr;
+ newpath = newstr;
+ first = 1;
+ }
+
+ /* directory below interchange */
+
+ v.push_back (newstr);
+ v.push_back (interchange_dir_name);
+ v.push_back (p);
+
+ oldstr = Glib::build_filename (v);
+
+ v.clear ();
+ v.push_back (newstr);
+ v.push_back (interchange_dir_name);
+ v.push_back (legal_name);
+
+ newstr = Glib::build_filename (v);
+
+ cerr << "Rename " << oldstr << " => " << newstr << endl;
+
+ if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
+ return 1;
+ }
+ }
+
+ /* state file */
+
+ oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
+ newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
+
+ cerr << "Rename " << oldstr << " => " << newstr << endl;
+
+ if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
+ return 1;
+ }
+
+ /* history file */
+
+ oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
+ newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
+
+ cerr << "Rename " << oldstr << " => " << newstr << endl;
+
+ if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
+ return 1;
+ }
+
+ _path = newpath;
+ _current_snapshot_name = new_name;
+ _name = new_name;
+
+ set_dirty ();
+
+ /* save state again to get everything just right */
+
+ save_state (_current_snapshot_name);
+
+ return 0;
+
+#undef RENAME
+}
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 158c9c144d..9078a17608 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -551,8 +551,8 @@ SMFSource::load_model (bool lock, bool force_reload)
have_event_id = false;
}
- //_model->end_write (_length_beats, false, true);
- _model->end_write (false);
+ _model->end_write (_length_beats, false, true);
+ //_model->end_write (false);
_model->set_edited (false);
_model_iter = _model->begin();
diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp
index 922b7594d4..298ef48e52 100644
--- a/libs/evoral/evoral/Sequence.hpp
+++ b/libs/evoral/evoral/Sequence.hpp
@@ -97,7 +97,7 @@ public:
void start_write();
bool writing() const { return _writing; }
- void end_write(bool delete_stuck=false);
+ void end_write (Time when=0, bool delete_stuck=false, bool resolve=false);
void append(const Event<Time>& ev, Evoral::event_id_t evid);
diff --git a/libs/evoral/src/Sequence.cpp b/libs/evoral/src/Sequence.cpp
index 7296ff4e1c..5c06e8c2ca 100644
--- a/libs/evoral/src/Sequence.cpp
+++ b/libs/evoral/src/Sequence.cpp
@@ -623,7 +623,7 @@ Sequence<Time>::start_write()
*/
template<typename Time>
void
-Sequence<Time>::end_write (bool delete_stuck)
+Sequence<Time>::end_write (Time when, bool delete_stuck, bool resolve)
{
WriteLock lock(write_lock());
@@ -631,27 +631,40 @@ Sequence<Time>::end_write (bool delete_stuck)
return;
}
+ if (resolve) {
+ assert (when != 0);
+ assert (!delete_stuck);
+ }
+
DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 : end_write (%2 notes)\n", this, _notes.size()));
- if (!_percussive && delete_stuck) {
+ if (!_percussive) {
+
for (typename Notes::iterator n = _notes.begin(); n != _notes.end() ;) {
typename Notes::iterator next = n;
++next;
if ((*n)->length() == 0) {
- cerr << "WARNING: Stuck note lost: " << (*n)->note() << endl;
- _notes.erase(n);
- }
-
+ if (delete_stuck) {
+ cerr << "WARNING: Stuck note lost: " << (*n)->note() << endl;
+ _notes.erase(n);
+ } else if (resolve) {
+ if (when <= (*n)->time()) {
+ cerr << "WARNING: Stuck note resolution - end time @ "
+ << when << " is before note on: " << (**n) << endl;
+ _notes.erase (*n);
+ } else {
+ (*n)->set_length (when - (*n)->time());
+ cerr << "WARNING: resolved note-on with no note-off to generate " << (**n) << endl;
+ }
+ }
+ }
+
n = next;
}
}
for (int i = 0; i < 16; ++i) {
- if (!_write_notes[i].empty()) {
- cerr << "WARNING: Sequence<Time>::end_write: Channel " << i << " has "
- << _write_notes[i].size() << " stuck notes" << endl;
- }
_write_notes[i].clear();
}
@@ -925,7 +938,7 @@ Sequence<Time>::append_note_off_unlocked (NotePtr note)
nn->set_off_velocity (note->velocity());
_write_notes[note->channel()].erase(n);
- DEBUG_TRACE (DEBUG::Sequence, string_compose ("resolved note, length: %1\n", nn->length()));
+ DEBUG_TRACE (DEBUG::Sequence, string_compose ("resolved note @ %2 length: %1\n", nn->length(), nn->time()));
resolved = true;
break;
}