diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index bd9ae6e0da..1abee5b42a 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -698,8 +698,7 @@ - - + @@ -900,6 +899,7 @@ + diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index c1d3ca200e..88e7a1b5e2 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -281,7 +281,6 @@ public: Gtk::Menu* shared_popup_menu (); void new_midi_tracer_window (); - void new_pianoroll_window (); void toggle_editing_space(); void toggle_mixer_space(); void toggle_keep_tearoffs(); @@ -522,7 +521,6 @@ private: void record_state_changed (); std::list _midi_tracer_windows; - std::list _pianoroll_windows; /* Transport Control */ diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index b8717e6775..2163d0a3ff 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -888,30 +888,6 @@ ARDOUR_UI::toggle_meterbridge () } } -void -ARDOUR_UI::new_pianoroll_window () -{ - RefPtr act = ActionManager::get_action (X_("Common"), X_("new-pianoroll")); - if (!act) { - return; - } - - std::list::iterator i = _pianoroll_windows.begin (); - while (i != _pianoroll_windows.end() && (*i)->get_visible() == true) { - ++i; - } - - if (i == _pianoroll_windows.end()) { - /* all our MIDITracer windows are visible; make a new one */ - PianorollWindow* pr = new PianorollWindow (string_compose (_("Pianoroll %1"), _pianoroll_windows.size() + 1)); - pr->show_all (); - _pianoroll_windows.push_back (pr); - } else { - /* re-use the hidden one */ - (*i)->show_all (); - } -} - void ARDOUR_UI::new_midi_tracer_window () { diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index ab72b9f2d0..5f3332fb0b 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -286,8 +286,6 @@ ARDOUR_UI::install_actions () act = ActionManager::register_action (common_actions, X_("NewMIDITracer"), _("MIDI Tracer"), sigc::mem_fun(*this, &ARDOUR_UI::new_midi_tracer_window)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (common_actions, X_("new-pianoroll"), _("Piano Roll"), sigc::mem_fun(*this, &ARDOUR_UI::new_pianoroll_window)); - ActionManager::session_sensitive_actions.push_back (act); ActionManager::register_action (common_actions, X_("chat"), _("Chat"), sigc::mem_fun(*this, &ARDOUR_UI::launch_chat)); ActionManager::register_action (common_actions, X_("tutorial"), S_("Help|Tutorial"), mem_fun(*this, &ARDOUR_UI::launch_tutorial)); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index f1ad94684d..6d14af495d 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -229,6 +229,8 @@ public: bool extend_selection_to_track (TimeAxisView&); + void edit_region_in_pianoroll_window (); + void play_selection (); void maybe_locate_with_edit_preroll (samplepos_t); void play_with_preroll (); diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 9e61efb4c1..654b832783 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -1253,6 +1253,9 @@ Editor::register_region_actions () /* Open the region properties dialogue for the selected regions */ register_region_action (_region_actions, RegionActionTarget (SelectedRegions), "show-region-properties", _("Properties..."), sigc::mem_fun (*this, &Editor::show_region_properties)); + /* Edit the region in a separate region pianoroll window */ + register_region_action (_region_actions, RegionActionTarget (SelectedRegions), "edit-region-pianoroll-window", _("Edit in separate window..."), sigc::mem_fun (*this, &Editor::edit_region_in_pianoroll_window)); + register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "play-selected-regions", _("Play Selected Regions"), sigc::mem_fun(*this, &Editor::play_selected_region)); register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "tag-selected-regions", _("Tag Selected Regions"), sigc::mem_fun(*this, &Editor::tag_selected_region)); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index c5b0078a6c..35d6f5cb3d 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -113,6 +113,7 @@ #include "note.h" #include "paste_context.h" #include "patch_change_dialog.h" +#include "pianoroll_window.h" #include "region_gain_line.h" #include "route_time_axis.h" #include "selection.h" @@ -9517,3 +9518,10 @@ Editor::temporal_zoom_extents () temporal_zoom_by_sample (start, end); } } + +void +Editor::edit_region_in_pianoroll_window () +{ + selection->foreach_midi_regionview (&MidiRegionView::edit_in_pianoroll_window); +} + diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 058d409077..bca953ffa0 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -48,7 +48,6 @@ #include "ardour/midi_track.h" #include "ardour/operations.h" #include "ardour/quantize.h" -#include "ardour/session.h" #include "evoral/Parameter.h" #include "evoral/Event.h" @@ -77,6 +76,7 @@ #include "midi_velocity_dialog.h" #include "note_player.h" #include "paste_context.h" +#include "pianoroll_window.h" #include "public_editor.h" #include "route_time_axis.h" #include "rgb_macros.h" @@ -681,3 +681,16 @@ MidiRegionView::add_control_points_to_selection (timepos_t const & start, timepo at.second->set_selected_points (_editing_context.get_selection().points); } } + +void +MidiRegionView::edit_in_pianoroll_window () +{ + std::shared_ptr track = std::dynamic_pointer_cast (trackview.stripable()); + assert (track); + + PianorollWindow* pr = new PianorollWindow (string_compose (_("Pianoroll: %1"), _region->name()), track->session());; + + pr->set (track, midi_region()); + pr->show_all (); + pr->present (); +} diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 202151b06d..130f155437 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -134,6 +134,7 @@ public: void set_visibility_note_range (MidiViewBackground::VisibleNoteRange, bool); MergeableLine* make_merger (); + void edit_in_pianoroll_window (); protected: void reset_width_dependent_items (double pixel_width); diff --git a/gtk2_ardour/midi_view.cc b/gtk2_ardour/midi_view.cc index 81e5ea763d..d48ac230e7 100644 --- a/gtk2_ardour/midi_view.cc +++ b/gtk2_ardour/midi_view.cc @@ -317,10 +317,19 @@ MidiView::region_going_away () { _midi_region.reset (); _model.reset (); + + clear_events (); + connections_requiring_model.drop_connections(); region_connections.drop_connections (); } +void +MidiView::set_show_source (bool yn) +{ + _show_source = yn; +} + void MidiView::set_region (std::shared_ptr mr) { @@ -334,6 +343,9 @@ MidiView::set_region (std::shared_ptr mr) _midi_region->DropReferences.connect (region_connections, invalidator (*this), std::bind (&MidiView::region_going_away, this), gui_context()); _midi_region->PropertyChanged.connect (region_connections, invalidator (*this), std::bind (&MidiView::region_resized, this, _1), gui_context()); + size_start_rect (); + size_end_rect (); + set_model (_midi_region->midi_source (0)->model()); } diff --git a/gtk2_ardour/midi_view.h b/gtk2_ardour/midi_view.h index 523f8b72a5..e4b1af436d 100644 --- a/gtk2_ardour/midi_view.h +++ b/gtk2_ardour/midi_view.h @@ -145,6 +145,8 @@ class MidiView : public virtual sigc::trackable, public LineMerger virtual void set_track (std::shared_ptr); virtual void set_model (std::shared_ptr); + void set_show_source (bool yn); + NoteBase* add_note(const std::shared_ptr note, bool visible); void cut_copy_clear (Editing::CutCopyOp); diff --git a/gtk2_ardour/midi_view_background.cc b/gtk2_ardour/midi_view_background.cc index 97d6cffb14..003f257f1b 100644 --- a/gtk2_ardour/midi_view_background.cc +++ b/gtk2_ardour/midi_view_background.cc @@ -229,6 +229,7 @@ MidiViewBackground::maybe_extend_note_range (uint8_t note_num) } if (changed) { + std::cerr << "changing it\n"; apply_note_range (_data_note_min, _data_note_max, true); } } diff --git a/gtk2_ardour/pianoroll.cc b/gtk2_ardour/pianoroll.cc index 4bb8ee7825..97e21932ee 100644 --- a/gtk2_ardour/pianoroll.cc +++ b/gtk2_ardour/pianoroll.cc @@ -16,6 +16,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "pbd/stateful_diff_command.h" + #include "ardour/midi_region.h" #include "ardour/midi_track.h" #include "ardour/smf_source.h" @@ -51,6 +53,7 @@ #include "pbd/i18n.h" +using namespace PBD; using namespace ARDOUR; using namespace ArdourCanvas; using namespace ArdourWidgets; @@ -502,6 +505,12 @@ Pianoroll::canvas_allocate (Gtk::Allocation alloc) prh->set (ArdourCanvas::Rect (0, 0, prh->x1(), view->midi_context().height())); _track_canvas_width = _visible_canvas_width - prh->x1(); + + if (_canvas->is_mapped()) { + // zoom_to_show (timecnt_t (timepos_t (Temporal::BeatTime), timepos_t (max_zoom_extent ().second.beats() * 1.1))); + } + + std::cerr << "new size " << _visible_canvas_width << " x " << _visible_canvas_width << std::endl; } timepos_t @@ -608,13 +617,29 @@ Pianoroll::canvas_cue_end_event (GdkEvent* event, ArdourCanvas::Item* item) void Pianoroll::set_trigger_start (Temporal::timepos_t const & p) { - ref.trigger()->the_region()->trim_front (p); + if (ref.trigger()) { + ref.trigger()->the_region()->trim_front (p); + } else { + begin_reversible_command (_("trim region front")); + view->midi_region()->clear_changes (); + view->midi_region()->trim_front (view->midi_region()->position() + p); + add_command (new StatefulDiffCommand (view->midi_region())); + commit_reversible_command (); + } } void Pianoroll::set_trigger_end (Temporal::timepos_t const & p) { - ref.trigger()->the_region()->trim_end (p); + if (ref.trigger()) { + ref.trigger()->the_region()->trim_end (p); + } else { + begin_reversible_command (_("trim region end")); + view->midi_region()->clear_changes (); + view->midi_region()->trim_end (view->midi_region()->position() + p); + add_command (new StatefulDiffCommand (view->midi_region())); + commit_reversible_command (); + } } Gtk::Widget& @@ -1937,6 +1962,14 @@ Pianoroll::unset () ref = TriggerReference (); } +void +Pianoroll::set_track (std::shared_ptr track) +{ + if (view) { + view->set_track (track); + } +} + void Pianoroll::set_region (std::shared_ptr r) { @@ -1949,12 +1982,6 @@ Pianoroll::set_region (std::shared_ptr r) view->show_start (true); view->show_end (true); - /* Compute zoom level to show entire source plus some margin if possible */ - - Temporal::timecnt_t duration = Temporal::timecnt_t (r->midi_source()->length().beats()); - - std::cerr << "new region: " << duration << std::endl; - bool provided = false; std::shared_ptr map; std::shared_ptr smf (std::dynamic_pointer_cast (r->midi_source())); @@ -1964,22 +1991,34 @@ Pianoroll::set_region (std::shared_ptr r) } if (!provided) { + /* COPY MAIN SESSION TEMPO MAP? */ map.reset (new Temporal::TempoMap (Temporal::Tempo (120, 4), Temporal::Meter (4, 4))); } { EditingContext::TempoMapScope tms (*this, map); - double width = bg->width(); - /* make it 20% wider than we need */ - samplecnt_t samples = (samplecnt_t) floor (1.2 * duration.samples()); - std::cerr << "new spp from " << samples << " / " << width << std::endl; - samplecnt_t spp = floor (samples / width); - reset_zoom (spp); + /* Compute zoom level to show entire source plus some margin if possible */ + zoom_to_show (timecnt_t (timepos_t (Temporal::BeatTime), timepos_t (max_zoom_extent ().second.beats() * 1.1))); + } set_visible_channel (0); } +void +Pianoroll::zoom_to_show (Temporal::timecnt_t const & duration) +{ + if (!_visible_canvas_width) { + return; + } + + /* make it 20% wider than we need */ + samplecnt_t samples = (samplecnt_t) floor (1.2 * duration.samples()); + std::cerr << "new spp from " << samples << " / " << _visible_canvas_width << std::endl; + samplecnt_t spp = floor (samples / _visible_canvas_width); + reset_zoom (spp); +} + bool Pianoroll::automation_button_event (GdkEventButton* ev, Evoral::ParameterType type, int id) { @@ -2091,6 +2130,7 @@ std::pair Pianoroll::max_zoom_extent() const { if (view && view->midi_region()) { + /* XXX make this dependent on view _show_source setting */ return std::make_pair (Temporal::timepos_t (Temporal::Beats()), Temporal::timepos_t (view->midi_region()->midi_source()->length().beats())); } diff --git a/gtk2_ardour/pianoroll.h b/gtk2_ardour/pianoroll.h index 24f7b8bec7..a05d714b43 100644 --- a/gtk2_ardour/pianoroll.h +++ b/gtk2_ardour/pianoroll.h @@ -79,6 +79,7 @@ class Pianoroll : public CueEditor void set (ARDOUR::TriggerReference&); void set_region (std::shared_ptr); + void set_track (std::shared_ptr); ArdourCanvas::ScrollGroup* get_hscroll_group () const { return h_scroll_group; } ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const { return cursor_scroll_group; } @@ -126,6 +127,7 @@ class Pianoroll : public CueEditor void set_trigger_bounds (Temporal::timepos_t const &, Temporal::timepos_t const &); void full_zoom_clicked(); + void zoom_to_show (Temporal::timecnt_t const &); void delete_ (); void paste (float times, bool from_context_menu); diff --git a/gtk2_ardour/pianoroll_window.cc b/gtk2_ardour/pianoroll_window.cc index 24c7d169d2..5a2db5fb71 100644 --- a/gtk2_ardour/pianoroll_window.cc +++ b/gtk2_ardour/pianoroll_window.cc @@ -23,10 +23,11 @@ using namespace ARDOUR; -PianorollWindow::PianorollWindow (std::string const & name) +PianorollWindow::PianorollWindow (std::string const & name, Session& s) : ArdourWindow (string_compose ("%1 - %2", PROGRAM_NAME, name)) , pianoroll (new Pianoroll (name)) { + pianoroll->set_session (&s); pianoroll->viewport().set_size_request (600, 120); add (pianoroll->toolbox()); @@ -37,3 +38,10 @@ PianorollWindow::~PianorollWindow () { delete pianoroll; } + +void +PianorollWindow::set (std::shared_ptr track, std::shared_ptr region) +{ + pianoroll->set_track (track); + pianoroll->set_region (region); +} diff --git a/gtk2_ardour/pianoroll_window.h b/gtk2_ardour/pianoroll_window.h index 4abb1635c2..befb3328dc 100644 --- a/gtk2_ardour/pianoroll_window.h +++ b/gtk2_ardour/pianoroll_window.h @@ -30,10 +30,10 @@ class Pianoroll; class PianorollWindow : public ArdourWindow { public: - PianorollWindow (std::string const & name); + PianorollWindow (std::string const & name, ARDOUR::Session&); ~PianorollWindow (); - void set (std::shared_ptr, std::shared_ptr); + void set (std::shared_ptr, std::shared_ptr); private: Pianoroll* pianoroll;