Fix AutomationTrackItem rubberband click thinking it was unhandled.
Fix several other cases where a single mouse click could cause several (not nested) selection ops. Fix missing selection memento for midi notes and midi commands. Rename some variables. Fix random style issues.
This commit is contained in:
parent
9e873acedb
commit
44203ce955
@ -156,7 +156,7 @@ void
|
||||
AutomationLine::update_visibility ()
|
||||
{
|
||||
if (_visible & Line) {
|
||||
/* Only show the line there are some points, otherwise we may show an out-of-date line
|
||||
/* Only show the line when there are some points, otherwise we may show an out-of-date line
|
||||
when automation points have been removed (the line will still follow the shape of the
|
||||
old points).
|
||||
*/
|
||||
|
@ -80,7 +80,6 @@
|
||||
|
||||
#include "control_protocol/control_protocol.h"
|
||||
|
||||
#include "actions.h"
|
||||
#include "actions.h"
|
||||
#include "analysis_window.h"
|
||||
#include "audio_clock.h"
|
||||
@ -251,6 +250,7 @@ pane_size_watcher (Paned* pane)
|
||||
Editor::Editor ()
|
||||
: _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
|
||||
|
||||
, _mouse_changed_selection (false)
|
||||
/* time display buttons */
|
||||
, minsec_label (_("Mins:Secs"))
|
||||
, bbt_label (_("Bars:Beats"))
|
||||
@ -3336,7 +3336,7 @@ void
|
||||
Editor::begin_reversible_selection_op (string name)
|
||||
{
|
||||
if (_session) {
|
||||
//cerr << name << endl;
|
||||
cerr << name << endl;
|
||||
/* begin/commit pairs can be nested */
|
||||
selection_op_cmd_depth++;
|
||||
}
|
||||
@ -3349,20 +3349,22 @@ Editor::commit_reversible_selection_op ()
|
||||
if (selection_op_cmd_depth == 1) {
|
||||
|
||||
if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
|
||||
/* the user has undone some selection ops and then made a new one */
|
||||
list<XMLNode *>::iterator it = selection_op_history.begin();
|
||||
advance (it, selection_op_history_it);
|
||||
selection_op_history.erase (selection_op_history.begin(), it);
|
||||
}
|
||||
|
||||
selection_op_history.push_front (&_selection_memento->get_state ());
|
||||
selection_op_history_it = 0;
|
||||
|
||||
selection_undo_action->set_sensitive (true);
|
||||
selection_redo_action->set_sensitive (false);
|
||||
}
|
||||
|
||||
if (selection_op_cmd_depth > 0) {
|
||||
selection_op_cmd_depth--;
|
||||
}
|
||||
|
||||
selection_undo_action->set_sensitive (true);
|
||||
selection_redo_action->set_sensitive (false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3378,7 +3380,6 @@ Editor::undo_selection_op ()
|
||||
selection_redo_action->set_sensitive (true);
|
||||
}
|
||||
++n;
|
||||
|
||||
}
|
||||
/* is there an earlier entry? */
|
||||
if ((selection_op_history_it + 1) >= selection_op_history.size()) {
|
||||
@ -3401,7 +3402,6 @@ Editor::redo_selection_op ()
|
||||
selection_undo_action->set_sensitive (true);
|
||||
}
|
||||
++n;
|
||||
|
||||
}
|
||||
|
||||
if (selection_op_history_it == 0) {
|
||||
@ -4899,17 +4899,17 @@ Editor::get_regions_from_selection_and_entered ()
|
||||
}
|
||||
|
||||
void
|
||||
Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) const
|
||||
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;
|
||||
RouteTimeAxisView* rtav;
|
||||
|
||||
if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
|
||||
if ((rtav = 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) {
|
||||
if ((tr = rtav->track()) == 0) {
|
||||
/* bus */
|
||||
continue;
|
||||
}
|
||||
@ -4917,9 +4917,9 @@ Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) co
|
||||
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);
|
||||
RegionView* rv = rtav->view()->find_view (r);
|
||||
if (rv) {
|
||||
regions.push_back (rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4927,6 +4927,21 @@ Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) co
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
|
||||
{
|
||||
|
||||
for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
MidiTimeAxisView* mtav;
|
||||
|
||||
if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
|
||||
|
||||
mtav->get_per_region_note_selection (selection);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
|
||||
{
|
||||
@ -5102,6 +5117,19 @@ Editor::region_view_added (RegionView * rv)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
|
||||
if (mrv) {
|
||||
list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
|
||||
for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
|
||||
if (rv->region()->id () == (*rnote).first) {
|
||||
mrv->select_notes ((*rnote).second);
|
||||
selection->pending_midi_note_selection.erase(rnote);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_summary->set_background_dirty ();
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,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 get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const;
|
||||
void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >&) const;
|
||||
|
||||
void center_screen (framepos_t);
|
||||
|
||||
@ -706,6 +707,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||
|
||||
void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type);
|
||||
bool button_release_can_deselect;
|
||||
bool _mouse_changed_selection;
|
||||
|
||||
void catch_vanishing_regionview (RegionView *);
|
||||
|
||||
|
@ -178,7 +178,9 @@ Editor::canvas_scroll_event (GdkEventScroll *event, bool from_canvas)
|
||||
bool
|
||||
Editor::track_canvas_button_press_event (GdkEventButton */*event*/)
|
||||
{
|
||||
begin_reversible_selection_op (_("Clear Selection Click (track canvas)"));
|
||||
selection->clear ();
|
||||
commit_reversible_selection_op();
|
||||
_track_canvas->grab_focus();
|
||||
return false;
|
||||
}
|
||||
@ -1105,8 +1107,10 @@ Editor::canvas_drop_zone_event (GdkEvent* event)
|
||||
switch (event->type) {
|
||||
case GDK_BUTTON_RELEASE:
|
||||
if (event->button.button == 1) {
|
||||
begin_reversible_selection_op (_("Nowhere Click"));
|
||||
selection->clear_objects ();
|
||||
selection->clear_tracks ();
|
||||
commit_reversible_selection_op ();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -4718,6 +4718,9 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
|
||||
} else {
|
||||
_region->unique_select (_primary);
|
||||
}
|
||||
|
||||
_editor->begin_reversible_selection_op(_("Select Note Press"));
|
||||
_editor->commit_reversible_selection_op();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4803,10 +4806,13 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
|
||||
if (_editor->current_mouse_mode() == Editing::MouseObject ||
|
||||
_editor->current_mouse_mode() == Editing::MouseDraw) {
|
||||
|
||||
bool changed = false;
|
||||
|
||||
if (_was_selected) {
|
||||
bool add = Keyboard::modifier_state_equals (ev->button.state, Keyboard::PrimaryModifier);
|
||||
if (add) {
|
||||
_region->note_deselected (_primary);
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
bool extend = Keyboard::modifier_state_equals (ev->button.state, Keyboard::TertiaryModifier);
|
||||
@ -4814,12 +4820,19 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
|
||||
|
||||
if (!extend && !add && _region->selection_size() > 1) {
|
||||
_region->unique_select (_primary);
|
||||
changed = true;
|
||||
} else if (extend) {
|
||||
_region->note_selected (_primary, true, true);
|
||||
changed = true;
|
||||
} else {
|
||||
/* it was added during button press */
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
_editor->begin_reversible_selection_op(_("Select Note Release"));
|
||||
_editor->commit_reversible_selection_op();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_region->note_dropped (_primary, total_dx(), total_dy());
|
||||
@ -5204,12 +5217,15 @@ EditorRubberbandSelectDrag::select_things (int button_state, framepos_t x1, fram
|
||||
void
|
||||
EditorRubberbandSelectDrag::deselect_things ()
|
||||
{
|
||||
if (!getenv("ARDOUR_SAE")) {
|
||||
_editor->begin_reversible_selection_op (_("Clear Selection (rubberband)"));
|
||||
|
||||
_editor->selection->clear_tracks();
|
||||
}
|
||||
_editor->selection->clear_regions();
|
||||
_editor->selection->clear_points ();
|
||||
_editor->selection->clear_lines ();
|
||||
_editor->selection->clear_midi_notes ();
|
||||
|
||||
_editor->commit_reversible_selection_op();
|
||||
}
|
||||
|
||||
NoteCreateDrag::NoteCreateDrag (Editor* e, ArdourCanvas::Item* i, MidiRegionView* rv)
|
||||
|
@ -448,11 +448,15 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||
Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
|
||||
bool press = (event->type == GDK_BUTTON_PRESS);
|
||||
|
||||
if (press) {
|
||||
_mouse_changed_selection = false;
|
||||
}
|
||||
|
||||
switch (item_type) {
|
||||
case RegionItem:
|
||||
if (press) {
|
||||
if (eff_mouse_mode != MouseRange) {
|
||||
set_selected_regionview_from_click (press, op);
|
||||
_mouse_changed_selection = set_selected_regionview_from_click (press, op);
|
||||
} else {
|
||||
/* don't change the selection unless the
|
||||
clicked track is not currently selected. if
|
||||
@ -465,7 +469,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||
}
|
||||
} else {
|
||||
if (eff_mouse_mode != MouseRange) {
|
||||
set_selected_regionview_from_click (press, op);
|
||||
_mouse_changed_selection = set_selected_regionview_from_click (press, op);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -483,7 +487,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||
case StartCrossFadeItem:
|
||||
case EndCrossFadeItem:
|
||||
if (get_smart_mode() || eff_mouse_mode != MouseRange) {
|
||||
set_selected_regionview_from_click (press, op);
|
||||
_mouse_changed_selection = set_selected_regionview_from_click (press, op);
|
||||
} else if (event->type == GDK_BUTTON_PRESS) {
|
||||
set_selected_track_as_side_effect (op);
|
||||
}
|
||||
@ -492,7 +496,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||
case ControlPointItem:
|
||||
set_selected_track_as_side_effect (op);
|
||||
if (eff_mouse_mode != MouseRange) {
|
||||
set_selected_control_point_from_click (press, op);
|
||||
_mouse_changed_selection = set_selected_control_point_from_click (press, op);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -501,6 +505,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||
if (event->button.button == 3) {
|
||||
selection->clear_tracks ();
|
||||
set_selected_track_as_side_effect (op);
|
||||
_mouse_changed_selection = true;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -511,6 +516,12 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((!press) && _mouse_changed_selection) {
|
||||
begin_reversible_selection_op (_("Button Selection"));
|
||||
commit_reversible_selection_op ();
|
||||
_mouse_changed_selection = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@ -744,6 +755,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
||||
case AutomationTrackItem:
|
||||
/* rubberband drag to select automation points */
|
||||
_drags->set (new EditorRubberbandSelectDrag (this, item), event);
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1465,10 +1477,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
||||
}
|
||||
|
||||
/* do any (de)selection operations that should occur on button release */
|
||||
|
||||
begin_reversible_selection_op (_("Button Select"));
|
||||
button_selection (item, event, item_type);
|
||||
commit_reversible_selection_op ();
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
@ -202,9 +202,10 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
|
||||
}
|
||||
} else if (group && group->is_active()) {
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
|
||||
if ((*i)->route_group() == group)
|
||||
if ((*i)->route_group() == group) {
|
||||
selection->remove(*i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
selection->remove (clicked_axisview);
|
||||
}
|
||||
@ -215,9 +216,10 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
|
||||
}
|
||||
} else if (group && group->is_active()) {
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
|
||||
if ( (*i)->route_group() == group)
|
||||
if ((*i)->route_group() == group) {
|
||||
selection->add(*i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
selection->add (clicked_axisview);
|
||||
}
|
||||
@ -234,9 +236,10 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
|
||||
}
|
||||
} else if (group && group->is_active()) {
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
|
||||
if ((*i)->route_group() == group)
|
||||
if ((*i)->route_group() == group) {
|
||||
selection->add(*i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
selection->add (clicked_axisview);
|
||||
}
|
||||
@ -253,9 +256,10 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
|
||||
}
|
||||
} else if (group && group->is_active()) {
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
|
||||
if ((*i)->route_group() == group)
|
||||
if ((*i)->route_group() == group) {
|
||||
selection->add(*i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
selection->set (clicked_axisview);
|
||||
}
|
||||
@ -1953,7 +1957,7 @@ Editor::get_edit_op_range (framepos_t& start, framepos_t& end) const
|
||||
void
|
||||
Editor::deselect_all ()
|
||||
{
|
||||
begin_reversible_selection_op(_("Clear Selection"));
|
||||
begin_reversible_selection_op(_("Deselect All"));
|
||||
selection->clear ();
|
||||
commit_reversible_selection_op ();
|
||||
}
|
||||
|
@ -123,6 +123,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
|
||||
, _last_event_y (0)
|
||||
, _grabbed_keyboard (false)
|
||||
, _entered (false)
|
||||
, _mouse_changed_selection (false)
|
||||
{
|
||||
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
|
||||
_note_group->raise_to_top();
|
||||
@ -169,6 +170,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
|
||||
, _last_event_y (0)
|
||||
, _grabbed_keyboard (false)
|
||||
, _entered (false)
|
||||
, _mouse_changed_selection (false)
|
||||
{
|
||||
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
|
||||
_note_group->raise_to_top();
|
||||
@ -220,6 +222,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other)
|
||||
, _last_event_y (0)
|
||||
, _grabbed_keyboard (false)
|
||||
, _entered (false)
|
||||
, _mouse_changed_selection (false)
|
||||
{
|
||||
init (false);
|
||||
}
|
||||
@ -250,6 +253,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M
|
||||
, _last_event_y (0)
|
||||
, _grabbed_keyboard (false)
|
||||
, _entered (false)
|
||||
, _mouse_changed_selection (false)
|
||||
{
|
||||
init (true);
|
||||
}
|
||||
@ -502,6 +506,7 @@ MidiRegionView::button_press (GdkEventButton* ev)
|
||||
}
|
||||
|
||||
_pressed_button = ev->button;
|
||||
_mouse_changed_selection = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -532,12 +537,14 @@ MidiRegionView::button_release (GdkEventButton* ev)
|
||||
case MouseRange:
|
||||
/* no motion occured - simple click */
|
||||
clear_selection ();
|
||||
_mouse_changed_selection = true;
|
||||
break;
|
||||
|
||||
case MouseContent:
|
||||
case MouseTimeFX:
|
||||
{
|
||||
clear_selection();
|
||||
_mouse_changed_selection = true;
|
||||
|
||||
if (Keyboard::is_insert_note_event(ev)) {
|
||||
|
||||
@ -591,6 +598,11 @@ MidiRegionView::button_release (GdkEventButton* ev)
|
||||
break;
|
||||
}
|
||||
|
||||
if(_mouse_changed_selection) {
|
||||
trackview.editor().begin_reversible_selection_op (_("Mouse Selection Change"));
|
||||
trackview.editor().commit_reversible_selection_op ();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -643,6 +655,7 @@ MidiRegionView::motion (GdkEventMotion* ev)
|
||||
editor.drags()->set (new MidiRubberbandSelectDrag (dynamic_cast<Editor *> (&editor), this), (GdkEvent *) ev);
|
||||
if (!Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
|
||||
clear_selection ();
|
||||
_mouse_changed_selection = true;
|
||||
}
|
||||
_mouse_state = SelectRectDragging;
|
||||
return true;
|
||||
@ -747,22 +760,32 @@ MidiRegionView::key_press (GdkEventKey* ev)
|
||||
|
||||
} else if (ev->keyval == GDK_Tab) {
|
||||
|
||||
trackview.editor().begin_reversible_selection_op (_("Select Adjacent Note"));
|
||||
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
||||
goto_previous_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
||||
} else {
|
||||
goto_next_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
||||
}
|
||||
|
||||
trackview.editor().commit_reversible_selection_op();
|
||||
|
||||
return true;
|
||||
|
||||
} else if (ev->keyval == GDK_ISO_Left_Tab) {
|
||||
|
||||
/* Shift-TAB generates ISO Left Tab, for some reason */
|
||||
|
||||
trackview.editor().begin_reversible_selection_op (_("Select Adjacent Note"));
|
||||
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
||||
goto_previous_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
||||
} else {
|
||||
goto_next_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
||||
}
|
||||
|
||||
trackview.editor().commit_reversible_selection_op();
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
@ -946,9 +969,11 @@ MidiRegionView::create_note_at (framepos_t t, double y, Evoral::Beats length, bo
|
||||
|
||||
view->update_note_range(new_note->note());
|
||||
|
||||
trackview.editor().begin_reversible_command(_("add note"));
|
||||
MidiModel::NoteDiffCommand* cmd = _model->new_note_diff_command(_("add note"));
|
||||
cmd->add (new_note);
|
||||
_model->apply_command(*trackview.session(), cmd);
|
||||
trackview.editor().commit_reversible_command();
|
||||
|
||||
play_midi_note (new_note);
|
||||
}
|
||||
@ -982,8 +1007,8 @@ MidiRegionView::display_model(boost::shared_ptr<MidiModel> model)
|
||||
|
||||
content_connection.disconnect ();
|
||||
_model->ContentsChanged.connect (content_connection, invalidator (*this), boost::bind (&MidiRegionView::redisplay_model, this), gui_context());
|
||||
|
||||
clear_events ();
|
||||
/* Don't signal as nobody else needs to know until selection has been altered.*/
|
||||
clear_events (false);
|
||||
|
||||
if (_enable_display) {
|
||||
redisplay_model();
|
||||
@ -994,6 +1019,7 @@ void
|
||||
MidiRegionView::start_note_diff_command (string name)
|
||||
{
|
||||
if (!_note_diff_command) {
|
||||
trackview.editor().begin_reversible_command (name);
|
||||
_note_diff_command = _model->new_note_diff_command (name);
|
||||
}
|
||||
}
|
||||
@ -1044,6 +1070,7 @@ void
|
||||
MidiRegionView::apply_diff (bool as_subcommand)
|
||||
{
|
||||
bool add_or_remove;
|
||||
bool commit = false;
|
||||
|
||||
if (!_note_diff_command) {
|
||||
return;
|
||||
@ -1060,6 +1087,7 @@ MidiRegionView::apply_diff (bool as_subcommand)
|
||||
_model->apply_command_as_subcommand (*trackview.session(), _note_diff_command);
|
||||
} else {
|
||||
_model->apply_command (*trackview.session(), _note_diff_command);
|
||||
commit = true;
|
||||
}
|
||||
|
||||
_note_diff_command = 0;
|
||||
@ -1070,6 +1098,9 @@ MidiRegionView::apply_diff (bool as_subcommand)
|
||||
}
|
||||
|
||||
_marked_for_velocity.clear();
|
||||
if (commit) {
|
||||
trackview.editor().commit_reversible_command ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1100,6 +1131,27 @@ MidiRegionView::find_canvas_note (boost::shared_ptr<NoteType> note)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** This version finds any canvas note matching the supplied note.*/
|
||||
NoteBase*
|
||||
MidiRegionView::find_canvas_note (NoteType note)
|
||||
{
|
||||
if (_optimization_iterator != _events.end()) {
|
||||
++_optimization_iterator;
|
||||
}
|
||||
|
||||
if (_optimization_iterator != _events.end() && (*(*_optimization_iterator)->note()) == note) {
|
||||
return *_optimization_iterator;
|
||||
}
|
||||
|
||||
for (_optimization_iterator = _events.begin(); _optimization_iterator != _events.end(); ++_optimization_iterator) {
|
||||
if (*((*_optimization_iterator)->note()) == note) {
|
||||
return *_optimization_iterator;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegionView::get_events (Events& e, Evoral::Sequence<Evoral::Beats>::NoteOperator op, uint8_t val, int chan_mask)
|
||||
{
|
||||
@ -1173,6 +1225,13 @@ MidiRegionView::redisplay_model()
|
||||
add_note (note, visible);
|
||||
}
|
||||
|
||||
set<boost::shared_ptr<NoteType> >::iterator it;
|
||||
for (it = _pending_note_selection.begin(); it != _pending_note_selection.end(); ++it) {
|
||||
if (*(*it) == *note) {
|
||||
add_to_selection (cne);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) {
|
||||
@ -1182,7 +1241,6 @@ MidiRegionView::redisplay_model()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* remove note items that are no longer valid */
|
||||
|
||||
if (!empty_when_starting) {
|
||||
@ -1213,6 +1271,7 @@ MidiRegionView::redisplay_model()
|
||||
|
||||
_marked_for_selection.clear ();
|
||||
_marked_for_velocity.clear ();
|
||||
_pending_note_selection.clear ();
|
||||
|
||||
/* we may have caused _events to contain things out of order (e.g. if a note
|
||||
moved earlier or later). we don't generally need them in time order, but
|
||||
@ -1909,7 +1968,9 @@ MidiRegionView::get_patch_key_at (Evoral::Beats time, uint8_t channel, MIDI::Nam
|
||||
void
|
||||
MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPrimaryKey& new_patch)
|
||||
{
|
||||
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("alter patch change"));
|
||||
string name = _("alter patch change");
|
||||
trackview.editor().begin_reversible_command (name);
|
||||
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name);
|
||||
|
||||
if (pc.patch()->program() != new_patch.program()) {
|
||||
c->change_program (pc.patch (), new_patch.program());
|
||||
@ -1921,6 +1982,7 @@ MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPri
|
||||
}
|
||||
|
||||
_model->apply_command (*trackview.session(), c);
|
||||
trackview.editor().commit_reversible_command ();
|
||||
|
||||
_patch_changes.clear ();
|
||||
display_patch_changes ();
|
||||
@ -1929,7 +1991,9 @@ MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPri
|
||||
void
|
||||
MidiRegionView::change_patch_change (MidiModel::PatchChangePtr old_change, const Evoral::PatchChange<Evoral::Beats> & new_change)
|
||||
{
|
||||
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("alter patch change"));
|
||||
string name = _("alter patch change");
|
||||
trackview.editor().begin_reversible_command (name);
|
||||
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name);
|
||||
|
||||
if (old_change->time() != new_change.time()) {
|
||||
c->change_time (old_change, new_change.time());
|
||||
@ -1948,6 +2012,7 @@ MidiRegionView::change_patch_change (MidiModel::PatchChangePtr old_change, const
|
||||
}
|
||||
|
||||
_model->apply_command (*trackview.session(), c);
|
||||
trackview.editor().commit_reversible_command ();
|
||||
|
||||
_patch_changes.clear ();
|
||||
display_patch_changes ();
|
||||
@ -1962,8 +2027,10 @@ void
|
||||
MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beats> const & patch)
|
||||
{
|
||||
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
|
||||
string name = _("add patch change");
|
||||
|
||||
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("add patch change"));
|
||||
trackview.editor().begin_reversible_command (name);
|
||||
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name);
|
||||
c->add (MidiModel::PatchChangePtr (
|
||||
new Evoral::PatchChange<Evoral::Beats> (
|
||||
absolute_frames_to_source_beats (_region->position() + t),
|
||||
@ -1973,6 +2040,7 @@ MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beat
|
||||
);
|
||||
|
||||
_model->apply_command (*trackview.session(), c);
|
||||
trackview.editor().commit_reversible_command ();
|
||||
|
||||
_patch_changes.clear ();
|
||||
display_patch_changes ();
|
||||
@ -1981,9 +2049,11 @@ MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beat
|
||||
void
|
||||
MidiRegionView::move_patch_change (PatchChange& pc, Evoral::Beats t)
|
||||
{
|
||||
trackview.editor().begin_reversible_command (_("move patch change"));
|
||||
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("move patch change"));
|
||||
c->change_time (pc.patch (), t);
|
||||
_model->apply_command (*trackview.session(), c);
|
||||
trackview.editor().commit_reversible_command ();
|
||||
|
||||
_patch_changes.clear ();
|
||||
display_patch_changes ();
|
||||
@ -1992,9 +2062,11 @@ MidiRegionView::move_patch_change (PatchChange& pc, Evoral::Beats t)
|
||||
void
|
||||
MidiRegionView::delete_patch_change (PatchChange* pc)
|
||||
{
|
||||
trackview.editor().begin_reversible_command (_("delete patch change"));
|
||||
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("delete patch change"));
|
||||
c->remove (pc->patch ());
|
||||
_model->apply_command (*trackview.session(), c);
|
||||
trackview.editor().commit_reversible_command ();
|
||||
|
||||
_patch_changes.clear ();
|
||||
display_patch_changes ();
|
||||
@ -2143,6 +2215,24 @@ MidiRegionView::invert_selection ()
|
||||
}
|
||||
}
|
||||
|
||||
/** Used for selection undo/redo.
|
||||
The requested notes most likely won't exist in the view until the next model redisplay.
|
||||
*/
|
||||
void
|
||||
MidiRegionView::select_notes (list<boost::shared_ptr<NoteType> > notes)
|
||||
{
|
||||
NoteBase* cne;
|
||||
list<boost::shared_ptr<NoteType> >::iterator n;
|
||||
|
||||
for (n = notes.begin(); n != notes.end(); ++n) {
|
||||
if ((cne = find_canvas_note(*(*n))) != 0) {
|
||||
add_to_selection (cne);
|
||||
} else {
|
||||
_pending_note_selection.insert(*n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegionView::select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend)
|
||||
{
|
||||
|
@ -203,6 +203,7 @@ public:
|
||||
void move_selection(double dx, double dy, double cumulative_dy);
|
||||
void note_dropped (NoteBase* ev, ARDOUR::frameoffset_t, int8_t d_note);
|
||||
|
||||
void select_notes (std::list<boost::shared_ptr<NoteType> >);
|
||||
void select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend);
|
||||
void toggle_matching_notes (uint8_t notenum, uint16_t channel_mask);
|
||||
|
||||
@ -438,6 +439,9 @@ private:
|
||||
* when they appear after the command is applied. */
|
||||
std::set< boost::shared_ptr<NoteType> > _marked_for_selection;
|
||||
|
||||
/** Notes that should be selected when the model is redisplayed. */
|
||||
std::set< boost::shared_ptr<NoteType> > _pending_note_selection;
|
||||
|
||||
/** New notes (created in the current command) which should have visible velocity
|
||||
* when they appear after the command is applied. */
|
||||
std::set< boost::shared_ptr<NoteType> > _marked_for_velocity;
|
||||
@ -448,6 +452,7 @@ private:
|
||||
PBD::ScopedConnection content_connection;
|
||||
|
||||
NoteBase* find_canvas_note (boost::shared_ptr<NoteType>);
|
||||
NoteBase* find_canvas_note (NoteType);
|
||||
Events::iterator _optimization_iterator;
|
||||
|
||||
void update_note (NoteBase*, bool update_ghost_regions = true);
|
||||
@ -499,6 +504,8 @@ private:
|
||||
bool _grabbed_keyboard;
|
||||
bool _entered;
|
||||
|
||||
bool _mouse_changed_selection;
|
||||
|
||||
framepos_t snap_frame_to_grid_underneath (framepos_t p, framecnt_t &) const;
|
||||
|
||||
PBD::ScopedConnection _mouse_mode_connection;
|
||||
|
@ -1308,6 +1308,8 @@ MidiTimeAxisView::set_note_selection (uint8_t note)
|
||||
{
|
||||
uint16_t chn_mask = midi_track()->get_playback_channel_mask();
|
||||
|
||||
_editor.begin_reversible_selection_op(_("Set Note Selection"));
|
||||
|
||||
if (_view->num_selected_regionviews() == 0) {
|
||||
_view->foreach_regionview (
|
||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_selection_region_view),
|
||||
@ -1317,6 +1319,8 @@ MidiTimeAxisView::set_note_selection (uint8_t note)
|
||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_selection_region_view),
|
||||
note, chn_mask));
|
||||
}
|
||||
|
||||
_editor.commit_reversible_selection_op();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1324,6 +1328,8 @@ MidiTimeAxisView::add_note_selection (uint8_t note)
|
||||
{
|
||||
const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
|
||||
|
||||
_editor.begin_reversible_selection_op(_("Add Note Selection"));
|
||||
|
||||
if (_view->num_selected_regionviews() == 0) {
|
||||
_view->foreach_regionview (
|
||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection_region_view),
|
||||
@ -1333,6 +1339,8 @@ MidiTimeAxisView::add_note_selection (uint8_t note)
|
||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection_region_view),
|
||||
note, chn_mask));
|
||||
}
|
||||
|
||||
_editor.commit_reversible_selection_op();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1340,6 +1348,8 @@ MidiTimeAxisView::extend_note_selection (uint8_t note)
|
||||
{
|
||||
const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
|
||||
|
||||
_editor.begin_reversible_selection_op(_("Extend Note Selection"));
|
||||
|
||||
if (_view->num_selected_regionviews() == 0) {
|
||||
_view->foreach_regionview (
|
||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection_region_view),
|
||||
@ -1349,6 +1359,8 @@ MidiTimeAxisView::extend_note_selection (uint8_t note)
|
||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection_region_view),
|
||||
note, chn_mask));
|
||||
}
|
||||
|
||||
_editor.commit_reversible_selection_op();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1356,6 +1368,8 @@ MidiTimeAxisView::toggle_note_selection (uint8_t note)
|
||||
{
|
||||
const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
|
||||
|
||||
_editor.begin_reversible_selection_op(_("Toggle Note Selection"));
|
||||
|
||||
if (_view->num_selected_regionviews() == 0) {
|
||||
_view->foreach_regionview (
|
||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection_region_view),
|
||||
@ -1365,6 +1379,15 @@ MidiTimeAxisView::toggle_note_selection (uint8_t note)
|
||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection_region_view),
|
||||
note, chn_mask));
|
||||
}
|
||||
|
||||
_editor.commit_reversible_selection_op();
|
||||
}
|
||||
|
||||
void
|
||||
MidiTimeAxisView::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >& selection)
|
||||
{
|
||||
_view->foreach_regionview (
|
||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::get_per_region_note_selection_region_view), sigc::ref(selection)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -1391,6 +1414,24 @@ MidiTimeAxisView::toggle_note_selection_region_view (RegionView* rv, uint8_t not
|
||||
dynamic_cast<MidiRegionView*>(rv)->toggle_matching_notes (note, chn_mask);
|
||||
}
|
||||
|
||||
void
|
||||
MidiTimeAxisView::get_per_region_note_selection_region_view (RegionView* rv, list<pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection)
|
||||
{
|
||||
Evoral::Sequence<Evoral::Beats>::Notes selected;
|
||||
dynamic_cast<MidiRegionView*>(rv)->selection_as_notelist (selected, false);
|
||||
|
||||
std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > notes;
|
||||
|
||||
Evoral::Sequence<Evoral::Beats>::Notes::iterator sel_it;
|
||||
for (sel_it = selected.begin(); sel_it != selected.end(); ++sel_it) {
|
||||
notes.insert (*sel_it);
|
||||
}
|
||||
|
||||
if (!notes.empty()) {
|
||||
selection.push_back (make_pair ((rv)->region()->id(), notes));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiTimeAxisView::set_channel_mode (ChannelMode, uint16_t)
|
||||
{
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <gtkmm2ext/selector.h>
|
||||
#include <list>
|
||||
|
||||
#include "evoral/Note.hpp"
|
||||
|
||||
#include "ardour/types.h"
|
||||
#include "ardour/region.h"
|
||||
|
||||
@ -100,6 +102,8 @@ class MidiTimeAxisView : public RouteTimeAxisView
|
||||
|
||||
uint8_t get_channel_for_add () const;
|
||||
|
||||
void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >&);
|
||||
|
||||
protected:
|
||||
void start_step_editing ();
|
||||
void stop_step_editing ();
|
||||
@ -165,6 +169,7 @@ class MidiTimeAxisView : public RouteTimeAxisView
|
||||
void add_note_selection_region_view (RegionView* rv, uint8_t note, uint16_t chn_mask);
|
||||
void extend_note_selection_region_view (RegionView*, uint8_t note, uint16_t chn_mask);
|
||||
void toggle_note_selection_region_view (RegionView*, uint8_t note, uint16_t chn_mask);
|
||||
void get_per_region_note_selection_region_view (RegionView*, std::list<std::pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >&);
|
||||
|
||||
void ensure_step_editor ();
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <gtkmm/actiongroup.h>
|
||||
#include <sigc++/signal.h>
|
||||
|
||||
#include "evoral/Note.hpp"
|
||||
#include "evoral/types.hpp"
|
||||
|
||||
#include "pbd/statefuldestructible.h"
|
||||
@ -391,6 +392,8 @@ 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_selection_op (std::string cmd_name) = 0;
|
||||
virtual void commit_reversible_selection_op () = 0;
|
||||
virtual void begin_reversible_command (std::string cmd_name) = 0;
|
||||
virtual void begin_reversible_command (GQuark) = 0;
|
||||
virtual void commit_reversible_command () = 0;
|
||||
@ -412,7 +415,8 @@ 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;
|
||||
virtual void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const = 0;
|
||||
virtual void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >&) const = 0;
|
||||
|
||||
/// Singleton instance, set up by Editor::Editor()
|
||||
|
||||
|
@ -109,6 +109,7 @@ Selection::clear ()
|
||||
clear_midi_notes ();
|
||||
clear_midi_regions ();
|
||||
clear_markers ();
|
||||
pending_midi_note_selection.clear();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1229,12 +1230,45 @@ 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()));
|
||||
}
|
||||
|
||||
/* midi region views have thir own internal selection. */
|
||||
XMLNode* n;
|
||||
list<pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > rid_notes;
|
||||
editor->get_per_region_note_selection (rid_notes);
|
||||
if (!rid_notes.empty()) {
|
||||
n = node->add_child (X_("MIDINote"));
|
||||
}
|
||||
list<pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rn_it;
|
||||
for (rn_it = rid_notes.begin(); rn_it != rid_notes.end(); ++rn_it) {
|
||||
n->add_property (X_("region_id"), atoi((*rn_it).first.to_s().c_str()));
|
||||
|
||||
for (std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > >::iterator i = (*rn_it).second.begin(); i != (*rn_it).second.end(); ++i) {
|
||||
XMLNode* nc = n->add_child(X_("note"));
|
||||
snprintf(buf, sizeof(buf), "%d", (*i)->channel());
|
||||
nc->add_property(X_("channel"), string(buf));
|
||||
|
||||
snprintf(buf, sizeof(buf), "%f", (*i)->time().to_double());
|
||||
nc->add_property(X_("time"), string(buf));
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", (*i)->note());
|
||||
nc->add_property(X_("note"), string(buf));
|
||||
|
||||
snprintf(buf, sizeof(buf), "%f", (*i)->length().to_double());
|
||||
nc->add_property(X_("length"), string(buf));
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", (*i)->velocity());
|
||||
nc->add_property(X_("velocity"), string(buf));
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", (*i)->off_velocity());
|
||||
nc->add_property(X_("off-velocity"), string(buf));
|
||||
}
|
||||
}
|
||||
|
||||
for (PointSelection::const_iterator i = points.begin(); i != points.end(); ++i) {
|
||||
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (&(*i)->line().trackview);
|
||||
if (atv) {
|
||||
|
||||
XMLNode* r = node->add_child (X_("ControlPoint"));
|
||||
r->add_property (X_("type"), "track");
|
||||
r->add_property (X_("route-id"), atoi (atv->parent_route()->id ().to_s ().c_str()));
|
||||
@ -1243,6 +1277,7 @@ Selection::get_state () const
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", (*i)->view_index());
|
||||
r->add_property (X_("view-index"), string(buf));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1304,14 +1339,72 @@ Selection::set_state (XMLNode const & node, int)
|
||||
add (rs);
|
||||
} else {
|
||||
/*
|
||||
regionviews are being constructed - stash the region IDs
|
||||
regionviews haven't been 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_("MIDINote")) {
|
||||
XMLProperty* prop_region_id = (*i)->property (X_("region-id"));
|
||||
|
||||
assert (prop_region_id);
|
||||
|
||||
PBD::ID const id (prop_region_id->value ());
|
||||
RegionSelection rs;
|
||||
|
||||
editor->get_regionviews_by_id (id, rs); // there could be more than one
|
||||
|
||||
std::list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > notes;
|
||||
XMLNodeList children = (*i)->children ();
|
||||
|
||||
for (XMLNodeList::const_iterator ci = children.begin(); ci != children.end(); ++ci) {
|
||||
XMLProperty* prop_channel = (*ci)->property (X_("channel"));
|
||||
XMLProperty* prop_time = (*ci)->property (X_("time"));
|
||||
XMLProperty* prop_note = (*ci)->property (X_("note"));
|
||||
XMLProperty* prop_length = (*ci)->property (X_("length"));
|
||||
XMLProperty* prop_velocity = (*ci)->property (X_("velocity"));
|
||||
XMLProperty* prop_off_velocity = (*ci)->property (X_("off-velocity"));
|
||||
|
||||
assert (prop_channel);
|
||||
assert (prop_time);
|
||||
assert (prop_note);
|
||||
assert (prop_length);
|
||||
assert (prop_velocity);
|
||||
assert (prop_off_velocity);
|
||||
|
||||
uint8_t channel = atoi(prop_channel->value());
|
||||
Evoral::Beats time (atof(prop_time->value()));
|
||||
Evoral::Beats length (atof(prop_length->value()));
|
||||
uint8_t note = atoi(prop_note->value());
|
||||
uint8_t velocity = atoi(prop_velocity->value());
|
||||
uint8_t off_velocity = atoi(prop_off_velocity->value());
|
||||
boost::shared_ptr<Evoral::Note<Evoral::Beats> > the_note
|
||||
(new Evoral::Note<Evoral::Beats> (channel, time, length, note, velocity));
|
||||
the_note->set_off_velocity (off_velocity);
|
||||
|
||||
notes.push_back (the_note);
|
||||
}
|
||||
|
||||
for (RegionSelection::iterator rsi = rs.begin(); rsi != rs.end(); ++rsi) {
|
||||
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (*rsi);
|
||||
if (mrv) {
|
||||
mrv->select_notes(notes);
|
||||
}
|
||||
}
|
||||
|
||||
if (rs.empty()) {
|
||||
/* regionviews containing these notes don't yet exist on the canvas.*/
|
||||
pending_midi_note_selection.push_back (make_pair (id, notes));
|
||||
}
|
||||
|
||||
} else if ((*i)->name() == X_("ControlPoint")) {
|
||||
XMLProperty* prop_type = (*i)->property (X_("type"));
|
||||
|
||||
assert(prop_type);
|
||||
|
||||
if (prop_type->value () == "track") {
|
||||
|
||||
XMLProperty* prop_route_id = (*i)->property (X_("route-id"));
|
||||
XMLProperty* prop_alist_id = (*i)->property (X_("automation-list-id"));
|
||||
XMLProperty* prop_parameter = (*i)->property (X_("parameter"));
|
||||
@ -1323,24 +1416,28 @@ Selection::set_state (XMLNode const & node, int)
|
||||
assert (prop_parameter);
|
||||
assert (prop_view_index);
|
||||
|
||||
if (prop_type->value () == "track") {
|
||||
PBD::ID id (prop_route_id->value ());
|
||||
RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (id);
|
||||
PBD::ID route_id (prop_route_id->value ());
|
||||
RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (route_id);
|
||||
vector <ControlPoint *> cps;
|
||||
|
||||
if (rtv) {
|
||||
boost::shared_ptr<AutomationTimeAxisView> atv = rtv->automation_child (EventTypeMap::instance().from_symbol (prop_parameter->value ()));
|
||||
if (atv) {
|
||||
list<boost::shared_ptr<AutomationLine> > lines = atv->lines();
|
||||
for (list<boost::shared_ptr<AutomationLine> > ::iterator i = lines.begin(); i != lines.end(); ++i) {
|
||||
if ((*i)->the_list()->id() == prop_alist_id->value()) {
|
||||
ControlPoint* cp = (*i)->nth(atol(prop_view_index->value().c_str()));
|
||||
for (list<boost::shared_ptr<AutomationLine> > ::iterator li = lines.begin(); li != lines.end(); ++li) {
|
||||
if ((*li)->the_list()->id() == prop_alist_id->value()) {
|
||||
ControlPoint* cp = (*li)->nth(atol(prop_view_index->value().c_str()));
|
||||
if (cp) {
|
||||
add (cp);
|
||||
cps.push_back (cp);
|
||||
cp->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cps.empty()) {
|
||||
add (cps);
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((*i)->name() == X_("AudioRange")) {
|
||||
|
@ -223,6 +223,8 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
|
||||
|
||||
PBD::Signal0<void> ClearMidiNoteSelection;
|
||||
|
||||
std::list<std::pair<PBD::ID const, std::list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > pending_midi_note_selection;
|
||||
|
||||
private:
|
||||
PublicEditor const * editor;
|
||||
uint32_t next_time_id;
|
||||
|
Loading…
Reference in New Issue
Block a user