#include <sigc++/signal.h>
-#include <ardour/playlist.h>
-#include <ardour/tempo.h>
-#include <ardour/midi_region.h>
-#include <ardour/midi_source.h>
-#include <ardour/midi_diskstream.h>
-#include <ardour/midi_model.h>
-#include <ardour/midi_patch_manager.h>
+#include "ardour/playlist.h"
+#include "ardour/tempo.h"
+#include "ardour/midi_region.h"
+#include "ardour/midi_source.h"
+#include "ardour/midi_diskstream.h"
+#include "ardour/midi_model.h"
+#include "ardour/midi_patch_manager.h"
-#include <evoral/Parameter.hpp>
-#include <evoral/Control.hpp>
+#include "evoral/Parameter.hpp"
+#include "evoral/Control.hpp"
#include "streamview.h"
#include "midi_region_view.h"
using namespace ArdourCanvas;
MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv,
- boost::shared_ptr<MidiRegion> r, double spu, Gdk::Color& basic_color)
+ boost::shared_ptr<MidiRegion> r, double spu, Gdk::Color const & basic_color)
: RegionView (parent, tv, r, spu, basic_color)
, _force_channel(-1)
, _last_channel_selection(0xFFFF)
MidiRegionView::MidiRegionView (const MidiRegionView& other)
- : RegionView (other)
+ : sigc::trackable(other)
+ , RegionView (other)
, _force_channel(-1)
, _last_channel_selection(0xFFFF)
, _default_note_length(1.0)
}
void
-MidiRegionView::init (Gdk::Color& basic_color, bool wfd)
+MidiRegionView::init (Gdk::Color const & basic_color, bool wfd)
{
if (wfd) {
midi_region()->midi_source(0)->load_model();
bool
MidiRegionView::canvas_event(GdkEvent* ev)
{
- static bool delete_mod = false;
- static Editing::MidiEditMode original_mode;
+ PublicEditor& editor (trackview.editor());
+
+ if (!editor.internal_editing()) {
+ return false;
+ }
static double drag_start_x, drag_start_y;
static double last_x, last_y;
static ArdourCanvas::SimpleRect* drag_rect = NULL;
- if (trackview.editor().current_mouse_mode() != MouseNote)
- return false;
-
- const Editing::MidiEditMode midi_edit_mode = trackview.editor().current_midi_edit_mode();
-
switch (ev->type) {
case GDK_KEY_PRESS:
- if (ev->key.keyval == GDK_Delete && !delete_mod) {
- delete_mod = true;
- original_mode = midi_edit_mode;
- trackview.editor().set_midi_edit_mode(MidiEditErase);
- start_delta_command(_("erase notes"));
- _mouse_state = EraseTouchDragging;
- return true;
- } else if (ev->key.keyval == GDK_Shift_L || ev->key.keyval == GDK_Control_L) {
+ if (ev->key.keyval == GDK_Shift_L || ev->key.keyval == GDK_Control_L) {
_mouse_state = SelectTouchDragging;
return true;
} else if (ev->key.keyval == GDK_Escape) {
case GDK_KEY_RELEASE:
if (ev->key.keyval == GDK_Delete) {
- if (_mouse_state == EraseTouchDragging) {
- delete_selection();
- apply_command();
- }
- if (delete_mod) {
- trackview.editor().set_midi_edit_mode(original_mode);
- _mouse_state = None;
- delete_mod = false;
- }
+ delete_selection();
+ apply_command();
return true;
} else if (ev->key.keyval == GDK_Shift_L || ev->key.keyval == GDK_Control_L) {
_mouse_state = None;
return false;
case GDK_BUTTON_PRESS:
- if (_mouse_state != SelectTouchDragging &&
- _mouse_state != EraseTouchDragging &&
- ev->button.button == 1) {
+ if (_mouse_state != SelectTouchDragging && ev->button.button == 1) {
_pressed_button = ev->button.button;
_mouse_state = Pressed;
return true;
case Pressed: // Drag start
// Select drag start
- if (_pressed_button == 1 && midi_edit_mode == MidiEditSelect) {
+ if (_pressed_button == 1 && editor.current_mouse_mode() == MouseRange) {
group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
last_x = event_x;
return true;
// Add note drag start
- } else if (midi_edit_mode == MidiEditPencil) {
+ } else if (editor.current_mouse_mode() == MouseObject) {
group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
last_x = event_x;
last_x = event_x;
last_y = event_y;
- case EraseTouchDragging:
case SelectTouchDragging:
return false;
switch (_mouse_state) {
case Pressed: // Clicked
- switch (midi_edit_mode) {
- case MidiEditSelect:
- case MidiEditResize:
+ switch (editor.current_mouse_mode()) {
+ case MouseRange:
+ case MouseTimeFX:
clear_selection();
break;
- case MidiEditPencil:
+ case MouseObject:
create_note_at(event_x, event_y, _default_note_length);
default: break;
}
assert(note <= 127.0);
// Start of note in frames relative to region start
- nframes64_t start_frames = snap_to_frame(trackview.editor().pixel_to_frame(x));
+ nframes64_t start_frames = snap_frame_to_frame(trackview.editor().pixel_to_frame(x));
assert(start_frames >= 0);
// Snap length
length = frames_to_beats(
- snap_to_frame(start_frames + beats_to_frames(length)) - start_frames);
+ snap_frame_to_frame(start_frames + beats_to_frames(length)) - start_frames);
const boost::shared_ptr<NoteType> new_note(new NoteType(0,
frames_to_beats(start_frames + _region->start()), length,
}
void
-MidiRegionView::command_add_note(const boost::shared_ptr<NoteType> note, bool selected)
+MidiRegionView::command_add_note(const boost::shared_ptr<NoteType> note, bool selected, bool show_velocity)
{
if (_delta_command) {
_delta_command->add(note);
if (selected) {
_marked_for_selection.insert(note);
}
+ if (show_velocity) {
+ _marked_for_velocity.insert(note);
+ }
}
void
midi_view()->midi_track()->diskstream()->playlist_modified();
_marked_for_selection.clear();
+ _marked_for_velocity.clear();
}
midi_stream_view()->highest_note(),
height != old_height + FUDGE);
- if (name_text) {
- name_text->raise_to_top();
+ if (name_pixbuf) {
+ name_pixbuf->raise_to_top();
}
}
item->show();
}
- event->hide_velocity();
if (CanvasNote* note = dynamic_cast<CanvasNote*>(event)) {
const double y1 = midi_stream_view()->note_to_y(event->note()->note());
const double y2 = y1 + floor(midi_stream_view()->note_height());
hit->move(x-hit->x1(), y-hit->y1());
hit->show();
}
- if (event->selected()) {
- event->show_velocity();
- }
}
}
}
GhostRegion*
MidiRegionView::add_ghost (TimeAxisView& tv)
{
- RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&trackview);
CanvasNote* note;
- assert(rtv);
double unit_position = _region->position () / samples_per_unit;
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(&tv);
delete[] _active_notes;
_active_notes = NULL;
_marked_for_selection.clear();
+ _marked_for_velocity.clear();
}
if (_marked_for_selection.find(note) != _marked_for_selection.end()) {
note_selected(event, true);
}
+ if (_marked_for_velocity.find(note) != _marked_for_velocity.end()) {
+ event->show_velocity();
+ }
event->on_channel_selection_change(_last_channel_selection);
_events.push_back(event);
if (note_in_visible_range(note)) {
void
MidiRegionView::delete_selection()
{
- assert(_delta_command);
+ if (_selection.empty()) {
+ return;
+ }
+
+ if (!_delta_command) {
+ _delta_command = _model->new_delta_command("delete selection");
+ }
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
if ((*i)->selected()) {
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
if ((*i)->selected() && (*i) != ev) {
(*i)->selected(false);
+ (*i)->hide_velocity();
}
}
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
if ((*i) != ev) {
(*i)->selected(false);
+ (*i)->hide_velocity();
}
}
void
MidiRegionView::move_selection(double dx, double dy)
{
- for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i)
+ for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
(*i)->move_event(dx, dy);
+ }
}
const boost::shared_ptr<NoteType> copy(new NoteType(*(*i)->note().get()));
- // we need to snap here again in nframes64_t in order to be sample accurate
- double start_frames = snap_to_frame(beats_to_frames((*i)->note()->time()) + dt);
-
- // keep notes inside region if dragged beyond left region bound
- if (start_frames < _region->start()) {
- start_frames = _region->start();
+ nframes64_t start_frames = beats_to_frames((*i)->note()->time());
+ if (dt >= 0) {
+ start_frames += snap_frame_to_frame(trackview.editor().pixel_to_frame(dt));
+ } else {
+ start_frames -= snap_frame_to_frame(trackview.editor().pixel_to_frame(-dt));
}
-
+
copy->set_time(frames_to_beats(start_frames));
uint8_t original_pitch = (*i)->note()->note();
- uint8_t new_pitch = original_pitch + dnote - highest_note_difference;
+ uint8_t new_pitch = original_pitch + dnote - highest_note_difference;
// keep notes in standard midi range
clamp_to_0_127(new_pitch);
}
nframes64_t
-MidiRegionView::snap_to_frame(double x)
+MidiRegionView::snap_pixel_to_frame(double x)
{
- PublicEditor &editor = trackview.editor();
+ PublicEditor& editor = trackview.editor();
// x is region relative, convert it to global absolute frames
nframes64_t frame = editor.pixel_to_frame(x) + _region->position();
editor.snap_to(frame);
}
nframes64_t
-MidiRegionView::snap_to_frame(nframes64_t x)
+MidiRegionView::snap_frame_to_frame(nframes64_t x)
{
- PublicEditor &editor = trackview.editor();
- // x is region relative
- // convert x to global frame
+ PublicEditor& editor = trackview.editor();
+ // x is region relative, convert it to global absolute frames
nframes64_t frame = x + _region->position();
editor.snap_to(frame);
- // convert event_frame back to local coordinates relative to position
- frame -= _region->position();
- return frame;
+ return frame - _region->position(); // convert back to region relative
}
double
MidiRegionView::snap_to_pixel(double x)
{
- return (double) trackview.editor().frame_to_pixel(snap_to_frame(x));
+ return (double) trackview.editor().frame_to_pixel(snap_pixel_to_frame(x));
}
double
// because snapping works on world coordinates we have to transform current_x
// to world coordinates before snapping and transform it back afterwards
- nframes64_t current_frame = snap_to_frame(current_x);
+ nframes64_t current_frame = snap_pixel_to_frame(current_x);
// transform to region start relative
current_frame += _region->start();
}
command_remove_note(event);
- command_add_note(copy, event->selected());
+ command_add_note(copy, event->selected(), true);
}
void
void
MidiRegionView::note_entered(ArdourCanvas::CanvasNoteEvent* ev)
{
- if (ev->note() && _mouse_state == EraseTouchDragging) {
- start_delta_command(_("note entered"));
- ev->selected(true);
- _delta_command->remove(ev->note());
- } else if (_mouse_state == SelectTouchDragging) {
+ if (_mouse_state == SelectTouchDragging) {
note_selected(ev, true);
}
}