fix logic of editing tempo & meter

Old code use the TempoMetric (Tempo + Meter) in effect at the old
location of the tempo/meter to compute the position of the edited tempo/meter,
using a BBT time from the dialog.

But this TempoMetric uses the very tempo/meter that we're editing!

So we have to use previous_tempo() or previous_meter() to construct
the relevant TempoMetric, and if it is the first tempo or meter, then
obviously it cannot move position at all.
This commit is contained in:
Paul Davis 2023-05-03 21:51:26 -06:00
parent 34ec1e57ac
commit 49e1f7f79d

View File

@ -623,18 +623,46 @@ Editor::edit_meter_section (Temporal::MeterPoint& section)
return;
}
Temporal::TempoMetric tm (TempoMap::use()->metric_at (section.sclock()));
Temporal::MeterPoint const * mpp (TempoMap::use()->previous_meter (tm.meter()));
double bpb = meter_dialog.get_bpb ();
bpb = max (1.0, bpb); // XXX is this a reasonable limit?
double const note_type = meter_dialog.get_note_type ();
const Meter meter (bpb, note_type);
Temporal::BBT_Time w;
meter_dialog.get_bbt_time (w);
Temporal::BBT_Argument when (timepos_t::zero (Temporal::BeatTime), w);
Temporal::Beats new_pos;
if (!mpp) {
/* first meter, cannot move */
new_pos = section.beats ();
} else {
/* Compute the given BBT time using a tempo metric composed
from the tempo in effect at the current position, and the
previous meter.
Step 1: get BBT time from dialog
*/
Temporal::BBT_Time w;
meter_dialog.get_bbt_time (w);
/* Step 2: construct the relevant tempo metric */
TempoMetric prev_tm (tm.tempo(), *mpp);
/* Step 3: construct new BBT_Argument */
Temporal::BBT_Argument when (tm.reftime(), w);
/* Step 4: convert to quarters */
new_pos = prev_tm.quarters_at (when);
}
TempoMapChange tmc (*this, _("edit time signature"));
tmc.map().set_meter (meter, when);
tmc.map().set_meter (meter, timepos_t (new_pos));
}
void
@ -666,7 +694,6 @@ void
Editor::edit_tempo_section (TempoPoint& section)
{
TempoDialog tempo_dialog (TempoMap::use(), section, _("done"));
Temporal::TempoMetric tm (TempoMap::use()->metric_at (section.sclock()));
switch (tempo_dialog.run ()) {
case RESPONSE_ACCEPT:
@ -675,6 +702,9 @@ Editor::edit_tempo_section (TempoPoint& section)
return;
}
Temporal::TempoMetric tm (TempoMap::use()->metric_at (section.sclock()));
Temporal::TempoPoint const * tpp (TempoMap::use()->previous_tempo (tm.tempo()));
double bpm = tempo_dialog.get_bpm ();
double end_bpm = tempo_dialog.get_end_bpm ();
int nt = tempo_dialog.get_note_type ();
@ -682,12 +712,41 @@ Editor::edit_tempo_section (TempoPoint& section)
const Tempo tempo (bpm, end_bpm, nt);
Temporal::BBT_Time w;
tempo_dialog.get_bbt_time (w);
Temporal::BBT_Argument when (tm.reftime(), w);
Temporal::Beats new_pos;
if (!tpp) {
/* first tempo, cannot move */
new_pos = section.beats ();
} else {
/* Compute the given BBT time using a tempo metric composed
from the meter in effect at the current position, and the
previous tempo.
Step 1: get BBT time from dialog
*/
Temporal::BBT_Time w;
tempo_dialog.get_bbt_time (w);
/* Step 2: construct the relevant tempo metric */
TempoMetric prev_tm (*tpp, tm.meter());
/* Step 3: construct new BBT_Argument */
Temporal::BBT_Argument when (tm.reftime(), w);
/* Step 4: convert to quarters */
new_pos = prev_tm.quarters_at (when);
}
TempoMapChange tmc (*this, _("edit tempo"));
tmc.map().replace_tempo (section, tempo, timepos_t (tmc.map().quarters_at (when)));
// std::cerr << "using tempometric " << tm << std::endl;
// std::cerr << "edit tempo at " << when << " via quarters at = " << tmc.map().quarters_at (when) << std::endl;
tmc.map().replace_tempo (section, tempo, timepos_t (new_pos));
}
void