diff --git a/English.lproj/VLGroove.nib/classes.nib b/English.lproj/VLGroove.nib/classes.nib
deleted file mode 100644
index 917f133..0000000
--- a/English.lproj/VLGroove.nib/classes.nib
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- IBClasses = (
- {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
- {
- ACTIONS = {endSheet = id; updateDescription = id; };
- CLASS = VLGrooveController;
- LANGUAGE = ObjC;
- OUTLETS = {fBrowser = NSBrowser; fDescription = NSTextField; fOKButton = NSButton; };
- SUPERCLASS = NSWindowController;
- }
- );
- IBVersion = 1;
-}
\ No newline at end of file
diff --git a/English.lproj/VLGroove.nib/designable.nib b/English.lproj/VLGroove.nib/designable.nib
new file mode 100644
index 0000000..a14e51a
--- /dev/null
+++ b/English.lproj/VLGroove.nib/designable.nib
@@ -0,0 +1,845 @@
+
+
+
+ 1050
+ 9A412
+ 599
+ 902
+ 304.00
+
+
+
+
+
+ YES
+
+
+ window
+
+
+
+ 19
+
+
+
+ endSheet:
+
+
+
+ 20
+
+
+
+ endSheet:
+
+
+
+ 21
+
+
+
+ delegate
+
+
+
+ 22
+
+
+
+ fBrowser
+
+
+
+ 23
+
+
+
+ fDescription
+
+
+
+ 25
+
+
+
+ updateDescription:
+
+
+
+ 26
+
+
+
+ fOKButton
+
+
+
+ 27
+
+
+
+ togglePlay:
+
+
+
+ 100028
+
+
+
+ fPlayButton
+
+
+
+ 100029
+
+
+
+
+ YES
+
+ 0
+
+ YES
+
+
+
+
+
+ -2
+
+
+ RmlsZSdzIE93bmVyA
+
+
+ -1
+
+
+ First Responder
+
+
+ 13
+
+
+ YES
+
+
+
+ Panel
+
+
+ 14
+
+
+ YES
+
+
+
+
+
+
+
+
+
+
+ 15
+
+
+
+
+ 16
+
+
+ YES
+
+
+
+
+
+ 17
+
+
+ YES
+
+
+
+
+
+ 18
+
+
+ YES
+
+
+
+
+
+ 24
+
+
+ YES
+
+
+
+
+
+ 100016
+
+
+
+
+ 100017
+
+
+
+
+ 100018
+
+
+
+
+ 100024
+
+
+
+
+ -3
+
+
+ Application
+
+
+ 100025
+
+
+ YES
+
+
+
+
+
+ 100026
+
+
+
+
+
+
+ YES
+
+ YES
+ -1.IBPluginDependency
+ -2.IBPluginDependency
+ 100025.IBPluginDependency
+ 100026.IBPluginDependency
+ 13.IBPluginDependency
+ 13.IBWindowTemplateEditedContentRect
+ 13.ImportedFromIB2
+ 13.editorWindowContentRectSynchronizationRect
+ 14.IBPluginDependency
+ 14.ImportedFromIB2
+ 15.IBPluginDependency
+ 15.ImportedFromIB2
+ 16.IBPluginDependency
+ 16.ImportedFromIB2
+ 17.IBPluginDependency
+ 17.ImportedFromIB2
+ 18.IBPluginDependency
+ 18.ImportedFromIB2
+ 24.IBPluginDependency
+ 24.ImportedFromIB2
+
+
+ YES
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ {{173, 57}, {634, 396}}
+
+ {{173, 57}, {634, 396}}
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+
+
+
+ YES
+
+ YES
+
+
+ YES
+
+
+
+
+ YES
+
+ YES
+
+
+ YES
+
+
+
+ 100029
+
+
+
+ YES
+
+ YES
+ FirstResponder
+ VLGrooveController
+
+
+ YES
+
+ FirstResponder
+ NSObject
+
+ YES
+
+ YES
+ alignCenter:
+ alignJustified:
+ alignLeft:
+ alignRight:
+ arrangeInFront:
+ centerSelectionInVisibleArea:
+ changeFont:
+ checkSpelling:
+ clear:
+ clearRecentDocuments:
+ complete:
+ copy:
+ copyFont:
+ copyRuler:
+ cut:
+ delete:
+ deminiaturize:
+ fax:
+ hide:
+ hideOtherApplications:
+ loosenKerning:
+ lowerBaseline:
+ makeKeyAndOrderFront:
+ miniaturize:
+ newDocument:
+ openDocument:
+ orderBack:
+ orderFront:
+ orderFrontColorPanel:
+ orderFrontHelpPanel:
+ orderOut:
+ outline:
+ paste:
+ pasteAsPlainText:
+ pasteAsRichText:
+ pasteFont:
+ pasteRuler:
+ pause:
+ performClose:
+ performFindPanelAction:
+ performMiniaturize:
+ performZoom:
+ play:
+ print:
+ printDocument:
+ raiseBaseline:
+ record:
+ redo:
+ resume:
+ revertDocumentToSaved:
+ run:
+ runPageLayout:
+ runToolbarCustomizationPalette:
+ saveAllDocuments:
+ saveDocument:
+ saveDocumentAs:
+ saveDocumentTo:
+ selectAll:
+ selectText:
+ showGuessPanel:
+ showHelp:
+ start:
+ startSpeaking:
+ stop:
+ stopSpeaking:
+ subscript:
+ superscript:
+ terminate:
+ tightenKerning:
+ toggleContinuousSpellChecking:
+ togglePlay:
+ toggleRuler:
+ toggleToolbarShown:
+ turnOffKerning:
+ turnOffLigatures:
+ underline:
+ undo:
+ unhideAllApplications:
+ unscript:
+ useAllLigatures:
+ useStandardKerning:
+ useStandardLigatures:
+
+
+ YES
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+ id
+
+
+
+
+
+ VLGrooveController
+ NSWindowController
+
+ YES
+
+ YES
+ endSheet:
+ togglePlay:
+ updateDescription:
+
+
+ YES
+ id
+ id
+ id
+
+
+
+ YES
+
+ YES
+ fBrowser
+ fDescription
+ fOKButton
+ fPlayButton
+
+
+ YES
+ NSBrowser
+ NSTextField
+ NSButton
+ NSButton
+
+
+
+
+
+
+ 0
+
+ YnBsaXN0MDDUAAEAAgADAAQABQAGAAkAClgkdmVyc2lvblQkdG9wWSRhcmNoaXZlclgkb2JqZWN0cxIA
+AYag0QAHAAhdSUIub2JqZWN0ZGF0YYABXxAPTlNLZXllZEFyY2hpdmVyrxCbAAsADAAxADUANgA8AD0A
+QQBFAFIAWgByAHMAdwB7AH4AgQALAI8AmAC0ALUAvwDAAMgAyQDMANAA0wDUANoA4gDjAO8A8AD1AP8B
+AAEBAQUBBwEMAQ0BEAEUARcBHwEgATQBNQE2ATcBOgE9AUYBRwFPAVABUQFZAVoBZAFtAW4BegF7AYAB
+gQGCAYUBgQGJAYwBkAALAZEBkwGUAZUBlgGZAZoBngGjAaQBqQGqAa8BsAGzAbgBvQG+AcMBxAHJAcoB
+zwHQAdUB1gHnAeoB6wHtAf4CEAIiAiMCJAIlAiYCJwIoAikCKgIrAiwCLQB2Ai4CLwIwAjMCNgJSAm4C
+bwJwAnEBKwJyAnMCdADHAnUCdgJ3AngCeQJ6ALMCewJ8An0CfgJ/AoACgQKCAoMChAKHAooCjVUkbnVs
+bN8QEgANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAo
+ACkAKgArACwALQAuAC8AMFZOU1Jvb3RWJGNsYXNzXU5TT2JqZWN0c0tleXNfEA9OU0NsYXNzZXNWYWx1
+ZXNfEBlOU0FjY2Vzc2liaWxpdHlPaWRzVmFsdWVzXU5TQ29ubmVjdGlvbnNbTlNOYW1lc0tleXNbTlNG
+cmFtZXdvcmtdTlNDbGFzc2VzS2V5c1pOU09pZHNLZXlzXU5TTmFtZXNWYWx1ZXNfEBlOU0FjY2Vzc2li
+aWxpdHlDb25uZWN0b3JzXU5TRm9udE1hbmFnZXJfEBBOU1Zpc2libGVXaW5kb3dzXxAPTlNPYmplY3Rz
+VmFsdWVzXxAXTlNBY2Nlc3NpYmlsaXR5T2lkc0tleXNZTlNOZXh0T2lkXE5TT2lkc1ZhbHVlc4ACgJqA
+ZIB7gJmACIBpgAWAeoB8gGqAl4AAgAaAaICYEgABhr6AfdIADgAyADMANFtOU0NsYXNzTmFtZYAEgANf
+EBJWTEdyb292ZUNvbnRyb2xsZXLSADcAOAA5ADpYJGNsYXNzZXNaJGNsYXNzbmFtZaIAOgA7Xk5TQ3Vz
+dG9tT2JqZWN0WE5TT2JqZWN0XxAQSUJDb2NvYUZyYW1ld29ya9IADgA+AD8AQFpOUy5vYmplY3RzgAeg
+0gA3ADgAQgBDowBDAEQAO1xOU011dGFibGVTZXRVTlNTZXTSAA4APgBGAEeASKoASABJAEoASwBMAE0A
+TgBPAFAAUYAJgFKAVIBWgFmAWoBcgF6AYIBi1AAOAFMAVABVAFYAVwAfAFldTlNEZXN0aW5hdGlvblhO
+U1NvdXJjZVdOU0xhYmVsgFGACoACgFDcAFsADgBcAF0AXgBfAGAAYQBiAGMAZABlAGYAZwBoAGkAagBr
+AGwAbQBuAG8AcABxXE5TV2luZG93Vmlld1xOU1NjcmVlblJlY3RdTlNXaW5kb3dUaXRsZVlOU1dURmxh
+Z3NdTlNXaW5kb3dDbGFzc1xOU1dpbmRvd1JlY3RZTlNNYXhTaXplXxAPTlNXaW5kb3dCYWNraW5nXxAR
+TlNXaW5kb3dTdHlsZU1hc2tZTlNNaW5TaXplW05TVmlld0NsYXNzgBCAT4BMgAwScHgAAIAOgAuAThAC
+EAOATYAPXxAYe3sxNzYsIDE2NX0sIHs2MzQsIDM5Nn190gAOAHQAdQB2WU5TLnN0cmluZ4ANVVBhbmVs
+0gA3ADgAeAB5owB5AHoAO18QD05TTXV0YWJsZVN0cmluZ1hOU1N0cmluZ9IADgB0AHUAfYANV05TUGFu
+ZWzSAA4AdAB1AICADVRWaWV31wCCAA4AgwCEAIUAhgCHAIgAiQCKAIsAjACIAI5fEA9OU05leHRSZXNw
+b25kZXJaTlNTdWJ2aWV3c1hOU3ZGbGFnc1tOU0ZyYW1lU2l6ZVhOU1dpbmRvd1tOU1N1cGVydmlld4AR
+gEuAEhEBAIBJgBGAStIADgA+AEYAkYBIpgCSAJMAlACVAJYAl4ATgB6ALYA1gDqAPd8QEQCCAA4AmQCa
+AJsAnACdAJ4AnwCEAKAAhgChAKIAhwCjAKQAZgCmAKcAqACpAKoAqwCsAK0AiwCtAIgAsABuAGYAsgCz
+V05TRnJhbWVfEA9OU1BhdGhTZXBhcmF0b3JZTlNCckZsYWdzXxASTlNGaXJzdENvbHVtblRpdGxlXxAP
+TlNDZWxsUHJvdG90eXBlXxAVTlNQcmVmZXJlZENvbHVtbldpZHRoXxASTlNBbGxvd3NUeXBlU2VsZWN0
+WU5TRW5hYmxlZF8QEE5TTWluQ29sdW1uV2lkdGhfEBhOU051bWJlck9mVmlzaWJsZUNvbHVtbnNVTlNU
+YWdfEBROU0NvbHVtblJlc2l6aW5nVHlwZYAQgB2AFIAbEhgCQACAHIAVI0BywAAAAAAACQmAERCWgBAR
+A+gQAV8QFnt7MjAsIDk4fSwgezM5MCwgMjk4fX3VALYADgC3ALgAuQC6ALsAvAC9AL5bTlNDZWxsRmxh
+Z3NaTlNDb250ZW50c1lOU1N1cHBvcnRcTlNDZWxsRmxhZ3MyEgQB/kCAGoAWgBcRCABRINQADgDBAMIA
+wwDEAMUAxgDHVk5TU2l6ZVZOU05hbWVYTlNmRmxhZ3OAGSNAKAAAAAAAAIAYEBBcTHVjaWRhR3JhbmRl
+0gA3ADgAygDLogDLADtWTlNGb2500gA3ADgAzQDOowDOAM8AO11OU0Jyb3dzZXJDZWxsVk5TQ2VsbNIA
+DgB0AHUA0oANUS9VU3R5bGXSADcAOADVANalANYA1wDYANkAO1lOU0Jyb3dzZXJZTlNDb250cm9sVk5T
+Vmlld1tOU1Jlc3BvbmRlctgAggAOAJkAzwCEAKAAhgCHAGYA3ADdAN4AiwCtAIgAZoAQgCyAH4AgCYAR
+gBBfEBh7ezM4MCwgMjQ5fSwgezIyNCwgMjU3fX3YALYADgDkALcAuADlALkA5gDnAOgA6QDqAOsAkwDt
+AO5fEBFOU0JhY2tncm91bmRDb2xvcl1OU0NvbnRyb2xWaWV3W05TVGV4dENvbG9yEgQB/gCAK4AjgCGA
+IoAeEhBAAACAKF8QEFN5c3RlbSBGb250IFRleHTUAA4AwQDCAMMAxADyAMYA9IAZI0AqAAAAAAAAgBgR
+BBTVAA4A9gD3APgA+QD6APsA/AD9AP5XTlNDb2xvclxOU0NvbG9yU3BhY2VbTlNDb2xvck5hbWVdTlND
+YXRhbG9nTmFtZYAngCYQBoAlgCRWU3lzdGVtXGNvbnRyb2xDb2xvctMADgD3AQIA+gBvAQRXTlNXaGl0
+ZYAnSzAuNjY2NjY2NjkA0gA3ADgBBgD2ogD2ADvVAA4A9gD3APgA+QD6AQkA/AEKAP6AJ4AqgCmAJF8Q
+EGNvbnRyb2xUZXh0Q29sb3LTAA4A9wECAPoAbwEPgCdCMADSADcAOAERARKkARIBEwDPADtfEA9OU1Rl
+eHRGaWVsZENlbGxcTlNBY3Rpb25DZWxs0gA3ADgBFQEWpQEWANcA2ADZADtbTlNUZXh0RmllbGTZAIIA
+DgCZAM8AhACgAIYAhwCjAGYBGQEaARsAiwCtAIgAZgCygBCANIAugC8JgBGAEF8QFXt7NTM4LCAxMn0s
+IHs4MiwgMzJ9fd4AtgAOASEBIgEjASQBJQC3ALgA5QEmALkBJwCjASgBKQEqASsAswDrAS0BLgDrAJQB
+MQEyATMAsl8QE05TQWx0ZXJuYXRlQ29udGVudHNfEBJOU1BlcmlvZGljSW50ZXJ2YWxeTlNCdXR0b25G
+bGFnczJfEBBOU0FsdGVybmF0ZUltYWdlXxAPTlNLZXlFcXVpdmFsZW50XxAPTlNQZXJpb2RpY0RlbGF5
+XU5TQnV0dG9uRmxhZ3MSJAH+AIAzgDEQGYAigDKAMIAigC0QyBIIAAAAE/////+GgkD/Uk9LUFEN0gA3
+ADgBOAE5pAE5ARMAzwA7XE5TQnV0dG9uQ2VsbNIANwA4ATsBPKUBPADXANgA2QA7WE5TQnV0dG9u2QCC
+AA4AmQDPAIQAoACGAIcAowBmARkBQAFBAIsArQCIAGYBRYAQgDSANoA3CYARgBARA+lfEBV7ezQ0Miwg
+MTJ9LCB7ODIsIDMyfX3eALYADgEhASIBIwEkASUAtwC4AOUBJgC5AScAowDnASkBKgErALMA6wFLAUwA
+6wCVATEBMgEzAUWAM4AxgCKAOYA4gCKANVZDYW5jZWxRG9gAggAOAJkAzwCEAKAAhgCHAGYA3AFUAVUA
+iwCtAIgAZoAQgCyAO4A8CYARgBBfEBd7ezQxNSwgOTh9LCB7MjAyLCAyNzZ9fdkAtgAOAOQAtwC4AOUA
+uQFbAOYBXADoAOkBKgDrAJYA7QCtAO5fEBFOU0RyYXdzQmFja2dyb3VuZBIEQf4AgCuAI4AxgCKAOgmA
+KNgAggAOAJkAzwCEAKAAhgCHAGYBGQFnAWgBaQCtAIgAZoAQgDSAPoA/EQEMCYARgBBfEBV7ezE4LCAx
+NH0sIHsxNTIsIDMyfX3eALYADgEhAW8BIgEjASQBJQC3ALgA5QEmALkBJwEoASkBKgFyASsAbgFzASoB
+dQDrAJcBMQF4AXldTlNOb3JtYWxJbWFnZYAzgDGAQYBFgDGAQIAigD0QABJIPFH/XxAUUGxheSBTZWxl
+Y3RlZCBHcm9vdmXTAA4AMgF8AX0BfgF/Xk5TUmVzb3VyY2VOYW1lgESAQoBDV05TSW1hZ2VYTlNTd2l0
+Y2jSADcAOAGDAYSiAYQAO18QEE5TQ3VzdG9tUmVzb3VyY2XSAA4BhgGHAYhbTlNJbWFnZU5hbWWAR4BG
+0gA3ADgBigGLogGLADtfEBNOU0J1dHRvbkltYWdlU291cmNl0gA3ADgBjQGOowGOAY8AO15OU011dGFi
+bGVBcnJheVdOU0FycmF5Wns2MzQsIDM5Nn3SADcAOAGSANijANgA2QA7XxAVe3swLCAwfSwgezEyODAs
+IDc3OH19WnsyMTMsIDEyOX1fEBp7My40MDI4MmUrMzgsIDMuNDAyODJlKzM4fdIANwA4AZcBmKIBmAA7
+XxAQTlNXaW5kb3dUZW1wbGF0ZVZ3aW5kb3fSADcAOAGbAZyjAZwBnQA7XxAUTlNOaWJPdXRsZXRDb25u
+ZWN0b3JeTlNOaWJDb25uZWN0b3LUAA4AUwBUAFUAVgCSAB8BooBRgBOAAoBTWGZCcm93c2Vy1AAOAFMA
+VABVAFYAHwCSAaiAUYACgBOAVVhkZWxlZ2F0ZdQADgBTAFQAVQGrAB8AlAGugFiAAoAtgFdZZW5kU2hl
+ZXQ60gA3ADgBsQGyowGyAZ0AO18QFU5TTmliQ29udHJvbENvbm5lY3RvctQADgBTAFQAVQGrAB8AlQGu
+gFiAAoA1gFfUAA4AUwBUAFUAVgCWAB8BvIBRgDqAAoBbXGZEZXNjcmlwdGlvbtQADgBTAFQAVQGrAB8A
+kgHCgFiAAoATgF1fEBJ1cGRhdGVEZXNjcmlwdGlvbjrUAA4AUwBUAFUAVgCUAB8ByIBRgC2AAoBfWWZP
+S0J1dHRvbtQADgBTAFQAVQGrAB8AlwHOgFiAAoA9gGFbdG9nZ2xlUGxheTrUAA4AUwBUAFUAVgCXAB8B
+1IBRgD2AAoBjW2ZQbGF5QnV0dG9u0gAOAD4B1wHYgGeuAJIBVQBmARsBaADeAJQAlQCXAeIAVwCWAUEA
+k4ATgDyAEIAvgD+AIIAtgDWAPYBlgAqAOoA3gB7SAA4AMgAzAemABIBmXU5TQXBwbGljYXRpb27SADcA
+OAHsAY+iAY8AO9IADgA+AdcB74BnrgBmAJYAVwCUAJcAkwBmAGYAZgAfAB8AZgCVAGaAEIA6gAqALYA9
+gB6AEIAQgBCAAoACgBCANYAQ0gAOAD4B1wIAgGevEA8AkgFVAGYBGwFoAN4AHwCUAJUB4gCXAUEAVwCW
+AJOAE4A8gBCAL4A/gCCAAoAtgDWAZYA9gDeACoA6gB7SAA4APgHXAhKAZ68QDwITAhQCFQIWAhcCGAIZ
+AhoCGwIcAh0CHgIfAiACIYBrgGyAbYBugG+AcIBxgHKAc4B0gHWAdoB3gHiAeVdCcm93c2VyXxAPVGV4
+dCBGaWVsZCBDZWxsXENvbnRlbnQgVmlld18QEEJ1dHRvbiBDZWxsIChPSylfECJCdXR0b24gQ2VsbCAo
+UGxheSBTZWxlY3RlZCBHcm9vdmUpXxAiVGV4dCBGaWVsZCBDZWxsIChTeXN0ZW0gRm9udCBUZXh0KVxG
+aWxlJ3MgT3duZXJfEBBQdXNoIEJ1dHRvbiAoT0spXxAUUHVzaCBCdXR0b24gKENhbmNlbClbQXBwbGlj
+YXRpb25fECBDaGVjayBCb3ggKFBsYXkgU2VsZWN0ZWQgR3Jvb3ZlKV8QFEJ1dHRvbiBDZWxsIChDYW5j
+ZWwpWlRleHQgRmllbGRfEB5TdGF0aWMgVGV4dCAoU3lzdGVtIEZvbnQgVGV4dCnSAA4APgHXAjKAZ6DS
+AA4APgHXAjWAZ6DSAA4APgHXAjiAZ68QGQBMAEgATgBKAE0AZgBJAeIAkwCSAFEBVQEbAWgA3gAfAJQA
+lQBPAJcAUABXAJYBQQBLgFmACYBcgFSAWoAQgFKAZYAegBOAYoA8gC+AP4AggAKALYA1gF6APYBggAqA
+OoA3gFbSAA4APgHXAlSAZ68QGQJVAlYCVwJYAlkCWgJbAlwCXQJeAl8CYAJhAmICYwJkAmUCZgJnAmgC
+aQJqAmsCbAJtgH6Af4CAgIGAgoCDgISAhYCGgIeAiICJgIqAi4CMgI2AjoCPgJCAkYCSgJOAlICVgJYQ
+FBATEBoQFhAOEBcT//////////0QDxIAAYa9EgABhrgSAAGGsRIAAYa6EgABhrAQERASEBsSAAGGuRIA
+AYa8EA0QGBIAAYayEBXSAA4APgBGAoaASKDSAA4APgHXAomAZ6DSAA4APgHXAoyAZ6DSADcAOAKOAo+i
+Ao8AO15OU0lCT2JqZWN0RGF0YQAIABkAIgAnADEAOgA/AEQAUgBUAGYBnwGlAfAB9wH+AgwCHgI6AkgC
+VAJgAm4CeQKHAqMCsQLEAtYC8AL6AwcDCQMLAw0DDwMRAxMDFQMXAxkDGwMdAx8DIQMjAyUDJwMsAy4D
+NwNDA0UDRwNcA2UDbgN5A34DjQOWA6kDsgO9A78DwAPJA9AD3QPjA+wD7gQDBAUEBwQJBAsEDQQPBBEE
+EwQVBBcEKAQ2BD8ERwRJBEsETQRPBIAEjQSaBKgEsgTABM0E1wTpBP0FBwUTBRUFFwUZBRsFIAUiBSQF
+JgUoBSoFLAUuBUkFUgVcBV4FZAVtBXQFhgWPBZgFmgWiBasFrQWyBc8F4QXsBfUGAQYKBhYGGAYaBhwG
+HwYhBiMGJQYuBjAGPQY/BkEGQwZFBkcGSQaQBpgGqga0BskG2wbzBwgHEgclB0AHRgddB18HYQdjB2UH
+agdsB24Hdwd4B3kHewd9B38HggeEB50Hsge+B8kH0wfgB+UH5wfpB+sH7gfwCAEICAgPCBgIGggjCCUI
+Jwg0CD0IQghJCFIIWQhnCG4Idwh5CHsIgQiKCJUInwipCLAIvAjdCN8I4QjjCOUI5gjoCOoJBQkmCToJ
+SAlUCVkJWwldCV8JYQljCWgJagl9CY4JkAmZCZsJngmzCbsJyAnUCeIJ5AnmCegJ6gnsCfMKAAoNChUK
+FwojCiwKMQpGCkgKSgpMCk4KYQpuCnAKcwp8CoUKlwqkCq0KuArECukK6wrtCu8K8QryCvQK9gsOC0cL
+XQtyC4ELlAumC7gLxgvLC80LzwvRC9ML1QvXC9kL2wvdC+IL6wvuC+8L8Qv6DAMMEAwZDCQMLQxSDFQM
+VgxYDFoMWwxdDF8MYgx6DLMMtQy3DLkMuwy9DL8MwQzIDMoM6wztDO8M8QzzDPQM9gz4DRINNw1LDVAN
+Ug1UDVYNWA1aDVsNXQ1+DYANgg2EDYYNiQ2KDYwNjg2mDd8N7Q3vDfEN8w31DfcN+Q37Df0N/w4EDhsO
+KA43DjkOOw49DkUOTg5XDlwObw54DoQOhg6IDpEOlg6sDrUOvA7LDtMO3g7nDu4PBg8RDy4PNw88D08P
+Vg9fD2YPfQ+MD50Pnw+hD6MPpQ+uD78PwQ/DD8UPxw/QD+EP4w/lD+cP6Q/zD/wQAxAbECwQLhAwEDIQ
+NBBFEEcQSRBLEE0QWhBrEG0QbxBxEHMQiBCZEJsQnRCfEKEQqxC8EL4QwBDCEMQQ0BDhEOMQ5RDnEOkQ
+9RD+EQARHREfESERIxElEScRKRErES0RLxExETMRNRE3ETkRQhFEEUYRVBFdEWIRaxFtEYoRjBGOEZAR
+khGUEZYRmBGaEZwRnhGgEaIRpBGmEa8RsRHSEdQR1hHYEdoR3BHeEeAR4hHkEeYR6BHqEewR7hHwEfkR
++xIcEh4SIBIiEiQSJhIoEioSLBIuEjASMhI0EjYSOBI6EkISVBJhEnQSmRK+EssS3hL1EwETJBM7E0YT
+ZxNwE3ITcxN8E34TfxOIE4oTvxPBE8MTxRPHE8kTyxPNE88T0RPTE9UT1xPZE9sT3RPfE+ET4xPlE+cT
+6RPrE+0T7xPxE/oT/BQxFDMUNRQ3FDkUOxQ9FD8UQRRDFEUURxRJFEsUTRRPFFEUUxRVFFcUWRRbFF0U
+XxRhFGMUZRRnFGkUaxRtFG8UeBR6FH8UhBSJFI4UkxSVFJcUmRSeFKMUpRSnFKwUrhS3FLkUuhTDFMUU
+xhTPFNEU0hTbFOAAAAAAAAACAgAAAAAAAAKQAAAAAAAAAAAAAAAAAAAU7w
+
+
+
diff --git a/English.lproj/VLGroove.nib/info.nib b/English.lproj/VLGroove.nib/info.nib
deleted file mode 100644
index b053b83..0000000
--- a/English.lproj/VLGroove.nib/info.nib
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
- IBDocumentLocation
- 59 9 356 240 0 0 1280 778
- IBFramework Version
- 460.0
- IBOpenObjects
-
- 13
-
- IBSystem Version
- 9A412
-
-
diff --git a/English.lproj/VLGroove.nib/keyedobjects.nib b/English.lproj/VLGroove.nib/keyedobjects.nib
index 2fd578f..94fbb27 100644
Binary files a/English.lproj/VLGroove.nib/keyedobjects.nib and b/English.lproj/VLGroove.nib/keyedobjects.nib differ
diff --git a/Sources/VLDocument.h b/Sources/VLDocument.h
index b036d69..e8d33ee 100644
--- a/Sources/VLDocument.h
+++ b/Sources/VLDocument.h
@@ -52,6 +52,8 @@
- (IBAction) showOutput:(id)sender;
- (IBAction) showLog:(id)sender;
+- (IBAction) play:(id)sender;
+- (IBAction) stop:(id)sender;
- (NSString *) tmpPath;
- (NSString *) workPath;
@@ -64,6 +66,7 @@
- (void) didChangeSong;
- (void) addObserver:(id)observer;
- (VLLogWindow *)logWin;
+- (void) playWithGroove:(NSString *)groove;
@end
diff --git a/Sources/VLDocument.mm b/Sources/VLDocument.mm
index 935395d..52d4089 100644
--- a/Sources/VLDocument.mm
+++ b/Sources/VLDocument.mm
@@ -418,6 +418,18 @@
[self fileURLWithExtension:@"mid"]]));
}
+- (void) playWithGroove:(NSString *)groove
+{
+ NSString * savedGroove = songGroove;
+ songGroove = groove;
+ [validTmpFiles removeObjectForKey:@"mma"];
+ [validTmpFiles removeObjectForKey:@"mid"];
+ [self play:groove];
+ songGroove = savedGroove;
+ [validTmpFiles removeObjectForKey:@"mma"];
+ [validTmpFiles removeObjectForKey:@"mid"];
+}
+
- (IBAction) stop:(id)sender
{
VLSoundOut::Instance()->Stop();
diff --git a/Sources/VLGrooveController.h b/Sources/VLGrooveController.h
index 779d7a4..6b71696 100644
--- a/Sources/VLGrooveController.h
+++ b/Sources/VLGrooveController.h
@@ -9,21 +9,25 @@
#import
@class VLSheetView;
+@class VLDocument;
@interface VLGrooveController : NSWindowController {
NSDictionary * fGrooves;
IBOutlet NSBrowser * fBrowser;
IBOutlet NSTextField * fDescription;
IBOutlet NSButton * fOKButton;
+ IBOutlet NSButton * fPlayButton;
NSString * fStyle;
NSDictionary * fSubStyles;
NSArray * fSubStyleList;
NSPredicate * fSubStyleFilter;
+ VLDocument * fDocument;
}
- (id) initWithSheetView:(VLSheetView *)view;
- (IBAction)endSheet:(id)sender;
- (IBAction)updateDescription:(id)sender;
+- (IBAction) togglePlay:(id)sender;
@end
diff --git a/Sources/VLGrooveController.mm b/Sources/VLGrooveController.mm
index de3be91..0b622d5 100644
--- a/Sources/VLGrooveController.mm
+++ b/Sources/VLGrooveController.mm
@@ -8,6 +8,7 @@
#import "VLGrooveController.h"
#import "VLSheetView.h"
+#import "VLDocument.h"
@implementation VLGrooveController
@@ -20,6 +21,7 @@
[[NSPredicate predicateWithFormat:
@"!(SELF like[c] '.DESC') AND !(SELF matches[c] '.*(Intro|End)\\\\d*$')"]
retain];
+ fDocument = [view document];
[NSApp beginSheet: [self window]
modalForWindow: [view window]
@@ -36,6 +38,14 @@
[super dealloc];
}
+- (IBAction) togglePlay:(id)sender
+{
+ if ([sender state])
+ [fDocument playWithGroove:[[fBrowser selectedCellInColumn:1] stringValue]];
+ else
+ [fDocument stop:sender];
+}
+
- (IBAction)endSheet:(id)sender
{
[NSApp endSheet:[self window] returnCode:[sender tag]];
@@ -43,9 +53,12 @@
- (void)didEndSheet:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
+ [fDocument stop:self];
if (returnCode == NSAlertFirstButtonReturn)
[(VLSheetView *)contextInfo setGroove:[[fBrowser selectedCellInColumn:1] stringValue]];
-
+ else
+ [(VLSheetView *)contextInfo setGroove:nil];
+
[[self window] orderOut:self];
}
@@ -98,13 +111,16 @@
{
BOOL validStyle = [fBrowser selectedColumn];
[fOKButton setEnabled:validStyle];
- if (validStyle)
+ [fPlayButton setEnabled:validStyle];
+ if (validStyle) {
[fDescription setStringValue:
[NSString stringWithFormat:@"%@\n\n%@",
[fSubStyles objectForKey:@".DESC"],
[fSubStyles objectForKey:
[[fBrowser selectedCellInColumn:1] stringValue]]]];
- else
+ [fDocument stop:self];
+ [self togglePlay:fPlayButton];
+ } else
[fDescription setStringValue:[fSubStyles objectForKey:@".DESC"]];
}
diff --git a/Sources/VLMMADocument.mm b/Sources/VLMMADocument.mm
index 2d308e9..2f2e6fb 100644
--- a/Sources/VLMMADocument.mm
+++ b/Sources/VLMMADocument.mm
@@ -37,7 +37,7 @@
size_t m = *i;
sprintf(buf, "%-5d", ++meas);
mmaFile += buf;
- song->fMeasures[m].MMAChords(mmas, prop);
+ song->fMeasures[m].MMAChords(mmas, prop, i==song->begin());
mmaFile += mmas;
song->fMeasures[m].MMANotes(mmas, prop, song->TiedDuration(m+1));
mmaFile += "\t{ " + mmas + " }\n";
diff --git a/Sources/VLModel.cpp b/Sources/VLModel.cpp
index 95e2839..4790305 100644
--- a/Sources/VLModel.cpp
+++ b/Sources/VLModel.cpp
@@ -619,15 +619,15 @@ static const VLChordModifier kMMAModifiers[] = {
{NULL, 0, 0}
};
-void VLChord::MMAName(std::string & name, bool useSharps) const
+bool VLChord::MMAName(std::string & name, bool useSharps, bool initial) const
{
VLFraction dur = fDuration;
int quarters = static_cast(dur*4.0f+0.5f);
name = "";
if (!quarters--)
- return;
+ return initial;
if (fPitch == kNoPitch) {
- name = '/';
+ name = initial ? 'z' : '/';
} else {
std::string base, ext;
VLNote::Name(base, useSharps);
@@ -675,6 +675,8 @@ void VLChord::MMAName(std::string & name, bool useSharps) const
}
while (quarters--)
name += " /";
+
+ return false;
}
static VLFraction MaxNote(VLFraction d)
@@ -799,7 +801,8 @@ void VLMeasure::MMANotes(std::string & notes, const VLProperties & prop,
notes += "<>;";
}
-void VLMeasure::MMAChords(std::string & chords, const VLProperties & prop) const
+void VLMeasure::MMAChords(std::string & chords, const VLProperties & prop,
+ bool initial) const
{
VLChordList::const_iterator i = fChords.begin();
VLChordList::const_iterator e = fChords.end();
@@ -807,7 +810,7 @@ void VLMeasure::MMAChords(std::string & chords, const VLProperties & prop) const
chords.clear();
for (; i!=e; ++i) {
std::string chord;
- i->MMAName(chord, prop.fKey >= 0);
+ initial = i->MMAName(chord, prop.fKey >= 0, initial);
if (chords.size())
chords += ' ';
chords += chord;
diff --git a/Sources/VLModel.h b/Sources/VLModel.h
index db382c8..79065c9 100644
--- a/Sources/VLModel.h
+++ b/Sources/VLModel.h
@@ -202,7 +202,7 @@ struct VLChord : VLNote {
VLChord(std::string name);
void Name(std::string & base, std::string & ext, std::string & root, bool useSharps = false) const;
void LilypondName(std::string & name, bool useSharps = false) const;
- void MMAName(std::string & name, bool useSharps) const;
+ bool MMAName(std::string & name, bool useSharps, bool initial) const;
};
struct VLProperties {
@@ -245,7 +245,7 @@ struct VLMeasure {
VLMeasure();
void MMANotes(std::string & notes, const VLProperties & prop, VLFraction extra) const;
- void MMAChords(std::string & chords, const VLProperties & prop) const;
+ void MMAChords(std::string & chords, const VLProperties & prop, bool initial) const;
};
struct VLRepeat {
diff --git a/Sources/VLSheetView.mm b/Sources/VLSheetView.mm
index 4b0e3f3..c10d839 100644
--- a/Sources/VLSheetView.mm
+++ b/Sources/VLSheetView.mm
@@ -982,8 +982,12 @@ static int8_t sSharpAcc[] = {
- (void)setGroove:(NSString *)groove
{
- [[self document] setValue:groove forKey:@"songGroove"];
- [self setGrooveMenu:groove];
+ if (groove) {
+ [[self document] setValue:groove forKey:@"songGroove"];
+ [self setGrooveMenu:groove];
+ } else {
+ [fGrooveMenu selectItemAtIndex:2];
+ }
}
- (void)setGrooveMenu:(NSString *)groove