// // File: VLPListDocument.h - Convert document from and to Cocoa plist // // Author(s): // // (MN) Matthias Neeracher // // Copyright © 2007 Matthias Neeracher // #import "VLPListDocument.h" #import "VLModel.h" // // To convert from and to complex file formats, we use ruby scripts operating // on the XML representation of a Cocoa property list. The property list // representation is strictly intended as an intermediate representation, // subject to change as necessary. // @implementation VLDocument (Plist) class VLPlistVisitor : public VLSongVisitor { public: VLPlistVisitor(NSMutableDictionary * plist, bool performanceOrder) : fPlist(plist), fPerfOrder(performanceOrder) {} virtual void Visit(VLSong & song); protected: virtual void VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas); virtual void VisitNote(VLLyricsNote & n); virtual void VisitChord(VLChord & c); NSArray * EncodeProperties(const std::vector & properties); NSDictionary * EncodeProperties(const VLProperties & properties); NSMutableDictionary * fPlist; NSMutableArray * fMeasures; NSMutableArray * fNotes; NSMutableArray * fChords; bool fPerfOrder; const VLSong * fSong; }; NSArray * VLPlistVisitor::EncodeProperties(const std::vector & properties) { NSMutableArray * pa = [NSMutableArray arrayWithCapacity:properties.size()]; for (std::vector::const_iterator i = properties.begin(); i != properties.end(); ++i) [pa addObject:EncodeProperties(*i)]; return pa; } NSDictionary * VLPlistVisitor::EncodeProperties(const VLProperties & properties) { return [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: properties.fTime.fNum], @"timeNum", [NSNumber numberWithInt: properties.fTime.fDenom], @"timeDenom", [NSNumber numberWithInt: properties.fKey], @"key", [NSNumber numberWithInt: properties.fMode], @"mode", [NSNumber numberWithInt: properties.fDivisions], @"divisions", nil]; } void VLPlistVisitor::Visit(VLSong & song) { fSong = &song; fMeasures = [NSMutableArray arrayWithCapacity:32]; VisitMeasures(song, fPerfOrder); [fPlist setObject:EncodeProperties(song.fProperties) forKey:@"properties"]; [fPlist setObject:fMeasures forKey:@"measures"]; } void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas) { fNotes = [NSMutableArray arrayWithCapacity:1]; fChords= [NSMutableArray arrayWithCapacity:1]; VisitNotes(meas, p, true); VisitChords(meas); NSMutableDictionary * md = [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:m], @"measure", [NSNumber numberWithInt:meas.fPropIdx], @"properties", fNotes, @"melody", fChords, @"chords", nil]; int times; bool last; size_t volta; if (fSong->DoesBeginRepeat(m, ×)) [md setObject: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:times], @"times", nil] forKey: @"begin-repeat"]; if (fSong->DoesBeginEnding(m, &last, &volta)) [md setObject: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:!last], @"last", [NSNumber numberWithInt:volta], @"volta", nil] forKey: @"begin-ending"]; if (fSong->DoesEndRepeat(m+1, ×)) [md setObject: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:times], @"times", nil] forKey: @"end-repeat"]; if (fSong->DoesEndEnding(m+1, &last, &volta)) [md setObject: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:!last], @"last", [NSNumber numberWithInt:volta], @"volta", nil] forKey: @"end-ending"]; if (fSong->fGoToCoda == m) [md setObject:[NSNumber numberWithBool:YES] forKey:@"tocoda"]; if (fSong->fCoda == m) [md setObject:[NSNumber numberWithBool:YES] forKey:@"coda"]; [fMeasures addObject:md]; } void VLPlistVisitor::VisitNote(VLLyricsNote & n) { NSMutableArray * ly = [NSMutableArray arrayWithCapacity:0]; for (size_t i = 0; i