diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 06142df30f..9bcbe4fc98 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -2547,8 +2547,7 @@ private: friend class RegionMoveDrag; friend class TrimDrag; friend class MappingTwistDrag; - friend class MappingLinearDrag; - friend class MappingStretchDrag; + friend class MappingEndDrag; friend class MeterMarkerDrag; friend class BBTMarkerDrag; friend class TempoMarkerDrag; diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 8de0576c8e..ba3799b808 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3476,7 +3476,7 @@ BBTMarkerDrag::aborted (bool moved) /******************************************************************************/ -MappingLinearDrag::MappingLinearDrag (Editor* e, ArdourCanvas::Item* i, Temporal::TempoMap::WritableSharedPtr& wmap, TempoPoint& tp, TempoPoint& ap, XMLNode& before) +MappingEndDrag::MappingEndDrag (Editor* e, ArdourCanvas::Item* i, Temporal::TempoMap::WritableSharedPtr& wmap, TempoPoint& tp, TempoPoint& ap, XMLNode& before) : Drag (e, i, Temporal::BeatTime) , _tempo (tp) , _after (ap) @@ -3485,12 +3485,12 @@ MappingLinearDrag::MappingLinearDrag (Editor* e, ArdourCanvas::Item* i, Temporal , _before_state (&before) , _drag_valid (true) { - DEBUG_TRACE (DEBUG::Drags, "New MappingLinearDrag\n"); + DEBUG_TRACE (DEBUG::Drags, "New MappingEndDrag\n"); } void -MappingLinearDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) +MappingEndDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) { Drag::start_grab (event, cursor); @@ -3509,7 +3509,7 @@ MappingLinearDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) } void -MappingLinearDrag::setup_pointer_offset () +MappingEndDrag::setup_pointer_offset () { Beats grab_qn = max (Beats(), raw_grab_time().beats()); @@ -3524,7 +3524,7 @@ MappingLinearDrag::setup_pointer_offset () } void -MappingLinearDrag::motion (GdkEvent* event, bool first_move) +MappingEndDrag::motion (GdkEvent* event, bool first_move) { if (!_drag_valid) { return; @@ -3554,7 +3554,7 @@ MappingLinearDrag::motion (GdkEvent* event, bool first_move) } void -MappingLinearDrag::finished (GdkEvent* event, bool movement_occurred) +MappingEndDrag::finished (GdkEvent* event, bool movement_occurred) { if (!_drag_valid) { aborted (false); @@ -3576,7 +3576,7 @@ MappingLinearDrag::finished (GdkEvent* event, bool movement_occurred) } void -MappingLinearDrag::aborted (bool /* moved */) +MappingEndDrag::aborted (bool /* moved */) { _editor->abort_reversible_command (); _editor->abort_tempo_mapping (); @@ -3600,7 +3600,8 @@ MappingTwistDrag::MappingTwistDrag (Editor* e, ArdourCanvas::Item* i, Temporal:: , _drag_valid (true) { DEBUG_TRACE (DEBUG::Drags, "New MappingTwistDrag\n"); - initial_npm = focus.note_types_per_minute (); + initial_focus_npm = focus.note_types_per_minute (); + initial_pre_npm = prv.note_types_per_minute (); } void @@ -3630,13 +3631,15 @@ MappingTwistDrag::motion (GdkEvent* event, bool first_move) if (_drags->current_pointer_x() < last_pointer_x()) { if (direction < 0.) { direction = 1.; - initial_npm += delta; + initial_focus_npm += delta; + initial_pre_npm += delta; delta = 0.; } } else { if (direction >= 0.) { direction = -1.; - initial_npm += delta; + initial_focus_npm += delta; + initial_pre_npm += delta; delta = 0.; } } @@ -3657,7 +3660,12 @@ MappingTwistDrag::motion (GdkEvent* event, bool first_move) delta += scaling_factor * pixel_distance; std::cerr << "pixels " << pixel_distance << " spp " << spp << " SF " << scaling_factor << " delta = " << delta << std::endl; - map->twist_tempi (prev, focus, next, initial_npm + delta); + bool do_a_ramp = true; // @ben + if (do_a_ramp) { + map->ramped_twist_tempi (prev, focus, next, initial_pre_npm + delta); + } else { + map->linear_twist_tempi (prev, focus, next, initial_focus_npm + delta); + } _editor->mid_tempo_change (Editor::MappingChanged); } diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 0816c78655..7fe7fe4819 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -912,10 +912,10 @@ private: XMLNode* _before_state; }; -class MappingLinearDrag : public Drag +class MappingEndDrag : public Drag { public: - MappingLinearDrag (Editor *, ArdourCanvas::Item *, Temporal::TempoMap::WritableSharedPtr&, Temporal::TempoPoint&, Temporal::TempoPoint& after, XMLNode& before_state); + MappingEndDrag (Editor *, ArdourCanvas::Item *, Temporal::TempoMap::WritableSharedPtr&, Temporal::TempoPoint&, Temporal::TempoPoint& after, XMLNode& before_state); void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); @@ -975,7 +975,8 @@ private: double direction; double delta; - double initial_npm; + double initial_focus_npm; + double initial_pre_npm; XMLNode* _before_state; bool _drag_valid; diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 1af3f0cce8..1b0b13e00a 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -2924,6 +2924,13 @@ Editor::get_pointer_position (double& x, double& y) const void Editor::choose_mapping_drag (ArdourCanvas::Item* item, GdkEvent* event) { + /* In a departure from convention, this event is not handled by a widget + * 'on' the ruler-bar, like a tempo marker, but is instead handled by the + * mapping-bar widget itself. The intent is for the user to feel that they + * are manipulating the 'beat and bar grid' which may or may not have tempo + * markers already assigned at the point under the mouse. + */ + if (item != mapping_bar) { return; } @@ -2935,9 +2942,9 @@ Editor::choose_mapping_drag (ArdourCanvas::Item* item, GdkEvent* event) Temporal::TempoMap::WritableSharedPtr map = begin_tempo_mapping (); - /* Decide between a tempo twist drag, which we do if the - * pointer is between two tempo markers, and a tempo stretch - * drag, which we do if the pointer is after the last tempo + /* Decide between a mid-twist, which we do if the + * pointer is between two tempo markers, and an end-stretch, + * which we do if the pointer is after the last tempo * marker before the end of the map or a BBT Marker. */ @@ -2952,17 +2959,38 @@ Editor::choose_mapping_drag (ArdourCanvas::Item* item, GdkEvent* event) TempoPoint* before; TempoPoint* focus; - bool stretch = false; - + bool at_end = false; if (!after || dynamic_cast(after)) { - stretch = true; + at_end = true; } BBT_Argument bbt = map->bbt_at (pointer_time); bbt = BBT_Argument (bbt.reference(), bbt.round_to_beat ()); - if (tempo.bbt() != bbt) { + /* BBT_Argument is meter-agnostic so we need to use the map's meter to resolve bar boundaries */ + const Meter& m = map->meter_at (pointer_time); + if (bbt.beats > m.divisions_per_bar()){ + bbt.beats = 1; + bbt.bars++; + } + if (tempo.bbt() == bbt) { + std::cerr << "we are on the RIGHT side of an EXISTING tempo marker" << bbt << " == " << tempo.bbt() << "\n"; + + before = const_cast (map->previous_tempo (tempo)); + focus = &tempo; + + } else if ((after && after->bbt() == bbt )) { + std::cerr << "we are on the LEFT side of an EXISTING tempo marker" << bbt << " == " << after->bbt() << "\n"; + + before = const_cast (&tempo); + focus = after; + after = const_cast (map->next_tempo (*focus)); + if (!after) { + at_end = true; //but it's the last one, so we're operating on the last + } + + } else { std::cerr << "ADD TEMPO MARKER " << bbt << " != " << tempo.bbt() << "\n"; /* Add a new tempo marker at the nearest beat point @@ -2978,32 +3006,20 @@ Editor::choose_mapping_drag (ArdourCanvas::Item* item, GdkEvent* event) reset_tempo_marks (); map->dump (std::cerr); - - } else { - - std::cerr << "USE TEMPO MARKER\n"; - - before = const_cast (map->previous_tempo (tempo)); - - if (!before) { - delete before_state; - return; - } - - focus = &tempo; } /* Reversible commands start here, must be ended/aborted in drag */ - if (stretch) { - begin_reversible_command (_("map tempo/stretch")); - std::cerr << "STRETCH\n"; - _drags->set (new MappingLinearDrag (this, item, map, tempo, *focus, *before_state), event); + if (at_end) { + begin_reversible_command (_("tempo mapping: end-stretch")); + std::cerr << "END STRETCH\n"; + _drags->set (new MappingEndDrag (this, item, map, tempo, *focus, *before_state), event); return; } - - std::cerr << "TWIST\n"; - begin_reversible_command (_("map tempo/twist")); - _drags->set (new MappingTwistDrag (this, item, map, *before, *focus, *after, *before_state), event); + if (before && focus && after) { + std::cerr << "TWIST\n"; + begin_reversible_command (_("tempo mapping: mid-twist")); + _drags->set (new MappingTwistDrag (this, item, map, *before, *focus, *after, *before_state), event); + } }