#include "canvas_patch_change.h"
#include "debug.h"
#include "editor.h"
+#include "editor_drag.h"
#include "ghostregion.h"
#include "gui_thread.h"
#include "keyboard.h"
SelectionCleared.connect (_selection_cleared_connection, invalidator (*this), ui_bind (&MidiRegionView::selection_cleared, this, _1), gui_context ());
}
+const boost::shared_ptr<ARDOUR::MidiRegion>
+MidiRegionView::midi_region() const
+{
+ return boost::dynamic_pointer_cast<ARDOUR::MidiRegion>(_region);
+}
+
void
MidiRegionView::connect_to_diskstream ()
{
midi_view()->midi_track()->DataRecorded.connect(
*this, invalidator(*this),
- ui_bind(&MidiRegionView::data_recorded, this, _1, _2),
+ ui_bind(&MidiRegionView::data_recorded, this, _1),
gui_context());
}
}
bool
-MidiRegionView::leave_notify (GdkEventCrossing* ev)
+MidiRegionView::leave_notify (GdkEventCrossing*)
{
_mouse_mode_connection.disconnect ();
group->w2i(event_x, event_y);
group->ungrab(ev->time);
+ PublicEditor& editor = trackview.editor ();
+
switch (_mouse_state) {
case Pressed: // Clicked
- switch (trackview.editor().current_mouse_mode()) {
+ switch (editor.current_mouse_mode()) {
case MouseObject:
case MouseTimeFX:
{
group->w2i(event_x, event_y);
bool success;
- Evoral::MusicalTime beats = trackview.editor().get_grid_type_as_beats (success, trackview.editor().pixel_to_frame (event_x));
+ Evoral::MusicalTime beats = editor.get_grid_type_as_beats (success, editor.pixel_to_frame (event_x));
if (!success) {
beats = 1;
case MouseRange:
{
bool success;
- Evoral::MusicalTime beats = trackview.editor().get_grid_type_as_beats (success, trackview.editor().pixel_to_frame (event_x));
+ Evoral::MusicalTime beats = editor.get_grid_type_as_beats (success, editor.pixel_to_frame (event_x));
if (!success) {
beats = 1;
break;
case SelectRectDragging: // Select drag done
-
+ editor.drags()->end_grab ((GdkEvent *) ev);
_mouse_state = None;
- delete _drag_rect;
- _drag_rect = 0;
break;
case AddDragging: // Add drag done
if (_pressed_button == 1 && editor.current_mouse_mode() == MouseObject
&& !Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier())) {
- // Select drag start
-
- group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
- Gdk::Cursor(Gdk::FLEUR), ev->time);
-
- _last_x = event_x;
- _last_y = event_y;
- _drag_start_x = event_x;
- _drag_start_y = event_y;
-
- _drag_rect = new ArdourCanvas::SimpleRect(*group);
- _drag_rect->property_x1() = event_x;
- _drag_rect->property_y1() = event_y;
- _drag_rect->property_x2() = event_x;
- _drag_rect->property_y2() = event_y;
- _drag_rect->property_outline_what() = 0xFF;
- _drag_rect->property_outline_color_rgba()
- = ARDOUR_UI::config()->canvasvar_MidiSelectRectOutline.get();
- _drag_rect->property_fill_color_rgba()
- = ARDOUR_UI::config()->canvasvar_MidiSelectRectFill.get();
+ editor.drags()->set (new MidiRubberbandSelectDrag (dynamic_cast<Editor *> (&editor), this), (GdkEvent *) ev);
_mouse_state = SelectRectDragging;
return true;
return false;
- case SelectRectDragging: // Select drag motion
+ case SelectRectDragging:
+ editor.drags()->motion_handler ((GdkEvent *) ev, false);
+ break;
+
case AddDragging: // Add note drag motion
if (ev->is_hint) {
}
}
- if (_drag_rect && _mouse_state == SelectRectDragging) {
-
- if (event_y > _drag_start_y) {
- _drag_rect->property_y2() = event_y;
- }
- else {
- _drag_rect->property_y1() = event_y;
- }
-
- update_drag_selection(_drag_start_x, event_x, _drag_start_y, event_y, Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
- }
-
_last_x = event_x;
_last_y = event_y;
return false;
}
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
+ /* XXX: bit of a hack; allow PrimaryModifier scroll through so that
+ it still works for zoom.
+ */
+ return false;
+ }
+
trackview.editor().verbose_cursor()->hide ();
bool fine = !Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier);
MidiRegionView::channel_edit ()
{
bool first = true;
- uint8_t current_channel;
+ uint8_t current_channel = 0;
if (_selection.empty()) {
return;
for (Events::iterator i = _events.begin(); i != _events.end(); ) {
if (!(*i)->valid ()) {
+
+ for (vector<GhostRegion*>::iterator j = ghosts.begin(); j != ghosts.end(); ++j) {
+ MidiGhostRegion* gr = dynamic_cast<MidiGhostRegion*> (*j);
+ if (gr) {
+ gr->remove_note (*i);
+ }
+ }
+
delete *i;
i = _events.erase (i);
+
} else {
++i;
}
}
}
+void
+MidiRegionView::select_range (framepos_t start, framepos_t end)
+{
+ clear_selection ();
+
+ for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
+ framepos_t t = source_beats_to_absolute_frames((*i)->note()->time());
+ if (t >= start && t <= end) {
+ add_to_selection (*i);
+ }
+ }
+}
+
+void
+MidiRegionView::invert_selection ()
+{
+ for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
+ if ((*i)->selected()) {
+ remove_from_selection(*i);
+ } else {
+ add_to_selection (*i);
+ }
+ }
+}
+
void
MidiRegionView::select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend)
{
}
}
+/** @param x Pixel relative to the region position.
+ * @return Snapped frame relative to the region position.
+ */
framepos_t
MidiRegionView::snap_pixel_to_frame(double x)
{
return snap_frame_to_frame (editor.pixel_to_frame (x));
}
+/** @param x Pixel relative to the region position.
+ * @return Snapped pixel relative to the region position.
+ */
double
MidiRegionView::snap_to_pixel(double x)
{
double beats;
beats = snap_pixel_to_frame (current_x);
- /* XXX not sure this is correct - snap_pixel_to_frame()
- returns an absolute frame.
- */
beats = region_frames_to_region_beats (beats);
double len;
}
}
- /* Convert that to a frame within the region */
+ /* Convert that to a frame within the source */
current_x = snap_pixel_to_frame (current_x) + _region->start ();
/* and then to beats */
- /* XXX not sure this is correct - snap_pixel_to_frame()
- returns an absolute frame.
- */
current_x = region_frames_to_region_beats (current_x);
if (at_front && current_x < canvas_note->note()->end_time()) {
time_sort_events ();
+ MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
+ uint16_t const channel_mask = mtv->channel_selector().get_selected_channels ();
+
for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
if ((*i)->selected()) {
use_next = true;
continue;
} else if (use_next) {
- if (!add_to_selection) {
- unique_select (*i);
- } else {
- note_selected (*i, true, false);
+ if (channel_mask & (1 << (*i)->note()->channel())) {
+ if (!add_to_selection) {
+ unique_select (*i);
+ } else {
+ note_selected (*i, true, false);
+ }
+ return;
}
- return;
}
}
/* use the first one */
- unique_select (_events.front());
-
+ if (!_events.empty() && (channel_mask & (1 << _events.front()->note()->channel ()))) {
+ unique_select (_events.front());
+ }
}
void
time_sort_events ();
+ MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
+ uint16_t const channel_mask = mtv->channel_selector().get_selected_channels ();
+
for (Events::reverse_iterator i = _events.rbegin(); i != _events.rend(); ++i) {
if ((*i)->selected()) {
use_next = true;
continue;
} else if (use_next) {
- if (!add_to_selection) {
- unique_select (*i);
- } else {
- note_selected (*i, true, false);
+ if (channel_mask & (1 << (*i)->note()->channel())) {
+ if (!add_to_selection) {
+ unique_select (*i);
+ } else {
+ note_selected (*i, true, false);
+ }
+ return;
}
- return;
}
}
/* use the last one */
- unique_select (*(_events.rbegin()));
+ if (!_events.empty() && (channel_mask & (1 << (*_events.rbegin())->note()->channel ()))) {
+ unique_select (*(_events.rbegin()));
+ }
}
void
}
/** Called when a diskstream on our track has received some data. Update the view, if applicable.
- * @param buf Data that has been recorded.
- * @param w Source that this data will end up in.
+ * @param w Source that the data will end up in.
*/
void
-MidiRegionView::data_recorded (boost::shared_ptr<MidiBuffer> buf, boost::weak_ptr<MidiSource> w)
+MidiRegionView::data_recorded (boost::weak_ptr<MidiSource> w)
{
if (!_active_notes) {
/* we aren't actively being recorded to */
}
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (&trackview);
+
+ boost::shared_ptr<MidiBuffer> buf = mtv->midi_track()->get_gui_feed_buffer ();
+
BeatsFramesConverter converter (trackview.session()->tempo_map(), mtv->midi_track()->get_capture_start_frame (0));
framepos_t back = max_framepos;