diff --git a/doc/mainpage.md b/doc/mainpage.md index cf5a01a7ff..67eca802c4 100755 --- a/doc/mainpage.md +++ b/doc/mainpage.md @@ -91,7 +91,7 @@ A few specific libraries are compiled statically (e.g. fluidsynth for use in plu Mini Ardour inside Ardour to export audio-files from sessions. It is a combination of AudioGrapher::Source and AudioGrapher::Sink classes that are chained together by ARDOUR::ExportGraphBuilder as shown in the ASCII art - [Export Graph](https://git.ardour.org/ardour/ardour/src/commit/0df0e14e2309a00d433827fa34b87638b87f4fff/libs/ardour/export_graph_builder.cc#L73-L154). + [Export Graph](https://github.com/Ardour/ardour/blob/56647acc25aa91ccf920e5ac21452bccf35b78e7/libs/ardour/export_graph_builder.cc#L73-L154). * `libs/ardour/` diff --git a/gtk2_ardour/ardour.keys.in b/gtk2_ardour/ardour.keys.in index 5bad418aed..839936a471 100644 --- a/gtk2_ardour/ardour.keys.in +++ b/gtk2_ardour/ardour.keys.in @@ -210,8 +210,8 @@ This mode provides many different operations on both regions and control points, @edit|Editor/multi-duplicate| <@SECONDARY@>d|duplicate (multi) @select|Editor/select-all-in-punch-range| <@TERTIARY@>d|select all in punch range @vis|Editor/fit-selection| f|fit selection vertically -@edit|Editing/toggle-follow-playhead| <@PRIMARY@>f|toggle playhead tracking -@edit|Editor/toggle-stationary-playhead| <@TERTIARY@>f|toggle stationary playhead +@edit|EditorEditing/toggle-follow-playhead| <@PRIMARY@>f|toggle playhead tracking +@edit|EditorEditing/toggle-stationary-playhead| <@TERTIARY@>f|toggle stationary playhead @rop|Region/show-rhythm-ferret| <@SECONDARY@>f|show rhythm ferret window @wvis|Common/ToggleMaximalEditor| <@PRIMARY@><@SECONDARY@>f|maximise editor space @wvis|Common/ToggleMaximalMixer| <@PRIMARY@><@TERTIARY@>f|maximise mixer space diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index d66a2fb919..8e18630777 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -187,7 +187,7 @@ - + diff --git a/gtk2_ardour/audio_clip_editor.cc b/gtk2_ardour/audio_clip_editor.cc index 18420b0ca6..e6913305ca 100644 --- a/gtk2_ardour/audio_clip_editor.cc +++ b/gtk2_ardour/audio_clip_editor.cc @@ -112,11 +112,9 @@ AudioClipEditor::AudioClipEditor (std::string const & name, bool with_transport) load_bindings (); register_actions (); - build_canvas (); - build_grid_type_menu (); - build_upper_toolbar (); + build_canvas (); build_lower_toolbar (); set_action_defaults (); @@ -125,6 +123,8 @@ AudioClipEditor::AudioClipEditor (std::string const & name, bool with_transport) void AudioClipEditor::load_shared_bindings () { + EC_LOCAL_TEMPO_SCOPE; + /* Full shared binding loading must have preceded this in some other EditingContext */ assert (!need_shared_actions); @@ -146,6 +146,8 @@ AudioClipEditor::load_shared_bindings () void AudioClipEditor::pack_inner (Gtk::Box& box) { + EC_LOCAL_TEMPO_SCOPE; + box.pack_start (snap_box, false, false); box.pack_start (grid_box, false, false); } @@ -153,6 +155,8 @@ AudioClipEditor::pack_inner (Gtk::Box& box) void AudioClipEditor::pack_outer (Gtk::Box& box) { + EC_LOCAL_TEMPO_SCOPE; + if (with_transport_controls) { box.pack_start (play_box, false, false); } @@ -164,12 +168,16 @@ AudioClipEditor::pack_outer (Gtk::Box& box) void AudioClipEditor::build_lower_toolbar () { + EC_LOCAL_TEMPO_SCOPE; + _toolbox.pack_start (*_canvas_hscrollbar, false, false); } void AudioClipEditor::build_canvas () { + EC_LOCAL_TEMPO_SCOPE; + _canvas.set_background_color (UIConfiguration::instance().color ("arrange base")); _canvas.signal_event().connect (sigc::mem_fun (*this, &CueEditor::canvas_pre_event), false); _canvas.use_nsglview (UIConfiguration::instance().get_nsgl_view_mode () == NSGLHiRes); @@ -213,14 +221,14 @@ AudioClipEditor::build_canvas () CANVAS_DEBUG_NAME (time_line_group, "audioclip time line group"); n_timebars = 0; - minsec_ruler = new ArdourCanvas::Ruler (time_line_group, clip_metric, ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height)); - // minsec_ruler->set_name ("audio clip editor ruler"); - minsec_ruler->set_font_description (UIConfiguration::instance ().get_SmallerFont ()); - minsec_ruler->set_fill_color (UIConfiguration::instance().color (X_("theme:bg1"))); - minsec_ruler->set_outline_color (UIConfiguration::instance().color (X_("theme:contrasting less"))); + main_ruler = new ArdourCanvas::Ruler (time_line_group, clip_metric, ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height)); + // main_ruler->set_name ("audio clip editor ruler"); + main_ruler->set_font_description (UIConfiguration::instance ().get_SmallerFont ()); + main_ruler->set_fill_color (UIConfiguration::instance().color (X_("ruler base"))); + main_ruler->set_outline_color (UIConfiguration::instance().color (X_("ruler text"))); n_timebars++; - minsec_ruler->Event.connect (sigc::mem_fun (*this, &CueEditor::ruler_event)); + main_ruler->Event.connect (sigc::mem_fun (*this, &CueEditor::ruler_event)); data_group = new ArdourCanvas::Container (hv_scroll_group); CANVAS_DEBUG_NAME (data_group, "cue data group"); @@ -230,8 +238,6 @@ AudioClipEditor::build_canvas () cursor_scroll_group->set_position (ArdourCanvas::Duple (_timeline_origin, timebar_height * n_timebars)); h_scroll_group->set_position (Duple (_timeline_origin, 0.)); - _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()); @@ -274,6 +280,8 @@ AudioClipEditor::build_canvas () AudioClipEditor::~AudioClipEditor () { + EC_LOCAL_TEMPO_SCOPE; + drop_waves (); delete clip_metric; } @@ -281,6 +289,8 @@ AudioClipEditor::~AudioClipEditor () bool AudioClipEditor::line_event_handler (GdkEvent* ev, ArdourCanvas::Line* l) { + EC_LOCAL_TEMPO_SCOPE; + std::cerr << "event type " << Gtkmm2ext::event_type_string (ev->type) << " on line " << std::endl; switch (ev->type) { @@ -317,12 +327,16 @@ AudioClipEditor::line_event_handler (GdkEvent* ev, ArdourCanvas::Line* l) bool AudioClipEditor::key_press (GdkEventKey* ev) { + EC_LOCAL_TEMPO_SCOPE; + return false; } void AudioClipEditor::position_lines () { + EC_LOCAL_TEMPO_SCOPE; + if (!_region) { return; } @@ -362,6 +376,8 @@ AudioClipEditor::LineDrag::motion (GdkEventMotion* ev) void AudioClipEditor::set_colors () { + EC_LOCAL_TEMPO_SCOPE; + _canvas.set_background_color (UIConfiguration::instance ().color (X_("theme:bg"))); start_line->set_outline_color (UIConfiguration::instance ().color (X_("theme:contrasting clock"))); @@ -374,6 +390,8 @@ AudioClipEditor::set_colors () void AudioClipEditor::drop_waves () { + EC_LOCAL_TEMPO_SCOPE; + for (auto& wave : waves) { delete wave; } @@ -384,6 +402,8 @@ AudioClipEditor::drop_waves () void AudioClipEditor::set_trigger (TriggerReference& tr) { + EC_LOCAL_TEMPO_SCOPE; + if (tr == ref) { return; } @@ -391,13 +411,15 @@ AudioClipEditor::set_trigger (TriggerReference& tr) CueEditor::set_trigger (tr); rec_box.show (); - minsec_ruler->show (); - minsec_ruler->set_range (0, pixel_to_sample (_visible_canvas_width - 2.)); + main_ruler->show (); + main_ruler->set_range (0, pixel_to_sample (_visible_canvas_width - 2.)); } void AudioClipEditor::set_region (std::shared_ptr region) { + EC_LOCAL_TEMPO_SCOPE; + CueEditor::set_region (region); if (_visible_pending_region) { @@ -425,7 +447,7 @@ AudioClipEditor::set_region (std::shared_ptr region) delete clip_metric; clip_metric = new ClipBBTMetric (ref); - minsec_ruler->set_metric (clip_metric); + main_ruler->set_metric (clip_metric); uint32_t n_chans = r->n_channels (); samplecnt_t len; @@ -474,6 +496,8 @@ AudioClipEditor::set_region (std::shared_ptr region) void AudioClipEditor::canvas_allocate (Gtk::Allocation& alloc) { + EC_LOCAL_TEMPO_SCOPE; + _canvas.size_allocate (alloc); _visible_canvas_width = alloc.get_width(); @@ -482,7 +506,7 @@ AudioClipEditor::canvas_allocate (Gtk::Allocation& alloc) /* no track header here, "track width" is the whole canvas */ _track_canvas_width = _visible_canvas_width; - minsec_ruler->set (ArdourCanvas::Rect (2, 2, alloc.get_width() - 4, timebar_height)); + main_ruler->set (ArdourCanvas::Rect (2, 2, alloc.get_width() - 4, timebar_height)); position_lines (); @@ -500,6 +524,8 @@ AudioClipEditor::canvas_allocate (Gtk::Allocation& alloc) void AudioClipEditor::set_spp_from_length (samplecnt_t len) { + EC_LOCAL_TEMPO_SCOPE; + if (_visible_canvas_width) { set_samples_per_pixel (floor (len / _visible_canvas_width)); } @@ -508,6 +534,8 @@ AudioClipEditor::set_spp_from_length (samplecnt_t len) void AudioClipEditor::set_wave_heights () { + EC_LOCAL_TEMPO_SCOPE; + if (waves.empty ()) { return; } @@ -526,6 +554,8 @@ AudioClipEditor::set_wave_heights () void AudioClipEditor::set_waveform_colors () { + EC_LOCAL_TEMPO_SCOPE; + Gtkmm2ext::Color clip = UIConfiguration::instance ().color ("clipped waveform"); Gtkmm2ext::Color zero = UIConfiguration::instance ().color ("zero line"); Gtkmm2ext::Color fill = UIConfiguration::instance ().color ("waveform fill"); @@ -542,17 +572,23 @@ AudioClipEditor::set_waveform_colors () Gtk::Widget& AudioClipEditor::contents () { + EC_LOCAL_TEMPO_SCOPE; + return _contents; } void AudioClipEditor::region_changed (const PBD::PropertyChange& what_changed) { + EC_LOCAL_TEMPO_SCOPE; + } void AudioClipEditor::set_samples_per_pixel (samplecnt_t spp) { + EC_LOCAL_TEMPO_SCOPE; + CueEditor::set_samples_per_pixel (spp); clip_metric->units_per_pixel = samples_per_pixel; @@ -572,12 +608,16 @@ AudioClipEditor::set_samples_per_pixel (samplecnt_t spp) samplecnt_t AudioClipEditor::current_page_samples() const { + EC_LOCAL_TEMPO_SCOPE; + return (samplecnt_t) _track_canvas_width * samples_per_pixel; } bool AudioClipEditor::canvas_enter_leave (GdkEventCrossing* ev) { + EC_LOCAL_TEMPO_SCOPE; + switch (ev->type) { case GDK_ENTER_NOTIFY: if (ev->detail != GDK_NOTIFY_INFERIOR) { @@ -602,26 +642,36 @@ AudioClipEditor::canvas_enter_leave (GdkEventCrossing* ev) void AudioClipEditor::begin_write () { + EC_LOCAL_TEMPO_SCOPE; + } void AudioClipEditor::end_write () { + EC_LOCAL_TEMPO_SCOPE; + } void AudioClipEditor::show_count_in (std::string const &) { + EC_LOCAL_TEMPO_SCOPE; + } void AudioClipEditor::hide_count_in () { + EC_LOCAL_TEMPO_SCOPE; + } void AudioClipEditor::maybe_update () { + EC_LOCAL_TEMPO_SCOPE; + ARDOUR::TriggerPtr playing_trigger; if (ref.trigger()) { @@ -679,6 +729,8 @@ AudioClipEditor::maybe_update () void AudioClipEditor::unset (bool trigger_too) { + EC_LOCAL_TEMPO_SCOPE; + drop_waves (); CueEditor::unset (trigger_too); } diff --git a/gtk2_ardour/audio_clip_editor.h b/gtk2_ardour/audio_clip_editor.h index 81060fec57..511b804cc6 100644 --- a/gtk2_ardour/audio_clip_editor.h +++ b/gtk2_ardour/audio_clip_editor.h @@ -134,7 +134,7 @@ public: ArdourCanvas::Line* end_line; ArdourCanvas::Line* loop_line; ArdourCanvas::Container* ruler_container; - ArdourCanvas::Ruler* minsec_ruler; + ArdourCanvas::Ruler* main_ruler; class ClipBBTMetric : public ArdourCanvas::Ruler::Metric { diff --git a/gtk2_ardour/cue_editor.cc b/gtk2_ardour/cue_editor.cc index 1f4b682cdc..cec71ef348 100644 --- a/gtk2_ardour/cue_editor.cc +++ b/gtk2_ardour/cue_editor.cc @@ -71,11 +71,15 @@ CueEditor::~CueEditor () void CueEditor::set_snapped_cursor_position (Temporal::timepos_t const & pos) { + EC_LOCAL_TEMPO_SCOPE; + } std::vector CueEditor::filter_to_unique_midi_region_views (RegionSelection const & ms) const { + EC_LOCAL_TEMPO_SCOPE; + std::vector mrv; return mrv; } @@ -83,17 +87,23 @@ CueEditor::filter_to_unique_midi_region_views (RegionSelection const & ms) const void CueEditor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const { + EC_LOCAL_TEMPO_SCOPE; + } StripableTimeAxisView* CueEditor::get_stripable_time_axis_by_id (const PBD::ID& id) const { + EC_LOCAL_TEMPO_SCOPE; + return nullptr; } TrackViewList CueEditor::axis_views_from_routes (std::shared_ptr) const { + EC_LOCAL_TEMPO_SCOPE; + TrackViewList tvl; return tvl; } @@ -101,42 +111,56 @@ CueEditor::axis_views_from_routes (std::shared_ptr) const ARDOUR::Location* CueEditor::find_location_from_marker (ArdourMarker*, bool&) const { + EC_LOCAL_TEMPO_SCOPE; + return nullptr; } ArdourMarker* CueEditor::find_marker_from_location_id (PBD::ID const&, bool) const { + EC_LOCAL_TEMPO_SCOPE; + return nullptr; } TempoMarker* CueEditor::find_marker_for_tempo (Temporal::TempoPoint const &) { + EC_LOCAL_TEMPO_SCOPE; + return nullptr; } MeterMarker* CueEditor::find_marker_for_meter (Temporal::MeterPoint const &) { + EC_LOCAL_TEMPO_SCOPE; + return nullptr; } void CueEditor::redisplay_grid (bool immediate_redraw) { + EC_LOCAL_TEMPO_SCOPE; + update_grid (); } Temporal::timecnt_t CueEditor::get_nudge_distance (Temporal::timepos_t const & pos, Temporal::timecnt_t& next) const { + EC_LOCAL_TEMPO_SCOPE; + return Temporal::timecnt_t (Temporal::AudioTime); } void CueEditor::instant_save() { + EC_LOCAL_TEMPO_SCOPE; + if (!_region) { return; } @@ -158,42 +182,58 @@ CueEditor::instant_save() void CueEditor::begin_selection_op_history () { + EC_LOCAL_TEMPO_SCOPE; + } void CueEditor::begin_reversible_selection_op (std::string cmd_name) { + EC_LOCAL_TEMPO_SCOPE; + } void CueEditor::commit_reversible_selection_op () { + EC_LOCAL_TEMPO_SCOPE; + } void CueEditor::abort_reversible_selection_op () { + EC_LOCAL_TEMPO_SCOPE; + } void CueEditor::undo_selection_op () { + EC_LOCAL_TEMPO_SCOPE; + } void CueEditor::redo_selection_op () { + EC_LOCAL_TEMPO_SCOPE; + } double CueEditor::get_y_origin () const { + EC_LOCAL_TEMPO_SCOPE; + return 0.; } void CueEditor::set_zoom_focus (Editing::ZoomFocus zf) { + EC_LOCAL_TEMPO_SCOPE; + using namespace Editing; /* We don't allow playhead for zoom focus here */ @@ -208,6 +248,8 @@ CueEditor::set_zoom_focus (Editing::ZoomFocus zf) void CueEditor::set_samples_per_pixel (samplecnt_t n) { + EC_LOCAL_TEMPO_SCOPE; + samples_per_pixel = n; ZoomChanged(); /* EMIT SIGNAL */ } @@ -215,12 +257,16 @@ CueEditor::set_samples_per_pixel (samplecnt_t n) samplecnt_t CueEditor::get_current_zoom () const { + EC_LOCAL_TEMPO_SCOPE; + return samples_per_pixel; } void CueEditor::reposition_and_zoom (samplepos_t pos, double spp) { + EC_LOCAL_TEMPO_SCOPE; + pending_visual_change.add (VisualChange::ZoomLevel); pending_visual_change.samples_per_pixel = spp; @@ -233,36 +279,30 @@ CueEditor::reposition_and_zoom (samplepos_t pos, double spp) void CueEditor::set_mouse_mode (Editing::MouseMode, bool force) { + EC_LOCAL_TEMPO_SCOPE; + } void CueEditor::step_mouse_mode (bool next) { + EC_LOCAL_TEMPO_SCOPE; + } Gdk::Cursor* CueEditor::get_canvas_cursor () const { + EC_LOCAL_TEMPO_SCOPE; + return nullptr; } -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); -} - void CueEditor::do_undo (uint32_t n) { + EC_LOCAL_TEMPO_SCOPE; + if (_drags->active ()) { _drags->abort (); } @@ -273,6 +313,8 @@ CueEditor::do_undo (uint32_t n) void CueEditor::do_redo (uint32_t n) { + EC_LOCAL_TEMPO_SCOPE; + if (_drags->active ()) { _drags->abort (); } @@ -283,12 +325,16 @@ CueEditor::do_redo (uint32_t n) void CueEditor::history_changed () { + EC_LOCAL_TEMPO_SCOPE; + update_undo_redo_actions (_history); } Temporal::timepos_t CueEditor::_get_preferred_edit_position (Editing::EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas) { + EC_LOCAL_TEMPO_SCOPE; + samplepos_t where; bool in_track_canvas = false; @@ -302,6 +348,8 @@ CueEditor::_get_preferred_edit_position (Editing::EditIgnoreOption ignore, bool void CueEditor::build_upper_toolbar () { + EC_LOCAL_TEMPO_SCOPE; + using namespace Gtk::Menu_Helpers; Gtk::HBox* mode_box = manage(new Gtk::HBox); @@ -423,6 +471,8 @@ CueEditor::build_upper_toolbar () void CueEditor::build_zoom_focus_menu () { + EC_LOCAL_TEMPO_SCOPE; + using namespace Gtk::Menu_Helpers; using namespace Editing; @@ -436,6 +486,8 @@ CueEditor::build_zoom_focus_menu () bool CueEditor::bang_button_press (GdkEventButton* ev) { + EC_LOCAL_TEMPO_SCOPE; + if (!ref.trigger()) { return true; } @@ -448,6 +500,8 @@ CueEditor::bang_button_press (GdkEventButton* ev) bool CueEditor::play_button_press (GdkEventButton* ev) { + EC_LOCAL_TEMPO_SCOPE; + if (_session && _region) { _session->request_locate (_region->position().samples()); _session->request_roll (); @@ -459,6 +513,8 @@ CueEditor::play_button_press (GdkEventButton* ev) bool CueEditor::loop_button_press (GdkEventButton* ev) { + EC_LOCAL_TEMPO_SCOPE; + if (!_region) { return true; } @@ -476,6 +532,8 @@ CueEditor::loop_button_press (GdkEventButton* ev) bool CueEditor::solo_button_press (GdkEventButton* ev) { + EC_LOCAL_TEMPO_SCOPE; + if (!_track) { return true; } @@ -488,6 +546,8 @@ CueEditor::solo_button_press (GdkEventButton* ev) bool CueEditor::rec_button_press (GdkEventButton* ev) { + EC_LOCAL_TEMPO_SCOPE; + if (ev->button != 1) { return false; } @@ -510,6 +570,8 @@ CueEditor::rec_button_press (GdkEventButton* ev) void CueEditor::blink_rec_enable (bool onoff) { + EC_LOCAL_TEMPO_SCOPE; + if (onoff) { rec_enable_button.set_active_state (Gtkmm2ext::ExplicitActive); } else { @@ -520,6 +582,8 @@ CueEditor::blink_rec_enable (bool onoff) void CueEditor::trigger_arm_change () { + EC_LOCAL_TEMPO_SCOPE; + if (!ref.trigger()) { return; } @@ -536,6 +600,8 @@ CueEditor::trigger_arm_change () void CueEditor::rec_enable_change () { + EC_LOCAL_TEMPO_SCOPE; + if (!ref.box()) { return; } @@ -568,12 +634,16 @@ CueEditor::rec_enable_change () void CueEditor::set_recording_length (Temporal::BBT_Offset dur) { + EC_LOCAL_TEMPO_SCOPE; + rec_length = dur; } void CueEditor::scrolled () { + EC_LOCAL_TEMPO_SCOPE; + pending_visual_change.add (VisualChange::TimeOrigin); pending_visual_change.time_origin = horizontal_adjustment.get_value() * samples_per_pixel; ensure_visual_change_idle_handler (); @@ -582,6 +652,8 @@ CueEditor::scrolled () bool CueEditor::canvas_pre_event (GdkEvent* ev) { + EC_LOCAL_TEMPO_SCOPE; + switch (ev->type) { case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: @@ -599,6 +671,8 @@ CueEditor::canvas_pre_event (GdkEvent* ev) bool CueEditor::autoscroll_active () const { + EC_LOCAL_TEMPO_SCOPE; + return autoscroll_connection.connected (); } @@ -610,6 +684,8 @@ CueEditor::autoscroll_active () const void CueEditor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers) { + EC_LOCAL_TEMPO_SCOPE; + if (!UIConfiguration::instance().get_autoscroll_editor () || autoscroll_active ()) { return; } @@ -681,6 +757,8 @@ CueEditor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_header bool CueEditor::autoscroll_canvas () { + EC_LOCAL_TEMPO_SCOPE; + using std::max; using std::min; int x, y; @@ -881,6 +959,8 @@ CueEditor::autoscroll_canvas () void CueEditor::start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const ArdourCanvas::Rect& boundary) { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { return; } @@ -904,6 +984,8 @@ CueEditor::start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const Ard void CueEditor::stop_canvas_autoscroll () { + EC_LOCAL_TEMPO_SCOPE; + autoscroll_connection.disconnect (); autoscroll_cnt = 0; } @@ -911,6 +993,8 @@ CueEditor::stop_canvas_autoscroll () void CueEditor::visual_changer (const VisualChange& vc) { + EC_LOCAL_TEMPO_SCOPE; + /** * Changed first so the correct horizontal canvas position is calculated in * EditingContext::set_horizontal_position @@ -951,6 +1035,8 @@ CueEditor::visual_changer (const VisualChange& vc) void CueEditor::catch_pending_show_region () { + EC_LOCAL_TEMPO_SCOPE; + if (_visible_pending_region) { std::shared_ptr r (_visible_pending_region); _visible_pending_region.reset (); @@ -961,6 +1047,8 @@ CueEditor::catch_pending_show_region () RegionSelection CueEditor::region_selection() { + EC_LOCAL_TEMPO_SCOPE; + RegionSelection rs; /* there is never any region-level selection in a pianoroll */ return rs; @@ -969,6 +1057,8 @@ CueEditor::region_selection() void CueEditor::mouse_mode_chosen (Editing::MouseMode m) { + EC_LOCAL_TEMPO_SCOPE; + if (!mouse_mode_actions[m]->get_active()) { /* this was just the notification that the old mode has been * left. we'll get called again with the new mode active in a @@ -989,6 +1079,8 @@ CueEditor::mouse_mode_chosen (Editing::MouseMode m) std::pair CueEditor::max_zoom_extent() const { + EC_LOCAL_TEMPO_SCOPE; + if (_region) { Temporal::Beats len; @@ -1011,6 +1103,8 @@ CueEditor::max_zoom_extent() const void CueEditor::zoom_to_show (Temporal::timecnt_t const & duration) { + EC_LOCAL_TEMPO_SCOPE; + if (!_track_canvas_width) { zoom_in_allocate = true; return; @@ -1022,6 +1116,8 @@ CueEditor::zoom_to_show (Temporal::timecnt_t const & duration) void CueEditor::full_zoom_clicked() { + EC_LOCAL_TEMPO_SCOPE; + /* XXXX NEED LOCAL TEMPO MAP */ std::pair dur (max_zoom_extent()); @@ -1032,12 +1128,16 @@ CueEditor::full_zoom_clicked() void CueEditor::set_show_source (bool yn) { + EC_LOCAL_TEMPO_SCOPE; + show_source = yn; } void CueEditor::update_solo_display () { + EC_LOCAL_TEMPO_SCOPE; + if (_track->solo_control()->get_value()) { solo_button.set_active_state (Gtkmm2ext::ExplicitActive); } else { @@ -1048,6 +1148,8 @@ CueEditor::update_solo_display () void CueEditor::set_track (std::shared_ptr t) { + EC_LOCAL_TEMPO_SCOPE; + _track = t; _track->solo_control()->Changed.connect (object_connections, invalidator (*this), std::bind (&CueEditor::update_solo_display, this), gui_context()); update_solo_display (); @@ -1056,6 +1158,8 @@ CueEditor::set_track (std::shared_ptr t) void CueEditor::set_region (std::shared_ptr r) { + EC_LOCAL_TEMPO_SCOPE; + if (r == _region) { return; } @@ -1064,6 +1168,9 @@ CueEditor::set_region (std::shared_ptr r) _region = r; + std::shared_ptr tmap (new TempoMap (_region->tempo(), _region->meter())); + start_local_tempo_map (tmap); + if (!get_canvas()->is_visible()) { _visible_pending_region = r; } else { @@ -1074,6 +1181,8 @@ CueEditor::set_region (std::shared_ptr r) void CueEditor::maybe_set_from_rsu () { + EC_LOCAL_TEMPO_SCOPE; + RegionUISettingsManager::iterator rsu = ARDOUR_UI::instance()->region_ui_settings_manager.find (_region->id()); if (rsu != ARDOUR_UI::instance()->region_ui_settings_manager.end()) { set_from_rsu (rsu->second); @@ -1083,6 +1192,8 @@ CueEditor::maybe_set_from_rsu () void CueEditor::set_from_rsu (RegionUISettings& rsu) { + EC_LOCAL_TEMPO_SCOPE; + follow_playhead_action->set_active (rsu.follow_playhead); /* XXXX play selection */ @@ -1101,6 +1212,8 @@ CueEditor::set_from_rsu (RegionUISettings& rsu) void CueEditor::set_trigger (TriggerReference& tref) { + EC_LOCAL_TEMPO_SCOPE; + if (tref == ref) { return; } @@ -1122,6 +1235,8 @@ CueEditor::set_trigger (TriggerReference& tref) void CueEditor::ruler_locate (GdkEventButton* ev) { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { return; } @@ -1143,6 +1258,8 @@ CueEditor::ruler_locate (GdkEventButton* ev) void CueEditor::maybe_set_count_in () { + EC_LOCAL_TEMPO_SCOPE; + if (!ref.box()) { std::cerr << "msci no box\n"; return; @@ -1179,6 +1296,8 @@ CueEditor::maybe_set_count_in () void CueEditor::count_in (Temporal::timepos_t audible, unsigned int clock_interval_msecs) { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { return; } @@ -1224,6 +1343,8 @@ CueEditor::count_in (Temporal::timepos_t audible, unsigned int clock_interval_ms bool CueEditor::ruler_event (GdkEvent* ev) { + EC_LOCAL_TEMPO_SCOPE; + switch (ev->type) { case GDK_BUTTON_RELEASE: if (ev->button.button == 1) { @@ -1240,6 +1361,8 @@ CueEditor::ruler_event (GdkEvent* ev) void CueEditor::data_captured (samplecnt_t total_duration) { + EC_LOCAL_TEMPO_SCOPE; + data_capture_duration = total_duration; if (!idle_update_queued.exchange (1)) { @@ -1250,6 +1373,8 @@ CueEditor::data_captured (samplecnt_t total_duration) bool CueEditor::idle_data_captured () { + EC_LOCAL_TEMPO_SCOPE; + if (!ref.box()) { return false; } @@ -1274,6 +1399,7 @@ CueEditor::idle_data_captured () void CueEditor::unset (bool trigger_too) { + end_local_tempo_map (); _history.clear (); history_connection.disconnect(); _update_connection.disconnect(); @@ -1293,6 +1419,8 @@ CueEditor::unset (bool trigger_too) void CueEditor::session_going_away () { + EC_LOCAL_TEMPO_SCOPE; + EditingContext::session_going_away (); unset (true); } @@ -1300,6 +1428,8 @@ CueEditor::session_going_away () void CueEditor::load_bindings () { + EC_LOCAL_TEMPO_SCOPE; + load_shared_bindings (); for (auto & b : bindings) { b->associate (); @@ -1310,6 +1440,8 @@ CueEditor::load_bindings () void CueEditor::register_actions () { + EC_LOCAL_TEMPO_SCOPE; + editor_actions = ActionManager::create_action_group (own_bindings, editor_name()); bind_mouse_mode_buttons (); } @@ -1317,12 +1449,16 @@ CueEditor::register_actions () ArdourCanvas::GtkCanvasViewport* CueEditor::get_canvas_viewport() const { + EC_LOCAL_TEMPO_SCOPE; + return const_cast(&_canvas_viewport); } ArdourCanvas::GtkCanvas* CueEditor::get_canvas() const { + EC_LOCAL_TEMPO_SCOPE; + return &_canvas; } @@ -1330,6 +1466,8 @@ CueEditor::get_canvas() const int CueEditor::set_state (XMLNode const & node, int version) { + EC_LOCAL_TEMPO_SCOPE; + set_common_editing_state (node); return 0; } @@ -1337,6 +1475,8 @@ CueEditor::set_state (XMLNode const & node, int version) XMLNode& CueEditor::get_state () const { + EC_LOCAL_TEMPO_SCOPE; + XMLNode* node (new XMLNode (editor_name())); get_common_editing_state (*node); return *node; @@ -1354,6 +1494,8 @@ edit_last_mark_label (std::vector& marks, const std:: void CueEditor::metric_get_bbt (std::vector& marks, samplepos_t leftmost, samplepos_t rightmost, gint /*maxchars*/) { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { return; } diff --git a/gtk2_ardour/cue_editor.h b/gtk2_ardour/cue_editor.h index 95c62e93df..9f4335aa0d 100644 --- a/gtk2_ardour/cue_editor.h +++ b/gtk2_ardour/cue_editor.h @@ -113,9 +113,6 @@ class CueEditor : public EditingContext, public PBD::HistoryOwner 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); - void scrolled (); bool canvas_pre_event (GdkEvent*); void catch_pending_show_region (); diff --git a/gtk2_ardour/editing_context.cc b/gtk2_ardour/editing_context.cc index 3200666009..f119a877cc 100644 --- a/gtk2_ardour/editing_context.cc +++ b/gtk2_ardour/editing_context.cc @@ -129,7 +129,6 @@ EditingContext::EditingContext (std::string const & name) , selection (new Selection (this, true)) , cut_buffer (new Selection (this, false)) , _selection_memento (new SelectionMemento()) - , _verbose_cursor (nullptr) , samples_per_pixel (2048) , bbt_ruler_scale (bbt_show_many) , bbt_bars (0) @@ -153,6 +152,8 @@ EditingContext::EditingContext (std::string const & name) , grid_lines (nullptr) , time_line_group (nullptr) , temporary_zoom_focus_change (false) + , _dragging_playhead (false) + { using namespace Gtk::Menu_Helpers; @@ -254,14 +255,13 @@ EditingContext::~EditingContext() ActionManager::drop_action_group (channel_actions); ActionManager::drop_action_group (velocity_actions); ActionManager::drop_action_group (zoom_actions); - - delete _verbose_cursor; - delete grid_lines; } void EditingContext::ui_parameter_changed (string parameter) { + EC_LOCAL_TEMPO_SCOPE; + if (parameter == "sound-midi-notes") { if (UIConfiguration::instance().get_sound_midi_notes()) { play_note_selection_button.set_active_state (Gtkmm2ext::ExplicitActive); @@ -275,11 +275,15 @@ EditingContext::ui_parameter_changed (string parameter) void EditingContext::parameter_changed (string parameter) { + EC_LOCAL_TEMPO_SCOPE; + } void EditingContext::set_session (ARDOUR::Session* s) { + EC_LOCAL_TEMPO_SCOPE; + SessionHandlePtr::set_session (s); disable_automation_bindings (); } @@ -287,6 +291,8 @@ EditingContext::set_session (ARDOUR::Session* s) void EditingContext::set_selected_midi_region_view (MidiRegionView& mrv) { + EC_LOCAL_TEMPO_SCOPE; + /* clear note selection in all currently selected MidiRegionViews */ if (get_selection().regions.contains (&mrv) && get_selection().regions.size() == 1) { @@ -301,6 +307,8 @@ EditingContext::set_selected_midi_region_view (MidiRegionView& mrv) void EditingContext::register_automation_actions (Bindings* automation_bindings, std::string const & prefix) { + EC_LOCAL_TEMPO_SCOPE; + _automation_actions = ActionManager::create_action_group (automation_bindings, prefix + X_("Automation")); reg_sens (_automation_actions, "create-point", _("Create Automation Point"), sigc::mem_fun (*this, &EditingContext::automation_create_point_at_edit_point)); @@ -315,6 +323,8 @@ EditingContext::register_automation_actions (Bindings* automation_bindings, std: void EditingContext::enable_automation_bindings () { + EC_LOCAL_TEMPO_SCOPE; + if (_automation_actions) { ActionManager::set_sensitive (_automation_actions, true); } @@ -323,6 +333,8 @@ EditingContext::enable_automation_bindings () void EditingContext::disable_automation_bindings () { + EC_LOCAL_TEMPO_SCOPE; + if (_automation_actions) { ActionManager::set_sensitive (_automation_actions, false); } @@ -331,6 +343,8 @@ EditingContext::disable_automation_bindings () void EditingContext::set_action_defaults () { + EC_LOCAL_TEMPO_SCOPE; + #ifndef LIVETRAX follow_playhead_action->set_active (false); follow_playhead_action->set_active (true); @@ -338,6 +352,10 @@ EditingContext::set_action_defaults () follow_playhead_action->set_active (true); follow_playhead_action->set_active (false); #endif + + stationary_playhead_action->set_active (true); + stationary_playhead_action->set_active (false); + mouse_mode_actions[Editing::MouseObject]->set_active (false); mouse_mode_actions[Editing::MouseObject]->set_active (true); zoom_focus_actions[Editing::ZoomFocusLeft]->set_active (false); @@ -368,15 +386,15 @@ EditingContext::set_action_defaults () void EditingContext::register_common_actions (Bindings* common_bindings, std::string const & prefix) { + EC_LOCAL_TEMPO_SCOPE; + _common_actions = ActionManager::create_action_group (common_bindings, prefix + X_("Editing")); reg_sens (_common_actions, "temporal-zoom-out", _("Zoom Out"), sigc::bind (sigc::mem_fun (*this, &EditingContext::temporal_zoom_step), true)); reg_sens (_common_actions, "temporal-zoom-in", _("Zoom In"), sigc::bind (sigc::mem_fun (*this, &EditingContext::temporal_zoom_step), false)); - /* toggle action that represents state */ - follow_playhead_action = toggle_reg_sens (_common_actions, "follow-playhead", _("Follow Playhead"), sigc::mem_fun (*this, &EditingContext::follow_playhead_chosen)); - /* invokable action that toggles the stateful action */ - reg_sens (_common_actions, "toggle-follow-playhead", _("Follow Playhead"), sigc::mem_fun (*this, &EditingContext::toggle_follow_playhead)); + follow_playhead_action = toggle_reg_sens (_common_actions, "toggle-follow-playhead", _("Follow Playhead"), sigc::mem_fun (*this, &EditingContext::follow_playhead_chosen)); + stationary_playhead_action = toggle_reg_sens (_common_actions, "toggle-stationary-playhead", _("Stationary Playhead"), (mem_fun(*this, &EditingContext::stationary_playhead_chosen))); undo_action = reg_sens (_common_actions, "undo", S_("Command|Undo"), sigc::bind (sigc::mem_fun (*this, &EditingContext::undo), 1U)); redo_action = reg_sens (_common_actions, "redo", _("Redo"), sigc::bind (sigc::mem_fun (*this, &EditingContext::redo), 1U)); @@ -457,6 +475,8 @@ EditingContext::register_common_actions (Bindings* common_bindings, std::string void EditingContext::register_midi_actions (Bindings* midi_bindings, std::string const & prefix) { + EC_LOCAL_TEMPO_SCOPE; + _midi_actions = ActionManager::create_action_group (midi_bindings, prefix + X_("Notes")); /* two versions to allow same action for Delete and Backspace */ @@ -587,6 +607,8 @@ EditingContext::register_midi_actions (Bindings* midi_bindings, std::string cons void EditingContext::midi_action (void (MidiView::*method)()) { + EC_LOCAL_TEMPO_SCOPE; + MidiRegionSelection ms = get_selection().midi_regions(); if (ms.empty()) { @@ -614,6 +636,8 @@ EditingContext::midi_action (void (MidiView::*method)()) void EditingContext::next_grid_choice () { + EC_LOCAL_TEMPO_SCOPE; + switch (grid_type()) { case Editing::GridTypeBeatDiv32: set_grid_type (Editing::GridTypeNone); @@ -659,6 +683,8 @@ EditingContext::next_grid_choice () void EditingContext::prev_grid_choice () { + EC_LOCAL_TEMPO_SCOPE; + switch (grid_type()) { case Editing::GridTypeBeatDiv32: set_grid_type (Editing::GridTypeBeatDiv16); @@ -704,6 +730,8 @@ EditingContext::prev_grid_choice () void EditingContext::grid_type_chosen (GridType gt) { + EC_LOCAL_TEMPO_SCOPE; + /* this is driven by a toggle on a radio group, and so is invoked twice, once for the item that became inactive and once for the one that became active. @@ -753,6 +781,8 @@ EditingContext::grid_type_chosen (GridType gt) void EditingContext::draw_length_chosen (GridType type) { + EC_LOCAL_TEMPO_SCOPE; + /* this is driven by a toggle on a radio group, and so is invoked twice, once for the item that became inactive and once for the one that became active. @@ -781,6 +811,8 @@ EditingContext::draw_length_chosen (GridType type) void EditingContext::draw_velocity_chosen (int v) { + EC_LOCAL_TEMPO_SCOPE; + /* this is driven by a toggle on a radio group, and so is invoked twice, once for the item that became inactive and once for the one that became active. @@ -812,6 +844,8 @@ EditingContext::draw_velocity_chosen (int v) void EditingContext::draw_channel_chosen (int c) { + EC_LOCAL_TEMPO_SCOPE; + /* this is driven by a toggle on a radio group, and so is invoked twice, once for the item that became inactive and once for the one that became active. @@ -843,6 +877,8 @@ EditingContext::draw_channel_chosen (int c) void EditingContext::cycle_snap_mode () { + EC_LOCAL_TEMPO_SCOPE; + switch (snap_mode()) { case SnapOff: case SnapNormal: @@ -857,6 +893,8 @@ EditingContext::cycle_snap_mode () void EditingContext::snap_mode_chosen (SnapMode mode) { + EC_LOCAL_TEMPO_SCOPE; + /* this is driven by a toggle on a radio group, and so is invoked twice, once for the item that became inactive and once for the one that became active. @@ -888,6 +926,8 @@ EditingContext::snap_mode_chosen (SnapMode mode) GridType EditingContext::grid_type() const { + EC_LOCAL_TEMPO_SCOPE; + for (auto const & [grid_type,action] : grid_actions) { if (action->get_active()) { return grid_type; @@ -900,6 +940,8 @@ EditingContext::grid_type() const GridType EditingContext::draw_length() const { + EC_LOCAL_TEMPO_SCOPE; + for (auto const & [len,action] : draw_length_actions) { if (action->get_active()) { return len; @@ -912,6 +954,8 @@ EditingContext::draw_length() const int EditingContext::draw_velocity() const { + EC_LOCAL_TEMPO_SCOPE; + for (auto const & [vel,action] : draw_velocity_actions) { if (action->get_active()) { return vel; @@ -924,6 +968,8 @@ EditingContext::draw_velocity() const int EditingContext::draw_channel() const { + EC_LOCAL_TEMPO_SCOPE; + for (auto const & [chn,action] : draw_channel_actions) { if (action->get_active()) { return chn; @@ -936,12 +982,16 @@ EditingContext::draw_channel() const bool EditingContext::grid_musical() const { + EC_LOCAL_TEMPO_SCOPE; + return grid_type_is_musical (grid_type()); } bool EditingContext::grid_type_is_musical(GridType gt) const { + EC_LOCAL_TEMPO_SCOPE; + switch (gt) { case GridTypeBeatDiv32: case GridTypeBeatDiv28: @@ -973,6 +1023,8 @@ EditingContext::grid_type_is_musical(GridType gt) const SnapMode EditingContext::snap_mode() const { + EC_LOCAL_TEMPO_SCOPE; + for (auto const & [mode,action] : snap_mode_actions) { if (action->get_active()) { return mode; @@ -985,12 +1037,16 @@ EditingContext::snap_mode() const void EditingContext::set_draw_length (GridType gt) { + EC_LOCAL_TEMPO_SCOPE; + draw_length_actions[gt]->set_active (true); } void EditingContext::set_draw_velocity (int v) { + EC_LOCAL_TEMPO_SCOPE; + if (v == DRAW_VEL_AUTO) { draw_velocity_actions[v]->set_active (true); } else { @@ -1001,6 +1057,8 @@ EditingContext::set_draw_velocity (int v) void EditingContext::set_draw_channel (int c) { + EC_LOCAL_TEMPO_SCOPE; + if (c == DRAW_CHAN_AUTO) { draw_channel_actions[c]->set_active (true); } else { @@ -1011,18 +1069,24 @@ EditingContext::set_draw_channel (int c) void EditingContext::set_grid_type (GridType gt) { + EC_LOCAL_TEMPO_SCOPE; + grid_actions[gt]->set_active (true); } void EditingContext::set_snap_mode (SnapMode mode) { + EC_LOCAL_TEMPO_SCOPE; + snap_mode_actions[mode]->set_active (true);; } void EditingContext::build_grid_type_menu () { + EC_LOCAL_TEMPO_SCOPE; + using namespace Menu_Helpers; /* there's no Grid, but if Snap is engaged, the Snap preferences will be applied */ @@ -1078,6 +1142,8 @@ EditingContext::build_grid_type_menu () void EditingContext::build_draw_midi_menus () { + EC_LOCAL_TEMPO_SCOPE; + using namespace Menu_Helpers; /* Note-Length when drawing */ @@ -1135,18 +1201,24 @@ EditingContext::build_draw_midi_menus () bool EditingContext::drag_active () const { + EC_LOCAL_TEMPO_SCOPE; + return _drags->active(); } bool EditingContext::preview_video_drag_active () const { + EC_LOCAL_TEMPO_SCOPE; + return _drags->preview_video (); } Temporal::TimeDomain EditingContext::time_domain () const { + EC_LOCAL_TEMPO_SCOPE; + if (_session) { return _session->config.get_default_time_domain(); } @@ -1174,15 +1246,55 @@ EditingContext::time_domain () const return Temporal::BeatTime; } +void +EditingContext::toggle_stationary_playhead () +{ + EC_LOCAL_TEMPO_SCOPE; + + stationary_playhead_action->set_active (!stationary_playhead_action->get_active ()); +} + +void +EditingContext::stationary_playhead_chosen () +{ + EC_LOCAL_TEMPO_SCOPE; + + instant_save (); +} + +void +EditingContext::set_stationary_playhead (bool yn) +{ + EC_LOCAL_TEMPO_SCOPE; + + stationary_playhead_action->set_active (yn); +} + +bool +EditingContext::stationary_playhead () const +{ + EC_LOCAL_TEMPO_SCOPE; + + if (!stationary_playhead_action) { + return false; + } + + return stationary_playhead_action->get_active (); +} + void EditingContext::toggle_follow_playhead () { + EC_LOCAL_TEMPO_SCOPE; + set_follow_playhead (!follow_playhead_action->get_active(), true); } void EditingContext::follow_playhead_chosen () { + EC_LOCAL_TEMPO_SCOPE; + instant_save (); } @@ -1192,6 +1304,8 @@ EditingContext::follow_playhead_chosen () void EditingContext::set_follow_playhead (bool yn, bool catch_up) { + EC_LOCAL_TEMPO_SCOPE; + assert (follow_playhead_action); follow_playhead_action->set_active (yn); if (yn && catch_up) { @@ -1200,33 +1314,55 @@ EditingContext::set_follow_playhead (bool yn, bool catch_up) } } +bool +EditingContext::follow_playhead() const +{ + EC_LOCAL_TEMPO_SCOPE; + + if (!follow_playhead_action) { + return false; + } + + return follow_playhead_action->get_active (); +} + double EditingContext::time_to_pixel (timepos_t const & pos) const { + EC_LOCAL_TEMPO_SCOPE; + return sample_to_pixel (pos.samples()); } double EditingContext::time_to_pixel_unrounded (timepos_t const & pos) const { + EC_LOCAL_TEMPO_SCOPE; + return sample_to_pixel_unrounded (pos.samples()); } double EditingContext::time_delta_to_pixel (timepos_t const& start, timepos_t const& end) const { + EC_LOCAL_TEMPO_SCOPE; + return sample_to_pixel (end.samples()) - sample_to_pixel (start.samples ()); } double EditingContext::duration_to_pixels (timecnt_t const & dur) const { + EC_LOCAL_TEMPO_SCOPE; + return sample_to_pixel (dur.samples()); } double EditingContext::duration_to_pixels_unrounded (timecnt_t const & dur) const { + EC_LOCAL_TEMPO_SCOPE; + return sample_to_pixel_unrounded (dur.samples()); } @@ -1238,6 +1374,8 @@ EditingContext::duration_to_pixels_unrounded (timecnt_t const & dur) const void EditingContext::snap_to_with_modifier (timepos_t& start, GdkEvent const * event, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap) const { + EC_LOCAL_TEMPO_SCOPE; + if (!_session || !event) { return; } @@ -1260,6 +1398,8 @@ EditingContext::snap_to_with_modifier (timepos_t& start, GdkEvent const * event, void EditingContext::snap_to (timepos_t& start, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap) const { + EC_LOCAL_TEMPO_SCOPE; + if (!_session || (snap_mode() == SnapOff && !ensure_snap)) { return; } @@ -1270,12 +1410,16 @@ EditingContext::snap_to (timepos_t& start, Temporal::RoundMode direction, SnapPr timepos_t EditingContext::snap_to_bbt (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref) const { + EC_LOCAL_TEMPO_SCOPE; + return snap_to_bbt_via_grid (presnap, direction, gpref, grid_type()); } timepos_t EditingContext::snap_to_bbt_via_grid (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref, GridType grid_type) const { + EC_LOCAL_TEMPO_SCOPE; + timepos_t ret(presnap); TempoMap::SharedPtr tmap (TempoMap::use()); @@ -1378,6 +1522,8 @@ EditingContext::snap_to_bbt_via_grid (timepos_t const & presnap, Temporal::Round void EditingContext::check_best_snap (timepos_t const & presnap, timepos_t &test, timepos_t &dist, timepos_t &best) const { + EC_LOCAL_TEMPO_SCOPE; + timepos_t diff = timepos_t (presnap.distance (test).abs ()); if (diff < dist) { dist = diff; @@ -1390,6 +1536,8 @@ EditingContext::check_best_snap (timepos_t const & presnap, timepos_t &test, tim timepos_t EditingContext::canvas_event_time (GdkEvent const * event, double* pcx, double* pcy) const { + EC_LOCAL_TEMPO_SCOPE; + timepos_t pos (canvas_event_sample (event, pcx, pcy)); if (time_domain() == Temporal::AudioTime) { @@ -1402,6 +1550,8 @@ EditingContext::canvas_event_time (GdkEvent const * event, double* pcx, double* samplepos_t EditingContext::canvas_event_sample (GdkEvent const * event, double* pcx, double* pcy) const { + EC_LOCAL_TEMPO_SCOPE; + double x; double y; @@ -1431,6 +1581,8 @@ EditingContext::canvas_event_sample (GdkEvent const * event, double* pcx, double uint32_t EditingContext::count_bars (Beats const & start, Beats const & end) const { + EC_LOCAL_TEMPO_SCOPE; + TempoMapPoints bar_grid; TempoMap::SharedPtr tmap (TempoMap::use()); bar_grid.reserve (4096); @@ -1443,6 +1595,8 @@ EditingContext::count_bars (Beats const & start, Beats const & end) const void EditingContext::compute_bbt_ruler_scale (samplepos_t lower, samplepos_t upper) { + EC_LOCAL_TEMPO_SCOPE; + if (_session == 0) { return; } @@ -1537,6 +1691,8 @@ EditingContext::compute_bbt_ruler_scale (samplepos_t lower, samplepos_t upper) Quantize* EditingContext::get_quantize_op () { + EC_LOCAL_TEMPO_SCOPE; + if (!quantize_dialog) { quantize_dialog = new QuantizeDialog (*this); } @@ -1562,6 +1718,8 @@ EditingContext::get_quantize_op () timecnt_t EditingContext::relative_distance (timepos_t const & origin, timecnt_t const & duration, Temporal::TimeDomain domain) { + EC_LOCAL_TEMPO_SCOPE; + return Temporal::TempoMap::use()->convert_duration (duration, origin, domain); } @@ -1574,6 +1732,8 @@ EditingContext::relative_distance (timepos_t const & origin, timecnt_t const & d timecnt_t EditingContext::snap_relative_time_to_relative_time (timepos_t const & origin, timecnt_t const & x, bool ensure_snap) const { + EC_LOCAL_TEMPO_SCOPE; + /* x is relative to origin, convert it to global absolute time */ timepos_t const session_pos = origin + x; @@ -1591,16 +1751,24 @@ EditingContext::snap_relative_time_to_relative_time (timepos_t const & origin, t return origin.distance (snapped); } -std::shared_ptr -EditingContext::start_local_tempo_map (std::shared_ptr) +void +EditingContext::start_local_tempo_map (std::shared_ptr map) { - /* default is a no-op */ - return Temporal::TempoMap::use (); + _local_tempo_map = map; +} + +void +EditingContext::end_local_tempo_map () +{ + _local_tempo_map.reset (); + Temporal::TempoMap::fetch (); } bool EditingContext::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type) { + EC_LOCAL_TEMPO_SCOPE; + if (!session () || session()->loading () || session()->deletion_in_progress ()) { return false; } @@ -1645,6 +1813,8 @@ EditingContext::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType void EditingContext::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event) { + EC_LOCAL_TEMPO_SCOPE; + using namespace Menu_Helpers; NoteBase* note = reinterpret_cast(item->get_data("notebase")); @@ -1690,6 +1860,8 @@ EditingContext::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* eve XMLNode* EditingContext::button_settings () const { + EC_LOCAL_TEMPO_SCOPE; + XMLNode* settings = ARDOUR_UI::instance()->editor_settings(); XMLNode* node = find_named_node (*settings, X_("Buttons")); @@ -1703,12 +1875,16 @@ EditingContext::button_settings () const EditingContext::MidiViews EditingContext::filter_to_unique_midi_region_views (RegionSelection const & rs) const { + EC_LOCAL_TEMPO_SCOPE; + return filter_to_unique_midi_region_views (midiviews_from_region_selection (rs)); } EditingContext::MidiViews EditingContext::filter_to_unique_midi_region_views (MidiViews const & mvs) const { + EC_LOCAL_TEMPO_SCOPE; + typedef std::pair,timepos_t> MapEntry; std::set single_region_set; @@ -1738,6 +1914,8 @@ EditingContext::filter_to_unique_midi_region_views (MidiViews const & mvs) const EditingContext::MidiViews EditingContext::midiviews_from_region_selection (RegionSelection const & rs) const { + EC_LOCAL_TEMPO_SCOPE; + MidiViews views; for (auto & rv : rs) { @@ -1753,6 +1931,8 @@ EditingContext::midiviews_from_region_selection (RegionSelection const & rs) con void EditingContext::quantize_region () { + EC_LOCAL_TEMPO_SCOPE; + if (_session) { quantize_regions (midiviews_from_region_selection (region_selection())); } @@ -1761,6 +1941,8 @@ EditingContext::quantize_region () void EditingContext::quantize_regions (const MidiViews& rs) { + EC_LOCAL_TEMPO_SCOPE; + if (rs.empty()) { std::cerr << "no regions\n"; return; @@ -1782,6 +1964,8 @@ EditingContext::quantize_regions (const MidiViews& rs) void EditingContext::legatize_region (bool shrink_only) { + EC_LOCAL_TEMPO_SCOPE; + if (_session) { legatize_regions (midiviews_from_region_selection (region_selection ()), shrink_only); } @@ -1790,6 +1974,8 @@ EditingContext::legatize_region (bool shrink_only) void EditingContext::legatize_regions (const MidiViews& rs, bool shrink_only) { + EC_LOCAL_TEMPO_SCOPE; + if (rs.empty()) { return; } @@ -1801,6 +1987,8 @@ EditingContext::legatize_regions (const MidiViews& rs, bool shrink_only) void EditingContext::transform_region () { + EC_LOCAL_TEMPO_SCOPE; + if (_session) { transform_regions (midiviews_from_region_selection (region_selection ())); } @@ -1809,6 +1997,8 @@ EditingContext::transform_region () void EditingContext::transform_regions (const MidiViews& rs) { + EC_LOCAL_TEMPO_SCOPE; + if (rs.empty()) { return; } @@ -1828,6 +2018,8 @@ EditingContext::transform_regions (const MidiViews& rs) void EditingContext::transpose_region () { + EC_LOCAL_TEMPO_SCOPE; + if (_session) { transpose_regions (midiviews_from_region_selection (region_selection ())); } @@ -1836,6 +2028,8 @@ EditingContext::transpose_region () void EditingContext::transpose_regions (const MidiViews& rs) { + EC_LOCAL_TEMPO_SCOPE; + if (rs.empty()) { return; } @@ -1852,6 +2046,8 @@ EditingContext::transpose_regions (const MidiViews& rs) void EditingContext::edit_notes (MidiView* mrv) { + EC_LOCAL_TEMPO_SCOPE; + MidiView::Selection const & s = mrv->selection(); if (s.empty ()) { @@ -1867,6 +2063,8 @@ EditingContext::edit_notes (MidiView* mrv) void EditingContext::note_edit_done (int r, EditNoteDialog* d) { + EC_LOCAL_TEMPO_SCOPE; + d->done (r); delete d; } @@ -1874,6 +2072,8 @@ EditingContext::note_edit_done (int r, EditNoteDialog* d) PBD::Command* EditingContext::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiView& mrv) { + EC_LOCAL_TEMPO_SCOPE; + Evoral::Sequence::Notes selected; mrv.selection_as_notelist (selected, true); @@ -1892,12 +2092,16 @@ EditingContext::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiView& m void EditingContext::apply_midi_note_edit_op (MidiOperator& op, const RegionSelection& rs) { + EC_LOCAL_TEMPO_SCOPE; + apply_midi_note_edit_op (op, midiviews_from_region_selection (rs)); } void EditingContext::apply_midi_note_edit_op (MidiOperator& op, const MidiViews& rs) { + EC_LOCAL_TEMPO_SCOPE; + if (rs.empty()) { return; } @@ -1928,12 +2132,16 @@ EditingContext::apply_midi_note_edit_op (MidiOperator& op, const MidiViews& rs) double EditingContext::horizontal_position () const { + EC_LOCAL_TEMPO_SCOPE; + return horizontal_adjustment.get_value(); } void EditingContext::set_horizontal_position (double p) { + EC_LOCAL_TEMPO_SCOPE; + p = std::max (0., p); horizontal_adjustment.set_value (p); @@ -1943,6 +2151,8 @@ EditingContext::set_horizontal_position (double p) Gdk::Cursor* EditingContext::get_canvas_cursor () const { + EC_LOCAL_TEMPO_SCOPE; + Glib::RefPtr win = get_canvas_viewport()->get_window(); if (win) { @@ -1955,6 +2165,8 @@ EditingContext::get_canvas_cursor () const void EditingContext::set_canvas_cursor (Gdk::Cursor* cursor) { + EC_LOCAL_TEMPO_SCOPE; + Glib::RefPtr win = get_canvas()->get_window(); if (win && !_cursors->is_invalid (cursor)) { @@ -1973,6 +2185,8 @@ EditingContext::set_canvas_cursor (Gdk::Cursor* cursor) void EditingContext::pack_draw_box (bool with_channel) { + EC_LOCAL_TEMPO_SCOPE; + /* Draw - these MIDI tools are only visible when in Draw mode */ draw_box.set_spacing (2); draw_box.set_border_width (2); @@ -1999,6 +2213,8 @@ EditingContext::pack_draw_box (bool with_channel) void EditingContext::pack_snap_box () { + EC_LOCAL_TEMPO_SCOPE; + snap_box.pack_start (snap_mode_button, false, false); snap_box.pack_start (grid_type_selector, false, false); } @@ -2006,6 +2222,8 @@ EditingContext::pack_snap_box () void EditingContext::bind_mouse_mode_buttons () { + EC_LOCAL_TEMPO_SCOPE; + RefPtr act; act = ActionManager::get_action ((_name + X_("Editing")).c_str(), X_("temporal-zoom-in")); @@ -2058,6 +2276,8 @@ EditingContext::bind_mouse_mode_buttons () Editing::MouseMode EditingContext::current_mouse_mode() const { + EC_LOCAL_TEMPO_SCOPE; + for (auto & [mode,action] : mouse_mode_actions) { if (action->get_active()) { return mode; @@ -2070,6 +2290,8 @@ EditingContext::current_mouse_mode() const void EditingContext::set_mouse_mode (MouseMode m, bool force) { + EC_LOCAL_TEMPO_SCOPE; + if (_drags->active ()) { return; } @@ -2084,6 +2306,8 @@ EditingContext::set_mouse_mode (MouseMode m, bool force) bool EditingContext::on_velocity_scroll_event (GdkEventScroll* ev) { + EC_LOCAL_TEMPO_SCOPE; + int v = PBD::atoi (draw_velocity_selector.get_text ()); switch (ev->direction) { case GDK_SCROLL_DOWN: @@ -2102,6 +2326,8 @@ EditingContext::on_velocity_scroll_event (GdkEventScroll* ev) void EditingContext::set_common_editing_state (XMLNode const & node) { + EC_LOCAL_TEMPO_SCOPE; + double z; if (node.get_property ("zoom", z)) { /* older versions of ardour used floating point samples_per_pixel */ @@ -2147,6 +2373,8 @@ EditingContext::set_common_editing_state (XMLNode const & node) void EditingContext::get_common_editing_state (XMLNode& node) const { + EC_LOCAL_TEMPO_SCOPE; + node.set_property ("zoom", samples_per_pixel); node.set_property ("grid-type", grid_type()); node.set_property ("snap-mode", snap_mode()); @@ -2160,6 +2388,8 @@ EditingContext::get_common_editing_state (XMLNode& node) const bool EditingContext::snap_mode_button_clicked (GdkEventButton* ev) { + EC_LOCAL_TEMPO_SCOPE; + if (ev->button != 3) { cycle_snap_mode(); return true; @@ -2177,6 +2407,8 @@ EditingContext::snap_mode_button_clicked (GdkEventButton* ev) void EditingContext::ensure_visual_change_idle_handler () { + EC_LOCAL_TEMPO_SCOPE; + if (pending_visual_change.idle_handler_id < 0) { /* see comment in add_to_idle_resize above. */ pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL); @@ -2193,6 +2425,8 @@ EditingContext::_idle_visual_changer (void* arg) int EditingContext::idle_visual_changer () { + EC_LOCAL_TEMPO_SCOPE; + pending_visual_change.idle_handler_id = -1; if (pending_visual_change.pending == 0) { @@ -2235,6 +2469,8 @@ EditingContext::idle_visual_changer () void EditingContext::reset_x_origin (samplepos_t sample) { + EC_LOCAL_TEMPO_SCOPE; + pending_visual_change.add (VisualChange::TimeOrigin); pending_visual_change.time_origin = sample; ensure_visual_change_idle_handler (); @@ -2243,6 +2479,8 @@ EditingContext::reset_x_origin (samplepos_t sample) void EditingContext::reset_y_origin (double y) { + EC_LOCAL_TEMPO_SCOPE; + pending_visual_change.add (VisualChange::YOrigin); pending_visual_change.y_origin = y; ensure_visual_change_idle_handler (); @@ -2251,6 +2489,8 @@ EditingContext::reset_y_origin (double y) void EditingContext::reset_zoom (samplecnt_t spp) { + EC_LOCAL_TEMPO_SCOPE; + if (_track_canvas_width <= 0) { return; } @@ -2274,6 +2514,8 @@ EditingContext::reset_zoom (samplecnt_t spp) void EditingContext::pre_render () { + EC_LOCAL_TEMPO_SCOPE; + visual_change_queued = false; if (pending_visual_change.pending != 0) { @@ -2310,6 +2552,8 @@ EditingContext::radio_reg_sens (RefPtr action_group, RadioAction::G void EditingContext::update_undo_redo_actions (PBD::UndoHistory const & history) { + EC_LOCAL_TEMPO_SCOPE; + string label; if (undo_action) { @@ -2338,6 +2582,8 @@ EditingContext::update_undo_redo_actions (PBD::UndoHistory const & history) int32_t EditingContext::get_grid_beat_divisions (GridType gt) const { + EC_LOCAL_TEMPO_SCOPE; + switch (gt) { case GridTypeBeatDiv32: return 32; case GridTypeBeatDiv28: return 28; @@ -2375,12 +2621,16 @@ EditingContext::get_grid_beat_divisions (GridType gt) const int32_t EditingContext::get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) const { + EC_LOCAL_TEMPO_SCOPE; + return get_grid_beat_divisions (gt); } Temporal::Beats EditingContext::get_grid_type_as_beats (bool& success, timepos_t const & position) const { + EC_LOCAL_TEMPO_SCOPE; + success = true; int32_t const divisions = get_grid_beat_divisions (grid_type()); @@ -2460,6 +2710,8 @@ EditingContext::get_grid_type_as_beats (bool& success, timepos_t const & positio Temporal::Beats EditingContext::get_draw_length_as_beats (bool& success, timepos_t const & position) const { + EC_LOCAL_TEMPO_SCOPE; + success = true; GridType grid_to_use = draw_length() == DRAW_LEN_AUTO ? grid_type() : draw_length(); int32_t const divisions = get_grid_beat_divisions (grid_to_use); @@ -2475,6 +2727,8 @@ EditingContext::get_draw_length_as_beats (bool& success, timepos_t const & posit void EditingContext::select_automation_line (GdkEventButton* event, ArdourCanvas::Item* item, ARDOUR::SelectionOperation op) { + EC_LOCAL_TEMPO_SCOPE; + AutomationLine* al = reinterpret_cast (item->get_data ("line")); std::list selectables; double mx = event->x; @@ -2525,6 +2779,8 @@ EditingContext::select_automation_line (GdkEventButton* event, ArdourCanvas::Ite void EditingContext::reset_point_selection () { + EC_LOCAL_TEMPO_SCOPE; + for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) { ARDOUR::AutomationList::iterator j = (*i)->model (); (*j)->value = (*i)->line().the_list()->descriptor ().normal; @@ -2534,6 +2790,8 @@ EditingContext::reset_point_selection () void EditingContext::choose_canvas_cursor_on_entry (ItemType type) { + EC_LOCAL_TEMPO_SCOPE; + if (_drags->active()) { return; } @@ -2549,17 +2807,16 @@ EditingContext::choose_canvas_cursor_on_entry (ItemType type) void EditingContext::play_note_selection_clicked () { - UIConfiguration::instance().set_sound_midi_notes (!UIConfiguration::instance().get_sound_midi_notes()); -} + EC_LOCAL_TEMPO_SCOPE; -void -EditingContext::follow_playhead_clicked () -{ + UIConfiguration::instance().set_sound_midi_notes (!UIConfiguration::instance().get_sound_midi_notes()); } void EditingContext::cycle_zoom_focus () { + EC_LOCAL_TEMPO_SCOPE; + switch (zoom_focus()) { case ZoomFocusLeft: set_zoom_focus (ZoomFocusRight); @@ -2585,6 +2842,8 @@ EditingContext::cycle_zoom_focus () void EditingContext::temporal_zoom_step_mouse_focus_scale (bool zoom_out, double scale) { + EC_LOCAL_TEMPO_SCOPE; + ZoomFocus old_zf (zoom_focus()); PBD::Unwinder uw (temporary_zoom_focus_change, true); set_zoom_focus (Editing::ZoomFocusMouse); @@ -2595,18 +2854,24 @@ EditingContext::temporal_zoom_step_mouse_focus_scale (bool zoom_out, double scal void EditingContext::temporal_zoom_step_mouse_focus (bool zoom_out) { + EC_LOCAL_TEMPO_SCOPE; + temporal_zoom_step_mouse_focus_scale (zoom_out, 2.0); } void EditingContext::temporal_zoom_step (bool zoom_out) { + EC_LOCAL_TEMPO_SCOPE; + temporal_zoom_step_scale (zoom_out, 2.0); } void EditingContext::temporal_zoom_step_scale (bool zoom_out, double scale) { + EC_LOCAL_TEMPO_SCOPE; + ENSURE_GUI_THREAD (*this, &EditingContext::temporal_zoom_step, zoom_out, scale) samplecnt_t nspp = samples_per_pixel; @@ -2637,6 +2902,8 @@ EditingContext::temporal_zoom_step_scale (bool zoom_out, double scale) void EditingContext::temporal_zoom (samplecnt_t spp) { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { return; } @@ -2768,6 +3035,8 @@ EditingContext::temporal_zoom (samplecnt_t spp) void EditingContext::calc_extra_zoom_edges (samplepos_t &start, samplepos_t &end) { + EC_LOCAL_TEMPO_SCOPE; + /* this func helps make sure we leave a little space at each end of the editor so that the zoom doesn't fit the region precisely to the screen. @@ -2800,6 +3069,8 @@ EditingContext::calc_extra_zoom_edges (samplepos_t &start, samplepos_t &end) void EditingContext::temporal_zoom_by_sample (samplepos_t start, samplepos_t end) { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) return; if ((start == 0 && end == 0) || end < start) { @@ -2828,6 +3099,8 @@ EditingContext::temporal_zoom_by_sample (samplepos_t start, samplepos_t end) void EditingContext::temporal_zoom_to_sample (bool coarser, samplepos_t sample) { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { return; } @@ -2879,6 +3152,8 @@ EditingContext::temporal_zoom_to_sample (bool coarser, samplepos_t sample) bool EditingContext::mouse_sample (samplepos_t& where, bool& in_track_canvas) const { + EC_LOCAL_TEMPO_SCOPE; + /* gdk_window_get_pointer() has X11's XQueryPointer semantics in that it only * pays attentions to subwindows. this means that menu windows are ignored, and * if the pointer is in a menu, the return window from the call will be the @@ -2927,6 +3202,8 @@ EditingContext::mouse_sample (samplepos_t& where, bool& in_track_canvas) const samplepos_t EditingContext::window_event_sample (GdkEvent const * event, double* pcx, double* pcy) const { + EC_LOCAL_TEMPO_SCOPE; + ArdourCanvas::Duple d; if (!gdk_event_get_coords (event, &d.x, &d.y)) { @@ -2952,6 +3229,8 @@ EditingContext::window_event_sample (GdkEvent const * event, double* pcx, double Editing::ZoomFocus EditingContext::zoom_focus () const { + EC_LOCAL_TEMPO_SCOPE; + for (auto & [mode,action] : zoom_focus_actions) { if (action->get_active()) { return mode; @@ -2964,6 +3243,8 @@ EditingContext::zoom_focus () const void EditingContext::zoom_focus_chosen (ZoomFocus focus) { + EC_LOCAL_TEMPO_SCOPE; + if (temporary_zoom_focus_change) { /* we are just changing settings momentarily, no need to do anything */ return; @@ -2985,6 +3266,8 @@ EditingContext::zoom_focus_chosen (ZoomFocus focus) void EditingContext::alt_delete_ () { + EC_LOCAL_TEMPO_SCOPE; + delete_ (); } @@ -2992,6 +3275,8 @@ EditingContext::alt_delete_ () void EditingContext::cut () { + EC_LOCAL_TEMPO_SCOPE; + cut_copy (Cut); } @@ -2999,12 +3284,16 @@ EditingContext::cut () void EditingContext::copy () { + EC_LOCAL_TEMPO_SCOPE; + cut_copy (Copy); } void EditingContext::load_shared_bindings () { + EC_LOCAL_TEMPO_SCOPE; + Bindings* m = Bindings::get_bindings (X_("MIDI")); Bindings* b = Bindings::get_bindings (X_("Editing")); Bindings* a = Bindings::get_bindings (X_("Automation")); @@ -3042,14 +3331,17 @@ EditingContext::load_shared_bindings () void EditingContext::drop_grid () { + EC_LOCAL_TEMPO_SCOPE; + hide_grid_lines (); - delete grid_lines; - grid_lines = nullptr; + grid_lines.reset (); } void EditingContext::hide_grid_lines () { + EC_LOCAL_TEMPO_SCOPE; + if (grid_lines) { grid_lines->hide(); } @@ -3058,12 +3350,14 @@ EditingContext::hide_grid_lines () void EditingContext::maybe_draw_grid_lines (ArdourCanvas::Container* group) { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { return; } if (!grid_lines) { - grid_lines = new GridLines (*this, group, ArdourCanvas::LineSet::Vertical); + grid_lines.reset (new GridLines (*this, group, ArdourCanvas::LineSet::Vertical)); } @@ -3089,6 +3383,8 @@ EditingContext::maybe_draw_grid_lines (ArdourCanvas::Container* group) void EditingContext::update_grid () { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { return; } @@ -3103,6 +3399,8 @@ EditingContext::update_grid () Location* EditingContext::transport_loop_location() { + EC_LOCAL_TEMPO_SCOPE; + if (_session) { return _session->locations()->auto_loop_location(); } else { @@ -3113,6 +3411,8 @@ EditingContext::transport_loop_location() void EditingContext::set_loop_range (timepos_t const & start, timepos_t const & end, string cmd) { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { return; } @@ -3145,6 +3445,8 @@ EditingContext::set_loop_range (timepos_t const & start, timepos_t const & end, bool EditingContext::allow_trim_cursors () const { + EC_LOCAL_TEMPO_SCOPE; + auto mouse_mode = current_mouse_mode(); return mouse_mode == MouseContent || mouse_mode == MouseTimeFX || mouse_mode == MouseDraw; } @@ -3153,6 +3455,8 @@ EditingContext::allow_trim_cursors () const void EditingContext::reset_x_origin_to_follow_playhead () { + EC_LOCAL_TEMPO_SCOPE; + assert (_session); samplepos_t const sample = _playhead_cursor->current_sample (); @@ -3204,6 +3508,8 @@ EditingContext::reset_x_origin_to_follow_playhead () void EditingContext::center_screen (samplepos_t sample) { + EC_LOCAL_TEMPO_SCOPE; + samplecnt_t const page = _visible_canvas_width * samples_per_pixel; /* if we're off the page, then scroll. @@ -3217,6 +3523,8 @@ EditingContext::center_screen (samplepos_t sample) void EditingContext::center_screen_internal (samplepos_t sample, float page) { + EC_LOCAL_TEMPO_SCOPE; + page /= 2; if (sample > page) { @@ -3227,13 +3535,3 @@ EditingContext::center_screen_internal (samplepos_t sample, float page) reset_x_origin (sample); } - -bool -EditingContext::follow_playhead() const -{ - if (!follow_playhead_action) { - return false; - } - - return follow_playhead_action->get_active (); -} diff --git a/gtk2_ardour/editing_context.h b/gtk2_ardour/editing_context.h index 75fcb70d98..f438993922 100644 --- a/gtk2_ardour/editing_context.h +++ b/gtk2_ardour/editing_context.h @@ -87,18 +87,17 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, Temporal::TimeDomain time_domain () const; - struct TempoMapScope { TempoMapScope (EditingContext& context, std::shared_ptr map) : ec (context) { - old_map = ec.start_local_tempo_map (map); + ec.start_local_tempo_map (map); + ec.ensure_local_tempo_scope (); } ~TempoMapScope () { - ec.end_local_tempo_map (old_map); + ec.end_local_tempo_map (); } EditingContext& ec; - std::shared_ptr old_map; }; DragManager* drags () const { @@ -385,8 +384,8 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, static MouseCursors const* cursors () { return _cursors; } - virtual VerboseCursor* verbose_cursor () const { - return _verbose_cursor; + virtual VerboseCursor& verbose_cursor () const { + return *_verbose_cursor; } virtual void set_snapped_cursor_position (Temporal::timepos_t const & pos) = 0; @@ -503,6 +502,14 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, void enable_automation_bindings (); void disable_automation_bindings (); + /* playhead/screen stuff */ + + void set_stationary_playhead (bool yn); + void toggle_stationary_playhead (); + bool stationary_playhead() const; + + bool dragging_playhead () const { return _dragging_playhead; } + protected: std::string _name; bool within_track_canvas; @@ -573,7 +580,6 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, virtual void play_note_selection_clicked(); virtual void note_mode_clicked() {} - virtual void follow_playhead_clicked (); virtual void full_zoom_clicked() {}; virtual void set_visible_channel (int) {} @@ -596,6 +602,9 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, Glib::RefPtr follow_playhead_action; void follow_playhead_chosen (); + Glib::RefPtr stationary_playhead_action; + void stationary_playhead_chosen (); + /* selection process */ Selection* selection; @@ -606,7 +615,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, static MouseCursors* _cursors; - VerboseCursor* _verbose_cursor; + std::unique_ptr _verbose_cursor; samplecnt_t samples_per_pixel; @@ -656,8 +665,9 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, QuantizeDialog* quantize_dialog; friend struct 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 */ } + void set_local_tempo_map (std::shared_ptr); + void start_local_tempo_map (std::shared_ptr); + void end_local_tempo_map (); virtual bool button_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) = 0; virtual bool button_press_handler_1 (ArdourCanvas::Item*, GdkEvent*, ItemType) = 0; @@ -775,7 +785,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, ARDOUR::Location* transport_loop_location(); std::vector grid_marks; - GridLines* grid_lines; + std::unique_ptr grid_lines; ArdourCanvas::Container* time_line_group; void drop_grid (); @@ -821,4 +831,15 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, virtual void automation_move_points_earlier () {}; bool temporary_zoom_focus_change; + bool _dragging_playhead; + + mutable std::shared_ptr _local_tempo_map; + void ensure_local_tempo_scope () const { + if (_local_tempo_map) { + Temporal::TempoMap::set (_local_tempo_map); + } + } }; + +#define EC_LOCAL_TEMPO_SCOPE ensure_local_tempo_scope () +#define EC_GIVEN_LOCAL_TEMPO_SCOPE(ec) ec.ensure_local_tempo_scope () diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 7ebf1a198b..2401dd0326 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -315,9 +315,7 @@ Editor::Editor () , ignore_gui_changes (false) , lock_dialog (nullptr) , _last_event_time (g_get_monotonic_time ()) - , _dragging_playhead (false) , ignore_map_change (false) - , _stationary_playhead (false) , _maximised (false) , global_rect_group (nullptr) , tempo_marker_menu (nullptr) @@ -740,7 +738,6 @@ Editor::~Editor() delete _track_canvas_viewport; delete _drags; delete nudge_clock; - delete _verbose_cursor; delete _region_peak_cursor; delete quantize_dialog; delete _summary; @@ -2358,7 +2355,7 @@ Editor::get_state () const node->set_property ("maximised", _maximised); node->set_property ("follow-playhead", follow_playhead()); - node->set_property ("stationary-playhead", _stationary_playhead); + node->set_property ("stationary-playhead", stationary_playhead()); node->set_property ("mouse-mode", current_mouse_mode()); node->set_property ("join-object-range", smart_mode_action->get_active ()); @@ -3406,25 +3403,6 @@ Editor::cycle_marker_click_behavior () } } -void -Editor::toggle_stationary_playhead () -{ - RefPtr tact = ActionManager::get_toggle_action (X_("Editor"), X_("toggle-stationary-playhead")); - set_stationary_playhead (tact->get_active()); -} - -void -Editor::set_stationary_playhead (bool yn) -{ - if (_stationary_playhead != yn) { - if ((_stationary_playhead = yn) == true) { - /* catch up -- FIXME need a 3.0 equivalent of this 2.X call */ - // update_current_screen (); - } - instant_save (); - } -} - bool Editor::show_touched_automation() const { @@ -5310,7 +5288,7 @@ Editor::super_rapid_screen_update () return; } - if (!_stationary_playhead) { + if (!stationary_playhead()) { reset_x_origin_to_follow_playhead (); } else { samplepos_t const sample = _playhead_cursor->current_sample (); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index b2d0b57f03..3729088504 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -320,14 +320,6 @@ public: void sequence_regions (); - /* playhead/screen stuff */ - - void set_stationary_playhead (bool yn); - void toggle_stationary_playhead (); - bool stationary_playhead() const { return _stationary_playhead; } - - bool dragging_playhead () const { return _dragging_playhead; } - void toggle_zero_line_visibility (); void set_summary (); void set_group_tabs (); @@ -1488,8 +1480,6 @@ private: ARDOUR::PlaylistSet motion_frozen_playlists; - bool _dragging_playhead; - void marker_drag_motion_callback (GdkEvent*); void marker_drag_finished_callback (GdkEvent*); @@ -1645,8 +1635,6 @@ private: /* display control */ - /// true if we scroll the tracks rather than the playhead - bool _stationary_playhead; /// true if we are in fullscreen mode bool _maximised; diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 24093e3636..2e5970bced 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -478,8 +478,6 @@ Editor::register_actions () act = reg_sens (editor_actions, "remove-last-capture", _("Remove Last Capture"), (sigc::mem_fun(*this, &Editor::remove_last_capture))); act = reg_sens (editor_actions, "tag-last-capture", _("Tag Last Capture"), (sigc::mem_fun(*this, &Editor::tag_last_capture))); - ActionManager::register_toggle_action (editor_actions, "toggle-stationary-playhead", _("Stationary Playhead"), (mem_fun(*this, &Editor::toggle_stationary_playhead))); - show_touched_automation_action = ActionManager::register_toggle_action (editor_actions, "show-touched-automation", _("Show Automation Lane on Touch"), (mem_fun(*this, &Editor::toggle_show_touched_automation))); act = reg_sens (editor_actions, "insert-time", _("Insert Time"), (sigc::mem_fun(*this, &Editor::do_insert_time))); diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index f854970a59..d3e5f97936 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -95,7 +95,7 @@ Editor::initialize_canvas () */ no_scroll_group = new ArdourCanvas::Container (_track_canvas->root()); - _verbose_cursor = new VerboseCursor (*this); + _verbose_cursor.reset (new VerboseCursor (*this)); ArdourCanvas::ScrollGroup* hsg; ArdourCanvas::ScrollGroup* hg; diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index a586e51fe1..ebaa890d92 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -425,8 +425,8 @@ Drag::end_grab (GdkEvent* event) _item->ungrab (); finished (event, _starting_point_passed); - - editing_context.verbose_cursor ()->hide (); + + editing_context.verbose_cursor().hide (); return _starting_point_passed; } @@ -595,28 +595,28 @@ Drag::abort () aborted (_move_threshold_passed); editing_context.stop_canvas_autoscroll (); - editing_context.verbose_cursor ()->hide (); + editing_context.verbose_cursor().hide (); } void Drag::show_verbose_cursor_time (timepos_t const& pos) { - editing_context.verbose_cursor ()->set_time (pos.samples ()); - editing_context.verbose_cursor ()->show (); + editing_context.verbose_cursor().set_time (pos.samples ()); + editing_context.verbose_cursor().show (); } void Drag::show_verbose_cursor_duration (timepos_t const& start, timepos_t const& end, double /*xoffset*/) { - editing_context.verbose_cursor ()->set_duration (start.samples (), end.samples ()); - editing_context.verbose_cursor ()->show (); + editing_context.verbose_cursor().set_duration (start.samples (), end.samples ()); + editing_context.verbose_cursor().show (); } void Drag::show_verbose_cursor_text (string const& text) { - editing_context.verbose_cursor ()->set (text); - editing_context.verbose_cursor ()->show (); + editing_context.verbose_cursor().set (text); + editing_context.verbose_cursor().show (); } void diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc index b266129dbd..5a7ab3c2ad 100644 --- a/gtk2_ardour/midi_streamview.cc +++ b/gtk2_ardour/midi_streamview.cc @@ -122,11 +122,11 @@ MidiStreamView::create_region_view (std::shared_ptr r, bool /*wfd*/, boo if (recording) { region_view = new MidiRegionView ( _region_group, _trackview.editor(), _trackview, region, - _samples_per_pixel, MidiViewBackground::region_color(), recording, + _samples_per_pixel, StreamView::region_color, recording, TimeAxisViewItem::Visibility(TimeAxisViewItem::ShowFrame)); } else { region_view = new MidiRegionView (_region_group, _trackview.editor(), _trackview, region, - _samples_per_pixel, MidiViewBackground::region_color()); + _samples_per_pixel, StreamView::region_color); } region_view->init (false); diff --git a/gtk2_ardour/midi_view.cc b/gtk2_ardour/midi_view.cc index 4ea88a833d..aa932d7005 100644 --- a/gtk2_ardour/midi_view.cc +++ b/gtk2_ardour/midi_view.cc @@ -4478,7 +4478,7 @@ MidiView::remove_ghost_note () void MidiView::hide_verbose_cursor () { - _editing_context.verbose_cursor()->hide (); + _editing_context.verbose_cursor().hide (); _midi_context.set_note_highlight (NO_MIDI_NOTE); } @@ -4865,9 +4865,9 @@ MidiView::show_verbose_cursor (std::shared_ptr n) const void MidiView::show_verbose_cursor (string const & text, double xoffset, double yoffset) const { - _editing_context.verbose_cursor()->set (text); - _editing_context.verbose_cursor()->show (); - _editing_context.verbose_cursor()->set_offset (ArdourCanvas::Duple (xoffset, yoffset)); + _editing_context.verbose_cursor().set (text); + _editing_context.verbose_cursor().show (); + _editing_context.verbose_cursor().set_offset (ArdourCanvas::Duple (xoffset, yoffset)); } diff --git a/gtk2_ardour/pianoroll.cc b/gtk2_ardour/pianoroll.cc index c4fff834cb..304403180f 100644 --- a/gtk2_ardour/pianoroll.cc +++ b/gtk2_ardour/pianoroll.cc @@ -105,6 +105,8 @@ Pianoroll::~Pianoroll () void Pianoroll::set_show_source (bool yn) { + EC_LOCAL_TEMPO_SCOPE; + CueEditor::set_show_source (yn); if (view) { view->set_show_source (yn); @@ -114,6 +116,8 @@ Pianoroll::set_show_source (bool yn) void Pianoroll::rebuild_parameter_button_map() { + EC_LOCAL_TEMPO_SCOPE; + parameter_button_map.clear (); parameter_button_map.insert (std::make_pair (velocity_button, Evoral::Parameter (ARDOUR::MidiVelocityAutomation, _visible_channel))); parameter_button_map.insert (std::make_pair (bender_button, Evoral::Parameter (ARDOUR::MidiPitchBenderAutomation, _visible_channel))); @@ -129,6 +133,8 @@ Pianoroll::rebuild_parameter_button_map() void Pianoroll::reset_user_cc_choice (std::string name, Evoral::Parameter param, MetaButton* metabutton) { + EC_LOCAL_TEMPO_SCOPE; + ParameterButtonMap::iterator iter; for (iter = parameter_button_map.begin(); iter != parameter_button_map.end(); ++iter) { @@ -149,6 +155,8 @@ Pianoroll::add_single_controller_item (Gtk::Menu_Helpers::MenuList& ctl_items, const std::string& name, ArdourWidgets::MetaButton* mb) { + EC_LOCAL_TEMPO_SCOPE; + using namespace Gtk::Menu_Helpers; const uint16_t selected_channels = 0xffff; @@ -174,6 +182,8 @@ Pianoroll::add_multi_controller_item (Gtk::Menu_Helpers::MenuList&, const std::string& name, MetaButton* mb) { + EC_LOCAL_TEMPO_SCOPE; + using namespace Gtk; using namespace Gtk::Menu_Helpers; @@ -223,6 +233,8 @@ Pianoroll::add_multi_controller_item (Gtk::Menu_Helpers::MenuList&, void Pianoroll::build_lower_toolbar () { + EC_LOCAL_TEMPO_SCOPE; + horizontal_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &Pianoroll::scrolled)); ArdourButton::Element elements = ArdourButton::Element (ArdourButton::Text|ArdourButton::Indicator|ArdourButton::Edge|ArdourButton::Body); @@ -292,6 +304,8 @@ Pianoroll::build_lower_toolbar () void Pianoroll::pack_inner (Gtk::Box& box) { + EC_LOCAL_TEMPO_SCOPE; + box.pack_start (snap_box, false, false); box.pack_start (grid_box, false, false); box.pack_start (draw_box, false, false); @@ -300,6 +314,8 @@ Pianoroll::pack_inner (Gtk::Box& box) void Pianoroll::pack_outer (Gtk::Box& box) { + EC_LOCAL_TEMPO_SCOPE; + if (with_transport_controls) { box.pack_start (play_box, false, false); } @@ -314,6 +330,8 @@ Pianoroll::pack_outer (Gtk::Box& box) void Pianoroll::set_visible_channel (int n) { + EC_LOCAL_TEMPO_SCOPE; + PBD::Unwinder uw (ignore_channel_changes, true); _visible_channel = n; @@ -332,6 +350,8 @@ Pianoroll::set_visible_channel (int n) void Pianoroll::build_canvas () { + EC_LOCAL_TEMPO_SCOPE; + _canvas.set_background_color (UIConfiguration::instance().color ("arrange base")); _canvas.signal_event().connect (sigc::mem_fun (*this, &Pianoroll::canvas_pre_event), false); dynamic_cast(&_canvas)->use_nsglview (UIConfiguration::instance().get_nsgl_view_mode () == NSGLHiRes); @@ -453,7 +473,7 @@ Pianoroll::build_canvas () cursor_scroll_group->set_position (ArdourCanvas::Duple (_timeline_origin, timebar_height * n_timebars)); h_scroll_group->set_position (Duple (_timeline_origin, 0.)); - _verbose_cursor = new VerboseCursor (*this); + _verbose_cursor.reset (new VerboseCursor (*this)); // _playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event, X_("playhead")); _playhead_cursor = new EditorCursor (*this, X_("playhead")); @@ -473,6 +493,8 @@ Pianoroll::build_canvas () void Pianoroll::visible_channel_changed () { + EC_LOCAL_TEMPO_SCOPE; + if (ignore_channel_changes) { /* We're changing it */ return; @@ -491,6 +513,8 @@ Pianoroll::visible_channel_changed () void Pianoroll::bindings_changed () { + EC_LOCAL_TEMPO_SCOPE; + bindings.clear (); load_shared_bindings (); } @@ -498,6 +522,8 @@ Pianoroll::bindings_changed () void Pianoroll::maybe_update () { + EC_LOCAL_TEMPO_SCOPE; + ARDOUR::TriggerPtr playing_trigger; if (ref.trigger()) { @@ -555,6 +581,8 @@ Pianoroll::maybe_update () bool Pianoroll::canvas_enter_leave (GdkEventCrossing* ev) { + EC_LOCAL_TEMPO_SCOPE; + switch (ev->type) { case GDK_ENTER_NOTIFY: if (ev->detail != GDK_NOTIFY_INFERIOR) { @@ -579,6 +607,8 @@ Pianoroll::canvas_enter_leave (GdkEventCrossing* ev) void Pianoroll::canvas_allocate (Gtk::Allocation alloc) { + EC_LOCAL_TEMPO_SCOPE; + _visible_canvas_width = alloc.get_width(); _visible_canvas_height = alloc.get_height(); @@ -610,6 +640,8 @@ Pianoroll::canvas_allocate (Gtk::Allocation alloc) timepos_t Pianoroll::snap_to_grid (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref) const { + EC_LOCAL_TEMPO_SCOPE; + /* BBT time only */ return snap_to_bbt (presnap, direction, gpref); } @@ -617,6 +649,8 @@ Pianoroll::snap_to_grid (timepos_t const & presnap, Temporal::RoundMode directio void Pianoroll::snap_to_internal (timepos_t& start, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap) const { + EC_LOCAL_TEMPO_SCOPE; + UIConfiguration const& uic (UIConfiguration::instance ()); const timepos_t presnap = start; @@ -654,6 +688,8 @@ Pianoroll::set_samples_per_pixel (samplecnt_t spp) return; } + EC_LOCAL_TEMPO_SCOPE; + CueEditor::set_samples_per_pixel (spp); if (view) { @@ -671,54 +707,72 @@ Pianoroll::set_samples_per_pixel (samplecnt_t spp) samplecnt_t Pianoroll::current_page_samples() const { + EC_LOCAL_TEMPO_SCOPE; + return (samplecnt_t) _track_canvas_width * samples_per_pixel; } bool Pianoroll::canvas_bg_event (GdkEvent* event, ArdourCanvas::Item* item) { + EC_LOCAL_TEMPO_SCOPE; + return typed_event (item, event, RegionItem); } bool Pianoroll::canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item* item, ControlPoint* cp) { + EC_LOCAL_TEMPO_SCOPE; + return typed_event (item, event, ControlPointItem); } bool Pianoroll::canvas_note_event (GdkEvent* event, ArdourCanvas::Item* item) { + EC_LOCAL_TEMPO_SCOPE; + return typed_event (item, event, NoteItem); } bool Pianoroll::canvas_velocity_base_event (GdkEvent* event, ArdourCanvas::Item* item) { + EC_LOCAL_TEMPO_SCOPE; + return typed_event (item, event, VelocityBaseItem); } bool Pianoroll::canvas_velocity_event (GdkEvent* event, ArdourCanvas::Item* item) { + EC_LOCAL_TEMPO_SCOPE; + return typed_event (item, event, VelocityItem); } bool Pianoroll::canvas_cue_start_event (GdkEvent* event, ArdourCanvas::Item* item) { + EC_LOCAL_TEMPO_SCOPE; + return typed_event (item, event, ClipStartItem); } bool Pianoroll::canvas_cue_end_event (GdkEvent* event, ArdourCanvas::Item* item) { + EC_LOCAL_TEMPO_SCOPE; + return typed_event (item, event, ClipEndItem); } void Pianoroll::set_trigger_start (Temporal::timepos_t const & p) { + EC_LOCAL_TEMPO_SCOPE; + if (ref.trigger()) { ref.trigger()->the_region()->trim_front (p); } else { @@ -733,6 +787,8 @@ Pianoroll::set_trigger_start (Temporal::timepos_t const & p) void Pianoroll::set_trigger_end (Temporal::timepos_t const & p) { + EC_LOCAL_TEMPO_SCOPE; + if (ref.trigger()) { ref.trigger()->the_region()->trim_end (p); } else { @@ -747,12 +803,16 @@ Pianoroll::set_trigger_end (Temporal::timepos_t const & p) Gtk::Widget& Pianoroll::contents () { + EC_LOCAL_TEMPO_SCOPE; + return _contents; } bool Pianoroll::idle_data_captured () { + EC_LOCAL_TEMPO_SCOPE; + if (!ref.box()) { return false; } @@ -769,6 +829,8 @@ Pianoroll::idle_data_captured () bool Pianoroll::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { + EC_LOCAL_TEMPO_SCOPE; + if (event->type != GDK_BUTTON_PRESS) { return false; } @@ -797,6 +859,8 @@ Pianoroll::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, Item bool Pianoroll::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { + EC_LOCAL_TEMPO_SCOPE; + NoteBase* note = nullptr; Editing::MouseMode mouse_mode = current_mouse_mode(); switch (item_type) { @@ -899,12 +963,16 @@ Pianoroll::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, It bool Pianoroll::button_press_handler_2 (ArdourCanvas::Item*, GdkEvent*, ItemType) { + EC_LOCAL_TEMPO_SCOPE; + return true; } bool Pianoroll::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { + EC_LOCAL_TEMPO_SCOPE; + if (!Keyboard::is_context_menu_event (&event->button)) { /* see if we're finishing a drag */ @@ -946,6 +1014,8 @@ Pianoroll::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, It void Pianoroll::popup_region_context_menu (ArdourCanvas::Item* item, GdkEvent* event) { + EC_LOCAL_TEMPO_SCOPE; + using namespace Gtk::Menu_Helpers; if (!view) { @@ -981,6 +1051,8 @@ Pianoroll::popup_region_context_menu (ArdourCanvas::Item* item, GdkEvent* event) bool Pianoroll::button_press_dispatch (GdkEventButton* ev) { + EC_LOCAL_TEMPO_SCOPE; + /* this function is intended only for buttons 4 and above. */ Gtkmm2ext::MouseButton b (ev->state, ev->button); @@ -990,6 +1062,8 @@ Pianoroll::button_press_dispatch (GdkEventButton* ev) bool Pianoroll::button_release_dispatch (GdkEventButton* ev) { + EC_LOCAL_TEMPO_SCOPE; + /* this function is intended only for buttons 4 and above. */ Gtkmm2ext::MouseButton b (ev->state, ev->button); @@ -999,6 +1073,8 @@ Pianoroll::button_release_dispatch (GdkEventButton* ev) bool Pianoroll::motion_handler (ArdourCanvas::Item*, GdkEvent* event, bool from_autoscroll) { + EC_LOCAL_TEMPO_SCOPE; + if (_drags->active ()) { //drags change the snapped_cursor location, because we are snapping the thing being dragged, not the actual mouse cursor return _drags->motion_handler (event, from_autoscroll); @@ -1010,6 +1086,8 @@ Pianoroll::motion_handler (ArdourCanvas::Item*, GdkEvent* event, bool from_autos bool Pianoroll::key_press_handler (ArdourCanvas::Item*, GdkEvent* ev, ItemType) { + EC_LOCAL_TEMPO_SCOPE; + switch (ev->key.keyval) { case GDK_d: @@ -1026,12 +1104,16 @@ Pianoroll::key_press_handler (ArdourCanvas::Item*, GdkEvent* ev, ItemType) bool Pianoroll::key_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) { + EC_LOCAL_TEMPO_SCOPE; + return true; } void Pianoroll::set_mouse_mode (Editing::MouseMode m, bool force) { + EC_LOCAL_TEMPO_SCOPE; + if (m != Editing::MouseDraw && m != Editing::MouseContent) { return; } @@ -1042,6 +1124,8 @@ Pianoroll::set_mouse_mode (Editing::MouseMode m, bool force) void Pianoroll::midi_action (void (MidiView::*method)()) { + EC_LOCAL_TEMPO_SCOPE; + if (!view) { return; } @@ -1052,6 +1136,8 @@ Pianoroll::midi_action (void (MidiView::*method)()) void Pianoroll::escape () { + EC_LOCAL_TEMPO_SCOPE; + if (!view) { return; } @@ -1062,12 +1148,16 @@ Pianoroll::escape () Gdk::Cursor* Pianoroll::which_track_cursor () const { + EC_LOCAL_TEMPO_SCOPE; + return _cursors->grabber; } Gdk::Cursor* Pianoroll::which_mode_cursor () const { + EC_LOCAL_TEMPO_SCOPE; + Gdk::Cursor* mode_cursor = MouseCursors::invalid_cursor (); switch (current_mouse_mode()) { @@ -1089,6 +1179,8 @@ Pianoroll::which_mode_cursor () const Gdk::Cursor* Pianoroll::which_trim_cursor (bool left_side) const { + EC_LOCAL_TEMPO_SCOPE; + abort (); /*NOTREACHED*/ return nullptr; @@ -1098,6 +1190,8 @@ Pianoroll::which_trim_cursor (bool left_side) const Gdk::Cursor* Pianoroll::which_canvas_cursor (ItemType type) const { + EC_LOCAL_TEMPO_SCOPE; + Gdk::Cursor* cursor = which_mode_cursor (); Editing::MouseMode mouse_mode = current_mouse_mode (); @@ -1185,6 +1279,8 @@ Pianoroll::which_canvas_cursor (ItemType type) const bool Pianoroll::enter_handler (ArdourCanvas::Item* item, GdkEvent* ev, ItemType item_type) { + EC_LOCAL_TEMPO_SCOPE; + choose_canvas_cursor_on_entry (item_type); switch (item_type) { @@ -1214,6 +1310,8 @@ Pianoroll::enter_handler (ArdourCanvas::Item* item, GdkEvent* ev, ItemType item_ bool Pianoroll::leave_handler (ArdourCanvas::Item* item, GdkEvent* ev, ItemType item_type) { + EC_LOCAL_TEMPO_SCOPE; + EditorAutomationLine* al; set_canvas_cursor (which_mode_cursor()); @@ -1247,6 +1345,8 @@ Pianoroll::leave_handler (ArdourCanvas::Item* item, GdkEvent* ev, ItemType item_ std::list Pianoroll::selectable_owners() { + EC_LOCAL_TEMPO_SCOPE; + if (view) { return view->selectable_owners(); } @@ -1257,6 +1357,8 @@ Pianoroll::selectable_owners() void Pianoroll::trigger_prop_change (PBD::PropertyChange const & what_changed) { + EC_LOCAL_TEMPO_SCOPE; + if (what_changed.contains (Properties::region)) { std::shared_ptr mr = std::dynamic_pointer_cast (ref.trigger()->the_region()); if (mr) { @@ -1268,6 +1370,8 @@ Pianoroll::trigger_prop_change (PBD::PropertyChange const & what_changed) void Pianoroll::region_prop_change (PBD::PropertyChange const & what_changed) { + EC_LOCAL_TEMPO_SCOPE; + if (what_changed.contains (Properties::length)) { std::shared_ptr mr = view->midi_region(); if (mr) { @@ -1279,6 +1383,8 @@ Pianoroll::region_prop_change (PBD::PropertyChange const & what_changed) void Pianoroll::set_trigger (TriggerReference & tref) { + EC_LOCAL_TEMPO_SCOPE; + if (ref == tref) { return; } @@ -1314,6 +1420,8 @@ Pianoroll::set_trigger (TriggerReference & tref) void Pianoroll::make_a_region () { + EC_LOCAL_TEMPO_SCOPE; + std::shared_ptr new_source = _session->create_midi_source_for_session (_track->name()); SourceList sources; sources.push_back (new_source); @@ -1339,6 +1447,8 @@ Pianoroll::make_a_region () void Pianoroll::unset (bool trigger_too) { + EC_LOCAL_TEMPO_SCOPE; + CueEditor::unset (trigger_too); view->set_region (nullptr); } @@ -1346,6 +1456,8 @@ Pianoroll::unset (bool trigger_too) void Pianoroll::set_track (std::shared_ptr track) { + EC_LOCAL_TEMPO_SCOPE; + CueEditor::set_track (track); if (view) { @@ -1374,6 +1486,8 @@ Pianoroll::set_track (std::shared_ptr track) void Pianoroll::set_region (std::shared_ptr region) { + EC_LOCAL_TEMPO_SCOPE; + CueEditor::set_region (region); if (_visible_pending_region) { @@ -1383,6 +1497,7 @@ Pianoroll::set_region (std::shared_ptr region) std::shared_ptr r (std::dynamic_pointer_cast (region)); if (!r || !region) { + _update_connection.disconnect (); return; } @@ -1442,6 +1557,8 @@ Pianoroll::set_region (std::shared_ptr region) bool Pianoroll::user_automation_button_event (GdkEventButton* ev, MetaButton* mb) { + EC_LOCAL_TEMPO_SCOPE; + if (mb->is_menu_popup_event (ev)) { return false; } @@ -1466,6 +1583,8 @@ Pianoroll::user_automation_button_event (GdkEventButton* ev, MetaButton* mb) void Pianoroll::user_led_click (GdkEventButton* ev, MetaButton* metabutton) { + EC_LOCAL_TEMPO_SCOPE; + if (ev->button != 1) { return; } @@ -1482,6 +1601,8 @@ Pianoroll::user_led_click (GdkEventButton* ev, MetaButton* metabutton) bool Pianoroll::automation_button_event (GdkEventButton* ev, Evoral::ParameterType type, int id) { + EC_LOCAL_TEMPO_SCOPE; + if (ev->button != 1) { return false; } @@ -1496,6 +1617,8 @@ Pianoroll::automation_button_event (GdkEventButton* ev, Evoral::ParameterType ty void Pianoroll::automation_led_click (GdkEventButton* ev, Evoral::ParameterType type, int id) { + EC_LOCAL_TEMPO_SCOPE; + if (ev->button != 1) { return; } @@ -1515,6 +1638,8 @@ Pianoroll::automation_led_click (GdkEventButton* ev, Evoral::ParameterType type, void Pianoroll::automation_state_changed () { + EC_LOCAL_TEMPO_SCOPE; + assert (view); for (ParameterButtonMap::iterator i = parameter_button_map.begin(); i != parameter_button_map.end(); ++i) { @@ -1541,6 +1666,8 @@ Pianoroll::automation_state_changed () void Pianoroll::note_mode_clicked () { + EC_LOCAL_TEMPO_SCOPE; + assert (bg); if (bg->note_mode() == Sustained) { @@ -1553,6 +1680,8 @@ Pianoroll::note_mode_clicked () void Pianoroll::set_note_mode (NoteMode nm) { + EC_LOCAL_TEMPO_SCOPE; + assert (bg); if (nm != bg->note_mode()) { @@ -1568,6 +1697,8 @@ Pianoroll::set_note_mode (NoteMode nm) void Pianoroll::point_selection_changed () { + EC_LOCAL_TEMPO_SCOPE; + if (view) { view->point_selection_changed (); } @@ -1576,6 +1707,8 @@ Pianoroll::point_selection_changed () void Pianoroll::delete_ () { + EC_LOCAL_TEMPO_SCOPE; + /* Editor has a lot to do here, potentially. But we don't */ cut_copy (Editing::Delete); } @@ -1583,6 +1716,8 @@ Pianoroll::delete_ () void Pianoroll::paste (float times, bool from_context_menu) { + EC_LOCAL_TEMPO_SCOPE; + if (view) { // view->paste (Editing::Cut); } @@ -1591,6 +1726,8 @@ Pianoroll::paste (float times, bool from_context_menu) void Pianoroll::keyboard_paste () { + EC_LOCAL_TEMPO_SCOPE; + } /** Cut, copy or clear selected regions, automation points or a time range. @@ -1600,6 +1737,8 @@ Pianoroll::keyboard_paste () void Pianoroll::cut_copy (Editing::CutCopyOp op) { + EC_LOCAL_TEMPO_SCOPE; + using namespace Editing; /* only cancel selection if cut/copy is successful.*/ @@ -1659,6 +1798,8 @@ Pianoroll::cut_copy (Editing::CutCopyOp op) void Pianoroll::select_all_within (Temporal::timepos_t const & start, Temporal::timepos_t const & end, double y0, double y1, std::list const & ignored, ARDOUR::SelectionOperation op, bool preserve_if_selected) { + EC_LOCAL_TEMPO_SCOPE; + std::list found; if (!view) { @@ -1741,6 +1882,8 @@ Pianoroll::select_all_within (Temporal::timepos_t const & start, Temporal::timep void Pianoroll::set_session (ARDOUR::Session* s) { + EC_LOCAL_TEMPO_SCOPE; + CueEditor::set_session (s); if (with_transport_controls) { @@ -1753,9 +1896,7 @@ Pianoroll::set_session (ARDOUR::Session* s) map_transport_state (); } - if (!_session) { - _update_connection.disconnect (); - } else { + if (_session) { zoom_to_show (timecnt_t (timepos_t (max_extents_scale() * max_zoom_extent ().second.samples()))); } } @@ -1763,6 +1904,8 @@ Pianoroll::set_session (ARDOUR::Session* s) void Pianoroll::map_transport_state () { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { loop_button.unset_active_state (); play_button.unset_active_state (); @@ -1800,6 +1943,8 @@ Pianoroll::map_transport_state () bool Pianoroll::allow_trim_cursors () const { + EC_LOCAL_TEMPO_SCOPE; + auto mouse_mode = current_mouse_mode (); return mouse_mode == Editing::MouseContent || mouse_mode == Editing::MouseTimeFX; } @@ -1807,6 +1952,8 @@ Pianoroll::allow_trim_cursors () const void Pianoroll::shift_midi (timepos_t const & t, bool model) { + EC_LOCAL_TEMPO_SCOPE; + if (!view) { return; } @@ -1817,6 +1964,8 @@ Pianoroll::shift_midi (timepos_t const & t, bool model) InstrumentInfo* Pianoroll::instrument_info () const { + EC_LOCAL_TEMPO_SCOPE; + if (!view || !view->midi_track()) { return nullptr; } @@ -1827,6 +1976,8 @@ Pianoroll::instrument_info () const void Pianoroll::update_tempo_based_rulers () { + EC_LOCAL_TEMPO_SCOPE; + if (!_session) { return; } @@ -1839,6 +1990,8 @@ Pianoroll::update_tempo_based_rulers () void Pianoroll::set_note_selection (uint8_t note) { + EC_LOCAL_TEMPO_SCOPE; + if (!view) { return; } @@ -1853,6 +2006,8 @@ Pianoroll::set_note_selection (uint8_t note) void Pianoroll::add_note_selection (uint8_t note) { + EC_LOCAL_TEMPO_SCOPE; + if (!view) { return; } @@ -1867,6 +2022,8 @@ Pianoroll::add_note_selection (uint8_t note) void Pianoroll::extend_note_selection (uint8_t note) { + EC_LOCAL_TEMPO_SCOPE; + if (!view) { return; } @@ -1881,6 +2038,8 @@ Pianoroll::extend_note_selection (uint8_t note) void Pianoroll::toggle_note_selection (uint8_t note) { + EC_LOCAL_TEMPO_SCOPE; + if (!view) { return; } @@ -1895,6 +2054,8 @@ Pianoroll::toggle_note_selection (uint8_t note) void Pianoroll::begin_write () { + EC_LOCAL_TEMPO_SCOPE; + if (view) { view->begin_write (); } @@ -1903,6 +2064,8 @@ Pianoroll::begin_write () void Pianoroll::end_write () { + EC_LOCAL_TEMPO_SCOPE; + if (view) { view->end_write (); } @@ -1911,6 +2074,8 @@ Pianoroll::end_write () void Pianoroll::manage_possible_header (Gtk::Allocation& alloc) { + EC_LOCAL_TEMPO_SCOPE; + if (prh) { double w, h; prh->size_request (w, h); @@ -1922,6 +2087,8 @@ Pianoroll::manage_possible_header (Gtk::Allocation& alloc) void Pianoroll::show_count_in (std::string const & str) { + EC_LOCAL_TEMPO_SCOPE; + if (view) { view->set_overlay_text (str); } @@ -1930,6 +2097,8 @@ Pianoroll::show_count_in (std::string const & str) void Pianoroll::hide_count_in () { + EC_LOCAL_TEMPO_SCOPE; + if (view) { view->hide_overlay_text (); } @@ -1938,6 +2107,8 @@ Pianoroll::hide_count_in () void Pianoroll::instant_save () { + EC_LOCAL_TEMPO_SCOPE; + region_ui_settings.draw_length = draw_length(); region_ui_settings.draw_velocity = draw_velocity(); region_ui_settings.channel = draw_channel(); @@ -1950,6 +2121,8 @@ Pianoroll::instant_save () void Pianoroll::parameter_changed (std::string param) { + EC_LOCAL_TEMPO_SCOPE; + if (param == X_("note-name-display")) { if (prh) { prh->instrument_info_change (); diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 295a0081a6..eb0e46b9bf 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -278,14 +278,9 @@ public: virtual void hide_track_in_display (TimeAxisView* tv, bool apply_to_selection = false) = 0; virtual void show_track_in_display (TimeAxisView* tv, bool move_into_view = false) = 0; - virtual void set_stationary_playhead (bool yn) = 0; - virtual void toggle_stationary_playhead () = 0; - virtual bool stationary_playhead() const = 0; - virtual void toggle_cue_behavior () = 0; /** @return true if the playhead is currently being dragged, otherwise false */ - virtual bool dragging_playhead () const = 0; virtual samplepos_t leftmost_sample() const = 0; virtual samplecnt_t current_page_samples() const = 0; virtual double visible_canvas_height () const = 0; diff --git a/gtk2_ardour/region_ui_settings.cc b/gtk2_ardour/region_ui_settings.cc index c4f4efe523..d208c5f03e 100644 --- a/gtk2_ardour/region_ui_settings.cc +++ b/gtk2_ardour/region_ui_settings.cc @@ -141,8 +141,8 @@ RegionUISettingsManager::save (std::string const & path) state_tree.set_root (&get_state()); state_tree.set_filename (path); - if (state_tree.write()) { - error << string_compose (_("could not save region GUI settings to %1"), path) << endmsg; + if (!state_tree.write()) { + error << string_compose (_("Could not save region GUI settings to %1"), path) << endmsg; } } diff --git a/gtk2_ardour/ui_config_vars.inc.h b/gtk2_ardour/ui_config_vars.inc.h index 2518e476c5..9b59b2c3da 100644 --- a/gtk2_ardour/ui_config_vars.inc.h +++ b/gtk2_ardour/ui_config_vars.inc.h @@ -126,10 +126,10 @@ UI_CONFIG_VARIABLE (uint32_t, action_table_columns, "action-table-columns", 3) UI_CONFIG_VARIABLE (bool, hide_splash_screen, "hide-splash-screen", true) UI_CONFIG_VARIABLE (bool, check_announcements, "check-announcements,", true) UI_CONFIG_VARIABLE (bool, use_wm_visibility, "use-wm-visibility", true) +UI_CONFIG_VARIABLE (std::string, stripable_color_palette, "stripable-color-palette", "#AA3939:#FFAAAA:#D46A6A:#801515:#550000:#AA8E39:#FFEAAA:#D4BA6A:#806515:#554000:#343477:#8080B3:#565695:#1A1A59:#09093B:#2D882D:#88CC88:#55AA55:#116611:#004400") /* Gtk::ColorSelection::palette_to_string */ UI_CONFIG_VARIABLE (bool, use_palette_for_new_track, "use-palette-for-new-track", true) UI_CONFIG_VARIABLE (bool, use_palette_for_new_bus, "use-palette-for-new-bus", true) UI_CONFIG_VARIABLE (bool, use_palette_for_new_vca, "use-palette-for-new-vca", true) -UI_CONFIG_VARIABLE (std::string, stripable_color_palette, "stripable-color-palette", "#AA3939:#FFAAAA:#D46A6A:#801515:#550000:#AA8E39:#FFEAAA:#D4BA6A:#806515:#554000:#343477:#8080B3:#565695:#1A1A59:#09093B:#2D882D:#88CC88:#55AA55:#116611:#004400") /* Gtk::ColorSelection::palette_to_string */ UI_CONFIG_VARIABLE (bool, use_note_bars_for_velocity, "use-note-bars-for-velocity", true) UI_CONFIG_VARIABLE (bool, use_note_color_for_velocity, "use-note-color-for-velocity", true) UI_CONFIG_VARIABLE (bool, show_snapped_cursor, "show-snapped-cursor", true) diff --git a/gtk2_ardour/velocity_display.cc b/gtk2_ardour/velocity_display.cc index 806a837ad0..2a1fb9f1d9 100644 --- a/gtk2_ardour/velocity_display.cc +++ b/gtk2_ardour/velocity_display.cc @@ -327,9 +327,9 @@ VelocityDisplay::drag_lolli (ArdourCanvas::Lollipop* l, GdkEventMotion* ev) snprintf (buf, sizeof (buf), "Velocity %d (%d)", verbose_velocity, verbose_velocity - oldvel); } - editing_context.verbose_cursor()->set (buf); - editing_context.verbose_cursor()->show (); - editing_context.verbose_cursor()->set_offset (ArdourCanvas::Duple (10., 10.)); + editing_context.verbose_cursor().set (buf); + editing_context.verbose_cursor().show (); + editing_context.verbose_cursor().set_offset (ArdourCanvas::Duple (10., 10.)); } int diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index bb078ef2f7..7f0723f5f1 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -291,6 +291,8 @@ class LIBARDOUR_API AudioRegion : public Region, public AudioReadable int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal); void send_change (const PBD::PropertyChange&); void ensure_length_sanity (); + + void set_tempo_stuff_from_source (); }; } /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/debug.h b/libs/ardour/ardour/debug.h index 61b84ad16a..c5e71d5c13 100644 --- a/libs/ardour/ardour/debug.h +++ b/libs/ardour/ardour/debug.h @@ -117,6 +117,7 @@ namespace PBD { LIBARDOUR_API extern DebugBits WiimoteControl; LIBARDOUR_API extern DebugBits Freesound; LIBARDOUR_API extern DebugBits ClipRecording; + LIBARDOUR_API extern DebugBits TempoEstimation; } } diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index d5f8d97877..795bf8f8a9 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -157,6 +157,8 @@ class LIBARDOUR_API MidiRegion : public Region void model_shifted (timecnt_t qn_distance); void model_automation_state_changed (Evoral::Parameter const &); + void set_tempo_stuff_from_source (); + std::set _filtered_parameters; ///< parameters that we ask our source not to return when reading PBD::ScopedConnection _model_connection; PBD::ScopedConnection _model_shift_connection; diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index d682ac9e0f..bccdbf78f0 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -29,6 +29,7 @@ #include "temporal/domain_swap.h" #include "temporal/timeline.h" #include "temporal/range.h" +#include "temporal/tempo.h" #include "pbd/undo.h" #include "pbd/signals.h" @@ -541,6 +542,9 @@ public: } } + Temporal::Tempo tempo() const { return _tempo; } + Temporal::Meter meter() const { return _meter; } + protected: virtual XMLNode& state () const; @@ -593,6 +597,9 @@ protected: uint32_t _fx_tail; RegionFxList _plugins; + Temporal::Tempo _tempo; + Temporal::Meter _meter; + PBD::Property _sync_marked; PBD::Property _left_of_split; PBD::Property _right_of_split; diff --git a/libs/ardour/ardour/utils.h b/libs/ardour/ardour/utils.h index 73b3ccc0d6..dfc71a5c88 100644 --- a/libs/ardour/ardour/utils.h +++ b/libs/ardour/ardour/utils.h @@ -44,10 +44,15 @@ class XMLNode; +namespace Temporal { + class Meter; +} + namespace ARDOUR { class Route; class Track; +class Region; LIBARDOUR_API std::string legalize_for_path (const std::string& str); LIBARDOUR_API std::string legalize_for_universal_path (const std::string& str); @@ -146,6 +151,8 @@ template std::shared_ptr stripable_list_to_co return cl; } +LIBARDOUR_API bool estimate_audio_tempo (std::shared_ptr region, Sample* data, samplecnt_t data_length, samplecnt_t sample_rate, double& qpm, Temporal::Meter& meter, double& beatcount); + #if __APPLE__ LIBARDOUR_API std::string CFStringRefToStdString(CFStringRef stringRef); #endif // __APPLE__ diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 3010687d38..0637e91126 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -433,6 +433,21 @@ AudioRegion::~AudioRegion () } } +void +AudioRegion::set_tempo_stuff_from_source () +{ + samplecnt_t data_size = _session.sample_rate() * 10; + std::unique_ptr data (new Sample[data_size]); + + if (read (data.get(), 0, data_size, 0) == data_size) { + double tempo; + double beatcount; + + estimate_audio_tempo (shared_from_this(), data.get(), data_size, _session.sample_rate(), tempo, _meter, beatcount); + _tempo = Temporal::Tempo (tempo, 4); + } +} + void AudioRegion::post_set (const PropertyChange& /*ignored*/) { @@ -2740,4 +2755,3 @@ AudioRegion::ensure_length_sanity () _length = timecnt_t (timepos_t (_length.val().samples()), _length.val().position()); } } - diff --git a/libs/ardour/debug.cc b/libs/ardour/debug.cc index 55171fef8f..b738c3f7b7 100644 --- a/libs/ardour/debug.cc +++ b/libs/ardour/debug.cc @@ -113,3 +113,4 @@ PBD::DebugBits PBD::DEBUG::VSTCallbacks = PBD::new_debug_bit ("vstcallbacks"); PBD::DebugBits PBD::DEBUG::WiimoteControl = PBD::new_debug_bit ("wiimotecontrol"); PBD::DebugBits PBD::DEBUG::Freesound = PBD::new_debug_bit ("freesound"); PBD::DebugBits PBD::DEBUG::ClipRecording = PBD::new_debug_bit ("cliprecording"); +PBD::DebugBits PBD::DEBUG::TempoEstimation = PBD::new_debug_bit ("tempoestimation"); diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index 119a3cdb83..4b8db7f199 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -3528,7 +3528,7 @@ LuaBindings::non_rt (lua_State* L) .addFunction ("add_master_bus", &Session::add_master_bus) .endClass () - .deriveWSPtrClass ("Route") + .beginWSPtrClass ("Route") .addFunction ("save_as_template", &Route::save_as_template) .addFunction ("add_sidechain", &Route::add_sidechain) .addFunction ("remove_sidechain", &Route::remove_sidechain) diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index dd9dc1d49b..348d0f7bbc 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -70,6 +70,8 @@ MidiRegion::MidiRegion (const SourceList& srcs) : Region (srcs) , _ignore_shift (false) { + set_tempo_stuff_from_source (); + /* by default MIDI regions are transparent, * this should probably be set depending on use-case, * (eg. loop recording, vs copy/edit/paste) @@ -106,6 +108,26 @@ MidiRegion::~MidiRegion () { } +void +MidiRegion::set_tempo_stuff_from_source () +{ + std::shared_ptr smf = std::dynamic_pointer_cast (midi_source ()); + assert (smf); + + bool provided; + Temporal::TempoMap::SharedPtr new_map (smf->tempo_map (provided)); + + if (!provided) { + new_map.reset (new Temporal::TempoMap()); + } + + Temporal::TempoPoint const tp (new_map->tempo_at (start())); + Temporal::MeterPoint const mp (new_map->meter_at (start())); + + _tempo = tp; + _meter = mp; +} + /** Export the MIDI data of the MidiRegion to a new MIDI file (SMF). */ bool diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index ac7d2ab2b6..6da010e635 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -228,7 +228,9 @@ Region::register_properties () } #define REGION_DEFAULT_STATE(s,l) \ - _sync_marked (Properties::sync_marked, false) \ + _tempo (120, 4) \ + , _meter (4, 4) \ + , _sync_marked (Properties::sync_marked, false) \ , _left_of_split (Properties::left_of_split, false) \ , _right_of_split (Properties::right_of_split, false) \ , _valid_transients (Properties::valid_transients, false) \ @@ -259,7 +261,9 @@ Region::register_properties () , _contents (Properties::contents, false) #define REGION_COPY_STATE(other) \ - _sync_marked (Properties::sync_marked, other->_sync_marked) \ + _tempo (other->_tempo) \ + , _meter (other->_meter) \ + , _sync_marked (Properties::sync_marked, other->_sync_marked) \ , _left_of_split (Properties::left_of_split, other->_left_of_split) \ , _right_of_split (Properties::right_of_split, other->_right_of_split) \ , _valid_transients (Properties::valid_transients, other->_valid_transients) \ @@ -1420,6 +1424,9 @@ Region::state () const node->set_property ("id", id ()); node->set_property ("type", _type); + node->add_child_nocopy (_tempo.get_state()); + node->add_child_nocopy (_meter.get_state()); + std::string fe; switch (_first_edit) { @@ -1619,6 +1626,10 @@ Region::_set_state (const XMLNode& node, int version, PropertyChange& what_chang } _plugins.push_back (rfx); changed = true; + } else if (child->name() == Temporal::Tempo::xml_node_name) { + _tempo.set_state (*child, version); + } else if (child->name() == Temporal::Meter::xml_node_name) { + _meter.set_state (*child, version); } } lm.release (); diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index a73a091cde..d3c1b729c8 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -1773,123 +1773,11 @@ AudioTrigger::set_region_in_worker_thread_internal (std::shared_ptr r, b void AudioTrigger::estimate_tempo () { - using namespace Temporal; - TempoMap::SharedPtr tm (TempoMap::use()); + double beatcount; + ARDOUR::estimate_audio_tempo (_region, data[0], data.length, _box.session().sample_rate(), _estimated_tempo, _meter, beatcount); + /* initialize our follow_length to match the beatcnt ... user can later change this value to have the clip end sooner or later than its data length */ + set_follow_length(Temporal::BBT_Offset( 0, rint(beatcount), 0)); - TimelineRange range (_region->start(), _region->start() + _region->length(), 0); - SegmentDescriptor segment; - bool have_segment; - - have_segment = _region->source (0)->get_segment_descriptor (range, segment); - - if (have_segment) { - - _estimated_tempo = segment.tempo().quarter_notes_per_minute (); - _meter = segment.meter(); - DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1: tempo and meter from segment descriptor\n", index())); - - } else { - /* not a great guess, but what else can we do? */ - - TempoMetric const & metric (tm->metric_at (timepos_t (AudioTime))); - - _meter = metric.meter (); - - /* check the name to see if there's a (heuristically obvious) hint - * about the tempo. - */ - - string str = _region->name(); - string::size_type bi; - string::size_type ni; - double text_tempo = -1.; - - if (((bi = str.find (" bpm")) != string::npos) || - ((bi = str.find ("bpm")) != string::npos) || - ((bi = str.find (" BPM")) != string::npos) || - ((bi = str.find ("BPM")) != string::npos) ){ - - string sub (str.substr (0, bi)); - - if ((ni = sub.find_last_of ("0123456789.,_-")) != string::npos) { - - int nni = ni; /* ni is unsigned, nni is signed */ - - while (nni >= 0) { - if (!isdigit (sub[nni]) && - (sub[nni] != '.') && - (sub[nni] != ',')) { - break; - } - --nni; - } - - if (nni > 0) { - std::stringstream p (sub.substr (nni + 1)); - p >> text_tempo; - if (!p) { - text_tempo = -1.; - } else { - _estimated_tempo = text_tempo; - } - } - } - } - - if (text_tempo < 0) { - - breakfastquay::MiniBPM mbpm (_box.session().sample_rate()); - - _estimated_tempo = mbpm.estimateTempoOfSamples (data[0], data.length); - - //cerr << name() << "MiniBPM Estimated: " << _estimated_tempo << " bpm from " << (double) data.length / _box.session().sample_rate() << " seconds\n"; - } - } - - const double seconds = (double) data.length / _box.session().sample_rate(); - - /* now check the determined tempo and force it to a value that gives us - an integer beat/quarter count. This is a heuristic that tries to - avoid clips that slightly over- or underrun a quantization point, - resulting in small or larger gaps in output if they are repeating. - */ - - if ((_estimated_tempo != 0.)) { - /* fractional beatcnt */ - double maybe_beats = (seconds / 60.) * _estimated_tempo; - double beatcount = round (maybe_beats); - - /* the vast majority of third-party clips are 1,2,4,8, or 16-bar 'beats'. - * Given no other metadata, it makes things 'just work' if we assume 4/4 time signature, and power-of-2 bars (1,2,4,8 or 16) - * TODO: someday we could provide a widget for users who have unlabeled, un-metadata'd, clips that they *know* are 3/4 or 5/4 or 11/4 */ - { - double barcount = round (beatcount/4); - if (barcount <= 18) { /* why not 16 here? fuzzy logic allows minibpm to misjudge the clip a bit */ - for (int pwr = 0; pwr <= 4; pwr++) { - float bc = pow(2,pwr); - if (barcount <= bc) { - barcount = bc; - break; - } - } - } - beatcount = round(barcount * 4); - } - - DEBUG_RESULT (double, est, _estimated_tempo); - _estimated_tempo = beatcount / (seconds/60.); - DEBUG_TRACE (DEBUG::Triggers, string_compose ("given original estimated tempo %1, rounded beatcnt is %2 : resulting in working bpm = %3\n", est, _beatcnt, _estimated_tempo)); - - /* initialize our follow_length to match the beatcnt ... user can later change this value to have the clip end sooner or later than its data length */ - set_follow_length(Temporal::BBT_Offset( 0, rint(beatcount), 0)); - } - -#if 0 - cerr << "estimated tempo: " << _estimated_tempo << endl; - const samplecnt_t one_beat = tm->bbt_duration_at (timepos_t (AudioTime), BBT_Offset (0, 1, 0)).samples(); - cerr << "one beat in samples: " << one_beat << endl; - cerr << "rounded beatcount = " << round (beatcount) << endl; -#endif } bool @@ -2757,14 +2645,9 @@ SegmentDescriptor MIDITrigger::get_segment_descriptor () const { SegmentDescriptor sd; - std::shared_ptr mr = std::dynamic_pointer_cast (_region); - assert (mr); - - sd.set_extent (Temporal::Beats(), mr->length().beats()); - - /* we don't really have tempo information for MIDI yet */ - sd.set_tempo (Temporal::Tempo (120, 4)); + sd.set_extent (Temporal::Beats(), _region->length().beats()); + sd.set_tempo (_region->tempo()); return sd; } diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc index c42d400839..cacb5f79db 100644 --- a/libs/ardour/utils.cc +++ b/libs/ardour/utils.cc @@ -60,8 +60,15 @@ #include "pbd/strsplit.h" #include "pbd/replace_all.h" -#include "ardour/utils.h" +#include "temporal/tempo.h" + +#include "ardour/debug.h" +#include "ardour/minibpm.h" +#include "ardour/region.h" #include "ardour/rc_configuration.h" +#include "ardour/segment_descriptor.h" +#include "ardour/source.h" +#include "ardour/utils.h" #include "pbd/i18n.h" @@ -793,3 +800,126 @@ ARDOUR::compute_sha1_of_file (std::string path) sha1_result_hash (&s, hash); return std::string (hash); } + +bool +ARDOUR::estimate_audio_tempo (std::shared_ptr region, Sample* data, samplecnt_t data_length, samplecnt_t sample_rate, double& qpm, Temporal::Meter& meter, double& beatcount) +{ + using namespace Temporal; + TempoMap::SharedPtr tm (TempoMap::use()); + + TimelineRange range (region->start(), region->start() + region->length(), 0); + SegmentDescriptor segment; + bool have_segment; + + have_segment = region->source (0)->get_segment_descriptor (range, segment); + + if (have_segment) { + + qpm = segment.tempo().quarter_notes_per_minute (); + meter = segment.meter(); + DEBUG_TRACE (DEBUG::TempoEstimation, string_compose ("%1: tempo and meter from segment descriptor\n", region->name())); + + } else { + /* not a great guess, but what else can we do? */ + + TempoMetric const & metric (tm->metric_at (timepos_t (AudioTime))); + + meter = metric.meter (); + + /* check the name to see if there's a (heuristically obvious) hint + * about the tempo. + */ + + string str = region->name(); + string::size_type bi; + string::size_type ni; + double text_tempo = -1.; + + if (((bi = str.find (" bpm")) != string::npos) || + ((bi = str.find ("bpm")) != string::npos) || + ((bi = str.find (" BPM")) != string::npos) || + ((bi = str.find ("BPM")) != string::npos) ){ + + string sub (str.substr (0, bi)); + + if ((ni = sub.find_last_of ("0123456789.,_-")) != string::npos) { + + int nni = ni; /* ni is unsigned, nni is signed */ + + while (nni >= 0) { + if (!isdigit (sub[nni]) && + (sub[nni] != '.') && + (sub[nni] != ',')) { + break; + } + --nni; + } + + if (nni > 0) { + std::stringstream p (sub.substr (nni + 1)); + p >> text_tempo; + if (!p) { + text_tempo = -1.; + } else { + qpm = text_tempo; + } + } + } + } + + if (text_tempo < 0) { + + breakfastquay::MiniBPM mbpm (sample_rate); + + qpm = mbpm.estimateTempoOfSamples (data, data_length); + + //cerr << name() << "MiniBPM Estimated: " << qpm << " bpm from " << (double) data.length / _box.session().sample_rate() << " seconds\n"; + } + } + + const double seconds = (double) data_length / sample_rate; + + /* now check the determined tempo and force it to a value that gives us + an integer beat/quarter count. This is a heuristic that tries to + avoid clips that slightly over- or underrun a quantization point, + resulting in small or larger gaps in output if they are repeating. + */ + + if ((qpm != 0.)) { + /* fractional beatcnt */ + double maybe_beats = (seconds / 60.) * qpm; + beatcount = round (maybe_beats); + + /* the vast majority of third-party clips are 1,2,4,8, or 16-bar 'beats'. + * Given no other metadata, it makes things 'just work' if we assume 4/4 time signature, and power-of-2 bars (1,2,4,8 or 16) + * TODO: someday we could provide a widget for users who have unlabeled, un-metadata'd, clips that they *know* are 3/4 or 5/4 or 11/4 */ + { + double barcount = round (beatcount/4); + if (barcount <= 18) { /* why not 16 here? fuzzy logic allows minibpm to misjudge the clip a bit */ + for (int pwr = 0; pwr <= 4; pwr++) { + float bc = pow(2,pwr); + if (barcount <= bc) { + barcount = bc; + break; + } + } + } + beatcount = round(barcount * 4); + } + + DEBUG_RESULT (double, est, qpm); + qpm = beatcount / (seconds/60.); + DEBUG_TRACE (DEBUG::TempoEstimation, string_compose ("given original estimated tempo %1, rounded beatcnt is %2 : resulting in working bpm = %3\n", est, beatcount, qpm)); + + } + +#if 0 + cerr << "estimated tempo: " << qpm << endl; + const samplecnt_t one_beat = tm->bbt_duration_at (timepos_t (AudioTime), BBT_Offset (0, 1, 0)).samples(); + cerr << "one beat in samples: " << one_beat << endl; + cerr << "rounded beatcount = " << round (beatcount) << endl; +#endif + + return true; +} + diff --git a/libs/evoral/ControlList.cc b/libs/evoral/ControlList.cc index b6ec83b3ad..6ef47917b0 100644 --- a/libs/evoral/ControlList.cc +++ b/libs/evoral/ControlList.cc @@ -1883,20 +1883,33 @@ ControlList::rt_safe_earliest_event_linear_unlocked (Temporal::timepos_t const& } /* This method is ONLY used for interpolating to generate value/time - * duples not present in the actual ControlList, and because of this, - * the desired time domain is always audio time. + * duples not present in the actual ControlList */ - double a = first->when.superclocks (); - double b = next->when.superclocks (); - const double slope = (b - a) / (next->value - first->value); - assert (slope != 0); + double slope; + + if (time_domain() == Temporal::AudioTime) { + double a = first->when.superclocks (); + double b = next->when.superclocks (); + slope = (b - a) / (next->value - first->value); + assert (slope != 0); + double t = start_time.superclocks (); + double dt = fmod (t, fabs (slope)); + t += fabs (slope) - dt; + x = timecnt_t::from_superclock (t + 1); + y = rint (first->value + (t - a) / slope); + } else { + double a = first->when.beats().to_ticks(); + double b = next->when.beats().to_ticks(); + slope = (b - a) / (next->value - first->value); + assert (slope != 0); + double t = start_time.beats ().to_ticks(); + double dt = fmod (t, fabs (slope)); + t += fabs (slope) - dt; + x = timecnt_t::from_ticks (t + 1); + y = rint (first->value + (t - a) / slope); + } - double t = start_time.superclocks (); - double dt = fmod (t, fabs (slope)); - t += fabs (slope) - dt; - x = timecnt_t::from_superclock (t + 1); - y = rint (first->value + (t - a) / slope); if (slope > 0) { y = std::max (first->value, std::min (next->value, y)); } else { diff --git a/libs/surfaces/mackie/strip.cc b/libs/surfaces/mackie/strip.cc index 453b7a4808..1fc71d51aa 100644 --- a/libs/surfaces/mackie/strip.cc +++ b/libs/surfaces/mackie/strip.cc @@ -234,7 +234,7 @@ Strip::set_stripable (std::shared_ptr r, bool /*with_messages*/) _stripable->solo_control()->Changed.connect (stripable_connections, MISSING_INVALIDATOR, std::bind (&Strip::notify_solo_changed, this), ui_context()); _stripable->mute_control()->Changed.connect(stripable_connections, MISSING_INVALIDATOR, std::bind (&Strip::notify_mute_changed, this), ui_context()); - _stripable->MappedControlsChanged.connect (stripable_connections, MISSING_INVALIDATOR, std::bind (&Strip::notify_eq_type_changed, this), ui_context()); + _stripable->MappedControlsChanged.connect (stripable_connections, MISSING_INVALIDATOR, std::bind (&Strip::notify_subview_type_changed, this), ui_context()); std::shared_ptr pan_control = _stripable->pan_azimuth_control(); if (pan_control) { @@ -350,7 +350,7 @@ Strip::notify_record_enable_changed () } void -Strip::notify_eq_type_changed () +Strip::notify_subview_type_changed () { if (_stripable) { _surface->mcp().MackieControlProtocol::redisplay_subview_mode(); @@ -719,6 +719,17 @@ Strip::remove_units (std::string s) { s = std::regex_replace (s, std::regex(" dB$"), ""); s = std::regex_replace (s, std::regex(" ms$"), ""); + // convert seconds to milliseconds + if (s.rfind(" s") != string::npos) { + char buf[32]; + s = std::regex_replace (s, std::regex(" s$"), ""); + if (sprintf(buf, "%2.0f", 1000.0*stof(s)) >= 0) { + s = std::string (buf); + } else { + DEBUG_TRACE (DEBUG::MackieControl, "couldn't convert string to float\n"); + } + } + return s; } diff --git a/libs/surfaces/mackie/strip.h b/libs/surfaces/mackie/strip.h index fbb7863a69..c944bc86ad 100644 --- a/libs/surfaces/mackie/strip.h +++ b/libs/surfaces/mackie/strip.h @@ -157,7 +157,7 @@ private: void notify_solo_changed (); void notify_mute_changed (); void notify_record_enable_changed (); - void notify_eq_type_changed (); + void notify_subview_type_changed (); void notify_gain_changed (bool force_update = true); void notify_property_changed (const PBD::PropertyChange&); void notify_panner_azi_changed (bool force_update = true); diff --git a/libs/surfaces/mackie/subview.cc b/libs/surfaces/mackie/subview.cc index c9045e3de5..a9eb36324d 100644 --- a/libs/surfaces/mackie/subview.cc +++ b/libs/surfaces/mackie/subview.cc @@ -278,6 +278,7 @@ void NoneSubview::setup_vpot( EQSubview::EQSubview(MackieControlProtocol& mcp, std::shared_ptr subview_stripable) : Subview(mcp, subview_stripable) + , _current_bank(0) {} EQSubview::~EQSubview() @@ -308,8 +309,8 @@ void EQSubview::setup_vpot( Pot* vpot, std::string pending_display[2]) { - const uint32_t global_strip_position = _mcp.global_index (*strip); - store_pointers(strip, vpot, pending_display, global_strip_position); + const uint32_t global_strip_position = _mcp.global_index (*strip) + _current_bank; + store_pointers(strip, vpot, pending_display, global_strip_position - _current_bank); if (!_subview_stripable) { return; @@ -357,6 +358,18 @@ void EQSubview::setup_vpot( pc = _subview_stripable->mapped_control(EQ_Enable); pot_id = "EQ"; break; + case 11: + pc = _subview_stripable->mapped_control(LPF_Freq); + pot_id = "LPF"; + break; + case 12: + pc = _subview_stripable->mapped_control(HPF_Freq); + pot_id = "HPF"; + break; + case 13: + pc = _subview_stripable->mapped_control(HPF_Enable); // shared HP/LP + pot_id = "Filter"; + break; } } else { //mixbus or master bus ( these are currently the same for MB & 32C ) @@ -402,7 +415,7 @@ void EQSubview::notify_change (std::weak_ptr pc, uint Strip* strip = 0; Pot* vpot = 0; std::string* pending_display = 0; - if (!retrieve_pointers(&strip, &vpot, &pending_display, global_strip_position)) + if (!retrieve_pointers(&strip, &vpot, &pending_display, global_strip_position - _current_bank)) { return; } @@ -416,10 +429,32 @@ void EQSubview::notify_change (std::weak_ptr pc, uint } } +bool EQSubview::handle_cursor_left_press() +{ + if (_current_bank >= 1) + { + _current_bank -= 1; + mcp().redisplay_subview_mode(); + } + + return true; +} + +bool EQSubview::handle_cursor_right_press() +{ + if (/* todo: generate this value on redisplay */ 14 > _current_bank + 1) { + _current_bank += 1; + mcp().redisplay_subview_mode(); + } + + return true; +} + DynamicsSubview::DynamicsSubview(MackieControlProtocol& mcp, std::shared_ptr subview_stripable) : Subview(mcp, subview_stripable) + , _current_bank(0) {} DynamicsSubview::~DynamicsSubview() @@ -450,54 +485,46 @@ void DynamicsSubview::setup_vpot( Pot* vpot, std::string pending_display[2]) { - const uint32_t global_strip_position = _mcp.global_index (*strip); - store_pointers(strip, vpot, pending_display, global_strip_position); + const uint32_t global_strip_position = _mcp.global_index (*strip) + _current_bank; + store_pointers(strip, vpot, pending_display, global_strip_position - _current_bank); if (!_subview_stripable) { return; } - std::shared_ptr hpfc = _subview_stripable->mapped_control (HPF_Freq); - std::shared_ptr lpfc = _subview_stripable->mapped_control (LPF_Freq); - std::shared_ptr fec = _subview_stripable->mapped_control (HPF_Enable); // shared HP/LP + available.clear(); + std::shared_ptr cec = _subview_stripable->mapped_control (Comp_Enable); std::shared_ptr ctc = _subview_stripable->mapped_control (Comp_Threshold); std::shared_ptr crc = _subview_stripable->mapped_control (Comp_Ratio); std::shared_ptr cac = _subview_stripable->mapped_control (Comp_Attack); std::shared_ptr csc = _subview_stripable->mapped_control (Comp_Release); std::shared_ptr ckc = _subview_stripable->mapped_control (Comp_Makeup); - std::shared_ptr cec = _subview_stripable->mapped_control (Comp_Enable); + std::shared_ptr gec = _subview_stripable->mapped_control (Gate_Enable); std::shared_ptr gtc = _subview_stripable->mapped_control (Gate_Threshold); std::shared_ptr gdc = _subview_stripable->mapped_control (Gate_Depth); std::shared_ptr gac = _subview_stripable->mapped_control (Gate_Attack); std::shared_ptr gsc = _subview_stripable->mapped_control (Gate_Release); - std::shared_ptr gec = _subview_stripable->mapped_control (Gate_Enable); /* we will control the global_strip_position-th available parameter, from the list in the * order shown above. */ - std::vector, std::string > > available; std::vector params; - //Mixbus32C needs to spill the filter controls into the comp section - if (hpfc) { available.push_back (std::make_pair (hpfc, "HPF")); } - if (lpfc) { available.push_back (std::make_pair (lpfc, "LPF")); } - if (fec) { available.push_back (std::make_pair (fec, "FiltIn")); } + if (cec) { available.push_back (std::make_pair (cec, "Comp")); } + if (ctc) { available.push_back (std::make_pair (ctc, "CThrsh")); } + if (crc) { available.push_back (std::make_pair (crc, "CRatio")); } + if (cac) { available.push_back (std::make_pair (cac, "CAttk")); } + if (csc) { available.push_back (std::make_pair (csc, "CRels")); } + if (ckc) { available.push_back (std::make_pair (ckc, "CMkup")); } - if (ctc) { available.push_back (std::make_pair (ctc, "Thresh")); } - if (crc) { available.push_back (std::make_pair (crc, "Ratio")); } - if (cac) { available.push_back (std::make_pair (cac, "Attk")); } - if (csc) { available.push_back (std::make_pair (csc, "Rels")); } - if (ckc) { available.push_back (std::make_pair (ckc, "Makeup")); } - if (cec) { available.push_back (std::make_pair (cec, "on/off")); } - - if (gtc) { available.push_back (std::make_pair (gtc, "Thresh")); } - if (gdc) { available.push_back (std::make_pair (gdc, "Depth")); } - if (gac) { available.push_back (std::make_pair (gac, "Attk")); } - if (gsc) { available.push_back (std::make_pair (gsc, "Rels")); } - if (gec) { available.push_back (std::make_pair (gec, "on/off")); } + if (gec) { available.push_back (std::make_pair (gec, "Gate")); } + if (gtc) { available.push_back (std::make_pair (gtc, "GThrsh")); } + if (gdc) { available.push_back (std::make_pair (gdc, "GDepth")); } + if (gac) { available.push_back (std::make_pair (gac, "GAttk")); } + if (gsc) { available.push_back (std::make_pair (gsc, "GRels")); } if (global_strip_position >= available.size()) { /* this knob is not needed to control the available parameters */ @@ -535,7 +562,7 @@ DynamicsSubview::notify_change (std::weak_ptr pc, uin Strip* strip = 0; Pot* vpot = 0; std::string* pending_display = 0; - if (!retrieve_pointers(&strip, &vpot, &pending_display, global_strip_position)) + if (!retrieve_pointers(&strip, &vpot, &pending_display, global_strip_position - _current_bank)) { return; } @@ -550,16 +577,33 @@ DynamicsSubview::notify_change (std::weak_ptr pc, uin if (control) { float val = control->get_value(); - if (control == _subview_stripable->mapped_control (Comp_Mode)) { - pending_display[1] = control->get_user_string (); - } else { - do_parameter_display(pending_display[1], control->desc(), val, strip, true); - } + pending_display[1] = Strip::remove_units(control->get_user_string()); /* update pot/encoder */ strip->surface()->write (vpot->set (control->internal_to_interface (val), true, Pot::wrap)); } } +bool DynamicsSubview::handle_cursor_left_press() +{ + if (_current_bank >= 1) + { + _current_bank -= 1; + mcp().redisplay_subview_mode(); + } + + return true; +} + +bool DynamicsSubview::handle_cursor_right_press() +{ + if (available.size() > _current_bank + 1) { + _current_bank += 1; + mcp().redisplay_subview_mode(); + } + + return true; +} + SendsSubview::SendsSubview(MackieControlProtocol& mcp, std::shared_ptr subview_stripable) diff --git a/libs/surfaces/mackie/subview.h b/libs/surfaces/mackie/subview.h index 5a5135cd82..25ea4511b8 100644 --- a/libs/surfaces/mackie/subview.h +++ b/libs/surfaces/mackie/subview.h @@ -127,6 +127,10 @@ class EQSubview : public Subview { Pot* vpot, std::string pending_display[2]); void notify_change (std::weak_ptr, uint32_t global_strip_position, bool force); + virtual bool handle_cursor_left_press(); + virtual bool handle_cursor_right_press(); + protected: + uint32_t _current_bank; }; class DynamicsSubview : public Subview { @@ -142,6 +146,11 @@ class DynamicsSubview : public Subview { Pot* vpot, std::string pending_display[2]); void notify_change (std::weak_ptr, uint32_t global_strip_position, bool force, bool propagate_mode_change); + virtual bool handle_cursor_left_press(); + virtual bool handle_cursor_right_press(); + protected: + uint32_t _current_bank; + std::vector, std::string>> available; }; class SendsSubview : public Subview { diff --git a/tools/osx_packaging/entitlements.plist b/tools/osx_packaging/entitlements.plist index cbd83446da..c407f7765c 100644 --- a/tools/osx_packaging/entitlements.plist +++ b/tools/osx_packaging/entitlements.plist @@ -18,5 +18,7 @@ com.apple.security.device.usb + com.apple.security.cs.disable-library-validation +