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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -96,7 +96,7 @@ void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
NSMutableDictionary * md = NSMutableDictionary * md =
[NSMutableDictionary dictionaryWithObjectsAndKeys: [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:m], @"measure", [NSNumber numberWithUnsignedInt:m], @"measure",
[NSNumber numberWithInt:meas.fPropIdx], @"properties", [NSNumber numberWithInt:meas.fPropIdx], @"properties",
fNotes, @"melody", fChords, @"chords", fNotes, @"melody", fChords, @"chords",
nil]; nil];
@ -112,7 +112,7 @@ void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
[md setObject: [md setObject:
[NSDictionary dictionaryWithObjectsAndKeys: [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:!last], @"last", [NSNumber numberWithBool:!last], @"last",
[NSNumber numberWithInt:volta], @"volta", [NSNumber numberWithUnsignedInt:volta], @"volta",
nil] nil]
forKey: @"begin-ending"]; forKey: @"begin-ending"];
if (fSong->DoesEndRepeat(m+1, &times)) if (fSong->DoesEndRepeat(m+1, &times))
@ -124,7 +124,7 @@ void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
[md setObject: [md setObject:
[NSDictionary dictionaryWithObjectsAndKeys: [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:!last], @"last", [NSNumber numberWithBool:!last], @"last",
[NSNumber numberWithInt:volta], @"volta", [NSNumber numberWithUnsignedInt:volta], @"volta",
nil] nil]
forKey: @"end-ending"]; forKey: @"end-ending"];
if (fSong->fGoToCoda == m+1) 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 - (void)readMelody:(NSArray *)melody inMeasure:(size_t)measNo onsets:(int *)onsets lyrics:(uint8_t *)prevKind
{ {
VLFraction at(0); VLLocation at = {measNo, VLFraction(0)};
int lastOnset = 0; int lastOnset = 0;
VLFraction tiedStart(0); VLLocation tiedStart = {measNo, VLFraction(0)};
VLLyricsNote tiedNote; VLLyricsNote tiedNote;
for (NSEnumerator * ne = [melody objectEnumerator]; for (NSEnumerator * ne = [melody objectEnumerator];
@ -328,13 +328,13 @@ enum {
[[ndict objectForKey:@"normalNotes"] intValue]); [[ndict objectForKey:@"normalNotes"] intValue]);
if ([[ndict objectForKey:@"tied"] intValue] & VLNote::kTiedWithPrev) { if ([[ndict objectForKey:@"tied"] intValue] & VLNote::kTiedWithPrev) {
if (at != 0) { if (at.fAt != VLFraction(0)) {
// //
// Extend preceding note // Extend preceding note
// //
tiedNote.fDuration += note.fDuration; tiedNote.fDuration += note.fDuration;
song->DelNote(measNo, tiedStart); song->DelNote(tiedStart);
song->AddNote(tiedNote, measNo, tiedStart); song->AddNote(tiedNote, tiedStart);
goto advanceAt; goto advanceAt;
} else { } else {
@ -376,10 +376,10 @@ enum {
tiedStart = at; tiedStart = at;
tiedNote = note; tiedNote = note;
song->AddNote(note, measNo, at); song->AddNote(note, at);
if (!(note.fTied & VLNote::kTiedWithPrev)) { 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; int onset = inQuarter.fNum * 48 / inQuarter.fDenom;
++onsets[onset]; ++onsets[onset];
switch (onset) { switch (onset) {
@ -398,13 +398,13 @@ enum {
} }
} }
advanceAt: advanceAt:
at += note.fDuration; at.fAt = at.fAt + note.fDuration;
} }
} }
- (void)readChords:(NSArray *)chords inMeasure:(size_t)measNo - (void)readChords:(NSArray *)chords inMeasure:(size_t)measNo
{ {
VLFraction at(0); VLLocation at = {measNo, VLFraction(0)};
for (NSEnumerator * ce = [chords objectEnumerator]; for (NSEnumerator * ce = [chords objectEnumerator];
NSDictionary * cdict = [ce nextObject]; NSDictionary * cdict = [ce nextObject];
@ -420,9 +420,9 @@ advanceAt:
chord.fRootAccidental = [[cdict objectForKey:@"rootvisual"] intValue]; chord.fRootAccidental = [[cdict objectForKey:@"rootvisual"] intValue];
chord.fSteps = [[cdict objectForKey:@"steps"] 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; NSPoint fLastNoteCenter;
NSTrackingRectTag fCursorTracking; NSTrackingRectTag fCursorTracking;
VLRegion fCursorRegion; VLRegion fCursorRegion;
int fCursorMeasure; VLLocation fCursorLocation;
VLFract fCursorAt;
int fCursorVertPos; int fCursorVertPos;
uint16_t fCursorVisual; uint16_t fCursorVisual;
size_t fCursorStanza; size_t fCursorStanza;
@ -95,10 +94,8 @@ enum VLCursorVisual {
size_t fVolta; size_t fVolta;
size_t fVoltaOK; size_t fVoltaOK;
VLLayout * fLayout; VLLayout * fLayout;
int fHighlightStartMeasure; VLLocation fHighlightStart;
VLFract fHighlightStartAt; VLLocation fHighlightEnd;
int fHighlightEndMeasure;
VLFract fHighlightEndAt;
size_t fHighlightStanza; size_t fHighlightStanza;
VLKeyValueUndo * fUndo; VLKeyValueUndo * fUndo;
@ -138,7 +135,7 @@ enum VLCursorVisual {
- (float) noteYInSection:(int)section withPitch:(int)pitch; - (float) noteYInSection:(int)section withPitch:(int)pitch;
- (VLMusicElement)accidentalForVisual:(uint16_t)visual; - (VLMusicElement)accidentalForVisual:(uint16_t)visual;
- (float) noteYInMeasure:(int)measure withGrid:(int)vertPos; - (float) noteYInMeasure:(int)measure withGrid:(int)vertPos;
- (float) noteXInMeasure:(int)measure at:(VLFraction)at; - (float) noteXAt:(VLLocation)at;
- (void) needsRecalculation; - (void) needsRecalculation;
- (void) scrollMeasureToVisible:(int)measure; - (void) scrollMeasureToVisible:(int)measure;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@
- (void) drawNotesForSystem:(int)system; - (void) drawNotesForSystem:(int)system;
- (void) addNoteAtCursor; - (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 @end

View File

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

View File

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

View File

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

View File

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