mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14:00 +00:00
Implemen loading, update management
This commit is contained in:
parent
1b61bcd41e
commit
fe55af3f7c
2
English.lproj/VLDocument.nib/classes.nib
generated
2
English.lproj/VLDocument.nib/classes.nib
generated
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
IBClasses = (
|
IBClasses = (
|
||||||
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
{CLASS = MyDocument; LANGUAGE = ObjC; SUPERCLASS = NSDocument; },
|
|
||||||
{CLASS = VLDocument; LANGUAGE = ObjC; SUPERCLASS = NSDocument; },
|
{CLASS = VLDocument; LANGUAGE = ObjC; SUPERCLASS = NSDocument; },
|
||||||
|
{CLASS = VLEditable; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
{
|
{
|
||||||
ACTIONS = {hideFieldEditor = id; setDivisions = id; setKey = id; setTime = id; };
|
ACTIONS = {hideFieldEditor = id; setDivisions = id; setKey = id; setTime = id; };
|
||||||
CLASS = VLSheetView;
|
CLASS = VLSheetView;
|
||||||
|
|
2
English.lproj/VLDocument.nib/info.nib
generated
2
English.lproj/VLDocument.nib/info.nib
generated
|
@ -11,6 +11,6 @@
|
||||||
<integer>5</integer>
|
<integer>5</integer>
|
||||||
</array>
|
</array>
|
||||||
<key>IBSystem Version</key>
|
<key>IBSystem Version</key>
|
||||||
<string>9A274</string>
|
<string>9A283</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
BIN
English.lproj/VLDocument.nib/keyedobjects.nib
generated
BIN
English.lproj/VLDocument.nib/keyedobjects.nib
generated
Binary file not shown.
|
@ -12,7 +12,7 @@
|
||||||
<string>vlsong</string>
|
<string>vlsong</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleTypeIconFile</key>
|
<key>CFBundleTypeIconFile</key>
|
||||||
<string></string>
|
<string>vlsong.icns</string>
|
||||||
<key>CFBundleTypeName</key>
|
<key>CFBundleTypeName</key>
|
||||||
<string>Song</string>
|
<string>Song</string>
|
||||||
<key>CFBundleTypeOSTypes</key>
|
<key>CFBundleTypeOSTypes</key>
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>Vocalese</string>
|
<string>Vocalese</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string></string>
|
<string>vocalese</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>com.aereperennius.Vocalese</string>
|
<string>com.aereperennius.Vocalese</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
|
|
@ -76,8 +76,13 @@
|
||||||
{
|
{
|
||||||
VLProperties & prop = song->fProperties.front();
|
VLProperties & prop = song->fProperties.front();
|
||||||
|
|
||||||
|
if (transpose)
|
||||||
|
song->Transpose((7*((key>>8)-prop.fKey) % 12));
|
||||||
|
|
||||||
prop.fKey = key >> 8;
|
prop.fKey = key >> 8;
|
||||||
prop.fMode= key & 0xFF;
|
prop.fMode= key & 0xFF;
|
||||||
|
|
||||||
|
[self updateChangeCount:NSChangeDone];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSNumber *) songTime
|
- (NSNumber *) songTime
|
||||||
|
@ -92,6 +97,8 @@
|
||||||
VLProperties & prop = song->fProperties.front();
|
VLProperties & prop = song->fProperties.front();
|
||||||
|
|
||||||
prop.fTime = VLFraction(num, denom);
|
prop.fTime = VLFraction(num, denom);
|
||||||
|
|
||||||
|
[self updateChangeCount:NSChangeDone];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSNumber *) songDivisions
|
- (NSNumber *) songDivisions
|
||||||
|
@ -106,37 +113,19 @@
|
||||||
VLProperties & prop = song->fProperties.front();
|
VLProperties & prop = song->fProperties.front();
|
||||||
|
|
||||||
prop.fDivisions = divisions;
|
prop.fDivisions = divisions;
|
||||||
|
|
||||||
|
[self updateChangeCount:NSChangeDone];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)windowNibName
|
- (NSString *)windowNibName
|
||||||
{
|
{
|
||||||
// Override returning the nib file name of the document
|
|
||||||
// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
|
|
||||||
return @"VLDocument";
|
return @"VLDocument";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowControllerDidLoadNib:(NSWindowController *) aController
|
- (void)windowControllerDidLoadNib:(NSWindowController *) controller
|
||||||
{
|
{
|
||||||
[super windowControllerDidLoadNib:aController];
|
[super windowControllerDidLoadNib:controller];
|
||||||
// Add any code here that needs to be executed once the windowController has loaded the document's window.
|
[controller setShouldCloseDocument:YES];
|
||||||
}
|
|
||||||
|
|
||||||
- (NSData *)dataRepresentationOfType:(NSString *)aType
|
|
||||||
{
|
|
||||||
// Insert code here to write your document from the given data. You can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.
|
|
||||||
|
|
||||||
// For applications targeted for Tiger or later systems, you should use the new Tiger API -dataOfType:error:. In this case you can also choose to override -writeToURL:ofType:error:, -fileWrapperOfType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
|
|
||||||
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType
|
|
||||||
{
|
|
||||||
// Insert code here to read your document from the given data. You can also choose to override -loadFileWrapperRepresentation:ofType: or -readFromFile:ofType: instead.
|
|
||||||
|
|
||||||
// For applications targeted for Tiger or later systems, you should use the new Tiger API readFromData:ofType:error:. In this case you can also choose to override -readFromURL:ofType:error: or -readFromFileWrapper:ofType:error: instead.
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -119,6 +119,7 @@ std::string NormalizeName(NSString* rawName)
|
||||||
fSong->AddChord(chord, fMeasure, fAt);
|
fSong->AddChord(chord, fMeasure, fAt);
|
||||||
[fView setNeedsDisplay:YES];
|
[fView setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
|
[[fView document] updateChangeCount:NSChangeDone];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) validValue:(NSString *)val
|
- (BOOL) validValue:(NSString *)val
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
[self song]->AddNote(newNote, fCursorMeasure, fCursorAt);
|
[self song]->AddNote(newNote, fCursorMeasure, fCursorAt);
|
||||||
|
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
|
[[self document] updateChangeCount:NSChangeDone];
|
||||||
|
|
||||||
VLSoundOut::Instance()->PlayNote(newNote);
|
VLSoundOut::Instance()->PlayNote(newNote);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
|
|
||||||
- (id) nodeForXPath:(NSString *)path error:(NSError **)outError
|
- (id) nodeForXPath:(NSString *)path error:(NSError **)outError
|
||||||
{
|
{
|
||||||
return [[self nodesForXPath:path error:outError] objectAtIndex:0];
|
NSArray * nodes = [self nodesForXPath:path error:outError];
|
||||||
|
return [nodes count] ? [nodes objectAtIndex:0] : nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)stringForXPath:(NSString *)path error:(NSError **)outError
|
- (NSString *)stringForXPath:(NSString *)path error:(NSError **)outError
|
||||||
|
@ -259,6 +260,105 @@ const char * sSteps = "C DbD EbE F GbG AbA BbB ";
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t sStepToPitch[] = {
|
||||||
|
9, 11, 0, 2, 4, 5, 7
|
||||||
|
};
|
||||||
|
|
||||||
|
- (VLNote) readNote:(NSXMLElement*)note withUnit:(VLFraction)unit
|
||||||
|
{
|
||||||
|
NSError * outError;
|
||||||
|
VLNote n;
|
||||||
|
|
||||||
|
n.fTied = 0;
|
||||||
|
|
||||||
|
if ([[note elementsForName:@"rest"] count]) {
|
||||||
|
n.fPitch = VLNote::kNoPitch;
|
||||||
|
} else {
|
||||||
|
n.fPitch = ([note intForXPath:@"./pitch/octave" error:&outError]+1)*12;
|
||||||
|
n.fPitch +=
|
||||||
|
sStepToPitch[[[note stringForXPath:@"./pitch/step" error:&outError]
|
||||||
|
characterAtIndex:0] - 'A'];
|
||||||
|
if (NSXMLElement * alter = [note nodeForXPath:@"./pitch/alter" error:&outError])
|
||||||
|
n.fPitch += [[alter stringValue] intValue];
|
||||||
|
}
|
||||||
|
n.fDuration = VLFraction([note intForXPath:@"./duration" error:&outError])*unit;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) readMelody:(NSArray *)measures error:(NSError **)outError
|
||||||
|
{
|
||||||
|
NSEnumerator * e = [measures objectEnumerator];
|
||||||
|
|
||||||
|
for (NSXMLElement * measure; measure = [e nextObject]; ) {
|
||||||
|
VLProperties & prop = song->fProperties.front();
|
||||||
|
VLFraction unit(1, 4*prop.fDivisions);
|
||||||
|
VLFraction at(0);
|
||||||
|
int m = [[[measure attributeForName:@"number"]
|
||||||
|
stringValue] intValue]-1;
|
||||||
|
|
||||||
|
if (m >= song->CountMeasures())
|
||||||
|
song->fMeasures.resize(m);
|
||||||
|
|
||||||
|
NSEnumerator * n = [[measure elementsForName:@"note"] objectEnumerator];
|
||||||
|
|
||||||
|
for (NSXMLElement * note; note = [n nextObject]; ) {
|
||||||
|
VLNote n = [self readNote:note withUnit:unit];
|
||||||
|
if (n.fPitch != VLNote::kNoPitch)
|
||||||
|
song->AddNote(n, m, at);
|
||||||
|
at += n.fDuration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) readChords:(NSArray *)measures error:(NSError **)outError
|
||||||
|
{
|
||||||
|
NSEnumerator * e = [measures objectEnumerator];
|
||||||
|
|
||||||
|
for (NSXMLElement * measure; measure = [e nextObject]; ) {
|
||||||
|
VLProperties & prop = song->fProperties.front();
|
||||||
|
VLFraction unit(1, 4*prop.fDivisions);
|
||||||
|
VLFraction at(0);
|
||||||
|
VLFraction dur(0);
|
||||||
|
int m = [[[measure attributeForName:@"number"]
|
||||||
|
stringValue] intValue]-1;
|
||||||
|
VLChord chord;
|
||||||
|
|
||||||
|
chord.fSteps = 0;
|
||||||
|
if (m >= song->CountMeasures())
|
||||||
|
song->fMeasures.resize(m);
|
||||||
|
|
||||||
|
NSEnumerator * n = [[measure elementsForName:@"note"] objectEnumerator];
|
||||||
|
|
||||||
|
for (NSXMLElement * note; note = [n nextObject]; ) {
|
||||||
|
VLNote n = [self readNote:note withUnit:unit];
|
||||||
|
if (![[note elementsForName:@"chord"] count]) {
|
||||||
|
//
|
||||||
|
// Start of new chord
|
||||||
|
//
|
||||||
|
if (chord.fSteps)
|
||||||
|
song->AddChord(chord, m, at);
|
||||||
|
at += dur;
|
||||||
|
chord.fPitch = n.fPitch;
|
||||||
|
chord.fRootPitch= VLNote::kNoPitch;
|
||||||
|
chord.fDuration = n.fDuration;
|
||||||
|
chord.fSteps = n.fPitch == VLNote::kNoPitch ? 0 : VLChord::kmUnison;
|
||||||
|
dur = n.fDuration;
|
||||||
|
if (n.fPitch < VLNote::kMiddleC) {
|
||||||
|
chord.fPitch = VLNote::kNoPitch;
|
||||||
|
chord.fRootPitch= n.fPitch;
|
||||||
|
}
|
||||||
|
} else if (chord.fPitch == VLNote::kNoPitch) {
|
||||||
|
chord.fPitch = n.fPitch;
|
||||||
|
} else {
|
||||||
|
chord.fSteps |= 1 << (n.fPitch-chord.fPitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chord.fSteps)
|
||||||
|
song->AddChord(chord, m, at);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
|
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
|
||||||
{
|
{
|
||||||
NSXMLDocument * doc = [[NSXMLDocument alloc] initWithData:data
|
NSXMLDocument * doc = [[NSXMLDocument alloc] initWithData:data
|
||||||
|
@ -280,7 +380,12 @@ const char * sSteps = "C DbD EbE F GbG AbA BbB ";
|
||||||
error:outError]
|
error:outError]
|
||||||
)
|
)
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
|
[self readMelody:[melody nodesForXPath:@"./measure" error:outError]
|
||||||
|
error:outError];
|
||||||
|
[self readChords:[chords nodesForXPath:@"./measure" error:outError]
|
||||||
|
error:outError];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user