summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornick_m <mainsbridge@gmail.com>2016-10-16 02:33:49 +1100
committernick_m <mainsbridge@gmail.com>2016-10-16 02:33:49 +1100
commit3a0a628a75fdbc9da1c0ad2a21f46286a5184503 (patch)
treeaa5baf48f846314a54820473d1a7b375655e901d
parent9698f16aee5f91d158551d333fe0fb1b23d22859 (diff)
Rework duration clock and TempoMap::insert_time to include meter at offset.
- should fix 7072 - also fixes scroll behavior over multiple tempi.
-rw-r--r--gtk2_ardour/audio_clock.cc63
-rw-r--r--gtk2_ardour/audio_clock.h2
-rw-r--r--libs/ardour/tempo.cc172
3 files changed, 111 insertions, 126 deletions
diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc
index ed81b6db21..7e490b4fdc 100644
--- a/gtk2_ardour/audio_clock.cc
+++ b/gtk2_ardour/audio_clock.cc
@@ -1003,7 +1003,7 @@ AudioClock::set (framepos_t when, bool force, framecnt_t offset)
break;
case BBT:
- set_bbt (when, force);
+ set_bbt (when, offset, force);
break;
case MinSec:
@@ -1226,7 +1226,7 @@ AudioClock::set_timecode (framepos_t when, bool /*force*/)
}
void
-AudioClock::set_bbt (framepos_t when, bool /*force*/)
+AudioClock::set_bbt (framepos_t when, framecnt_t offset, bool /*force*/)
{
char buf[16];
Timecode::BBT_Time BBT;
@@ -1253,9 +1253,58 @@ AudioClock::set_bbt (framepos_t when, bool /*force*/)
BBT.beats = 0;
BBT.ticks = 0;
} else {
- BBT = _session->tempo_map().bbt_at_frame (when);
- BBT.bars--;
- BBT.beats--;
+ TempoMap& tmap (_session->tempo_map());
+ const double divisions = tmap.meter_section_at_frame (offset).divisions_per_bar();
+
+ if (negative) {
+ BBT = tmap.bbt_at_beat (tmap.beat_at_frame (offset));
+ Timecode::BBT_Time when_bbt = tmap.bbt_at_frame (offset - when);
+
+ BBT.bars -= when_bbt.bars;
+
+ if (BBT.ticks < when_bbt.ticks) {
+ if (BBT.beats == 1) {
+ BBT.bars--;
+ BBT.beats = divisions;
+ } else {
+ BBT.beats--;
+ }
+ BBT.ticks = Timecode::BBT_Time::ticks_per_beat - (when_bbt.ticks - BBT.ticks);
+ } else {
+ BBT.ticks -= when_bbt.ticks;
+ }
+
+ if (BBT.beats < when_bbt.beats) {
+ BBT.bars--;
+ BBT.beats = divisions - (when_bbt.beats - BBT.beats);
+ } else {
+ BBT.beats -= when_bbt.beats;
+ }
+ } else {
+ BBT = tmap.bbt_at_beat (tmap.beat_at_frame (when + offset));
+ Timecode::BBT_Time when_bbt = tmap.bbt_at_frame (offset);
+
+ BBT.bars -= when_bbt.bars;
+
+ if (BBT.ticks < when_bbt.ticks) {
+ if (BBT.beats == 1) {
+ BBT.bars--;
+ BBT.beats = divisions;
+ } else {
+ BBT.beats--;
+ }
+ BBT.ticks = Timecode::BBT_Time::ticks_per_beat - (when_bbt.ticks - BBT.ticks);
+ } else {
+ BBT.ticks -= when_bbt.ticks;
+ }
+
+ if (BBT.beats < when_bbt.beats) {
+ BBT.bars--;
+ BBT.beats = divisions - (when_bbt.beats - BBT.beats);
+ } else {
+ BBT.beats -= when_bbt.beats;
+ }
+ }
}
} else {
BBT = _session->tempo_map().bbt_at_frame (when);
@@ -1732,7 +1781,7 @@ AudioClock::on_scroll_event (GdkEventScroll *ev)
switch (ev->direction) {
case GDK_SCROLL_UP:
- frames = get_frame_step (f);
+ frames = get_frame_step (f, current_time(), 1);
if (frames != 0) {
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
frames *= 10;
@@ -1743,7 +1792,7 @@ AudioClock::on_scroll_event (GdkEventScroll *ev)
break;
case GDK_SCROLL_DOWN:
- frames = get_frame_step (f);
+ frames = get_frame_step (f, current_time(), -1);
if (frames != 0) {
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
frames *= 10;
diff --git a/gtk2_ardour/audio_clock.h b/gtk2_ardour/audio_clock.h
index 51cac850a0..79d05f62fe 100644
--- a/gtk2_ardour/audio_clock.h
+++ b/gtk2_ardour/audio_clock.h
@@ -209,7 +209,7 @@ class AudioClock : public CairoWidget, public ARDOUR::SessionHandlePtr
void set_slave_info ();
void set_timecode (framepos_t, bool);
- void set_bbt (framepos_t, bool);
+ void set_bbt (framepos_t, ARDOUR::framecnt_t, bool);
void set_minsec (framepos_t, bool);
void set_frames (framepos_t, bool);
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 27ba9f6223..1d6f4eccf2 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -3192,11 +3192,52 @@ TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir)
{
Glib::Threads::RWLock::ReaderLock lm (lock);
- const double tick_at_time = max (0.0, beat_at_frame_locked (_metrics, pos)) * BBT_Time::ticks_per_beat;
- const double bbt_ticks = bbt.ticks + (bbt.beats * BBT_Time::ticks_per_beat);
- const double total_beats = (tick_at_time + bbt_ticks) / BBT_Time::ticks_per_beat;
+ BBT_Time pos_bbt = bbt_at_frame_locked (_metrics, pos);
+ const framecnt_t offset = frame_at_bbt_locked (_metrics, pos_bbt);
+ const double divisions = meter_section_at_frame_locked (_metrics, pos).divisions_per_bar();
- return frame_at_beat_locked (_metrics, total_beats);
+ if (dir > 0) {
+ pos_bbt.bars += bbt.bars;
+
+ pos_bbt.ticks += bbt.ticks;
+ if ((double) pos_bbt.ticks > BBT_Time::ticks_per_beat) {
+ pos_bbt.beats += 1;
+ pos_bbt.ticks -= BBT_Time::ticks_per_beat;
+ }
+
+ pos_bbt.beats += bbt.beats;
+ if ((double) pos_bbt.beats > divisions) {
+ pos_bbt.bars += 1;
+ pos_bbt.beats -= divisions;
+ }
+
+ return frame_at_bbt_locked (_metrics, pos_bbt) - offset;
+ } else {
+ pos_bbt.bars -= bbt.bars;
+
+ if (pos_bbt.ticks < bbt.ticks) {
+ if (pos_bbt.beats == 1) {
+ pos_bbt.bars--;
+ pos_bbt.beats = divisions;
+ } else {
+ pos_bbt.beats--;
+ }
+ pos_bbt.ticks = BBT_Time::ticks_per_beat - (bbt.ticks - pos_bbt.ticks);
+ } else {
+ pos_bbt.ticks -= bbt.ticks;
+ }
+
+ if (pos_bbt.beats <= bbt.beats) {
+ pos_bbt.bars--;
+ pos_bbt.beats = divisions - (bbt.beats - pos_bbt.beats);
+ } else {
+ pos_bbt.beats -= bbt.beats;
+ }
+
+ return offset - frame_at_bbt_locked (_metrics, pos_bbt);
+ }
+
+ return 0;
}
framepos_t
@@ -3890,129 +3931,24 @@ TempoMap::n_meters() const
void
TempoMap::insert_time (framepos_t where, framecnt_t amount)
{
- {
- Glib::Threads::RWLock::WriterLock lm (lock);
- for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
- if ((*i)->frame() >= where && (*i)->movable ()) {
- (*i)->set_frame ((*i)->frame() + amount);
- }
- }
-
- /* now reset the BBT time of all metrics, based on their new
- * audio time. This is the only place where we do this reverse
- * timestamp.
- */
-
- Metrics::iterator i;
- const MeterSection* meter;
- const TempoSection* tempo;
- MeterSection *m;
- TempoSection *t;
-
- meter = &first_meter ();
- tempo = &first_tempo ();
-
- BBT_Time start;
- BBT_Time end;
-
- // cerr << "\n###################### TIMESTAMP via AUDIO ##############\n" << endl;
-
- bool first = true;
- MetricSection* prev = 0;
+ for (Metrics::reverse_iterator i = _metrics.rbegin(); i != _metrics.rend(); ++i) {
+ if ((*i)->frame() >= where && (*i)->movable ()) {
+ MeterSection* ms;
+ TempoSection* ts;
- for (i = _metrics.begin(); i != _metrics.end(); ++i) {
-
- BBT_Time bbt;
- //TempoMetric metric (*meter, *tempo);
- MeterSection* ms = const_cast<MeterSection*>(meter);
- TempoSection* ts = const_cast<TempoSection*>(tempo);
- if (prev) {
- if (ts){
- if ((t = dynamic_cast<TempoSection*>(prev)) != 0) {
- if (!t->active()) {
- continue;
- }
- ts->set_pulse (t->pulse());
- }
- if ((m = dynamic_cast<MeterSection*>(prev)) != 0) {
- ts->set_pulse (m->pulse());
- }
- ts->set_frame (prev->frame());
-
- }
- if (ms) {
- if ((m = dynamic_cast<MeterSection*>(prev)) != 0) {
- pair<double, BBT_Time> start = make_pair (m->beat(), m->bbt());
- ms->set_beat (start);
- ms->set_pulse (m->pulse());
- }
- if ((t = dynamic_cast<TempoSection*>(prev)) != 0) {
- if (!t->active()) {
- continue;
- }
- const double beat = beat_at_pulse_locked (_metrics, t->pulse());
- pair<double, BBT_Time> start = make_pair (beat, bbt_at_beat_locked (_metrics, beat));
- ms->set_beat (start);
- ms->set_pulse (t->pulse());
- }
- ms->set_frame (prev->frame());
- }
-
- } else {
- // metric will be at frames=0 bbt=1|1|0 by default
- // which is correct for our purpose
+ if ((ms = dynamic_cast <MeterSection*>(*i)) != 0) {
+ gui_move_meter (ms, (*i)->frame() + amount);
}
- // cerr << bbt << endl;
-
- if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
- if (!t->active()) {
- continue;
- }
- t->set_pulse (pulse_at_frame_locked (_metrics, m->frame()));
- tempo = t;
- // cerr << "NEW TEMPO, frame = " << (*i)->frame() << " beat = " << (*i)->pulse() <<endl;
- } else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
- bbt = bbt_at_frame_locked (_metrics, m->frame());
-
- // cerr << "timestamp @ " << (*i)->frame() << " with " << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << " => ";
-
- if (first) {
- first = false;
- } else {
-
- if (bbt.ticks > BBT_Time::ticks_per_beat/2) {
- /* round up to next beat */
- bbt.beats += 1;
- }
-
- bbt.ticks = 0;
-
- if (bbt.beats != 1) {
- /* round up to next bar */
- bbt.bars += 1;
- bbt.beats = 1;
- }
- }
- pair<double, BBT_Time> start = make_pair (max (0.0, beat_at_frame_locked (_metrics, m->frame())), bbt);
- m->set_beat (start);
- m->set_pulse (pulse_at_frame_locked (_metrics, m->frame()));
- meter = m;
- // cerr << "NEW METER, frame = " << (*i)->frame() << " beat = " << (*i)->pulse() <<endl;
- } else {
- fatal << _("programming error: unhandled MetricSection type") << endmsg;
- abort(); /*NOTREACHED*/
+ if ((ts = dynamic_cast <TempoSection*>(*i)) != 0) {
+ gui_move_tempo (ts, (*i)->frame() + amount, 0);
}
-
- prev = (*i);
}
-
- recompute_map (_metrics);
}
-
PropertyChanged (PropertyChange ());
}
+
bool
TempoMap::remove_time (framepos_t where, framecnt_t amount)
{