mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 19:23:59 +00:00
Edit lyrics
This commit is contained in:
parent
d32906f0bb
commit
afe4f8078d
|
@ -1160,7 +1160,6 @@ bool VLSong::NextWord(size_t stanza, size_t & measure, VLFraction & at)
|
|||
VLNoteList::iterator note = fMeasures[measure].fMelody.begin();
|
||||
VLNoteList::iterator end = fMeasures[measure].fMelody.end();
|
||||
bool hasWord = false;
|
||||
VLFraction word(0);
|
||||
VLFraction now(0);
|
||||
|
||||
while (note != meas.fMelody.end()) {
|
||||
|
@ -1168,20 +1167,92 @@ bool VLSong::NextWord(size_t stanza, size_t & measure, VLFraction & at)
|
|||
if (note->fLyrics.size() < stanza
|
||||
|| !(note->fLyrics[stanza-1].fKind & VLSyllable::kHasPrev)
|
||||
) {
|
||||
word = now;
|
||||
hasWord = true;
|
||||
at = now;
|
||||
|
||||
return true;
|
||||
}
|
||||
now += note->fDuration;
|
||||
++note;
|
||||
}
|
||||
if (hasWord) {
|
||||
at = word;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
firstMeasure = false;
|
||||
}
|
||||
firstMeasure = false;
|
||||
} while (++measure < fMeasures.size());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string VLSong::GetWord(size_t stanza, size_t measure, VLFraction at)
|
||||
{
|
||||
std::string word;
|
||||
|
||||
do {
|
||||
VLMeasure & meas = fMeasures[measure];
|
||||
VLNoteList::iterator note = fMeasures[measure].fMelody.begin();
|
||||
VLNoteList::iterator end = fMeasures[measure].fMelody.end();
|
||||
VLFraction now(0);
|
||||
|
||||
while (note != meas.fMelody.end()) {
|
||||
if (now >= at && note->fPitch != VLNote::kNoPitch) {
|
||||
if (word.size())
|
||||
word += '-';
|
||||
if (stanza <= note->fLyrics.size()) {
|
||||
word += note->fLyrics[stanza-1].fText;
|
||||
if (!(note->fLyrics[stanza-1].fKind & VLSyllable::kHasNext))
|
||||
return word;
|
||||
}
|
||||
}
|
||||
now += note->fDuration;
|
||||
++note;
|
||||
}
|
||||
at = 0;
|
||||
} while (++measure < fMeasures.size());
|
||||
|
||||
return word;
|
||||
}
|
||||
|
||||
void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string word)
|
||||
{
|
||||
uint8_t kind = 0;
|
||||
bool cleanup = false;
|
||||
|
||||
do {
|
||||
VLMeasure & meas = fMeasures[measure];
|
||||
VLNoteList::iterator note = fMeasures[measure].fMelody.begin();
|
||||
VLNoteList::iterator end = fMeasures[measure].fMelody.end();
|
||||
VLFraction now(0);
|
||||
|
||||
while (note != meas.fMelody.end()) {
|
||||
if (now >= at && note->fPitch != VLNote::kNoPitch) {
|
||||
if (cleanup) {
|
||||
//
|
||||
// Make sure that following syllable doesn't have
|
||||
// kHasPrev set
|
||||
//
|
||||
if (note->fLyrics.size() >= stanza)
|
||||
note->fLyrics[stanza-1].fKind &= ~VLSyllable::kHasPrev;
|
||||
|
||||
return;
|
||||
}
|
||||
if (note->fLyrics.size()<stanza)
|
||||
note->fLyrics.resize(stanza);
|
||||
size_t root = word.find('-');
|
||||
std::string syll;
|
||||
if (root == std::string::npos) {
|
||||
syll = word;
|
||||
kind &= ~VLSyllable::kHasNext;
|
||||
cleanup = true;
|
||||
} else {
|
||||
syll = word.substr(0, root);
|
||||
word.erase(0, root+1);
|
||||
kind |= VLSyllable::kHasNext;
|
||||
}
|
||||
note->fLyrics[stanza-1].fText = syll;
|
||||
note->fLyrics[stanza-1].fKind = kind;
|
||||
kind |= VLSyllable::kHasPrev;
|
||||
}
|
||||
now += note->fDuration;
|
||||
++note;
|
||||
}
|
||||
at = 0;
|
||||
} while (++measure < fMeasures.size());
|
||||
}
|
||||
|
||||
|
|
|
@ -258,6 +258,8 @@ struct VLSong {
|
|||
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 CountMeasures() const { return fMeasures.size(); }
|
||||
size_t CountStanzas() const;
|
||||
|
|
|
@ -73,6 +73,7 @@ enum VLRecalc {
|
|||
int fCursorPitch;
|
||||
int fCursorActualPitch;
|
||||
VLMusicElement fCursorAccidental;
|
||||
size_t fCursorStanza;
|
||||
|
||||
IBOutlet id fFieldEditor;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#import "VLSheetViewInternal.h"
|
||||
#import "VLSheetViewChords.h"
|
||||
#import "VLSheetViewNotes.h"
|
||||
#import "VLSheetViewLyrics.h"
|
||||
#import "VLSoundOut.h"
|
||||
|
||||
#import "VLDocument.h"
|
||||
|
@ -597,6 +598,8 @@ static int8_t sSharpAcc[] = {
|
|||
fCursorAt = VLFraction(fCursorAt.fNum / scale, 4);
|
||||
return fCursorRegion = kRegionChord;
|
||||
} else if (loc.y < kSystemY+kLyricsY) {
|
||||
fCursorStanza = static_cast<size_t>((kSystemY+kLyricsY-loc.y) / kLyricsH)
|
||||
+ 1;
|
||||
return fCursorRegion = kRegionLyrics;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,14 +9,16 @@
|
|||
#import "VLSheetWindow.h"
|
||||
|
||||
@interface VLLyricsEditable : VLEditable {
|
||||
VLSheetView * fView;
|
||||
VLSong * fSong;
|
||||
int fMeasure;
|
||||
VLFract fAt;
|
||||
VLSheetView * fView;
|
||||
VLSong * fSong;
|
||||
size_t fStanza;
|
||||
size_t fMeasure;
|
||||
VLFraction fAt;
|
||||
}
|
||||
|
||||
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
||||
song:(VLSong *)song
|
||||
stanza:(int)stanza
|
||||
measure:(int)measure
|
||||
at:(VLFract)at;
|
||||
- (NSString *) stringValue;
|
||||
|
@ -32,7 +34,7 @@
|
|||
|
||||
- (void) editLyrics;
|
||||
- (void) drawLyricsForSystem:(int)system stanza:(size_t)stanza;
|
||||
- (void) highlightLyricsInMeasure:(int)measure at:(VLFraction)at stanza:(size_t)stanza;
|
||||
- (void) highlightLyricsInStanza:(size_t)stanza measure:(int)measure at:(VLFraction)at;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -17,15 +17,19 @@
|
|||
|
||||
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
||||
song:(VLSong *)song
|
||||
stanza:(int)stanza
|
||||
measure:(int)measure
|
||||
at:(VLFract)at
|
||||
{
|
||||
self = [super init];
|
||||
fView = view;
|
||||
fSong = song;
|
||||
fStanza = stanza;
|
||||
fMeasure= measure;
|
||||
fAt = at;
|
||||
|
||||
fSong->FindWord(fStanza, fMeasure, fAt);
|
||||
|
||||
[fView setNeedsDisplay: YES];
|
||||
|
||||
return self;
|
||||
|
@ -33,10 +37,13 @@
|
|||
|
||||
- (NSString *) stringValue
|
||||
{
|
||||
std::string word = fSong->GetWord(fStanza, fMeasure, fAt);
|
||||
return [NSString stringWithUTF8String:word.c_str()];
|
||||
}
|
||||
|
||||
- (void) setStringValue:(NSString *)val
|
||||
{
|
||||
fSong->SetWord(fStanza, fMeasure, fAt, [val UTF8String]);
|
||||
}
|
||||
|
||||
- (BOOL) validValue:(NSString *)val
|
||||
|
@ -46,15 +53,25 @@
|
|||
|
||||
- (void) moveToNext
|
||||
{
|
||||
if (!fSong->NextWord(fStanza, fMeasure, fAt)) {
|
||||
fMeasure = 0;
|
||||
fAt = 0;
|
||||
fSong->FindWord(fStanza, fMeasure, fAt);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) moveToPrev
|
||||
{
|
||||
if (!fSong->PrevWord(fStanza, fMeasure, fAt)) {
|
||||
fMeasure = fSong->CountMeasures()-1;
|
||||
fAt = fSong->fMeasures[fMeasure].fProperties->fTime;
|
||||
fSong->PrevWord(fStanza, fMeasure, fAt);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) highlightCursor
|
||||
{
|
||||
[fView highlightLyricsInMeasure:fMeasure at:fAt];
|
||||
[fView highlightLyricsInStanza:fStanza measure:fMeasure at:fAt];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -117,21 +134,15 @@
|
|||
[[VLLyricsEditable alloc]
|
||||
initWithView:self
|
||||
song:[self song]
|
||||
stanza:fCursorStanza
|
||||
measure:fCursorMeasure
|
||||
at:fCursorAt];
|
||||
[self setEditTarget:e];
|
||||
[fFieldEditor selectText:self];
|
||||
}
|
||||
|
||||
- (void) highlightLyricsInMeasure:(int)measure at:(VLFraction)at stanza:(size_t)stanza
|
||||
- (void) highlightLyricsInStanza:(size_t)stanza measure:(int)measure at:(VLFraction)at
|
||||
{
|
||||
const VLProperties & prop = [self song]->fProperties.front();
|
||||
const float kSystemY = [self systemY:measure / fMeasPerSystem];
|
||||
NSRect r =
|
||||
NSMakeRect([self noteXInMeasure:measure at:at]-kNoteW*0.5f,
|
||||
kSystemY+kChordY, prop.fDivisions*kNoteW, kChordH);
|
||||
[[NSColor colorWithCalibratedWhite:0.8f alpha:1.0f] setFill];
|
||||
NSRectFillUsingOperation(r, NSCompositePlusDarker);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue
Block a user