diff options
-rw-r--r-- | gtk2_ardour/ardour.menus.in | 1 | ||||
-rw-r--r-- | gtk2_ardour/ardour_ui.cc | 68 | ||||
-rw-r--r-- | gtk2_ardour/ardour_ui.h | 1 | ||||
-rw-r--r-- | gtk2_ardour/ardour_ui_ed.cc | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/session_directory.h | 7 | ||||
-rw-r--r-- | libs/ardour/midi_source.cc | 3 | ||||
-rw-r--r-- | libs/ardour/midi_stretch.cc | 4 | ||||
-rw-r--r-- | libs/ardour/session_directory.cc | 7 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 147 | ||||
-rw-r--r-- | libs/ardour/smf_source.cc | 4 | ||||
-rw-r--r-- | libs/evoral/evoral/Sequence.hpp | 2 | ||||
-rw-r--r-- | libs/evoral/src/Sequence.cpp | 35 |
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; } |