13
0

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
This commit is contained in:
Carl Hetherington 2011-01-19 17:38:56 +00:00
parent 074d58fc6f
commit 1e8586742e
12 changed files with 117 additions and 71 deletions

View File

@ -3069,6 +3069,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 ()
{

View File

@ -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 {

View File

@ -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));

View File

@ -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));

View File

@ -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();

View File

@ -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 ();

View File

@ -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);

View File

@ -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*);

View File

@ -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 (a < _session_range_location->start()) {
_session_range_location->set_start (a);
}
if (ext.second > _session_range_location->end()) {
_session_range_location->set_end (ext.second);
set_dirty ();
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 */

View File

@ -2363,6 +2363,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
@ -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;
}

View File

@ -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;
}

View File

@ -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',