summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2011-01-19 17:38:56 +0000
committerCarl Hetherington <carl@carlh.net>2011-01-19 17:38:56 +0000
commit1e8586742e48f56bb81fa14c50442cec23894dfd (patch)
tree717797af5e3e87e67a1356e14a5d74520cbbd904
parent074d58fc6f97c225e804d32b5d2b8f09e4d512da (diff)
Fix session range location by hooking into the undo system. Fixes #3654.
git-svn-id: svn://localhost/ardour2/branches/3.0@8539 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/editor.cc8
-rw-r--r--gtk2_ardour/editor.h1
-rw-r--r--gtk2_ardour/editor_audio_import.cc3
-rw-r--r--gtk2_ardour/editor_drag.cc6
-rw-r--r--gtk2_ardour/editor_mouse.cc5
-rw-r--r--gtk2_ardour/editor_ops.cc9
-rw-r--r--gtk2_ardour/midi_time_axis.cc3
-rw-r--r--libs/ardour/ardour/session.h20
-rw-r--r--libs/ardour/session.cc104
-rw-r--r--libs/ardour/session_state.cc25
-rw-r--r--libs/ardour/session_transport.cc3
-rw-r--r--libs/ardour/wscript1
12 files changed, 117 insertions, 71 deletions
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 086e68ab3c..ba8a5e93e8 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -3070,6 +3070,14 @@ Editor::begin_reversible_command (string name)
}
void
+Editor::begin_reversible_command (GQuark q)
+{
+ if (_session) {
+ _session->begin_reversible_command (q);
+ }
+}
+
+void
Editor::commit_reversible_command ()
{
if (_session) {
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 55d5eccbb2..e500060b41 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -429,6 +429,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void snap_to (framepos_t& first, framepos_t& last, int32_t direction = 0, bool for_mark = false);
void begin_reversible_command (std::string cmd_name);
+ void begin_reversible_command (GQuark);
void commit_reversible_command ();
DragManager* drags () const {
diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc
index 8ed6248cf1..03eda12082 100644
--- a/gtk2_ardour/editor_audio_import.cc
+++ b/gtk2_ardour/editor_audio_import.cc
@@ -48,6 +48,7 @@
#include "ardour/source_factory.h"
#include "ardour/session.h"
#include "ardour/smf_source.h"
+#include "ardour/operations.h"
#include "pbd/memento_command.h"
#include "ardour_ui.h"
@@ -874,7 +875,7 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
boost::shared_ptr<Playlist> playlist = existing_track->playlist();
boost::shared_ptr<Region> copy (RegionFactory::create (region, region->properties()));
- begin_reversible_command (_("insert file"));
+ begin_reversible_command (Operations::insert_file);
playlist->clear_changes ();
playlist->add_region (copy, pos);
_session->add_command (new StatefulDiffCommand (playlist));
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index 014b91bb61..24182397c3 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -32,6 +32,8 @@
#include "ardour/session.h"
#include "ardour/dB.h"
#include "ardour/region_factory.h"
+#include "ardour/operations.h"
+
#include "editor.h"
#include "i18n.h"
#include "keyboard.h"
@@ -905,7 +907,7 @@ RegionMoveDrag::finished_no_copy (
if (_x_constrained) {
_editor->begin_reversible_command (_("fixed time region drag"));
} else {
- _editor->begin_reversible_command (_("region drag"));
+ _editor->begin_reversible_command (Operations::region_drag);
}
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ) {
@@ -1227,7 +1229,7 @@ RegionInsertDrag::finished (GdkEvent *, bool)
boost::shared_ptr<Playlist> playlist = dest_rtv->playlist();
- _editor->begin_reversible_command (_("insert region"));
+ _editor->begin_reversible_command (Operations::insert_region);
playlist->clear_changes ();
playlist->add_region (_primary->region (), _last_frame_position);
_editor->session()->add_command (new StatefulDiffCommand (playlist));
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index 7f995ca6ee..0c8da2bf1b 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -74,6 +74,7 @@
#include "ardour/region_factory.h"
#include "ardour/source_factory.h"
#include "ardour/session.h"
+#include "ardour/operations.h"
#include <bitset>
@@ -2540,7 +2541,7 @@ Editor::add_region_brush_drag (ArdourCanvas::Item* item, GdkEvent* event, Region
RegionSelection s = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id);
_drags->add (new RegionMoveDrag (this, item, region_view, s.by_layer(), true, false));
- begin_reversible_command (_("Drag region brush"));
+ begin_reversible_command (Operations::drag_region_brush);
}
/** Start a grab where a time range is selected, track(s) are selected, and the
@@ -2581,7 +2582,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event)
creating the new region and another for moving it.
*/
- begin_reversible_command (_("selection grab"));
+ begin_reversible_command (Operations::selection_grab);
boost::shared_ptr<Playlist> playlist = clicked_axisview->playlist();
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 4b7c409d3c..6eb837e5e4 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -55,6 +55,7 @@
#include "ardour/quantize.h"
#include "ardour/strip_silence.h"
#include "ardour/route_group.h"
+#include "ardour/operations.h"
#include "ardour_ui.h"
#include "editor.h"
@@ -3032,7 +3033,7 @@ Editor::region_fill_track ()
framepos_t const end = _session->current_end_frame ();
- begin_reversible_command (_("region fill"));
+ begin_reversible_command (Operations::region_fill);
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
@@ -3086,7 +3087,7 @@ Editor::region_fill_selection ()
framepos_t selection_length = end - start;
float times = (float)selection_length / region->length();
- begin_reversible_command (_("fill selection"));
+ begin_reversible_command (Operations::fill_selection);
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
@@ -4155,7 +4156,7 @@ Editor::paste_internal (framepos_t position, float times)
position = get_preferred_edit_position();
}
- begin_reversible_command (_("paste"));
+ begin_reversible_command (Operations::paste);
TrackViewList ts;
TrackViewList::iterator i;
@@ -4218,7 +4219,7 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times)
framepos_t const start_frame = regions.start ();
framepos_t const end_frame = regions.end_frame ();
- begin_reversible_command (_("duplicate region"));
+ begin_reversible_command (Operations::duplicate_region);
selection->clear_regions ();
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index 59cfe4abbd..41c85a193d 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -52,6 +52,7 @@
#include "ardour/session_playlist.h"
#include "ardour/tempo.h"
#include "ardour/utils.h"
+#include "ardour/operations.h"
#include "midi++/names.h"
@@ -1028,7 +1029,7 @@ MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit)
{
Editor* real_editor = dynamic_cast<Editor*> (&_editor);
- real_editor->begin_reversible_command (_("create region"));
+ real_editor->begin_reversible_command (Operations::create_region);
playlist()->clear_changes ();
real_editor->snap_to (pos, 0);
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 2dc2650be9..ba39ee47f9 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -23,7 +23,6 @@
#include <list>
#include <map>
#include <set>
-#include <stack>
#include <string>
#include <vector>
#include <stdint.h>
@@ -315,7 +314,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
int wipe ();
- std::pair<framepos_t, framepos_t> get_extent () const;
framepos_t current_end_frame () const;
framepos_t current_start_frame () const;
/** "actual" sample rate of session, set by current audioengine rate, pullup/down etc. */
@@ -666,6 +664,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
std::string next_redo() const { return _history.next_redo(); }
void begin_reversible_command (const std::string& cmd_name);
+ void begin_reversible_command (GQuark);
void commit_reversible_command (Command* cmd = 0);
void add_command (Command *const cmd) {
@@ -673,6 +672,11 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
_current_trans->add_command (cmd);
}
+ /** @return The list of operations that are currently in progress */
+ std::list<GQuark> const & current_operations () {
+ return _current_trans_quarks;
+ }
+
void add_commands (std::vector<Command*> const & cmds);
std::map<PBD::ID,PBD::StatefulDestructible*> registry;
@@ -841,6 +845,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
Location* _session_range_location; ///< session range, or 0 if there is nothing in the session yet
Slave* _slave;
bool _silent;
+
+ void maybe_update_session_range (framepos_t, framepos_t);
// varispeed playback
double _transport_speed;
@@ -1059,7 +1065,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void first_stage_init (std::string path, std::string snapshot_name);
int second_stage_init ();
- void update_session_range_location_marker ();
void remove_empty_sounds ();
void setup_midi_control ();
@@ -1258,6 +1263,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void remove_playlist (boost::weak_ptr<Playlist>);
void track_playlist_changed (boost::weak_ptr<Track>);
+ void playlist_region_added (boost::weak_ptr<Region>);
+ void playlist_ranges_moved (std::list<Evoral::RangeMove<framepos_t> > const &);
/* NAMED SELECTIONS */
@@ -1339,8 +1346,11 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
UndoHistory _history;
/** current undo transaction, or 0 */
UndoTransaction* _current_trans;
- /** number of times that begin_reversible_command has been called without commit_reversible_command */
- int _current_trans_depth;
+ /** GQuarks to describe the reversible commands that are currently in progress.
+ * These may be nested, in which case more recently-started commands are toward
+ * the front of the list.
+ */
+ std::list<GQuark> _current_trans_quarks;
void jack_timebase_callback (jack_transport_state_t, pframes_t, jack_position_t*, int);
int jack_sync_callback (jack_transport_state_t, jack_position_t*);
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 4d31c20456..9ac7dcc908 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -100,6 +100,7 @@
#include "ardour/utils.h"
#include "ardour/graph.h"
#include "ardour/vbap_speakers.h"
+#include "ardour/operations.h"
#include "midi++/port.h"
#include "midi++/mmc.h"
@@ -152,7 +153,6 @@ Session::Session (AudioEngine &eng,
, _bundles (new BundleList)
, _bundle_xml_node (0)
, _current_trans (0)
- , _current_trans_depth (0)
, _click_io ((IO*) 0)
, click_data (0)
, click_emphasis_data (0)
@@ -766,11 +766,9 @@ Session::track_playlist_changed (boost::weak_ptr<Track> wp)
boost::shared_ptr<Playlist> playlist;
if ((playlist = track->playlist()) != 0) {
- playlist->LengthChanged.connect_same_thread (*this, boost::bind (&Session::update_session_range_location_marker, this));
- playlist->RangesMoved.connect_same_thread (*this, boost::bind (&Session::update_session_range_location_marker, this));
+ playlist->RegionAdded.connect_same_thread (*this, boost::bind (&Session::playlist_region_added, this, _1));
+ playlist->RangesMoved.connect_same_thread (*this, boost::bind (&Session::playlist_ranges_moved, this, _1));
}
-
- update_session_range_location_marker ();
}
bool
@@ -2168,7 +2166,6 @@ Session::remove_route (boost::shared_ptr<Route> route)
}
update_route_solo_state ();
- update_session_range_location_marker ();
// We need to disconnect the route's inputs and outputs
@@ -2496,64 +2493,77 @@ Session::route_by_remote_id (uint32_t id)
return boost::shared_ptr<Route> ((Route*) 0);
}
-/** If either end of the session range location marker lies inside the current
- * session extent, move it to the corresponding session extent.
+void
+Session::playlist_region_added (boost::weak_ptr<Region> w)
+{
+ boost::shared_ptr<Region> r = w.lock ();
+ if (!r) {
+ return;
+ }
+
+ /* These are the operations that are currently in progress... */
+ list<GQuark> curr = _current_trans_quarks;
+ curr.sort ();
+
+ /* ...and these are the operations during which we want to update
+ the session range location markers.
+ */
+ list<GQuark> ops;
+ ops.push_back (Operations::capture);
+ ops.push_back (Operations::paste);
+ ops.push_back (Operations::duplicate_region);
+ ops.push_back (Operations::insert_file);
+ ops.push_back (Operations::insert_region);
+ ops.push_back (Operations::drag_region_brush);
+ ops.push_back (Operations::region_drag);
+ ops.push_back (Operations::selection_grab);
+ ops.push_back (Operations::region_fill);
+ ops.push_back (Operations::fill_selection);
+ ops.push_back (Operations::create_region);
+ ops.sort ();
+
+ /* See if any of the current operations match the ones that we want */
+ list<GQuark> in;
+ set_intersection (_current_trans_quarks.begin(), _current_trans_quarks.end(), ops.begin(), ops.end(), back_inserter (in));
+
+ /* If so, update the session range markers */
+ if (!in.empty ()) {
+ maybe_update_session_range (r->position (), r->last_frame ());
+ }
+}
+
+/** Update the session range markers if a is before the current start or
+ * b is after the current end.
*/
void
-Session::update_session_range_location_marker ()
+Session::maybe_update_session_range (framepos_t a, framepos_t b)
{
if (_state_of_the_state & Loading) {
return;
}
- pair<framepos_t, framepos_t> const ext = get_extent ();
-
if (_session_range_location == 0) {
- /* we don't have a session range yet; use this one (provided it is valid) */
- if (ext.first != max_framepos) {
- add_session_range_location (ext.first, ext.second);
- }
+
+ add_session_range_location (a, b);
+
} else {
- /* update the existing session range */
- if (ext.first < _session_range_location->start()) {
- _session_range_location->set_start (ext.first);
- set_dirty ();
- }
- if (ext.second > _session_range_location->end()) {
- _session_range_location->set_end (ext.second);
- set_dirty ();
+ if (a < _session_range_location->start()) {
+ _session_range_location->set_start (a);
}
+ if (b > _session_range_location->end()) {
+ _session_range_location->set_end (b);
+ }
}
}
-/** @return Extent of the session's contents; if the session is empty, the first value of
- * the pair will equal max_framepos.
- */
-pair<framepos_t, framepos_t>
-Session::get_extent () const
+void
+Session::playlist_ranges_moved (list<Evoral::RangeMove<framepos_t> > const & ranges)
{
- pair<framepos_t, framepos_t> ext (max_framepos, 0);
-
- boost::shared_ptr<RouteList> rl = routes.reader ();
- for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
- boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
- if (!tr || tr->destructive()) {
- // ignore tape tracks when getting extents
- continue;
- }
-
- pair<framepos_t, framepos_t> e = tr->playlist()->get_extent ();
- if (e.first < ext.first) {
- ext.first = e.first;
- }
- if (e.second > ext.second) {
- ext.second = e.second;
- }
+ for (list<Evoral::RangeMove<framepos_t> >::const_iterator i = ranges.begin(); i != ranges.end(); ++i) {
+ maybe_update_session_range (i->to, i->to + i->length);
}
-
- return ext;
}
/* Region management */
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index e7ccb02c7b..4f11291637 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -2364,6 +2364,16 @@ Session::add_commands (vector<Command*> const & cmds)
void
Session::begin_reversible_command (const string& name)
{
+ begin_reversible_command (g_quark_from_string (name.c_str ()));
+}
+
+/** Begin a reversible command using a GQuark to identify it.
+ * begin_reversible_command() and commit_reversible_command() calls may be nested,
+ * but there must be as many begin...()s as there are commit...()s.
+ */
+void
+Session::begin_reversible_command (GQuark q)
+{
/* If nested begin/commit pairs are used, we create just one UndoTransaction
to hold all the commands that are committed. This keeps the order of
commands correct in the history.
@@ -2371,20 +2381,19 @@ Session::begin_reversible_command (const string& name)
if (_current_trans == 0) {
/* start a new transaction */
- assert (_current_trans_depth == 0);
+ assert (_current_trans_quarks.empty ());
_current_trans = new UndoTransaction();
- _current_trans->set_name (name);
- } else {
- /* use the existing transaction */
- ++_current_trans_depth;
+ _current_trans->set_name (g_quark_to_string (q));
}
+
+ _current_trans_quarks.push_front (q);
}
void
Session::commit_reversible_command (Command *cmd)
{
assert (_current_trans);
- assert (_current_trans_depth > 0);
+ assert (!_current_trans_quarks.empty ());
struct timeval now;
@@ -2392,9 +2401,9 @@ Session::commit_reversible_command (Command *cmd)
_current_trans->add_command (cmd);
}
- --_current_trans_depth;
+ _current_trans_quarks.pop_front ();
- if (_current_trans_depth > 0) {
+ if (!_current_trans_quarks.empty ()) {
/* the transaction we're committing is not the top-level one */
return;
}
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 2258f70921..30c5c4b27c 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -40,6 +40,7 @@
#include "ardour/location.h"
#include "ardour/session.h"
#include "ardour/slave.h"
+#include "ardour/operations.h"
#include "i18n.h"
@@ -435,7 +436,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
reset_rf_scale (0);
if (did_record) {
- begin_reversible_command ("capture");
+ begin_reversible_command (Operations::capture);
_have_captured = true;
}
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index 779ab26d73..0a81c306c3 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -136,6 +136,7 @@ libardour_sources = [
'mute_master.cc',
'named_selection.cc',
'onset_detector.cc',
+ 'operations.cc',
'panner.cc',
'pcm_utils.cc',
'pi_controller.cc',