mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14:00 +00:00
Reorganize locations to use VLLocation
This commit is contained in:
parent
8a30706b8c
commit
ddc7b4d923
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,12 +1402,9 @@ 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->fAt = now;
|
||||||
nextAt = 0;
|
nextAt = 0;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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, ×))
|
if (fSong->DoesEndRepeat(m+1, ×))
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user