//=============================================================================
//  MuseScore
//  Music Composition & Notation
//
//  Copyright (C) 2002-2009 Werner Schweer
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License version 2
//  as published by the Free Software Foundation and appearing in
//  the file LICENCE.GPL
//=============================================================================
 
#include "pos.h"
#include "xml.h"
#include "sig.h"
#include "tempo.h"
 
namespace Ms {
 
//---------------------------------------------------------
//   Pos
//---------------------------------------------------------
 
Pos::Pos()
      {
      tempo  = 0;
      sig    = 0;
      _type  = TType::TICKS;
      _tick  = 0;
      _frame = 0;
      sn     = -1;
      _valid = false;
      }
 
Pos::Pos(TempoMap* tl, TimeSigMap* sl)
      {
      tempo  = tl;
      sig    = sl;
      _type   = TType::TICKS;
      _tick   = 0;
      _frame  = 0;
      sn      = -1;
      _valid  = false;
      }
 
Pos::Pos(TempoMap* tl, TimeSigMap* sl, unsigned t, TType timeType)
      {
      tempo  = tl;
      sig    = sl;
      _type = timeType;
      if (_type == TType::TICKS)
            _tick   = t;
      else
            _frame = t;
      sn = -1;
      _valid = true;
      }
 
Pos::Pos(TempoMap* tl, TimeSigMap* sl, const QString& s)
      {
      tempo  = tl;
      sig    = sl;
      int m, b, t;
      sscanf(s.toLatin1().data(), "%04d.%02d.%03d", &m, &b, &t);
      _tick = sig->bar2tick(m, b) + t;
      _type = TType::TICKS;
      sn    = -1;
      _valid = true;
      }
 
Pos::Pos(TempoMap* tl, TimeSigMap* sl, int measure, int beat, int tick)
      {
      tempo  = tl;
      sig    = sl;
      _tick  = sig->bar2tick(measure, beat) + tick;
      _type  = TType::TICKS;
      sn     = -1;
      _valid = true;
      }
 
Pos::Pos(TempoMap* tl, TimeSigMap* sl, int min, int sec, int frame, int subframe)
      {
      tempo  = tl;
      sig    = sl;
      double time = min * 60.0 + sec;
 
      double f = frame + subframe/100.0;
      switch (MScore::mtcType) {
            case 0:     // 24 frames sec
                  time += f * 1.0/24.0;
                  break;
            case 1:     // 25
                  time += f * 1.0/25.0;
                  break;
            case 2:     // 30 drop frame
                  time += f * 1.0/30.0;
                  break;
            case 3:     // 30 non drop frame
                  time += f * 1.0/30.0;
                  break;
            }
      _type  = TType::FRAMES;
      _frame = lrint(time * MScore::sampleRate);
      sn     = -1;
      _valid = true;
      }
 
//---------------------------------------------------------
//   setType
//---------------------------------------------------------
 
void Pos::setType(TType t)
      {
      if (t == _type)
            return;
 
      if (_type == TType::TICKS) {
            // convert from ticks to frames
            _frame = tempo->tick2time(_tick, _frame, &sn) * MScore::sampleRate;
            }
      else {
            // convert from frames to ticks
            _tick = tempo->time2tick(_frame / MScore::sampleRate, _tick, &sn);
            }
      _type = t;
      }
 
//---------------------------------------------------------
//   operator+=
//---------------------------------------------------------
 
Pos& Pos::operator+=(const Pos& a)
      {
      if (_type == TType::FRAMES)
            _frame += a.frame();
      else
            _tick += a.tick();
      sn = -1;          // invalidate cached values
      return *this;
      }
 
//---------------------------------------------------------
//   operator-=
//---------------------------------------------------------
 
Pos& Pos::operator-=(const Pos& a)
      {
      if (_type == TType::FRAMES)
            _frame -= a.frame();
      else
            _tick -= a.tick();
      sn = -1;          // invalidate cached values
      return *this;
      }
 
//---------------------------------------------------------
//   operator+=
//---------------------------------------------------------
 
Pos& Pos::operator+=(int a)
      {
      if (_type == TType::FRAMES)
            _frame += a;
      else
            _tick += a;
      sn = -1;          // invalidate cached values
      return *this;
      }
 
//---------------------------------------------------------
//   operator-=
//---------------------------------------------------------
 
Pos& Pos::operator-=(int a)
      {
      if (_type == TType::FRAMES)
            _frame -= a;
      else
            _tick -= a;
      sn = -1;          // invalidate cached values
      return *this;
      }
 
Pos operator+(const Pos& a, int b)
      {
      Pos c(a);
      return c += b;
      }
 
Pos operator-(const Pos& a, int b)
      {
      Pos c(a);
      return c -= b;
      }
 
Pos operator+(const Pos& a, const Pos& b)
      {
      Pos c(a);
      return c += b;
      }
 
Pos operator-(const Pos& a, const Pos& b)
      {
      Pos c(a);
      return c -= b;
      }
 
bool Pos::operator>=(const Pos& s) const
      {
      if (_type == TType::FRAMES)
            return _frame >= s.frame();
      else
            return _tick >= s.tick();
      }
 
bool Pos::operator>(const Pos& s) const
      {
      if (_type == TType::FRAMES)
            return _frame > s.frame();
      else
            return _tick > s.tick();
      }
 
bool Pos::operator<(const Pos& s) const
      {
      if (_type == TType::FRAMES)
            return _frame < s.frame();
      else
            return _tick < s.tick();
      }
 
bool Pos::operator<=(const Pos& s) const
      {
      if (_type == TType::FRAMES)
            return _frame <= s.frame();
      else
            return _tick <= s.tick();
      }
 
bool Pos::operator==(const Pos& s) const
      {
      if (_type == TType::FRAMES)
            return _frame == s.frame();
      else
            return _tick == s.tick();
      }
 
bool Pos::operator!=(const Pos& s) const
      {
      if (_type == TType::FRAMES)
            return _frame != s.frame();
      else
            return _tick != s.tick();
      }
 
//---------------------------------------------------------
//   tick
//---------------------------------------------------------
 
unsigned Pos::tick() const
      {
      if (_type == TType::FRAMES)
            _tick = tempo->time2tick(_frame / MScore::sampleRate, _tick, &sn);
      return _tick;
      }
 
//---------------------------------------------------------
//   frame
//---------------------------------------------------------
 
unsigned Pos::frame() const
      {
   if (_type == TType::TICKS) {
            // qreal time = _frame / MScore::sampleRate;
            // _frame = tempo->tick2time(_tick, time, &sn) * MScore::sampleRate;
            _frame = tempo->tick2time(_tick) * MScore::sampleRate;
            }
      return _frame;
      }
 
//---------------------------------------------------------
//   setTick
//---------------------------------------------------------
 
void Pos::setTick(unsigned pos)
      {
      _tick = pos;
      sn    = -1;
      if (_type == TType::FRAMES)
            _frame = tempo->tick2time(pos, &sn) * MScore::sampleRate;
      _valid = true;
      }
 
//---------------------------------------------------------
//   setFrame
//---------------------------------------------------------
 
void Pos::setFrame(unsigned pos)
      {
      _frame = pos;
      sn     = -1;
      if (_type == TType::TICKS)
            _tick = tempo->time2tick(pos/MScore::sampleRate, &sn);
      _valid = true;
      }
 
//---------------------------------------------------------
//   write
//---------------------------------------------------------
 
void Pos::write(XmlWriter& xml, const char* name) const
      {
      if (_type == TType::TICKS)
            xml.tagE(QString("%1 tick=\"%2\"").arg(name).arg(_tick));
      else
            xml.tagE(QString("%1 frame=\"%2\"").arg(name).arg(_frame));
      }
 
//---------------------------------------------------------
//   read
//---------------------------------------------------------
 
void Pos::read(XmlReader& e)
      {
      sn = -1;
      if (e.hasAttribute("tick")) {
            _tick = e.intAttribute("tick");
            _type = TType::TICKS;
            }
      if (e.hasAttribute("frame")) {
            _frame = e.intAttribute("frame");
            _type = TType::FRAMES;
            }
      }
 
//---------------------------------------------------------
//   PosLen
//---------------------------------------------------------
 
PosLen::PosLen(TempoMap* tl, TimeSigMap* sl)
   : Pos(tl, sl)
      {
      _lenTick  = 0;
      _lenFrame = 0;
      sn        = -1;
      }
 
PosLen::PosLen(const PosLen& p)
  : Pos(p)
      {
      _lenTick  = p._lenTick;
      _lenFrame = p._lenFrame;
      sn = -1;
      }
 
//---------------------------------------------------------
//   dump
//---------------------------------------------------------
 
void PosLen::dump(int n) const
      {
      Pos::dump(n);
      qDebug("  Len(");
      switch(type()) {
            case TType::FRAMES:
                  qDebug("samples=%d)", _lenFrame);
                  break;
            case TType::TICKS:
                  qDebug("ticks=%d)", _lenTick);
                  break;
            }
      }
 
void Pos::dump(int /*n*/) const
      {
      qDebug("Pos(%s, sn=%d, ", type() == TType::FRAMES ? "Frames" : "Ticks", sn);
      switch(type()) {
            case TType::FRAMES:
                  qDebug("samples=%d)", _frame);
                  break;
            case TType::TICKS:
                  qDebug("ticks=%d)", _tick);
                  break;
            }
      }
 
//---------------------------------------------------------
//   write
//---------------------------------------------------------
 
void PosLen::write(XmlWriter& xml, const char* name) const
      {
      if (type() == TType::TICKS)
            xml.tagE(QString("%1 tick=\"%2\" len=\"%3\"").arg(name).arg(tick()).arg(_lenTick));
      else
            xml.tagE(QString("%1 sample=\"%2\" len=\"%3\"").arg(name).arg(frame()).arg(_lenFrame));
      }
 
//---------------------------------------------------------
//   read
//---------------------------------------------------------
 
void PosLen::read(XmlReader& e)
      {
      QString s;
      if (e.hasAttribute("tick")) {
            setType(TType::TICKS);
            setTick(e.intAttribute("tick"));
            }
      if (e.hasAttribute("sample")) {
            setType(TType::FRAMES);
            setFrame(e.intAttribute("sample"));
            }
      if (e.hasAttribute("len")) {
            int n = e.intAttribute("len");
            if (type() == TType::TICKS)
                  setLenTick(n);
            else
                  setLenFrame(n);
            }
      }
 
//---------------------------------------------------------
//   setLenTick
//---------------------------------------------------------
 
void PosLen::setLenTick(unsigned len)
      {
      _lenTick = len;
      sn       = -1;
      if (type() == TType::FRAMES)
            _lenFrame = tempo->tick2time(len, &sn) * MScore::sampleRate;
      else
            _lenTick = len;
      }
 
//---------------------------------------------------------
//   setLenFrame
//---------------------------------------------------------
 
void PosLen::setLenFrame(unsigned len)
      {
      sn      = -1;
      if (type() == TType::TICKS)
            _lenTick = tempo->time2tick(len/MScore::sampleRate, &sn);
      else
            _lenFrame = len;
      }
 
//---------------------------------------------------------
//   lenTick
//---------------------------------------------------------
 
unsigned PosLen::lenTick() const
      {
      if (type() == TType::FRAMES)
            _lenTick = tempo->time2tick(_lenFrame/MScore::sampleRate, _lenTick, &sn);
      return _lenTick;
      }
 
//---------------------------------------------------------
//   lenFrame
//---------------------------------------------------------
 
unsigned PosLen::lenFrame() const
      {
      if (type() == TType::TICKS)
            _lenFrame = tempo->tick2time(_lenTick, _lenFrame, &sn) * MScore::sampleRate;
      return _lenFrame;
      }
 
//---------------------------------------------------------
//   end
//---------------------------------------------------------
 
Pos PosLen::end() const
      {
      Pos pos(*this);
      pos.invalidSn();
      switch(type()) {
            case TType::FRAMES:
                  pos.setFrame(pos.frame() + _lenFrame);
                  break;
            case TType::TICKS:
                  pos.setTick(pos.tick() + _lenTick);
                  break;
            }
      return pos;
      }
 
//---------------------------------------------------------
//   setPos
//---------------------------------------------------------
 
void PosLen::setPos(const Pos& pos)
      {
      switch(pos.type()) {
            case TType::FRAMES:
                  setFrame(pos.frame());
                  break;
            case TType::TICKS:
                  setTick(pos.tick());
                  break;
            }
      }
 
//---------------------------------------------------------
//   operator==
//---------------------------------------------------------
 
bool PosLen::operator==(const PosLen& pl) const
      {
      if (type() == TType::TICKS)
            return (_lenTick == pl._lenTick && Pos::operator==((const Pos&)pl));
      else
            return (_lenFrame==pl._lenFrame && Pos::operator==((const Pos&)pl));
      }
 
//---------------------------------------------------------
//   mbt
//---------------------------------------------------------
 
void Pos::mbt(int* bar, int* beat, int* tk) const
      {
      sig->tickValues(tick(), bar, beat, tk);
      }
 
//---------------------------------------------------------
//   msf
//---------------------------------------------------------
 
void Pos::msf(int* min, int* sec, int* fr, int* subFrame) const
      {
      // for further testing:
 
      double time = double(frame()) / double(MScore::sampleRate);
      *min        = int(time) / 60;
      *sec        = int(time) % 60;
      double rest = time - ((*min) * 60 + (*sec));
      switch(MScore::mtcType) {
            case 0:     // 24 frames sec
                  rest *= 24;
                  break;
            case 1:     // 25
                  rest *= 25;
                  break;
            case 2:     // 30 drop frame
                  rest *= 30;
                  break;
            case 3:     // 30 non drop frame
                  rest *= 30;
                  break;
            }
      *fr       = lrint(rest);
      *subFrame = lrint((rest - (*fr)) * 100.0);
      }
 
//---------------------------------------------------------
//   timesig
//---------------------------------------------------------
 
SigEvent Pos::timesig() const
      {
      return sig->timesig(tick());
      }
 
//---------------------------------------------------------
//   snap
//    raster = 1  no snap
//    raster = 0  snap to measure
//    all other raster values snap to raster tick
//---------------------------------------------------------
 
void Pos::snap(int raster)
      {
      setTick(sig->raster(tick(), raster));
      }
 
void Pos::upSnap(int raster)
      {
      setTick(sig->raster2(tick(), raster));
      }
 
void Pos::downSnap(int raster)
      {
      setTick(sig->raster1(tick(), raster));
      }
 
Pos Pos::snaped(int raster) const
      {
      return Pos(tempo, sig, sig->raster(tick(), raster));
      }
 
Pos Pos::upSnaped(int raster) const
      {
      return Pos(tempo, sig, sig->raster2(tick(), raster));
      }
 
Pos Pos::downSnaped(int raster) const
      {
      return Pos(tempo, sig, sig->raster1(tick(), raster));
      }
 
}
 

V730 Not all members of a class are initialized inside the constructor. Consider inspecting: _frame.

V730 Not all members of a class are initialized inside the constructor. Consider inspecting: _frame.

V730 Not all members of a class are initialized inside the constructor. Consider inspecting: _tick.