, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
- , pre_enter_cursor (0)
- , pre_press_cursor (0)
- , pre_note_enter_cursor (0)
- , _note_player (0)
{
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
_note_group->raise_to_top();
connect_to_diskstream ();
SelectionCleared.connect (_selection_cleared_connection, invalidator (*this), boost::bind (&MidiRegionView::selection_cleared, this, _1), gui_context ());
+
+ PublicEditor& editor (trackview.editor());
+ editor.get_selection().ClearMidiNoteSelection.connect (_clear_midi_selection_connection, invalidator (*this), boost::bind (&MidiRegionView::clear_midi_selection, this), gui_context ());
}
MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
- , pre_enter_cursor (0)
- , pre_press_cursor (0)
- , pre_note_enter_cursor (0)
- , _note_player (0)
{
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
_note_group->raise_to_top();
connect_to_diskstream ();
SelectionCleared.connect (_selection_cleared_connection, invalidator (*this), boost::bind (&MidiRegionView::selection_cleared, this, _1), gui_context ());
+
+ PublicEditor& editor (trackview.editor());
+ editor.get_selection().ClearMidiNoteSelection.connect (_clear_midi_selection_connection, invalidator (*this), boost::bind (&MidiRegionView::clear_midi_selection, this), gui_context ());
}
void
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
- , pre_enter_cursor (0)
- , pre_press_cursor (0)
- , pre_note_enter_cursor (0)
- , _note_player (0)
{
init (false);
}
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
- , pre_enter_cursor (0)
- , pre_press_cursor (0)
- , pre_note_enter_cursor (0)
- , _note_player (0)
{
init (true);
}
gui_context());
if (wfd) {
- midi_region()->midi_source(0)->load_model();
+ Glib::Threads::Mutex::Lock lm(midi_region()->midi_source(0)->mutex());
+ midi_region()->midi_source(0)->load_model(lm);
}
_model = midi_region()->midi_source(0)->model();
_enable_display = false;
- _fill_color_name = "midi frame base";
+ fill_color_name = "midi frame base";
RegionView::init (false);
boost::bind (&MidiRegionView::snap_changed, this),
gui_context());
+ trackview.editor().MouseModeChanged.connect(_mouse_mode_connection, invalidator (*this),
+ boost::bind (&MidiRegionView::mouse_mode_changed, this),
+ gui_context ());
+
Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&MidiRegionView::parameter_changed, this, _1), gui_context());
connect_to_diskstream ();
SelectionCleared.connect (_selection_cleared_connection, invalidator (*this), boost::bind (&MidiRegionView::selection_cleared, this, _1), gui_context ());
+
+ PublicEditor& editor (trackview.editor());
+ editor.get_selection().ClearMidiNoteSelection.connect (_clear_midi_selection_connection, invalidator (*this), boost::bind (&MidiRegionView::clear_midi_selection, this), gui_context ());
}
InstrumentInfo&
return RegionView::canvas_group_event (ev);
}
- const MouseMode m = trackview.editor().current_mouse_mode();
bool r;
switch (ev->type) {
// reset entered_regionview (among other things)
return RegionView::canvas_group_event (ev);
- case GDK_2BUTTON_PRESS:
- // cannot use double-click to exit internal mode if single-click is being used
- if ((m != MouseDraw) &&
- (m != MouseObject ||
- !Keyboard::modifier_state_contains (ev->button.state, Keyboard::insert_note_modifier()))) {
- return trackview.editor().toggle_internal_editing_from_double_click (ev);
- }
- break;
-
case GDK_SCROLL:
if (scroll (&ev->scroll)) {
return true;
case GDK_BUTTON_RELEASE:
r = button_release (&ev->button);
- delete _note_player;
- _note_player = 0;
+ _note_player.reset();
return r;
case GDK_MOTION_NOTIFY:
bool
MidiRegionView::enter_notify (GdkEventCrossing* ev)
{
- trackview.editor().MouseModeChanged.connect (
- _mouse_mode_connection, invalidator (*this), boost::bind (&MidiRegionView::mouse_mode_changed, this), gui_context ()
- );
-
enter_internal();
_entered = true;
bool
MidiRegionView::leave_notify (GdkEventCrossing*)
{
- _mouse_mode_connection.disconnect ();
-
leave_internal();
_entered = false;
void
MidiRegionView::mouse_mode_changed ()
{
- if (trackview.editor().internal_editing()) {
- // Switched in to internal editing mode while entered
- enter_internal();
- } else {
- // Switched out of internal editing mode while entered
- leave_internal();
+ // Adjust frame colour (become more transparent for internal tools)
+ set_frame_color();
+
+ if (_entered) {
+ if (trackview.editor().internal_editing()) {
+ // Switched in to internal editing mode while entered
+ enter_internal();
+ } else {
+ // Switched out of internal editing mode while entered
+ leave_internal();
+ }
}
}
Keyboard::magic_widget_grab_focus();
_grabbed_keyboard = true;
}
+
+ // Lower frame handles below notes so they don't steal events
+ if (frame_handle_start) {
+ frame_handle_start->lower_to_bottom();
+ }
+ if (frame_handle_end) {
+ frame_handle_end->lower_to_bottom();
+ }
}
void
Keyboard::magic_widget_drop_focus();
_grabbed_keyboard = false;
}
+
+ // Raise frame handles above notes so they catch events
+ if (frame_handle_start) {
+ frame_handle_start->raise_to_top();
+ }
+ if (frame_handle_end) {
+ frame_handle_end->raise_to_top();
+ }
}
bool
Editor* editor = dynamic_cast<Editor *> (&trackview.editor());
MouseMode m = editor->current_mouse_mode();
- if (m == MouseObject && Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier())) {
- pre_press_cursor = editor->get_canvas_cursor ();
- editor->set_canvas_cursor (editor->cursors()->midi_pencil);
+ if (m == MouseContent && Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier())) {
+ _press_cursor_ctx = CursorContext::create(*editor, editor->cursors()->midi_pencil);
}
if (_mouse_state != SelectTouchDragging) {
PublicEditor& editor = trackview.editor ();
- if (pre_press_cursor) {
- dynamic_cast<Editor*>(&editor)->set_canvas_cursor (pre_press_cursor, false);
- pre_press_cursor = 0;
- }
+ _press_cursor_ctx.reset();
switch (_mouse_state) {
case Pressed: // Clicked
clear_selection ();
break;
- case MouseObject:
+ case MouseContent:
case MouseTimeFX:
{
clear_selection();
{
PublicEditor& editor = trackview.editor ();
- if (!_ghost_note && editor.current_mouse_mode() == MouseObject &&
+ if (!_ghost_note && editor.current_mouse_mode() == MouseContent &&
Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier()) &&
_mouse_state != AddDragging) {
create_ghost_note (ev->x, ev->y);
- } else if (_ghost_note && editor.current_mouse_mode() == MouseObject &&
+ } else if (_ghost_note && editor.current_mouse_mode() == MouseContent &&
Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier())) {
update_ghost_note (ev->x, ev->y);
- } else if (_ghost_note && editor.current_mouse_mode() == MouseObject) {
+ } else if (_ghost_note && editor.current_mouse_mode() == MouseContent) {
remove_ghost_note ();
editor.verbose_cursor()->hide ();
MouseMode m = editor.current_mouse_mode();
- if (m == MouseDraw || (m == MouseObject && Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier()))) {
+ if (m == MouseDraw || (m == MouseContent && Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier()))) {
editor.drags()->set (new NoteCreateDrag (dynamic_cast<Editor *> (&editor), group, this), (GdkEvent *) ev);
_mouse_state = AddDragging;
remove_ghost_note ();
editor.verbose_cursor()->hide ();
return true;
- } else if (m == MouseObject) {
+ } else if (m == MouseContent) {
editor.drags()->set (new MidiRubberbandSelectDrag (dynamic_cast<Editor *> (&editor), this), (GdkEvent *) ev);
if (!Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
clear_selection ();
bool have_periodic_system_messages = false;
bool display_periodic_messages = true;
- if (!Config->get_never_display_periodic_midi()) {
+ if (!ARDOUR_UI::config()->get_never_display_periodic_midi()) {
for (MidiModel::SysExes::const_iterator i = _model->sysexes().begin(); i != _model->sysexes().end(); ++i) {
const boost::shared_ptr<const Evoral::MIDIEvent<Evoral::MusicalTime> > mev =
for (unsigned i=0; i < 128; ++i) {
if (_active_notes[i]) {
- _active_notes[i]->set_x1 (trackview.editor().sample_to_pixel(_region->length()));
+ _active_notes[i]->set_x1(
+ trackview.editor().sample_to_pixel(_region->position() + _region->length()));
}
}
}
void
MidiRegionView::play_midi_note(boost::shared_ptr<NoteType> note)
{
- if (_no_sound_notes || !Config->get_sound_midi_notes()) {
+ if (_no_sound_notes || !ARDOUR_UI::config()->get_sound_midi_notes()) {
return;
}
void
MidiRegionView::start_playing_midi_note(boost::shared_ptr<NoteType> note)
{
- if (_no_sound_notes || !Config->get_sound_midi_notes()) {
- return;
- }
-
- RouteUI* route_ui = dynamic_cast<RouteUI*> (&trackview);
-
- if (!route_ui || !route_ui->midi_track()) {
- return;
- }
-
- delete _note_player;
- _note_player = new NotePlayer (route_ui->midi_track ());
- _note_player->add (note);
- _note_player->on ();
+ const std::vector< boost::shared_ptr<NoteType> > notes(1, note);
+ start_playing_midi_chord(notes);
}
void
MidiRegionView::start_playing_midi_chord (vector<boost::shared_ptr<NoteType> > notes)
{
- if (_no_sound_notes || !Config->get_sound_midi_notes()) {
+ if (_no_sound_notes || !ARDOUR_UI::config()->get_sound_midi_notes()) {
return;
}
return;
}
- delete _note_player;
- _note_player = new NotePlayer (route_ui->midi_track());
+ _note_player = boost::shared_ptr<NotePlayer>(new NotePlayer(route_ui->midi_track()));
for (vector<boost::shared_ptr<NoteType> >::iterator n = notes.begin(); n != notes.end(); ++n) {
_note_player->add (*n);
/* outline all edges */
ev->set_outline_all ();
}
-
+
+ // Update color in case velocity has changed
+ ev->set_fill_color(ev->base_color());
+ ev->set_outline_color(ev->calculate_outline(ev->base_color(), ev->selected()));
+
if (update_ghost_regions) {
for (std::vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
MidiGhostRegion* gr = dynamic_cast<MidiGhostRegion*> (*i);
}
if (i != _model->patch_changes().end() && patch_applies(*i, time, channel)) {
- key.bank_number = (*i)->bank();
- key.program_number = (*i)->program ();
+ key.set_bank((*i)->bank());
+ key.set_program((*i)->program ());
} else {
- key.bank_number = key.program_number = 0;
- }
-
- if (!key.is_sane()) {
- error << string_compose(_("insane MIDI patch key %1:%2"),
- key.bank_number, key.program_number) << endmsg;
+ key.set_bank(0);
+ key.set_program(0);
}
}
{
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("alter patch change"));
- if (pc.patch()->program() != new_patch.program_number) {
- c->change_program (pc.patch (), new_patch.program_number);
+ if (pc.patch()->program() != new_patch.program()) {
+ c->change_program (pc.patch (), new_patch.program());
}
- int const new_bank = new_patch.bank_number;
+ int const new_bank = new_patch.bank();
if (pc.patch()->bank() != new_bank) {
c->change_bank (pc.patch (), new_bank);
}
}
void
-MidiRegionView::previous_patch (PatchChange& patch)
+MidiRegionView::step_patch (PatchChange& patch, bool bank, int delta)
{
- if (patch.patch()->program() < 127) {
- MIDI::Name::PatchPrimaryKey key = patch_change_to_patch_key (patch.patch());
- key.program_number++;
- change_patch_change (patch, key);
- }
-}
-
-void
-MidiRegionView::next_patch (PatchChange& patch)
-{
- if (patch.patch()->program() > 0) {
- MIDI::Name::PatchPrimaryKey key = patch_change_to_patch_key (patch.patch());
- key.program_number--;
- change_patch_change (patch, key);
- }
-}
-
-void
-MidiRegionView::next_bank (PatchChange& patch)
-{
- if (patch.patch()->program() < 127) {
- MIDI::Name::PatchPrimaryKey key = patch_change_to_patch_key (patch.patch());
- if (key.bank_number > 0) {
- key.bank_number--;
- change_patch_change (patch, key);
- }
- }
-}
-
-void
-MidiRegionView::previous_bank (PatchChange& patch)
-{
- if (patch.patch()->program() > 0) {
- MIDI::Name::PatchPrimaryKey key = patch_change_to_patch_key (patch.patch());
- if (key.bank_number < 127) {
- key.bank_number++;
- change_patch_change (patch, key);
- }
+ MIDI::Name::PatchPrimaryKey key = patch_change_to_patch_key(patch.patch());
+ if (bank) {
+ key.set_bank(key.bank() + delta);
+ } else {
+ key.set_program(key.program() + delta);
}
+ change_patch_change(patch, key);
}
void
(*i)->move_event(dx, dy);
}
- if (dy && !_selection.empty() && !_no_sound_notes && Config->get_sound_midi_notes()) {
+ if (dy && !_selection.empty() && !_no_sound_notes && ARDOUR_UI::config()->get_sound_midi_notes()) {
if (to_play.size() > 1) {
{
Editor* editor = dynamic_cast<Editor*>(&trackview.editor());
- pre_note_enter_cursor = editor->get_canvas_cursor ();
-
if (_mouse_state == SelectTouchDragging) {
note_selected (ev, true);
+ } else if (editor->current_mouse_mode() == MouseContent) {
+ show_verbose_cursor (ev->note ());
+ } else if (editor->current_mouse_mode() == MouseDraw) {
+ show_verbose_cursor (ev->note ());
}
-
- show_verbose_cursor (ev->note ());
}
void
}
editor->verbose_cursor()->hide ();
-
- if (pre_note_enter_cursor) {
- editor->set_canvas_cursor (pre_note_enter_cursor);
- pre_note_enter_cursor = 0;
- }
}
void
{
Editor* editor = dynamic_cast<Editor*>(&trackview.editor());
Editing::MouseMode mm = editor->current_mouse_mode();
- bool trimmable = (mm == MouseObject || mm == MouseTimeFX || mm == MouseDraw);
+ bool trimmable = (mm == MouseContent || mm == MouseTimeFX || mm == MouseDraw);
- if (can_set_cursor) {
+ Editor::EnterContext* ctx = editor->get_enter_context(NoteItem);
+ if (can_set_cursor && ctx) {
if (trimmable && x_fraction > 0.0 && x_fraction < 0.2) {
- editor->set_canvas_cursor (editor->cursors()->left_side_trim);
+ ctx->cursor_ctx->change(editor->cursors()->left_side_trim);
} else if (trimmable && x_fraction >= 0.8 && x_fraction < 1.0) {
- editor->set_canvas_cursor (editor->cursors()->right_side_trim);
- } else if (pre_note_enter_cursor) {
- editor->set_canvas_cursor (pre_note_enter_cursor);
+ ctx->cursor_ctx->change(editor->cursors()->right_side_trim);
+ } else {
+ ctx->cursor_ctx->change(editor->cursors()->grabber_note);
}
}
}
-void
-MidiRegionView::set_frame_color()
+uint32_t
+MidiRegionView::get_fill_color() const
{
- uint32_t f;
-
- TimeAxisViewItem::set_frame_color ();
-
- if (!frame) {
- return;
- }
-
+ const std::string mod_name = (_dragging ? "dragging region" :
+ trackview.editor().internal_editing() ? "editable region" :
+ "midi frame base");
if (_selected) {
- f = ARDOUR_UI::config()->color ("selected region base");
+ return ARDOUR_UI::config()->color_mod ("selected region base", mod_name);
} else if (high_enough_for_name || !ARDOUR_UI::config()->get_color_regions_using_track_color()) {
- f = ARDOUR_UI::config()->color_mod ("midi frame base", "midi frame base");
- } else {
- f = fill_color;
- }
-
- if (!rect_visible) {
- f = UINT_RGBA_CHANGE_A (f, 80);
+ return ARDOUR_UI::config()->color_mod ("midi frame base", mod_name);
}
-
- frame->set_fill_color (f);
+ return ARDOUR_UI::config()->color_mod (fill_color, mod_name);
}
void
bool
MidiRegionView::paste (framepos_t pos, const ::Selection& selection, PasteContext& ctx)
{
- trackview.session()->begin_reversible_command (Operations::paste);
-
// Paste notes, if available
MidiNoteSelection::const_iterator m = selection.midi_notes.get_nth(ctx.counts.n_notes());
if (m != selection.midi_notes.end()) {
a->second->paste(pos, selection, ctx);
}
- trackview.session()->commit_reversible_command ();
-
return true;
}
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;
for (MidiBuffer::iterator i = buf->begin(); i != buf->end(); ++i) {
}
}
- /* ev.time() is in session frames, so (ev.time() - converter.origin_b()) is
- frames from the start of the source, and so time_beats is in terms of the
- source.
- */
-
- Evoral::MusicalTime const time_beats = converter.from (ev.time () - converter.origin_b ());
+ /* convert from session frames to source beats */
+ Evoral::MusicalTime const time_beats = _source_relative_time_converter.from(ev.time());
if (ev.type() == MIDI_CMD_NOTE_ON) {
boost::shared_ptr<NoteType> note (
get_patch_key_at(n->time(), n->channel(), patch_key);
name = device_names->note_name(mtv->gui_property(X_("midnam-custom-device-mode")),
n->channel(),
- patch_key.bank_number,
- patch_key.program_number,
+ patch_key.bank(),
+ patch_key.program(),
n->note());
}
}
void
MidiRegionView::note_button_release ()
{
- delete _note_player;
- _note_player = 0;
+ _note_player.reset();
}
ChannelMode