mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 19:23:59 +00:00
Switch to NSFileWrapper based documents
This commit is contained in:
parent
6f67b7df9e
commit
a970adcbc9
Binary file not shown.
|
@ -22,12 +22,13 @@
|
||||||
<key>CFBundleTypeRole</key>
|
<key>CFBundleTypeRole</key>
|
||||||
<string>Editor</string>
|
<string>Editor</string>
|
||||||
<key>LSTypeIsPackage</key>
|
<key>LSTypeIsPackage</key>
|
||||||
<false/>
|
<true/>
|
||||||
<key>NSDocumentClass</key>
|
<key>NSDocumentClass</key>
|
||||||
<string>VLDocument</string>
|
<string>VLDocument</string>
|
||||||
<key>NSExportableAs</key>
|
<key>NSExportableAs</key>
|
||||||
<array>
|
<array>
|
||||||
<string>VLLilypondType</string>
|
<string>VLLilypondType</string>
|
||||||
|
<string>VLMusicXMLType</string>
|
||||||
</array>
|
</array>
|
||||||
<key>NSPersistentStoreTypeKey</key>
|
<key>NSPersistentStoreTypeKey</key>
|
||||||
<string>XML</string>
|
<string>XML</string>
|
||||||
|
@ -50,6 +51,20 @@
|
||||||
<key>NSPersistentStoreTypeKey</key>
|
<key>NSPersistentStoreTypeKey</key>
|
||||||
<string>Binary</string>
|
<string>Binary</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>xml</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>VLMusicXMLType</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>None</string>
|
||||||
|
<key>LSTypeIsPackage</key>
|
||||||
|
<false/>
|
||||||
|
<key>NSPersistentStoreTypeKey</key>
|
||||||
|
<string>Binary</string>
|
||||||
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>VocalEasel</string>
|
<string>VocalEasel</string>
|
||||||
|
|
BIN
Resources/VLPDFWindow.nib/keyedobjects.nib
generated
BIN
Resources/VLPDFWindow.nib/keyedobjects.nib
generated
Binary file not shown.
|
@ -67,14 +67,13 @@
|
||||||
char line[1000];
|
char line[1000];
|
||||||
FILE * output = popen([command UTF8String], "r");
|
FILE * output = popen([command UTF8String], "r");
|
||||||
if (fgets(line, 1000, output)) {
|
if (fgets(line, 1000, output)) {
|
||||||
fprintf(stderr, "Line %s", line);
|
|
||||||
size_t len = strlen(line);
|
size_t len = strlen(line);
|
||||||
if (len && line[len-1]=='\n') {
|
if (len && line[len-1]=='\n') {
|
||||||
line[len-1] = 0;
|
line[len-1] = 0;
|
||||||
return [NSString stringWithUTF8String:line];
|
return [NSString stringWithUTF8String:line];
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
NSLog(@"Failed command: %@ (%d)\n", command, errno);
|
NSLog(@"Failed command: %@ %s (%d)\n", command, feof(output) ? "EOF" : "Error", errno);
|
||||||
pclose(output);
|
pclose(output);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -181,9 +180,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
|
|
||||||
{
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -32,21 +32,29 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) close
|
|
||||||
{
|
|
||||||
[logWin close];
|
|
||||||
[pdfWin close];
|
|
||||||
|
|
||||||
[super close];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
delete song;
|
delete song;
|
||||||
|
|
||||||
|
[lilypondTemplate release];
|
||||||
|
[songTitle release];
|
||||||
|
[songLyricist release];
|
||||||
|
[songComposer release];
|
||||||
|
[songArranger release];
|
||||||
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)removeWindowController:(NSWindowController *)win
|
||||||
|
{
|
||||||
|
if (win == logWin)
|
||||||
|
logWin = nil;
|
||||||
|
else if (win == pdfWin)
|
||||||
|
pdfWin = nil;
|
||||||
|
|
||||||
|
[super removeWindowController:win];
|
||||||
|
}
|
||||||
|
|
||||||
- (VLLogWindow *)logWin
|
- (VLLogWindow *)logWin
|
||||||
{
|
{
|
||||||
if (!logWin) {
|
if (!logWin) {
|
||||||
|
@ -141,12 +149,14 @@
|
||||||
[self updateChangeCount:NSChangeDone];
|
[self updateChangeCount:NSChangeDone];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
|
- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError
|
||||||
{
|
{
|
||||||
if ([typeName isEqual:@"VLNativeType"]) {
|
if ([typeName isEqual:@"VLNativeType"]) {
|
||||||
return [self XMLDataWithError:outError];
|
return [self XMLFileWrapperWithError:outError flat:NO];
|
||||||
|
} else if ([typeName isEqual:@"VLMusicXMLType"]) {
|
||||||
|
return [self XMLFileWrapperWithError:outError flat:YES];
|
||||||
} else if ([typeName isEqual:@"VLLilypondType"]) {
|
} else if ([typeName isEqual:@"VLLilypondType"]) {
|
||||||
return [self lilypondDataWithError:outError];
|
return [self lilypondFileWrapperWithError:outError];
|
||||||
} else {
|
} else {
|
||||||
if (outError)
|
if (outError)
|
||||||
*outError = [NSError errorWithDomain:NSCocoaErrorDomain
|
*outError = [NSError errorWithDomain:NSCocoaErrorDomain
|
||||||
|
@ -156,10 +166,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
|
- (BOOL)readFromFileWrapper:(NSFileWrapper *)wrapper ofType:(NSString *)typeName error:(NSError **)outError
|
||||||
{
|
{
|
||||||
if ([typeName isEqual:@"VLNativeType"]) {
|
if ([typeName isEqual:@"VLNativeType"]) {
|
||||||
return [self readFromXMLData:data error:outError];
|
return [self readFromXMLFileWrapper:wrapper error:outError];
|
||||||
} else {
|
} else {
|
||||||
if (outError)
|
if (outError)
|
||||||
*outError = [NSError errorWithDomain:NSCocoaErrorDomain
|
*outError = [NSError errorWithDomain:NSCocoaErrorDomain
|
||||||
|
@ -169,14 +179,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (IBAction) performEngrave:(id)sender
|
||||||
- (IBAction) engrave:(id)sender
|
|
||||||
{
|
{
|
||||||
NSTask * lilypondTask = [[NSTask alloc] init];
|
NSTask * lilypondTask = [[NSTask alloc] init];
|
||||||
NSString * path = [[self fileURL] path];
|
NSString * path = [[self fileURL] path];
|
||||||
NSString * root =
|
NSString * base = [[path lastPathComponent]
|
||||||
[[path lastPathComponent] stringByDeletingPathExtension];
|
stringByDeletingPathExtension];
|
||||||
NSString * tmpDir = @"/var/tmp";
|
|
||||||
NSBundle * mainBundle = [NSBundle mainBundle];
|
NSBundle * mainBundle = [NSBundle mainBundle];
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -184,21 +192,20 @@
|
||||||
//
|
//
|
||||||
NSError * err;
|
NSError * err;
|
||||||
[self writeToURL:
|
[self writeToURL:
|
||||||
[NSURL fileURLWithPath:
|
[NSURL fileURLWithPath:[[path stringByAppendingPathComponent:base]
|
||||||
[[tmpDir stringByAppendingPathComponent:root]
|
stringByAppendingPathExtension:@"ly"]]
|
||||||
stringByAppendingPathExtension:@"ly"]]
|
|
||||||
ofType:@"VLLilypondType" error:&err];
|
ofType:@"VLLilypondType" error:&err];
|
||||||
NSPipe * pipe = [NSPipe pipe];
|
NSPipe * pipe = [NSPipe pipe];
|
||||||
NSString * tool =
|
NSString * tool =
|
||||||
[[NSUserDefaults standardUserDefaults]
|
[[NSUserDefaults standardUserDefaults]
|
||||||
stringForKey:@"VLLilypondPath"];
|
stringForKey:@"VLLilypondPath"];
|
||||||
NSArray * arguments = [NSArray arrayWithObjects:tool, root, nil];
|
NSArray * arguments = [NSArray arrayWithObjects:tool, base, nil];
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
addObserver:self selector:@selector(engraveDone:)
|
addObserver:self selector:@selector(engraveDone:)
|
||||||
name:NSTaskDidTerminateNotification object:lilypondTask];
|
name:NSTaskDidTerminateNotification object:lilypondTask];
|
||||||
|
|
||||||
[lilypondTask setCurrentDirectoryPath:tmpDir];
|
[lilypondTask setCurrentDirectoryPath:path];
|
||||||
[lilypondTask setStandardOutput: pipe];
|
[lilypondTask setStandardOutput: pipe];
|
||||||
[lilypondTask setStandardError: pipe];
|
[lilypondTask setStandardError: pipe];
|
||||||
[lilypondTask setArguments: arguments];
|
[lilypondTask setArguments: arguments];
|
||||||
|
@ -216,26 +223,45 @@
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver: self];
|
[[NSNotificationCenter defaultCenter] removeObserver: self];
|
||||||
int status = [[notification object] terminationStatus];
|
int status = [[notification object] terminationStatus];
|
||||||
if (!status) {
|
if (!status) {
|
||||||
NSFileManager * fileManager = [NSFileManager defaultManager];
|
|
||||||
NSString * path = [[self fileURL] path];
|
|
||||||
NSString * root =
|
|
||||||
[[path lastPathComponent] stringByDeletingPathExtension];
|
|
||||||
NSString * tmpDir = @"/var/tmp";
|
|
||||||
NSString * dstDir = [path stringByDeletingLastPathComponent];
|
|
||||||
NSString * pdf =
|
|
||||||
[root stringByAppendingPathExtension:@"pdf"];
|
|
||||||
[fileManager
|
|
||||||
removeFileAtPath:[dstDir stringByAppendingPathComponent:pdf]
|
|
||||||
handler:nil];
|
|
||||||
[fileManager
|
|
||||||
movePath:[tmpDir stringByAppendingPathComponent:pdf]
|
|
||||||
toPath:[dstDir stringByAppendingPathComponent:pdf]
|
|
||||||
handler:nil];
|
|
||||||
[[self pdfWin] showWindow: self];
|
[[self pdfWin] showWindow: self];
|
||||||
[pdfWin reloadPDF];
|
[pdfWin reloadPDF];
|
||||||
|
} else {
|
||||||
|
NSBeep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) engrave:(NSDocument *)doc didSave:(BOOL)didSave contextInfo:(void *)contextInfo
|
||||||
|
{
|
||||||
|
if (didSave)
|
||||||
|
[self performEngrave:(id)contextInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)engrave:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(id)sender
|
||||||
|
{
|
||||||
|
if (returnCode == NSAlertDefaultReturn) {
|
||||||
|
[[alert window] orderOut:self];
|
||||||
|
[self saveDocumentWithDelegate:self
|
||||||
|
didSaveSelector:@selector(engrave:didSave:contextInfo:)
|
||||||
|
contextInfo:sender];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction) engrave:(id)sender
|
||||||
|
{
|
||||||
|
if ([self isDocumentEdited]) {
|
||||||
|
NSAlert * alert =
|
||||||
|
[NSAlert alertWithMessageText:@"Do you want to save your changes?"
|
||||||
|
defaultButton:[self fileURL] ? @"Save" : @"Save..."
|
||||||
|
alternateButton:@"Cancel" otherButton:nil
|
||||||
|
informativeTextWithFormat:@"You need to save your document before typesetting."];
|
||||||
|
[alert beginSheetModalForWindow:[sheetWin window]
|
||||||
|
modalDelegate:self
|
||||||
|
didEndSelector:@selector(engrave:returnCode:contextInfo:)
|
||||||
|
contextInfo:sender];
|
||||||
|
} else
|
||||||
|
[self performEngrave:sender];
|
||||||
|
}
|
||||||
|
|
||||||
- (IBAction) showOutput:(id)sender
|
- (IBAction) showOutput:(id)sender
|
||||||
{
|
{
|
||||||
[[self pdfWin] showWindow:sender];
|
[[self pdfWin] showWindow:sender];
|
||||||
|
|
|
@ -11,6 +11,6 @@
|
||||||
|
|
||||||
@interface VLDocument (Lilypond)
|
@interface VLDocument (Lilypond)
|
||||||
|
|
||||||
- (NSData *)lilypondDataWithError:(NSError **)outError;
|
- (NSFileWrapper *)lilypondFileWrapperWithError:(NSError **)outError;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -131,4 +131,16 @@ const char * sKeyNames[] = {
|
||||||
return [ly dataUsingEncoding:enc];
|
return [ly dataUsingEncoding:enc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSFileWrapper *)lilypondFileWrapperWithError:(NSError **)outError
|
||||||
|
{
|
||||||
|
NSData * data = [self lilypondDataWithError:outError];
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return nil;
|
||||||
|
else
|
||||||
|
return [[[NSFileWrapper alloc]
|
||||||
|
initRegularFileWithContents:data]
|
||||||
|
autorelease];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -36,13 +36,36 @@ static NSString* sZoomOutToolbarItemIdentifier = @"Zoom Out Toolbar Item Identif
|
||||||
- (void)reloadPDF
|
- (void)reloadPDF
|
||||||
{
|
{
|
||||||
if (pdfView) {
|
if (pdfView) {
|
||||||
NSString * inString = [[[self document] fileURL] path];
|
NSString * path = [[[self document] fileURL] path];
|
||||||
NSString * baseString = [inString stringByDeletingPathExtension];
|
if (!path)
|
||||||
NSString * outString = [baseString stringByAppendingPathExtension: @"pdf"];
|
return;
|
||||||
NSURL * pdfURL = [NSURL fileURLWithPath: outString];
|
NSFileWrapper * wrapper =
|
||||||
PDFDocument * pdfDoc = [[[PDFDocument alloc] initWithURL: pdfURL] autorelease];
|
[[[NSFileWrapper alloc] initWithPath:path] autorelease];
|
||||||
[(PDFView *)pdfView setDocument: pdfDoc];
|
//
|
||||||
[pdfView setNeedsDisplay:YES];
|
// Find newest pdf file
|
||||||
|
//
|
||||||
|
NSEnumerator * w = [[wrapper fileWrappers] objectEnumerator];
|
||||||
|
NSString * pdfPath = nil;
|
||||||
|
NSDate * pdfDate = nil;
|
||||||
|
while (wrapper = [w nextObject]) {
|
||||||
|
NSString * path = [wrapper filename];
|
||||||
|
if (![[path pathExtension] isEqual:@"pdf"])
|
||||||
|
continue;
|
||||||
|
NSDate * date = [[wrapper fileAttributes]
|
||||||
|
objectForKey:NSFileModificationDate];
|
||||||
|
if (!pdfPath || [date compare:pdfDate]==NSOrderedAscending) {
|
||||||
|
pdfPath = path;
|
||||||
|
pdfDate = date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pdfPath) {
|
||||||
|
NSURL * pdfURL =
|
||||||
|
[NSURL fileURLWithPath:[path stringByAppendingPathComponent:pdfPath]];
|
||||||
|
PDFDocument * pdfDoc =
|
||||||
|
[[[PDFDocument alloc] initWithURL:pdfURL] autorelease];
|
||||||
|
[(PDFView *)pdfView setDocument: pdfDoc];
|
||||||
|
[pdfView setNeedsDisplay:YES];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
@interface VLDocument (XML)
|
@interface VLDocument (XML)
|
||||||
|
|
||||||
- (NSData *)XMLDataWithError:(NSError **)outError;
|
- (NSFileWrapper *)XMLFileWrapperWithError:(NSError **)outError flat:(BOOL)flat;
|
||||||
- (BOOL)readFromXMLData:(NSData *)data error:(NSError **)outError;
|
- (BOOL)readFromXMLFileWrapper:(NSFileWrapper *)wrapper error:(NSError **)outError;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -283,6 +283,28 @@ const char * sSteps = "C DbD EbE F GbG AbA BbB ";
|
||||||
return [doc XMLDataWithOptions:NSXMLNodePrettyPrint|NSXMLNodeCompactEmptyElement];
|
return [doc XMLDataWithOptions:NSXMLNodePrettyPrint|NSXMLNodeCompactEmptyElement];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSFileWrapper *)XMLFileWrapperWithError:(NSError **)outError flat:(BOOL)flat;
|
||||||
|
{
|
||||||
|
NSData * contents = [self XMLDataWithError:outError];
|
||||||
|
|
||||||
|
if (!contents) {
|
||||||
|
return nil;
|
||||||
|
} else if (flat) {
|
||||||
|
return [[[NSFileWrapper alloc]
|
||||||
|
initRegularFileWithContents:contents]
|
||||||
|
autorelease];
|
||||||
|
} else {
|
||||||
|
NSFileWrapper * wrap = [[[NSFileWrapper alloc]
|
||||||
|
initDirectoryWithFileWrappers:
|
||||||
|
[NSDictionary dictionary]]
|
||||||
|
autorelease];
|
||||||
|
[wrap addRegularFileWithContents:contents
|
||||||
|
preferredFilename:@"Song"];
|
||||||
|
|
||||||
|
return wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)readPropsFromAttributes:(NSXMLElement*)attr error:(NSError **)outError
|
- (BOOL)readPropsFromAttributes:(NSXMLElement*)attr error:(NSError **)outError
|
||||||
{
|
{
|
||||||
VLProperties & prop = song->fProperties.front();
|
VLProperties & prop = song->fProperties.front();
|
||||||
|
@ -432,4 +454,11 @@ int8_t sStepToPitch[] = {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)readFromXMLFileWrapper:(NSFileWrapper *)wrapper error:(NSError **)outError
|
||||||
|
{
|
||||||
|
return [self readFromXMLData: [[[wrapper fileWrappers] objectForKey:@"Song"]
|
||||||
|
regularFileContents]
|
||||||
|
error:outError];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user