diff options
-rw-r--r-- | gtk2_ardour/canvas-program-change.cc | 17 | ||||
-rw-r--r-- | gtk2_ardour/canvas-program-change.h | 19 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.cc | 142 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.h | 45 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 25 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.h | 2 |
6 files changed, 212 insertions, 38 deletions
diff --git a/gtk2_ardour/canvas-program-change.cc b/gtk2_ardour/canvas-program-change.cc index d87b164f40..b48d7b33ba 100644 --- a/gtk2_ardour/canvas-program-change.cc +++ b/gtk2_ardour/canvas-program-change.cc @@ -6,11 +6,16 @@ #include "ardour_ui.h" #include "midi_region_view.h" #include "canvas-program-change.h" +#include "editor.h" +#include "editor_drag.h" using namespace Gnome::Canvas; using namespace MIDI::Name; using namespace std; +/** @param x x position in pixels. + * @param event_time PC time in beats, with respect to the start of the source. + */ CanvasProgramChange::CanvasProgramChange( MidiRegionView& region, Group& parent, @@ -107,7 +112,17 @@ CanvasProgramChange::on_event(GdkEvent* ev) { switch (ev->type) { case GDK_BUTTON_PRESS: - if (ev->button.button == 3) { + switch (ev->button.button) { + case 1: + { + /* XXX: icky dcast */ + Editor* e = dynamic_cast<Editor*> (&_region.get_time_axis_view().editor()); + if (e->current_mouse_mode() == Editing::MouseObject && e->internal_editing()) { + e->drags()->set (new ProgramChangeDrag (e, this, &_region), ev); + return true; + } + } + case 3: // lazy init if (!_popup_initialized) { initialize_popup_menus(); diff --git a/gtk2_ardour/canvas-program-change.h b/gtk2_ardour/canvas-program-change.h index 4093984555..51a7d427e4 100644 --- a/gtk2_ardour/canvas-program-change.h +++ b/gtk2_ardour/canvas-program-change.h @@ -35,20 +35,11 @@ public: virtual bool on_event(GdkEvent* ev); - string model_name() const { return _model_name; } - void set_model_name(string model_name) { _model_name = model_name; } - - string custom_device_mode() const { return _custom_device_mode; } - void set_custom_device_mode(string custom_device_mode) { _custom_device_mode = custom_device_mode; } - - double event_time() const { return _event_time; } - void set_event_time(double new_time) { _event_time = new_time; }; - - uint8_t program() const { return _program; } - void set_program(uint8_t new_program) { _program = new_program; }; - - uint8_t channel() const { return _channel; } - void set_channel(uint8_t new_channel) { _channel = new_channel; }; + string model_name () const { return _model_name; } + string custom_device_mode () const { return _custom_device_mode; } + double event_time () const { return _event_time; } + uint8_t program () const { return _program; } + uint8_t channel () const { return _channel; } void initialize_popup_menus(); diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index af69691189..4845e8c918 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -220,6 +220,7 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor) } _raw_grab_frame = _editor->event_frame (event, &_grab_x, &_grab_y); + setup_pointer_frame_offset (); _grab_frame = adjusted_frame (_raw_grab_frame, event); _last_pointer_frame = _grab_frame; _last_pointer_x = _grab_x; @@ -1181,10 +1182,8 @@ RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, } void -RegionMoveDrag::start_grab (GdkEvent* event, Gdk::Cursor* c) +RegionMoveDrag::setup_pointer_frame_offset () { - RegionMotionDrag::start_grab (event, c); - _pointer_frame_offset = raw_grab_frame() - _last_frame_position; } @@ -1800,12 +1799,16 @@ MeterMarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) Drag::start_grab (event, cursor); - _pointer_frame_offset = raw_grab_frame() - _marker->meter().frame(); - _editor->show_verbose_time_cursor (adjusted_current_frame(event), 10); } void +MeterMarkerDrag::setup_pointer_frame_offset () +{ + _pointer_frame_offset = raw_grab_frame() - _marker->meter().frame(); +} + +void MeterMarkerDrag::motion (GdkEvent* event, bool) { framepos_t const pf = adjusted_current_frame (event); @@ -1892,11 +1895,16 @@ TempoMarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) Drag::start_grab (event, cursor); - _pointer_frame_offset = raw_grab_frame() - _marker->tempo().frame(); _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); } void +TempoMarkerDrag::setup_pointer_frame_offset () +{ + _pointer_frame_offset = raw_grab_frame() - _marker->tempo().frame(); +} + +void TempoMarkerDrag::motion (GdkEvent* event, bool) { framepos_t const pf = adjusted_current_frame (event); @@ -1993,12 +2001,16 @@ CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c) } } - _pointer_frame_offset = raw_grab_frame() - _cursor->current_frame; - _editor->show_verbose_time_cursor (_cursor->current_frame, 10); } void +CursorDrag::setup_pointer_frame_offset () +{ + _pointer_frame_offset = raw_grab_frame() - _cursor->current_frame; +} + +void CursorDrag::motion (GdkEvent* event, bool) { framepos_t const adjusted_frame = adjusted_current_frame (event); @@ -2071,13 +2083,20 @@ FadeInDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary); boost::shared_ptr<AudioRegion> const r = arv->audio_region (); - _pointer_frame_offset = raw_grab_frame() - ((framecnt_t) r->fade_in()->back()->when + r->position()); _editor->show_verbose_duration_cursor (r->position(), r->position() + r->fade_in()->back()->when, 10); arv->show_fade_line((framepos_t) r->fade_in()->back()->when); } void +FadeInDrag::setup_pointer_frame_offset () +{ + AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary); + boost::shared_ptr<AudioRegion> const r = arv->audio_region (); + _pointer_frame_offset = raw_grab_frame() - ((framecnt_t) r->fade_in()->back()->when + r->position()); +} + +void FadeInDrag::motion (GdkEvent* event, bool) { framecnt_t fade_length; @@ -2183,13 +2202,20 @@ FadeOutDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary); boost::shared_ptr<AudioRegion> r = arv->audio_region (); - _pointer_frame_offset = raw_grab_frame() - (r->length() - (framecnt_t) r->fade_out()->back()->when + r->position()); _editor->show_verbose_duration_cursor (r->last_frame() - r->fade_out()->back()->when, r->last_frame(), 10); arv->show_fade_line(r->length() - r->fade_out()->back()->when); } void +FadeOutDrag::setup_pointer_frame_offset () +{ + AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary); + boost::shared_ptr<AudioRegion> r = arv->audio_region (); + _pointer_frame_offset = raw_grab_frame() - (r->length() - (framecnt_t) r->fade_out()->back()->when + r->position()); +} + +void FadeOutDrag::motion (GdkEvent* event, bool) { framecnt_t fade_length; @@ -2321,8 +2347,6 @@ MarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) Location *location = _editor->find_location_from_marker (_marker, is_start); _editor->_dragging_edit_point = true; - _pointer_frame_offset = raw_grab_frame() - (is_start ? location->start() : location->end()); - update_item (location); // _drag_line->show(); @@ -2389,6 +2413,14 @@ MarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) } void +MarkerDrag::setup_pointer_frame_offset () +{ + bool is_start; + Location *location = _editor->find_location_from_marker (_marker, is_start); + _pointer_frame_offset = raw_grab_frame() - (is_start ? location->start() : location->end()); +} + +void MarkerDrag::motion (GdkEvent* event, bool) { framecnt_t f_delta = 0; @@ -3141,9 +3173,6 @@ SelectionDrag::SelectionDrag (Editor* e, ArdourCanvas::Item* i, Operation o) void SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*) { - framepos_t start = 0; - framepos_t end = 0; - if (_editor->session() == 0) { return; } @@ -3166,8 +3195,6 @@ SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*) _editor->clicked_axisview->order_selection_trims (_item, true); } Drag::start_grab (event, _editor->cursors()->left_side_trim); - start = _editor->selection->time[_editor->clicked_selection].start; - _pointer_frame_offset = raw_grab_frame() - start; break; case SelectionEndTrim: @@ -3175,19 +3202,15 @@ SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*) _editor->clicked_axisview->order_selection_trims (_item, false); } Drag::start_grab (event, _editor->cursors()->right_side_trim); - end = _editor->selection->time[_editor->clicked_selection].end; - _pointer_frame_offset = raw_grab_frame() - end; break; case SelectionMove: - start = _editor->selection->time[_editor->clicked_selection].start; Drag::start_grab (event, cursor); - _pointer_frame_offset = raw_grab_frame() - start; break; } if (_operation == SelectionMove) { - _editor->show_verbose_time_cursor (start, 10); + _editor->show_verbose_time_cursor (_editor->selection->time[_editor->clicked_selection].start, 10); } else { _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); } @@ -3196,6 +3219,25 @@ SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*) } void +SelectionDrag::setup_pointer_frame_offset () +{ + switch (_operation) { + case CreateSelection: + _pointer_frame_offset = 0; + break; + + case SelectionStartTrim: + case SelectionMove: + _pointer_frame_offset = raw_grab_frame() - _editor->selection->time[_editor->clicked_selection].start; + break; + + case SelectionEndTrim: + _pointer_frame_offset = raw_grab_frame() - _editor->selection->time[_editor->clicked_selection].end; + break; + } +} + +void SelectionDrag::motion (GdkEvent* event, bool first_move) { framepos_t start = 0; @@ -4038,3 +4080,59 @@ DraggingView::DraggingView (RegionView* v, RegionDrag* parent) initial_position = v->region()->position (); initial_end = v->region()->position () + v->region()->length (); } + +ProgramChangeDrag::ProgramChangeDrag (Editor* e, CanvasProgramChange* i, MidiRegionView* r) + : Drag (e, i) + , _region_view (r) + , _program_change (i) + , _cumulative_dx (0) +{ + DEBUG_TRACE (DEBUG::Drags, "New ProgramChangeDrag\n"); +} + +void +ProgramChangeDrag::motion (GdkEvent* ev, bool) +{ + framepos_t f = adjusted_current_frame (ev); + boost::shared_ptr<Region> r = _region_view->region (); + f = max (f, r->position ()); + f = min (f, r->last_frame ()); + + framecnt_t const dxf = f - grab_frame(); + double const dxu = _editor->frame_to_unit (dxf); + _program_change->move (dxu - _cumulative_dx, 0); + _cumulative_dx = dxu; +} + +void +ProgramChangeDrag::finished (GdkEvent* ev, bool movement_occurred) +{ + if (!movement_occurred) { + return; + } + + boost::shared_ptr<Region> r (_region_view->region ()); + + framepos_t f = adjusted_current_frame (ev); + f = max (f, r->position ()); + f = min (f, r->last_frame ()); + + _region_view->move_program_change ( + MidiRegionView::PCEvent (_program_change->event_time(), _program_change->program(), _program_change->channel()), + _region_view->frames_to_beats (f - r->position() - r->start()) + ); +} + +void +ProgramChangeDrag::aborted () +{ + _program_change->move (-_cumulative_dx, 0); +} + +void +ProgramChangeDrag::setup_pointer_frame_offset () +{ + boost::shared_ptr<Region> region = _region_view->region (); + _pointer_frame_offset = raw_grab_frame() - _region_view->beats_to_frames (_program_change->event_time()) - region->position() + region->start(); +} + diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index e0d3d91ee8..a3d3919fed 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -42,6 +42,7 @@ namespace PBD { namespace Gnome { namespace Canvas { class CanvasNoteEvent; + class CanvasProgramChange; } } @@ -175,6 +176,11 @@ public: return true; } + /** Set up the _pointer_frame_offset */ + virtual void setup_pointer_frame_offset () { + _pointer_frame_offset = 0; + } + protected: double grab_x () const { @@ -312,7 +318,6 @@ public: RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool); virtual ~RegionMoveDrag () {} - virtual void start_grab (GdkEvent *, Gdk::Cursor *); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); void aborted (); @@ -325,6 +330,8 @@ public: return std::make_pair (4, 4); } + void setup_pointer_frame_offset (); + private: typedef std::set<boost::shared_ptr<ARDOUR::Playlist> > PlaylistSet; @@ -444,6 +451,28 @@ class NoteDrag : public Drag double _note_height; }; +/** Drag to move MIDI program changes */ +class ProgramChangeDrag : public Drag +{ +public: + ProgramChangeDrag (Editor *, ArdourCanvas::CanvasProgramChange *, MidiRegionView *); + + void motion (GdkEvent *, bool); + void finished (GdkEvent *, bool); + void aborted (); + + bool y_movement_matters () const { + return false; + } + + void setup_pointer_frame_offset (); + +private: + MidiRegionView* _region_view; + ArdourCanvas::CanvasProgramChange* _program_change; + double _cumulative_dx; +}; + /** Drag of region gain */ class RegionGainDrag : public Drag { @@ -504,6 +533,8 @@ public: bool y_movement_matters () const { return false; } + + void setup_pointer_frame_offset (); private: MeterMarker* _marker; @@ -529,6 +560,8 @@ public: return false; } + void setup_pointer_frame_offset (); + private: TempoMarker* _marker; bool _copy; @@ -558,6 +591,8 @@ public: return false; } + void setup_pointer_frame_offset (); + private: EditorCursor* _cursor; ///< cursor being dragged bool _stop; ///< true to stop the transport on starting the drag, otherwise false @@ -578,6 +613,8 @@ public: bool y_movement_matters () const { return false; } + + void setup_pointer_frame_offset (); }; /** Region fade-out drag */ @@ -594,6 +631,8 @@ public: bool y_movement_matters () const { return false; } + + void setup_pointer_frame_offset (); }; /** Marker drag */ @@ -615,6 +654,8 @@ public: bool y_movement_matters () const { return false; } + + void setup_pointer_frame_offset (); private: void update_item (ARDOUR::Location *); @@ -758,6 +799,8 @@ public: void finished (GdkEvent *, bool); void aborted (); + void setup_pointer_frame_offset (); + private: Operation _operation; bool _copy; diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index a27d437274..e2298c42ad 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -1669,6 +1669,31 @@ MidiRegionView::alter_program_change(PCEvent& old_program, const MIDI::Name::Pat } void +MidiRegionView::move_program_change (PCEvent pc, double t) +{ + boost::shared_ptr<Evoral::Control> control = _model->control (Evoral::Parameter (MidiPgmChangeAutomation, pc.channel, 0)); + assert (control); + + /* XXX: seems that these events should have IDs, or that this code should + at least be in ControlList. + */ + + boost::shared_ptr<Evoral::ControlList> list = control->list (); + Evoral::ControlList::iterator i = list->begin (); + while (i != list->end() && ((*i)->when != pc.time || (*i)->value != pc.value)) { + ++i; + } + + assert (i != list->end ()); + + list->erase (i); + list->add (t, pc.value); + + _pgm_changes.clear (); + display_program_changes (); +} + +void MidiRegionView::program_selected(CanvasProgramChange& program, const MIDI::Name::PatchPrimaryKey& new_patch) { PCEvent program_change_event(program.event_time(), program.program(), program.channel()); diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 2b07c02382..79a8405927 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -149,6 +149,8 @@ class MidiRegionView : public RegionView */ void alter_program_change(PCEvent& old_program, const MIDI::Name::PatchPrimaryKey& new_patch); + void move_program_change (PCEvent, double); + /** Alter a given program to the new given one. * (Called on context menu select on CanvasProgramChange) */ |