using namespace ArdourCanvas;
using Gtkmm2ext::Keyboard;
+PBD::Signal1<void, MidiRegionView *> MidiRegionView::SelectionCleared;
+
#define MIDI_BP_ZERO ((Config->get_first_midi_bank_is_zero())?0:1)
MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv,
Config->ParameterChanged.connect (*this, invalidator (*this), ui_bind (&MidiRegionView::parameter_changed, this, _1), gui_context());
connect_to_diskstream ();
+
+ SelectionCleared.connect (_selection_cleared_connection, invalidator (*this), ui_bind (&MidiRegionView::selection_cleared, this, _1), gui_context ());
}
MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv,
PublicEditor::DropDownKeys.connect (sigc::mem_fun (*this, &MidiRegionView::drop_down_keys));
connect_to_diskstream ();
+
+ SelectionCleared.connect (_selection_cleared_connection, invalidator (*this), ui_bind (&MidiRegionView::selection_cleared, this, _1), gui_context ());
}
void
Config->ParameterChanged.connect (*this, invalidator (*this), ui_bind (&MidiRegionView::parameter_changed, this, _1), gui_context());
connect_to_diskstream ();
+
+ 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
}
bool
-MidiRegionView::leave_notify (GdkEventCrossing* ev)
+MidiRegionView::leave_notify (GdkEventCrossing*)
{
_mouse_mode_connection.disconnect ();
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;
}
void
-MidiRegionView::clear_selection_except (ArdourCanvas::CanvasNoteEvent* ev)
+MidiRegionView::clear_selection_except (ArdourCanvas::CanvasNoteEvent* ev, bool signal)
{
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
if ((*i) != ev) {
/* this does not change the status of this regionview w.r.t the editor
selection.
*/
+
+ if (signal) {
+ SelectionCleared (this); /* EMIT SIGNAL */
+ }
}
void
}
}
+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)
{
// keep notes in standard midi range
clamp_to_0_127(new_pitch);
- // keep original pitch if note is dragged outside valid midi range
- if ((original_pitch != 0 && new_pitch == 0)
- || (original_pitch != 127 && new_pitch == 127)) {
- new_pitch = original_pitch;
- }
-
lowest_note_in_selection = std::min(lowest_note_in_selection, new_pitch);
highest_note_in_selection = std::max(highest_note_in_selection, new_pitch);
}
}
+/** @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));
}
-/** Snap a frame offset within our region using the current snap settings.
- * @param x Frame offset from this region's position.
- * @return Snapped frame offset from this region's position.
+/** @param x Pixel relative to the region position.
+ * @return Snapped pixel relative to the region position.
*/
-frameoffset_t
-MidiRegionView::snap_frame_to_frame (frameoffset_t x) const
-{
- PublicEditor& editor = trackview.editor();
-
- /* x is region relative, convert it to global absolute frames */
- framepos_t const session_frame = x + _region->position();
-
- /* try a snap in either direction */
- framepos_t frame = session_frame;
- editor.snap_to (frame, 0);
-
- /* if we went off the beginning of the region, snap forwards */
- if (frame < _region->position ()) {
- frame = session_frame;
- editor.snap_to (frame, 1);
- }
-
- /* back to region relative */
- return frame - _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()) {
double length = region_frames_to_region_beats (snap_frame_to_frame (f + grid_frames) - f);
/* note that this sets the time of the ghost note in beats relative to
- the start of the region.
+ the start of the source; that is how all note times are stored.
*/
- _ghost_note->note()->set_time (region_frames_to_region_beats (f));
+ _ghost_note->note()->set_time (absolute_frames_to_source_beats (f + _region->position ()));
_ghost_note->note()->set_length (length);
_ghost_note->note()->set_note (midi_stream_view()->y_to_note (y));
_ghost_note->note()->set_channel (mtv->get_channel_for_add ());
return snap_frame_to_frame (p);
}
+
+/** Called when the selection has been cleared in any MidiRegionView.
+ * @param rv MidiRegionView that the selection was cleared in.
+ */
+void
+MidiRegionView::selection_cleared (MidiRegionView* rv)
+{
+ if (rv == this) {
+ return;
+ }
+
+ /* Clear our selection in sympathy; but don't signal the fact */
+ clear_selection (false);
+}