Add editor selection state to session history via a SelectionMemento, which

combines selection related editor properties with the current editor selection.

The related editor properties are:
mouse mode,
zoom setting,
left frame of the canvas,
y origin of the canvas.

Selection state now includes region views (storing the underlying region id)
and time.

This patch also fixes a region mute undo bug.
This commit is contained in:
nick_m 2014-12-15 00:13:38 +11:00 committed by Paul Davis
parent 2c8a769aae
commit 9af9e17adc
24 changed files with 414 additions and 134 deletions

View File

@ -1237,7 +1237,7 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
can represent automation data with it.
*/
trackview.session()->begin_reversible_command (_("add gain control point"));
trackview.editor().begin_reversible_command (_("add gain control point"));
XMLNode &before = audio_region()->envelope()->get_state();
if (!audio_region()->envelope_active()) {
@ -1251,7 +1251,7 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
XMLNode &after = audio_region()->envelope()->get_state();
trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after));
trackview.session()->commit_reversible_command ();
trackview.editor().commit_reversible_command ();
}
void

View File

@ -283,7 +283,7 @@ AutomationLine::modify_point_y (ControlPoint& cp, double y)
double const x = trackview.editor().sample_to_pixel_unrounded (_time_converter->to((*cp.model())->when) - _offset);
trackview.editor().session()->begin_reversible_command (_("automation event move"));
trackview.editor().begin_reversible_command (_("automation event move"));
trackview.editor().session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
@ -304,7 +304,7 @@ AutomationLine::modify_point_y (ControlPoint& cp, double y)
trackview.editor().session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder(), 0, &alist->get_state()));
trackview.editor().session()->commit_reversible_command ();
trackview.editor().commit_reversible_command ();
trackview.editor().session()->set_dirty ();
}
@ -456,7 +456,7 @@ AutomationLine::string_to_fraction (string const & s) const
void
AutomationLine::start_drag_single (ControlPoint* cp, double x, float fraction)
{
trackview.editor().session()->begin_reversible_command (_("automation event move"));
trackview.editor().begin_reversible_command (_("automation event move"));
trackview.editor().session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
@ -482,7 +482,7 @@ AutomationLine::start_drag_single (ControlPoint* cp, double x, float fraction)
void
AutomationLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction)
{
trackview.editor().session()->begin_reversible_command (_("automation range move"));
trackview.editor().begin_reversible_command (_("automation range move"));
trackview.editor().session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder (), &get_state(), 0));
@ -502,7 +502,7 @@ AutomationLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction)
void
AutomationLine::start_drag_multiple (list<ControlPoint*> cp, float fraction, XMLNode* state)
{
trackview.editor().session()->begin_reversible_command (_("automation range move"));
trackview.editor().begin_reversible_command (_("automation range move"));
trackview.editor().session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder(), state, 0));
@ -857,7 +857,7 @@ AutomationLine::is_first_point (ControlPoint& cp)
void
AutomationLine::remove_point (ControlPoint& cp)
{
trackview.editor().session()->begin_reversible_command (_("remove control point"));
trackview.editor().begin_reversible_command (_("remove control point"));
XMLNode &before = alist->get_state();
alist->erase (cp.model());
@ -865,7 +865,7 @@ AutomationLine::remove_point (ControlPoint& cp)
trackview.editor().session()->add_command(
new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
trackview.editor().session()->commit_reversible_command ();
trackview.editor().commit_reversible_command ();
trackview.editor().session()->set_dirty ();
}

View File

@ -182,15 +182,15 @@ AutomationRegionView::add_automation_event (GdkEvent *, framepos_t when, double
double when_d = when;
_line->view_to_model_coord (when_d, y);
view->session()->begin_reversible_command (_("add automation event"));
view->editor().begin_reversible_command (_("add automation event"));
XMLNode& before = _line->the_list()->get_state();
_line->the_list()->add (when_d, y, with_guard_points, false);
XMLNode& after = _line->the_list()->get_state();
view->session()->commit_reversible_command (
new MementoCommand<ARDOUR::AutomationList> (_line->memento_command_binder(), &before, &after));
view->session()->add_command (new MementoCommand<ARDOUR::AutomationList> (_line->memento_command_binder(), &before, &after));
view->editor().commit_reversible_command ();
view->session()->set_dirty ();
}

View File

@ -434,7 +434,7 @@ AutomationTimeAxisView::clear_clicked ()
{
assert (_line || _view);
_session->begin_reversible_command (_("clear automation"));
_editor.begin_reversible_command (_("clear automation"));
if (_line) {
_line->clear ();
@ -442,7 +442,7 @@ AutomationTimeAxisView::clear_clicked ()
_view->clear ();
}
_session->commit_reversible_command ();
_editor.commit_reversible_command ();
_session->set_dirty ();
}
@ -627,13 +627,14 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when,
_editor.snap_to_with_modifier (when, event);
_session->begin_reversible_command (_("add automation event"));
_editor.begin_reversible_command (_("add automation event"));
XMLNode& before = list->get_state();
list->add (when, y, with_guard_points);
XMLNode& after = list->get_state();
_session->commit_reversible_command (new MementoCommand<ARDOUR::AutomationList> (*list, &before, &after));
_session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list, &before, &after));
_editor.commit_reversible_command ();
_session->set_dirty ();
}

View File

@ -780,7 +780,7 @@ CrossfadeEditor::apply_preset (Preset *preset)
void
CrossfadeEditor::apply ()
{
_session->begin_reversible_command (_("Edit crossfade"));
the_editor().begin_reversible_command (_("Edit crossfade"));
XMLNode& before = xfade->get_state ();
@ -793,7 +793,7 @@ CrossfadeEditor::apply ()
)
);
_session->commit_reversible_command ();
the_editor().commit_reversible_command ();
}
void

View File

@ -305,6 +305,8 @@ Editor::Editor ()
selection = new Selection (this);
cut_buffer = new Selection (this);
_selection_memento = new SelectionMemento ();
before.clear();
clicked_regionview = 0;
clicked_axisview = 0;
@ -1392,6 +1394,7 @@ Editor::set_session (Session *t)
/* register for undo history */
_session->register_with_memento_command_factory(id(), this);
_session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
@ -3317,6 +3320,7 @@ void
Editor::begin_reversible_command (string name)
{
if (_session) {
before.push_back (&_selection_memento->get_state ());
_session->begin_reversible_command (name);
}
}
@ -3325,6 +3329,7 @@ void
Editor::begin_reversible_command (GQuark q)
{
if (_session) {
before.push_back (&_selection_memento->get_state ());
_session->begin_reversible_command (q);
}
}
@ -3333,6 +3338,14 @@ void
Editor::commit_reversible_command ()
{
if (_session) {
if (before.size() == 1) {
_session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
}
if (!before.empty()) {
before.pop_back();
}
_session->commit_reversible_command ();
}
}
@ -4182,7 +4195,7 @@ Editor::copy_playlists (TimeAxisView* v)
void
Editor::clear_playlists (TimeAxisView* v)
{
begin_reversible_command (_("clear playlists"));
begin_reversible_command (_("clear playlists"));
vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
_session->playlists->get (playlists);
mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
@ -4220,6 +4233,12 @@ Editor::on_key_release_event (GdkEventKey* ev)
// return key_press_focus_accelerator_handler (*this, ev);
}
double
Editor::get_y_origin () const
{
return vertical_adjustment.get_value ();
}
/** Queue up a change to the viewport x origin.
* @param frame New x origin.
*/
@ -4629,8 +4648,7 @@ Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
_session->set_auto_punch_location (loc);
XMLNode &after = _session->locations()->get_state();
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
}
else {
} else {
XMLNode &before = tpl->get_state();
tpl->set_hidden (false, this);
tpl->set (start, end);
@ -4807,6 +4825,35 @@ Editor::get_regions_from_selection_and_entered ()
return regions;
}
void
Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) const
{
for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
RouteTimeAxisView* tatv;
if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
boost::shared_ptr<Playlist> pl;
std::vector<boost::shared_ptr<Region> > results;
boost::shared_ptr<Track> tr;
if ((tr = tatv->track()) == 0) {
/* bus */
continue;
}
if ((pl = (tr->playlist())) != 0) {
boost::shared_ptr<Region> r = pl->region_by_id (id);
if (r) {
RegionView* marv = tatv->view()->find_view (r);
if (marv) {
regions.push_back (marv);
}
}
}
}
}
}
void
Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
{
@ -4966,8 +5013,15 @@ Editor::located ()
}
void
Editor::region_view_added (RegionView *)
Editor::region_view_added (RegionView * rv)
{
for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
if (rv->region ()->id () == (*pr)) {
selection->add (rv);
selection->regions.pending.erase (pr);
break;
}
}
_summary->set_background_dirty ();
}

View File

@ -58,6 +58,7 @@
#include "enums.h"
#include "editor_items.h"
#include "region_selection.h"
#include "selection_memento.h"
namespace Gtkmm2ext {
class TearOff;
@ -149,7 +150,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
double visible_canvas_height () const {
return _visible_canvas_height;
}
double trackviews_height() const;
double trackviews_height () const;
void cycle_snap_mode ();
void next_snap_choice ();
@ -372,6 +373,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void update_tearoff_visibility();
void reattach_all_tearoffs ();
double get_y_origin () const;
void reset_x_origin (framepos_t);
void reset_x_origin_to_follow_playhead ();
void reset_y_origin (double);
@ -405,6 +407,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void get_regions_corresponding_to (boost::shared_ptr<ARDOUR::Region> region, std::vector<RegionView*>& regions, bool src_comparison);
void get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) const;
void center_screen (framepos_t);
TrackViewList axis_views_from_routes (boost::shared_ptr<ARDOUR::RouteList>) const;
@ -1716,6 +1720,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
Selection* selection;
Selection* cut_buffer;
SelectionMemento* _selection_memento;
void time_selection_changed ();
void update_time_selection_display ();
@ -1875,7 +1880,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void write_selection ();
XMLNode *before; /* used in *_reversible_command */
std::list<XMLNode *> before; /* used in *_reversible_command */
void update_title ();
void update_title_s (const std::string & snapshot_name);

View File

@ -840,6 +840,12 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move)
{
if (_copy && first_move) {
if (_x_constrained) {
_editor->begin_reversible_command (Operations::fixed_time_region_copy);
} else {
_editor->begin_reversible_command (Operations::region_copy);
}
/* duplicate the regionview(s) and region(s) */
list<DraggingView> new_regionviews;
@ -890,6 +896,14 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move)
swap_grab (new_regionviews.front().view->get_canvas_group (), 0, event ? event->motion.time : 0);
}
} else if (!_copy && first_move) {
if (_x_constrained) {
_editor->begin_reversible_command (_("fixed time region drag"));
} else {
_editor->begin_reversible_command (Operations::region_drag);
}
}
RegionMotionDrag::motion (event, first_move);
@ -1020,12 +1034,6 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed
return;
}
if (_x_constrained) {
_editor->begin_reversible_command (Operations::fixed_time_region_copy);
} else {
_editor->begin_reversible_command (Operations::region_copy);
}
/* insert the regions into their new playlists */
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end();) {
@ -1102,12 +1110,6 @@ RegionMoveDrag::finished_no_copy (
return;
}
if (_x_constrained) {
_editor->begin_reversible_command (_("fixed time region drag"));
} else {
_editor->begin_reversible_command (Operations::region_drag);
}
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ) {
RegionView* rv = i->view;
@ -3632,7 +3634,7 @@ ControlPointDrag::finished (GdkEvent* event, bool movement_occurred)
}
_point->line().end_drag (_pushing, _final_index);
_editor->session()->commit_reversible_command ();
_editor->commit_reversible_command ();
}
void
@ -3746,7 +3748,7 @@ LineDrag::finished (GdkEvent* event, bool movement_occured)
}
}
_editor->session()->commit_reversible_command ();
_editor->commit_reversible_command ();
}
void
@ -5043,7 +5045,7 @@ AutomationRangeDrag::finished (GdkEvent* event, bool)
i->line->end_drag (false, 0);
}
_editor->session()->commit_reversible_command ();
_editor->commit_reversible_command ();
}
void
@ -5189,9 +5191,11 @@ EditorRubberbandSelectDrag::select_things (int button_state, framepos_t x1, fram
}
Selection::Operation op = ArdourKeyboard::selection_type (button_state);
_editor->begin_reversible_command (_("rubberband selection"));
_editor->select_all_within (x1, x2 - 1, y1, y2, _editor->track_views, op, false);
_editor->commit_reversible_command ();
}

View File

@ -28,7 +28,7 @@ using namespace Gtk;
EditorLocations::EditorLocations (Editor* e)
: EditorComponent (e)
{
_locations = new LocationUI;
_locations = new LocationUI ();
_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER);
_scroller.add (*_locations);
}

View File

@ -654,12 +654,12 @@ Editor::mouse_add_new_marker (framepos_t where, bool is_cd, bool is_xrun)
return;
}
Location *location = new Location (*_session, where, where, markername, (Location::Flags) flags);
_session->begin_reversible_command (_("add marker"));
begin_reversible_command (_("add marker"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->add (location, true);
XMLNode &after = _session->locations()->get_state();
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
/* find the marker we just added */
@ -668,6 +668,8 @@ Editor::mouse_add_new_marker (framepos_t where, bool is_cd, bool is_xrun)
/* make it the selected marker */
selection->set (lam->start);
}
commit_reversible_command ();
}
}
@ -721,12 +723,12 @@ Editor::remove_marker (ArdourCanvas::Item& item, GdkEvent*)
gint
Editor::really_remove_marker (Location* loc)
{
_session->begin_reversible_command (_("remove marker"));
begin_reversible_command (_("remove marker"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->remove (loc);
XMLNode &after = _session->locations()->get_state();
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
commit_reversible_command ();
return FALSE;
}

View File

@ -2344,8 +2344,6 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event)
clicked_routeview->playlist()->add_region (region, selection->time[clicked_selection].start);
_session->add_command(new StatefulDiffCommand (playlist));
commit_reversible_command ();
c.disconnect ();
if (latest_regionviews.empty()) {
@ -2356,8 +2354,11 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event)
/* we need to deselect all other regionviews, and select this one
i'm ignoring undo stuff, because the region creation will take care of it
*/
selection->set (latest_regionviews);
commit_reversible_command ();
_drags->set (new RegionMoveDrag (this, latest_regionviews.front()->get_canvas_group(), latest_regionviews.front(), latest_regionviews, false, false), event);
}

View File

@ -219,14 +219,14 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions)
a = tmp;
}
latest_regionviews.clear ();
vector<sigc::connection> region_added_connections;
for (list<RouteTimeAxisView*>::iterator i = used_trackviews.begin(); i != used_trackviews.end(); ++i) {
region_added_connections.push_back ((*i)->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view)));
}
latest_regionviews.clear ();
while (used_playlists.size() > 0) {
list <boost::shared_ptr<Playlist > >::iterator i = used_playlists.begin();
(*i)->thaw();
@ -236,8 +236,6 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions)
for (vector<sigc::connection>::iterator c = region_added_connections.begin(); c != region_added_connections.end(); ++c) {
(*c).disconnect ();
}
commit_reversible_command ();
if (frozen){
EditorThaw(); /* Emit Signal */
@ -251,7 +249,15 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions)
selection->add (latest_regionviews); //these are the new regions created after the split
}
_ignore_follow_edits = false;
} else {
_ignore_follow_edits = true;
if( working_on_selection ) {
selection->add (latest_regionviews); //these are the new regions created after the split
}
_ignore_follow_edits = false;
}
commit_reversible_command ();
}
/** Move one extreme of the current range selection. If more than one range is selected,
@ -1928,12 +1934,14 @@ Editor::add_location_from_selection ()
_session->locations()->next_available_name(rangename,"selection");
Location *location = new Location (*_session, start, end, rangename, Location::IsRangeMarker);
_session->begin_reversible_command (_("add marker"));
begin_reversible_command (_("add marker"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->add (location, true);
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -1948,12 +1956,14 @@ Editor::add_location_mark (framepos_t where)
return;
}
Location *location = new Location (*_session, where, where, markername, Location::IsMark);
_session->begin_reversible_command (_("add marker"));
begin_reversible_command (_("add marker"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->add (location, true);
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -1968,7 +1978,8 @@ Editor::remove_location_at_playhead_cursor ()
if (_session) {
//set up for undo
_session->begin_reversible_command (_("remove marker"));
begin_reversible_command (_("remove marker"));
XMLNode &before = _session->locations()->get_state();
bool removed = false;
@ -1986,7 +1997,8 @@ Editor::remove_location_at_playhead_cursor ()
if (removed) {
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
commit_reversible_command ();
}
}
}
@ -2001,7 +2013,8 @@ Editor::add_locations_from_region ()
return;
}
_session->begin_reversible_command (selection->regions.size () > 1 ? _("add markers") : _("add marker"));
begin_reversible_command (selection->regions.size () > 1 ? _("add markers") : _("add marker"));
XMLNode &before = _session->locations()->get_state();
for (RegionSelection::iterator i = rs.begin (); i != rs.end (); ++i) {
@ -2015,7 +2028,8 @@ Editor::add_locations_from_region ()
XMLNode &after = _session->locations()->get_state();
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
commit_reversible_command ();
}
/** Add a single range marker around all selected regions */
@ -2028,7 +2042,8 @@ Editor::add_location_from_region ()
return;
}
_session->begin_reversible_command (_("add marker"));
begin_reversible_command (_("add marker"));
XMLNode &before = _session->locations()->get_state();
string markername;
@ -2051,7 +2066,8 @@ Editor::add_location_from_region ()
XMLNode &after = _session->locations()->get_state();
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
commit_reversible_command ();
}
/* MARKS */
@ -2107,12 +2123,14 @@ void
Editor::clear_markers ()
{
if (_session) {
_session->begin_reversible_command (_("clear markers"));
begin_reversible_command (_("clear markers"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->clear_markers ();
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
commit_reversible_command ();
}
}
@ -2120,27 +2138,30 @@ void
Editor::clear_ranges ()
{
if (_session) {
_session->begin_reversible_command (_("clear ranges"));
begin_reversible_command (_("clear ranges"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->clear_ranges ();
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
commit_reversible_command ();
}
}
void
Editor::clear_locations ()
{
_session->begin_reversible_command (_("clear locations"));
begin_reversible_command (_("clear locations"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->clear ();
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
_session->locations()->clear ();
commit_reversible_command ();
}
void
@ -4537,11 +4558,11 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times)
foo.insert (foo.end(), latest_regionviews.begin(), latest_regionviews.end());
}
commit_reversible_command ();
if (!foo.empty()) {
selection->set (foo);
}
commit_reversible_command ();
}
void
@ -5168,8 +5189,8 @@ Editor::reset_region_gain_envelopes ()
return;
}
_session->begin_reversible_command (_("reset region gain"));
begin_reversible_command (_("reset region gain"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
@ -5180,8 +5201,8 @@ Editor::reset_region_gain_envelopes ()
_session->add_command (new MementoCommand<AutomationList>(*arv->audio_region()->envelope().get(), &before, &alist->get_state()));
}
}
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -5221,8 +5242,8 @@ Editor::toggle_gain_envelope_active ()
return;
}
_session->begin_reversible_command (_("region gain envelope active"));
begin_reversible_command (_("region gain envelope active"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
@ -5231,8 +5252,8 @@ Editor::toggle_gain_envelope_active ()
_session->add_command (new StatefulDiffCommand (arv->region()));
}
}
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -5248,15 +5269,15 @@ Editor::toggle_region_lock ()
return;
}
_session->begin_reversible_command (_("toggle region lock"));
begin_reversible_command (_("toggle region lock"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
(*i)->region()->clear_changes ();
(*i)->region()->set_locked (!(*i)->region()->locked());
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -5272,15 +5293,15 @@ Editor::toggle_region_video_lock ()
return;
}
_session->begin_reversible_command (_("Toggle Video Lock"));
begin_reversible_command (_("Toggle Video Lock"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
(*i)->region()->clear_changes ();
(*i)->region()->set_video_locked (!(*i)->region()->video_locked());
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -5296,16 +5317,16 @@ Editor::toggle_region_lock_style ()
return;
}
_session->begin_reversible_command (_("region lock style"));
begin_reversible_command (_("region lock style"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
(*i)->region()->clear_changes ();
PositionLockStyle const ns = (*i)->region()->position_lock_style() == AudioTime ? MusicTime : AudioTime;
(*i)->region()->set_position_lock_style (ns);
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -5321,15 +5342,15 @@ Editor::toggle_opaque_region ()
return;
}
_session->begin_reversible_command (_("change region opacity"));
begin_reversible_command (_("change region opacity"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
(*i)->region()->clear_changes ();
(*i)->region()->set_opaque (!(*i)->region()->opaque());
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -6137,8 +6158,8 @@ Editor::split_region_at_transients ()
return;
}
_session->begin_reversible_command (_("split regions"));
begin_reversible_command (_("split regions"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ) {
RegionSelection::iterator tmp;
@ -6155,8 +6176,8 @@ Editor::split_region_at_transients ()
i = tmp;
}
_session->commit_reversible_command ();
commit_reversible_command ();
}
@ -6344,14 +6365,14 @@ Editor::place_transient()
framepos_t where = get_preferred_edit_position();
_session->begin_reversible_command (_("place transient"));
begin_reversible_command (_("place transient"));
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
framepos_t position = (*r)->region()->position();
(*r)->region()->add_transient(where - position);
}
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -6379,8 +6400,8 @@ Editor::snap_regions_to_grid ()
return;
}
_session->begin_reversible_command (_("snap regions to grid"));
begin_reversible_command (_("snap regions to grid"));
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
boost::shared_ptr<Playlist> pl = (*r)->region()->playlist();
@ -6403,8 +6424,8 @@ Editor::snap_regions_to_grid ()
(*i)->thaw();
used_playlists.pop_front();
}
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -6462,8 +6483,8 @@ Editor::close_region_gaps ()
/* Iterate over the region list and make adjacent regions overlap by crossfade_len_ms */
_session->begin_reversible_command (_("close region gaps"));
begin_reversible_command (_("close region gaps"));
int idx = 0;
boost::shared_ptr<Region> last_region;
@ -6502,8 +6523,8 @@ Editor::close_region_gaps ()
(*i)->thaw();
used_playlists.pop_front();
}
_session->commit_reversible_command ();
commit_reversible_command ();
}
void
@ -7111,7 +7132,7 @@ Editor::toggle_region_mute ()
(*i)->region()->playlist()->clear_changes ();
(*i)->region()->set_muted (!(*i)->region()->muted ());
_session->add_command (new StatefulDiffCommand ((*i)->region()->playlist()));
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}

View File

@ -33,6 +33,7 @@
#include "location_ui.h"
#include "prompter.h"
#include "utils.h"
#include "public_editor.h"
#include "i18n.h"
@ -853,12 +854,12 @@ LocationUI::do_location_remove (ARDOUR::Location *loc)
return FALSE;
}
_session->begin_reversible_command (_("remove marker"));
PublicEditor::instance().begin_reversible_command (_("remove marker"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->remove (loc);
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
PublicEditor::instance().commit_reversible_command ();
return FALSE;
}
@ -1017,12 +1018,12 @@ LocationUI::add_new_location()
if (Config->get_name_new_markers()) {
newest_location = location;
}
_session->begin_reversible_command (_("add marker"));
PublicEditor::instance().begin_reversible_command (_("add marker"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->add (location, true);
XMLNode &after = _session->locations()->get_state();
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
PublicEditor::instance().commit_reversible_command ();
}
}
@ -1036,12 +1037,12 @@ LocationUI::add_new_range()
framepos_t where = _session->audible_frame();
_session->locations()->next_available_name(rangename,"unnamed");
Location *location = new Location (*_session, where, where, rangename, Location::IsRangeMarker);
_session->begin_reversible_command (_("add range marker"));
PublicEditor::instance().begin_reversible_command (_("add range marker"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->add (location, true);
XMLNode &after = _session->locations()->get_state();
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
_session->commit_reversible_command ();
PublicEditor::instance().commit_reversible_command ();
}
}

View File

@ -3350,7 +3350,7 @@ MidiRegionView::selection_as_cut_buffer () const
bool
MidiRegionView::paste (framepos_t pos, const ::Selection& selection, PasteContext& ctx)
{
trackview.session()->begin_reversible_command (Operations::paste);
trackview.editor().begin_reversible_command (Operations::paste);
// Paste notes, if available
MidiNoteSelection::const_iterator m = selection.midi_notes.get_nth(ctx.counts.n_notes());
@ -3366,7 +3366,7 @@ MidiRegionView::paste (framepos_t pos, const ::Selection& selection, PasteContex
a->second->paste(pos, selection, ctx);
}
trackview.session()->commit_reversible_command ();
trackview.editor().commit_reversible_command ();
return true;
}

View File

@ -245,6 +245,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
virtual void set_zoom_focus (Editing::ZoomFocus) = 0;
virtual Editing::ZoomFocus get_zoom_focus () const = 0;
virtual framecnt_t get_current_zoom () const = 0;
virtual void reset_zoom (framecnt_t) = 0;
virtual PlaylistSelector& playlist_selector() const = 0;
virtual void clear_playlist (boost::shared_ptr<ARDOUR::Playlist>) = 0;
virtual void new_playlists (TimeAxisView*) = 0;
@ -288,6 +289,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
virtual void prepare_for_cleanup () = 0;
virtual void finish_cleanup () = 0;
virtual void reset_x_origin (framepos_t frame) = 0;
virtual double get_y_origin () const = 0;
virtual void reset_y_origin (double pos) = 0;
virtual void remove_last_capture () = 0;
virtual void maximise_editing_space () = 0;
virtual void restore_editing_space () = 0;
@ -403,6 +406,10 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
virtual void stop_canvas_autoscroll () = 0;
virtual bool autoscroll_active() const = 0;
virtual void begin_reversible_command (std::string cmd_name) = 0;
virtual void begin_reversible_command (GQuark) = 0;
virtual void commit_reversible_command () = 0;
virtual MouseCursors const * cursors () const = 0;
virtual VerboseCursor * verbose_cursor () const = 0;
@ -420,6 +427,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
virtual void get_regions_at (RegionSelection &, framepos_t where, TrackViewList const &) const = 0;
virtual RegionSelection get_regions_from_selection_and_mouse (framepos_t) = 0;
virtual void get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) const = 0;
/// Singleton instance, set up by Editor::Editor()

View File

@ -33,6 +33,7 @@
#include "main_clock.h"
#include "gui_thread.h"
#include "region_editor.h"
#include "public_editor.h"
#include "i18n.h"
@ -269,7 +270,7 @@ RegionEditor::connect_editor_events ()
void
RegionEditor::position_clock_changed ()
{
_session->begin_reversible_command (_("change region start position"));
PublicEditor::instance().begin_reversible_command (_("change region start position"));
boost::shared_ptr<Playlist> pl = _region->playlist();
@ -279,13 +280,13 @@ RegionEditor::position_clock_changed ()
_session->add_command(new StatefulDiffCommand (_region));
}
_session->commit_reversible_command ();
PublicEditor::instance().commit_reversible_command ();
}
void
RegionEditor::end_clock_changed ()
{
_session->begin_reversible_command (_("change region end position"));
PublicEditor::instance().begin_reversible_command (_("change region end position"));
boost::shared_ptr<Playlist> pl = _region->playlist();
@ -295,7 +296,7 @@ RegionEditor::end_clock_changed ()
_session->add_command(new StatefulDiffCommand (_region));
}
_session->commit_reversible_command ();
PublicEditor::instance().commit_reversible_command ();
end_clock.set (_region->position() + _region->length() - 1, true);
}
@ -305,7 +306,7 @@ RegionEditor::length_clock_changed ()
{
framecnt_t frames = length_clock.current_time();
_session->begin_reversible_command (_("change region length"));
PublicEditor::instance().begin_reversible_command (_("change region length"));
boost::shared_ptr<Playlist> pl = _region->playlist();
@ -315,7 +316,7 @@ RegionEditor::length_clock_changed ()
_session->add_command(new StatefulDiffCommand (_region));
}
_session->commit_reversible_command ();
PublicEditor::instance().commit_reversible_command ();
length_clock.set (_region->length());
}
@ -399,25 +400,25 @@ RegionEditor::audition_state_changed (bool yn)
void
RegionEditor::sync_offset_absolute_clock_changed ()
{
_session->begin_reversible_command (_("change region sync point"));
PublicEditor::instance().begin_reversible_command (_("change region sync point"));
_region->clear_changes ();
_region->set_sync_position (sync_offset_absolute_clock.current_time());
_session->add_command (new StatefulDiffCommand (_region));
_session->commit_reversible_command ();
PublicEditor::instance().commit_reversible_command ();
}
void
RegionEditor::sync_offset_relative_clock_changed ()
{
_session->begin_reversible_command (_("change region sync point"));
PublicEditor::instance().begin_reversible_command (_("change region sync point"));
_region->clear_changes ();
_region->set_sync_position (sync_offset_relative_clock.current_time() + _region->position ());
_session->add_command (new StatefulDiffCommand (_region));
_session->commit_reversible_command ();
PublicEditor::instance().commit_reversible_command ();
}
bool

View File

@ -69,7 +69,7 @@ AudioRegionGainLine::start_drag_single (ControlPoint* cp, double x, float fracti
void
AudioRegionGainLine::remove_point (ControlPoint& cp)
{
trackview.editor().session()->begin_reversible_command (_("remove control point"));
trackview.editor().begin_reversible_command (_("remove control point"));
XMLNode &before = alist->get_state();
if (!rv.audio_region()->envelope_active()) {
@ -81,7 +81,7 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
alist->erase (cp.model());
trackview.editor().session()->add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
trackview.editor().session()->commit_reversible_command ();
trackview.editor().commit_reversible_command ();
trackview.editor().session()->set_dirty ();
}

View File

@ -73,6 +73,7 @@ void
RegionSelection::clear_all()
{
clear();
pending.clear ();
_bylayer.clear();
}

View File

@ -62,6 +62,7 @@ class RegionSelection : public std::list<RegionView*>
void by_track (std::list<RegionView*>&) const;
std::set<boost::shared_ptr<ARDOUR::Playlist> > playlists () const;
std::list<PBD::ID> pending;
private:
void remove_it (RegionView*);

View File

@ -352,7 +352,7 @@ RhythmFerret::do_split_action ()
editor.EditorFreeze(); /* Emit signal */
_session->begin_reversible_command (_("split regions (rhythm ferret)"));
editor.begin_reversible_command (_("split regions (rhythm ferret)"));
/* Merge the transient positions for regions in consideration */
AnalysisFeatureList merged_features;
@ -381,7 +381,7 @@ RhythmFerret::do_split_action ()
i = tmp;
}
_session->commit_reversible_command ();
editor.commit_reversible_command ();
editor.EditorThaw(); /* Emit signal */
}

View File

@ -1206,6 +1206,7 @@ Selection::get_state () const
so that re-opening plugin windows for editor mixer strips works
*/
char buf[32];
XMLNode* node = new XMLNode (X_("Selection"));
for (TrackSelection::const_iterator i = tracks.begin(); i != tracks.end(); ++i) {
@ -1221,9 +1222,23 @@ Selection::get_state () const
}
}
for (RegionSelection::const_iterator i = regions.begin(); i != regions.end(); ++i) {
XMLNode* r = node->add_child (X_("Region"));
r->add_property (X_("id"), atoi ((*i)->region ()->id ().to_s ().c_str()));
}
for (TimeSelection::const_iterator i = time.begin(); i != time.end(); ++i) {
XMLNode* t = node->add_child (X_("AudioRange"));
snprintf(buf, sizeof(buf), "%ld", (*i).start);
t->add_property (X_("start"), string(buf));
snprintf(buf, sizeof(buf), "%ld", (*i).end);
t->add_property (X_("end"), string(buf));
}
for (MarkerSelection::const_iterator i = markers.begin(); i != markers.end(); ++i) {
XMLNode* t = node->add_child (X_("Marker"));
bool is_start;
Location* loc = editor->find_location_from_marker (*i, is_start);
@ -1241,6 +1256,11 @@ Selection::set_state (XMLNode const & node, int)
return -1;
}
clear_regions ();
clear_time ();
clear_tracks ();
clear_markers ();
XMLNodeList children = node.children ();
for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
if ((*i)->name() == X_("RouteView")) {
@ -1253,6 +1273,36 @@ Selection::set_state (XMLNode const & node, int)
add (rtv);
}
} else if ((*i)->name() == X_("Region")) {
XMLProperty* prop_id = (*i)->property (X_("id"));
assert (prop_id);
PBD::ID id (prop_id->value ());
RegionSelection rs;
editor->get_regionviews_by_id (id, rs);
if (!rs.empty ()) {
add (rs);
} else {
/*
regionviews are being constructed - stash the region IDs
so we can identify them in Editor::region_view_added ()
*/
regions.pending.push_back (id);
}
} else if ((*i)->name() == X_("AudioRange")) {
XMLProperty* prop_start = (*i)->property (X_("start"));
XMLProperty* prop_end = (*i)->property (X_("end"));
assert (prop_start);
assert (prop_end);
framepos_t s (atol (prop_start->value ().c_str()));
framepos_t e (atol (prop_end->value ().c_str()));
set_preserving_all_ranges (s, e);
} else if ((*i)->name() == X_("AutomationView")) {
XMLProperty* prop_id = (*i)->property (X_("id"));

View File

@ -0,0 +1,95 @@
/*
Copyright (C) 2014 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "selection_memento.h"
#include "editing.h"
#include "public_editor.h"
#include "i18n.h"
SelectionMemento::SelectionMemento ()
{
}
SelectionMemento::~SelectionMemento ()
{
}
XMLNode&
SelectionMemento::get_state () {
XMLNode* node = new XMLNode ("SelectionMemento");
char buf[32];
PublicEditor& editor = PublicEditor::instance();
node->add_property ("mouse-mode", enum2str(editor.current_mouse_mode()));
snprintf (buf, sizeof(buf), "%" PRId64, editor.get_current_zoom());
node->add_property ("zoom", buf);
snprintf (buf, sizeof (buf), "%" PRIi64, editor.leftmost_sample());
node->add_property ("left-frame", buf);
snprintf (buf, sizeof (buf), "%f", editor.get_y_origin());
node->add_property ("y-origin", buf);
node->add_child_nocopy (editor.get_selection().get_state());
return *node;
}
int
SelectionMemento::set_state (const XMLNode& node, int /*version*/) {
const XMLProperty* prop;
PublicEditor& editor = PublicEditor::instance();
if (node.name() != X_("SelectionMemento")) {
return -1;
}
if ((prop = node.property ("mouse-mode"))) {
Editing::MouseMode m = Editing::str2mousemode(prop->value());
editor.set_mouse_mode (m, true);
} else {
editor.set_mouse_mode (Editing::MouseObject, true);
}
if ((prop = node.property ("zoom"))) {
/* older versions of ardour used floating point samples_per_pixel */
double f = PBD::atof (prop->value());
editor.reset_zoom (llrintf (f));
}
if ((prop = node.property ("left-frame")) != 0) {
framepos_t pos;
if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
if (pos < 0) {
pos = 0;
}
editor.reset_x_origin (pos);
}
}
if ((prop = node.property ("y-origin")) != 0) {
editor.reset_y_origin (atof (prop->value ().c_str()));
}
XMLNodeList children = node.children ();
for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
editor.get_selection().set_state (**i, Stateful::current_state_version);
}
return 0;
}

View File

@ -0,0 +1,34 @@
/*
Copyright (C) 2014 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ardour_gtk_selection_memento_h__
#define __ardour_gtk_selection_memento_h__
#include "pbd/statefuldestructible.h"
class SelectionMemento : public PBD::StatefulDestructible
{
public:
SelectionMemento ();
~SelectionMemento ();
XMLNode& get_state ();
int set_state (const XMLNode&, int version);
};
#endif /* __ardour_gtk_selection_memento_h__ */

View File

@ -201,6 +201,7 @@ gtk2_ardour_sources = [
'ruler_dialog.cc',
'search_path_option.cc',
'selection.cc',
'selection_memento.cc',
'send_ui.cc',
'session_dialog.cc',
'session_import_dialog.cc',