mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 19:56:31 +01:00
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
14 changed files with 375 additions and 66 deletions
|
|
@ -156,7 +156,7 @@ void
|
||||||
AutomationLine::update_visibility ()
|
AutomationLine::update_visibility ()
|
||||||
{
|
{
|
||||||
if (_visible & Line) {
|
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
|
when automation points have been removed (the line will still follow the shape of the
|
||||||
old points).
|
old points).
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,6 @@
|
||||||
|
|
||||||
#include "control_protocol/control_protocol.h"
|
#include "control_protocol/control_protocol.h"
|
||||||
|
|
||||||
#include "actions.h"
|
|
||||||
#include "actions.h"
|
#include "actions.h"
|
||||||
#include "analysis_window.h"
|
#include "analysis_window.h"
|
||||||
#include "audio_clock.h"
|
#include "audio_clock.h"
|
||||||
|
|
@ -251,6 +250,7 @@ pane_size_watcher (Paned* pane)
|
||||||
Editor::Editor ()
|
Editor::Editor ()
|
||||||
: _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
|
: _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
|
||||||
|
|
||||||
|
, _mouse_changed_selection (false)
|
||||||
/* time display buttons */
|
/* time display buttons */
|
||||||
, minsec_label (_("Mins:Secs"))
|
, minsec_label (_("Mins:Secs"))
|
||||||
, bbt_label (_("Bars:Beats"))
|
, bbt_label (_("Bars:Beats"))
|
||||||
|
|
@ -3336,7 +3336,7 @@ void
|
||||||
Editor::begin_reversible_selection_op (string name)
|
Editor::begin_reversible_selection_op (string name)
|
||||||
{
|
{
|
||||||
if (_session) {
|
if (_session) {
|
||||||
//cerr << name << endl;
|
cerr << name << endl;
|
||||||
/* begin/commit pairs can be nested */
|
/* begin/commit pairs can be nested */
|
||||||
selection_op_cmd_depth++;
|
selection_op_cmd_depth++;
|
||||||
}
|
}
|
||||||
|
|
@ -3349,20 +3349,22 @@ Editor::commit_reversible_selection_op ()
|
||||||
if (selection_op_cmd_depth == 1) {
|
if (selection_op_cmd_depth == 1) {
|
||||||
|
|
||||||
if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
|
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();
|
list<XMLNode *>::iterator it = selection_op_history.begin();
|
||||||
advance (it, selection_op_history_it);
|
advance (it, selection_op_history_it);
|
||||||
selection_op_history.erase (selection_op_history.begin(), it);
|
selection_op_history.erase (selection_op_history.begin(), it);
|
||||||
}
|
}
|
||||||
|
|
||||||
selection_op_history.push_front (&_selection_memento->get_state ());
|
selection_op_history.push_front (&_selection_memento->get_state ());
|
||||||
selection_op_history_it = 0;
|
selection_op_history_it = 0;
|
||||||
|
|
||||||
|
selection_undo_action->set_sensitive (true);
|
||||||
|
selection_redo_action->set_sensitive (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection_op_cmd_depth > 0) {
|
if (selection_op_cmd_depth > 0) {
|
||||||
selection_op_cmd_depth--;
|
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);
|
selection_redo_action->set_sensitive (true);
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
|
|
||||||
}
|
}
|
||||||
/* is there an earlier entry? */
|
/* is there an earlier entry? */
|
||||||
if ((selection_op_history_it + 1) >= selection_op_history.size()) {
|
if ((selection_op_history_it + 1) >= selection_op_history.size()) {
|
||||||
|
|
@ -3401,7 +3402,6 @@ Editor::redo_selection_op ()
|
||||||
selection_undo_action->set_sensitive (true);
|
selection_undo_action->set_sensitive (true);
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection_op_history_it == 0) {
|
if (selection_op_history_it == 0) {
|
||||||
|
|
@ -4899,17 +4899,17 @@ Editor::get_regions_from_selection_and_entered ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
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;
|
boost::shared_ptr<Playlist> pl;
|
||||||
std::vector<boost::shared_ptr<Region> > results;
|
std::vector<boost::shared_ptr<Region> > results;
|
||||||
boost::shared_ptr<Track> tr;
|
boost::shared_ptr<Track> tr;
|
||||||
|
|
||||||
if ((tr = tatv->track()) == 0) {
|
if ((tr = rtav->track()) == 0) {
|
||||||
/* bus */
|
/* bus */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -4917,9 +4917,9 @@ Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) co
|
||||||
if ((pl = (tr->playlist())) != 0) {
|
if ((pl = (tr->playlist())) != 0) {
|
||||||
boost::shared_ptr<Region> r = pl->region_by_id (id);
|
boost::shared_ptr<Region> r = pl->region_by_id (id);
|
||||||
if (r) {
|
if (r) {
|
||||||
RegionView* marv = tatv->view()->find_view (r);
|
RegionView* rv = rtav->view()->find_view (r);
|
||||||
if (marv) {
|
if (rv) {
|
||||||
regions.push_back (marv);
|
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
|
void
|
||||||
Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
|
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;
|
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 ();
|
_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_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);
|
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);
|
void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type);
|
||||||
bool button_release_can_deselect;
|
bool button_release_can_deselect;
|
||||||
|
bool _mouse_changed_selection;
|
||||||
|
|
||||||
void catch_vanishing_regionview (RegionView *);
|
void catch_vanishing_regionview (RegionView *);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,9 @@ Editor::canvas_scroll_event (GdkEventScroll *event, bool from_canvas)
|
||||||
bool
|
bool
|
||||||
Editor::track_canvas_button_press_event (GdkEventButton */*event*/)
|
Editor::track_canvas_button_press_event (GdkEventButton */*event*/)
|
||||||
{
|
{
|
||||||
|
begin_reversible_selection_op (_("Clear Selection Click (track canvas)"));
|
||||||
selection->clear ();
|
selection->clear ();
|
||||||
|
commit_reversible_selection_op();
|
||||||
_track_canvas->grab_focus();
|
_track_canvas->grab_focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1105,8 +1107,10 @@ Editor::canvas_drop_zone_event (GdkEvent* event)
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
if (event->button.button == 1) {
|
if (event->button.button == 1) {
|
||||||
|
begin_reversible_selection_op (_("Nowhere Click"));
|
||||||
selection->clear_objects ();
|
selection->clear_objects ();
|
||||||
selection->clear_tracks ();
|
selection->clear_tracks ();
|
||||||
|
commit_reversible_selection_op ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4718,6 +4718,9 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
|
||||||
} else {
|
} else {
|
||||||
_region->unique_select (_primary);
|
_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 ||
|
if (_editor->current_mouse_mode() == Editing::MouseObject ||
|
||||||
_editor->current_mouse_mode() == Editing::MouseDraw) {
|
_editor->current_mouse_mode() == Editing::MouseDraw) {
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
if (_was_selected) {
|
if (_was_selected) {
|
||||||
bool add = Keyboard::modifier_state_equals (ev->button.state, Keyboard::PrimaryModifier);
|
bool add = Keyboard::modifier_state_equals (ev->button.state, Keyboard::PrimaryModifier);
|
||||||
if (add) {
|
if (add) {
|
||||||
_region->note_deselected (_primary);
|
_region->note_deselected (_primary);
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool extend = Keyboard::modifier_state_equals (ev->button.state, Keyboard::TertiaryModifier);
|
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) {
|
if (!extend && !add && _region->selection_size() > 1) {
|
||||||
_region->unique_select (_primary);
|
_region->unique_select (_primary);
|
||||||
|
changed = true;
|
||||||
} else if (extend) {
|
} else if (extend) {
|
||||||
_region->note_selected (_primary, true, true);
|
_region->note_selected (_primary, true, true);
|
||||||
|
changed = true;
|
||||||
} else {
|
} else {
|
||||||
/* it was added during button press */
|
/* it was added during button press */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
_editor->begin_reversible_selection_op(_("Select Note Release"));
|
||||||
|
_editor->commit_reversible_selection_op();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_region->note_dropped (_primary, total_dx(), total_dy());
|
_region->note_dropped (_primary, total_dx(), total_dy());
|
||||||
|
|
@ -5204,12 +5217,15 @@ EditorRubberbandSelectDrag::select_things (int button_state, framepos_t x1, fram
|
||||||
void
|
void
|
||||||
EditorRubberbandSelectDrag::deselect_things ()
|
EditorRubberbandSelectDrag::deselect_things ()
|
||||||
{
|
{
|
||||||
if (!getenv("ARDOUR_SAE")) {
|
_editor->begin_reversible_selection_op (_("Clear Selection (rubberband)"));
|
||||||
_editor->selection->clear_tracks();
|
|
||||||
}
|
_editor->selection->clear_tracks();
|
||||||
_editor->selection->clear_regions();
|
_editor->selection->clear_regions();
|
||||||
_editor->selection->clear_points ();
|
_editor->selection->clear_points ();
|
||||||
_editor->selection->clear_lines ();
|
_editor->selection->clear_lines ();
|
||||||
|
_editor->selection->clear_midi_notes ();
|
||||||
|
|
||||||
|
_editor->commit_reversible_selection_op();
|
||||||
}
|
}
|
||||||
|
|
||||||
NoteCreateDrag::NoteCreateDrag (Editor* e, ArdourCanvas::Item* i, MidiRegionView* rv)
|
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);
|
Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
|
||||||
bool press = (event->type == GDK_BUTTON_PRESS);
|
bool press = (event->type == GDK_BUTTON_PRESS);
|
||||||
|
|
||||||
|
if (press) {
|
||||||
|
_mouse_changed_selection = false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (item_type) {
|
switch (item_type) {
|
||||||
case RegionItem:
|
case RegionItem:
|
||||||
if (press) {
|
if (press) {
|
||||||
if (eff_mouse_mode != MouseRange) {
|
if (eff_mouse_mode != MouseRange) {
|
||||||
set_selected_regionview_from_click (press, op);
|
_mouse_changed_selection = set_selected_regionview_from_click (press, op);
|
||||||
} else {
|
} else {
|
||||||
/* don't change the selection unless the
|
/* don't change the selection unless the
|
||||||
clicked track is not currently selected. if
|
clicked track is not currently selected. if
|
||||||
|
|
@ -465,7 +469,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (eff_mouse_mode != MouseRange) {
|
if (eff_mouse_mode != MouseRange) {
|
||||||
set_selected_regionview_from_click (press, op);
|
_mouse_changed_selection = set_selected_regionview_from_click (press, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -483,7 +487,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||||
case StartCrossFadeItem:
|
case StartCrossFadeItem:
|
||||||
case EndCrossFadeItem:
|
case EndCrossFadeItem:
|
||||||
if (get_smart_mode() || eff_mouse_mode != MouseRange) {
|
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) {
|
} else if (event->type == GDK_BUTTON_PRESS) {
|
||||||
set_selected_track_as_side_effect (op);
|
set_selected_track_as_side_effect (op);
|
||||||
}
|
}
|
||||||
|
|
@ -492,7 +496,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||||
case ControlPointItem:
|
case ControlPointItem:
|
||||||
set_selected_track_as_side_effect (op);
|
set_selected_track_as_side_effect (op);
|
||||||
if (eff_mouse_mode != MouseRange) {
|
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;
|
break;
|
||||||
|
|
||||||
|
|
@ -501,6 +505,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||||
if (event->button.button == 3) {
|
if (event->button.button == 3) {
|
||||||
selection->clear_tracks ();
|
selection->clear_tracks ();
|
||||||
set_selected_track_as_side_effect (op);
|
set_selected_track_as_side_effect (op);
|
||||||
|
_mouse_changed_selection = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -511,6 +516,12 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((!press) && _mouse_changed_selection) {
|
||||||
|
begin_reversible_selection_op (_("Button Selection"));
|
||||||
|
commit_reversible_selection_op ();
|
||||||
|
_mouse_changed_selection = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -744,6 +755,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
||||||
case AutomationTrackItem:
|
case AutomationTrackItem:
|
||||||
/* rubberband drag to select automation points */
|
/* rubberband drag to select automation points */
|
||||||
_drags->set (new EditorRubberbandSelectDrag (this, item), event);
|
_drags->set (new EditorRubberbandSelectDrag (this, item), event);
|
||||||
|
return true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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 */
|
/* do any (de)selection operations that should occur on button release */
|
||||||
|
button_selection (item, event, item_type);
|
||||||
begin_reversible_selection_op (_("Button Select"));
|
|
||||||
button_selection (item, event, item_type);
|
|
||||||
commit_reversible_selection_op ();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -202,8 +202,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
|
||||||
}
|
}
|
||||||
} else if (group && group->is_active()) {
|
} else if (group && group->is_active()) {
|
||||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
|
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);
|
selection->remove(*i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
selection->remove (clicked_axisview);
|
selection->remove (clicked_axisview);
|
||||||
|
|
@ -215,8 +216,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
|
||||||
}
|
}
|
||||||
} else if (group && group->is_active()) {
|
} else if (group && group->is_active()) {
|
||||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
|
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);
|
selection->add(*i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
selection->add (clicked_axisview);
|
selection->add (clicked_axisview);
|
||||||
|
|
@ -234,8 +236,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
|
||||||
}
|
}
|
||||||
} else if (group && group->is_active()) {
|
} else if (group && group->is_active()) {
|
||||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
|
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);
|
selection->add(*i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
selection->add (clicked_axisview);
|
selection->add (clicked_axisview);
|
||||||
|
|
@ -253,8 +256,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
|
||||||
}
|
}
|
||||||
} else if (group && group->is_active()) {
|
} else if (group && group->is_active()) {
|
||||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
|
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);
|
selection->add(*i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
selection->set (clicked_axisview);
|
selection->set (clicked_axisview);
|
||||||
|
|
@ -1953,7 +1957,7 @@ Editor::get_edit_op_range (framepos_t& start, framepos_t& end) const
|
||||||
void
|
void
|
||||||
Editor::deselect_all ()
|
Editor::deselect_all ()
|
||||||
{
|
{
|
||||||
begin_reversible_selection_op(_("Clear Selection"));
|
begin_reversible_selection_op(_("Deselect All"));
|
||||||
selection->clear ();
|
selection->clear ();
|
||||||
commit_reversible_selection_op ();
|
commit_reversible_selection_op ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
|
||||||
, _last_event_y (0)
|
, _last_event_y (0)
|
||||||
, _grabbed_keyboard (false)
|
, _grabbed_keyboard (false)
|
||||||
, _entered (false)
|
, _entered (false)
|
||||||
|
, _mouse_changed_selection (false)
|
||||||
{
|
{
|
||||||
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
|
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
|
||||||
_note_group->raise_to_top();
|
_note_group->raise_to_top();
|
||||||
|
|
@ -169,6 +170,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
|
||||||
, _last_event_y (0)
|
, _last_event_y (0)
|
||||||
, _grabbed_keyboard (false)
|
, _grabbed_keyboard (false)
|
||||||
, _entered (false)
|
, _entered (false)
|
||||||
|
, _mouse_changed_selection (false)
|
||||||
{
|
{
|
||||||
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
|
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
|
||||||
_note_group->raise_to_top();
|
_note_group->raise_to_top();
|
||||||
|
|
@ -220,6 +222,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other)
|
||||||
, _last_event_y (0)
|
, _last_event_y (0)
|
||||||
, _grabbed_keyboard (false)
|
, _grabbed_keyboard (false)
|
||||||
, _entered (false)
|
, _entered (false)
|
||||||
|
, _mouse_changed_selection (false)
|
||||||
{
|
{
|
||||||
init (false);
|
init (false);
|
||||||
}
|
}
|
||||||
|
|
@ -250,6 +253,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M
|
||||||
, _last_event_y (0)
|
, _last_event_y (0)
|
||||||
, _grabbed_keyboard (false)
|
, _grabbed_keyboard (false)
|
||||||
, _entered (false)
|
, _entered (false)
|
||||||
|
, _mouse_changed_selection (false)
|
||||||
{
|
{
|
||||||
init (true);
|
init (true);
|
||||||
}
|
}
|
||||||
|
|
@ -502,6 +506,7 @@ MidiRegionView::button_press (GdkEventButton* ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
_pressed_button = ev->button;
|
_pressed_button = ev->button;
|
||||||
|
_mouse_changed_selection = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -532,12 +537,14 @@ MidiRegionView::button_release (GdkEventButton* ev)
|
||||||
case MouseRange:
|
case MouseRange:
|
||||||
/* no motion occured - simple click */
|
/* no motion occured - simple click */
|
||||||
clear_selection ();
|
clear_selection ();
|
||||||
|
_mouse_changed_selection = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MouseContent:
|
case MouseContent:
|
||||||
case MouseTimeFX:
|
case MouseTimeFX:
|
||||||
{
|
{
|
||||||
clear_selection();
|
clear_selection();
|
||||||
|
_mouse_changed_selection = true;
|
||||||
|
|
||||||
if (Keyboard::is_insert_note_event(ev)) {
|
if (Keyboard::is_insert_note_event(ev)) {
|
||||||
|
|
||||||
|
|
@ -591,6 +598,11 @@ MidiRegionView::button_release (GdkEventButton* ev)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(_mouse_changed_selection) {
|
||||||
|
trackview.editor().begin_reversible_selection_op (_("Mouse Selection Change"));
|
||||||
|
trackview.editor().commit_reversible_selection_op ();
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -643,6 +655,7 @@ MidiRegionView::motion (GdkEventMotion* ev)
|
||||||
editor.drags()->set (new MidiRubberbandSelectDrag (dynamic_cast<Editor *> (&editor), this), (GdkEvent *) ev);
|
editor.drags()->set (new MidiRubberbandSelectDrag (dynamic_cast<Editor *> (&editor), this), (GdkEvent *) ev);
|
||||||
if (!Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
|
if (!Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
|
||||||
clear_selection ();
|
clear_selection ();
|
||||||
|
_mouse_changed_selection = true;
|
||||||
}
|
}
|
||||||
_mouse_state = SelectRectDragging;
|
_mouse_state = SelectRectDragging;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -747,22 +760,32 @@ MidiRegionView::key_press (GdkEventKey* ev)
|
||||||
|
|
||||||
} else if (ev->keyval == GDK_Tab) {
|
} else if (ev->keyval == GDK_Tab) {
|
||||||
|
|
||||||
|
trackview.editor().begin_reversible_selection_op (_("Select Adjacent Note"));
|
||||||
|
|
||||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
||||||
goto_previous_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
goto_previous_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
||||||
} else {
|
} else {
|
||||||
goto_next_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
goto_next_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackview.editor().commit_reversible_selection_op();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else if (ev->keyval == GDK_ISO_Left_Tab) {
|
} else if (ev->keyval == GDK_ISO_Left_Tab) {
|
||||||
|
|
||||||
/* Shift-TAB generates ISO Left Tab, for some reason */
|
/* 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)) {
|
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
||||||
goto_previous_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
goto_previous_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
||||||
} else {
|
} else {
|
||||||
goto_next_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
goto_next_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackview.editor().commit_reversible_selection_op();
|
||||||
|
|
||||||
return true;
|
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());
|
view->update_note_range(new_note->note());
|
||||||
|
|
||||||
|
trackview.editor().begin_reversible_command(_("add note"));
|
||||||
MidiModel::NoteDiffCommand* cmd = _model->new_note_diff_command(_("add note"));
|
MidiModel::NoteDiffCommand* cmd = _model->new_note_diff_command(_("add note"));
|
||||||
cmd->add (new_note);
|
cmd->add (new_note);
|
||||||
_model->apply_command(*trackview.session(), cmd);
|
_model->apply_command(*trackview.session(), cmd);
|
||||||
|
trackview.editor().commit_reversible_command();
|
||||||
|
|
||||||
play_midi_note (new_note);
|
play_midi_note (new_note);
|
||||||
}
|
}
|
||||||
|
|
@ -982,8 +1007,8 @@ MidiRegionView::display_model(boost::shared_ptr<MidiModel> model)
|
||||||
|
|
||||||
content_connection.disconnect ();
|
content_connection.disconnect ();
|
||||||
_model->ContentsChanged.connect (content_connection, invalidator (*this), boost::bind (&MidiRegionView::redisplay_model, this), gui_context());
|
_model->ContentsChanged.connect (content_connection, invalidator (*this), boost::bind (&MidiRegionView::redisplay_model, this), gui_context());
|
||||||
|
/* Don't signal as nobody else needs to know until selection has been altered.*/
|
||||||
clear_events ();
|
clear_events (false);
|
||||||
|
|
||||||
if (_enable_display) {
|
if (_enable_display) {
|
||||||
redisplay_model();
|
redisplay_model();
|
||||||
|
|
@ -994,6 +1019,7 @@ void
|
||||||
MidiRegionView::start_note_diff_command (string name)
|
MidiRegionView::start_note_diff_command (string name)
|
||||||
{
|
{
|
||||||
if (!_note_diff_command) {
|
if (!_note_diff_command) {
|
||||||
|
trackview.editor().begin_reversible_command (name);
|
||||||
_note_diff_command = _model->new_note_diff_command (name);
|
_note_diff_command = _model->new_note_diff_command (name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1044,6 +1070,7 @@ void
|
||||||
MidiRegionView::apply_diff (bool as_subcommand)
|
MidiRegionView::apply_diff (bool as_subcommand)
|
||||||
{
|
{
|
||||||
bool add_or_remove;
|
bool add_or_remove;
|
||||||
|
bool commit = false;
|
||||||
|
|
||||||
if (!_note_diff_command) {
|
if (!_note_diff_command) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1060,6 +1087,7 @@ MidiRegionView::apply_diff (bool as_subcommand)
|
||||||
_model->apply_command_as_subcommand (*trackview.session(), _note_diff_command);
|
_model->apply_command_as_subcommand (*trackview.session(), _note_diff_command);
|
||||||
} else {
|
} else {
|
||||||
_model->apply_command (*trackview.session(), _note_diff_command);
|
_model->apply_command (*trackview.session(), _note_diff_command);
|
||||||
|
commit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_note_diff_command = 0;
|
_note_diff_command = 0;
|
||||||
|
|
@ -1070,6 +1098,9 @@ MidiRegionView::apply_diff (bool as_subcommand)
|
||||||
}
|
}
|
||||||
|
|
||||||
_marked_for_velocity.clear();
|
_marked_for_velocity.clear();
|
||||||
|
if (commit) {
|
||||||
|
trackview.editor().commit_reversible_command ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1100,6 +1131,27 @@ MidiRegionView::find_canvas_note (boost::shared_ptr<NoteType> note)
|
||||||
return 0;
|
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
|
void
|
||||||
MidiRegionView::get_events (Events& e, Evoral::Sequence<Evoral::Beats>::NoteOperator op, uint8_t val, int chan_mask)
|
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);
|
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 {
|
} else {
|
||||||
|
|
||||||
if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) {
|
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 */
|
/* remove note items that are no longer valid */
|
||||||
|
|
||||||
if (!empty_when_starting) {
|
if (!empty_when_starting) {
|
||||||
|
|
@ -1213,6 +1271,7 @@ MidiRegionView::redisplay_model()
|
||||||
|
|
||||||
_marked_for_selection.clear ();
|
_marked_for_selection.clear ();
|
||||||
_marked_for_velocity.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
|
/* 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
|
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
|
void
|
||||||
MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPrimaryKey& new_patch)
|
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()) {
|
if (pc.patch()->program() != new_patch.program()) {
|
||||||
c->change_program (pc.patch (), 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);
|
_model->apply_command (*trackview.session(), c);
|
||||||
|
trackview.editor().commit_reversible_command ();
|
||||||
|
|
||||||
_patch_changes.clear ();
|
_patch_changes.clear ();
|
||||||
display_patch_changes ();
|
display_patch_changes ();
|
||||||
|
|
@ -1929,7 +1991,9 @@ MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPri
|
||||||
void
|
void
|
||||||
MidiRegionView::change_patch_change (MidiModel::PatchChangePtr old_change, const Evoral::PatchChange<Evoral::Beats> & new_change)
|
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()) {
|
if (old_change->time() != new_change.time()) {
|
||||||
c->change_time (old_change, 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);
|
_model->apply_command (*trackview.session(), c);
|
||||||
|
trackview.editor().commit_reversible_command ();
|
||||||
|
|
||||||
_patch_changes.clear ();
|
_patch_changes.clear ();
|
||||||
display_patch_changes ();
|
display_patch_changes ();
|
||||||
|
|
@ -1962,8 +2027,10 @@ void
|
||||||
MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beats> const & patch)
|
MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beats> const & patch)
|
||||||
{
|
{
|
||||||
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
|
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 (
|
c->add (MidiModel::PatchChangePtr (
|
||||||
new Evoral::PatchChange<Evoral::Beats> (
|
new Evoral::PatchChange<Evoral::Beats> (
|
||||||
absolute_frames_to_source_beats (_region->position() + t),
|
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);
|
_model->apply_command (*trackview.session(), c);
|
||||||
|
trackview.editor().commit_reversible_command ();
|
||||||
|
|
||||||
_patch_changes.clear ();
|
_patch_changes.clear ();
|
||||||
display_patch_changes ();
|
display_patch_changes ();
|
||||||
|
|
@ -1981,9 +2049,11 @@ MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beat
|
||||||
void
|
void
|
||||||
MidiRegionView::move_patch_change (PatchChange& pc, Evoral::Beats t)
|
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"));
|
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("move patch change"));
|
||||||
c->change_time (pc.patch (), t);
|
c->change_time (pc.patch (), t);
|
||||||
_model->apply_command (*trackview.session(), c);
|
_model->apply_command (*trackview.session(), c);
|
||||||
|
trackview.editor().commit_reversible_command ();
|
||||||
|
|
||||||
_patch_changes.clear ();
|
_patch_changes.clear ();
|
||||||
display_patch_changes ();
|
display_patch_changes ();
|
||||||
|
|
@ -1992,9 +2062,11 @@ MidiRegionView::move_patch_change (PatchChange& pc, Evoral::Beats t)
|
||||||
void
|
void
|
||||||
MidiRegionView::delete_patch_change (PatchChange* pc)
|
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"));
|
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("delete patch change"));
|
||||||
c->remove (pc->patch ());
|
c->remove (pc->patch ());
|
||||||
_model->apply_command (*trackview.session(), c);
|
_model->apply_command (*trackview.session(), c);
|
||||||
|
trackview.editor().commit_reversible_command ();
|
||||||
|
|
||||||
_patch_changes.clear ();
|
_patch_changes.clear ();
|
||||||
display_patch_changes ();
|
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
|
void
|
||||||
MidiRegionView::select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend)
|
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 move_selection(double dx, double dy, double cumulative_dy);
|
||||||
void note_dropped (NoteBase* ev, ARDOUR::frameoffset_t, int8_t d_note);
|
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 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);
|
void toggle_matching_notes (uint8_t notenum, uint16_t channel_mask);
|
||||||
|
|
||||||
|
|
@ -438,6 +439,9 @@ private:
|
||||||
* when they appear after the command is applied. */
|
* when they appear after the command is applied. */
|
||||||
std::set< boost::shared_ptr<NoteType> > _marked_for_selection;
|
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
|
/** New notes (created in the current command) which should have visible velocity
|
||||||
* when they appear after the command is applied. */
|
* when they appear after the command is applied. */
|
||||||
std::set< boost::shared_ptr<NoteType> > _marked_for_velocity;
|
std::set< boost::shared_ptr<NoteType> > _marked_for_velocity;
|
||||||
|
|
@ -448,6 +452,7 @@ private:
|
||||||
PBD::ScopedConnection content_connection;
|
PBD::ScopedConnection content_connection;
|
||||||
|
|
||||||
NoteBase* find_canvas_note (boost::shared_ptr<NoteType>);
|
NoteBase* find_canvas_note (boost::shared_ptr<NoteType>);
|
||||||
|
NoteBase* find_canvas_note (NoteType);
|
||||||
Events::iterator _optimization_iterator;
|
Events::iterator _optimization_iterator;
|
||||||
|
|
||||||
void update_note (NoteBase*, bool update_ghost_regions = true);
|
void update_note (NoteBase*, bool update_ghost_regions = true);
|
||||||
|
|
@ -499,6 +504,8 @@ private:
|
||||||
bool _grabbed_keyboard;
|
bool _grabbed_keyboard;
|
||||||
bool _entered;
|
bool _entered;
|
||||||
|
|
||||||
|
bool _mouse_changed_selection;
|
||||||
|
|
||||||
framepos_t snap_frame_to_grid_underneath (framepos_t p, framecnt_t &) const;
|
framepos_t snap_frame_to_grid_underneath (framepos_t p, framecnt_t &) const;
|
||||||
|
|
||||||
PBD::ScopedConnection _mouse_mode_connection;
|
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();
|
uint16_t chn_mask = midi_track()->get_playback_channel_mask();
|
||||||
|
|
||||||
|
_editor.begin_reversible_selection_op(_("Set Note Selection"));
|
||||||
|
|
||||||
if (_view->num_selected_regionviews() == 0) {
|
if (_view->num_selected_regionviews() == 0) {
|
||||||
_view->foreach_regionview (
|
_view->foreach_regionview (
|
||||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_selection_region_view),
|
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),
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_selection_region_view),
|
||||||
note, chn_mask));
|
note, chn_mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_editor.commit_reversible_selection_op();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1324,6 +1328,8 @@ MidiTimeAxisView::add_note_selection (uint8_t note)
|
||||||
{
|
{
|
||||||
const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
|
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) {
|
if (_view->num_selected_regionviews() == 0) {
|
||||||
_view->foreach_regionview (
|
_view->foreach_regionview (
|
||||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection_region_view),
|
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),
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection_region_view),
|
||||||
note, chn_mask));
|
note, chn_mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_editor.commit_reversible_selection_op();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1340,6 +1348,8 @@ MidiTimeAxisView::extend_note_selection (uint8_t note)
|
||||||
{
|
{
|
||||||
const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
|
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) {
|
if (_view->num_selected_regionviews() == 0) {
|
||||||
_view->foreach_regionview (
|
_view->foreach_regionview (
|
||||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection_region_view),
|
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),
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection_region_view),
|
||||||
note, chn_mask));
|
note, chn_mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_editor.commit_reversible_selection_op();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1356,6 +1368,8 @@ MidiTimeAxisView::toggle_note_selection (uint8_t note)
|
||||||
{
|
{
|
||||||
const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
|
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) {
|
if (_view->num_selected_regionviews() == 0) {
|
||||||
_view->foreach_regionview (
|
_view->foreach_regionview (
|
||||||
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection_region_view),
|
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),
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection_region_view),
|
||||||
note, chn_mask));
|
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
|
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);
|
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
|
void
|
||||||
MidiTimeAxisView::set_channel_mode (ChannelMode, uint16_t)
|
MidiTimeAxisView::set_channel_mode (ChannelMode, uint16_t)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@
|
||||||
#include <gtkmm2ext/selector.h>
|
#include <gtkmm2ext/selector.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#include "evoral/Note.hpp"
|
||||||
|
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
#include "ardour/region.h"
|
#include "ardour/region.h"
|
||||||
|
|
||||||
|
|
@ -65,7 +67,7 @@ class MidiChannelSelectorWindow;
|
||||||
|
|
||||||
class MidiTimeAxisView : public RouteTimeAxisView
|
class MidiTimeAxisView : public RouteTimeAxisView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MidiTimeAxisView (PublicEditor&, ARDOUR::Session*, ArdourCanvas::Canvas& canvas);
|
MidiTimeAxisView (PublicEditor&, ARDOUR::Session*, ArdourCanvas::Canvas& canvas);
|
||||||
virtual ~MidiTimeAxisView ();
|
virtual ~MidiTimeAxisView ();
|
||||||
|
|
||||||
|
|
@ -100,11 +102,13 @@ class MidiTimeAxisView : public RouteTimeAxisView
|
||||||
|
|
||||||
uint8_t get_channel_for_add () const;
|
uint8_t get_channel_for_add () const;
|
||||||
|
|
||||||
protected:
|
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 start_step_editing ();
|
||||||
void stop_step_editing ();
|
void stop_step_editing ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sigc::signal<void, std::string, std::string> _midi_patch_settings_changed;
|
sigc::signal<void, std::string, std::string> _midi_patch_settings_changed;
|
||||||
|
|
||||||
void model_changed(const std::string& model);
|
void model_changed(const std::string& model);
|
||||||
|
|
@ -165,6 +169,7 @@ class MidiTimeAxisView : public RouteTimeAxisView
|
||||||
void add_note_selection_region_view (RegionView* rv, uint8_t note, uint16_t chn_mask);
|
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 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 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 ();
|
void ensure_step_editor ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include <gtkmm/actiongroup.h>
|
#include <gtkmm/actiongroup.h>
|
||||||
#include <sigc++/signal.h>
|
#include <sigc++/signal.h>
|
||||||
|
|
||||||
|
#include "evoral/Note.hpp"
|
||||||
#include "evoral/types.hpp"
|
#include "evoral/types.hpp"
|
||||||
|
|
||||||
#include "pbd/statefuldestructible.h"
|
#include "pbd/statefuldestructible.h"
|
||||||
|
|
@ -391,6 +392,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
|
||||||
virtual void stop_canvas_autoscroll () = 0;
|
virtual void stop_canvas_autoscroll () = 0;
|
||||||
virtual bool autoscroll_active() const = 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 (std::string cmd_name) = 0;
|
||||||
virtual void begin_reversible_command (GQuark) = 0;
|
virtual void begin_reversible_command (GQuark) = 0;
|
||||||
virtual void commit_reversible_command () = 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 void get_regions_at (RegionSelection &, framepos_t where, TrackViewList const &) const = 0;
|
||||||
virtual RegionSelection get_regions_from_selection_and_mouse (framepos_t) = 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()
|
/// Singleton instance, set up by Editor::Editor()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ Selection::clear ()
|
||||||
clear_midi_notes ();
|
clear_midi_notes ();
|
||||||
clear_midi_regions ();
|
clear_midi_regions ();
|
||||||
clear_markers ();
|
clear_markers ();
|
||||||
|
pending_midi_note_selection.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -506,9 +507,9 @@ Selection::add (RegionView* r)
|
||||||
|
|
||||||
if (find (regions.begin(), regions.end(), r) == regions.end()) {
|
if (find (regions.begin(), regions.end(), r) == regions.end()) {
|
||||||
bool changed = regions.add (r);
|
bool changed = regions.add (r);
|
||||||
if (changed) {
|
if (changed) {
|
||||||
RegionsChanged ();
|
RegionsChanged ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1229,12 +1230,45 @@ Selection::get_state () const
|
||||||
for (RegionSelection::const_iterator i = regions.begin(); i != regions.end(); ++i) {
|
for (RegionSelection::const_iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||||
XMLNode* r = node->add_child (X_("Region"));
|
XMLNode* r = node->add_child (X_("Region"));
|
||||||
r->add_property (X_("id"), atoi ((*i)->region ()->id ().to_s ().c_str()));
|
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) {
|
for (PointSelection::const_iterator i = points.begin(); i != points.end(); ++i) {
|
||||||
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (&(*i)->line().trackview);
|
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (&(*i)->line().trackview);
|
||||||
if (atv) {
|
if (atv) {
|
||||||
|
|
||||||
XMLNode* r = node->add_child (X_("ControlPoint"));
|
XMLNode* r = node->add_child (X_("ControlPoint"));
|
||||||
r->add_property (X_("type"), "track");
|
r->add_property (X_("type"), "track");
|
||||||
r->add_property (X_("route-id"), atoi (atv->parent_route()->id ().to_s ().c_str()));
|
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());
|
snprintf(buf, sizeof(buf), "%d", (*i)->view_index());
|
||||||
r->add_property (X_("view-index"), string(buf));
|
r->add_property (X_("view-index"), string(buf));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1304,43 +1339,105 @@ Selection::set_state (XMLNode const & node, int)
|
||||||
add (rs);
|
add (rs);
|
||||||
} else {
|
} 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 ()
|
so we can identify them in Editor::region_view_added ()
|
||||||
*/
|
*/
|
||||||
regions.pending.push_back (id);
|
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")) {
|
} else if ((*i)->name() == X_("ControlPoint")) {
|
||||||
XMLProperty* prop_type = (*i)->property (X_("type"));
|
XMLProperty* prop_type = (*i)->property (X_("type"));
|
||||||
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"));
|
|
||||||
XMLProperty* prop_view_index = (*i)->property (X_("view-index"));
|
|
||||||
|
|
||||||
assert (prop_type);
|
assert(prop_type);
|
||||||
assert (prop_route_id);
|
|
||||||
assert (prop_alist_id);
|
|
||||||
assert (prop_parameter);
|
|
||||||
assert (prop_view_index);
|
|
||||||
|
|
||||||
if (prop_type->value () == "track") {
|
if (prop_type->value () == "track") {
|
||||||
PBD::ID id (prop_route_id->value ());
|
|
||||||
RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (id);
|
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"));
|
||||||
|
XMLProperty* prop_view_index = (*i)->property (X_("view-index"));
|
||||||
|
|
||||||
|
assert (prop_type);
|
||||||
|
assert (prop_route_id);
|
||||||
|
assert (prop_alist_id);
|
||||||
|
assert (prop_parameter);
|
||||||
|
assert (prop_view_index);
|
||||||
|
|
||||||
|
PBD::ID route_id (prop_route_id->value ());
|
||||||
|
RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (route_id);
|
||||||
|
vector <ControlPoint *> cps;
|
||||||
|
|
||||||
if (rtv) {
|
if (rtv) {
|
||||||
boost::shared_ptr<AutomationTimeAxisView> atv = rtv->automation_child (EventTypeMap::instance().from_symbol (prop_parameter->value ()));
|
boost::shared_ptr<AutomationTimeAxisView> atv = rtv->automation_child (EventTypeMap::instance().from_symbol (prop_parameter->value ()));
|
||||||
if (atv) {
|
if (atv) {
|
||||||
list<boost::shared_ptr<AutomationLine> > lines = atv->lines();
|
list<boost::shared_ptr<AutomationLine> > lines = atv->lines();
|
||||||
for (list<boost::shared_ptr<AutomationLine> > ::iterator i = lines.begin(); i != lines.end(); ++i) {
|
for (list<boost::shared_ptr<AutomationLine> > ::iterator li = lines.begin(); li != lines.end(); ++li) {
|
||||||
if ((*i)->the_list()->id() == prop_alist_id->value()) {
|
if ((*li)->the_list()->id() == prop_alist_id->value()) {
|
||||||
ControlPoint* cp = (*i)->nth(atol(prop_view_index->value().c_str()));
|
ControlPoint* cp = (*li)->nth(atol(prop_view_index->value().c_str()));
|
||||||
if (cp) {
|
if (cp) {
|
||||||
add (cp);
|
cps.push_back (cp);
|
||||||
|
cp->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!cps.empty()) {
|
||||||
|
add (cps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((*i)->name() == X_("AudioRange")) {
|
} else if ((*i)->name() == X_("AudioRange")) {
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,8 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
|
||||||
|
|
||||||
PBD::Signal0<void> ClearMidiNoteSelection;
|
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:
|
private:
|
||||||
PublicEditor const * editor;
|
PublicEditor const * editor;
|
||||||
uint32_t next_time_id;
|
uint32_t next_time_id;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue