Reorganize locations to use VLLocation

This commit is contained in:
Matthias Neeracher 2011-09-11 04:03:22 +02:00
parent 8a30706b8c
commit ddc7b4d923
18 changed files with 368 additions and 373 deletions

View File

@ -5,7 +5,7 @@
//
// (MN) Matthias Neeracher
//
// Copyright © 2007 Matthias Neeracher
// Copyright © 2007-2011 Matthias Neeracher
//
#include "VLLayout.h"
@ -77,17 +77,17 @@ float VLLayout::MeasurePosition(int measure) const
return 0.0f;
}
float VLLayout::NotePosition(int measure, VLFraction at) const
float VLLayout::NotePosition(VLLocation at) const
{
for (int sys=0; sys<size(); ++sys) {
const VLSystemLayout & layout = (*this)[sys];
if (measure < layout.NumMeasures()) {
int div = at.fNum*4*layout.Divisions() / at.fDenom;
if (at.fMeasure < layout.NumMeasures()) {
int div = at.fAt.fNum*4*layout.Divisions() / at.fAt.fDenom;
return layout.MeasurePosition(measure)
return layout.MeasurePosition(at.fMeasure)
+ (div + div/layout.DivPerGroup() + 1)*kNoteW;
}
measure -= layout.NumMeasures();
at.fMeasure -= layout.NumMeasures();
}
return 0.0f;
}

View File

@ -5,7 +5,7 @@
//
// (MN) Matthias Neeracher
//
// Copyright © 2007 Matthias Neeracher
// Copyright © 2007-2011 Matthias Neeracher
//
#include "VLModel.h"
@ -38,9 +38,9 @@ public:
int FirstMeasure(int system) const;
int SystemForMeasure(int measure) const;
int NumSystems() const { return size(); }
int NumSystems() const { return static_cast<int>(size()); }
float MeasurePosition(int measure) const;
float NotePosition(int measure, VLFraction at) const;
float NotePosition(VLLocation at) const;
};
class VLFontHandler {

View File

@ -35,40 +35,40 @@ void VLMIDIWriter::Visit(VLSong & song)
void VLMIDIWriter::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
{
const VLLocation kStartOfMeasure = {m, VLFraction(0)};
if (fVolta.size() <= m)
fVolta.push_back(0);
fTime = p.fTime;
fMeasure = m;
fStanza = ++fVolta[m];
if (!fChordTime)
fChordTime = fNoteTime = fCountIn*fTime.fNum;
fAt = 0;
fAt = kStartOfMeasure;
VisitChords(meas);
fAt = 0;
fAt = kStartOfMeasure;
VisitNotes(meas, p, false);
}
void VLMIDIWriter::VisitNote(VLLyricsNote & n)
{
if (!(n.fTied & VLNote::kTiedWithPrev)) {
VLMIDIUserEvent event = {12, n.fPitch, fStanza, fMeasure, n.fVisual, fAt};
VLMIDIUserEvent event = {12, n.fPitch, fStanza, n.fVisual, fAt};
MusicTrackNewUserEvent(fTrack, fNoteTime,
reinterpret_cast<const MusicEventUserData *>(&event));
}
fAt += n.fDuration;
fAt.fAt = fAt.fAt+n.fDuration;
fNoteTime += n.fDuration * (float)fTime.fDenom;
}
void VLMIDIWriter::VisitChord(VLChord & c)
{
if (c.fPitch != VLNote::kNoPitch) {
VLMIDIUserEvent event = {12, 0, fStanza, fMeasure, 0, fAt};
VLMIDIUserEvent event = {12, 0, fStanza, 0, fAt};
MusicTrackNewUserEvent(fTrack, fChordTime,
reinterpret_cast<const MusicEventUserData *>(&event));
}
fAt += c.fDuration;
fAt.fAt = fAt.fAt+c.fDuration;
fChordTime += c.fDuration * (float)fTime.fDenom;
}

View File

@ -16,9 +16,8 @@ struct VLMIDIUserEvent {
uint32_t fLength;
int8_t fPitch; // 0 -> Chord
uint8_t fStanza;
int16_t fMeasure;
uint32_t fVisual;
VLFract fAt;
uint16_t fVisual;
VLLocation fAt;
};
class VLMIDIWriter: public VLSongVisitor {
@ -34,11 +33,10 @@ private:
MusicSequence fMusic;
size_t fCountIn;
MusicTrack fTrack;
size_t fMeasure;
size_t fStanza;
MusicTimeStamp fChordTime;
MusicTimeStamp fNoteTime;
VLFraction fAt;
VLLocation fAt;
VLFraction fTime;
std::vector<uint8_t> fVolta;
};

View File

@ -109,7 +109,7 @@ std::string VLNote::Name(uint16_t accidental) const
void VLNote::MakeRepresentable()
{
if (fDuration > 1)
if (fDuration > VLFraction(1))
fDuration = 1;
fVisual = kWhole | (fVisual & kAccidentalsMask);
VLFraction part(1,1);
@ -251,7 +251,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose
// Don't paint ourselves into a corner by leaving a non-representable
// remainder.
//
if (p.fDuration != c.fDuration && (c.fDuration-p.fDuration) % kMinDuration != 0) {
if (p.fDuration != c.fDuration && (c.fDuration-p.fDuration) % kMinDuration != VLFraction(0)) {
r += kMinDuration;
p.fDuration = c.fDuration-r;
continue;
@ -296,7 +296,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose
if (at.fDenom == 3 || at.fDenom > 4) {
//
// Break up notes not starting on quarter beat
// - Never cross middle of measure
// - Never cross middle of at.fMeasure
//
VLFraction middle;
if (prop.fTime.fNum & 1) // Treat 5/4 as 3+2, not 2+3
@ -324,8 +324,8 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose
VLFraction sw24(1,24);
VLFraction grid4(1, 4);
VLFraction grid8(1, 8);
if ((p.fDuration == sw6 && (at % grid4 == 0))
|| (swing16 && p.fDuration == sw12 && (at % grid8 == 0))
if ((p.fDuration == sw6 && !(at % grid4))
|| (swing16 && p.fDuration == sw12 && !(at % grid8))
) {
if (p.fDuration == c.fDuration && n2!=e
&& n->fDuration == p.fDuration && n2->fDuration >= p.fDuration
@ -337,8 +337,8 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose
//
p.fVisual = (p.fVisual+1) & ~VLNote::kTupletMask;
}
} else if ((p.fDuration == sw12 && ((at+p.fDuration) % grid4 == 0))
|| (swing16 && p.fDuration == sw24 && ((at+p.fDuration) % grid8 == 0))
} else if ((p.fDuration == sw12 && !((at+p.fDuration) % grid4))
|| (swing16 && p.fDuration == sw24 && !((at+p.fDuration) % grid8))
) {
//
// Second swing note (8th triplet -> 8th)
@ -346,7 +346,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose
if (!prevTriplets)
p.fVisual &= ~VLNote::kTupletMask;
} else if ((p.fDuration > kMinDuration) &&
((at % p.fDuration != 0)
((at % p.fDuration != VLFraction(0))
|| (p.fDuration != c.fDuration
&& 2*p.fDuration != c.fDuration)
|| (n!=e && n->fDuration != c.fDuration
@ -379,7 +379,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose
p.fDuration = c.fDuration;
p.fTied |= VLNote::kTiedWithPrev;
p.fLyrics.clear();
} while (c.fDuration > 0);
} while (c.fDuration > VLFraction(0));
i = n;
}
}
@ -499,21 +499,21 @@ void VLSong::clear()
//
// Deal with chords - a bit simpler
//
void VLSong::AddChord(VLChord chord, size_t measure, VLFraction at)
void VLSong::AddChord(VLChord chord, VLLocation at)
{
//
// Always keep an empty measure in reserve
//
while (measure+1 >= fMeasures.size())
while (at.fMeasure+1 >= fMeasures.size())
AddMeasure();
VLChordList::iterator i = fMeasures[measure].fChords.begin();
VLChordList::iterator i = fMeasures[at.fMeasure].fChords.begin();
VLFraction t(0);
for (;;) {
VLFraction tEnd = t+i->fDuration;
if (tEnd > at) {
if (t == at) {
if (tEnd > at.fAt) {
if (t == at.fAt) {
//
// Exact match, replace current
//
@ -523,9 +523,9 @@ void VLSong::AddChord(VLChord chord, size_t measure, VLFraction at)
//
// Overlap, split current
//
chord.fDuration = tEnd-at;
i->fDuration = at-t;
fMeasures[measure].fChords.insert(++i, chord);
chord.fDuration = tEnd-at.fAt;
i->fDuration = at.fAt-t;
fMeasures[at.fMeasure].fChords.insert(++i, chord);
}
break; // Exit here
}
@ -534,24 +534,24 @@ void VLSong::AddChord(VLChord chord, size_t measure, VLFraction at)
}
}
void VLSong::DelChord(size_t measure, VLFraction at)
void VLSong::DelChord(VLLocation at)
{
VLChordList::iterator i = fMeasures[measure].fChords.begin();
VLChordList::iterator i = fMeasures[at.fMeasure].fChords.begin();
VLFraction t(0);
for (;;) {
if (t == at) {
if (t == at.fAt) {
//
// Found it. Extend previous or make rest
//
if (i != fMeasures[measure].fChords.begin()) {
if (i != fMeasures[at.fMeasure].fChords.begin()) {
//
// Extend previous
//
VLChordList::iterator j = i;
--j;
j->fDuration += i->fDuration;
fMeasures[measure].fChords.erase(i);
fMeasures[at.fMeasure].fChords.erase(i);
} else {
//
// Turn into rest
@ -561,7 +561,7 @@ void VLSong::DelChord(size_t measure, VLFraction at)
break;
}
VLFraction tEnd = t+i->fDuration;
if (tEnd > at)
if (tEnd > at.fAt)
break; // Past the point, quit
t = tEnd;
++i;
@ -569,17 +569,17 @@ void VLSong::DelChord(size_t measure, VLFraction at)
//
// Trim excess empty measures
//
if (measure == fMeasures.size()-2 && fMeasures[measure].IsEmpty())
if (at.fMeasure == fMeasures.size()-2 && fMeasures[at.fMeasure].IsEmpty())
fMeasures.pop_back();
}
uint8_t & FirstTie(VLMeasure & measure)
static uint8_t & FirstTie(VLMeasure & measure)
{
VLNoteList::iterator i = measure.fMelody.begin();
return i->fTied;
}
uint8_t & LastTie(VLMeasure & measure)
static uint8_t & LastTie(VLMeasure & measure)
{
VLNoteList::iterator i = measure.fMelody.end();
--i;
@ -589,25 +589,25 @@ uint8_t & LastTie(VLMeasure & measure)
//
// Dealing with notes is similar, but we also have to handle ties
//
void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at)
void VLSong::AddNote(VLLyricsNote note, VLLocation at)
{
//
// Sanity check on accidentals
//
note.fVisual = VLPitchAccidental(note.fPitch, note.fVisual, Properties(measure).fKey);
note.fVisual = VLPitchAccidental(note.fPitch, note.fVisual, Properties(at.fMeasure).fKey);
//
// Always keep an empty measure in reserve
//
while (measure+1 >= fMeasures.size())
while (at.fMeasure+1 >= fMeasures.size())
AddMeasure();
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
VLNoteList::iterator i = fMeasures[at.fMeasure].fMelody.begin();
VLFraction t(0);
for (;;) {
VLFraction tEnd = t+i->fDuration;
if (tEnd > at) {
if (t == at) {
if (tEnd > at.fAt) {
if (t == at.fAt) {
//
// Exact match, replace current
//
@ -617,11 +617,11 @@ void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at)
//
if (i->fTied & VLNote::kTiedWithPrev) {
i->fTied &= ~VLNote::kTiedWithPrev;
LastTie(fMeasures[measure-1]) &= ~VLNote::kTiedWithNext;
LastTie(fMeasures[at.fMeasure-1]) &= ~VLNote::kTiedWithNext;
}
if (i->fTied & VLNote::kTiedWithNext) {
VLNoteList::iterator j = i;
for (size_t tiedMeas = measure+1; j->fTied & VLNote::kTiedWithNext;++tiedMeas) {
for (size_t tiedMeas = at.fMeasure+1; j->fTied & VLNote::kTiedWithNext;++tiedMeas) {
j = fMeasures[tiedMeas].fMelody.begin();
j->fPitch = note.fPitch;
j->fVisual= note.fVisual;
@ -639,28 +639,28 @@ void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at)
//
// Overlap, split current
//
note.fDuration = tEnd-at;
i->fDuration = at-t;
i = fMeasures[measure].fMelody.insert(++i, note);
note.fDuration = tEnd-at.fAt;
i->fDuration = at.fAt-t;
i = fMeasures[at.fMeasure].fMelody.insert(++i, note);
}
if (i->fPitch == VLNote::kNoPitch) {
//
// Merge with adjacent rests
//
if (i != fMeasures[measure].fMelody.begin()) {
if (i != fMeasures[at.fMeasure].fMelody.begin()) {
VLNoteList::iterator j = i;
--j;
if (j->fPitch == VLNote::kNoPitch) {
j->fDuration += i->fDuration;
fMeasures[measure].fMelody.erase(i);
fMeasures[at.fMeasure].fMelody.erase(i);
i = j;
}
}
VLNoteList::iterator j = i;
++j;
if (j != fMeasures[measure].fMelody.end() && j->fPitch == VLNote::kNoPitch) {
if (j != fMeasures[at.fMeasure].fMelody.end() && j->fPitch == VLNote::kNoPitch) {
i->fDuration += j->fDuration;
fMeasures[measure].fMelody.erase(j);
fMeasures[at.fMeasure].fMelody.erase(j);
}
}
break; // Exit here
@ -670,8 +670,8 @@ void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at)
}
i->fTied = 0;
if (note.fTied & VLNote::kTiedWithPrev) // kTiedWithNext is NEVER user set
if (measure && i == fMeasures[measure].fMelody.begin()) {
VLNoteList::iterator j = fMeasures[measure-1].fMelody.end();
if (at.fMeasure && i == fMeasures[at.fMeasure].fMelody.begin()) {
VLNoteList::iterator j = fMeasures[at.fMeasure-1].fMelody.end();
--j;
if (j->fPitch == i->fPitch) {
j->fTied |= VLNote::kTiedWithNext;
@ -680,40 +680,40 @@ void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at)
}
}
void VLSong::DelNote(size_t measure, VLFraction at)
void VLSong::DelNote(VLLocation at)
{
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
VLNoteList::iterator i = fMeasures[at.fMeasure].fMelody.begin();
VLFraction t(0);
for (;;) {
if (t == at) {
if (t == at.fAt) {
//
// Found it. Break ties.
//
if (i->fTied & VLNote::kTiedWithNext)
FirstTie(fMeasures[measure+1]) &= ~VLNote::kTiedWithPrev;
FirstTie(fMeasures[at.fMeasure+1]) &= ~VLNote::kTiedWithPrev;
if (i->fTied & VLNote::kTiedWithPrev)
LastTie(fMeasures[measure-1]) &= ~VLNote::kTiedWithNext;
LastTie(fMeasures[at.fMeasure-1]) &= ~VLNote::kTiedWithNext;
//
// Extend previous or make rest
//
if (i != fMeasures[measure].fMelody.begin()) {
if (i != fMeasures[at.fMeasure].fMelody.begin()) {
//
// Extend previous
//
VLNoteList::iterator j = i;
--j;
j->fDuration += i->fDuration;
fMeasures[measure].fMelody.erase(i);
fMeasures[at.fMeasure].fMelody.erase(i);
} else {
//
// Merge with next if it's a rest, otherwise, just turn into rest
//
VLNoteList::iterator j = i;
++j;
if (j != fMeasures[measure].fMelody.end() && j->fPitch == VLNote::kNoPitch) {
if (j != fMeasures[at.fMeasure].fMelody.end() && j->fPitch == VLNote::kNoPitch) {
i->fDuration += j->fDuration;
fMeasures[measure].fMelody.erase(j);
fMeasures[at.fMeasure].fMelody.erase(j);
}
i->fPitch = VLNote::kNoPitch;
i->fTied = 0;
@ -721,7 +721,7 @@ void VLSong::DelNote(size_t measure, VLFraction at)
break;
}
VLFraction tEnd = t+i->fDuration;
if (tEnd > at)
if (tEnd > at.fAt)
break; // Past the point, quit
t = tEnd;
++i;
@ -729,19 +729,19 @@ void VLSong::DelNote(size_t measure, VLFraction at)
//
// Trim excess empty measures
//
if (measure == fMeasures.size()-2 && fMeasures[measure].IsEmpty())
if (at.fMeasure == fMeasures.size()-2 && fMeasures[at.fMeasure].IsEmpty())
fMeasures.pop_back();
}
VLNote VLSong::ExtendNote(size_t measure, VLFraction at)
VLNote VLSong::ExtendNote(VLLocation at)
{
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
VLNoteList::iterator end= fMeasures[measure].fMelody.end();
VLNoteList::iterator i = fMeasures[at.fMeasure].fMelody.begin();
VLNoteList::iterator end= fMeasures[at.fMeasure].fMelody.end();
if (i==end)
return VLNote(); // Empty song, do nothing
for (VLFraction t(0); i != end && t+i->fDuration <= at; ++i)
for (VLFraction t(0); i != end && t+i->fDuration <= at.fAt; ++i)
t += i->fDuration;
if (i == end)
@ -752,17 +752,17 @@ VLNote VLSong::ExtendNote(size_t measure, VLFraction at)
for (;;) {
VLNoteList::iterator j=i;
++j;
if (j != fMeasures[measure].fMelody.end()) {
if (j != fMeasures[at.fMeasure].fMelody.end()) {
//
// Extend across next note/rest
//
i->fDuration += j->fDuration;
fMeasures[measure].fMelody.erase(j);
} else if (++measure < fMeasures.size()) {
fMeasures[at.fMeasure].fMelody.erase(j);
} else if (++at.fMeasure < fMeasures.size()) {
//
// Extend into next measure
//
VLNoteList::iterator k = fMeasures[measure].fMelody.begin();
VLNoteList::iterator k = fMeasures[at.fMeasure].fMelody.begin();
if (k->fTied & VLNote::kTiedWithPrev) {
//
// Already extended, extend further
@ -783,10 +783,10 @@ VLNote VLSong::ExtendNote(size_t measure, VLFraction at)
if (!wasTied)
break;
i = k;
k = fMeasures[++measure].fMelody.begin();
k = fMeasures[++at.fMeasure].fMelody.begin();
}
}
if (measure+1 == fMeasures.size())
if (at.fMeasure+1 == fMeasures.size())
AddMeasure();
}
break;
@ -1220,23 +1220,23 @@ size_t VLSong::CountBotLedgers() const
return 0;
}
bool VLSong::FindWord(size_t stanza, size_t & measure, VLFraction & at)
bool VLSong::FindWord(size_t stanza, VLLocation & at)
{
at += VLFraction(1,64);
return PrevWord(stanza, measure, at);
at.fAt = at.fAt+VLFraction(1,64);
return PrevWord(stanza, at);
}
bool VLSong::PrevWord(size_t stanza, size_t & measure, VLFraction & at)
bool VLSong::PrevWord(size_t stanza, VLLocation & at)
{
do {
VLMeasure & meas = fMeasures[measure];
VLNoteList::iterator note = fMeasures[measure].fMelody.begin();
VLNoteList::iterator end = fMeasures[measure].fMelody.end();
VLMeasure & meas = fMeasures[at.fMeasure];
VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin();
VLNoteList::iterator end = fMeasures[at.fMeasure].fMelody.end();
bool hasWord = false;
VLFraction word(0);
VLFraction now(0);
while (note != meas.fMelody.end() && now < at) {
while (note != meas.fMelody.end() && now < at.fAt) {
if (!(note->fTied & VLNote::kTiedWithPrev)
&& note->fPitch != VLNote::kNoPitch
)
@ -1250,37 +1250,37 @@ bool VLSong::PrevWord(size_t stanza, size_t & measure, VLFraction & at)
++note;
}
if (hasWord) {
at = word;
at.fAt = word;
return true;
} else {
at = fProperties[meas.fPropIdx].fTime;
at.fAt = fProperties[meas.fPropIdx].fTime;
}
} while (measure-- > 0);
} while (at.fMeasure-- > 0);
measure = 0;
at.fMeasure = 0;
return false;
}
bool VLSong::NextWord(size_t stanza, size_t & measure, VLFraction & at)
bool VLSong::NextWord(size_t stanza, VLLocation & at)
{
bool firstMeasure = true;
do {
VLMeasure & meas = fMeasures[measure];
VLNoteList::iterator note = fMeasures[measure].fMelody.begin();
VLNoteList::iterator end = fMeasures[measure].fMelody.end();
VLMeasure & meas = fMeasures[at.fMeasure];
VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin();
VLNoteList::iterator end = fMeasures[at.fMeasure].fMelody.end();
VLFraction now(0);
while (note != meas.fMelody.end()) {
if (!(note->fTied & VLNote::kTiedWithPrev)
&& note->fPitch != VLNote::kNoPitch
&& (!firstMeasure || now>at)
&& (!firstMeasure || now>at.fAt)
)
if (note->fLyrics.size() < stanza
|| !(note->fLyrics[stanza-1].fKind & VLSyllable::kHasPrev)
) {
at = now;
at.fAt = now;
return true;
}
@ -1288,23 +1288,23 @@ bool VLSong::NextWord(size_t stanza, size_t & measure, VLFraction & at)
++note;
}
firstMeasure = false;
} while (++measure < fMeasures.size());
} while (++at.fMeasure < fMeasures.size());
return false;
}
std::string VLSong::GetWord(size_t stanza, size_t measure, VLFraction at)
std::string VLSong::GetWord(size_t stanza, VLLocation at)
{
std::string word;
while (measure < fMeasures.size()) {
VLMeasure & meas = fMeasures[measure];
while (at.fMeasure < fMeasures.size()) {
VLMeasure & meas = fMeasures[at.fMeasure];
VLNoteList::iterator note = meas.fMelody.begin();
VLNoteList::iterator end = meas.fMelody.end();
VLFraction now(0);
while (note != end) {
if (now >= at && note->fPitch != VLNote::kNoPitch
if (now >= at.fAt && note->fPitch != VLNote::kNoPitch
&& !(note->fTied & VLNote::kTiedWithPrev)
) {
if (word.size())
@ -1319,19 +1319,19 @@ std::string VLSong::GetWord(size_t stanza, size_t measure, VLFraction at)
now += note->fDuration;
++note;
}
at = 0;
++measure;
at.fAt = VLFraction(0);
++at.fMeasure;
}
return word;
}
void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string word, size_t * nextMeas, VLFract * nextAt)
void VLSong::SetWord(size_t stanza, VLLocation at, std::string word, VLLocation * nextAt)
{
//
// Always keep an empty measure in reserve
//
while (measure+1 >= fMeasures.size())
while (at.fMeasure+1 >= fMeasures.size())
AddMeasure();
uint8_t kind = 0;
@ -1342,9 +1342,9 @@ void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string w
} state = kFindFirst;
do {
VLMeasure & meas = fMeasures[measure];
VLNoteList::iterator note = fMeasures[measure].fMelody.begin();
VLNoteList::iterator end = fMeasures[measure].fMelody.end();
VLMeasure & meas = fMeasures[at.fMeasure];
VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin();
VLNoteList::iterator end = fMeasures[at.fMeasure].fMelody.end();
VLFraction now(0);
while (note != meas.fMelody.end()) {
@ -1353,7 +1353,7 @@ void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string w
)
switch (state) {
case kFindFirst:
if (now < at)
if (now < at.fAt)
break; // Not yet there, skip this note
state = kOverwrite;
// Fall through
@ -1402,13 +1402,10 @@ void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string w
kind &= ~VLSyllable::kHasPrev;
break; }
case kCleanup:
if (nextMeas) {
*nextMeas = measure;
nextMeas = 0;
}
if (nextAt) {
*nextAt = now;
nextAt = 0;
nextAt->fMeasure = at.fMeasure;
nextAt->fAt = now;
nextAt = 0;
}
//
// Delete all subsequent syllables with kHasPrev set
@ -1424,12 +1421,12 @@ void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string w
now += note->fDuration;
++note;
}
at = 0;
} while (++measure < fMeasures.size());
if (nextMeas)
*nextMeas = 0;
if (nextAt)
*nextAt = VLFraction(0);
at.fAt = VLFraction(0);
} while (++at.fMeasure < fMeasures.size());
if (nextAt) {
nextAt->fMeasure = 0;
nextAt->fAt = VLFraction(0);
}
}
void VLSong::AddRepeat(size_t beginMeasure, size_t endMeasure, int times)
@ -1937,7 +1934,7 @@ void VLSong::PasteMeasures(size_t beginMeasure, const VLSong & measures, int mod
if (endProp > beginProp && fProperties[propAt] == endProp[-1])
--endProp;
}
int postOffset = endProp - beginProp;
ptrdiff_t postOffset = endProp - beginProp;
fProperties.insert(fProperties.begin()+propAt, beginProp, endProp);
fMeasures.insert(fMeasures.begin()+beginMeasure,

View File

@ -65,36 +65,83 @@ inline VLFraction operator%(VLFraction one, VLFraction other)
return one %= other;
}
inline bool operator==(VLFraction one, VLFraction other)
inline bool operator!(VLFract fract)
{
return !fract.fNum;
}
inline bool operator==(VLFract one, VLFract other)
{
return one.fNum*other.fDenom == other.fNum*one.fDenom;
}
inline bool operator!=(VLFraction one, VLFraction other)
inline bool operator!=(VLFract one, VLFract other)
{
return one.fNum*other.fDenom != other.fNum*one.fDenom;
}
inline bool operator<(VLFraction one, VLFraction other)
inline bool operator<(VLFract one, VLFract other)
{
return one.fNum*other.fDenom < other.fNum*one.fDenom;
}
inline bool operator>(VLFraction one, VLFraction other)
inline bool operator>(VLFract one, VLFract other)
{
return one.fNum*other.fDenom > other.fNum*one.fDenom;
}
inline bool operator<=(VLFraction one, VLFraction other)
inline bool operator<=(VLFract one, VLFract other)
{
return one.fNum*other.fDenom <= other.fNum*one.fDenom;
}
inline bool operator>=(VLFraction one, VLFraction other)
inline bool operator>=(VLFract one, VLFract other)
{
return one.fNum*other.fDenom >= other.fNum*one.fDenom;
}
#pragma mark -
#pragma mark struct VLLocation
struct VLLocation {
uint32_t fMeasure;
VLFract fAt;
};
inline bool operator==(const VLLocation & one, const VLLocation & other)
{
return one.fMeasure == other.fMeasure && one.fAt == other.fAt;
}
inline bool operator!=(const VLLocation & one, const VLLocation & other)
{
return one.fMeasure != other.fMeasure || one.fAt != other.fAt;
}
inline bool operator<(const VLLocation & one, const VLLocation & other)
{
return one.fMeasure < other.fMeasure
|| (one.fMeasure == other.fMeasure && one.fAt < other.fAt);
}
inline bool operator<=(const VLLocation & one, const VLLocation & other)
{
return one.fMeasure < other.fMeasure
|| (one.fMeasure == other.fMeasure && one.fAt <= other.fAt);
}
inline bool operator>(const VLLocation & one, const VLLocation & other)
{
return one.fMeasure > other.fMeasure
|| (one.fMeasure == other.fMeasure && one.fAt > other.fAt);
}
inline bool operator>=(const VLLocation & one, const VLLocation & other)
{
return one.fMeasure > other.fMeasure
|| (one.fMeasure == other.fMeasure && one.fAt >= other.fAt);
}
#pragma mark -
#pragma mark class VLNote
@ -324,8 +371,8 @@ public:
VLPropertyList fProperties;
VLMeasureList fMeasures;
VLRepeatList fRepeats;
int8_t fGoToCoda;
int8_t fCoda;
int16_t fGoToCoda;
int16_t fCoda;
//
// Iterate over measures in performance order
@ -367,11 +414,11 @@ public:
iterator begin() { return iterator(*this, false); }
iterator end() { return iterator(*this, true); }
void AddChord(VLChord chord, size_t measure, VLFraction at);
void AddNote(VLLyricsNote note, size_t measure, VLFraction at);
void DelChord(size_t measure, VLFraction at);
void DelNote(size_t measure, VLFraction at);
VLNote ExtendNote(size_t measure, VLFraction at);
void AddChord(VLChord chord, VLLocation at);
void AddNote(VLLyricsNote note, VLLocation at);
void DelChord(VLLocation at);
void DelNote(VLLocation at);
VLNote ExtendNote(VLLocation at);
void AddRepeat(size_t beginMeasure, size_t endMeasure, int times);
void DelRepeat(size_t beginMeasure, size_t endMeasure);
void AddEnding(size_t beginMeasure, size_t endMeasure, size_t volta);
@ -391,12 +438,12 @@ public:
void ChangeDivisions(int section, int newDivisions);
void ChangeTime(int section, VLFraction newTime);
bool FindWord(size_t stanza, size_t & measure, VLFraction & at);
bool PrevWord(size_t stanza, size_t & measure, VLFraction & at);
bool NextWord(size_t stanza, size_t & measure, VLFraction & at);
std::string GetWord(size_t stanza, size_t measure, VLFraction at);
void SetWord(size_t stanza, size_t measure, VLFraction at, std::string word,
size_t * nextMeas=0, VLFract * nextAt=0);
bool FindWord(size_t stanza, VLLocation & at);
bool PrevWord(size_t stanza, VLLocation & at);
bool NextWord(size_t stanza, VLLocation & at);
std::string GetWord(size_t stanza, VLLocation at);
void SetWord(size_t stanza, VLLocation at, std::string word,
VLLocation * nextAt=0);
enum {
kInsert,

View File

@ -96,7 +96,7 @@ void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
NSMutableDictionary * md =
[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:m], @"measure",
[NSNumber numberWithUnsignedInt:m], @"measure",
[NSNumber numberWithInt:meas.fPropIdx], @"properties",
fNotes, @"melody", fChords, @"chords",
nil];
@ -112,7 +112,7 @@ void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
[md setObject:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:!last], @"last",
[NSNumber numberWithInt:volta], @"volta",
[NSNumber numberWithUnsignedInt:volta], @"volta",
nil]
forKey: @"begin-ending"];
if (fSong->DoesEndRepeat(m+1, &times))
@ -124,7 +124,7 @@ void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
[md setObject:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:!last], @"last",
[NSNumber numberWithInt:volta], @"volta",
[NSNumber numberWithUnsignedInt:volta], @"volta",
nil]
forKey: @"end-ending"];
if (fSong->fGoToCoda == m+1)
@ -305,9 +305,9 @@ enum {
- (void)readMelody:(NSArray *)melody inMeasure:(size_t)measNo onsets:(int *)onsets lyrics:(uint8_t *)prevKind
{
VLFraction at(0);
int lastOnset = 0;
VLFraction tiedStart(0);
VLLocation at = {measNo, VLFraction(0)};
int lastOnset = 0;
VLLocation tiedStart = {measNo, VLFraction(0)};
VLLyricsNote tiedNote;
for (NSEnumerator * ne = [melody objectEnumerator];
@ -328,13 +328,13 @@ enum {
[[ndict objectForKey:@"normalNotes"] intValue]);
if ([[ndict objectForKey:@"tied"] intValue] & VLNote::kTiedWithPrev) {
if (at != 0) {
if (at.fAt != VLFraction(0)) {
//
// Extend preceding note
//
tiedNote.fDuration += note.fDuration;
song->DelNote(measNo, tiedStart);
song->AddNote(tiedNote, measNo, tiedStart);
song->DelNote(tiedStart);
song->AddNote(tiedNote, tiedStart);
goto advanceAt;
} else {
@ -376,10 +376,10 @@ enum {
tiedStart = at;
tiedNote = note;
song->AddNote(note, measNo, at);
song->AddNote(note, at);
if (!(note.fTied & VLNote::kTiedWithPrev)) {
VLFraction inQuarter = at % VLFraction(1,4);
VLFraction inQuarter = at.fAt % VLFraction(1,4);
int onset = inQuarter.fNum * 48 / inQuarter.fDenom;
++onsets[onset];
switch (onset) {
@ -398,13 +398,13 @@ enum {
}
}
advanceAt:
at += note.fDuration;
at.fAt = at.fAt + note.fDuration;
}
}
- (void)readChords:(NSArray *)chords inMeasure:(size_t)measNo
{
VLFraction at(0);
VLLocation at = {measNo, VLFraction(0)};
for (NSEnumerator * ce = [chords objectEnumerator];
NSDictionary * cdict = [ce nextObject];
@ -420,9 +420,9 @@ advanceAt:
chord.fRootAccidental = [[cdict objectForKey:@"rootvisual"] intValue];
chord.fSteps = [[cdict objectForKey:@"steps"] intValue];
song->AddChord(chord, measNo, at);
song->AddChord(chord, at);
at += chord.fDuration;
at.fAt = at.fAt + chord.fDuration;
}
}

View File

@ -81,8 +81,7 @@ enum VLCursorVisual {
NSPoint fLastNoteCenter;
NSTrackingRectTag fCursorTracking;
VLRegion fCursorRegion;
int fCursorMeasure;
VLFract fCursorAt;
VLLocation fCursorLocation;
int fCursorVertPos;
uint16_t fCursorVisual;
size_t fCursorStanza;
@ -95,10 +94,8 @@ enum VLCursorVisual {
size_t fVolta;
size_t fVoltaOK;
VLLayout * fLayout;
int fHighlightStartMeasure;
VLFract fHighlightStartAt;
int fHighlightEndMeasure;
VLFract fHighlightEndAt;
VLLocation fHighlightStart;
VLLocation fHighlightEnd;
size_t fHighlightStanza;
VLKeyValueUndo * fUndo;
@ -138,7 +135,7 @@ enum VLCursorVisual {
- (float) noteYInSection:(int)section withPitch:(int)pitch;
- (VLMusicElement)accidentalForVisual:(uint16_t)visual;
- (float) noteYInMeasure:(int)measure withGrid:(int)vertPos;
- (float) noteXInMeasure:(int)measure at:(VLFraction)at;
- (float) noteXAt:(VLLocation)at;
- (void) needsRecalculation;
- (void) scrollMeasureToVisible:(int)measure;

View File

@ -233,9 +233,9 @@ static float sFlatPos[] = {
+ [self noteYInGrid:vertPos];
}
- (float) noteXInMeasure:(int)measure at:(VLFraction)at
- (float) noteXAt:(VLLocation)at
{
return fLayout->NotePosition(measure, at);
return fLayout->NotePosition(at);
}
- (void) scrollMeasureToVisible:(int)measure
@ -764,9 +764,9 @@ const float kSemiFloor = -1.0f*kLineH;
if (measure < 0 || measure > kLayout.NumMeasures())
return fCursorRegion = kRegionNowhere;
fCursorMeasure = measure+fLayout->FirstMeasure(system);
fCursorLocation.fMeasure = measure+fLayout->FirstMeasure(system);
if (fCursorMeasure > [self song]->fMeasures.size())
if (fCursorLocation.fMeasure > [self song]->fMeasures.size())
return fCursorRegion = kRegionNowhere;
else
return fCursorRegion = kRegionMeasure;
@ -780,18 +780,18 @@ const float kSemiFloor = -1.0f*kLineH;
loc.x -= group*(kLayout.DivPerGroup()+1)*kNoteW;
int div = static_cast<int>(roundf(loc.x / kNoteW))-1;
div = std::min(std::max(div, 0), kLayout.DivPerGroup()-1);
fCursorMeasure = measure+fLayout->FirstMeasure(system);
if (fCursorMeasure > [self song]->fMeasures.size())
fCursorLocation.fMeasure = measure+fLayout->FirstMeasure(system);
if (fCursorLocation.fMeasure > [self song]->fMeasures.size())
return fCursorRegion = kRegionNowhere;
fCursorAt = VLFraction(div+group*kLayout.DivPerGroup(), 4*song->Properties(fCursorMeasure).fDivisions);
fCursorLocation.fAt = VLFraction(div+group*kLayout.DivPerGroup(), 4*song->Properties(fCursorLocation.fMeasure).fDivisions);
if (loc.y >= kSystemBaseline+kChordY) {
//
// Chord, round to quarters
//
int scale = fCursorAt.fDenom / 4;
fCursorAt = VLFraction(fCursorAt.fNum / scale, 4);
int scale = fCursorLocation.fAt.fDenom / 4;
fCursorLocation.fAt = VLFraction(fCursorLocation.fAt.fNum / scale, 4);
return fCursorRegion = kRegionChord;
} else if (loc.y < kSystemBaseline+kLyricsY) {
fCursorStanza = static_cast<size_t>((kSystemBaseline+kLyricsY-loc.y) / kLyricsH)
@ -855,7 +855,7 @@ const float kSemiFloor = -1.0f*kLineH;
break;
case kRegionLyrics:
if (extend && [[self editTarget] canExtendSelection:kRegionLyrics]) {
[[self editTarget] extendSelection:fCursorMeasure at:fCursorAt];
[[self editTarget] extendSelection:fCursorLocation];
} else {
fSelEnd = -1;
[self editLyrics];
@ -881,7 +881,7 @@ const float kSemiFloor = -1.0f*kLineH;
if (prevRegion == kRegionMeasure)
[self adjustSelection:event];
else if ([[self editTarget] canExtendSelection:[self findRegionForEvent:event]])
[[self editTarget] extendSelection:fCursorMeasure at:fCursorAt];
[[self editTarget] extendSelection:fCursorLocation];
}
- (void) keyDown:(NSEvent *)event

View File

@ -13,14 +13,12 @@
@interface VLChordEditable : VLEditable {
VLSheetView * fView;
VLSong * fSong;
int fMeasure;
VLFract fAt;
VLLocation fSelection;
}
- (VLChordEditable *)initWithView:(VLSheetView *)view
song:(VLSong *)song
measure:(int)measure
at:(VLFract)at;
at:(VLLocation)at;
- (NSString *) stringValue;
- (void) setStringValue:(NSString*)val;
- (BOOL) validValue:(NSString*)val;
@ -34,7 +32,7 @@
- (void) editChord;
- (void) drawChordsForSystem:(int)system;
- (void) highlightChordInMeasure:(int)measure at:(VLFraction)at;
- (void) highlightChord:(VLLocation)at;
@end

View File

@ -61,14 +61,12 @@ std::string NormalizeName(NSString* rawName)
- (VLChordEditable *)initWithView:(VLSheetView *)view
song:(VLSong *)song
measure:(int)measure
at:(VLFract)at;
at:(VLLocation)at;
{
self = [super init];
fView = view;
fSong = song;
fMeasure= measure;
fAt = at;
self = [super init];
fView = view;
fSong = song;
fSelection = at;
[fView setNeedsDisplay: YES];
@ -77,23 +75,23 @@ std::string NormalizeName(NSString* rawName)
- (NSString *) stringValue
{
if (fMeasure >= fSong->CountMeasures())
if (fSelection.fMeasure >= fSong->CountMeasures())
return @"";
const VLMeasure measure = fSong->fMeasures[fMeasure];
const VLMeasure measure = fSong->fMeasures[fSelection.fMeasure];
const VLChordList & chords = measure.fChords;
VLFraction at(0);
for (VLChordList::const_iterator chord = chords.begin();
chord != chords.end() && at <= fAt;
chord != chords.end() && at <= fSelection.fAt;
++chord
) {
if (at == fAt && chord->fPitch != VLNote::kNoPitch) {
if (at == fSelection.fAt && chord->fPitch != VLNote::kNoPitch) {
//
// Found it!
//
VLSoundOut::Instance()->PlayChord(*chord);
const VLProperties & prop = fSong->Properties(fMeasure);
const VLProperties & prop = fSong->Properties(fSelection.fMeasure);
std::string name, ext, root;
chord->Name(name, ext, root, prop.fKey > 0);
@ -114,14 +112,14 @@ std::string NormalizeName(NSString* rawName)
std::string chordName = NormalizeName(val);
if (!chordName.size()) {
[[fView document] willChangeSong];
fSong->DelChord(fMeasure, fAt);
fSong->DelChord(fSelection);
[[fView document] didChangeSong];
} else {
VLChord chord(chordName);
VLSoundOut::Instance()->PlayChord(chord);
[[fView document] willChangeSong];
fSong->AddChord(chord, fMeasure, fAt);
fSong->AddChord(chord, fSelection);
[[fView document] didChangeSong];
}
}
@ -144,29 +142,29 @@ std::string NormalizeName(NSString* rawName)
{
const VLProperties & prop = fSong->fProperties.front();
fAt = fAt+VLFraction(1,4);
if (fAt >= prop.fTime) {
fAt = VLFraction(0,4);
fMeasure = (fMeasure+1) % fSong->CountMeasures();
[fView scrollMeasureToVisible:fMeasure];
fSelection.fAt = fSelection.fAt+VLFraction(1,4);
if (fSelection.fAt >= prop.fTime) {
fSelection.fAt = VLFraction(0,4);
fSelection.fMeasure = (fSelection.fMeasure+1) % fSong->CountMeasures();
[fView scrollMeasureToVisible:fSelection.fMeasure];
}
}
- (void) moveToPrev
{
if (fAt < VLFraction(1,4)) {
const VLProperties & prop = fSong->fProperties.front();
fAt = prop.fTime - VLFraction(1,4);
fMeasure =
(fMeasure+fSong->CountMeasures()-1) % fSong->CountMeasures();
[fView scrollMeasureToVisible:fMeasure];
if (fSelection.fAt < VLFraction(1,4)) {
const VLProperties & prop = fSong->fProperties.front();
fSelection.fAt = prop.fTime - VLFraction(1,4);
fSelection.fMeasure =
(fSelection.fMeasure+fSong->CountMeasures()-1) % fSong->CountMeasures();
[fView scrollMeasureToVisible:fSelection.fMeasure];
} else
fAt = fAt-VLFraction(1,4);
fSelection.fAt = fSelection.fAt-VLFraction(1,4);
}
- (void) highlightCursor
{
[fView highlightChordInMeasure:fMeasure at:fAt];
[fView highlightChord:fSelection];
}
@end
@ -231,16 +229,16 @@ std::string NormalizeName(NSString* rawName)
break;
const VLMeasure measure = song->fMeasures[measIdx];
const VLChordList & chords = measure.fChords;
VLFraction at(0);
VLLocation at = {measIdx, VLFraction(0)};
for (VLChordList::const_iterator chord = chords.begin();
chord != chords.end();
++chord
) {
NSAttributedString * chordName = [self stringWithChord:*chord];
NSPoint chordLoc =
NSMakePoint([self noteXInMeasure:measIdx at:at], kSystemY+kChordY);
NSMakePoint([self noteXAt:at], kSystemY+kChordY);
[chordName drawAtPoint:chordLoc];
at += chord->fDuration;
at.fAt = at.fAt+chord->fDuration;
}
}
}
@ -251,18 +249,17 @@ std::string NormalizeName(NSString* rawName)
[[VLChordEditable alloc]
initWithView:self
song:[self song]
measure:fCursorMeasure
at:fCursorAt];
at:fCursorLocation];
[self setEditTarget:e];
[fFieldEditor selectText:self];
}
- (void) highlightChordInMeasure:(int)measure at:(VLFraction)at
- (void) highlightChord:(VLLocation)at
{
const VLProperties & prop = [self song]->fProperties.front();
const float kSystemY = [self systemY:fLayout->SystemForMeasure(measure)];
const float kSystemY = [self systemY:fLayout->SystemForMeasure(at.fMeasure)];
NSRect r =
NSMakeRect([self noteXInMeasure:measure at:at]-kNoteW*0.5f,
NSMakeRect([self noteXAt:at]-kNoteW*0.5f,
kSystemY+kChordY, prop.fDivisions*kNoteW, kChordH);
[[NSColor colorWithCalibratedWhite:0.8f alpha:1.0f] setFill];
NSRectFillUsingOperation(r, NSCompositePlusDarker);

View File

@ -14,20 +14,16 @@
VLSheetView * fView;
VLSong * fSong;
size_t fStanza;
size_t fMeasure;
VLFract fAt;
size_t fAnchorMeas;
VLFract fAnchorAt;
size_t fNextMeas;
VLFract fNextAt;
VLLocation fSelection;
VLLocation fAnchor;
VLLocation fNext;
NSString * fText;
}
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
song:(VLSong *)song
stanza:(int)stanza
measure:(int)measure
at:(VLFract)at;
at:(VLLocation)at;
- (NSString *) stringValue;
- (void) setStringValue:(NSString*)val;
- (BOOL) validValue:(NSString*)val;
@ -41,9 +37,8 @@
- (void) editLyrics;
- (void) drawLyricsForSystem:(int)system stanza:(size_t)stanza;
- (void) highlightLyricsInStanza:(size_t)stanza measure:(int)measure at:(VLFraction)at;
- (void) highlightTextInStanza:(size_t)stanza startMeasure:(int)startMeasure at:(VLFraction)startAt
endMeasure:(int)endMeasure at:(VLFraction)endAt;
- (void) highlightLyricsInStanza:(size_t)stanza at:(VLLocation)at;
- (void) highlightTextInStanza:(size_t)stanza start:(VLLocation)start end:(VLLocation)end;
@end

View File

@ -20,35 +20,28 @@
- (void)highlightWord
{
size_t endMeas = fMeasure;
VLFraction endAt = fAt;
if (!fSong->NextWord(fStanza, endMeas, endAt))
endMeas = 1000;
[fView highlightTextInStanza:fStanza startMeasure:fMeasure at:fAt endMeasure:endMeas at:endAt];
std::string word = fSong->GetWord(fStanza, fMeasure, fAt);
VLLocation end = fSelection;
if (!fSong->NextWord(fStanza, end))
end.fMeasure = 1000;
[fView highlightTextInStanza:fStanza start:fSelection end:end];
std::string word = fSong->GetWord(fStanza, fSelection);
fText = [[NSString alloc] initWithUTF8String:word.c_str()];
}
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
song:(VLSong *)song
stanza:(int)stanza
measure:(int)measure
at:(VLFract)at
at:(VLLocation)at
{
self = [super init];
fView = view;
fSong = song;
fStanza = stanza;
fMeasure = measure;
fAt = at;
fAnchorMeas = measure;
fAnchorAt = at;
fNextMeas = fMeasure;
fNextAt = fAt;
fSelection = at;
fAnchor = at;
fNext = at;
VLFraction At = fAt;
fSong->FindWord(fStanza, fMeasure, At);
fAt = At;
fSong->FindWord(fStanza, fSelection);
[self highlightWord];
return self;
@ -67,7 +60,7 @@
- (void) setStringValue:(NSString *)val
{
[[fView document] willChangeSong];
fSong->SetWord(fStanza, fMeasure, fAt, val ? [val UTF8String] : "", &fNextMeas, &fNextAt);
fSong->SetWord(fStanza, fSelection, val ? [val UTF8String] : "", &fNext);
[[fView document] didChangeSong];
}
@ -78,46 +71,38 @@
- (void) moveToNext
{
if (fNextMeas != fMeasure || fNextAt != fAt) {
fMeasure = fNextMeas;
VLFraction at = fNextAt;
fSong->FindWord(fStanza, fMeasure, at);
fAt = at;
if (fNext != fSelection) {
fSelection = fNext;
fSong->FindWord(fStanza, fSelection);
} else {
VLFraction at = fAt;
if (!fSong->NextWord(fStanza, fMeasure, at)) {
fMeasure = 0;
at = 0;
fSong->FindWord(fStanza, fMeasure, at);
if (!fSong->NextWord(fStanza, fSelection)) {
fSelection.fMeasure = 0;
fSelection.fAt = VLFraction(0);
fSong->FindWord(fStanza, fSelection);
}
fAt = at;
}
fNextMeas = fMeasure;
fNextAt = fAt;
fNext = fSelection;
[self highlightWord];
[fView scrollMeasureToVisible:fMeasure];
[fView scrollMeasureToVisible:fSelection.fMeasure];
}
- (void) moveToPrev
{
VLFraction at = fAt;
if (!fSong->PrevWord(fStanza, fMeasure, at)) {
fMeasure = fSong->CountMeasures()-1;
at = fSong->Properties(fMeasure).fTime;
fSong->PrevWord(fStanza, fMeasure, at);
if (!fSong->PrevWord(fStanza, fSelection)) {
fSelection.fMeasure = fSong->CountMeasures()-1;
fSelection.fAt = fSong->Properties(fSelection.fMeasure).fTime;
fSong->PrevWord(fStanza, fSelection);
}
fAt = at;
fNextMeas = fMeasure;
fNextAt = fAt;
fNext = fSelection;
[self highlightWord];
[fView scrollMeasureToVisible:fMeasure];
[fView scrollMeasureToVisible:fSelection.fMeasure];
}
- (void) highlightCursor
{
std::string word = fSong->GetWord(fStanza, fMeasure, fAt);
std::string word = fSong->GetWord(fStanza, fSelection);
if (!word.size())
[fView highlightLyricsInStanza:fStanza measure:fMeasure at:fAt];
[fView highlightLyricsInStanza:fStanza at:fSelection];
}
- (BOOL)canExtendSelection:(VLRegion)region
@ -125,40 +110,33 @@
return region == kRegionLyrics;
}
- (void)extendSelection:(size_t)measure at:(VLFract)At
- (void)extendSelection:(VLLocation)at
{
VLFraction at = At;
if (!fSong->FindWord(fStanza, measure, at))
if (!fSong->FindWord(fStanza, at))
return;
if (measure < fAnchorMeas || (measure==fAnchorMeas && at < fAnchorAt)) {
if (at < fAnchor) {
//
// Backward from anchor
//
fMeasure = measure;
fAt = at;
measure = fAnchorMeas;
at = fAnchorAt;
fSelection = at;
at = fAnchor;
} else {
//
// Forward from anchor
//
fMeasure = fAnchorMeas;
at = fAnchorAt;
fSong->FindWord(fStanza, fMeasure, at);
fAt = at;
at = At;
fSelection = fAnchor;
fSong->FindWord(fStanza, fSelection);
}
if (!fSong->NextWord(fStanza, measure, at))
measure = 1000;
[fView highlightTextInStanza:fStanza startMeasure:fMeasure at:fAt endMeasure:measure at:at];
if (!fSong->NextWord(fStanza, at))
at.fMeasure = 1000;
[fView highlightTextInStanza:fStanza start:fSelection end:at];
std::string text;
size_t textMeas = fMeasure;
VLFraction textAt = fAt;
while (textMeas < measure || (textMeas == measure && textAt < at)) {
VLLocation textAt = fSelection;
while (textAt < at) {
if (text.size())
text += ' ';
text += fSong->GetWord(fStanza, textMeas, textAt);
fSong->NextWord(fStanza, textMeas, textAt);
text += fSong->GetWord(fStanza, textAt);
fSong->NextWord(fStanza, textAt);
}
[fText release];
fText = [[NSString alloc] initWithUTF8String:text.c_str()];
@ -236,7 +214,7 @@ float VLCocoaFontHandler::Width(const char * utf8Text)
break;
const VLMeasure measure = song->fMeasures[measIdx];
const VLNoteList & notes = measure.fMelody;
VLFraction at(0);
VLLocation at = {measIdx, VLFraction(0)};
for (VLNoteList::const_iterator note = notes.begin();
note != notes.end();
++note
@ -247,18 +225,15 @@ float VLCocoaFontHandler::Width(const char * utf8Text)
;
} else {
bool highlight = stanza == fHighlightStanza
&& (measIdx > fHighlightStartMeasure
|| (measIdx == fHighlightStartMeasure && at >= fHighlightStartAt))
&& (measIdx < fHighlightEndMeasure
|| (measIdx == fHighlightEndMeasure && at < fHighlightEndAt));
&& at >= fHighlightStart && at < fHighlightEnd;
if (highlight && !sHighlightColor)
sHighlightColor = [[self textBackgroundColorForSystem:system] shadowWithLevel:0.2];
text.AddSyllable(note->fLyrics[stanza-1],
[self noteXInMeasure:measIdx at:at],
[self noteXAt:at],
highlight);
}
at += note->fDuration;
at.fAt = at.fAt+note->fDuration;
}
}
@ -273,30 +248,26 @@ float VLCocoaFontHandler::Width(const char * utf8Text)
initWithView:self
song:[self song]
stanza:fCursorStanza
measure:fCursorMeasure
at:fCursorAt];
at:fCursorLocation];
[self setEditTarget:e];
[fFieldEditor selectText:self];
}
- (void) highlightLyricsInStanza:(size_t)stanza measure:(int)measure at:(VLFraction)at
- (void) highlightLyricsInStanza:(size_t)stanza at:(VLLocation)at
{
const float kSystemY = [self systemY:fLayout->SystemForMeasure(measure)];
const float kSystemY = [self systemY:fLayout->SystemForMeasure(at.fMeasure)];
NSRect r =
NSMakeRect([self noteXInMeasure:measure at:at]-kNoteW*0.5f,
NSMakeRect([self noteXAt:at]-kNoteW*0.5f,
kSystemY+kLyricsY-stanza*kLyricsH, kNoteW, kLyricsH);
[[NSColor colorWithCalibratedWhite:0.8f alpha:1.0f] setFill];
NSRectFillUsingOperation(r, NSCompositePlusDarker);
}
- (void) highlightTextInStanza:(size_t)stanza startMeasure:(int)startMeasure at:(VLFraction)startAt
endMeasure:(int)endMeasure at:(VLFraction)endAt
- (void) highlightTextInStanza:(size_t)stanza start:(VLLocation)start end:(VLLocation)end
{
fHighlightStanza = stanza;
fHighlightStartMeasure = startMeasure;
fHighlightStartAt = startAt;
fHighlightEndMeasure = endMeasure;
fHighlightEndAt = endAt;
fHighlightStanza = stanza;
fHighlightStart = start;
fHighlightEnd = end;
[self setNeedsDisplay:YES];
}

View File

@ -14,7 +14,7 @@
- (void) drawNotesForSystem:(int)system;
- (void) addNoteAtCursor;
- (void) drawNoteCursor:(int)vertPos inMeasure:(size_t)measure at:(VLFract)at visual:(uint16_t)visual;
- (void) drawNoteCursor:(int)vertPos at:(VLLocation)at visual:(uint16_t)visual;
@end

View File

@ -21,20 +21,20 @@
- (void) addNoteAtCursor
{
if (fCursorMeasure > -1 && fCursorVertPos != kCursorNoPitch) {
if (fCursorLocation.fMeasure > -1 && fCursorVertPos != kCursorNoPitch) {
[[self document] willChangeSong];
if (fCursorVisual == kCursorExtend) {
VLNote oldNote = [self song]->ExtendNote(fCursorMeasure, fCursorAt);
VLNote oldNote = [self song]->ExtendNote(fCursorLocation);
VLSoundOut::Instance()->PlayNote(oldNote);
} else if (fClickMode == 'k') {
[self song]->DelNote(fCursorMeasure, fCursorAt);
[self song]->DelNote(fCursorLocation);
} else {
int pitch = VLNote::kNoPitch;
if (fClickMode == ' ')
pitch = VLGridToPitch(fCursorVertPos, fCursorVisual,
[self song]->Properties(fCursorMeasure).fKey);
[self song]->Properties(fCursorLocation.fMeasure).fKey);
VLNote newNote(1, pitch, fCursorVisual & ~kCursorFlagsMask);
[self song]->AddNote(VLLyricsNote(newNote), fCursorMeasure, fCursorAt);
[self song]->AddNote(VLLyricsNote(newNote), fCursorLocation);
VLSoundOut::Instance()->PlayNote(newNote);
}
fClickMode = ' ';
@ -68,7 +68,7 @@
[self drawLedgerLines:[self gridInSection:section withPitch:pitch visual:visual] at:p];
}
- (void) drawNoteCursor:(int)vertPos inMeasure:(size_t)measure at:(VLFract)at
- (void) drawNoteCursor:(int)vertPos at:(VLLocation)at
visual:(uint16_t)visual mode:(char)mode
{
int cursorX;
@ -76,24 +76,24 @@
VLMusicElement cursorElt;
VLMusicElement accidental = mode ? [self accidentalForVisual:visual] : kMusicNothing;
cursorX = [self noteXInMeasure:measure at:at];
cursorX = [self noteXAt:at];
if (visual == kCursorExtend) {
cursorY = [self noteYInMeasure:measure withGrid:vertPos];
cursorY = [self noteYInMeasure:at.fMeasure withGrid:vertPos];
cursorElt = kMusicExtendCursor;
} else {
switch (mode) {
default:
cursorY = [self noteYInMeasure:measure withGrid:vertPos] - kNoteY;
cursorY = [self noteYInMeasure:at.fMeasure withGrid:vertPos] - kNoteY;
[self drawLedgerLines:vertPos at:NSMakePoint(cursorX,
[self systemY:fLayout->SystemForMeasure(measure)])];
[self systemY:fLayout->SystemForMeasure(at.fMeasure)])];
cursorElt = kMusicNoteCursor;
break;
case 'r':
cursorY = [self noteYInMeasure:measure withGrid:3];
cursorY = [self noteYInMeasure:at.fMeasure withGrid:3];
cursorElt = kMusicRestCursor;
break;
case 'k':
cursorY = [self noteYInMeasure:measure withGrid:vertPos] - kNoteY;
cursorY = [self noteYInMeasure:at.fMeasure withGrid:vertPos] - kNoteY;
cursorElt = kMusicKillCursor;
break;
}
@ -135,15 +135,14 @@
}
}
- (void) drawNoteCursor:(int)vertPos inMeasure:(size_t)measure at:(VLFract)at visual:(uint16_t)visual
- (void) drawNoteCursor:(int)vertPos at:(VLLocation)at visual:(uint16_t)visual
{
[self drawNoteCursor:vertPos inMeasure:measure at:at visual:visual mode:0];
[self drawNoteCursor:vertPos at:at visual:visual mode:0];
}
- (void) drawNoteCursor
{
[self drawNoteCursor:fCursorVertPos inMeasure:fCursorMeasure at:fCursorAt
visual:fCursorVisual mode:fClickMode];
[self drawNoteCursor:fCursorVertPos at:fCursorLocation visual:fCursorVisual mode:fClickMode];
}
- (void) drawNote:(int)visual at:(NSPoint)p
@ -337,7 +336,7 @@
const VLMeasure & measure = song->fMeasures[measIdx];
VLNoteList melody;
measure.DecomposeNotes(kProp, melody);
VLFraction at(0);
VLLocation at = {measIdx, VLFraction(0)};
float tupletStartX;
float tupletEndX;
CGFloat tupletY;
@ -356,11 +355,11 @@
if (pitch != VLNote::kNoPitch) {
[self drawLedgerLinesInSection:measure.fPropIdx withPitch:pitch
visual:note->fVisual
at:NSMakePoint([self noteXInMeasure:measIdx at:at],
at:NSMakePoint([self noteXAt:at],
kSystemY)];
uint16_t visual = VLPitchAccidental(note->fPitch, note->fVisual, kProp.fKey);
pos =
NSMakePoint([self noteXInMeasure:measIdx at:at],
NSMakePoint([self noteXAt:at],
kSystemY+[self noteYInSection:measure.fPropIdx
withPitch:pitch visual:&visual]);
int step = [self gridInSection:measure.fPropIdx
@ -370,7 +369,7 @@
accidental:[self accidentalForVisual:filterVisuals(step, visual)]
tied:tied];
} else {
pos = NSMakePoint([self noteXInMeasure:measIdx at:at],
pos = NSMakePoint([self noteXAt:at],
kSystemY+[self noteYInSection:measure.fPropIdx withPitch:65]);
[self drawRest:note->fVisual & VLNote::kNoteHeadMask at: pos];
}
@ -403,12 +402,12 @@
inTuplet = 0;
}
at += note->fDuration;
at.fAt = at.fAt+note->fDuration;
}
if (inTuplet)
[self drawTuplet:tuplet bracketFrom:tupletStartX to:tupletEndX atY:tupletY];
}
if (fCursorRegion == kRegionNote && fLayout->SystemForMeasure(fCursorMeasure) == system)
if (fCursorRegion == kRegionNote && fLayout->SystemForMeasure(fCursorLocation.fMeasure) == system)
[self drawNoteCursor];
}

View File

@ -21,12 +21,10 @@
@interface VLPlaybackEditable : VLEditable {
VLSheetView * fView;
size_t fStanza;
size_t fNoteMeasure;
VLFract fNoteAt;
VLLocation fNote;
int fNoteVert;
uint16_t fNoteVisual;
size_t fChordMeasure;
VLFract fChordAt;
VLLocation fChord;
}
- (VLPlaybackEditable *)initWithView:(VLSheetView *)view;
@ -42,8 +40,8 @@
{
fView = view;
fStanza = 1;
fNoteMeasure = 0x80000000;
fChordMeasure = 0x80000000;
fNote.fMeasure = 0x80000000;
fChord.fMeasure = 0x80000000;
return self;
}
@ -51,31 +49,29 @@
- (void) userEvent:(const VLMIDIUserEvent *) event
{
if (event->fPitch) {
fNoteMeasure = event->fMeasure;
fNoteAt = event->fAt;
fNote = event->fAt;
fNoteVisual = event->fVisual & VLNote::kAccidentalsMask;
if (event->fPitch == VLNote::kNoPitch)
fNoteVert = kCursorNoPitch;
else
fNoteVert = VLPitchToGrid(event->fPitch, fNoteVisual, [fView song]->Properties(fNoteMeasure).fKey);
fNoteVert = VLPitchToGrid(event->fPitch, fNoteVisual, [fView song]->Properties(fNote.fMeasure).fKey);
fStanza = event->fStanza;
VLFraction endAt= fNoteAt+VLFraction(1,128);
[fView highlightTextInStanza:fStanza startMeasure:fNoteMeasure at:fNoteAt
endMeasure:fNoteMeasure at:endAt];
VLLocation end = fNote;
end.fAt = end.fAt+VLFraction(1,128);
[fView highlightTextInStanza:fStanza start:fNote end:end];
} else {
fChordMeasure = event->fMeasure;
fChordAt = event->fAt;
fChord = event->fAt;
}
[fView scrollMeasureToVisible:event->fMeasure+1];
[fView scrollMeasureToVisible:event->fAt.fMeasure+1];
[fView setNeedsDisplay:YES];
}
- (void) highlightCursor
{
if (fNoteMeasure != 0x80000000 && fNoteVert != kCursorNoPitch)
[fView drawNoteCursor:fNoteVert inMeasure:fNoteMeasure at:fNoteAt visual:fNoteVisual];
if (fChordMeasure != 0x80000000)
[fView highlightChordInMeasure:fChordMeasure at:fChordAt];
if (fNote.fMeasure != 0x80000000 && fNoteVert != kCursorNoPitch)
[fView drawNoteCursor:fNoteVert at:fNote visual:fNoteVisual];
if (fChord.fMeasure != 0x80000000)
[fView highlightChord:fChord];
}
- (BOOL) hidden
@ -120,12 +116,12 @@ VLSequenceCallback(
- (void)editSelection:(BOOL)extend
{
if (extend && fSelEnd > -1) {
if (fCursorMeasure > fSelEnd)
fSelEnd = fCursorMeasure;
else if (fCursorMeasure < fSelStart)
fSelStart = fCursorMeasure;
if (fCursorLocation.fMeasure > fSelEnd)
fSelEnd = fCursorLocation.fMeasure;
else if (fCursorLocation.fMeasure < fSelStart)
fSelStart = fCursorLocation.fMeasure;
} else {
fSelStart = fSelEnd = fSelAnchor = fCursorMeasure;
fSelStart = fSelEnd = fSelAnchor = fCursorLocation.fMeasure;
}
[self updateMenus];
[self setNeedsDisplay:YES];
@ -137,21 +133,21 @@ VLSequenceCallback(
case kRegionNote:
case kRegionChord:
case kRegionLyrics:
if (fCursorAt.fNum > 0 && fCursorMeasure >= fSelAnchor)
++fCursorMeasure;
if (fCursorLocation.fAt.fNum > 0 && fCursorLocation.fMeasure >= fSelAnchor)
++fCursorLocation.fMeasure;
//
// Fall through
//
case kRegionMeasure:
fCursorMeasure =
std::max(0, std::min<int>(fCursorMeasure, [self song]->CountMeasures()));
if (fCursorMeasure >= fSelAnchor) {
fCursorLocation.fMeasure =
std::max(0, std::min<int>(fCursorLocation.fMeasure, [self song]->CountMeasures()));
if (fCursorLocation.fMeasure >= fSelAnchor) {
fSelStart = fSelAnchor;
fSelEnd = fCursorMeasure;
fSelEnd = fCursorLocation.fMeasure;
[self updateMenus];
[self setNeedsDisplay:YES];
} else {
fSelStart = fCursorMeasure;
fSelStart = fCursorLocation.fMeasure;
fSelEnd = fSelAnchor;
[self updateMenus];
[self setNeedsDisplay:YES];

View File

@ -23,7 +23,7 @@
- (void) moveToPrev;
- (void) highlightCursor;
- (BOOL) canExtendSelection:(VLRegion)region;
- (void) extendSelection:(size_t)measure at:(VLFract)at;
- (void) extendSelection:(VLLocation)at;
- (BOOL) hidden;
@end

View File

@ -49,7 +49,7 @@
return NO;
}
- (void)extendSelection:(size_t)measure at:(VLFract)at
- (void)extendSelection:(VLLocation)at
{
}
@ -132,14 +132,14 @@
- (IBAction) togglePlayElements:(id)sender
{
[[self document] setPlayElements:[[self document] playElements] ^ [sender tag]];
[[self document] setPlayElements:[[self document] playElements] ^ (int)[sender tag]];
}
- (BOOL) validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
{
if ([item action] == @selector(togglePlayElements:)) {
NSMenuItem * menuItem = (NSMenuItem *)item;
if (int tag = [item tag])
if (NSInteger tag = [item tag])
[menuItem setState:([[self document] playElements] & tag) != 0];
} else if ([item action] == @selector(playStop:)) {
NSMenuItem * menuItem = [(NSObject *)item isKindOfClass:[NSMenuItem class]] ? (NSMenuItem *)item : nil;