Merge branch 'master' into scroll

This commit is contained in:
ferprojo 2025-08-09 12:01:35 -06:00 committed by GitHub
commit cfa19d9136
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 1123 additions and 322 deletions

View file

@ -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/`

View file

@ -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

View file

@ -187,7 +187,7 @@
<menuitem action='ToggleAutoReturn'/>
<menuitem action='ToggleClick'/>
<menuitem action='EditorEditing/toggle-follow-playhead'/>
<menuitem action='toggle-stationary-playhead'/>
<menuitem action='EditorEditing/toggle-stationary-playhead'/>
<menuitem action='ToggleFollowEdits'/>
<menuitem action='ToggleExternalSync'/>
<menuitem action='panic'/>

View file

@ -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> region)
{
EC_LOCAL_TEMPO_SCOPE;
CueEditor::set_region (region);
if (_visible_pending_region) {
@ -425,7 +447,7 @@ AudioClipEditor::set_region (std::shared_ptr<Region> 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> 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);
}

View file

@ -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
{

View file

@ -71,11 +71,15 @@ CueEditor::~CueEditor ()
void
CueEditor::set_snapped_cursor_position (Temporal::timepos_t const & pos)
{
EC_LOCAL_TEMPO_SCOPE;
}
std::vector<MidiRegionView*>
CueEditor::filter_to_unique_midi_region_views (RegionSelection const & ms) const
{
EC_LOCAL_TEMPO_SCOPE;
std::vector<MidiRegionView*> 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<ARDOUR::RouteList>) const
{
EC_LOCAL_TEMPO_SCOPE;
TrackViewList tvl;
return tvl;
}
@ -101,42 +111,56 @@ CueEditor::axis_views_from_routes (std::shared_ptr<ARDOUR::RouteList>) 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<Temporal::TempoMap const>
CueEditor::start_local_tempo_map (std::shared_ptr<Temporal::TempoMap> map)
{
std::shared_ptr<Temporal::TempoMap const> tmp = Temporal::TempoMap::use();
Temporal::TempoMap::set (map);
return tmp;
}
void
CueEditor::end_local_tempo_map (std::shared_ptr<Temporal::TempoMap const> 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<Region> 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<Temporal::timepos_t,Temporal::timepos_t>
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<Temporal::timepos_t,Temporal::timepos_t> 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<Track> 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<Track> t)
void
CueEditor::set_region (std::shared_ptr<Region> r)
{
EC_LOCAL_TEMPO_SCOPE;
if (r == _region) {
return;
}
@ -1064,6 +1168,9 @@ CueEditor::set_region (std::shared_ptr<Region> r)
_region = r;
std::shared_ptr<TempoMap> 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<Region> 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<ArdourCanvas::GtkCanvasViewport*>(&_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<ArdourCanvas::Ruler::Mark>& marks, const std::
void
CueEditor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, samplepos_t leftmost, samplepos_t rightmost, gint /*maxchars*/)
{
EC_LOCAL_TEMPO_SCOPE;
if (!_session) {
return;
}

View file

@ -113,9 +113,6 @@ class CueEditor : public EditingContext, public PBD::HistoryOwner
std::vector<MidiRegionView*> filter_to_unique_midi_region_views (RegionSelection const & ms) const;
std::shared_ptr<Temporal::TempoMap const> start_local_tempo_map (std::shared_ptr<Temporal::TempoMap>);
void end_local_tempo_map (std::shared_ptr<Temporal::TempoMap const>);
void scrolled ();
bool canvas_pre_event (GdkEvent*);
void catch_pending_show_region ();

File diff suppressed because it is too large Load diff

View file

@ -87,18 +87,17 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
Temporal::TimeDomain time_domain () const;
struct TempoMapScope {
TempoMapScope (EditingContext& context, std::shared_ptr<Temporal::TempoMap> 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<Temporal::TempoMap const> 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<Gtk::ToggleAction> follow_playhead_action;
void follow_playhead_chosen ();
Glib::RefPtr<Gtk::ToggleAction> 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<VerboseCursor> _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<Temporal::TempoMap const> start_local_tempo_map (std::shared_ptr<Temporal::TempoMap>);
virtual void end_local_tempo_map (std::shared_ptr<Temporal::TempoMap const>) { /* no-op by default */ }
void set_local_tempo_map (std::shared_ptr<Temporal::TempoMap>);
void start_local_tempo_map (std::shared_ptr<Temporal::TempoMap>);
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<ArdourCanvas::Ruler::Mark> grid_marks;
GridLines* grid_lines;
std::unique_ptr<GridLines> 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<Temporal::TempoMap> _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 ()

View file

@ -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<ToggleAction> 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 ();

View file

@ -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;

View file

@ -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)));

View file

@ -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;

View file

@ -426,7 +426,7 @@ Drag::end_grab (GdkEvent* event)
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

View file

@ -122,11 +122,11 @@ MidiStreamView::create_region_view (std::shared_ptr<Region> 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);

View file

@ -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<NoteType> 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));
}

View file

@ -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<bool> 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<ArdourCanvas::GtkCanvas*>(&_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<SelectableOwner*>
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<MidiRegion> mr = std::dynamic_pointer_cast<MidiRegion> (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<MidiRegion> 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<MidiSource> 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<ARDOUR::Track> track)
{
EC_LOCAL_TEMPO_SCOPE;
CueEditor::set_track (track);
if (view) {
@ -1374,6 +1486,8 @@ Pianoroll::set_track (std::shared_ptr<ARDOUR::Track> track)
void
Pianoroll::set_region (std::shared_ptr<ARDOUR::Region> region)
{
EC_LOCAL_TEMPO_SCOPE;
CueEditor::set_region (region);
if (_visible_pending_region) {
@ -1383,6 +1497,7 @@ Pianoroll::set_region (std::shared_ptr<ARDOUR::Region> region)
std::shared_ptr<MidiRegion> r (std::dynamic_pointer_cast<ARDOUR::MidiRegion> (region));
if (!r || !region) {
_update_connection.disconnect ();
return;
}
@ -1442,6 +1557,8 @@ Pianoroll::set_region (std::shared_ptr<ARDOUR::Region> 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<SelectableOwner*> const & ignored, ARDOUR::SelectionOperation op, bool preserve_if_selected)
{
EC_LOCAL_TEMPO_SCOPE;
std::list<Selectable*> 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 ();

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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)

View file

@ -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

View file

@ -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 */

View file

@ -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;
}
}

View file

@ -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<Evoral::Parameter> _filtered_parameters; ///< parameters that we ask our source not to return when reading
PBD::ScopedConnection _model_connection;
PBD::ScopedConnection _model_shift_connection;

View file

@ -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<bool> _sync_marked;
PBD::Property<bool> _left_of_split;
PBD::Property<bool> _right_of_split;

View file

@ -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<typename T> std::shared_ptr<AutomationControlList> stripable_list_to_co
return cl;
}
LIBARDOUR_API bool estimate_audio_tempo (std::shared_ptr<Region> 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__

View file

@ -433,6 +433,21 @@ AudioRegion::~AudioRegion ()
}
}
void
AudioRegion::set_tempo_stuff_from_source ()
{
samplecnt_t data_size = _session.sample_rate() * 10;
std::unique_ptr<Sample> 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());
}
}

View file

@ -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");

View file

@ -3528,7 +3528,7 @@ LuaBindings::non_rt (lua_State* L)
.addFunction ("add_master_bus", &Session::add_master_bus)
.endClass ()
.deriveWSPtrClass <Route, Stripable> ("Route")
.beginWSPtrClass <Route> ("Route")
.addFunction ("save_as_template", &Route::save_as_template)
.addFunction ("add_sidechain", &Route::add_sidechain)
.addFunction ("remove_sidechain", &Route::remove_sidechain)

View file

@ -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<Evoral::SMF> smf = std::dynamic_pointer_cast<Evoral::SMF> (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

View file

@ -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 ();

View file

@ -1773,123 +1773,11 @@ AudioTrigger::set_region_in_worker_thread_internal (std::shared_ptr<Region> 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<MidiRegion> mr = std::dynamic_pointer_cast<MidiRegion> (_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;
}

View file

@ -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> 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;
}

View file

@ -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 {

View file

@ -234,7 +234,7 @@ Strip::set_stripable (std::shared_ptr<Stripable> 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<AutomationControl> 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;
}

View file

@ -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);

View file

@ -278,6 +278,7 @@ void NoneSubview::setup_vpot(
EQSubview::EQSubview(MackieControlProtocol& mcp, std::shared_ptr<ARDOUR::Stripable> 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<ARDOUR::AutomationControl> 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<ARDOUR::AutomationControl> 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<ARDOUR::Stripable> 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<AutomationControl> hpfc = _subview_stripable->mapped_control (HPF_Freq);
std::shared_ptr<AutomationControl> lpfc = _subview_stripable->mapped_control (LPF_Freq);
std::shared_ptr<AutomationControl> fec = _subview_stripable->mapped_control (HPF_Enable); // shared HP/LP
available.clear();
std::shared_ptr<AutomationControl> cec = _subview_stripable->mapped_control (Comp_Enable);
std::shared_ptr<AutomationControl> ctc = _subview_stripable->mapped_control (Comp_Threshold);
std::shared_ptr<AutomationControl> crc = _subview_stripable->mapped_control (Comp_Ratio);
std::shared_ptr<AutomationControl> cac = _subview_stripable->mapped_control (Comp_Attack);
std::shared_ptr<AutomationControl> csc = _subview_stripable->mapped_control (Comp_Release);
std::shared_ptr<AutomationControl> ckc = _subview_stripable->mapped_control (Comp_Makeup);
std::shared_ptr<AutomationControl> cec = _subview_stripable->mapped_control (Comp_Enable);
std::shared_ptr<AutomationControl> gec = _subview_stripable->mapped_control (Gate_Enable);
std::shared_ptr<AutomationControl> gtc = _subview_stripable->mapped_control (Gate_Threshold);
std::shared_ptr<AutomationControl> gdc = _subview_stripable->mapped_control (Gate_Depth);
std::shared_ptr<AutomationControl> gac = _subview_stripable->mapped_control (Gate_Attack);
std::shared_ptr<AutomationControl> gsc = _subview_stripable->mapped_control (Gate_Release);
std::shared_ptr<AutomationControl> 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::pair<std::shared_ptr<AutomationControl>, std::string > > available;
std::vector<AutomationType> 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<ARDOUR::AutomationControl> 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<ARDOUR::AutomationControl> 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<ARDOUR::Stripable> subview_stripable)

View file

@ -127,6 +127,10 @@ class EQSubview : public Subview {
Pot* vpot,
std::string pending_display[2]);
void notify_change (std::weak_ptr<ARDOUR::AutomationControl>, 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<ARDOUR::AutomationControl>, 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::pair<std::shared_ptr<ARDOUR::AutomationControl>, std::string>> available;
};
class SendsSubview : public Subview {

View file

@ -18,5 +18,7 @@
<true/>
<key>com.apple.security.device.usb</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>