Use PBD::sys::operator/ instead of PBD::sys::path::operator/= in ARDOUR::SessionDirectory
[ardour.git] / libs / ardour / tempo.cc
index c2ff4f9a3a5cc97c9e0df2bd2d938bf6c299e6f9..cd59e93054145fb05160c52f1aad2fdecfd9ab46 100644 (file)
@@ -15,7 +15,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
 #include <algorithm>
@@ -47,7 +46,7 @@ const double Meter::ticks_per_beat = 1920.0;
 /***********************************************************************/
 
 double
-Meter::frames_per_bar (const Tempo& tempo, jack_nframes_t sr) const
+Meter::frames_per_bar (const Tempo& tempo, nframes_t sr) const
 {
        return ((60.0 * sr * _beats_per_bar) / tempo.beats_per_minute());
 }
@@ -200,13 +199,12 @@ struct MetricSectionSorter {
     }
 };
 
-TempoMap::TempoMap (jack_nframes_t fr)
+TempoMap::TempoMap (nframes_t fr)
 {
        metrics = new Metrics;
        _frame_rate = fr;
        last_bbt_valid = false;
        BBT_Time start;
-       in_set_state = false;
        
        start.bars = 1;
        start.beats = 1;
@@ -222,8 +220,6 @@ TempoMap::TempoMap (jack_nframes_t fr)
        
        metrics->push_back (t);
        metrics->push_back (m);
-       
-       save_state (_("initial"));
 }
 
 TempoMap::~TempoMap ()
@@ -256,7 +252,6 @@ TempoMap::move_metric_section (MetricSection& section, const BBT_Time& when)
        section.set_start (corrected);
        metrics->sort (cmp);
        timestamp_metrics ();
-       save_state (_("move metric"));
 
        return 0;
 }
@@ -265,7 +260,7 @@ void
 TempoMap::move_tempo (TempoSection& tempo, const BBT_Time& when)
 {
        if (move_metric_section (tempo, when) == 0) {
-               send_state_changed (Change (0));
+               StateChanged (Change (0));
        }
 }
 
@@ -273,7 +268,7 @@ void
 TempoMap::move_meter (MeterSection& meter, const BBT_Time& when)
 {
        if (move_metric_section (meter, when) == 0) {
-               send_state_changed (Change (0));
+               StateChanged (Change (0));
        }
 }
                
@@ -301,7 +296,7 @@ TempoMap::remove_tempo (const TempoSection& tempo)
        }
 
        if (removed) {
-               send_state_changed (Change (0));
+               StateChanged (Change (0));
        }
 }
 
@@ -325,14 +320,10 @@ TempoMap::remove_meter (const MeterSection& tempo)
                                }
                        }
                }
-
-               if (removed) {
-                       save_state (_("metric removed"));
-               }
        }
 
        if (removed) {
-               send_state_changed (Change (0));
+               StateChanged (Change (0));
        }
 }
 
@@ -369,11 +360,9 @@ TempoMap::add_tempo (const Tempo& tempo, BBT_Time where)
                where.ticks = 0;
                
                do_insert (new TempoSection (where, tempo.beats_per_minute()));
-
-               save_state (_("add tempo"));
        }
 
-       send_state_changed (Change (0));
+       StateChanged (Change (0));
 }
 
 void
@@ -397,14 +386,10 @@ TempoMap::replace_tempo (TempoSection& existing, const Tempo& replacement)
                                break;
                        }
                }
-
-               if (replaced) {
-                       save_state (_("replace tempo"));
-               }
        }
        
        if (replaced) {
-               send_state_changed (Change (0));
+               StateChanged (Change (0));
        }
 }
 
@@ -431,11 +416,9 @@ TempoMap::add_meter (const Meter& meter, BBT_Time where)
                where.ticks = 0;
 
                do_insert (new MeterSection (where, meter.beats_per_bar(), meter.note_divisor()));
-
-               save_state (_("add meter"));
        }
 
-       send_state_changed (Change (0));
+       StateChanged (Change (0));
 }
 
 void
@@ -458,14 +441,10 @@ TempoMap::replace_meter (MeterSection& existing, const Meter& replacement)
                                break;
                        }
                }
-
-               if (replaced) {
-                       save_state (_("replaced meter"));
-               }
        }
        
        if (replaced) {
-               send_state_changed (Change (0));
+               StateChanged (Change (0));
        }
 }
 
@@ -509,8 +488,8 @@ TempoMap::timestamp_metrics ()
        const Tempo* tempo;
        Meter *m;
        Tempo *t;
-       jack_nframes_t current;
-       jack_nframes_t section_frames;
+       nframes_t current;
+       nframes_t section_frames;
        BBT_Time start;
        BBT_Time end;
 
@@ -542,7 +521,7 @@ TempoMap::timestamp_metrics ()
 }
 
 TempoMap::Metric
-TempoMap::metric_at (jack_nframes_t frame) const
+TempoMap::metric_at (nframes_t frame) const
 {
        Metric m (first_meter(), first_tempo());
        const Meter* meter;
@@ -610,7 +589,7 @@ TempoMap::metric_at (BBT_Time bbt) const
 }
 
 void
-TempoMap::bbt_time (jack_nframes_t frame, BBT_Time& bbt) const
+TempoMap::bbt_time (nframes_t frame, BBT_Time& bbt) const
 {
         {
                Glib::RWLock::ReaderLock lm (lock);
@@ -619,15 +598,15 @@ TempoMap::bbt_time (jack_nframes_t frame, BBT_Time& bbt) const
 }
 
 void
-TempoMap::bbt_time_unlocked (jack_nframes_t frame, BBT_Time& bbt) const
+TempoMap::bbt_time_unlocked (nframes_t frame, BBT_Time& bbt) const
 {
        bbt_time_with_metric (frame, bbt, metric_at (frame));
 }
 
 void
-TempoMap::bbt_time_with_metric (jack_nframes_t frame, BBT_Time& bbt, const Metric& metric) const
+TempoMap::bbt_time_with_metric (nframes_t frame, BBT_Time& bbt, const Metric& metric) const
 {
-       jack_nframes_t frame_diff;
+       nframes_t frame_diff;
 
        uint32_t xtra_bars = 0;
        double xtra_beats = 0;
@@ -667,7 +646,7 @@ TempoMap::bbt_time_with_metric (jack_nframes_t frame, BBT_Time& bbt, const Metri
 }
 
 
-jack_nframes_t 
+nframes_t 
 TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) const
 {
 
@@ -676,9 +655,9 @@ TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) con
        */
 
 
-       jack_nframes_t frames = 0;
-       jack_nframes_t start_frame = 0;
-       jack_nframes_t end_frame = 0;
+       nframes_t frames = 0;
+       nframes_t start_frame = 0;
+       nframes_t end_frame = 0;
 
        Metric m = metric_at(start);
 
@@ -688,7 +667,7 @@ TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) con
                + start.ticks/Meter::ticks_per_beat;
 
 
-       start_frame = m.frame() + (jack_nframes_t) rint( beat_offset * m.tempo().frames_per_beat(_frame_rate));
+       start_frame = m.frame() + (nframes_t) rint( beat_offset * m.tempo().frames_per_beat(_frame_rate));
 
        m =  metric_at(end);
 
@@ -697,7 +676,7 @@ TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) con
        beat_offset = bar_offset * m.meter().beats_per_bar() - (m.start().beats -1) + (end.beats - 1) 
                + end.ticks/Meter::ticks_per_beat;
 
-       end_frame = m.frame() + (jack_nframes_t) rint(beat_offset * m.tempo().frames_per_beat(_frame_rate));
+       end_frame = m.frame() + (nframes_t) rint(beat_offset * m.tempo().frames_per_beat(_frame_rate));
 
        frames = end_frame - start_frame;
 
@@ -705,12 +684,12 @@ TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) con
        
 }      
 
-jack_nframes_t 
+nframes_t 
 TempoMap::count_frames_between_metrics (const Meter& meter, const Tempo& tempo, const BBT_Time& start, const BBT_Time& end) const
 {
         /*this is used in timestamping the metrics by actually counting the beats */ 
 
-       jack_nframes_t frames = 0;
+       nframes_t frames = 0;
        uint32_t bar = start.bars;
        double beat = (double) start.beats;
        double beats_counted = 0;
@@ -739,13 +718,13 @@ TempoMap::count_frames_between_metrics (const Meter& meter, const Tempo& tempo,
                }
        }
        
-       frames = (jack_nframes_t) floor (beats_counted * beat_frames);
+       frames = (nframes_t) floor (beats_counted * beat_frames);
 
        return frames;
        
 }      
 
-jack_nframes_t 
+nframes_t 
 TempoMap::frame_time (const BBT_Time& bbt) const
 {
        BBT_Time start ; /* 1|1|0 */
@@ -753,10 +732,10 @@ TempoMap::frame_time (const BBT_Time& bbt) const
        return  count_frames_between ( start, bbt);
 }
 
-jack_nframes_t 
-TempoMap::bbt_duration_at (jack_nframes_t pos, const BBT_Time& bbt, int dir) const
+nframes_t 
+TempoMap::bbt_duration_at (nframes_t pos, const BBT_Time& bbt, int dir) const
 {
-       jack_nframes_t frames = 0;
+       nframes_t frames = 0;
 
        BBT_Time when;
        bbt_time(pos,when);
@@ -769,11 +748,11 @@ TempoMap::bbt_duration_at (jack_nframes_t pos, const BBT_Time& bbt, int dir) con
        return frames;
 }
 
-jack_nframes_t 
+nframes_t 
 TempoMap::bbt_duration_at_unlocked (const BBT_Time& when, const BBT_Time& bbt, int dir) const
 {
 
-       jack_nframes_t frames = 0;
+       nframes_t frames = 0;
 
        double beats_per_bar;
        BBT_Time result;
@@ -896,8 +875,8 @@ TempoMap::bbt_duration_at_unlocked (const BBT_Time& when, const BBT_Time& bbt, i
 
 
 
-jack_nframes_t
-TempoMap::round_to_bar (jack_nframes_t fr, int dir)
+nframes_t
+TempoMap::round_to_bar (nframes_t fr, int dir)
 {
         {
                Glib::RWLock::ReaderLock lm (lock);
@@ -906,8 +885,8 @@ TempoMap::round_to_bar (jack_nframes_t fr, int dir)
 }
 
 
-jack_nframes_t
-TempoMap::round_to_beat (jack_nframes_t fr, int dir)
+nframes_t
+TempoMap::round_to_beat (nframes_t fr, int dir)
 {
         {
                Glib::RWLock::ReaderLock lm (lock);
@@ -915,9 +894,9 @@ TempoMap::round_to_beat (jack_nframes_t fr, int dir)
        }
 }
 
-jack_nframes_t
+nframes_t
 
-TempoMap::round_to_beat_subdivision (jack_nframes_t fr, int sub_num)
+TempoMap::round_to_beat_subdivision (nframes_t fr, int sub_num)
 {
 
        BBT_Time the_beat;
@@ -944,20 +923,23 @@ TempoMap::round_to_beat_subdivision (jack_nframes_t fr, int sub_num)
 
        return frame_time (the_beat);
 
-       /* XXX just keeping this for reference
+
+
+       /*****************************  
+       XXX just keeping this for reference
 
         TempoMap::BBTPointList::iterator i;
         TempoMap::BBTPointList *more_zoomed_bbt_points;
-        jack_nframes_t frame_one_beats_worth;
-        jack_nframes_t pos = 0;
-       jack_nframes_t next_pos = 0 ;
+        nframes_t frame_one_beats_worth;
+        nframes_t pos = 0;
+       nframes_t next_pos = 0 ;
         double tempo = 1;
         double frames_one_subdivisions_worth;
         bool fr_has_changed = false;
 
         int n;
 
-       frame_one_beats_worth = (jack_nframes_t) ::floor ((double)  _frame_rate *  60 / 20 ); //one beat @ 20 bpm
+       frame_one_beats_worth = (nframes_t) ::floor ((double)  _frame_rate *  60 / 20 ); //one beat @ 20 bpm
         {
          Glib::RWLock::ReaderLock lm (lock);
          more_zoomed_bbt_points = get_points((fr >= frame_one_beats_worth) ? 
@@ -982,7 +964,7 @@ TempoMap::round_to_beat_subdivision (jack_nframes_t fr, int sub_num)
 
        for (n = sub_num; n > 0; n--) {
                if (fr >= (pos + ((n - 0.5) * frames_one_subdivisions_worth))) {
-                       fr = (jack_nframes_t) round(pos + (n  * frames_one_subdivisions_worth));
+                       fr = (nframes_t) round(pos + (n  * frames_one_subdivisions_worth));
                        if (fr > next_pos) {
                                fr = next_pos;  //take care of fractional beats that don't match the subdivision asked
                        }
@@ -998,13 +980,14 @@ TempoMap::round_to_beat_subdivision (jack_nframes_t fr, int sub_num)
         delete more_zoomed_bbt_points;
         return fr ;
 
-       */
+       ******************************/
+
 
 }
 
-jack_nframes_t
+nframes_t
 
-TempoMap::round_to_type (jack_nframes_t frame, int dir, BBTPointType type)
+TempoMap::round_to_type (nframes_t frame, int dir, BBTPointType type)
 {
        Metric metric = metric_at (frame);
        BBT_Time bbt;
@@ -1055,7 +1038,7 @@ TempoMap::round_to_type (jack_nframes_t frame, int dir, BBTPointType type)
 }
 
 TempoMap::BBTPointList *
-TempoMap::get_points (jack_nframes_t lower, jack_nframes_t upper) const
+TempoMap::get_points (nframes_t lower, nframes_t upper) const
 {
 
        Metrics::const_iterator i;
@@ -1071,7 +1054,10 @@ TempoMap::get_points (jack_nframes_t lower, jack_nframes_t upper) const
        double beat_frame;
        double beat_frames;
        double frames_per_bar;
-       jack_nframes_t limit;
+       double delta_bars;
+       double delta_beats;
+       double dummy;
+       nframes_t limit;
 
        meter = &first_meter ();
        tempo = &first_tempo ();
@@ -1100,6 +1086,10 @@ TempoMap::get_points (jack_nframes_t lower, jack_nframes_t upper) const
           Now start generating points.
        */
 
+       beats_per_bar = meter->beats_per_bar ();
+       frames_per_bar = meter->frames_per_bar (*tempo, _frame_rate);
+       beat_frames = tempo->frames_per_beat (_frame_rate);
+       
        if (meter->frame() > tempo->frame()) {
                bar = meter->start().bars;
                beat = meter->start().beats;
@@ -1110,12 +1100,21 @@ TempoMap::get_points (jack_nframes_t lower, jack_nframes_t upper) const
                current = tempo->frame();
        }
 
+       /* initialize current to point to the bar/beat just prior to the
+          lower frame bound passed in.  assumes that current is initialized
+          above to be on a beat.
+       */
+       
+       delta_bars = (lower-current) / frames_per_bar;
+       delta_beats = modf(delta_bars, &dummy) * beats_per_bar;
+       current += (floor(delta_bars) * frames_per_bar) +  (floor(delta_beats) * beat_frames);
+
+       // adjust bars and beats too
+       bar += (uint32_t) (floor(delta_bars));
+       beat += (uint32_t) (floor(delta_beats));
+
        points = new BBTPointList;
                
-       beats_per_bar = meter->beats_per_bar ();
-       frames_per_bar = meter->frames_per_bar (*tempo, _frame_rate);
-       beat_frames = tempo->frames_per_beat (_frame_rate);
-
        do {
 
                if (i == metrics->end()) {
@@ -1132,7 +1131,7 @@ TempoMap::get_points (jack_nframes_t lower, jack_nframes_t upper) const
 
                        if (beat == 1) {
                                if (current >= lower) {
-                                       points->push_back (BBTPoint (*meter, *tempo,(jack_nframes_t)rint(current), Bar, bar, 1));
+                                       points->push_back (BBTPoint (*meter, *tempo,(nframes_t)rint(current), Bar, bar, 1));
 
                                }
                        }
@@ -1143,7 +1142,7 @@ TempoMap::get_points (jack_nframes_t lower, jack_nframes_t upper) const
 
                        while (beat <= ceil( beats_per_bar) && beat_frame < limit) {
                                if (beat_frame >= lower) {
-                                       points->push_back (BBTPoint (*meter, *tempo, (jack_nframes_t) rint(beat_frame), Beat, bar, beat));
+                                       points->push_back (BBTPoint (*meter, *tempo, (nframes_t) rint(beat_frame), Beat, bar, beat));
                                }
                                beat_frame += beat_frames;
                                current+= beat_frames;
@@ -1197,6 +1196,10 @@ TempoMap::get_points (jack_nframes_t lower, jack_nframes_t upper) const
                                beat = 1;
                        }
 
+                       beats_per_bar = meter->beats_per_bar ();
+                       frames_per_bar = meter->frames_per_bar (*tempo, _frame_rate);
+                       beat_frames = tempo->frames_per_beat (_frame_rate);
+                       
                        ++i;
                }
 
@@ -1206,7 +1209,7 @@ TempoMap::get_points (jack_nframes_t lower, jack_nframes_t upper) const
 }      
 
 const Tempo&
-TempoMap::tempo_at (jack_nframes_t frame)
+TempoMap::tempo_at (nframes_t frame)
 {
        Metric m (metric_at (frame));
        return m.tempo();
@@ -1214,7 +1217,7 @@ TempoMap::tempo_at (jack_nframes_t frame)
 
 
 const Meter&
-TempoMap::meter_at (jack_nframes_t frame)
+TempoMap::meter_at (nframes_t frame)
 {
        Metric m (metric_at (frame));
        return m.meter();
@@ -1246,8 +1249,6 @@ TempoMap::set_state (const XMLNode& node)
                XMLNodeConstIterator niter;
                Metrics old_metrics (*metrics);
                
-               in_set_state = true;
-               
                metrics->clear();
 
                nlist = node.children();
@@ -1287,20 +1288,9 @@ TempoMap::set_state (const XMLNode& node)
                        metrics->sort (cmp);
                        timestamp_metrics ();
                }
-
-               in_set_state = false;
        }
        
-       /* This state needs to be saved. This string will never be a part of the 
-          object's history though, because the allow_save flag is false during 
-          session load. This state will eventually be tagged "initial state", 
-          by a call to StateManager::allow_save from Session::set_state.
-
-          If this state is not saved, there is no way to reach it through undo actions.
-       */
-       save_state(_("load XML data"));
-       
-       send_state_changed (Change (0));
+       StateChanged (Change (0));
 
        return 0;
 }
@@ -1323,65 +1313,3 @@ TempoMap::dump (std::ostream& o) const
        }
 }
 
-UndoAction
-TempoMap::get_memento () const
-{
-       return sigc::bind (mem_fun (*(const_cast<TempoMap *> (this)), &StateManager::use_state), _current_state_id);
-}
-
-Change
-TempoMap::restore_state (StateManager::State& state)
-{
-       Glib::RWLock::ReaderLock lm (lock);
-
-       TempoMapState* tmstate = dynamic_cast<TempoMapState*> (&state);
-
-       /* We can't just set the metrics pointer to the address of the metrics list 
-          stored in the state, cause this would ruin this state for restoring in
-          the future. If they have the same address, they are the same list.
-          Thus we need to copy all the elements from the state metrics list to the 
-          current metrics list.
-       */
-       metrics->clear();
-       for (Metrics::iterator i = tmstate->metrics->begin(); i != tmstate->metrics->end(); ++i) {
-               TempoSection *ts;
-               MeterSection *ms;
-               
-               if ((ts = dynamic_cast<TempoSection*>(*i)) != 0) {
-                       metrics->push_back (new TempoSection (*ts));
-               } else if ((ms = dynamic_cast<MeterSection*>(*i)) != 0) {
-                       metrics->push_back (new MeterSection (*ms));
-               }
-       }
-       
-       last_bbt_valid = false;
-
-       return Change (0);
-}
-
-StateManager::State* 
-TempoMap::state_factory (std::string why) const
-{
-       TempoMapState* state = new TempoMapState (why);
-
-       for (Metrics::iterator i = metrics->begin(); i != metrics->end(); ++i) {
-               TempoSection *ts;
-               MeterSection *ms;
-               
-               if ((ts = dynamic_cast<TempoSection*>(*i)) != 0) {
-                       state->metrics->push_back (new TempoSection (*ts));
-               } else if ((ms = dynamic_cast<MeterSection*>(*i)) != 0) {
-                       state->metrics->push_back (new MeterSection (*ms));
-               }
-       }
-               
-       return state;
-}
-
-void
-TempoMap::save_state (std::string why)
-{
-       if (!in_set_state) {
-               StateManager::save_state (why);
-       }
-}