mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 06:44:57 +01:00
Merge branch 'master' into scroll
This commit is contained in:
commit
cfa19d9136
39 changed files with 1123 additions and 322 deletions
|
|
@ -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/`
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'/>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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 ()
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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__
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue