Allow dragging of program change flags in MIDI regions.
git-svn-id: svn://localhost/ardour2/branches/3.0@8303 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
ed0deee747
commit
570ed69d2a
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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,11 +1799,15 @@ 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)
|
||||
{
|
||||
|
@ -1892,10 +1895,15 @@ 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)
|
||||
{
|
||||
|
@ -1993,11 +2001,15 @@ 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)
|
||||
{
|
||||
|
@ -2071,12 +2083,19 @@ 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)
|
||||
{
|
||||
|
@ -2183,12 +2202,19 @@ 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)
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -2388,6 +2412,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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -3195,6 +3218,25 @@ SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
|
|||
_original_pointer_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ()).first->order ();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1668,6 +1668,31 @@ MidiRegionView::alter_program_change(PCEvent& old_program, const MIDI::Name::Pat
|
|||
display_program_changes (); // XXX would be nice to limit to just old_program.channel
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue