Merge with trunk R2978.
[ardour.git] / libs / ardour / tempo.cc
index e9d46f83e3736177cb84a9d6cb9f1f24f5f3820c..b2865fc399128f11356e47cb87460fe3cc851611 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>
@@ -44,12 +43,17 @@ Tempo    TempoMap::_default_tempo (120.0);
 
 const double Meter::ticks_per_beat = 1920.0;
 
+double Tempo::frames_per_beat (nframes_t sr, const Meter& meter) const
+{
+       return  ((60.0 * sr) / (_beats_per_minute * meter.note_divisor()/_note_type));
+}
+
 /***********************************************************************/
 
 double
 Meter::frames_per_bar (const Tempo& tempo, nframes_t sr) const
 {
-       return ((60.0 * sr * _beats_per_bar) / tempo.beats_per_minute());
+       return ((60.0 * sr * _beats_per_bar) / (tempo.beats_per_minute() * _note_type/tempo.note_type()));
 }
 
 /***********************************************************************/
@@ -87,6 +91,16 @@ TempoSection::TempoSection (const XMLNode& node)
                error << _("TempoSection XML node has an illegal \"beats_per_minute\" value") << endmsg;
                throw failed_constructor();
        }
+       
+       if ((prop = node.property ("note-type")) == 0) {
+               /* older session, make note type be quarter by default */
+               _note_type = 4.0;
+       } else {
+               if (sscanf (prop->value().c_str(), "%lf", &_note_type) != 1 || _note_type < 1.0) {
+                       error << _("TempoSection XML node has an illegal \"note-type\" value") << endmsg;
+                       throw failed_constructor();
+               }
+       }
 
        if ((prop = node.property ("movable")) == 0) {
                error << _("TempoSection XML node has no \"movable\" property") << endmsg;
@@ -110,6 +124,8 @@ TempoSection::get_state() const
        root->add_property ("start", buf);
        snprintf (buf, sizeof (buf), "%f", _beats_per_minute);
        root->add_property ("beats-per-minute", buf);
+       snprintf (buf, sizeof (buf), "%f", _note_type);
+       root->add_property ("note-type", buf);
        snprintf (buf, sizeof (buf), "%s", movable()?"yes":"no");
        root->add_property ("movable", buf);
 
@@ -206,15 +222,12 @@ TempoMap::TempoMap (nframes_t fr)
        _frame_rate = fr;
        last_bbt_valid = false;
        BBT_Time start;
-#ifdef STATE_MANAGER
-       in_set_state = false;
-#endif
        
        start.bars = 1;
        start.beats = 1;
        start.ticks = 0;
 
-       TempoSection *t = new TempoSection (start, _default_tempo.beats_per_minute());
+       TempoSection *t = new TempoSection (start, _default_tempo.beats_per_minute(), _default_tempo.note_type());
        MeterSection *m = new MeterSection (start, _default_meter.beats_per_bar(), _default_meter.note_divisor());
 
        t->set_movable (false);
@@ -224,10 +237,6 @@ TempoMap::TempoMap (nframes_t fr)
        
        metrics->push_back (t);
        metrics->push_back (m);
-       
-#ifdef STATE_MANAGER
-       save_state (_("initial"));
-#endif
 }
 
 TempoMap::~TempoMap ()
@@ -259,10 +268,7 @@ TempoMap::move_metric_section (MetricSection& section, const BBT_Time& when)
 
        section.set_start (corrected);
        metrics->sort (cmp);
-       timestamp_metrics ();
-#ifdef STATE_MANAGER
-       save_state (_("move metric"));
-#endif
+       timestamp_metrics (true);
 
        return 0;
 }
@@ -331,12 +337,6 @@ TempoMap::remove_meter (const MeterSection& tempo)
                                }
                        }
                }
-
-               if (removed) {
-#ifdef STATE_MANAGER
-                       save_state (_("metric removed"));
-#endif
-               }
        }
 
        if (removed) {
@@ -345,16 +345,22 @@ TempoMap::remove_meter (const MeterSection& tempo)
 }
 
 void
-TempoMap::do_insert (MetricSection* section)
+TempoMap::do_insert (MetricSection* section, bool with_bbt)
 {
        Metrics::iterator i;
 
        for (i = metrics->begin(); i != metrics->end(); ++i) {
                
-               if ((*i)->start() < section->start()) {
-                       continue;
+               if (with_bbt) {
+                       if ((*i)->start() < section->start()) {
+                               continue;
+                       }
+               } else {
+                       if ((*i)->frame() < section->frame()) {
+                               continue;
+                       }                       
                }
-               
+
                metrics->insert (i, section);
                break;
        }
@@ -363,7 +369,7 @@ TempoMap::do_insert (MetricSection* section)
                metrics->insert (metrics->end(), section);
        }
        
-       timestamp_metrics ();
+       timestamp_metrics (with_bbt);
 }      
 
 void
@@ -376,11 +382,18 @@ TempoMap::add_tempo (const Tempo& tempo, BBT_Time where)
        
                where.ticks = 0;
                
-               do_insert (new TempoSection (where, tempo.beats_per_minute()));
+               do_insert (new TempoSection (where, tempo.beats_per_minute(), tempo.note_type()), true);
+       }
 
-#ifdef STATE_MANAGER
-               save_state (_("add tempo"));
-#endif
+       StateChanged (Change (0));
+}
+
+void
+TempoMap::add_tempo (const Tempo& tempo, nframes_t where)
+{
+       {
+               Glib::RWLock::WriterLock lm (lock);
+               do_insert (new TempoSection (where, tempo.beats_per_minute(), tempo.note_type()), false);
        }
 
        StateChanged (Change (0));
@@ -403,16 +416,10 @@ TempoMap::replace_tempo (TempoSection& existing, const Tempo& replacement)
                                *((Tempo *) ts) = replacement;
 
                                replaced = true;
-                               timestamp_metrics ();
+                               timestamp_metrics (true);
                                break;
                        }
                }
-
-               if (replaced) {
-#ifdef STATE_MANAGER
-                       save_state (_("replace tempo"));
-#endif
-               }
        }
        
        if (replaced) {
@@ -442,11 +449,18 @@ TempoMap::add_meter (const Meter& meter, BBT_Time where)
                
                where.ticks = 0;
 
-               do_insert (new MeterSection (where, meter.beats_per_bar(), meter.note_divisor()));
+               do_insert (new MeterSection (where, meter.beats_per_bar(), meter.note_divisor()), true);
+       }
 
-#ifdef STATE_MANAGER
-               save_state (_("add meter"));
-#endif
+       StateChanged (Change (0));
+}
+
+void
+TempoMap::add_meter (const Meter& meter, nframes_t where)
+{
+       {
+               Glib::RWLock::WriterLock lm (lock);
+               do_insert (new MeterSection (where, meter.beats_per_bar(), meter.note_divisor()), false);
        }
 
        StateChanged (Change (0));
@@ -468,16 +482,10 @@ TempoMap::replace_meter (MeterSection& existing, const Meter& replacement)
                                *((Meter*) ms) = replacement;
 
                                replaced = true;
-                               timestamp_metrics ();
+                               timestamp_metrics (true);
                                break;
                        }
                }
-
-               if (replaced) {
-#ifdef STATE_MANAGER
-                       save_state (_("replaced meter"));
-#endif
-               }
        }
        
        if (replaced) {
@@ -485,6 +493,49 @@ TempoMap::replace_meter (MeterSection& existing, const Meter& replacement)
        }
 }
 
+void
+TempoMap::change_existing_tempo_at (nframes_t where, double beats_per_minute, double note_type)
+{
+       Tempo newtempo (beats_per_minute, note_type);
+
+       TempoSection* prev;
+       TempoSection* first;
+       Metrics::iterator i;
+
+       /* find the TempoSection immediately preceding "where"
+        */
+
+       for (first = 0, i = metrics->begin(), prev = 0; i != metrics->end(); ++i) {
+
+               if ((*i)->frame() > where) {
+                       break;
+               }
+
+               TempoSection* t;
+
+               if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
+                       if (!first) {
+                               first = t;
+                       }
+                       prev = t;
+               }
+       }
+
+       if (!prev) {
+               if (!first) {
+                       error << string_compose (_("no tempo sections defined in tempo map - cannot change tempo @ %1"), where) << endmsg;
+                       return;
+               }
+
+               prev = first;
+       }
+
+       /* reset */
+
+       *((Tempo*)prev) = newtempo;
+       StateChanged (Change (0));
+}
+
 const MeterSection&
 TempoMap::first_meter () const
 {
@@ -518,43 +569,84 @@ TempoMap::first_tempo () const
 }
 
 void
-TempoMap::timestamp_metrics ()
+TempoMap::timestamp_metrics (bool use_bbt)
 {
        Metrics::iterator i;
        const Meter* meter;
        const Tempo* tempo;
        Meter *m;
        Tempo *t;
-       nframes_t current;
-       nframes_t section_frames;
-       BBT_Time start;
-       BBT_Time end;
 
        meter = &first_meter ();
        tempo = &first_tempo ();
-       current = 0;
 
-       for (i = metrics->begin(); i != metrics->end(); ++i) {
-               
-               end = (*i)->start();
+       if (use_bbt) {
+
+               nframes_t current = 0;
+               nframes_t section_frames;
+               BBT_Time start;
+               BBT_Time end;
+
+               for (i = metrics->begin(); i != metrics->end(); ++i) {
+                       
+                       end = (*i)->start();
+                       
+                       section_frames = count_frames_between_metrics (*meter, *tempo, start, end);
+                       
+                       current += section_frames;
+                       
+                       start = end;
+                       
+                       (*i)->set_frame (current);
+                       
+                       if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
+                               tempo = t;
+                       } else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
+                               meter = m;
+                       } else {
+                               fatal << _("programming error: unhandled MetricSection type") << endmsg;
+                               /*NOTREACHED*/
+                       }
+               }
 
-               section_frames = count_frames_between_metrics (*meter, *tempo, start, end);
+       } else {
 
-               current += section_frames;
+               bool first = true;
 
-               start = end;
+               for (i = metrics->begin(); i != metrics->end(); ++i) {
 
-               (*i)->set_frame (current);
+                       BBT_Time bbt;
 
-               if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
-                       tempo = t;
-               } else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
-                       meter = m;
-               } else {
-                       fatal << _("programming error: unhandled MetricSection type") << endmsg;
-                       /*NOTREACHED*/
+                       bbt_time_with_metric ((*i)->frame(), bbt, Metric (*meter, *tempo));
+
+                       // cerr << "timestamp @ " << (*i)->frame() << " with " << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << " => ";
+
+                       if (first) {
+                               first = false;
+                       } else {
+                               if (bbt.beats != 1 || bbt.ticks != 0) {
+                                       bbt.bars += 1;
+                                       bbt.beats = 1;
+                                       bbt.ticks = 0;
+                               }
+                       }
+
+                       // cerr << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << endl;
+
+                       (*i)->set_start (bbt);
+
+                       if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
+                               tempo = t;
+                       } else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
+                               meter = m;
+                       } else {
+                               fatal << _("programming error: unhandled MetricSection type") << endmsg;
+                               /*NOTREACHED*/
+                       }
                }
        }
+
+       // dump (cerr);
 }
 
 TempoMap::Metric
@@ -651,7 +743,7 @@ TempoMap::bbt_time_with_metric (nframes_t frame, BBT_Time& bbt, const Metric& me
 
        const double beats_per_bar = metric.meter().beats_per_bar();
        const double frames_per_bar = metric.meter().frames_per_bar (metric.tempo(), _frame_rate);
-       const double beat_frames = metric.tempo().frames_per_beat (_frame_rate);
+       const double beat_frames = metric.tempo().frames_per_beat (_frame_rate, metric.meter());
 
        /* now compute how far beyond that point we actually are. */
 
@@ -686,17 +778,15 @@ TempoMap::bbt_time_with_metric (nframes_t frame, BBT_Time& bbt, const Metric& me
 nframes_t 
 TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) const
 {
-
-        /* for this to work with fractional measure types, start and end have to "legal" BBT types, 
-        that means that  the  beats and ticks should be  inside a bar
+        /* for this to work with fractional measure types, start and end have to be "legal" BBT types, 
+        that means that the beats and ticks should be inside a bar
        */
 
-
        nframes_t frames = 0;
        nframes_t start_frame = 0;
        nframes_t end_frame = 0;
 
-       Metric m = metric_at(start);
+       Metric m = metric_at (start);
 
        uint32_t bar_offset = start.bars - m.start().bars;
 
@@ -704,7 +794,7 @@ TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) con
                + start.ticks/Meter::ticks_per_beat;
 
 
-       start_frame = m.frame() + (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.meter()));
 
        m =  metric_at(end);
 
@@ -713,7 +803,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() + (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, m.meter()));
 
        frames = end_frame - start_frame;
 
@@ -734,7 +824,7 @@ TempoMap::count_frames_between_metrics (const Meter& meter, const Tempo& tempo,
        double beat_frames = 0;
 
        beats_per_bar = meter.beats_per_bar();
-       beat_frames = tempo.frames_per_beat (_frame_rate);
+       beat_frames = tempo.frames_per_beat (_frame_rate,meter);
 
        frames = 0;
 
@@ -959,63 +1049,6 @@ TempoMap::round_to_beat_subdivision (nframes_t fr, int sub_num)
        }
 
        return frame_time (the_beat);
-
-       /* XXX just keeping this for reference
-
-        TempoMap::BBTPointList::iterator i;
-        TempoMap::BBTPointList *more_zoomed_bbt_points;
-        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 = (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) ? 
-                                           fr - frame_one_beats_worth : 0, fr+frame_one_beats_worth );
-       }
-       if (more_zoomed_bbt_points == 0 || more_zoomed_bbt_points->empty()) {
-               return fr;
-       }
-
-       for (i = more_zoomed_bbt_points->begin(); i != more_zoomed_bbt_points->end(); i++) {
-               if  ((*i).frame <= fr) {
-                       pos = (*i).frame;
-                       tempo = (*i).tempo->beats_per_minute();
-                       
-               } else {
-                       i++;
-                       next_pos = (*i).frame;
-                       break;
-               }
-       }
-       frames_one_subdivisions_worth = ((double) _frame_rate *  60 / (sub_num * tempo));
-
-       for (n = sub_num; n > 0; n--) {
-               if (fr >= (pos + ((n - 0.5) * 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
-                       }
-                       fr_has_changed = true;
-                       break;
-               }
-       }
-
-       if (!fr_has_changed) {
-               fr = pos;
-       }
-
-        delete more_zoomed_bbt_points;
-        return fr ;
-
-       */
-
 }
 
 nframes_t
@@ -1067,6 +1100,12 @@ TempoMap::round_to_type (nframes_t frame, int dir, BBTPointType type)
        
        }
 
+       /* 
+          cerr << "for " << frame << " round to " << bbt << " using "
+          << metric.start()
+          << endl;
+       */
+
        return metric.frame() + count_frames_between (metric.start(), bbt);
 }
 
@@ -1121,7 +1160,7 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
 
        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);
+       beat_frames = tempo->frames_per_beat (_frame_rate, *meter);
        
        if (meter->frame() > tempo->frame()) {
                bar = meter->start().bars;
@@ -1164,6 +1203,7 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
 
                        if (beat == 1) {
                                if (current >= lower) {
+                                       // cerr << "Add Bar at " << bar << "|1" << " @ " << current << endl;
                                        points->push_back (BBTPoint (*meter, *tempo,(nframes_t)rint(current), Bar, bar, 1));
 
                                }
@@ -1175,6 +1215,7 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
 
                        while (beat <= ceil( beats_per_bar) && beat_frame < limit) {
                                if (beat_frame >= lower) {
+                                       // cerr << "Add Beat at " << bar << '|' << beat << " @ " << beat_frame << endl;
                                        points->push_back (BBTPoint (*meter, *tempo, (nframes_t) rint(beat_frame), Beat, bar, beat));
                                }
                                beat_frame += beat_frames;
@@ -1183,7 +1224,7 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
                                beat++;
                        }
 
-                       if (beat > ceil(beats_per_bar) ) {
+                       if (beat > ceil(beats_per_bar) || i != metrics->end()) {
 
                                /* we walked an entire bar. its
                                   important to move `current' forward
@@ -1201,10 +1242,15 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
                                   so we subtract the possible extra fraction from the current
                                */
 
-                               current -=  beat_frames * (ceil(beats_per_bar)-beats_per_bar);
+                               if (beat > ceil (beats_per_bar)) {
+                                       /* next bar goes where the numbers suggest */
+                                       current -=  beat_frames * (ceil(beats_per_bar)-beats_per_bar);
+                               } else {
+                                       /* next bar goes where the next metric is */
+                                       current = limit;
+                               }
                                bar++;
                                beat = 1;
-
                        } 
                
                }
@@ -1231,7 +1277,7 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
 
                        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);
+                       beat_frames = tempo->frames_per_beat (_frame_rate, *meter);
                        
                        ++i;
                }
@@ -1241,6 +1287,33 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
        return points;
 }      
 
+const TempoSection&
+TempoMap::tempo_section_at (nframes_t frame)
+{
+       Glib::RWLock::ReaderLock lm (lock);
+       Metrics::iterator i;
+       TempoSection* prev = 0;
+       
+       for (i = metrics->begin(); i != metrics->end(); ++i) {
+               TempoSection* t;
+
+               if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+
+                       if ((*i)->frame() > frame) {
+                               break;
+                       }
+
+                       prev = t;
+               }
+       }
+
+       if (prev == 0) {
+               fatal << endmsg;
+       }
+
+       return *prev;
+}
+
 const Tempo&
 TempoMap::tempo_at (nframes_t frame)
 {
@@ -1282,10 +1355,6 @@ TempoMap::set_state (const XMLNode& node)
                XMLNodeConstIterator niter;
                Metrics old_metrics (*metrics);
                
-#ifdef STATE_MANAGER
-               in_set_state = true;
-#endif
-               
                metrics->clear();
 
                nlist = node.children();
@@ -1323,26 +1392,10 @@ TempoMap::set_state (const XMLNode& node)
                        
                        MetricSectionSorter cmp;
                        metrics->sort (cmp);
-                       timestamp_metrics ();
+                       timestamp_metrics (true);
                }
-
-#ifdef STATE_MANAGER
-               in_set_state = false;
-#endif
        }
        
-       /* 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.
-       */
-
-#ifdef STATE_MANAGER
-       save_state(_("load XML data"));
-#endif
-       
        StateChanged (Change (0));
 
        return 0;
@@ -1357,7 +1410,7 @@ TempoMap::dump (std::ostream& o) const
        for (Metrics::const_iterator i = metrics->begin(); i != metrics->end(); ++i) {
 
                if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
-                       o << "Tempo @ " << *i << ' ' << t->beats_per_minute() << " BPM at " << t->start() << " frame= " << t->frame() << " (move? "
+                       o << "Tempo @ " << *i << ' ' << t->beats_per_minute() << " BPM (denom = " << t->note_type() << ") at " << t->start() << " frame= " << t->frame() << " (move? "
                          << t->movable() << ')' << endl;
                } else if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
                        o << "Meter @ " << *i << ' ' << m->beats_per_bar() << '/' << m->note_divisor() << " at " << m->start() << " frame= " << m->frame() 
@@ -1366,67 +1419,3 @@ TempoMap::dump (std::ostream& o) const
        }
 }
 
-#ifdef STATE_MANAGER
-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);
-       }
-}
-#endif