2006-10-22 07:16:29 +00:00
|
|
|
//
|
2007-04-27 06:41:34 +00:00
|
|
|
// File: VLLilypondDocument.mm - Export document in LilyPond format
|
2006-10-22 07:16:29 +00:00
|
|
|
//
|
2007-04-27 06:41:34 +00:00
|
|
|
// Author(s):
|
|
|
|
//
|
|
|
|
// (MN) Matthias Neeracher
|
|
|
|
//
|
|
|
|
// Copyright © 2006-2007 Matthias Neeracher
|
2006-10-22 07:16:29 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
#import "VLLilypondDocument.h"
|
2007-05-24 08:52:14 +00:00
|
|
|
#import "VLLilypondWriter.h"
|
2006-10-22 07:16:29 +00:00
|
|
|
|
|
|
|
@interface NSMutableString (VLLilypond)
|
|
|
|
|
|
|
|
- (void) substituteMacro:(NSString *)macro withValue:(NSString *)value;
|
|
|
|
- (void) purgeMacros;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSMutableString (VLLilypond)
|
|
|
|
|
2006-11-27 07:07:45 +00:00
|
|
|
- (void) substituteMacro:(NSString *)m withValue:(NSString *)value repeat:(BOOL)repeat
|
2006-10-22 07:16:29 +00:00
|
|
|
{
|
2006-10-23 07:42:53 +00:00
|
|
|
if ([value isEqual:@""])
|
|
|
|
return;
|
2006-10-22 07:16:29 +00:00
|
|
|
NSString * macro = [NSString stringWithFormat:@"<{%@}>", m];
|
|
|
|
NSRange range =
|
|
|
|
[value rangeOfCharacterFromSet:
|
|
|
|
[NSCharacterSet characterSetWithCharactersInString:@"\n"]];
|
|
|
|
BOOL hasEOL= range.location != NSNotFound;
|
2006-11-27 07:07:45 +00:00
|
|
|
unsigned from = 0;
|
2006-10-22 07:16:29 +00:00
|
|
|
|
|
|
|
for (range = [self rangeOfString:macro];
|
|
|
|
range.location != NSNotFound;
|
2006-11-27 07:07:45 +00:00
|
|
|
range = [self rangeOfString:macro options:0
|
|
|
|
range:NSMakeRange(from, [self length]-from)]
|
2006-10-22 07:16:29 +00:00
|
|
|
) {
|
|
|
|
if (hasEOL) {
|
|
|
|
//
|
|
|
|
// Multi line substitution, figure out a prefix
|
|
|
|
//
|
|
|
|
NSRange prefix, suffix;
|
|
|
|
NSRange line = [self lineRangeForRange:range];
|
|
|
|
suffix.location = range.location+range.length;
|
|
|
|
suffix.length = line.location+line.length-suffix.location;
|
|
|
|
prefix.location = line.location;
|
|
|
|
prefix.length = range.location-prefix.location;
|
|
|
|
NSString * pfxStr = [self substringWithRange:prefix];
|
|
|
|
NSString * nonBlank =
|
|
|
|
[pfxStr stringByTrimmingCharactersInSet:
|
|
|
|
[NSCharacterSet whitespaceCharacterSet]];
|
|
|
|
NSString * sfxStr =
|
|
|
|
[[self substringWithRange:suffix]
|
|
|
|
stringByTrimmingCharactersInSet:
|
|
|
|
[NSCharacterSet whitespaceCharacterSet]];
|
2006-11-27 07:07:45 +00:00
|
|
|
NSString * nl;
|
2006-10-22 07:16:29 +00:00
|
|
|
if ([nonBlank length]) {
|
|
|
|
NSRange nb = [pfxStr rangeOfString:nonBlank];
|
2006-11-27 07:07:45 +00:00
|
|
|
prefix.length = nb.location;
|
2006-10-22 07:16:29 +00:00
|
|
|
pfxStr =
|
|
|
|
[[self substringWithRange:prefix]
|
|
|
|
stringByAppendingString:@" "];
|
|
|
|
sfxStr = [NSString stringWithFormat:@"\n%@", pfxStr];
|
2006-11-27 07:07:45 +00:00
|
|
|
nl = @"\n";
|
2006-10-22 07:16:29 +00:00
|
|
|
} else {
|
|
|
|
range = line;
|
2006-11-27 07:07:45 +00:00
|
|
|
nl = @"";
|
2006-10-22 07:16:29 +00:00
|
|
|
}
|
|
|
|
NSArray * lines = [value componentsSeparatedByString:@"\n"];
|
|
|
|
value =
|
2006-11-27 07:07:45 +00:00
|
|
|
[NSString stringWithFormat:@"%@%@%@%@", nl, pfxStr,
|
2006-10-22 07:16:29 +00:00
|
|
|
[lines componentsJoinedByString:
|
|
|
|
[@"\n" stringByAppendingString:pfxStr]],
|
|
|
|
sfxStr];
|
|
|
|
}
|
2006-11-27 07:07:45 +00:00
|
|
|
from = range.location + [value length];
|
|
|
|
if (repeat) {
|
|
|
|
NSRange line = [self lineRangeForRange:range];
|
|
|
|
[self insertString:[self substringWithRange:line]
|
|
|
|
atIndex:line.location+line.length];
|
|
|
|
from = line.location+2*line.length+[value length]-range.length;
|
|
|
|
}
|
2006-10-22 07:16:29 +00:00
|
|
|
[self replaceCharactersInRange:range withString:value];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-27 07:07:45 +00:00
|
|
|
|
|
|
|
- (void)substituteMacro:(NSString*)macro withValue:(NSString*)value
|
|
|
|
{
|
|
|
|
[self substituteMacro:macro withValue:value repeat:NO];
|
|
|
|
}
|
|
|
|
|
2006-10-22 07:16:29 +00:00
|
|
|
- (void) purgeMacros
|
|
|
|
{
|
|
|
|
for (NSRange range = [self rangeOfString:@"<{"];
|
|
|
|
range.location != NSNotFound;
|
|
|
|
range = [self rangeOfString:@"<{"]
|
|
|
|
)
|
|
|
|
[self replaceCharactersInRange:[self lineRangeForRange:range]
|
|
|
|
withString: @""];
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation VLDocument (Lilypond)
|
|
|
|
|
|
|
|
- (NSData *)lilypondDataWithError:(NSError **)outError
|
|
|
|
{
|
2007-05-24 08:52:14 +00:00
|
|
|
VLLilypondWriter writer;
|
|
|
|
writer.Visit(*song);
|
2006-10-23 07:42:53 +00:00
|
|
|
NSBundle * bndl = [NSBundle mainBundle];
|
|
|
|
NSString * tmpl =
|
2006-10-22 07:16:29 +00:00
|
|
|
[bndl pathForResource:lilypondTemplate
|
|
|
|
ofType:@"lyt" inDirectory:@"Templates"];
|
2006-10-23 07:42:53 +00:00
|
|
|
NSStringEncoding enc = NSUTF8StringEncoding;
|
|
|
|
NSMutableString * ly =
|
|
|
|
[NSMutableString stringWithContentsOfFile:tmpl encoding:enc error:outError];
|
|
|
|
[ly substituteMacro:@"TITLE" withValue:songTitle];
|
|
|
|
[ly substituteMacro:@"POET" withValue:songLyricist];
|
|
|
|
[ly substituteMacro:@"COMPOSER" withValue:songComposer];
|
|
|
|
[ly substituteMacro:@"ARRANGER" withValue:songArranger];
|
|
|
|
[ly substituteMacro:@"VLVERSION" withValue:
|
|
|
|
[bndl objectForInfoDictionaryKey:@"CFBundleVersion"]];
|
|
|
|
[ly substituteMacro:@"PAPERSIZE" withValue:@"letter"];
|
|
|
|
[ly substituteMacro:@"FORMATTING" withValue:@"ragged-last-bottom = ##f"];
|
2006-10-22 07:16:29 +00:00
|
|
|
[ly substituteMacro:@"VLVERSION" withValue:
|
|
|
|
[bndl objectForInfoDictionaryKey:@"CFBundleVersion"]];
|
2006-10-23 07:42:53 +00:00
|
|
|
[ly substituteMacro:@"CHORDS" withValue:
|
2007-05-24 08:52:14 +00:00
|
|
|
[NSString stringWithUTF8String:writer.Chords().c_str()]];
|
2006-10-23 07:42:53 +00:00
|
|
|
[ly substituteMacro:@"NOTES" withValue:
|
2007-05-24 08:52:14 +00:00
|
|
|
[NSString stringWithUTF8String:writer.Melody().c_str()]];
|
2006-11-27 07:07:45 +00:00
|
|
|
if (size_t stanzas = song->CountStanzas())
|
2007-05-24 08:52:14 +00:00
|
|
|
for (size_t s=0; s<stanzas; ++s) {
|
2006-11-27 07:07:45 +00:00
|
|
|
[ly substituteMacro:@"LYRICS" withValue:
|
2007-05-24 08:52:14 +00:00
|
|
|
[NSString stringWithUTF8String:writer.Lyrics(s).c_str()]
|
2006-11-27 07:07:45 +00:00
|
|
|
repeat: s<stanzas];
|
|
|
|
}
|
2006-10-22 07:16:29 +00:00
|
|
|
[ly purgeMacros];
|
|
|
|
return [ly dataUsingEncoding:enc];
|
|
|
|
}
|
|
|
|
|
2006-10-29 07:49:33 +00:00
|
|
|
- (NSFileWrapper *)lilypondFileWrapperWithError:(NSError **)outError
|
|
|
|
{
|
|
|
|
NSData * data = [self lilypondDataWithError:outError];
|
|
|
|
|
|
|
|
if (!data)
|
|
|
|
return nil;
|
|
|
|
else
|
|
|
|
return [[[NSFileWrapper alloc]
|
|
|
|
initRegularFileWithContents:data]
|
|
|
|
autorelease];
|
|
|
|
}
|
|
|
|
|
2006-10-22 07:16:29 +00:00
|
|
|
@end
|