diff options
Diffstat (limited to 'gtk2_ardour/midi_time_axis.cc')
-rw-r--r-- | gtk2_ardour/midi_time_axis.cc | 440 |
1 files changed, 55 insertions, 385 deletions
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index 3eb7fff692..62beda8774 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -80,8 +80,8 @@ #include "region_view.h" #include "rgb_macros.h" #include "selection.h" +#include "step_editor.h" #include "simplerect.h" -#include "step_entry.h" #include "utils.h" #include "ardour/midi_track.h" @@ -116,7 +116,6 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session* sess, , _midi_thru_item (0) , default_channel_menu (0) , controller_menu (0) - , step_editor (0) { subplugin_menu.set_name ("ArdourContextMenu"); @@ -127,8 +126,6 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session* sess, mute_button->set_active (false); solo_button->set_active (false); - step_edit_insert_position = 0; - if (is_midi_track()) { controls_ebox.set_name ("MidiTimeAxisViewControlsBaseUnselected"); _note_mode = midi_track()->note_mode(); @@ -168,11 +165,6 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session* sess, _view->RegionViewAdded.connect (sigc::mem_fun(*this, &MidiTimeAxisView::region_view_added)); _view->attach (); - midi_track()->PlaylistChanged.connect (*this, invalidator (*this), - boost::bind (&MidiTimeAxisView::playlist_changed, this), - gui_context()); - playlist_changed (); - } HBox* midi_controls_hbox = manage(new HBox()); @@ -235,35 +227,17 @@ MidiTimeAxisView::~MidiTimeAxisView () _range_scroomer = 0; delete controller_menu; + delete _step_editor; } void -MidiTimeAxisView::playlist_changed () +MidiTimeAxisView::check_step_edit () { - step_edit_region_connection.disconnect (); - midi_track()->playlist()->RegionRemoved.connect (step_edit_region_connection, invalidator (*this), - ui_bind (&MidiTimeAxisView::region_removed, this, _1), - gui_context()); + _step_editor->check_step_edit (); } -void -MidiTimeAxisView::region_removed (boost::weak_ptr<Region> wr) -{ - boost::shared_ptr<Region> r (wr.lock()); - - if (!r) { - return; - } - - if (step_edit_region == r) { - step_edit_region.reset(); - step_edit_region_view = 0; - // force a recompute of the insert position - step_edit_beat_pos = -1.0; - } -} - -void MidiTimeAxisView::model_changed() +void +MidiTimeAxisView::model_changed() { std::list<std::string> device_modes = MIDI::Name::MidiPatchManager::instance() .custom_device_mode_names_by_model(_model_selector.get_active_text()); @@ -892,360 +866,7 @@ MidiTimeAxisView::route_active_changed () } } -void -MidiTimeAxisView::start_step_editing () -{ - _step_edit_triplet_countdown = 0; - _step_edit_within_chord = 0; - _step_edit_chord_duration = 0.0; - step_edit_region.reset (); - step_edit_region_view = 0; - - resync_step_edit_position (); - prepare_step_edit_region (); - reset_step_edit_beat_pos (); - - assert (step_edit_region); - assert (step_edit_region_view); - - if (step_editor == 0) { - step_editor = new StepEntry (*this); - step_editor->signal_delete_event().connect (sigc::mem_fun (*this, &MidiTimeAxisView::step_editor_hidden)); - step_editor->signal_hide().connect (sigc::mem_fun (*this, &MidiTimeAxisView::step_editor_hide)); - } - - step_edit_region_view->show_step_edit_cursor (step_edit_beat_pos); - step_edit_region_view->set_step_edit_cursor_width (step_editor->note_length()); - - step_editor->set_position (WIN_POS_MOUSE); - step_editor->present (); -} - -void -MidiTimeAxisView::resync_step_edit_position () -{ - step_edit_insert_position = _editor.get_preferred_edit_position (); -} - -void -MidiTimeAxisView::resync_step_edit_to_edit_point () -{ - resync_step_edit_position (); - if (step_edit_region) { - reset_step_edit_beat_pos (); - } -} - -void -MidiTimeAxisView::prepare_step_edit_region () -{ - boost::shared_ptr<Region> r = playlist()->top_region_at (step_edit_insert_position); - - if (r) { - step_edit_region = boost::dynamic_pointer_cast<MidiRegion>(r); - } - - if (step_edit_region) { - RegionView* rv = view()->find_view (step_edit_region); - step_edit_region_view = dynamic_cast<MidiRegionView*> (rv); - - } else { - step_edit_region = add_region (step_edit_insert_position); - RegionView* rv = view()->find_view (step_edit_region); - step_edit_region_view = dynamic_cast<MidiRegionView*>(rv); - } -} - - -void -MidiTimeAxisView::reset_step_edit_beat_pos () -{ - assert (step_edit_region); - assert (step_edit_region_view); - - framecnt_t frames_from_start = _editor.get_preferred_edit_position() - step_edit_region->position(); - - if (frames_from_start < 0) { - /* this can happen with snap enabled, and the edit point == Playhead. we snap the - position of the new region, and it can end up after the edit point. - */ - frames_from_start = 0; - } - - step_edit_beat_pos = step_edit_region_view->frames_to_beats (frames_from_start); - step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos); -} - -bool -MidiTimeAxisView::step_editor_hidden (GdkEventAny*) -{ - step_editor_hide (); - return true; -} - -void -MidiTimeAxisView::step_editor_hide () -{ - /* everything else will follow the change in the model */ - midi_track()->set_step_editing (false); -} - -void -MidiTimeAxisView::stop_step_editing () -{ - if (step_editor) { - step_editor->hide (); - } - - if (step_edit_region_view) { - step_edit_region_view->hide_step_edit_cursor(); - } - - step_edit_region.reset (); -} - -void -MidiTimeAxisView::check_step_edit () -{ - MidiRingBuffer<nframes_t>& incoming (midi_track()->step_edit_ring_buffer()); - uint8_t* buf; - uint32_t bufsize = 32; - - buf = new uint8_t[bufsize]; - - while (incoming.read_space()) { - nframes_t time; - Evoral::EventType type; - uint32_t size; - - incoming.read_prefix (&time, &type, &size); - - if (size > bufsize) { - delete [] buf; - bufsize = size; - buf = new uint8_t[bufsize]; - } - - incoming.read_contents (size, buf); - - if ((buf[0] & 0xf0) == MIDI_CMD_NOTE_ON) { - step_add_note (buf[0] & 0xf, buf[1], buf[2], 0.0); - } - } -} - -int -MidiTimeAxisView::step_add_bank_change (uint8_t channel, uint8_t bank) -{ - return 0; -} - -int -MidiTimeAxisView::step_add_program_change (uint8_t channel, uint8_t program) -{ - return 0; -} - -void -MidiTimeAxisView::step_edit_sustain (Evoral::MusicalTime beats) -{ - if (step_edit_region_view) { - step_edit_region_view->step_sustain (beats); - } -} - -void -MidiTimeAxisView::move_step_edit_beat_pos (Evoral::MusicalTime beats) -{ - if (beats > 0.0) { - step_edit_beat_pos = min (step_edit_beat_pos + beats, - step_edit_region_view->frames_to_beats (step_edit_region->length())); - } else if (beats < 0.0) { - if (beats < step_edit_beat_pos) { - step_edit_beat_pos += beats; // its negative, remember - } else { - step_edit_beat_pos = 0; - } - } - step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos); -} - -int -MidiTimeAxisView::step_add_note (uint8_t channel, uint8_t pitch, uint8_t velocity, Evoral::MusicalTime beat_duration) -{ - /* do these things in case undo removed the step edit region - */ - if (!step_edit_region) { - resync_step_edit_position (); - prepare_step_edit_region (); - reset_step_edit_beat_pos (); - step_edit_region_view->show_step_edit_cursor (step_edit_beat_pos); - step_edit_region_view->set_step_edit_cursor_width (step_editor->note_length()); - } - - assert (step_edit_region); - assert (step_edit_region_view); - - if (beat_duration == 0.0) { - bool success; - beat_duration = _editor.get_grid_type_as_beats (success, step_edit_insert_position); - - if (!success) { - return -1; - } - } - - MidiStreamView* msv = midi_view(); - - /* make sure its visible on the vertical axis */ - - if (pitch < msv->lowest_note() || pitch > msv->highest_note()) { - msv->update_note_range (pitch); - msv->set_note_range (MidiStreamView::ContentsRange); - } - - /* make sure its visible on the horizontal axis */ - - nframes64_t fpos = step_edit_region->position() + - step_edit_region_view->beats_to_frames (step_edit_beat_pos + beat_duration); - - if (fpos >= (_editor.leftmost_position() + _editor.current_page_frames())) { - _editor.reset_x_origin (fpos - (_editor.current_page_frames()/4)); - } - - step_edit_region_view->step_add_note (channel, pitch, velocity, step_edit_beat_pos, beat_duration); - - if (_step_edit_triplet_countdown > 0) { - _step_edit_triplet_countdown--; - - if (_step_edit_triplet_countdown == 0) { - _step_edit_triplet_countdown = 3; - } - } - - if (!_step_edit_within_chord) { - step_edit_beat_pos += beat_duration; - step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos); - } else { - step_edit_beat_pos += 1.0/Meter::ticks_per_beat; // tiny, but no longer overlapping - _step_edit_chord_duration = max (_step_edit_chord_duration, beat_duration); - } - - return 0; -} - -void -MidiTimeAxisView::set_step_edit_cursor_width (Evoral::MusicalTime beats) -{ - if (step_edit_region_view) { - step_edit_region_view->set_step_edit_cursor_width (beats); - } -} - -bool -MidiTimeAxisView::step_edit_within_triplet() const -{ - return _step_edit_triplet_countdown > 0; -} - -bool -MidiTimeAxisView::step_edit_within_chord() const -{ - return _step_edit_within_chord; -} - -void -MidiTimeAxisView::step_edit_toggle_triplet () -{ - if (_step_edit_triplet_countdown == 0) { - _step_edit_within_chord = false; - _step_edit_triplet_countdown = 3; - } else { - _step_edit_triplet_countdown = 0; - } -} - -void -MidiTimeAxisView::step_edit_toggle_chord () -{ - if (_step_edit_within_chord) { - _step_edit_within_chord = false; - step_edit_beat_pos += _step_edit_chord_duration; - step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos); - } else { - _step_edit_triplet_countdown = 0; - _step_edit_within_chord = true; - } -} - -void -MidiTimeAxisView::step_edit_rest (Evoral::MusicalTime beats) -{ - bool success; - - if (beats == 0.0) { - beats = _editor.get_grid_type_as_beats (success, step_edit_insert_position); - } else { - success = true; - } - - if (success) { - step_edit_beat_pos += beats; - step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos); - } -} - -void -MidiTimeAxisView::step_edit_beat_sync () -{ - step_edit_beat_pos = ceil (step_edit_beat_pos); - step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos); -} - -void -MidiTimeAxisView::step_edit_bar_sync () -{ - if (!_session || !step_edit_region_view || !step_edit_region) { - return; - } - - framepos_t fpos = step_edit_region->position() + - step_edit_region_view->beats_to_frames (step_edit_beat_pos); - fpos = _session->tempo_map().round_to_bar (fpos, 1); - step_edit_beat_pos = ceil (step_edit_region_view->frames_to_beats (fpos - step_edit_region->position())); - step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos); -} - -boost::shared_ptr<MidiRegion> -MidiTimeAxisView::add_region (framepos_t pos) -{ - Editor* real_editor = dynamic_cast<Editor*> (&_editor); - - real_editor->begin_reversible_command (_("create region")); - playlist()->clear_history (); - - real_editor->snap_to (pos, 0); - const Meter& m = _session->tempo_map().meter_at(pos); - const Tempo& t = _session->tempo_map().tempo_at(pos); - double length = floor (m.frames_per_bar(t, _session->frame_rate())); - - boost::shared_ptr<Source> src = _session->create_midi_source_for_session (view()->trackview().track().get(), - view()->trackview().track()->name()); - PropertyList plist; - - plist.add (ARDOUR::Properties::start, 0); - plist.add (ARDOUR::Properties::length, length); - plist.add (ARDOUR::Properties::name, PBD::basename_nosuffix(src->name())); - - boost::shared_ptr<Region> region = (RegionFactory::create (src, plist)); - - playlist()->add_region (region, pos); - _session->add_command (new StatefulDiffCommand (playlist())); - - real_editor->commit_reversible_command(); - return boost::dynamic_pointer_cast<MidiRegion>(region); -} void MidiTimeAxisView::add_note_selection (uint8_t note) @@ -1380,3 +1001,52 @@ MidiTimeAxisView::automation_child_menu_item (Evoral::Parameter param) return 0; } + +boost::shared_ptr<MidiRegion> +MidiTimeAxisView::add_region (framepos_t pos) +{ + Editor* real_editor = dynamic_cast<Editor*> (&_editor); + + real_editor->begin_reversible_command (_("create region")); + playlist()->clear_history (); + + real_editor->snap_to (pos, 0); + const Meter& m = _session->tempo_map().meter_at(pos); + const Tempo& t = _session->tempo_map().tempo_at(pos); + double length = floor (m.frames_per_bar(t, _session->frame_rate())); + + boost::shared_ptr<Source> src = _session->create_midi_source_for_session (view()->trackview().track().get(), + view()->trackview().track()->name()); + PropertyList plist; + + plist.add (ARDOUR::Properties::start, 0); + plist.add (ARDOUR::Properties::length, length); + plist.add (ARDOUR::Properties::name, PBD::basename_nosuffix(src->name())); + + boost::shared_ptr<Region> region = (RegionFactory::create (src, plist)); + + playlist()->add_region (region, pos); + _session->add_command (new StatefulDiffCommand (playlist())); + + real_editor->commit_reversible_command(); + + return boost::dynamic_pointer_cast<MidiRegion>(region); +} + +void +MidiTimeAxisView::start_step_editing () +{ + if (!_step_editor) { + _step_editor = new StepEditor (_editor, midi_track(), *this); + } + + _step_editor->start_step_editing (); + +} +void +MidiTimeAxisView::stop_step_editing () +{ + if (_step_editor) { + _step_editor->stop_step_editing (); + } +} |