summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2010-12-20 03:42:59 +0000
committerCarl Hetherington <carl@carlh.net>2010-12-20 03:42:59 +0000
commit570ed69d2a791486a907b62ee2336a3953a7a1c0 (patch)
treeca759d0dfc198a81fbd4bb544febffe7b2039138
parented0deee74775ff2b7830f7461c90fc6423b8520e (diff)
Allow dragging of program change flags in MIDI regions.
git-svn-id: svn://localhost/ardour2/branches/3.0@8303 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/canvas-program-change.cc17
-rw-r--r--gtk2_ardour/canvas-program-change.h19
-rw-r--r--gtk2_ardour/editor_drag.cc142
-rw-r--r--gtk2_ardour/editor_drag.h45
-rw-r--r--gtk2_ardour/midi_region_view.cc25
-rw-r--r--gtk2_ardour/midi_region_view.h2
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)
*/