mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-23 03:34:00 +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 note = fMeasures[measure].fMelody.begin();
|
||||||
VLNoteList::iterator end = fMeasures[measure].fMelody.end();
|
VLNoteList::iterator end = fMeasures[measure].fMelody.end();
|
||||||
bool hasWord = false;
|
bool hasWord = false;
|
||||||
VLFraction word(0);
|
|
||||||
VLFraction now(0);
|
VLFraction now(0);
|
||||||
|
|
||||||
while (note != meas.fMelody.end()) {
|
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
|
if (note->fLyrics.size() < stanza
|
||||||
|| !(note->fLyrics[stanza-1].fKind & VLSyllable::kHasPrev)
|
|| !(note->fLyrics[stanza-1].fKind & VLSyllable::kHasPrev)
|
||||||
) {
|
) {
|
||||||
word = now;
|
at = now;
|
||||||
hasWord = true;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
now += note->fDuration;
|
now += note->fDuration;
|
||||||
++note;
|
++note;
|
||||||
}
|
}
|
||||||
if (hasWord) {
|
|
||||||
at = word;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
firstMeasure = false;
|
firstMeasure = false;
|
||||||
}
|
|
||||||
} while (++measure < fMeasures.size());
|
} while (++measure < fMeasures.size());
|
||||||
|
|
||||||
return false;
|
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 FindWord(size_t stanza, size_t & measure, VLFraction & at);
|
||||||
bool PrevWord(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);
|
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 CountMeasures() const { return fMeasures.size(); }
|
||||||
size_t CountStanzas() const;
|
size_t CountStanzas() const;
|
||||||
|
|
|
@ -73,6 +73,7 @@ enum VLRecalc {
|
||||||
int fCursorPitch;
|
int fCursorPitch;
|
||||||
int fCursorActualPitch;
|
int fCursorActualPitch;
|
||||||
VLMusicElement fCursorAccidental;
|
VLMusicElement fCursorAccidental;
|
||||||
|
size_t fCursorStanza;
|
||||||
|
|
||||||
IBOutlet id fFieldEditor;
|
IBOutlet id fFieldEditor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#import "VLSheetViewInternal.h"
|
#import "VLSheetViewInternal.h"
|
||||||
#import "VLSheetViewChords.h"
|
#import "VLSheetViewChords.h"
|
||||||
#import "VLSheetViewNotes.h"
|
#import "VLSheetViewNotes.h"
|
||||||
|
#import "VLSheetViewLyrics.h"
|
||||||
#import "VLSoundOut.h"
|
#import "VLSoundOut.h"
|
||||||
|
|
||||||
#import "VLDocument.h"
|
#import "VLDocument.h"
|
||||||
|
@ -597,6 +598,8 @@ static int8_t sSharpAcc[] = {
|
||||||
fCursorAt = VLFraction(fCursorAt.fNum / scale, 4);
|
fCursorAt = VLFraction(fCursorAt.fNum / scale, 4);
|
||||||
return fCursorRegion = kRegionChord;
|
return fCursorRegion = kRegionChord;
|
||||||
} else if (loc.y < kSystemY+kLyricsY) {
|
} else if (loc.y < kSystemY+kLyricsY) {
|
||||||
|
fCursorStanza = static_cast<size_t>((kSystemY+kLyricsY-loc.y) / kLyricsH)
|
||||||
|
+ 1;
|
||||||
return fCursorRegion = kRegionLyrics;
|
return fCursorRegion = kRegionLyrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,14 @@
|
||||||
@interface VLLyricsEditable : VLEditable {
|
@interface VLLyricsEditable : VLEditable {
|
||||||
VLSheetView * fView;
|
VLSheetView * fView;
|
||||||
VLSong * fSong;
|
VLSong * fSong;
|
||||||
int fMeasure;
|
size_t fStanza;
|
||||||
VLFract fAt;
|
size_t fMeasure;
|
||||||
|
VLFraction fAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
||||||
song:(VLSong *)song
|
song:(VLSong *)song
|
||||||
|
stanza:(int)stanza
|
||||||
measure:(int)measure
|
measure:(int)measure
|
||||||
at:(VLFract)at;
|
at:(VLFract)at;
|
||||||
- (NSString *) stringValue;
|
- (NSString *) stringValue;
|
||||||
|
@ -32,7 +34,7 @@
|
||||||
|
|
||||||
- (void) editLyrics;
|
- (void) editLyrics;
|
||||||
- (void) drawLyricsForSystem:(int)system stanza:(size_t)stanza;
|
- (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
|
@end
|
||||||
|
|
||||||
|
|
|
@ -17,15 +17,19 @@
|
||||||
|
|
||||||
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
||||||
song:(VLSong *)song
|
song:(VLSong *)song
|
||||||
|
stanza:(int)stanza
|
||||||
measure:(int)measure
|
measure:(int)measure
|
||||||
at:(VLFract)at
|
at:(VLFract)at
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
fView = view;
|
fView = view;
|
||||||
fSong = song;
|
fSong = song;
|
||||||
|
fStanza = stanza;
|
||||||
fMeasure= measure;
|
fMeasure= measure;
|
||||||
fAt = at;
|
fAt = at;
|
||||||
|
|
||||||
|
fSong->FindWord(fStanza, fMeasure, fAt);
|
||||||
|
|
||||||
[fView setNeedsDisplay: YES];
|
[fView setNeedsDisplay: YES];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -33,10 +37,13 @@
|
||||||
|
|
||||||
- (NSString *) stringValue
|
- (NSString *) stringValue
|
||||||
{
|
{
|
||||||
|
std::string word = fSong->GetWord(fStanza, fMeasure, fAt);
|
||||||
|
return [NSString stringWithUTF8String:word.c_str()];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setStringValue:(NSString *)val
|
- (void) setStringValue:(NSString *)val
|
||||||
{
|
{
|
||||||
|
fSong->SetWord(fStanza, fMeasure, fAt, [val UTF8String]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) validValue:(NSString *)val
|
- (BOOL) validValue:(NSString *)val
|
||||||
|
@ -46,15 +53,25 @@
|
||||||
|
|
||||||
- (void) moveToNext
|
- (void) moveToNext
|
||||||
{
|
{
|
||||||
|
if (!fSong->NextWord(fStanza, fMeasure, fAt)) {
|
||||||
|
fMeasure = 0;
|
||||||
|
fAt = 0;
|
||||||
|
fSong->FindWord(fStanza, fMeasure, fAt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) moveToPrev
|
- (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
|
- (void) highlightCursor
|
||||||
{
|
{
|
||||||
[fView highlightLyricsInMeasure:fMeasure at:fAt];
|
[fView highlightLyricsInStanza:fStanza measure:fMeasure at:fAt];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -117,21 +134,15 @@
|
||||||
[[VLLyricsEditable alloc]
|
[[VLLyricsEditable alloc]
|
||||||
initWithView:self
|
initWithView:self
|
||||||
song:[self song]
|
song:[self song]
|
||||||
|
stanza:fCursorStanza
|
||||||
measure:fCursorMeasure
|
measure:fCursorMeasure
|
||||||
at:fCursorAt];
|
at:fCursorAt];
|
||||||
[self setEditTarget:e];
|
[self setEditTarget:e];
|
||||||
[fFieldEditor selectText:self];
|
[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
|
@end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user