summaryrefslogtreecommitdiff
path: root/libs/ardour
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 /libs/ardour
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
Diffstat (limited to 'libs/ardour')
-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
5 files changed, 92 insertions, 61 deletions
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',