mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 03:04:00 +00:00
Reorganize locations to use VLLocation
This commit is contained in:
parent
8a30706b8c
commit
ddc7b4d923
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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,12 +1402,9 @@ 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->fMeasure = at.fMeasure;
|
||||
nextAt->fAt = now;
|
||||
nextAt = 0;
|
||||
}
|
||||
//
|
||||
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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, ×))
|
||||
|
@ -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);
|
||||
VLLocation at = {measNo, VLFraction(0)};
|
||||
int lastOnset = 0;
|
||||
VLFraction tiedStart(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
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)) {
|
||||
if (fSelection.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];
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
fHighlightStart = start;
|
||||
fHighlightEnd = end;
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user