Display lyrics

This commit is contained in:
Matthias Neeracher 2006-12-02 03:35:21 +00:00
parent c832f4cca3
commit d32906f0bb
7 changed files with 216 additions and 34 deletions

View File

@ -1113,16 +1113,14 @@ void VLSong::LilypondStanza(std::string & lyrics, size_t stanza) const
} }
} }
bool VLSong::FindWord(size_t & measure, VLFraction & at) bool VLSong::FindWord(size_t stanza, size_t & measure, VLFraction & at)
{ {
at += VLFraction(1,64); at += VLFraction(1,64);
return PrevWord(stanza, measure, at);
return PrevWord(measure, at);
} }
bool VLSong::PrevWord(size_t & measure, VLFraction & at) bool VLSong::PrevWord(size_t stanza, size_t & measure, VLFraction & at)
{ {
#if 0
do { do {
VLMeasure & meas = fMeasures[measure]; VLMeasure & meas = fMeasures[measure];
VLNoteList::iterator note = fMeasures[measure].fMelody.begin(); VLNoteList::iterator note = fMeasures[measure].fMelody.begin();
@ -1131,17 +1129,16 @@ bool VLSong::PrevWord(size_t & measure, VLFraction & at)
VLFraction word(0); VLFraction word(0);
VLFraction now(0); VLFraction now(0);
for (VLNoteList::iterator note = meas.fMelody.begin(); while (note != meas.fMelody.end() && now < at) {
note != meas.fMelody.end() && now < at; if (note->fPitch != VLNote::kNoPitch)
++note if (note->fLyrics.size() < stanza
) { || !(note->fLyrics[stanza-1].fKind & VLSyllable::kHasPrev)
if (!(note->fTied & VLNote::kTiedWithPrev) ) {
&& !(note->fHyphen & VLNote::kHyphenToPrev) word = now;
) { hasWord = true;
word = now; }
hasWord = true;
}
now += note->fDuration; now += note->fDuration;
++note;
} }
if (hasWord) { if (hasWord) {
at = word; at = word;
@ -1151,14 +1148,12 @@ bool VLSong::PrevWord(size_t & measure, VLFraction & at)
at = meas.fProperties->fTime; at = meas.fProperties->fTime;
} }
} while (measure-- > 0); } while (measure-- > 0);
#endif
return false; return false;
} }
bool VLSong::NextWord(size_t & measure, VLFraction & at) bool VLSong::NextWord(size_t stanza, size_t & measure, VLFraction & at)
{ {
#if 0
bool firstMeasure = true; bool firstMeasure = true;
do { do {
VLMeasure & meas = fMeasures[measure]; VLMeasure & meas = fMeasures[measure];
@ -1168,18 +1163,16 @@ bool VLSong::NextWord(size_t & measure, VLFraction & at)
VLFraction word(0); VLFraction word(0);
VLFraction now(0); VLFraction now(0);
for (VLNoteList::iterator note = meas.fMelody.begin(); while (note != meas.fMelody.end()) {
note != meas.fMelody.end(); if (note->fPitch != VLNote::kNoPitch && (!firstMeasure || now>at))
++note if (note->fLyrics.size() < stanza
) { || !(note->fLyrics[stanza-1].fKind & VLSyllable::kHasPrev)
if (!(note->fTied & VLNote::kTiedWithPrev) ) {
&& !(note->fHyphen & VLNote::kHyphenToPrev) word = now;
&& (!firstMeasure || now > at) hasWord = true;
) { }
word = now;
hasWord = true;
}
now += note->fDuration; now += note->fDuration;
++note;
} }
if (hasWord) { if (hasWord) {
at = word; at = word;
@ -1189,7 +1182,6 @@ bool VLSong::NextWord(size_t & measure, VLFraction & at)
firstMeasure = false; firstMeasure = false;
} }
} while (++measure < fMeasures.size()); } while (++measure < fMeasures.size());
#endif
return false; return false;
} }

View File

@ -255,9 +255,9 @@ struct VLSong {
void DelNote(size_t measure, VLFraction at); void DelNote(size_t measure, VLFraction at);
void Transpose(int semitones); void Transpose(int semitones);
bool FindWord(size_t & measure, VLFraction & at); bool FindWord(size_t stanza, size_t & measure, VLFraction & at);
bool PrevWord(size_t & measure, VLFraction & at); bool PrevWord(size_t stanza, size_t & measure, VLFraction & at);
bool NextWord(size_t & measure, VLFraction & at); bool NextWord(size_t stanza, size_t & measure, VLFraction & at);
size_t CountMeasures() const { return fMeasures.size(); } size_t CountMeasures() const { return fMeasures.size(); }
size_t CountStanzas() const; size_t CountStanzas() const;

View File

@ -388,6 +388,7 @@ VLMusicElement sSemi2Accidental[12][12] = {
if (fNeedsRecalc) if (fNeedsRecalc)
[self recalculateDimensions]; [self recalculateDimensions];
size_t stanzas = [self song]->CountStanzas();
const float kLineW = fClefKeyW + fMeasPerSystem*fMeasureW; const float kLineW = fClefKeyW + fMeasPerSystem*fMeasureW;
for (int system = 0; system<fNumSystems; ++system) { for (int system = 0; system<fNumSystems; ++system) {
const float kSystemY = [self systemY:system]; const float kSystemY = [self systemY:system];
@ -399,6 +400,8 @@ VLMusicElement sSemi2Accidental[12][12] = {
[self drawGridForSystem:system]; [self drawGridForSystem:system];
[self drawNotesForSystem:system]; [self drawNotesForSystem:system];
[self drawChordsForSystem:system]; [self drawChordsForSystem:system];
for (size_t stanza=0; stanza++<stanzas;)
[self drawLyricsForSystem:system stanza:stanza];
} }
[[self editTarget] highlightCursor]; [[self editTarget] highlightCursor];
} }

View File

@ -9,7 +9,7 @@
const float kLineX = 5.0; const float kLineX = 5.0;
const float kLineH = 10.0; const float kLineH = 10.0;
const float kSystemH = 15.0f*kLineH; const float kSystemH = 15.0f*kLineH;
const float kSystemY = 3.0f*kLineH; const float kSystemY = 5.0f*kLineH;
const float kClefX = 20.5f; const float kClefX = 20.5f;
const float kClefY =-15.0f; const float kClefY =-15.0f;
const float kClefW = 30.0f; const float kClefW = 30.0f;
@ -29,6 +29,7 @@ const float kChordY = 7.0f*kLineH;
const float kChordW = 40.0f; const float kChordW = 40.0f;
const float kChordH = 25.0f; const float kChordH = 25.0f;
const float kLyricsY = -3.0*kLineH; const float kLyricsY = -3.0*kLineH;
const float kLyricsH = 1.5*kLineH;
const float kNoteX = 7.0f; const float kNoteX = 7.0f;
const float kNoteY = 5.0f; const float kNoteY = 5.0f;
const float kStemX = 0.0f; const float kStemX = 0.0f;

View File

@ -0,0 +1,41 @@
//
// VLSheetViewLyrics.h
// Vocalese
//
// Created by Matthias Neeracher on 1/4/06.
// Copyright 2006 __MyCompanyName__. All rights reserved.
//
#import "VLSheetWindow.h"
@interface VLLyricsEditable : VLEditable {
VLSheetView * fView;
VLSong * fSong;
int fMeasure;
VLFract fAt;
}
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
song:(VLSong *)song
measure:(int)measure
at:(VLFract)at;
- (NSString *) stringValue;
- (void) setStringValue:(NSString*)val;
- (BOOL) validValue:(NSString*)val;
- (void) moveToNext;
- (void) moveToPrev;
- (void) highlightCursor;
@end
@interface VLSheetView (Lyrics)
- (void) editLyrics;
- (void) drawLyricsForSystem:(int)system stanza:(size_t)stanza;
- (void) highlightLyricsInMeasure:(int)measure at:(VLFraction)at stanza:(size_t)stanza;
@end
// Local Variables:
// mode:ObjC
// End:

View File

@ -0,0 +1,137 @@
//
// VLSheetViewLyrics.mm
// Vocalese
//
// Created by Matthias Neeracher on 1/4/06.
// Copyright 2006 __MyCompanyName__. All rights reserved.
//
#import "VLSheetView.h"
#import "VLSheetViewLyrics.h"
#import "VLSheetViewInternal.h"
#import "VLModel.h"
#import "VLSoundOut.h"
@implementation VLLyricsEditable
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
song:(VLSong *)song
measure:(int)measure
at:(VLFract)at
{
self = [super init];
fView = view;
fSong = song;
fMeasure= measure;
fAt = at;
[fView setNeedsDisplay: YES];
return self;
}
- (NSString *) stringValue
{
}
- (void) setStringValue:(NSString *)val
{
}
- (BOOL) validValue:(NSString *)val
{
return YES;
}
- (void) moveToNext
{
}
- (void) moveToPrev
{
}
- (void) highlightCursor
{
[fView highlightLyricsInMeasure:fMeasure at:fAt];
}
@end
@implementation VLSheetView (Lyrics)
- (void) drawLyricsForSystem:(int)system stanza:(size_t)stanza
{
static NSDictionary * sLyricsFont = nil;
if (!sLyricsFont)
sLyricsFont =
[[NSDictionary alloc] initWithObjectsAndKeys:
[NSFont fontWithName: @"Helvetica" size: 12],
NSFontAttributeName,
nil];
const VLSong * song = [self song];
const float kSystemY = [self systemY:system];
//
// Build new list
//
for (int m = 0; m<fMeasPerSystem; ++m) {
int measIdx = m+system*fMeasPerSystem;
if (measIdx >= song->CountMeasures())
break;
const VLMeasure measure = song->fMeasures[measIdx];
const VLNoteList & notes = measure.fMelody;
VLFraction at(0);
for (VLNoteList::const_iterator note = notes.begin();
note != notes.end();
++note
) {
if (note->fLyrics.size() < stanza
|| !note->fLyrics[stanza-1].fText.size()
) {
;
} else {
NSString * syll =
[NSString stringWithUTF8String:
note->fLyrics[stanza-1].fText.c_str()];
NSSize sz =
[syll sizeWithAttributes:sLyricsFont];
NSPoint syllLoc =
NSMakePoint(fClefKeyW+(m+at)*fMeasureW
+ 0.5f*(kNoteW-sz.width),
kSystemY+kLyricsY-stanza*kLyricsH);
if (note->fLyrics[stanza-1].fKind & VLSyllable::kHasNext)
syll = [syll stringByAppendingString:@" -"];
[syll drawAtPoint:syllLoc withAttributes:sLyricsFont];
}
at += note->fDuration;
}
}
}
- (void) editLyrics
{
VLEditable * e =
[[VLLyricsEditable alloc]
initWithView:self
song:[self song]
measure:fCursorMeasure
at:fCursorAt];
[self setEditTarget:e];
[fFieldEditor selectText:self];
}
- (void) highlightLyricsInMeasure:(int)measure at:(VLFraction)at stanza:(size_t)stanza
{
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

View File

@ -67,6 +67,8 @@
95E04DAB0AEB4886006F30A0 /* VLXMLDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95F5F50E0ADCC433003980B2 /* VLXMLDocument.mm */; }; 95E04DAB0AEB4886006F30A0 /* VLXMLDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95F5F50E0ADCC433003980B2 /* VLXMLDocument.mm */; };
95E04DC70AEB4B57006F30A0 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */; }; 95E04DC70AEB4B57006F30A0 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */; };
95E04DCE0AEB4D9B006F30A0 /* Templates in Resources */ = {isa = PBXBuildFile; fileRef = 95E04DCA0AEB4D9B006F30A0 /* Templates */; }; 95E04DCE0AEB4D9B006F30A0 /* Templates in Resources */ = {isa = PBXBuildFile; fileRef = 95E04DCA0AEB4D9B006F30A0 /* Templates */; };
95E299BF0B2006F5001977D2 /* VLSheetViewLyrics.h in Copy MMA Library */ = {isa = PBXBuildFile; fileRef = 95E299BD0B2006F5001977D2 /* VLSheetViewLyrics.h */; };
95E299C00B2006F5001977D2 /* VLSheetViewLyrics.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95E299BE0B2006F5001977D2 /* VLSheetViewLyrics.mm */; };
95EDA5AA0B06DE46004D8D6E /* VLMIDIDocument.h in Copy MMA Library */ = {isa = PBXBuildFile; fileRef = 95EDA5A80B06DE46004D8D6E /* VLMIDIDocument.h */; }; 95EDA5AA0B06DE46004D8D6E /* VLMIDIDocument.h in Copy MMA Library */ = {isa = PBXBuildFile; fileRef = 95EDA5A80B06DE46004D8D6E /* VLMIDIDocument.h */; };
95EDA5AB0B06DE47004D8D6E /* VLMIDIDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95EDA5A90B06DE46004D8D6E /* VLMIDIDocument.mm */; }; 95EDA5AB0B06DE47004D8D6E /* VLMIDIDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95EDA5A90B06DE46004D8D6E /* VLMIDIDocument.mm */; };
95F5F50F0ADCC433003980B2 /* VLXMLDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95F5F50E0ADCC433003980B2 /* VLXMLDocument.mm */; }; 95F5F50F0ADCC433003980B2 /* VLXMLDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95F5F50E0ADCC433003980B2 /* VLXMLDocument.mm */; };
@ -103,6 +105,7 @@
95009B510B0ED0BB00EB33A4 /* CADebugMacros.h in Copy MMA Library */, 95009B510B0ED0BB00EB33A4 /* CADebugMacros.h in Copy MMA Library */,
95009B640B0ED18700EB33A4 /* CAConditionalMacros.h in Copy MMA Library */, 95009B640B0ED18700EB33A4 /* CAConditionalMacros.h in Copy MMA Library */,
95009B650B0ED18700EB33A4 /* CAMath.h in Copy MMA Library */, 95009B650B0ED18700EB33A4 /* CAMath.h in Copy MMA Library */,
95E299BF0B2006F5001977D2 /* VLSheetViewLyrics.h in Copy MMA Library */,
); );
name = "Copy MMA Library"; name = "Copy MMA Library";
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -190,6 +193,8 @@
95E04DA00AEB4837006F30A0 /* TVLLilypond */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TVLLilypond; sourceTree = BUILT_PRODUCTS_DIR; }; 95E04DA00AEB4837006F30A0 /* TVLLilypond */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TVLLilypond; sourceTree = BUILT_PRODUCTS_DIR; };
95E04DA60AEB486E006F30A0 /* TVLLilypond.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = TVLLilypond.mm; path = Tests/TVLLilypond.mm; sourceTree = "<group>"; }; 95E04DA60AEB486E006F30A0 /* TVLLilypond.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = TVLLilypond.mm; path = Tests/TVLLilypond.mm; sourceTree = "<group>"; };
95E04DCA0AEB4D9B006F30A0 /* Templates */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Templates; path = Resources/Templates; sourceTree = "<group>"; }; 95E04DCA0AEB4D9B006F30A0 /* Templates */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Templates; path = Resources/Templates; sourceTree = "<group>"; };
95E299BD0B2006F5001977D2 /* VLSheetViewLyrics.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = VLSheetViewLyrics.h; path = Sources/VLSheetViewLyrics.h; sourceTree = "<group>"; };
95E299BE0B2006F5001977D2 /* VLSheetViewLyrics.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = VLSheetViewLyrics.mm; path = Sources/VLSheetViewLyrics.mm; sourceTree = "<group>"; };
95EDA5A80B06DE46004D8D6E /* VLMIDIDocument.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = VLMIDIDocument.h; path = Sources/VLMIDIDocument.h; sourceTree = "<group>"; }; 95EDA5A80B06DE46004D8D6E /* VLMIDIDocument.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = VLMIDIDocument.h; path = Sources/VLMIDIDocument.h; sourceTree = "<group>"; };
95EDA5A90B06DE46004D8D6E /* VLMIDIDocument.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = VLMIDIDocument.mm; path = Sources/VLMIDIDocument.mm; sourceTree = "<group>"; }; 95EDA5A90B06DE46004D8D6E /* VLMIDIDocument.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = VLMIDIDocument.mm; path = Sources/VLMIDIDocument.mm; sourceTree = "<group>"; };
95F5F50D0ADCC433003980B2 /* VLXMLDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLXMLDocument.h; path = Sources/VLXMLDocument.h; sourceTree = "<group>"; }; 95F5F50D0ADCC433003980B2 /* VLXMLDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLXMLDocument.h; path = Sources/VLXMLDocument.h; sourceTree = "<group>"; };
@ -341,6 +346,8 @@
952DCD77096BBB11001C2316 /* VLSheetViewChords.mm */, 952DCD77096BBB11001C2316 /* VLSheetViewChords.mm */,
95B66656096BCA1F00FE18C9 /* VLSheetViewNotes.h */, 95B66656096BCA1F00FE18C9 /* VLSheetViewNotes.h */,
95B66657096BCA1F00FE18C9 /* VLSheetViewNotes.mm */, 95B66657096BCA1F00FE18C9 /* VLSheetViewNotes.mm */,
95E299BD0B2006F5001977D2 /* VLSheetViewLyrics.h */,
95E299BE0B2006F5001977D2 /* VLSheetViewLyrics.mm */,
95F5F50D0ADCC433003980B2 /* VLXMLDocument.h */, 95F5F50D0ADCC433003980B2 /* VLXMLDocument.h */,
95F5F50E0ADCC433003980B2 /* VLXMLDocument.mm */, 95F5F50E0ADCC433003980B2 /* VLXMLDocument.mm */,
953722650AE9F0E100B6E483 /* VLLilypondDocument.h */, 953722650AE9F0E100B6E483 /* VLLilypondDocument.h */,
@ -626,6 +633,7 @@
95009B2A0B0ECF9000EB33A4 /* CAAudioFileFormats.cpp in Sources */, 95009B2A0B0ECF9000EB33A4 /* CAAudioFileFormats.cpp in Sources */,
95009B2C0B0ECF9000EB33A4 /* CAStreamBasicDescription.cpp in Sources */, 95009B2C0B0ECF9000EB33A4 /* CAStreamBasicDescription.cpp in Sources */,
95009B500B0ED0BB00EB33A4 /* CADebugMacros.cpp in Sources */, 95009B500B0ED0BB00EB33A4 /* CADebugMacros.cpp in Sources */,
95E299C00B2006F5001977D2 /* VLSheetViewLyrics.mm in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };