From 10b48d2cc4cba6b73d4c48722db568fd27ccd1d2 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 26 Jan 2024 20:45:22 -0700 Subject: [PATCH] lock in some major steps for the midi cue/pianoroll editor --- gtk2_ardour/cue_editor.cc | 31 +++++++++++--------- gtk2_ardour/cue_editor.h | 5 ++-- gtk2_ardour/editing_context.cc | 7 +++++ gtk2_ardour/editing_context.h | 29 ++++++++++++++++++ gtk2_ardour/editor.cc | 5 ++++ gtk2_ardour/editor.h | 4 ++- gtk2_ardour/editor_canvas.cc | 2 +- gtk2_ardour/editor_cursors.cc | 6 ++-- gtk2_ardour/editor_cursors.h | 8 ++--- gtk2_ardour/editor_drag.cc | 5 +--- gtk2_ardour/midi_cue_background.cc | 8 +++-- gtk2_ardour/midi_cue_background.h | 1 + gtk2_ardour/midi_cue_editor.cc | 47 ++++++++++++++++++++++++++---- gtk2_ardour/midi_cue_editor.h | 7 +++-- gtk2_ardour/midi_region_view.cc | 2 ++ gtk2_ardour/midi_view.cc | 9 +++--- gtk2_ardour/midi_view.h | 3 ++ gtk2_ardour/public_editor.h | 1 - gtk2_ardour/wscript | 1 + libs/canvas/canvas.cc | 2 +- 20 files changed, 140 insertions(+), 43 deletions(-) diff --git a/gtk2_ardour/cue_editor.cc b/gtk2_ardour/cue_editor.cc index 40adb5fa62..8567370333 100644 --- a/gtk2_ardour/cue_editor.cc +++ b/gtk2_ardour/cue_editor.cc @@ -7,12 +7,6 @@ CueEditor::~CueEditor () { } -VerboseCursor* -CueEditor::verbose_cursor () const -{ - return nullptr; -} - void CueEditor::set_snapped_cursor_position (Temporal::timepos_t const & pos) { @@ -167,15 +161,11 @@ CueEditor::get_zoom_focus () const return Editing::ZoomFocusPlayhead; } -samplecnt_t -CueEditor::get_current_zoom () const -{ - return 2048; -} - void -CueEditor::reset_zoom (samplecnt_t) +CueEditor::reset_zoom (samplecnt_t n) { + samples_per_pixel = n; + ZoomChanged(); /* EMIT SIGNAL */ } void @@ -228,3 +218,18 @@ CueEditor::current_mouse_mode () const return Editing::MouseContent; } + +std::shared_ptr +CueEditor::start_local_tempo_map (std::shared_ptr map) +{ + std::shared_ptr tmp = Temporal::TempoMap::use(); + Temporal::TempoMap::set (map); + return tmp; +} + +void +CueEditor::end_local_tempo_map (std::shared_ptr map) +{ + Temporal::TempoMap::set (map); +} + diff --git a/gtk2_ardour/cue_editor.h b/gtk2_ardour/cue_editor.h index a2aa2a1402..57b9785e3f 100644 --- a/gtk2_ardour/cue_editor.h +++ b/gtk2_ardour/cue_editor.h @@ -90,12 +90,13 @@ class CueEditor : public EditingContext MouseCursors const* cursors () const { return _cursors; } - VerboseCursor* verbose_cursor () const; - void set_snapped_cursor_position (Temporal::timepos_t const & pos); std::vector filter_to_unique_midi_region_views (RegionSelection const & ms) const; + std::shared_ptr start_local_tempo_map (std::shared_ptr); + void end_local_tempo_map (std::shared_ptr); + protected: void set_canvas_cursor (Gdk::Cursor*); size_t push_canvas_cursor (Gdk::Cursor*); diff --git a/gtk2_ardour/editing_context.cc b/gtk2_ardour/editing_context.cc index 7e0e877e68..7dd70a122c 100644 --- a/gtk2_ardour/editing_context.cc +++ b/gtk2_ardour/editing_context.cc @@ -1586,3 +1586,10 @@ EditingContext::snap_relative_time_to_relative_time (timepos_t const & origin, t /* back to relative */ return origin.distance (snapped); } + +std::shared_ptr +EditingContext::start_local_tempo_map (std::shared_ptr) +{ + /* default is a no-op */ + return Temporal::TempoMap::use (); +} diff --git a/gtk2_ardour/editing_context.h b/gtk2_ardour/editing_context.h index 7ee7863c03..05ff1686e4 100644 --- a/gtk2_ardour/editing_context.h +++ b/gtk2_ardour/editing_context.h @@ -51,6 +51,10 @@ using ARDOUR::samplepos_t; using ARDOUR::samplecnt_t; +namespace Temporal { + class TempoMap; +} + class XMLNode; class CursorContext; @@ -79,6 +83,20 @@ public: Temporal::TimeDomain time_domain () const; + + struct TempoMapScope { + TempoMapScope (EditingContext& context, std::shared_ptr map) + : ec (context) + { + old_map = ec.start_local_tempo_map (map); + } + ~TempoMapScope () { + ec.end_local_tempo_map (old_map); + } + EditingContext& ec; + std::shared_ptr old_map; + }; + DragManager* drags () const { return _drags; } @@ -86,6 +104,8 @@ public: bool drag_active () const; bool preview_video_drag_active () const; + virtual ArdourCanvas::Duple upper_left() const { return ArdourCanvas::Duple (0, 0); } + virtual void select_all_within (Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, TrackViewList const &, Selection::Operation, bool) = 0; virtual void get_per_region_note_selection (std::list > > > >&) const = 0; virtual void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const = 0; @@ -249,6 +269,8 @@ public: virtual void reset_zoom (samplecnt_t) = 0; virtual void reposition_and_zoom (samplepos_t, double) = 0; + sigc::signal ZoomChanged; + virtual Selection& get_selection() const { return *selection; } virtual Selection& get_cut_buffer () const { return *cut_buffer; } @@ -295,6 +317,9 @@ public: ArdourCanvas::Rectangle* rubberband_rect; virtual ArdourCanvas::Container* get_noscroll_group() const = 0; + virtual ArdourCanvas::ScrollGroup* get_hscroll_group () const = 0; + virtual ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const = 0; + virtual bool canvas_playhead_cursor_event (GdkEvent* event, ArdourCanvas::Item*) { return false; } protected: Glib::RefPtr _midi_actions; @@ -426,6 +451,10 @@ public: double _visible_canvas_height; ///< height of the visible area of the track canvas QuantizeDialog* quantize_dialog; + + friend class TempoMapScope; + virtual std::shared_ptr start_local_tempo_map (std::shared_ptr); + virtual void end_local_tempo_map (std::shared_ptr) { /* no-op by default */ } }; diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 2ce6731eb6..b501199d6c 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -6592,3 +6592,8 @@ Editor::snap_to_internal (timepos_t& start, Temporal::RoundMode direction, SnapP start = best; } +ArdourCanvas::Duple +Editor::upper_left() const +{ + get_trackview_group ()->canvas_origin ().y; +} diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 0b8786db62..3d77b9b1e7 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -654,6 +654,8 @@ private: void reparent_location_markers (LocationMarkers*, ArdourCanvas::Item*); + ArdourCanvas::Duple upper_left() const; + LocationMarkers* find_location_markers (ARDOUR::Location*) const; ARDOUR::Location* find_location_from_marker (ArdourMarker*, bool& is_start) const; ArdourMarker* find_marker_from_location_id (PBD::ID const&, bool) const; @@ -1636,6 +1638,7 @@ private: void mid_tempo_change (MidTempoChanges); Editing::EditPoint edit_point() const { return _edit_point; } + bool canvas_playhead_cursor_event (GdkEvent* event, ArdourCanvas::Item*); enum MarkerBarType { CueMarks = 0x1, @@ -1673,7 +1676,6 @@ private: /* non-public event handlers */ bool canvas_section_box_event (GdkEvent* event); - bool canvas_playhead_cursor_event (GdkEvent* event, ArdourCanvas::Item*); bool track_canvas_scroll (GdkEventScroll* event); bool track_canvas_button_press_event (GdkEventButton* event); diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 3fc6f0aee1..3fd702ac6d 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -229,7 +229,7 @@ Editor::initialize_canvas () videotl_group->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_videotl_bar_event), videotl_group)); range_marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), range_marker_bar, RangeMarkerBarItem, "range marker bar")); - _playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event, X_("playhead")); + _playhead_cursor = new EditorCursor (*this, &EditingContext::canvas_playhead_cursor_event, X_("playhead")); _playhead_cursor->set_sensitive (UIConfiguration::instance().get_sensitize_playhead()); _snapped_cursor = new EditorCursor (*this, X_("snapped")); diff --git a/gtk2_ardour/editor_cursors.cc b/gtk2_ardour/editor_cursors.cc index 39de7942e9..609ea0b524 100644 --- a/gtk2_ardour/editor_cursors.cc +++ b/gtk2_ardour/editor_cursors.cc @@ -29,13 +29,13 @@ #include "canvas/scroll_group.h" #include "editor_cursors.h" -#include "editor.h" +#include "editing_context.h" using namespace ARDOUR; using namespace PBD; using namespace Gtk; -EditorCursor::EditorCursor (Editor& ed, bool (Editor::*callback)(GdkEvent*,ArdourCanvas::Item*), std::string const & name) +EditorCursor::EditorCursor (EditingContext& ed, bool (EditingContext::*callback)(GdkEvent*,ArdourCanvas::Item*), std::string const & name) : _editor (ed) , _track_canvas_item (new ArdourCanvas::Arrow (_editor.get_cursor_scroll_group())) { @@ -57,7 +57,7 @@ EditorCursor::EditorCursor (Editor& ed, bool (Editor::*callback)(GdkEvent*,Ardou _current_sample = 1; /* force redraw at 0 */ } -EditorCursor::EditorCursor (Editor& ed, std::string const & name) +EditorCursor::EditorCursor (EditingContext& ed, std::string const & name) : _editor (ed) , _track_canvas_item (new ArdourCanvas::Arrow (_editor.get_hscroll_group())) { diff --git a/gtk2_ardour/editor_cursors.h b/gtk2_ardour/editor_cursors.h index bdba8fc7fe..4344ee54a4 100644 --- a/gtk2_ardour/editor_cursors.h +++ b/gtk2_ardour/editor_cursors.h @@ -29,13 +29,13 @@ #include "canvas/line.h" #include "canvas/types.h" -class Editor; +class EditingContext; class EditorCursor { public: - EditorCursor (Editor&, bool (Editor::*)(GdkEvent*,ArdourCanvas::Item*), std::string const &); - EditorCursor (Editor&, std::string const &); + EditorCursor (EditingContext&, bool (EditingContext::*)(GdkEvent*,ArdourCanvas::Item*), std::string const &); + EditorCursor (EditingContext&, std::string const &); ~EditorCursor (); void set_position (samplepos_t); @@ -57,7 +57,7 @@ public: PBD::Signal1 PositionChanged; private: - Editor& _editor; + EditingContext& _editor; ArdourCanvas::Arrow* _track_canvas_item; samplepos_t _current_sample; }; diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 1ead968452..e7e96f7b57 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -471,10 +471,7 @@ Drag::current_pointer_y () const return _drags->current_pointer_y (); } - Editor* editor = dynamic_cast(&editing_context); - assert (editor); - - return _drags->current_pointer_y () - editor->get_trackview_group ()->canvas_origin ().y; + return _drags->current_pointer_y () - editing_context.upper_left ().y; } void diff --git a/gtk2_ardour/midi_cue_background.cc b/gtk2_ardour/midi_cue_background.cc index 716fc8c86b..50097938c4 100644 --- a/gtk2_ardour/midi_cue_background.cc +++ b/gtk2_ardour/midi_cue_background.cc @@ -41,8 +41,6 @@ CueMidiBackground::set_size (double w, double h) _width = w; _height = h; - std::cerr << "Size for cue midi: " << w << " x " << h << std::endl; - update_contents_height (); } @@ -58,6 +56,12 @@ CueMidiBackground::height() const return _height; } +double +CueMidiBackground::width() const +{ + return _width; +} + uint8_t CueMidiBackground::get_preferred_midi_channel () const { diff --git a/gtk2_ardour/midi_cue_background.h b/gtk2_ardour/midi_cue_background.h index f759a2d9dc..2d1a546dc6 100644 --- a/gtk2_ardour/midi_cue_background.h +++ b/gtk2_ardour/midi_cue_background.h @@ -40,6 +40,7 @@ class CueMidiBackground : public MidiViewBackground ~CueMidiBackground (); double height() const; + double width() const; double contents_height() const; uint8_t get_preferred_midi_channel () const; diff --git a/gtk2_ardour/midi_cue_editor.cc b/gtk2_ardour/midi_cue_editor.cc index cce3e26814..abef10873d 100644 --- a/gtk2_ardour/midi_cue_editor.cc +++ b/gtk2_ardour/midi_cue_editor.cc @@ -16,18 +16,24 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "ardour/midi_region.h" +#include "ardour/midi_source.h" + #include "canvas/canvas.h" #include "canvas/container.h" #include "canvas/debug.h" #include "canvas/scroll_group.h" #include "canvas/rectangle.h" +#include "editor_cursors.h" #include "midi_cue_background.h" #include "midi_cue_editor.h" -#include "midi_view.h" +#include "midi_cue_view.h" #include "ui_config.h" #include "verbose_cursor.h" +#include "pbd/i18n.h" + using namespace ARDOUR; using namespace ArdourCanvas; using namespace Temporal; @@ -40,6 +46,12 @@ MidiCueEditor::MidiCueEditor() build_canvas (); _verbose_cursor = new VerboseCursor (*this); + + // _playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event, X_("playhead")); + _playhead_cursor = new EditorCursor (*this, X_("playhead")); + _playhead_cursor->set_sensitive (UIConfiguration::instance().get_sensitize_playhead()); + + _snapped_cursor = new EditorCursor (*this, X_("snapped")); } MidiCueEditor::~MidiCueEditor () @@ -90,9 +102,6 @@ MidiCueEditor::build_canvas () time_line_group = new ArdourCanvas::Container (h_scroll_group); CANVAS_DEBUG_NAME (time_line_group, "time line group"); - _trackview_group = new ArdourCanvas::Container (hv_scroll_group); - CANVAS_DEBUG_NAME (_trackview_group, "Canvas TrackViews"); - // used as rubberband rect rubberband_rect = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0)); rubberband_rect->hide(); @@ -146,6 +155,16 @@ MidiCueEditor::snap_to_internal (timepos_t& start, Temporal::RoundMode direction start = best; } +void +MidiCueEditor::reset_zoom (samplecnt_t spp) +{ + CueEditor::reset_zoom (spp); + + if (view) { + view->set_samples_per_pixel (spp); + } +} + samplecnt_t MidiCueEditor::current_page_samples() const { @@ -201,8 +220,26 @@ MidiCueEditor::set_region (std::shared_ptr t, std::shared_ptr return; } - view = new MidiView (t, *hv_scroll_group, *this, *bg, 0xff0000ff); + view = new MidiCueView (t, *hv_scroll_group, *this, *bg, 0xff0000ff); view->set_region (r); bg->set_view (view); + + /* Compute zoom level to show entire source plus some margin if possible */ + + std::shared_ptr map; + + Temporal::timecnt_t duration = Temporal::timecnt_t (r->midi_source()->length().beats()); + /* XXX build tempo map from source */ + map.reset (new Temporal::TempoMap (Temporal::Tempo (120, 4), Temporal::Meter (4, 4))); + + { + EditingContext::TempoMapScope tms (*this, map); + double width = bg->width(); + samplecnt_t samples = duration.samples(); + + samplecnt_t spp = floor (samples / width); + reset_zoom (spp); + } } + diff --git a/gtk2_ardour/midi_cue_editor.h b/gtk2_ardour/midi_cue_editor.h index e36e20ab95..a10f828f99 100644 --- a/gtk2_ardour/midi_cue_editor.h +++ b/gtk2_ardour/midi_cue_editor.h @@ -64,6 +64,11 @@ class MidiCueEditor : public CueEditor void set_region (std::shared_ptr, std::shared_ptr); + ArdourCanvas::ScrollGroup* get_hscroll_group () const { return h_scroll_group; } + ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const { return cursor_scroll_group; } + + void reset_zoom (samplecnt_t); + protected: Temporal::timepos_t snap_to_grid (Temporal::timepos_t const & start, Temporal::RoundMode direction, @@ -98,8 +103,6 @@ class MidiCueEditor : public CueEditor /* The group containing all trackviews. */ ArdourCanvas::Container* no_scroll_group; - /* The group containing all trackviews. */ - ArdourCanvas::Container* _trackview_group; ArdourCanvas::Container* global_rect_group; ArdourCanvas::Container* time_line_group; diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index bfc3154925..6fd98d4ceb 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -150,6 +150,8 @@ MidiRegionView::init (bool /*wfd*/) RegionView::init (false); + CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name())); + set_region (std::dynamic_pointer_cast (_region)); //set_height (trackview.current_height()); diff --git a/gtk2_ardour/midi_view.cc b/gtk2_ardour/midi_view.cc index d8241b5750..265859ac5b 100644 --- a/gtk2_ardour/midi_view.cc +++ b/gtk2_ardour/midi_view.cc @@ -31,8 +31,6 @@ #include -#include "gtkmm2ext/gtk_ui.h" - #include #include "midi++/midnam_patch.h" @@ -57,6 +55,9 @@ #include "canvas/debug.h" +#include "gtkmm2ext/gtk_ui.h" +#include "gtkmm2ext/utils.h" + #include "automation_region_view.h" #include "automation_time_axis.h" #include "control_point.h" @@ -172,8 +173,6 @@ MidiView::MidiView (MidiView const & other) void MidiView::init () { - // CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name())); - _patch_change_outline = UIConfiguration::instance().color ("midi patch change outline"); _patch_change_fill = UIConfiguration::instance().color_mod ("midi patch change fill", "midi patch change fill"); @@ -239,6 +238,8 @@ MidiView::canvas_group_event (GdkEvent* ev) //For now, move the snapped cursor aside so it doesn't bother you during internal editing //_editing_context.set_snapped_cursor_position(_midi_region->position()); + std::cerr << "MV @ " << this << " CGE " << Gtkmm2ext::event_type_string (ev->type) << std::endl; + bool r; switch (ev->type) { diff --git a/gtk2_ardour/midi_view.h b/gtk2_ardour/midi_view.h index 82a4d79fe7..88446338cc 100644 --- a/gtk2_ardour/midi_view.h +++ b/gtk2_ardour/midi_view.h @@ -92,6 +92,9 @@ class MidiView : public virtual sigc::trackable virtual ~MidiView (); void init (bool wfd); + + virtual void set_samples_per_pixel (double) {}; + virtual bool display_is_enabled() const { return true; } virtual ArdourCanvas::Item* drag_group() const; diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 3780eee848..2b659a6409 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -353,7 +353,6 @@ public: virtual RegionView* regionview_from_region (std::shared_ptr) const = 0; virtual RouteTimeAxisView* rtav_from_route (std::shared_ptr) const = 0; - sigc::signal ZoomChanged; sigc::signal Realized; sigc::signal UpdateAllTransportClocks; diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 274b2241b1..a35ad24f59 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -160,6 +160,7 @@ gtk2_ardour_sources = [ 'midi_channel_selector.cc', 'midi_cue_background.cc', 'midi_cue_editor.cc', + 'midi_cue_view.cc', 'midi_cut_buffer.cc', 'midi_export_dialog.cc', 'midi_list_editor.cc', diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc index 48e30a3cf4..63a2e6eb93 100644 --- a/libs/canvas/canvas.cc +++ b/libs/canvas/canvas.cc @@ -673,7 +673,7 @@ GtkCanvas::pick_current_item (Duple const & point, int state) } if (_current_item) { - DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("CURRENT ITEM %1/%2\n", _new_current_item->whatami(), _current_item->name)); + DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("CURRENT ITEM %1/%2\n", _current_item->whatami(), _current_item->name)); } else { DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, "--- no current item\n"); }