add ctrl-drag on tempo bar/ruler to adjust tempo more directly

This commit is contained in:
Paul Davis 2022-05-29 14:19:27 -06:00
parent ef07fb601a
commit fdd634f530
5 changed files with 106 additions and 3 deletions

View File

@ -2493,6 +2493,7 @@ private:
friend class BBTRulerDrag;
friend class MeterMarkerDrag;
friend class TempoMarkerDrag;
friend class TempoCurveDrag;
friend class TempoTwistDrag;
friend class TempoEndDrag;
friend class CursorDrag;

View File

@ -3530,6 +3530,83 @@ MeterMarkerDrag::aborted (bool moved)
}
TempoCurveDrag::TempoCurveDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i, Temporal::BeatTime)
{
}
void
TempoCurveDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{
Drag::start_grab (event, cursor);
/* setup thread-local tempo map ptr as a writable copy */
map = _editor->begin_tempo_map_edit ();
TempoCurve* tc = reinterpret_cast<TempoCurve*> (_item->get_data (X_("tempo curve")));
if (!tc) {
point = const_cast<TempoPoint*> (&map->tempo_at (raw_grab_time()));
} else {
point = const_cast<TempoPoint*> (&tc->tempo());
}
initial_bpm = point->note_types_per_minute();
}
void
TempoCurveDrag::motion (GdkEvent* event, bool first_move)
{
if (first_move) {
/* get current state */
_before_state = &map->get_state();
_editor->begin_reversible_command (_("change tempo"));
}
double new_bpm = std::max (1.5, initial_bpm - ((current_pointer_x() - grab_x()) / 5.0));
stringstream strs;
Temporal::Tempo new_tempo (new_bpm, point->note_type());
map->change_tempo (*point, new_tempo);
strs << "Tempo: " << fixed << setprecision(3) << new_bpm;
show_verbose_cursor_text (strs.str());
_editor->mid_tempo_change ();
}
void
TempoCurveDrag::finished (GdkEvent* event, bool movement_occurred)
{
if (!movement_occurred) {
/* reset the per-thread tempo map ptr back to the current
* official version
*/
_editor->abort_tempo_map_edit ();
if (was_double_click()) {
// XXX would be nice to do this
// _editor->edit_tempo_marker (*_marker);
}
return;
}
/* push the current state of our writable map copy */
TempoMap::update (map);
XMLNode &after = map->get_state();
_editor->session()->add_command (new Temporal::TempoCommand (_("change tempo"), _before_state, &after));
_editor->commit_reversible_command ();
}
void
TempoCurveDrag::aborted (bool moved)
{
/* reset the per-thread tempo map ptr back to the current
* official version
*/
_editor->abort_tempo_map_edit ();
}
TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i, Temporal::BeatTime)
, _grab_bpm (120.0, 4.0)

View File

@ -76,6 +76,7 @@ class MidiRegionView;
class MeterMarker;
class ArdourMarker;
class TempoMarker;
class TempoCurve;
class ControlPoint;
class AudioRegionView;
class AutomationLine;
@ -860,6 +861,24 @@ private:
XMLNode* before_state;
};
/** Tempo curve drag */
class TempoCurveDrag : public Drag
{
public:
TempoCurveDrag (Editor*, ArdourCanvas::Item*);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
void finished (GdkEvent *, bool);
void aborted (bool);
private:
Temporal::TempoPoint* point;
double initial_bpm;
Temporal::TempoMap::WritableSharedPtr map;
XMLNode* _before_state;
};
/** Tempo marker drag */
class TempoMarkerDrag : public Drag
{

View File

@ -816,9 +816,14 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
return true;
break;
case MarkerBarItem:
case TempoBarItem:
case TempoCurveItem:
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drags->set (new TempoCurveDrag (this, item), event);
return true;
}
/* fallthru */
case MarkerBarItem:
case MeterBarItem:
case TimecodeRulerItem:
case SamplesRulerItem:

View File

@ -99,13 +99,14 @@ TempoCurve::TempoCurve (PublicEditor& ed, ArdourCanvas::Item& parent, guint32 rg
* make sure they can both be used to lookup this object.
*/
_curve->set_data ("tempo curve", this);
_curve->set_data (X_("tempo curve"), this);
if (handle_events) {
//group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_marker_event), group, this));
// group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_marker_event), group, this));
}
group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_tempo_curve_event), _curve, this));
_curve->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_tempo_curve_event), _curve, this));
}