diff --git a/build/linux/JUCE.make b/build/linux/JUCE.make index 527e7f5cfa..902b9baf37 100644 --- a/build/linux/JUCE.make +++ b/build/linux/JUCE.make @@ -321,6 +321,7 @@ OBJECTS := \ $(OBJDIR)/juce_FileFilter.o \ $(OBJDIR)/juce_FileListComponent.o \ $(OBJDIR)/juce_FilenameComponent.o \ + $(OBJDIR)/juce_FileSearchPathListComponent.o \ $(OBJDIR)/juce_FileTreeComponent.o \ $(OBJDIR)/juce_ImagePreviewComponent.o \ $(OBJDIR)/juce_WildcardFileFilter.o \ @@ -1859,6 +1860,11 @@ $(OBJDIR)/juce_FilenameComponent.o: ../../src/juce_appframework/gui/components/f @echo $(notdir $<) @$(CXX) $(CXXFLAGS) -o $@ -c $< +$(OBJDIR)/juce_FileSearchPathListComponent.o: ../../src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CXX) $(CXXFLAGS) -o $@ -c $< + $(OBJDIR)/juce_FileTreeComponent.o: ../../src/juce_appframework/gui/components/filebrowser/juce_FileTreeComponent.cpp -@$(CMD_MKOBJDIR) @echo $(notdir $<) diff --git a/build/linux/platform_specific_code/juce_linux_Windowing.cpp b/build/linux/platform_specific_code/juce_linux_Windowing.cpp index 86879ea8f7..2966674a51 100644 --- a/build/linux/platform_specific_code/juce_linux_Windowing.cpp +++ b/build/linux/platform_specific_code/juce_linux_Windowing.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #if JUCE_USE_XINERAMA /* If you're trying to use Xinerama, you'll need to install the "libxinerama-dev" package.. @@ -2564,14 +2565,20 @@ void Desktop::setMousePosition (int x, int y) throw() //============================================================================== +static bool screenSaverAllowed = false; + void Desktop::setScreenSaverEnabled (const bool isEnabled) throw() { - jassertfalse // anyone know how to do this?? + if (screenSaverAllowed != isEnabled) + { + screenSaverAllowed = isEnabled; + XScreenSaverSuspend (display, ! isEnabled); + } } bool Desktop::isScreenSaverEnabled() throw() { - return true; + return screenSaverAllowed; } //============================================================================== @@ -2897,6 +2904,14 @@ bool juce_makeOpenGLContextCurrent (void* context) return glXMakeCurrent (display, None, 0); } +bool juce_isActiveOpenGLContext (void* context) throw() +{ + OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; + + jassert (oc != 0); + return glXGetCurrentContext() == oc->renderContext; +} + void juce_swapOpenGLBuffers (void* context) { OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; diff --git a/build/macosx/Juce.xcodeproj/project.pbxproj b/build/macosx/Juce.xcodeproj/project.pbxproj index 8ecc025440..dbb9a1f158 100644 --- a/build/macosx/Juce.xcodeproj/project.pbxproj +++ b/build/macosx/Juce.xcodeproj/project.pbxproj @@ -646,6 +646,8 @@ 84FC31BB09B74A5C00B75141 /* juce_WildcardFileFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 84FC31A909B74A5C00B75141 /* juce_WildcardFileFilter.h */; }; 84FC31BE09B74A7700B75141 /* juce_BorderSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FC31BC09B74A7700B75141 /* juce_BorderSize.cpp */; }; 84FC31BF09B74A7700B75141 /* juce_BorderSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 84FC31BD09B74A7700B75141 /* juce_BorderSize.h */; }; + 84FFAF2B0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAF290C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp */; }; + 84FFAF2C0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 84FFAF2A0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -1291,6 +1293,8 @@ 84FC31A909B74A5C00B75141 /* juce_WildcardFileFilter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_WildcardFileFilter.h; path = filebrowser/juce_WildcardFileFilter.h; sourceTree = ""; }; 84FC31BC09B74A7700B75141 /* juce_BorderSize.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_BorderSize.cpp; sourceTree = ""; }; 84FC31BD09B74A7700B75141 /* juce_BorderSize.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_BorderSize.h; sourceTree = ""; }; + 84FFAF290C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileSearchPathListComponent.cpp; path = filebrowser/juce_FileSearchPathListComponent.cpp; sourceTree = ""; }; + 84FFAF2A0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_FileSearchPathListComponent.h; path = filebrowser/juce_FileSearchPathListComponent.h; sourceTree = ""; }; D2AAC046055464E500DB518D /* libjucedebug.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjucedebug.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -2416,6 +2420,8 @@ 84FC31A209B74A5C00B75141 /* juce_FileFilter.h */, 84FC31A309B74A5C00B75141 /* juce_FileListComponent.cpp */, 84FC31A409B74A5C00B75141 /* juce_FileListComponent.h */, + 84FFAF290C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp */, + 84FFAF2A0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h */, 847F72D90C2702A000CBECEC /* juce_FileTreeComponent.cpp */, 847F72DA0C2702A000CBECEC /* juce_FileTreeComponent.h */, 84F1F05B0A36CE96008CCC5E /* juce_FilenameComponent.cpp */, @@ -2722,6 +2728,7 @@ 84F6B7550C06E29D00BB8791 /* juce_ChannelRemappingAudioSource.h in Headers */, 847F72DC0C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.h in Headers */, 847F72DE0C2702A000CBECEC /* juce_FileTreeComponent.h in Headers */, + 84FFAF2C0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3118,6 +3125,7 @@ 847F72DB0C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.cpp in Sources */, 847F72DD0C2702A000CBECEC /* juce_FileTreeComponent.cpp in Sources */, 8406AA5A0C4BDF90003A0D6A /* juce_MidiOutput.cpp in Sources */, + 84FFAF2B0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/build/macosx/platform_specific_code/juce_mac_Windowing.cpp b/build/macosx/platform_specific_code/juce_mac_Windowing.cpp index 5fd103402a..459e7753f7 100644 --- a/build/macosx/platform_specific_code/juce_mac_Windowing.cpp +++ b/build/macosx/platform_specific_code/juce_mac_Windowing.cpp @@ -1937,6 +1937,15 @@ bool juce_isHIViewCreatedByJuce (HIViewRef view) && HIObjectIsOfClass ((HIObjectRef) view, juceHiViewClassNameCFString); } +bool juce_isWindowCreatedByJuce (WindowRef window) +{ + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) + if (ComponentPeer::getPeer(i)->getNativeHandle() == window) + return true; + + return false; +} + static void trackNextMouseEvent() { UInt32 mods; @@ -3350,6 +3359,14 @@ bool juce_makeOpenGLContextCurrent (void* context) return aglSetCurrentContext ((oc != 0) ? oc->renderContext : 0); } +bool juce_isActiveOpenGLContext (void* context) throw() +{ + OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; + + jassert (oc != 0); + return aglGetCurrentContext() == oc->renderContext; +} + void juce_swapOpenGLBuffers (void* context) { OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; diff --git a/build/win32/platform_specific_code/juce_win32_Windowing.cpp b/build/win32/platform_specific_code/juce_win32_Windowing.cpp index 8b8e5f0f16..0f60f5c704 100644 --- a/build/win32/platform_specific_code/juce_win32_Windowing.cpp +++ b/build/win32/platform_specific_code/juce_win32_Windowing.cpp @@ -3141,6 +3141,14 @@ bool juce_makeOpenGLContextCurrent (void* context) return wglMakeCurrent (0, 0) != 0; } +bool juce_isActiveOpenGLContext (void* context) throw() +{ + OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; + + jassert (oc != 0); + return wglGetCurrentContext() == oc->renderContext; +} + void juce_swapOpenGLBuffers (void* context) { OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; diff --git a/build/win32/vc8/JUCE.vcproj b/build/win32/vc8/JUCE.vcproj index 784a750543..7fb417ade9 100644 --- a/build/win32/vc8/JUCE.vcproj +++ b/build/win32/vc8/JUCE.vcproj @@ -4145,6 +4145,14 @@ RelativePath="..\..\..\src\juce_appframework\gui\components\filebrowser\juce_FilePreviewComponent.h" > + + + + diff --git a/docs/JUCE changelist.txt b/docs/JUCE changelist.txt index f67c540126..57cbed9195 100644 --- a/docs/JUCE changelist.txt +++ b/docs/JUCE changelist.txt @@ -6,7 +6,10 @@ ============================================================================== Changelist for version 1.45 -- +- big new project in the "extras" folder - a basic audio plugin host! Currently it loads VSTs on PC/Mac, and lets you put them together in a filter graph, which it plays. Hosting functionality is very basic at the moment, but I'm laying down a good architecture to hopefully build out into cross-platform plugin loading. +- audio plugins: AudioFilterBase now requires a few extra methods to be implemented by your plugin: getInputChannelName, getOutputChannelName, isInputChannelStereoPair, isOutputChannelStereoPair. +- new class: FileSearchPathListComponent, for letting the user edit a FileSearchPath. + ============================================================================== Changelist for version 1.44 diff --git a/extras/audio plugin host/build/mac/Info.plist b/extras/audio plugin host/build/mac/Info.plist new file mode 100644 index 0000000000..b982ce0d96 --- /dev/null +++ b/extras/audio plugin host/build/mac/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + com.yourcompany.PluginHost + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CSResourcesFileMapped + + + diff --git a/extras/audio plugin host/build/mac/PluginHost.xcodeproj/project.pbxproj b/extras/audio plugin host/build/mac/PluginHost.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..f316a15b15 --- /dev/null +++ b/extras/audio plugin host/build/mac/PluginHost.xcodeproj/project.pbxproj @@ -0,0 +1,371 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 84FFAEAC0C6C8A6F009F6E72 /* FilterGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE920C6C8A6F009F6E72 /* FilterGraph.cpp */; }; + 84FFAEAD0C6C8A6F009F6E72 /* GraphEditorPanel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE940C6C8A6F009F6E72 /* GraphEditorPanel.cpp */; }; + 84FFAEAE0C6C8A6F009F6E72 /* InternalFilters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE960C6C8A6F009F6E72 /* InternalFilters.cpp */; }; + 84FFAEAF0C6C8A6F009F6E72 /* MainHostWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE980C6C8A6F009F6E72 /* MainHostWindow.cpp */; }; + 84FFAEB00C6C8A6F009F6E72 /* HostStartup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE9A0C6C8A6F009F6E72 /* HostStartup.cpp */; }; + 84FFAEB10C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE9C0C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp */; }; + 84FFAEB20C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE9E0C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp */; }; + 84FFAEB30C6C8A6F009F6E72 /* juce_KnownPluginList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAEA00C6C8A6F009F6E72 /* juce_KnownPluginList.cpp */; }; + 84FFAEB40C6C8A6F009F6E72 /* juce_PluginDescription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAEA20C6C8A6F009F6E72 /* juce_PluginDescription.cpp */; }; + 84FFAEB50C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAEA40C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp */; }; + 84FFAEB60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAEA60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp */; }; + 84FFAEB70C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAEAA0C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp */; }; + 84FFAEFE0C6C8E80009F6E72 /* libjucedebug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAEFC0C6C8E76009F6E72 /* libjucedebug.a */; }; + 84FFAF040C6C8ED5009F6E72 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAEFF0C6C8ED5009F6E72 /* CoreAudio.framework */; }; + 84FFAF050C6C8ED5009F6E72 /* CoreMIDI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAF000C6C8ED5009F6E72 /* CoreMIDI.framework */; }; + 84FFAF060C6C8ED5009F6E72 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAF010C6C8ED5009F6E72 /* IOKit.framework */; }; + 84FFAF080C6C8ED5009F6E72 /* QuickTime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAF030C6C8ED5009F6E72 /* QuickTime.framework */; }; + 84FFAF150C6C8EE8009F6E72 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAF140C6C8EE8009F6E72 /* AGL.framework */; }; + 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 84FFAEFB0C6C8E76009F6E72 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 84FFAEF70C6C8E76009F6E72 /* Juce.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D2AAC046055464E500DB518D; + remoteInfo = Juce; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 20286C33FDCF999611CA2CEA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; + 4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = ""; }; + 4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = ""; }; + 508344B209E5C41E0093A071 /* Juce Plugin Host.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Juce Plugin Host.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 84FFAE920C6C8A6F009F6E72 /* FilterGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = FilterGraph.cpp; path = ../../src/host/FilterGraph.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAE930C6C8A6F009F6E72 /* FilterGraph.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = FilterGraph.h; path = ../../src/host/FilterGraph.h; sourceTree = SOURCE_ROOT; }; + 84FFAE940C6C8A6F009F6E72 /* GraphEditorPanel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = GraphEditorPanel.cpp; path = ../../src/host/GraphEditorPanel.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAE950C6C8A6F009F6E72 /* GraphEditorPanel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = GraphEditorPanel.h; path = ../../src/host/GraphEditorPanel.h; sourceTree = SOURCE_ROOT; }; + 84FFAE960C6C8A6F009F6E72 /* InternalFilters.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = InternalFilters.cpp; path = ../../src/host/InternalFilters.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAE970C6C8A6F009F6E72 /* InternalFilters.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = InternalFilters.h; path = ../../src/host/InternalFilters.h; sourceTree = SOURCE_ROOT; }; + 84FFAE980C6C8A6F009F6E72 /* MainHostWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = MainHostWindow.cpp; path = ../../src/host/MainHostWindow.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAE990C6C8A6F009F6E72 /* MainHostWindow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MainHostWindow.h; path = ../../src/host/MainHostWindow.h; sourceTree = SOURCE_ROOT; }; + 84FFAE9A0C6C8A6F009F6E72 /* HostStartup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = HostStartup.cpp; path = ../../src/HostStartup.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAE9C0C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_AudioPluginFormat.cpp; path = ../../src/plugins/juce_AudioPluginFormat.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAE9D0C6C8A6F009F6E72 /* juce_AudioPluginFormat.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_AudioPluginFormat.h; path = ../../src/plugins/juce_AudioPluginFormat.h; sourceTree = SOURCE_ROOT; }; + 84FFAE9E0C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_AudioPluginInstance.cpp; path = ../../src/plugins/juce_AudioPluginInstance.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAE9F0C6C8A6F009F6E72 /* juce_AudioPluginInstance.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_AudioPluginInstance.h; path = ../../src/plugins/juce_AudioPluginInstance.h; sourceTree = SOURCE_ROOT; }; + 84FFAEA00C6C8A6F009F6E72 /* juce_KnownPluginList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_KnownPluginList.cpp; path = ../../src/plugins/juce_KnownPluginList.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAEA10C6C8A6F009F6E72 /* juce_KnownPluginList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_KnownPluginList.h; path = ../../src/plugins/juce_KnownPluginList.h; sourceTree = SOURCE_ROOT; }; + 84FFAEA20C6C8A6F009F6E72 /* juce_PluginDescription.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_PluginDescription.cpp; path = ../../src/plugins/juce_PluginDescription.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAEA30C6C8A6F009F6E72 /* juce_PluginDescription.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_PluginDescription.h; path = ../../src/plugins/juce_PluginDescription.h; sourceTree = SOURCE_ROOT; }; + 84FFAEA40C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_PluginDirectoryScanner.cpp; path = ../../src/plugins/juce_PluginDirectoryScanner.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAEA50C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_PluginDirectoryScanner.h; path = ../../src/plugins/juce_PluginDirectoryScanner.h; sourceTree = SOURCE_ROOT; }; + 84FFAEA60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_PluginListComponent.cpp; path = ../../src/plugins/juce_PluginListComponent.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAEA70C6C8A6F009F6E72 /* juce_PluginListComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_PluginListComponent.h; path = ../../src/plugins/juce_PluginListComponent.h; sourceTree = SOURCE_ROOT; }; + 84FFAEA90C6C8A6F009F6E72 /* juce_VSTPluginFormat.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_VSTPluginFormat.h; path = ../../src/plugins/vst/juce_VSTPluginFormat.h; sourceTree = SOURCE_ROOT; }; + 84FFAEAA0C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_VSTPluginInstance.cpp; path = ../../src/plugins/vst/juce_VSTPluginInstance.cpp; sourceTree = SOURCE_ROOT; }; + 84FFAEAB0C6C8A6F009F6E72 /* juce_VSTPluginInstance.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_VSTPluginInstance.h; path = ../../src/plugins/vst/juce_VSTPluginInstance.h; sourceTree = SOURCE_ROOT; }; + 84FFAEF70C6C8E76009F6E72 /* Juce.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Juce.xcodeproj; path = ../../../../build/macosx/Juce.xcodeproj; sourceTree = SOURCE_ROOT; }; + 84FFAEFF0C6C8ED5009F6E72 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; }; + 84FFAF000C6C8ED5009F6E72 /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = /System/Library/Frameworks/CoreMIDI.framework; sourceTree = ""; }; + 84FFAF010C6C8ED5009F6E72 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; + 84FFAF030C6C8ED5009F6E72 /* QuickTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = /System/Library/Frameworks/QuickTime.framework; sourceTree = ""; }; + 84FFAF140C6C8EE8009F6E72 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = /System/Library/Frameworks/AGL.framework; sourceTree = ""; }; + 8D0C4E960486CD37000505A6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8D0C4E910486CD37000505A6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 84FFAEFE0C6C8E80009F6E72 /* libjucedebug.a in Frameworks */, + 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */, + 84FFAF040C6C8ED5009F6E72 /* CoreAudio.framework in Frameworks */, + 84FFAF050C6C8ED5009F6E72 /* CoreMIDI.framework in Frameworks */, + 84FFAF060C6C8ED5009F6E72 /* IOKit.framework in Frameworks */, + 84FFAF080C6C8ED5009F6E72 /* QuickTime.framework in Frameworks */, + 84FFAF150C6C8EE8009F6E72 /* AGL.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 195DF8CFFE9D517E11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 508344B209E5C41E0093A071 /* Juce Plugin Host.app */, + ); + name = Products; + sourceTree = ""; + }; + 20286C29FDCF999611CA2CEA /* PluginHost */ = { + isa = PBXGroup; + children = ( + 20286C2AFDCF999611CA2CEA /* Sources */, + 20286C2CFDCF999611CA2CEA /* Resources */, + 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */, + 195DF8CFFE9D517E11CA2CBB /* Products */, + ); + name = PluginHost; + sourceTree = ""; + }; + 20286C2AFDCF999611CA2CEA /* Sources */ = { + isa = PBXGroup; + children = ( + 84FFAE900C6C8A6F009F6E72 /* src */, + ); + name = Sources; + sourceTree = ""; + }; + 20286C2CFDCF999611CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 8D0C4E960486CD37000505A6 /* Info.plist */, + ); + name = Resources; + sourceTree = ""; + }; + 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 84FFAF140C6C8EE8009F6E72 /* AGL.framework */, + 84FFAEFF0C6C8ED5009F6E72 /* CoreAudio.framework */, + 84FFAF000C6C8ED5009F6E72 /* CoreMIDI.framework */, + 84FFAF010C6C8ED5009F6E72 /* IOKit.framework */, + 84FFAF030C6C8ED5009F6E72 /* QuickTime.framework */, + 84FFAEF70C6C8E76009F6E72 /* Juce.xcodeproj */, + 20286C33FDCF999611CA2CEA /* Carbon.framework */, + 4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */, + 4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + 84FFAE900C6C8A6F009F6E72 /* src */ = { + isa = PBXGroup; + children = ( + 84FFAE910C6C8A6F009F6E72 /* host */, + 84FFAE9A0C6C8A6F009F6E72 /* HostStartup.cpp */, + 84FFAE9B0C6C8A6F009F6E72 /* plugins */, + ); + name = src; + path = ../../src; + sourceTree = SOURCE_ROOT; + }; + 84FFAE910C6C8A6F009F6E72 /* host */ = { + isa = PBXGroup; + children = ( + 84FFAE920C6C8A6F009F6E72 /* FilterGraph.cpp */, + 84FFAE930C6C8A6F009F6E72 /* FilterGraph.h */, + 84FFAE940C6C8A6F009F6E72 /* GraphEditorPanel.cpp */, + 84FFAE950C6C8A6F009F6E72 /* GraphEditorPanel.h */, + 84FFAE960C6C8A6F009F6E72 /* InternalFilters.cpp */, + 84FFAE970C6C8A6F009F6E72 /* InternalFilters.h */, + 84FFAE980C6C8A6F009F6E72 /* MainHostWindow.cpp */, + 84FFAE990C6C8A6F009F6E72 /* MainHostWindow.h */, + ); + name = host; + path = ../../src/host; + sourceTree = SOURCE_ROOT; + }; + 84FFAE9B0C6C8A6F009F6E72 /* plugins */ = { + isa = PBXGroup; + children = ( + 84FFAE9C0C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp */, + 84FFAE9D0C6C8A6F009F6E72 /* juce_AudioPluginFormat.h */, + 84FFAE9E0C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp */, + 84FFAE9F0C6C8A6F009F6E72 /* juce_AudioPluginInstance.h */, + 84FFAEA00C6C8A6F009F6E72 /* juce_KnownPluginList.cpp */, + 84FFAEA10C6C8A6F009F6E72 /* juce_KnownPluginList.h */, + 84FFAEA20C6C8A6F009F6E72 /* juce_PluginDescription.cpp */, + 84FFAEA30C6C8A6F009F6E72 /* juce_PluginDescription.h */, + 84FFAEA40C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp */, + 84FFAEA50C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.h */, + 84FFAEA60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp */, + 84FFAEA70C6C8A6F009F6E72 /* juce_PluginListComponent.h */, + 84FFAEA80C6C8A6F009F6E72 /* vst */, + ); + name = plugins; + path = ../../src/plugins; + sourceTree = SOURCE_ROOT; + }; + 84FFAEA80C6C8A6F009F6E72 /* vst */ = { + isa = PBXGroup; + children = ( + 84FFAEA90C6C8A6F009F6E72 /* juce_VSTPluginFormat.h */, + 84FFAEAA0C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp */, + 84FFAEAB0C6C8A6F009F6E72 /* juce_VSTPluginInstance.h */, + ); + name = vst; + path = ../../src/plugins/vst; + sourceTree = SOURCE_ROOT; + }; + 84FFAEF80C6C8E76009F6E72 /* Products */ = { + isa = PBXGroup; + children = ( + 84FFAEFC0C6C8E76009F6E72 /* libjucedebug.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8D0C4E890486CD37000505A6 /* PluginHost */ = { + isa = PBXNativeTarget; + buildConfigurationList = C0E91AC508A95435008D54AB /* Build configuration list for PBXNativeTarget "PluginHost" */; + buildPhases = ( + 8D0C4E8C0486CD37000505A6 /* Resources */, + 8D0C4E8F0486CD37000505A6 /* Sources */, + 8D0C4E910486CD37000505A6 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PluginHost; + productInstallPath = "$(HOME)/Applications"; + productName = PluginHost; + productReference = 508344B209E5C41E0093A071 /* Juce Plugin Host.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 20286C28FDCF999611CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C0E91AC908A95435008D54AB /* Build configuration list for PBXProject "PluginHost" */; + hasScannedForEncodings = 1; + mainGroup = 20286C29FDCF999611CA2CEA /* PluginHost */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 84FFAEF80C6C8E76009F6E72 /* Products */; + ProjectRef = 84FFAEF70C6C8E76009F6E72 /* Juce.xcodeproj */; + }, + ); + targets = ( + 8D0C4E890486CD37000505A6 /* PluginHost */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 84FFAEFC0C6C8E76009F6E72 /* libjucedebug.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libjucedebug.a; + remoteRef = 84FFAEFB0C6C8E76009F6E72 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 8D0C4E8C0486CD37000505A6 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8D0C4E8F0486CD37000505A6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84FFAEAC0C6C8A6F009F6E72 /* FilterGraph.cpp in Sources */, + 84FFAEAD0C6C8A6F009F6E72 /* GraphEditorPanel.cpp in Sources */, + 84FFAEAE0C6C8A6F009F6E72 /* InternalFilters.cpp in Sources */, + 84FFAEAF0C6C8A6F009F6E72 /* MainHostWindow.cpp in Sources */, + 84FFAEB00C6C8A6F009F6E72 /* HostStartup.cpp in Sources */, + 84FFAEB10C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp in Sources */, + 84FFAEB20C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp in Sources */, + 84FFAEB30C6C8A6F009F6E72 /* juce_KnownPluginList.cpp in Sources */, + 84FFAEB40C6C8A6F009F6E72 /* juce_PluginDescription.cpp in Sources */, + 84FFAEB50C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp in Sources */, + 84FFAEB60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp in Sources */, + 84FFAEB70C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + C0E91AC608A95435008D54AB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ppc; + COPY_PHASE_STRIP = NO; + }; + name = Debug; + }; + C0E91AC708A95435008D54AB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ppc; + DEAD_CODE_STRIPPING = YES; + INSTALL_PATH = "$(HOME)/Applications"; + PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES; + }; + name = Release; + }; + C0E91ACA08A95435008D54AB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_OPTIMIZATION_LEVEL = 0; + PRODUCT_NAME = "Juce Plugin Host"; + USER_HEADER_SEARCH_PATHS = "~/stuff/vstsdk2.4 $(inherited)"; + ZERO_LINK = NO; + }; + name = Debug; + }; + C0E91ACB08A95435008D54AB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + PRODUCT_NAME = "Juce Plugin Host"; + SEPARATE_STRIP = YES; + USER_HEADER_SEARCH_PATHS = "~/stuff/vstsdk2.4 $(inherited)"; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C0E91AC508A95435008D54AB /* Build configuration list for PBXNativeTarget "PluginHost" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C0E91AC608A95435008D54AB /* Debug */, + C0E91AC708A95435008D54AB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C0E91AC908A95435008D54AB /* Build configuration list for PBXProject "PluginHost" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C0E91ACA08A95435008D54AB /* Debug */, + C0E91ACB08A95435008D54AB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 20286C28FDCF999611CA2CEA /* Project object */; +} diff --git a/extras/audio plugin host/build/win32/PluginHost.sln b/extras/audio plugin host/build/win32/PluginHost.sln new file mode 100644 index 0000000000..96e4ee242d --- /dev/null +++ b/extras/audio plugin host/build/win32/PluginHost.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginHost", "PluginHost.vcproj", "{A20203D2-E1C3-48E3-89DD-401D5731DCC0}" + ProjectSection(ProjectDependencies) = postProject + {AE232C11-D91C-4CA1-B24E-8B11A52EFF26} = {AE232C11-D91C-4CA1-B24E-8B11A52EFF26} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JUCE", "..\..\..\..\build\win32\vc8\JUCE.vcproj", "{AE232C11-D91C-4CA1-B24E-8B11A52EFF26}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + DLL Debug|Win32 = DLL Debug|Win32 + DLL Release|Win32 = DLL Release|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A20203D2-E1C3-48E3-89DD-401D5731DCC0}.Debug|Win32.ActiveCfg = Debug|Win32 + {A20203D2-E1C3-48E3-89DD-401D5731DCC0}.Debug|Win32.Build.0 = Debug|Win32 + {A20203D2-E1C3-48E3-89DD-401D5731DCC0}.DLL Debug|Win32.ActiveCfg = Debug|Win32 + {A20203D2-E1C3-48E3-89DD-401D5731DCC0}.DLL Debug|Win32.Build.0 = Debug|Win32 + {A20203D2-E1C3-48E3-89DD-401D5731DCC0}.DLL Release|Win32.ActiveCfg = Release|Win32 + {A20203D2-E1C3-48E3-89DD-401D5731DCC0}.DLL Release|Win32.Build.0 = Release|Win32 + {A20203D2-E1C3-48E3-89DD-401D5731DCC0}.Release|Win32.ActiveCfg = Release|Win32 + {A20203D2-E1C3-48E3-89DD-401D5731DCC0}.Release|Win32.Build.0 = Release|Win32 + {AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.Debug|Win32.ActiveCfg = Debug|Win32 + {AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.Debug|Win32.Build.0 = Debug|Win32 + {AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.Release|Win32.ActiveCfg = Release|Win32 + {AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/extras/audio plugin host/build/win32/PluginHost.suo b/extras/audio plugin host/build/win32/PluginHost.suo new file mode 100644 index 0000000000..5bd63ee344 Binary files /dev/null and b/extras/audio plugin host/build/win32/PluginHost.suo differ diff --git a/extras/audio plugin host/build/win32/PluginHost.vcproj b/extras/audio plugin host/build/win32/PluginHost.vcproj new file mode 100644 index 0000000000..a3081568d1 --- /dev/null +++ b/extras/audio plugin host/build/win32/PluginHost.vcproj @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extras/audio plugin host/src/HostStartup.cpp b/extras/audio plugin host/src/HostStartup.cpp new file mode 100644 index 0000000000..2be3a8ed7b --- /dev/null +++ b/extras/audio plugin host/src/HostStartup.cpp @@ -0,0 +1,110 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "../../../juce.h" +#include "host/MainHostWindow.h" +#include "host/InternalFilters.h" + + +ApplicationCommandManager* commandManager = 0; + + +//============================================================================== +class PluginHostApp : public JUCEApplication +{ + MainHostWindow* mainWindow; + +public: + //============================================================================== + PluginHostApp() + : mainWindow (0) + { + } + + ~PluginHostApp() + { + } + + void initialise (const String& /*commandLine*/) + { + // initialise our settings file.. + ApplicationProperties::getInstance() + ->setStorageParameters (T("Juce Audio Plugin Host"), + T("settings"), String::empty, 1000, + PropertiesFile::storeAsXML); + + commandManager = new ApplicationCommandManager(); + + AudioPluginFormatManager::getInstance()->addDefaultFormats(); + AudioPluginFormatManager::getInstance()->addFormat (new InternalPluginFormat()); + + mainWindow = new MainHostWindow(); + + commandManager->registerAllCommandsForTarget (this); + commandManager->registerAllCommandsForTarget (mainWindow); + } + + void shutdown() + { + deleteAndZero (mainWindow); + + ApplicationProperties::getInstance()->closeFiles(); + + deleteAndZero (commandManager); + } + + const String getApplicationName() + { + return T("Juce Plug-In Host"); + } + + const String getApplicationVersion() + { + return T("0.9"); + } + + void systemRequestedQuit() + { + if (mainWindow->isValidComponent()) + mainWindow->tryToQuitApplication(); + else + JUCEApplication::quit(); + } + + bool moreThanOneInstanceAllowed() + { + return true; + } +}; + + +// This kicks the whole thing off.. +START_JUCE_APPLICATION (PluginHostApp) diff --git a/extras/audio plugin host/src/host/FilterGraph.cpp b/extras/audio plugin host/src/host/FilterGraph.cpp new file mode 100644 index 0000000000..430643a517 --- /dev/null +++ b/extras/audio plugin host/src/host/FilterGraph.cpp @@ -0,0 +1,744 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "FilterGraph.h" +#include "InternalFilters.h" + + +//============================================================================== +FilterConnection::FilterConnection (FilterGraph& owner_) + : owner (owner_) +{ +} + +FilterConnection::FilterConnection (const FilterConnection& other) + : sourceFilterID (other.sourceFilterID), + sourceChannel (other.sourceChannel), + destFilterID (other.destFilterID), + destChannel (other.destChannel), + owner (other.owner) +{ +} + +FilterConnection::~FilterConnection() +{ +} + + +//============================================================================== +class PluginWindow : public DocumentWindow +{ +public: + PluginWindow (Component* const uiComp, + FilterInGraph& owner_) + : DocumentWindow (uiComp->getName(), Colours::lightblue, + DocumentWindow::minimiseButton | DocumentWindow::closeButton), + owner (owner_) + { + setSize (400, 300); + + setContentComponent (uiComp, true, true); + + setTopLeftPosition (owner.lastX, owner.lastY); + setVisible (true); + } + + ~PluginWindow() + { + setContentComponent (0); + } + + void moved() + { + owner.lastX = getX(); + owner.lastY = getY(); + } + + void closeButtonPressed() + { + owner.activeUI = 0; + delete this; + } + +private: + FilterInGraph& owner; +}; + + +//============================================================================== +FilterInGraph::FilterInGraph (FilterGraph& owner_, AudioPluginInstance* const filter_) + : owner (owner_), + filter (filter_), + uid (0), + processedAudio (1, 1), + inputAudio (1, 1), + activeUI (0) +{ + lastX = 100 + Random::getSystemRandom().nextInt (400); + lastY = 100 + Random::getSystemRandom().nextInt (400); +} + +FilterInGraph::~FilterInGraph() +{ + delete activeUI; + delete filter; +} + +void FilterInGraph::setPosition (double newX, double newY) throw() +{ + x = jlimit (0.0, 1.0, newX); + y = jlimit (0.0, 1.0, newY); +} + +void FilterInGraph::showUI() +{ + if (activeUI == 0) + { + Component* ui = filter->createEditorIfNeeded(); + + if (ui != 0) + { + ui->setName (filter->getName()); + activeUI = new PluginWindow (ui, *this); + } + } + + if (activeUI != 0) + activeUI->toFront (true); +} + +void FilterInGraph::prepareBuffers (int blockSize) +{ + processedAudio.setSize (jmax (1, filter->getNumOutputChannels()), blockSize); + inputAudio.setSize (jmax (1, filter->getNumInputChannels()), blockSize); + processedAudio.clear(); + + processedMidi.clear(); +} + +void FilterInGraph::renderBlock (int numSamples, + const ReferenceCountedArray & filters, + const OwnedArray & connections) +{ + processedAudio.setSize (jmax (1, filter->getNumOutputChannels()), numSamples); + inputAudio.setSize (jmax (1, filter->getNumInputChannels()), numSamples); + + // this isn't particularly efficient - could do with some optimising here + inputAudio.clear(); + processedAudio.clear(); + processedMidi.clear(); + + for (int i = connections.size(); --i >= 0;) + { + const FilterConnection* const fc = connections.getUnchecked(i); + + if (fc->destFilterID == uid) + { + for (int j = filters.size(); --j >= 0;) + { + const FilterInGraph* const input = filters.getUnchecked(j); + + if (filters.getUnchecked(j)->uid == fc->sourceFilterID) + { + if (fc->sourceChannel == FilterGraph::midiChannelNumber) + { + processedMidi.addEvents (input->processedMidi, 0, numSamples, 0); + } + else + { + inputAudio.addFrom (fc->destChannel, 0, input->processedAudio, + fc->sourceChannel, 0, numSamples); + } + + break; + } + } + } + } + + filter->processBlock (inputAudio, processedAudio, true, processedMidi); +} + +XmlElement* FilterInGraph::createXml() const +{ + XmlElement* e = new XmlElement ("FILTER"); + e->setAttribute (T("uid"), (int) uid); + e->setAttribute (T("x"), x); + e->setAttribute (T("y"), y); + e->setAttribute (T("uiLastX"), lastX); + e->setAttribute (T("uiLastY"), lastY); + + PluginDescription pd; + pd.fillInFromInstance (*filter); + e->addChildElement (pd.createXml()); + + XmlElement* state = new XmlElement ("STATE"); + + juce::MemoryBlock m; + filter->getStateInformation (m); + state->addTextElement (m.toBase64Encoding()); + e->addChildElement (state); + + return e; +} + +FilterInGraph* FilterInGraph::createForDescription (FilterGraph& owner, const PluginDescription& desc) +{ + AudioPluginInstance* instance = desc.createInstance(); + + if (instance != 0) + return new FilterInGraph (owner, instance); + + return 0; +} + +FilterInGraph* FilterInGraph::createFromXml (FilterGraph& owner, const XmlElement& xml) +{ + PluginDescription pd; + + forEachXmlChildElement (xml, e) + { + if (pd.loadFromXml (*e)) + break; + } + + FilterInGraph* const c = createForDescription (owner, pd); + + if (c == 0) + return 0; + + const XmlElement* const state = xml.getChildByName (T("STATE")); + + if (state != 0) + { + juce::MemoryBlock m; + m.fromBase64Encoding (state->getAllSubText()); + + c->filter->setStateInformation (m.getData(), m.getSize()); + } + + c->uid = xml.getIntAttribute (T("uid")); + c->x = xml.getDoubleAttribute (T("x")); + c->y = xml.getDoubleAttribute (T("y")); + c->lastX = xml.getIntAttribute (T("uiLastX"), c->lastX); + c->lastY = xml.getIntAttribute (T("uiLastY"), c->lastY); + + return c; +} + + +//============================================================================== +const int FilterGraph::midiChannelNumber = 0x1000; + +FilterGraph::FilterGraph() + : FileBasedDocument (filenameSuffix, + filenameWildcard, + "Load a filter graph", + "Save a filter graph"), + lastUID (0) +{ + InternalPluginFormat internalFormat; + + addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioInputFilter), + 0.5f, 0.1f); + + addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::midiInputFilter), + 0.25f, 0.1f); + + addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioOutputFilter), + 0.5f, 0.9f); + + setChangedFlag (false); +} + +FilterGraph::~FilterGraph() +{ + clear(); +} + +uint32 FilterGraph::getNextUID() throw() +{ + return ++lastUID; +} + +//============================================================================== +const String FilterGraph::getDocumentTitle() +{ + if (! getFile().exists()) + return "Unnamed"; + + return getFile().getFileNameWithoutExtension(); +} + +const String FilterGraph::loadDocument (const File& file) +{ + XmlDocument doc (file); + XmlElement* xml = doc.getDocumentElement(); + + if (xml == 0 || ! xml->hasTagName (T("FILTERGRAPH"))) + { + delete xml; + return "Not a valid filter graph file"; + } + + restoreFromXml (*xml); + delete xml; + + return String::empty; +} + +const String FilterGraph::saveDocument (const File& file) +{ + XmlElement* xml = createXml(); + + String error; + + if (! xml->writeToFile (file, String::empty)) + error = "Couldn't write to the file"; + + delete xml; + return error; +} + +const File FilterGraph::getLastDocumentOpened() +{ + RecentlyOpenedFilesList recentFiles; + recentFiles.restoreFromString (ApplicationProperties::getInstance()->getUserSettings() + ->getValue ("recentFilterGraphFiles")); + + return recentFiles.getFile (0); +} + +void FilterGraph::setLastDocumentOpened (const File& file) +{ + RecentlyOpenedFilesList recentFiles; + recentFiles.restoreFromString (ApplicationProperties::getInstance()->getUserSettings() + ->getValue ("recentFilterGraphFiles")); + + recentFiles.addFile (file); + + ApplicationProperties::getInstance()->getUserSettings() + ->setValue ("recentFilterGraphFiles", recentFiles.toString()); +} + +//============================================================================== +FilterInGraph* FilterGraph::getFilterForUID (const uint32 uid) const throw() +{ + for (int i = filters.size(); --i >= 0;) + if (filters.getUnchecked(i)->uid == uid) + return filters.getUnchecked(i); + + return 0; +} + +void FilterGraph::addFilter (const FilterInGraph::Ptr& newFilter) +{ + if (newFilter->uid == 0) + newFilter->uid = getNextUID(); + else if (newFilter->uid > lastUID) + lastUID = newFilter->uid; + + filters.add (newFilter); + + changed(); +} + +void FilterGraph::addFilter (const PluginDescription* desc, double x, double y) +{ + if (desc != 0) + { + FilterInGraph* cf = FilterInGraph::createForDescription (*this, *desc); + + if (cf != 0) + { + cf->setPosition (x, y); + addFilter (cf); + } + } +} + +void FilterGraph::removeFilter (const uint32 uid) +{ + FilterInGraph* const filter = getFilterForUID (uid); + + if (filter != 0) + { + disconnectFilter (uid); + + filters.removeObject (filter); + changed(); + } +} + +void FilterGraph::disconnectFilter (const uint32 uid) +{ + for (int i = connections.size(); --i >= 0;) + { + const FilterConnection* const fc = connections.getUnchecked(i); + + if (fc->sourceFilterID == uid + || fc->destFilterID == uid) + { + removeConnection (i); + } + } +} + +bool FilterGraph::isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination, int recursionCheck) const throw() +{ + if (recursionCheck > 0) + { + for (int i = 0; i < connections.size(); ++i) + { + if (connections.getUnchecked(i)->destFilterID == possibleDestination + && (connections.getUnchecked(i)->sourceFilterID == possibleInput + || isAnInputTo (possibleInput, connections.getUnchecked(i)->sourceFilterID, recursionCheck - 1))) + return true; + } + } + + return false; +} + +bool FilterGraph::isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination) const throw() +{ + return isAnInputTo (possibleInput, possibleDestination, filters.size() + 1); +} + +FilterConnection* FilterGraph::getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel, + uint32 destFilterUID, int destFilterChannel) const throw() +{ + for (int i = connections.size(); --i >= 0;) + { + FilterConnection* const fc = connections.getUnchecked(i); + + if (fc->sourceFilterID == sourceFilterUID + && fc->sourceChannel == sourceFilterChannel + && fc->destFilterID == destFilterUID + && fc->destChannel == destFilterChannel) + { + return fc; + } + } + + return 0; +} + +bool FilterGraph::canConnect (uint32 sourceFilterUID, int sourceFilterChannel, + uint32 destFilterUID, int destFilterChannel) const throw() +{ + if (sourceFilterChannel < 0 + || destFilterChannel < 0 + || sourceFilterUID == destFilterUID + || (destFilterChannel == midiChannelNumber) != (sourceFilterChannel == midiChannelNumber)) + return false; + + const FilterInGraph* const source = getFilterForUID (sourceFilterUID); + + if (source == 0 + || (sourceFilterChannel != midiChannelNumber && (sourceFilterChannel < 0 || sourceFilterChannel >= source->filter->getNumOutputChannels())) + || (sourceFilterChannel == midiChannelNumber && ! source->filter->producesMidi())) + return false; + + const FilterInGraph* const dest = getFilterForUID (destFilterUID); + + if (dest == 0 + || (destFilterChannel != midiChannelNumber && (destFilterChannel < 0 || destFilterChannel >= dest->filter->getNumInputChannels())) + || (destFilterChannel == midiChannelNumber && ! dest->filter->acceptsMidi())) + return false; + + if (getConnectionBetween (sourceFilterUID, sourceFilterChannel, destFilterUID, destFilterChannel) != 0) + return false; + + return true; +} + +void FilterGraph::addConnection (uint32 sourceFilterUID, int sourceChannel, + uint32 destFilterUID, int destChannel) +{ + if (canConnect (sourceFilterUID, sourceChannel, destFilterUID, destChannel)) + { + FilterConnection* const conn = new FilterConnection (*this); + + conn->sourceFilterID = sourceFilterUID; + conn->sourceChannel = sourceChannel; + conn->destFilterID = destFilterUID; + conn->destChannel = destChannel; + + connections.add (conn); + changed(); + } +} + +void FilterGraph::removeConnection (const int index) +{ + if (connections [index] != 0) + { + connections.remove (index); + changed(); + } +} + +void FilterGraph::removeConnection (uint32 sourceFilterUID, int sourceFilterChannel, + uint32 destFilterUID, int destFilterChannel) +{ + for (int i = connections.size(); --i >= 0;) + { + const FilterConnection* const fc = connections.getUnchecked(i); + + if (fc->sourceFilterID == sourceFilterUID + && fc->sourceChannel == sourceFilterChannel + && fc->destFilterID == destFilterUID + && fc->destChannel == destFilterChannel) + { + removeConnection (i); + } + } +} + +void FilterGraph::clear() +{ + connections.clear(); + filters.clear(); + changed(); +} + +XmlElement* FilterGraph::createXml() const +{ + XmlElement* xml = new XmlElement ("FILTERGRAPH"); + + int i; + for (i = 0; i < filters.size(); ++i) + xml->addChildElement (filters.getUnchecked(i)->createXml()); + + for (i = 0; i < connections.size(); ++i) + { + const FilterConnection* const fc = connections.getUnchecked(i); + + XmlElement* e = new XmlElement ("CONNECTION"); + + e->setAttribute (T("srcFilter"), (int) fc->sourceFilterID); + e->setAttribute (T("srcChannel"), fc->sourceChannel); + e->setAttribute (T("dstFilter"), (int) fc->destFilterID); + e->setAttribute (T("dstChannel"), fc->destChannel); + + xml->addChildElement (e); + } + + return xml; +} + +void FilterGraph::restoreFromXml (const XmlElement& xml) +{ + clear(); + + forEachXmlChildElementWithTagName (xml, e, T("FILTER")) + { + FilterInGraph* f = FilterInGraph::createFromXml (*this, *e); + + if (f != 0) + addFilter (f); + } + + forEachXmlChildElementWithTagName (xml, e, T("CONNECTION")) + { + addConnection ((uint32) e->getIntAttribute (T("srcFilter")), + e->getIntAttribute (T("srcChannel")), + (uint32) e->getIntAttribute (T("dstFilter")), + e->getIntAttribute (T("dstChannel"))); + } +} + +//============================================================================== +FilterGraphPlayer::FilterGraphPlayer() + : sampleRate (44100.0), + blockSize (512), + deviceManager (0), + inputChannelData (0), + totalNumInputChannels (0), + outputChannelData (0), + totalNumOutputChannels (0) +{ + setAudioDeviceManager (0); + keyState.addListener (&messageCollector); +} + +FilterGraphPlayer::~FilterGraphPlayer() +{ + keyState.removeListener (&messageCollector); +} + +void FilterGraphPlayer::setAudioDeviceManager (AudioDeviceManager* dm) +{ + if (deviceManager != 0) + { + deviceManager->removeMidiInputCallback (this); + deviceManager->setAudioCallback (0); + } + + deviceManager = dm; + + if (dm != 0) + { + dm->addMidiInputCallback (String::empty, this); + dm->setAudioCallback (this); + } +} + +int FilterGraphPlayer::compareElements (FilterInGraph* const first, FilterInGraph* const second) throw() +{ + const bool firstIsInputToSecond = first->owner.isAnInputTo (first->uid, second->uid); + const bool secondInInputToFirst = first->owner.isAnInputTo (second->uid, first->uid); + + if (firstIsInputToSecond == secondInInputToFirst) + return 0; + + return firstIsInputToSecond ? -1 : 1; +} + +void FilterGraphPlayer::updateFrom (FilterGraph* graphToUse) +{ + ReferenceCountedArray filtersBeingRemoved (filters); + + if (graphToUse != 0) + { + ReferenceCountedArray newFilters (graphToUse->filters); + int i; + for (i = newFilters.size(); --i >= 0;) + if (filters.contains (newFilters.getUnchecked(i))) + newFilters.remove (i); + + for (i = filtersBeingRemoved.size(); --i >= 0;) + if (graphToUse->filters.contains (filtersBeingRemoved.getUnchecked(i))) + filtersBeingRemoved.remove (i); + + // prepare any new filters for use.. + for (i = 0; i < newFilters.size(); ++i) + newFilters.getUnchecked(i)->filter->prepareToPlay (sampleRate, blockSize); + + ReferenceCountedArray sortedFilters (graphToUse->filters); + sortedFilters.sort (*this, true); + + for (i = sortedFilters.size(); --i >= 0;) + { + PlayerAwareFilter* const specialFilter = dynamic_cast (sortedFilters.getUnchecked(i)->filter); + + if (specialFilter != 0) + specialFilter->setPlayer (this); + } + + { + const ScopedLock sl (processLock); + + filters = sortedFilters; + connections.clear(); + + for (int i = 0; i < graphToUse->connections.size(); ++i) + connections.add (new FilterConnection (*graphToUse->connections.getUnchecked(i))); + } + } + else + { + const ScopedLock sl (processLock); + + filters.clear(); + connections.clear(); + } + + // release any old ones.. + for (int i = 0; i < filtersBeingRemoved.size(); ++i) + { + filtersBeingRemoved.getUnchecked(i)->filter->releaseResources(); + + PlayerAwareFilter* const specialFilter = dynamic_cast (filtersBeingRemoved.getUnchecked(i)->filter); + + if (specialFilter != 0) + specialFilter->setPlayer (0); + } +} + +void FilterGraphPlayer::audioDeviceIOCallback (const float** inputChannelData_, + int totalNumInputChannels_, + float** outputChannelData_, + int totalNumOutputChannels_, + int numSamples) +{ + incomingMidi.clear(); + messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples); + + for (int i = 0; i < totalNumOutputChannels_; ++i) + if (outputChannelData_[i] != 0) + zeromem (outputChannelData_[i], sizeof (float) * numSamples); + + const ScopedLock sl (processLock); + + inputChannelData = inputChannelData_; + totalNumInputChannels = totalNumInputChannels_; + outputChannelData = outputChannelData_; + totalNumOutputChannels = totalNumOutputChannels_; + + for (int i = 0; i < filters.size(); ++i) + { + FilterInGraph* const cf = filters.getUnchecked(i); + + cf->renderBlock (numSamples, filters, connections); + } +} + +void FilterGraphPlayer::audioDeviceAboutToStart (double sampleRate_, int numSamplesPerBlock) +{ + const ScopedLock sl (processLock); + + sampleRate = sampleRate_; + blockSize = numSamplesPerBlock; + + messageCollector.reset (sampleRate_); + + for (int i = 0; i < filters.size(); ++i) + { + filters.getUnchecked(i)->prepareBuffers (blockSize); + filters.getUnchecked(i)->filter->prepareToPlay (sampleRate, blockSize); + } +} + +void FilterGraphPlayer::audioDeviceStopped() +{ + const ScopedLock sl (processLock); + + for (int i = 0; i < filters.size(); ++i) + filters.getUnchecked(i)->filter->releaseResources(); +} + +void FilterGraphPlayer::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message) +{ +// keyState.processNextMidiEvent (message); + messageCollector.addMessageToQueue (message); +} diff --git a/extras/audio plugin host/src/host/FilterGraph.h b/extras/audio plugin host/src/host/FilterGraph.h new file mode 100644 index 0000000000..fdc0b63af9 --- /dev/null +++ b/extras/audio plugin host/src/host/FilterGraph.h @@ -0,0 +1,269 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_FILTERGRAPH_JUCEHEADER__ +#define __JUCE_FILTERGRAPH_JUCEHEADER__ + +#include "../plugins/juce_AudioPluginInstance.h" +#include "../plugins/juce_PluginDescription.h" + +class FilterInGraph; +class FilterGraph; +class FilterGraphPlayer; + +const char* const filenameSuffix = ".filtergraph"; +const char* const filenameWildcard = "*.filtergraph"; + + +//============================================================================== +/** + Represents a connection between two pins in a FilterGraph. +*/ +class FilterConnection +{ +public: + //============================================================================== + FilterConnection (FilterGraph& owner); + FilterConnection (const FilterConnection& other); + ~FilterConnection(); + + //============================================================================== + uint32 sourceFilterID; + int sourceChannel; + uint32 destFilterID; + int destChannel; + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + FilterGraph& owner; + + const FilterConnection& operator= (const FilterConnection&); +}; + + +//============================================================================== +/** + Represents one of the filters in a FilterGraph. +*/ +class FilterInGraph : public ReferenceCountedObject +{ +public: + //============================================================================== + FilterInGraph (FilterGraph& owner, AudioPluginInstance* const plugin); + ~FilterInGraph(); + + //============================================================================== + AudioPluginInstance* const filter; + uint32 uid; + + //============================================================================== + void showUI(); + + double getX() const throw() { return x; } + double getY() const throw() { return y; } + void setPosition (double x, double y) throw(); + + XmlElement* createXml() const; + + static FilterInGraph* createForDescription (FilterGraph& owner, const PluginDescription& desc); + static FilterInGraph* createFromXml (FilterGraph& owner, const XmlElement& xml); + + //============================================================================== + typedef ReferenceCountedObjectPtr Ptr; + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + friend class FilterGraphPlayer; + FilterGraph& owner; + double x, y; + + friend class PluginWindow; + Component* activeUI; + int lastX, lastY; + + MidiBuffer outputMidi; + AudioSampleBuffer inputAudio, processedAudio; + MidiBuffer processedMidi; + + void prepareBuffers (int blockSize); + void renderBlock (int numSamples, + const ReferenceCountedArray & filters, + const OwnedArray & connections); + + FilterInGraph (const FilterInGraph&); + const FilterInGraph& operator= (const FilterInGraph&); +}; + + +//============================================================================== +/** + A collection of filters and some connections between them. +*/ +class FilterGraph : public FileBasedDocument +{ +public: + //============================================================================== + FilterGraph(); + ~FilterGraph(); + + //============================================================================== + int getNumFilters() const throw() { return filters.size(); } + FilterInGraph* getFilter (const int index) const throw() { return filters [index]; } + FilterInGraph* getFilterForUID (const uint32 uid) const throw(); + + void addFilter (const FilterInGraph::Ptr& newFilter); + void addFilter (const PluginDescription* desc, double x, double y); + + void removeFilter (const uint32 filterUID); + void disconnectFilter (const uint32 filterUID); + + //============================================================================== + int getNumConnections() const throw() { return connections.size(); } + FilterConnection* getConnection (const int index) const throw() { return connections [index]; } + + FilterConnection* getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel, + uint32 destFilterUID, int destFilterChannel) const throw(); + + bool isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination) const throw(); + + bool canConnect (uint32 sourceFilterUID, int sourceFilterChannel, + uint32 destFilterUID, int destFilterChannel) const throw(); + + void addConnection (uint32 sourceFilterUID, int sourceFilterChannel, + uint32 destFilterUID, int destFilterChannel); + + void removeConnection (const int index); + + void removeConnection (uint32 sourceFilterUID, int sourceFilterChannel, + uint32 destFilterUID, int destFilterChannel); + + void clear(); + + XmlElement* createXml() const; + void restoreFromXml (const XmlElement& xml); + + //============================================================================== + const String getDocumentTitle(); + const String loadDocument (const File& file); + const String saveDocument (const File& file); + const File getLastDocumentOpened(); + void setLastDocumentOpened (const File& file); + + /** The special channel index used to refer to a filter's midi channel. + */ + static const int midiChannelNumber; + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + friend class FilterGraphPlayer; + ReferenceCountedArray filters; + OwnedArray connections; + + uint32 lastUID; + uint32 getNextUID() throw(); + + bool isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination, int recursionCheck) const throw(); + + FilterGraph (const FilterGraph&); + const FilterGraph& operator= (const FilterGraph&); +}; + + +//============================================================================== +/** + An object the +*/ +class FilterGraphPlayer : public AudioIODeviceCallback, + public MidiInputCallback + +{ +public: + //============================================================================== + FilterGraphPlayer(); + ~FilterGraphPlayer(); + + //============================================================================== + void updateFrom (FilterGraph* graphToUse); + + void setAudioDeviceManager (AudioDeviceManager* dm); + AudioDeviceManager* getAudioDeviceManager() const throw() { return deviceManager; } + + //============================================================================== + void audioDeviceIOCallback (const float** inputChannelData, + int totalNumInputChannels, + float** outputChannelData, + int totalNumOutputChannels, + int numSamples); + void audioDeviceAboutToStart (double sampleRate, int numSamplesPerBlock); + void audioDeviceStopped(); + + void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message); + + //============================================================================== + static int compareElements (FilterInGraph* const first, FilterInGraph* const second) throw(); + + const float** inputChannelData; + int totalNumInputChannels; + float** outputChannelData; + int totalNumOutputChannels; + MidiBuffer incomingMidi; + + MidiKeyboardState keyState; + MidiMessageCollector messageCollector; + + //============================================================================== + class PlayerAwareFilter + { + public: + virtual void setPlayer (FilterGraphPlayer* newPlayer) = 0; + }; + +private: + CriticalSection processLock; + double sampleRate; + int blockSize; + AudioDeviceManager* deviceManager; + + ReferenceCountedArray filters; + OwnedArray connections; + + FilterGraphPlayer (const FilterGraphPlayer&); + const FilterGraphPlayer& operator= (const FilterGraphPlayer&); +}; + + +#endif diff --git a/extras/audio plugin host/src/host/GraphEditorPanel.cpp b/extras/audio plugin host/src/host/GraphEditorPanel.cpp new file mode 100644 index 0000000000..394d4e0ef2 --- /dev/null +++ b/extras/audio plugin host/src/host/GraphEditorPanel.cpp @@ -0,0 +1,901 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "../../../../juce.h" +#include "GraphEditorPanel.h" +#include "InternalFilters.h" +#include "MainHostWindow.h" + + +//============================================================================== +class PinComponent : public Component +{ +public: + PinComponent (FilterGraph& graph_, + const uint32 filterID_, const int index_, const bool isInput_) + : graph (graph_), + filterID (filterID_), + index (index_), + isInput (isInput_) + { + setSize (16, 16); + } + + ~PinComponent() + { + } + + void paint (Graphics& g) + { + const float w = (float) getWidth(); + const float h = (float) getHeight(); + + Path p; + p.addEllipse (w * 0.25f, h * 0.25f, w * 0.5f, h * 0.5f); + + p.addRectangle (w * 0.4f, isInput ? (0.5f * h) : 0.0f, w * 0.2f, h * 0.5f); + + g.setColour (index == FilterGraph::midiChannelNumber ? Colours::red : Colours::green); + g.fillPath (p); + } + + void mouseDown (const MouseEvent& e) + { + getGraphPanel()->beginConnectorDrag (isInput ? 0 : filterID, + index, + isInput ? filterID : 0, + index, + e); + } + + void mouseDrag (const MouseEvent& e) + { + getGraphPanel()->dragConnector (e); + } + + void mouseUp (const MouseEvent& e) + { + getGraphPanel()->endDraggingConnector (e); + } + + juce_UseDebuggingNewOperator + + const uint32 filterID; + const int index; + const bool isInput; + +private: + FilterGraph& graph; + + PinComponent (const PinComponent&); + const PinComponent& operator= (const PinComponent&); + + GraphEditorPanel* getGraphPanel() const throw() + { + return findParentComponentOfClass ((GraphEditorPanel*) 0); + } +}; + +//============================================================================== +class FilterComponent : public Component +{ +public: + FilterComponent (FilterGraph& graph_, + const uint32 filterID_) + : graph (graph_), + filterID (filterID_), + numInputs (0), + numOutputs (0), + pinSize (16), + originalX (0), + originalY (0), + font (13.0f, Font::bold), + numIns (0), + numOuts (0) + { + shadow.setShadowProperties (2.5f, 0.5f, -1, 0); + setComponentEffect (&shadow); + + setSize (150, 60); + } + + ~FilterComponent() + { + deleteAllChildren(); + } + + void mouseDown (const MouseEvent& e) + { + originalX = 0; + originalY = 0; + relativePositionToGlobal (originalX, originalY); + + toFront (true); + + if (e.mods.isPopupMenu()) + { + PopupMenu m; + m.addItem (1, "Delete this filter"); + m.addItem (2, "Disconnect all pins"); + + const int r = m.show(); + + if (r == 1) + { + graph.removeFilter (filterID); + return; + } + else if (r == 2) + { + graph.disconnectFilter (filterID); + } + } + } + + void mouseDrag (const MouseEvent& e) + { + if (! e.mods.isPopupMenu()) + { + int x = originalX + e.getDistanceFromDragStartX(); + int y = originalY + e.getDistanceFromDragStartY(); + + if (getParentComponent() != 0) + getParentComponent()->globalPositionToRelative (x, y); + + const FilterInGraph::Ptr f (graph.getFilterForUID (filterID)); + + if (f != 0) + { + f->setPosition ((x + getWidth() / 2) / (double) getParentWidth(), + (y + getHeight() / 2) / (double) getParentHeight()); + + getGraphPanel()->updateComponents(); + } + } + } + + void mouseUp (const MouseEvent& e) + { + if (e.mouseWasClicked() && e.getNumberOfClicks() == 2) + { + const FilterInGraph::Ptr f (graph.getFilterForUID (filterID)); + + if (f != 0) + f->showUI(); + } + else if (! e.mouseWasClicked()) + { + graph.setChangedFlag (true); + } + } + + bool hitTest (int x, int y) + { + for (int i = getNumChildComponents(); --i >= 0;) + if (getChildComponent(i)->getBounds().contains (x, y)) + return true; + + return x >= 3 && x < getWidth() - 6 && y >= pinSize && y < getHeight() - pinSize; + } + + void paint (Graphics& g) + { + g.setColour (Colours::lightgrey); + + const int x = 4; + const int y = pinSize; + const int w = getWidth() - x * 2; + const int h = getHeight() - pinSize * 2; + + g.fillRect (x, y, w, h); + + g.setColour (Colours::black); + g.setFont (font); + g.drawFittedText (getName(), + x + 4, y + 2, w - 8, h - 4, + Justification::centred, 2); + + g.setColour (Colours::grey); + g.drawRect (x, y, w, h); + } + + void resized() + { + for (int i = 0; i < getNumChildComponents(); ++i) + { + PinComponent* const pc = dynamic_cast (getChildComponent(i)); + + if (pc != 0) + { + const int total = pc->isInput ? numIns : numOuts; + const int index = pc->index == FilterGraph::midiChannelNumber ? (total - 1) : pc->index; + + pc->setBounds (proportionOfWidth ((1 + index) / (total + 1.0f)) - pinSize / 2, + pc->isInput ? 0 : (getHeight() - pinSize), + pinSize, pinSize); + } + } + } + + void getPinPos (const int index, const bool isInput, float& x, float& y) + { + for (int i = 0; i < getNumChildComponents(); ++i) + { + PinComponent* const pc = dynamic_cast (getChildComponent(i)); + + if (pc != 0 && pc->index == index && isInput == pc->isInput) + { + x = getX() + pc->getX() + pc->getWidth() * 0.5f; + y = getY() + pc->getY() + pc->getHeight() * 0.5f; + break; + } + } + } + + void update() + { + const FilterInGraph* const f = graph.getFilterForUID (filterID); + + if (f == 0) + { + delete this; + return; + } + + numIns = f->filter->getNumInputChannels(); + if (f->filter->acceptsMidi()) + ++numIns; + + numOuts = f->filter->getNumOutputChannels(); + if (f->filter->producesMidi()) + ++numOuts; + + int w = 100; + int h = 60; + + w = jmax (w, (jmax (numIns, numOuts) + 1) * 20); + + const int textWidth = font.getStringWidth (f->filter->getName()); + w = jmax (w, 16 + jmin (textWidth, 300)); + if (textWidth > 300) + h = 100; + + setSize (w, h); + + setCentreRelative ((float) f->getX(), (float) f->getY()); + + if (numIns != numInputs || numOuts != numOutputs) + { + numInputs = numIns; + numOutputs = numOuts; + + deleteAllChildren(); + + int i; + for (i = 0; i < f->filter->getNumInputChannels(); ++i) + addAndMakeVisible (new PinComponent (graph, filterID, i, true)); + + if (f->filter->acceptsMidi()) + addAndMakeVisible (new PinComponent (graph, filterID, FilterGraph::midiChannelNumber, true)); + + for (i = 0; i < f->filter->getNumOutputChannels(); ++i) + addAndMakeVisible (new PinComponent (graph, filterID, i, false)); + + if (f->filter->producesMidi()) + addAndMakeVisible (new PinComponent (graph, filterID, FilterGraph::midiChannelNumber, false)); + + setName (f->filter->getName()); + + resized(); + } + } + + FilterGraph& graph; + const uint32 filterID; + int numInputs, numOutputs; + +private: + int pinSize; + int originalX, originalY; + int numIns, numOuts; + DropShadowEffect shadow; + Font font; + + GraphEditorPanel* getGraphPanel() const throw() + { + return findParentComponentOfClass ((GraphEditorPanel*) 0); + } + + FilterComponent (const FilterComponent&); + const FilterComponent& operator= (const FilterComponent&); +}; + +//============================================================================== +class ConnectorComponent : public Component +{ +public: + ConnectorComponent (FilterGraph& graph_) + : graph (graph_), + sourceFilterID (0), + destFilterID (0), + sourceFilterChannel (0), + destFilterChannel (0), + lastInputX (0), + lastInputY (0), + lastOutputX (0), + lastOutputY (0) + { + setAlwaysOnTop (true); + } + + ~ConnectorComponent() + { + } + + void setInput (const uint32 sourceFilterID_, const int sourceFilterChannel_) + { + if (sourceFilterID != sourceFilterID_ || sourceFilterChannel != sourceFilterChannel_) + { + sourceFilterID = sourceFilterID_; + sourceFilterChannel = sourceFilterChannel_; + update(); + } + } + + void setOutput (const uint32 destFilterID_, const int destFilterChannel_) + { + if (destFilterID != destFilterID_ || destFilterChannel != destFilterChannel_) + { + destFilterID = destFilterID_; + destFilterChannel = destFilterChannel_; + update(); + } + } + + void dragStart (int x, int y) + { + lastInputX = (float) x; + lastInputY = (float) y; + resizeToFit(); + } + + void dragEnd (int x, int y) + { + lastOutputX = (float) x; + lastOutputY = (float) y; + resizeToFit(); + } + + void update() + { + float x1, y1, x2, y2; + getPoints (x1, y1, x2, y2); + + if (lastInputX != x1 + || lastInputY != y1 + || lastOutputX != x2 + || lastOutputY != y2) + { + resizeToFit(); + } + } + + void resizeToFit() + { + float x1, y1, x2, y2; + getPoints (x1, y1, x2, y2); + + const Rectangle newBounds ((int) jmin (x1, x2) - 4, + (int) jmin (y1, y2) - 4, + (int) abs (x1 - x2) + 8, + (int) abs (y1 - y2) + 8); + + if (newBounds != getBounds()) + setBounds (newBounds); + else + resized(); + + repaint(); + } + + void getPoints (float& x1, float& y1, float& x2, float& y2) const + { + x1 = lastInputX; + y1 = lastInputY; + x2 = lastOutputX; + y2 = lastOutputY; + + GraphEditorPanel* const hostPanel = getGraphPanel(); + + if (hostPanel != 0) + { + FilterComponent* srcFilterComp = hostPanel->getComponentForFilter (sourceFilterID); + + if (srcFilterComp != 0) + srcFilterComp->getPinPos (sourceFilterChannel, false, x1, y1); + + FilterComponent* dstFilterComp = hostPanel->getComponentForFilter (destFilterID); + + if (dstFilterComp != 0) + dstFilterComp->getPinPos (destFilterChannel, true, x2, y2); + } + } + + void paint (Graphics& g) + { + if (sourceFilterChannel == FilterGraph::midiChannelNumber + || destFilterChannel == FilterGraph::midiChannelNumber) + { + g.setColour (Colours::red); + } + else + { + g.setColour (Colours::green); + } + + g.fillPath (linePath); + } + + bool hitTest (int x, int y) + { + if (hitPath.contains ((float) x, (float) y)) + { + double distanceFromStart, distanceFromEnd; + getDistancesFromEnds (x, y, distanceFromStart, distanceFromEnd); + + // avoid clicking the connector when over a pin + return distanceFromStart > 7.0 && distanceFromEnd > 7.0; + } + + return false; + } + + void mouseDown (const MouseEvent&) + { + dragging = false; + } + + void mouseDrag (const MouseEvent& e) + { + if ((! dragging) && ! e.mouseWasClicked()) + { + dragging = true; + + graph.removeConnection (sourceFilterID, sourceFilterChannel, destFilterID, destFilterChannel); + + double distanceFromStart, distanceFromEnd; + getDistancesFromEnds (e.x, e.y, distanceFromStart, distanceFromEnd); + const bool isNearerSource = (distanceFromStart < distanceFromEnd); + + getGraphPanel()->beginConnectorDrag (isNearerSource ? 0 : sourceFilterID, + sourceFilterChannel, + isNearerSource ? destFilterID : 0, + destFilterChannel, + e); + } + else if (dragging) + { + getGraphPanel()->dragConnector (e); + } + } + + void mouseUp (const MouseEvent& e) + { + if (dragging) + getGraphPanel()->endDraggingConnector (e); + } + + void resized() + { + float x1, y1, x2, y2; + getPoints (x1, y1, x2, y2); + + lastInputX = x1; + lastInputY = y1; + lastOutputX = x2; + lastOutputY = y2; + + x1 -= getX(); + y1 -= getY(); + x2 -= getX(); + y2 -= getY(); + + linePath.clear(); + linePath.startNewSubPath (x1, y1); + linePath.cubicTo (x1, y1 + (y2 - y1) * 0.33f, + x2, y1 + (y2 - y1) * 0.66f, + x2, y2); + + PathStrokeType wideStroke (8.0f); + wideStroke.createStrokedPath (hitPath, linePath); + + PathStrokeType stroke (2.5f); + stroke.createStrokedPath (linePath, linePath); + + const float arrowW = 5.0f; + const float arrowL = 4.0f; + + Path arrow; + arrow.addTriangle (-arrowL, arrowW, + -arrowL, -arrowW, + arrowL, 0.0f); + + arrow.applyTransform (AffineTransform::identity + .rotated (float_Pi * 0.5f - (float) atan2 (x2 - x1, y2 - y1)) + .translated ((x1 + x2) * 0.5f, + (y1 + y2) * 0.5f)); + + linePath.addPath (arrow); + linePath.setUsingNonZeroWinding (true); + } + + juce_UseDebuggingNewOperator + + uint32 sourceFilterID, destFilterID; + int sourceFilterChannel, destFilterChannel; + +private: + FilterGraph& graph; + float lastInputX, lastInputY, lastOutputX, lastOutputY; + Path linePath, hitPath; + bool dragging; + + GraphEditorPanel* getGraphPanel() const throw() + { + return findParentComponentOfClass ((GraphEditorPanel*) 0); + } + + void getDistancesFromEnds (int x, int y, double& distanceFromStart, double& distanceFromEnd) const + { + float x1, y1, x2, y2; + getPoints (x1, y1, x2, y2); + + distanceFromStart = juce_hypot (x - (x1 - getX()), y - (y1 - getY())); + distanceFromEnd = juce_hypot (x - (x2 - getX()), y - (y2 - getY())); + } + + ConnectorComponent (const ConnectorComponent&); + const ConnectorComponent& operator= (const ConnectorComponent&); +}; + + +//============================================================================== +GraphEditorPanel::GraphEditorPanel (FilterGraph& graph_) + : graph (graph_), + draggingConnector (0) +{ + graph.addChangeListener (this); + setOpaque (true); +} + +GraphEditorPanel::~GraphEditorPanel() +{ + graph.removeChangeListener (this); + deleteAndZero (draggingConnector); + deleteAllChildren(); +} + +void GraphEditorPanel::paint (Graphics& g) +{ + g.fillAll (Colours::white); +} + +void GraphEditorPanel::mouseDown (const MouseEvent& e) +{ + if (e.mods.isPopupMenu()) + { + PopupMenu m; + + MainHostWindow* const mainWindow = findParentComponentOfClass ((MainHostWindow*) 0); + + if (mainWindow != 0) + { + mainWindow->addPluginsToMenu (m); + + const int r = m.show(); + + createNewPlugin (mainWindow->getChosenType (r), e.x, e.y); + } + } +} + +void GraphEditorPanel::createNewPlugin (const PluginDescription* desc, int x, int y) +{ + graph.addFilter (desc, x / (double) getWidth(), y / (double) getHeight()); +} + +FilterComponent* GraphEditorPanel::getComponentForFilter (const uint32 filterID) const +{ + for (int i = getNumChildComponents(); --i >= 0;) + { + FilterComponent* const fc = dynamic_cast (getChildComponent (i)); + + if (fc != 0 && fc->filterID == filterID) + return fc; + } + + return 0; +} + +ConnectorComponent* GraphEditorPanel::getComponentForConnection (const FilterConnection& conn) const +{ + for (int i = getNumChildComponents(); --i >= 0;) + { + ConnectorComponent* const c = dynamic_cast (getChildComponent (i)); + + if (c != 0 + && c->sourceFilterID == conn.sourceFilterID + && c->destFilterID == conn.destFilterID + && c->sourceFilterChannel == conn.sourceChannel + && c->destFilterChannel == conn.destChannel) + { + return c; + } + } + + return 0; +} + +PinComponent* GraphEditorPanel::findPinAt (const int x, const int y) const +{ + for (int i = getNumChildComponents(); --i >= 0;) + { + FilterComponent* const fc = dynamic_cast (getChildComponent (i)); + + if (fc != 0) + { + PinComponent* const pin + = dynamic_cast (fc->getComponentAt (x - fc->getX(), + y - fc->getY())); + + if (pin != 0) + return pin; + } + } + + return 0; +} + +void GraphEditorPanel::resized() +{ + updateComponents(); +} + +void GraphEditorPanel::changeListenerCallback (void*) +{ + updateComponents(); +} + +void GraphEditorPanel::updateComponents() +{ + int i; + for (i = getNumChildComponents(); --i >= 0;) + { + FilterComponent* const fc = dynamic_cast (getChildComponent (i)); + + if (fc != 0) + fc->update(); + } + + for (i = getNumChildComponents(); --i >= 0;) + { + ConnectorComponent* const cc = dynamic_cast (getChildComponent (i)); + + if (cc != 0 && cc != draggingConnector) + { + if (graph.getConnectionBetween (cc->sourceFilterID, cc->sourceFilterChannel, + cc->destFilterID, cc->destFilterChannel) == 0) + { + delete cc; + } + else + { + cc->update(); + } + } + } + + for (i = graph.getNumFilters(); --i >= 0;) + { + const FilterInGraph* const f = graph.getFilter (i); + + if (getComponentForFilter (f->uid) == 0) + { + FilterComponent* const comp = new FilterComponent (graph, f->uid); + addAndMakeVisible (comp); + comp->update(); + } + } + + for (i = graph.getNumConnections(); --i >= 0;) + { + FilterConnection* const c = graph.getConnection (i); + + if (getComponentForConnection (*c) == 0) + { + ConnectorComponent* const comp = new ConnectorComponent (graph); + addAndMakeVisible (comp); + + comp->setInput (c->sourceFilterID, c->sourceChannel); + comp->setOutput (c->destFilterID, c->destChannel); + } + } +} + +void GraphEditorPanel::beginConnectorDrag (const uint32 sourceFilterID, const int sourceFilterChannel, + const uint32 destFilterID, const int destFilterChannel, + const MouseEvent& e) +{ + delete draggingConnector; + draggingConnector = dynamic_cast (e.originalComponent); + + if (draggingConnector == 0) + draggingConnector = new ConnectorComponent (graph); + + draggingConnector->setInput (sourceFilterID, sourceFilterChannel); + draggingConnector->setOutput (destFilterID, destFilterChannel); + + addAndMakeVisible (draggingConnector); + draggingConnector->toFront (false); + + dragConnector (e); +} + +void GraphEditorPanel::dragConnector (const MouseEvent& e) +{ + const MouseEvent e2 (e.getEventRelativeTo (this)); + + if (draggingConnector != 0) + { + int x = e2.x; + int y = e2.y; + + PinComponent* const pin = findPinAt (x, y); + + if (pin != 0) + { + uint32 srcFilter = draggingConnector->sourceFilterID; + int srcChannel = draggingConnector->sourceFilterChannel; + uint32 dstFilter = draggingConnector->destFilterID; + int dstChannel = draggingConnector->destFilterChannel; + + if (srcFilter == 0 && ! pin->isInput) + { + srcFilter = pin->filterID; + srcChannel = pin->index; + } + else if (dstFilter == 0 && pin->isInput) + { + dstFilter = pin->filterID; + dstChannel = pin->index; + } + + if (graph.canConnect (srcFilter, srcChannel, dstFilter, dstChannel)) + { + x = pin->getParentComponent()->getX() + pin->getX() + pin->getWidth() / 2; + y = pin->getParentComponent()->getY() + pin->getY() + pin->getHeight() / 2; + } + } + + if (draggingConnector->sourceFilterID == 0) + draggingConnector->dragStart (x, y); + else + draggingConnector->dragEnd (x, y); + } +} + +void GraphEditorPanel::endDraggingConnector (const MouseEvent& e) +{ + if (draggingConnector == 0) + return; + + const MouseEvent e2 (e.getEventRelativeTo (this)); + + uint32 srcFilter = draggingConnector->sourceFilterID; + int srcChannel = draggingConnector->sourceFilterChannel; + uint32 dstFilter = draggingConnector->destFilterID; + int dstChannel = draggingConnector->destFilterChannel; + + deleteAndZero (draggingConnector); + + PinComponent* const pin = findPinAt (e2.x, e2.y); + + if (pin != 0) + { + if (srcFilter == 0) + { + if (pin->isInput) + return; + + srcFilter = pin->filterID; + srcChannel = pin->index; + } + else + { + if (! pin->isInput) + return; + + dstFilter = pin->filterID; + dstChannel = pin->index; + } + + graph.addConnection (srcFilter, srcChannel, dstFilter, dstChannel); + } +} + + +//============================================================================== +GraphDocumentComponent::GraphDocumentComponent (AudioDeviceManager* deviceManager_) + : deviceManager (deviceManager_) +{ + addAndMakeVisible (graphPanel = new GraphEditorPanel (graph)); + + addAndMakeVisible (keyboardComp = new MidiKeyboardComponent (graphRenderer.keyState, + MidiKeyboardComponent::horizontalKeyboard)); + + graphRenderer.setAudioDeviceManager (deviceManager); + graphRenderer.updateFrom (&graph); + + graph.addChangeListener (this); + deviceManager->addChangeListener (this); + + graphPanel->updateComponents(); +} + +GraphDocumentComponent::~GraphDocumentComponent() +{ + graph.removeChangeListener (this); + deviceManager->removeChangeListener (this); + + deleteAllChildren(); + + graphRenderer.updateFrom (0); + graphRenderer.setAudioDeviceManager (0); + + graph.clear(); +} + +void GraphDocumentComponent::resized() +{ + const int keysHeight = 60; + graphPanel->setBounds (0, 0, getWidth(), getHeight() - keysHeight); + keyboardComp->setBounds (0, getHeight() - keysHeight, getWidth(), keysHeight); +} + +void GraphDocumentComponent::createNewPlugin (const PluginDescription* desc, int x, int y) +{ + graphPanel->createNewPlugin (desc, x, y); +} + +void GraphDocumentComponent::changeListenerCallback (void*) +{ + graphRenderer.updateFrom (&graph); +} diff --git a/extras/audio plugin host/src/host/GraphEditorPanel.h b/extras/audio plugin host/src/host/GraphEditorPanel.h new file mode 100644 index 0000000000..098d163747 --- /dev/null +++ b/extras/audio plugin host/src/host/GraphEditorPanel.h @@ -0,0 +1,122 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_FILTERGRAPHEDITOR_JUCEHEADER__ +#define __JUCE_FILTERGRAPHEDITOR_JUCEHEADER__ + +#include "../plugins/juce_KnownPluginList.h" +#include "FilterGraph.h" + +class FilterComponent; +class ConnectorComponent; +class PinComponent; + + +//============================================================================== +/** + A panel that displays and edits a FilterGraph. +*/ +class GraphEditorPanel : public Component, + public ChangeListener +{ +public: + GraphEditorPanel (FilterGraph& graph); + ~GraphEditorPanel(); + + void paint (Graphics& g); + void mouseDown (const MouseEvent& e); + + void createNewPlugin (const PluginDescription* desc, int x, int y); + + FilterComponent* getComponentForFilter (const uint32 filterID) const; + ConnectorComponent* getComponentForConnection (const FilterConnection& conn) const; + PinComponent* findPinAt (const int x, const int y) const; + + void resized(); + void changeListenerCallback (void*); + void updateComponents(); + + //============================================================================== + void beginConnectorDrag (const uint32 sourceFilterID, const int sourceFilterChannel, + const uint32 destFilterID, const int destFilterChannel, + const MouseEvent& e); + void dragConnector (const MouseEvent& e); + void endDraggingConnector (const MouseEvent& e); + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + FilterGraph& graph; + ConnectorComponent* draggingConnector; + + GraphEditorPanel (const GraphEditorPanel&); + const GraphEditorPanel& operator= (const GraphEditorPanel&); +}; + + +//============================================================================== +/** + A panel that embeds a GraphEditorPanel with a midi keyboard at the bottom. + + It also manages the graph itself, and plays it. +*/ +class GraphDocumentComponent : public Component, + public ChangeListener +{ +public: + //============================================================================== + GraphDocumentComponent (AudioDeviceManager* deviceManager); + ~GraphDocumentComponent(); + + //============================================================================== + void createNewPlugin (const PluginDescription* desc, int x, int y); + + //============================================================================== + FilterGraph graph; + + //============================================================================== + void resized(); + void changeListenerCallback (void*); + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + AudioDeviceManager* deviceManager; + FilterGraphPlayer graphRenderer; + + GraphEditorPanel* graphPanel; + Component* keyboardComp; +}; + + +#endif diff --git a/extras/audio plugin host/src/host/InternalFilters.cpp b/extras/audio plugin host/src/host/InternalFilters.cpp new file mode 100644 index 0000000000..2fceb4d452 --- /dev/null +++ b/extras/audio plugin host/src/host/InternalFilters.cpp @@ -0,0 +1,406 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "InternalFilters.h" +#include "FilterGraph.h" + +//============================================================================== +class InternalFilterBase : public AudioPluginInstance, + public FilterGraphPlayer::PlayerAwareFilter +{ +public: + InternalFilterBase() + : player (0) + { + } + + ~InternalFilterBase() + { + } + + void setPlayer (FilterGraphPlayer* p) + { + player = p; + rendererChanged(); + } + + virtual void rendererChanged() {} + + const String getManufacturer() const { return "Raw Material Software"; } + const String getFormatName() const { return "Internal"; } + const File getFile() const { return File::nonexistent; } + int getUID() const { return getName().hashCode(); } + int getSamplesLatency() const { return 0; } + + AudioFilterEditor* JUCE_CALLTYPE createEditor() { return 0; } + int JUCE_CALLTYPE getNumParameters() { return 0; } + const String JUCE_CALLTYPE getParameterName (int) { return String::empty; } + float JUCE_CALLTYPE getParameter (int) { return 0; } + const String JUCE_CALLTYPE getParameterText (int) { return String::empty; } + void JUCE_CALLTYPE setParameter (int, float) {} + int JUCE_CALLTYPE getNumPrograms() { return 0; } + int JUCE_CALLTYPE getCurrentProgram() { return 0; } + void JUCE_CALLTYPE setCurrentProgram (int) {} + const String JUCE_CALLTYPE getProgramName (int) { return String::empty; } + void JUCE_CALLTYPE changeProgramName (int, const String&) {} + void JUCE_CALLTYPE getStateInformation (JUCE_NAMESPACE::MemoryBlock&) {} + void JUCE_CALLTYPE setStateInformation (const void*, int) {} + +protected: + FilterGraphPlayer* player; + + AudioIODevice* getAudioDevice() const + { + if (player != 0) + { + AudioDeviceManager* const dm = player->getAudioDeviceManager(); + + jassert (dm != 0); + if (dm != 0) + return dm->getCurrentAudioDevice(); + } + + return 0; + } +}; + +//============================================================================== +class AudioInputDeviceFilter : public InternalFilterBase +{ +public: + AudioInputDeviceFilter (const int numChannels) + { + numOutputChannels = numChannels; + } + + ~AudioInputDeviceFilter() {} + + const String getName() const { return "Audio Input"; } + const String getVersion() const { return "1.0"; } + bool isInstrument() const { return true; } + const String getCategory() const { return "I/O devices"; } + bool acceptsMidi() const { return false; } + bool producesMidi() const { return false; } + + void rendererChanged() + { + AudioIODevice* const dev = getAudioDevice(); + + if (dev != 0) + numOutputChannels = dev->getInputChannelNames().size(); + } + + void JUCE_CALLTYPE prepareToPlay (double /*sampleRate*/, int /*estimatedSamplesPerBlock*/) + { + rendererChanged(); + } + + void JUCE_CALLTYPE releaseResources() + { + } + + void JUCE_CALLTYPE processBlock (const AudioSampleBuffer& /*input*/, + AudioSampleBuffer& output, + const bool accumulateOutput, + MidiBuffer&) + { + int n = 0; + + for (int i = 0; i < player->totalNumInputChannels; ++i) + { + if (n >= output.getNumChannels()) + break; + + if (player->inputChannelData [i] != 0) + { + if (accumulateOutput) + output.addFrom (n, 0, player->inputChannelData [i], output.getNumSamples()); + else + output.copyFrom (n, 0, player->inputChannelData [i], output.getNumSamples()); + + ++n; + } + } + } + + const String JUCE_CALLTYPE getInputChannelName (const int channelIndex) const + { + return String (channelIndex + 1); + } + + const String JUCE_CALLTYPE getOutputChannelName (const int channelIndex) const + { + AudioIODevice* const dev = getAudioDevice(); + + if (dev != 0) + return dev->getInputChannelNames() [channelIndex]; + + return String (channelIndex + 1); + } + + bool JUCE_CALLTYPE isInputChannelStereoPair (int) const + { + return true; + } + + bool JUCE_CALLTYPE isOutputChannelStereoPair (int) const + { + return true; + } +}; + + +//============================================================================== +class AudioOutputDeviceFilter : public InternalFilterBase +{ +public: + AudioOutputDeviceFilter (const int numChannels) + { + numInputChannels = numChannels; + } + + ~AudioOutputDeviceFilter() {} + + const String getName() const { return "Audio Output"; } + const String getVersion() const { return "1.0"; } + bool isInstrument() const { return false; } + const String getCategory() const { return "I/O devices"; } + bool acceptsMidi() const { return false; } + bool producesMidi() const { return false; } + + void rendererChanged() + { + AudioIODevice* const dev = getAudioDevice(); + + if (dev != 0) + numInputChannels = dev->getOutputChannelNames().size(); + } + + void JUCE_CALLTYPE prepareToPlay (double /*sampleRate*/, int /*estimatedSamplesPerBlock*/) + { + rendererChanged(); + } + + void JUCE_CALLTYPE releaseResources() + { + } + + void JUCE_CALLTYPE processBlock (const AudioSampleBuffer& input, + AudioSampleBuffer&, + const bool accumulateOutput, + MidiBuffer&) + { + int n = 0; + + for (int i = 0; i < player->totalNumOutputChannels; ++i) + { + if (n >= input.getNumChannels()) + break; + + float* dst = player->outputChannelData [i]; + + if (dst != 0) + { + const float* src = input.getSampleData (n); + + if (accumulateOutput) + { + for (int i = input.getNumSamples(); --i >= 0;) + *dst++ += *src++; + } + else + { + memcpy (dst, src, sizeof (float) * input.getNumSamples()); + } + + ++n; + } + } + } + + const String JUCE_CALLTYPE getInputChannelName (const int channelIndex) const + { + AudioIODevice* const dev = getAudioDevice(); + + if (dev != 0) + return dev->getOutputChannelNames() [channelIndex]; + + return String (channelIndex + 1); + } + + const String JUCE_CALLTYPE getOutputChannelName (const int channelIndex) const + { + return String (channelIndex + 1); + } + + bool JUCE_CALLTYPE isInputChannelStereoPair (int) const + { + return true; + } + + bool JUCE_CALLTYPE isOutputChannelStereoPair (int) const + { + return true; + } +}; + + +//============================================================================== +class MidiInputDeviceFilter : public InternalFilterBase +{ +public: + MidiInputDeviceFilter() + { + } + + ~MidiInputDeviceFilter() {} + + const String getName() const { return "Midi Input"; } + const String getVersion() const { return "1.0"; } + bool isInstrument() const { return true; } + const String getCategory() const { return "I/O devices"; } + bool acceptsMidi() const { return false; } + bool producesMidi() const { return true; } + + void rendererChanged() + { + if (player != 0) + { + AudioDeviceManager* const dm = player->getAudioDeviceManager(); + + jassert (dm != 0); + } + } + + void JUCE_CALLTYPE prepareToPlay (double /*sampleRate*/, int /*estimatedSamplesPerBlock*/) + { + rendererChanged(); + } + + void JUCE_CALLTYPE releaseResources() + { + } + + void JUCE_CALLTYPE processBlock (const AudioSampleBuffer& input, + AudioSampleBuffer&, + const bool accumulateOutput, + MidiBuffer& midiBuffer) + { + if (! accumulateOutput) + midiBuffer.clear(); + + midiBuffer.addEvents (player->incomingMidi, 0, input.getNumSamples(), 0); + } + + const String JUCE_CALLTYPE getInputChannelName (const int channelIndex) const + { + return String (channelIndex + 1); + } + + const String JUCE_CALLTYPE getOutputChannelName (const int channelIndex) const + { + AudioIODevice* const dev = getAudioDevice(); + + if (dev != 0) + return dev->getInputChannelNames() [channelIndex]; + + return String (channelIndex + 1); + } + + bool JUCE_CALLTYPE isInputChannelStereoPair (int) const + { + return true; + } + + bool JUCE_CALLTYPE isOutputChannelStereoPair (int) const + { + return true; + } +}; + + +//============================================================================== +InternalPluginFormat::InternalPluginFormat() +{ + { + AudioInputDeviceFilter f (2); + audioInDesc.fillInFromInstance (f); + } + + { + AudioOutputDeviceFilter f (2); + audioOutDesc.fillInFromInstance (f); + } + + { + MidiInputDeviceFilter f; + midiInDesc.fillInFromInstance (f); + } +} + +AudioPluginInstance* InternalPluginFormat::createInstanceFromDescription (const PluginDescription& desc) +{ + if (desc.name == audioOutDesc.name) + { + return new AudioOutputDeviceFilter (desc.numInputChannels); + } + else if (desc.name == audioInDesc.name) + { + return new AudioInputDeviceFilter (desc.numOutputChannels); + } + else if (desc.name == midiInDesc.name) + { + return new MidiInputDeviceFilter(); + } + + return 0; +} + +const PluginDescription* InternalPluginFormat::getDescriptionFor (const InternalFilterType type) +{ + switch (type) + { + case audioInputFilter: + return &audioInDesc; + case audioOutputFilter: + return &audioOutDesc; + case midiInputFilter: + return &midiInDesc; + } + + return 0; +} + +void InternalPluginFormat::getAllTypes (OwnedArray & results) +{ + for (int i = 0; i < (int) endOfFilterTypes; ++i) + results.add (new PluginDescription (*getDescriptionFor ((InternalFilterType) i))); +} diff --git a/extras/audio plugin host/src/host/InternalFilters.h b/extras/audio plugin host/src/host/InternalFilters.h new file mode 100644 index 0000000000..1837e9e16f --- /dev/null +++ b/extras/audio plugin host/src/host/InternalFilters.h @@ -0,0 +1,80 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_MAINHOSTWINDOW_JUCEHEADER__xxxxx +#define __JUCE_MAINHOSTWINDOW_JUCEHEADER__xxxxx + +#include "FilterGraph.h" +#include "../plugins/juce_AudioPluginFormat.h" + +//============================================================================== +/** + Manages the internal plugin types. +*/ +class InternalPluginFormat : public AudioPluginFormat +{ +public: + //============================================================================== + InternalPluginFormat(); + ~InternalPluginFormat() {} + + //============================================================================== + enum InternalFilterType + { + audioInputFilter = 0, + audioOutputFilter, + midiInputFilter, + + endOfFilterTypes + }; + + const PluginDescription* getDescriptionFor (const InternalFilterType type); + + void getAllTypes (OwnedArray & results); + + //============================================================================== + const String getName() const { return "Internal"; } + bool fileMightContainThisPluginType (const File&) { return false; } + const FileSearchPath getDefaultLocationsToSearch() { return FileSearchPath(); } + void findAllTypesForFile (OwnedArray &, const File&) {} + AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + PluginDescription audioInDesc; + PluginDescription audioOutDesc; + PluginDescription midiInDesc; +}; + + +#endif diff --git a/extras/audio plugin host/src/host/MainHostWindow.cpp b/extras/audio plugin host/src/host/MainHostWindow.cpp new file mode 100644 index 0000000000..5e81ef9bd3 --- /dev/null +++ b/extras/audio plugin host/src/host/MainHostWindow.cpp @@ -0,0 +1,484 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "../../../../juce.h" +#include "MainHostWindow.h" +#include "InternalFilters.h" +#include "../plugins/juce_PluginListComponent.h" + +//============================================================================== +class PluginListWindow : public DocumentWindow +{ +public: + PluginListWindow (KnownPluginList& knownPluginList) + : DocumentWindow ("Available Plugins", Colours::white, + DocumentWindow::minimiseButton | DocumentWindow::closeButton) + { + currentPluginListWindow = this; + + const File deadMansPedalFile (ApplicationProperties::getInstance()->getUserSettings() + ->getFile().getSiblingFile ("RecentlyCrashedPluginsList")); + + setContentComponent (new PluginListComponent (knownPluginList, + deadMansPedalFile, + ApplicationProperties::getInstance()->getUserSettings()), true, true); + + setResizable (true, false); + setVisible (true); + setResizeLimits (300, 400, 800, 1500); + setTopLeftPosition (60, 60); + + restoreWindowStateFromString (ApplicationProperties::getInstance()->getUserSettings()->getValue ("listWindowPos")); + } + + ~PluginListWindow() + { + ApplicationProperties::getInstance()->getUserSettings()->setValue ("listWindowPos", getWindowStateAsString()); + + setContentComponent (0); + + jassert (currentPluginListWindow == this); + currentPluginListWindow = 0; + } + + void closeButtonPressed() + { + delete this; + } + + static PluginListWindow* currentPluginListWindow; +}; + +PluginListWindow* PluginListWindow::currentPluginListWindow = 0; + + +//============================================================================== +MainHostWindow::MainHostWindow() + : DocumentWindow (JUCEApplication::getInstance()->getApplicationName(), Colours::lightgrey, + DocumentWindow::allButtons) +{ + setResizable (true, false); + setResizeLimits (500, 400, 10000, 10000); + centreWithSize (800, 600); + + setContentComponent (new GraphDocumentComponent (&deviceManager)); + + restoreWindowStateFromString (ApplicationProperties::getInstance()->getUserSettings()->getValue ("mainWindowPos")); + +#if JUCE_MAC + setMacMainMenu (this); +#else + setMenuBar (this); +#endif + + setVisible (true); + + InternalPluginFormat internalFormat; + internalFormat.getAllTypes (internalTypes); + + XmlElement* const savedAudioState = ApplicationProperties::getInstance()->getUserSettings() + ->getXmlValue (T("audioDeviceState")); + + deviceManager.initialise (256, 256, savedAudioState, true); + + delete savedAudioState; + + XmlElement* const savedPluginList = ApplicationProperties::getInstance() + ->getUserSettings() + ->getXmlValue (T("pluginList")); + + if (savedPluginList != 0) + { + knownPluginList.recreateFromXml (*savedPluginList); + delete savedPluginList; + } + + pluginSortMethod = (KnownPluginList::SortMethod) ApplicationProperties::getInstance()->getUserSettings() + ->getIntValue (T("pluginSortMethod"), KnownPluginList::sortByManufacturer); + + knownPluginList.addChangeListener (this); + + addKeyListener (commandManager->getKeyMappings()); +} + +MainHostWindow::~MainHostWindow() +{ + delete PluginListWindow::currentPluginListWindow; + +#if JUCE_MAC + setMacMainMenu (0); +#else + setMenuBar (0); +#endif + + knownPluginList.removeChangeListener (this); + + ApplicationProperties::getInstance()->getUserSettings()->setValue ("mainWindowPos", getWindowStateAsString()); + setContentComponent (0); +} + +void MainHostWindow::closeButtonPressed() +{ + tryToQuitApplication(); +} + +bool MainHostWindow::tryToQuitApplication() +{ + if (getGraphEditor() != 0 + && getGraphEditor()->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk) + { + JUCEApplication::quit(); + return true; + } + + return false; +} + +void MainHostWindow::changeListenerCallback (void*) +{ + menuItemsChanged(); + + // save the plugin list every time it gets chnaged, so that if we're scanning + // and it crashes, we've still saved the previous ones + XmlElement* const savedPluginList = knownPluginList.createXml(); + + if (savedPluginList != 0) + { + ApplicationProperties::getInstance()->getUserSettings() + ->setValue (T("pluginList"), savedPluginList); + + delete savedPluginList; + + ApplicationProperties::getInstance()->saveIfNeeded(); + } +} + +const StringArray MainHostWindow::getMenuBarNames() +{ + const tchar* const names[] = { T("File"), T("Plugins"), T("Options"), 0 }; + + return StringArray ((const tchar**) names); +} + +const PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const String& /*menuName*/) +{ + PopupMenu menu; + + if (topLevelMenuIndex == 0) + { + // "File" menu + menu.addCommandItem (commandManager, CommandIDs::open); + + RecentlyOpenedFilesList recentFiles; + recentFiles.restoreFromString (ApplicationProperties::getInstance()->getUserSettings() + ->getValue ("recentFilterGraphFiles")); + + PopupMenu recentFilesMenu; + recentFiles.createPopupMenuItems (recentFilesMenu, 100, true, true); + menu.addSubMenu (T("Open recent file"), recentFilesMenu); + + menu.addCommandItem (commandManager, CommandIDs::save); + menu.addCommandItem (commandManager, CommandIDs::saveAs); + menu.addSeparator(); + menu.addCommandItem (commandManager, StandardApplicationCommandIDs::quit); + } + else if (topLevelMenuIndex == 1) + { + // "Plugins" menu + PopupMenu pluginsMenu; + addPluginsToMenu (pluginsMenu); + menu.addSubMenu (T("Create plugin"), pluginsMenu); + menu.addSeparator(); + menu.addItem (250, T("Delete all plugins")); + + } + else if (topLevelMenuIndex == 2) + { + // "Options" menu + + menu.addCommandItem (commandManager, CommandIDs::showPluginListEditor); + + PopupMenu sortTypeMenu; + sortTypeMenu.addItem (200, "List plugins in default order", true, pluginSortMethod == KnownPluginList::defaultOrder); + sortTypeMenu.addItem (201, "List plugins in alphabetical order", true, pluginSortMethod == KnownPluginList::sortAlphabetically); + sortTypeMenu.addItem (202, "List plugins by category", true, pluginSortMethod == KnownPluginList::sortByCategory); + sortTypeMenu.addItem (203, "List plugins by manufacturer", true, pluginSortMethod == KnownPluginList::sortByManufacturer); + menu.addSubMenu ("Plugin menu type", sortTypeMenu); + + menu.addSeparator(); + menu.addCommandItem (commandManager, CommandIDs::showAudioSettings); + + menu.addSeparator(); + menu.addCommandItem (commandManager, CommandIDs::aboutBox); + } + + return menu; +} + +void MainHostWindow::menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/) +{ + GraphDocumentComponent* const graphEditor = getGraphEditor(); + + if (menuItemID == 250) + { + if (graphEditor != 0) + graphEditor->graph.clear(); + } + else if (menuItemID >= 100 && menuItemID < 200) + { + RecentlyOpenedFilesList recentFiles; + recentFiles.restoreFromString (ApplicationProperties::getInstance()->getUserSettings() + ->getValue ("recentFilterGraphFiles")); + + if (graphEditor != 0 && graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk) + graphEditor->graph.loadFrom (recentFiles.getFile (menuItemID - 100), true); + } + else if (menuItemID >= 200 && menuItemID < 210) + { + if (menuItemID == 200) + pluginSortMethod = KnownPluginList::defaultOrder; + else if (menuItemID == 201) + pluginSortMethod = KnownPluginList::sortAlphabetically; + else if (menuItemID == 202) + pluginSortMethod = KnownPluginList::sortByCategory; + else if (menuItemID == 203) + pluginSortMethod = KnownPluginList::sortByManufacturer; + + ApplicationProperties::getInstance()->getUserSettings() + ->setValue (T("pluginSortMethod"), (int) pluginSortMethod); + } + else + { + createPlugin (getChosenType (menuItemID), + proportionOfWidth (0.3f + Random::getSystemRandom().nextFloat() * 0.6f), + proportionOfHeight (0.3f + Random::getSystemRandom().nextFloat() * 0.6f)); + } +} + +void MainHostWindow::createPlugin (const PluginDescription* desc, int x, int y) +{ + GraphDocumentComponent* const graphEditor = getGraphEditor(); + + if (graphEditor != 0) + graphEditor->createNewPlugin (desc, x, y); +} + +void MainHostWindow::addPluginsToMenu (PopupMenu& m) const +{ + for (int i = 0; i < internalTypes.size(); ++i) + m.addItem (i + 1, internalTypes.getUnchecked(i)->name); + + m.addSeparator(); + + knownPluginList.addToMenu (m, pluginSortMethod); +} + +const PluginDescription* MainHostWindow::getChosenType (const int menuID) const +{ + if (menuID >= 1 && menuID < 1 + internalTypes.size()) + { + return internalTypes [menuID - 1]; + } + else + { + return knownPluginList.getType (knownPluginList.getIndexChosenByMenu (menuID)); + } +} + +//============================================================================== +ApplicationCommandTarget* MainHostWindow::getNextCommandTarget() +{ + return findFirstTargetParentComponent(); +} + +void MainHostWindow::getAllCommands (Array & commands) +{ + // this returns the set of all commands that this target can perform.. + const CommandID ids[] = { CommandIDs::open, + CommandIDs::save, + CommandIDs::saveAs, + CommandIDs::showPluginListEditor, + CommandIDs::showAudioSettings, + CommandIDs::aboutBox + }; + + commands.addArray (ids, numElementsInArray (ids)); +} + +void MainHostWindow::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result) +{ + const String category ("General"); + + switch (commandID) + { + case CommandIDs::open: + result.setInfo (T("Open..."), + T("Opens a filter graph file"), + category, 0); + result.defaultKeypresses.add (KeyPress (T('o'), ModifierKeys::commandModifier, 0)); + break; + + case CommandIDs::save: + result.setInfo (T("Save"), + T("Saves the current graph to a file"), + category, 0); + result.defaultKeypresses.add (KeyPress (T('s'), ModifierKeys::commandModifier, 0)); + break; + + case CommandIDs::saveAs: + result.setInfo (T("Save As..."), + T("Saves a copy of the current graph to a file"), + category, 0); + result.defaultKeypresses.add (KeyPress (T('s'), ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0)); + break; + + case CommandIDs::showPluginListEditor: + result.setInfo ("Edit the list of available plug-Ins...", String::empty, category, 0); + result.addDefaultKeypress (T('p'), ModifierKeys::commandModifier); + break; + + case CommandIDs::showAudioSettings: + result.setInfo ("Change the audio device settings", String::empty, category, 0); + result.addDefaultKeypress (T('a'), ModifierKeys::commandModifier); + break; + + case CommandIDs::aboutBox: + result.setInfo ("About...", String::empty, category, 0); + break; + + default: + break; + } +} + +bool MainHostWindow::perform (const InvocationInfo& info) +{ + GraphDocumentComponent* const graphEditor = getGraphEditor(); + + switch (info.commandID) + { + case CommandIDs::open: + if (graphEditor != 0 && graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk) + graphEditor->graph.loadFromUserSpecifiedFile (true); + + break; + + case CommandIDs::save: + if (graphEditor != 0) + graphEditor->graph.save (true, true); + break; + + case CommandIDs::saveAs: + if (graphEditor != 0) + graphEditor->graph.saveAs (File::nonexistent, true, true, true); + break; + + case CommandIDs::showPluginListEditor: + if (PluginListWindow::currentPluginListWindow == 0) + PluginListWindow::currentPluginListWindow = new PluginListWindow (knownPluginList); + + PluginListWindow::currentPluginListWindow->toFront (true); + break; + + case CommandIDs::showAudioSettings: + showAudioSettings(); + break; + + case CommandIDs::aboutBox: + { +/* AboutBoxComponent aboutComp; + + DialogWindow::showModalDialog (T("About"), + &aboutComp, + this, Colours::white, + true, false, false); + */ } + + break; + + default: + return false; + } + + return true; +} + +void MainHostWindow::showAudioSettings() +{ + AudioDeviceSelectorComponent audioSettingsComp (deviceManager, + 0, 2, + 0, 2, + false); + + audioSettingsComp.setSize (500, 300); + + DialogWindow::showModalDialog (T("Audio Settings"), + &audioSettingsComp, + this, + Colours::azure, + true); + + XmlElement* const audioState = deviceManager.createStateXml(); + + ApplicationProperties::getInstance()->getUserSettings() + ->setValue (T("audioSettings"), audioState); + + ApplicationProperties::getInstance()->getUserSettings()->saveIfNeeded(); + + delete audioState; +} + +bool MainHostWindow::filesDropped (const StringArray& files, int x, int y) +{ + if (files.size() == 1 && File (files[0]).hasFileExtension (filenameSuffix)) + { + GraphDocumentComponent* const graphEditor = getGraphEditor(); + + if (graphEditor == 0) + return false; + + return graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk + && graphEditor->graph.loadFrom (File (files[0]), true); + } + + OwnedArray typesFound; + knownPluginList.scanAndAddDragAndDroppedFiles (files, typesFound); + + for (int i = 0; i < jmin (5, typesFound.size()); ++i) + createPlugin (typesFound.getUnchecked(i), x, y); + + return typesFound.size() > 0; +} + +GraphDocumentComponent* MainHostWindow::getGraphEditor() const +{ + return dynamic_cast (getContentComponent()); +} diff --git a/extras/audio plugin host/src/host/MainHostWindow.h b/extras/audio plugin host/src/host/MainHostWindow.h new file mode 100644 index 0000000000..c17166c7a3 --- /dev/null +++ b/extras/audio plugin host/src/host/MainHostWindow.h @@ -0,0 +1,103 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_MAINHOSTWINDOW_JUCEHEADER__ +#define __JUCE_MAINHOSTWINDOW_JUCEHEADER__ + +#include "FilterGraph.h" +#include "GraphEditorPanel.h" +#include "../plugins/juce_KnownPluginList.h" + + +//============================================================================== +namespace CommandIDs +{ + static const int open = 0x30000; + static const int save = 0x30001; + static const int saveAs = 0x30002; + static const int showPluginListEditor = 0x30100; + static const int showAudioSettings = 0x30200; + static const int aboutBox = 0x30300; +} + +extern ApplicationCommandManager* commandManager; + + +//============================================================================== +/** +*/ +class MainHostWindow : public DocumentWindow, + public MenuBarModel, + public ApplicationCommandTarget, + public ChangeListener +{ +public: + //============================================================================== + MainHostWindow(); + ~MainHostWindow(); + + //============================================================================== + void closeButtonPressed(); + void changeListenerCallback (void*); + bool filesDropped (const StringArray& filenames, int x, int y); + + const StringArray getMenuBarNames(); + const PopupMenu getMenuForIndex (int topLevelMenuIndex, const String& menuName); + void menuItemSelected (int menuItemID, int topLevelMenuIndex); + ApplicationCommandTarget* getNextCommandTarget(); + void getAllCommands (Array & commands); + void getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result); + bool perform (const InvocationInfo& info); + + bool tryToQuitApplication(); + + void createPlugin (const PluginDescription* desc, int x, int y); + + void addPluginsToMenu (PopupMenu& m) const; + const PluginDescription* getChosenType (const int menuID) const; + + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + AudioDeviceManager deviceManager; + + OwnedArray internalTypes; + KnownPluginList knownPluginList; + KnownPluginList::SortMethod pluginSortMethod; + + void showAudioSettings(); + GraphDocumentComponent* getGraphEditor() const; +}; + + +#endif diff --git a/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.cpp b/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.cpp new file mode 100644 index 0000000000..f2001aeca6 --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.cpp @@ -0,0 +1,73 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "../../../../juce.h" +#include "juce_AudioPluginFormat.h" +#include "vst/juce_VSTPluginFormat.h" + + +//============================================================================== +AudioPluginFormatManager::AudioPluginFormatManager() throw() +{ +} + +AudioPluginFormatManager::~AudioPluginFormatManager() throw() +{ +} + +juce_ImplementSingleton_SingleThreaded (AudioPluginFormatManager); + +//============================================================================== +void AudioPluginFormatManager::addDefaultFormats() +{ +#ifdef JUCE_DEBUG + // you should only call this method once! + for (int i = formats.size(); --i >= 0;) + jassert (dynamic_cast (formats[i]) == 0); +#endif + + formats.add (new VSTPluginFormat()); +} + +int AudioPluginFormatManager::getNumFormats() throw() +{ + return formats.size(); +} + +AudioPluginFormat* AudioPluginFormatManager::getFormat (const int index) throw() +{ + return formats [index]; +} + +void AudioPluginFormatManager::addFormat (AudioPluginFormat* const format) throw() +{ + formats.add (format); +} diff --git a/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h b/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h new file mode 100644 index 0000000000..b63292acf5 --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h @@ -0,0 +1,154 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_AUDIOPLUGINFORMAT_JUCEHEADER__ +#define __JUCE_AUDIOPLUGINFORMAT_JUCEHEADER__ + +#include "juce_AudioPluginInstance.h" +class PluginDescription; + + +//============================================================================== +/** + The base class for a type of plugin format, such as VST, AudioUnit, LADSPA, etc. + + Use the static getNumFormats() and getFormat() calls to find the types + of format that are available. +*/ +class AudioPluginFormat +{ +public: + //============================================================================== + /** Destructor. */ + virtual ~AudioPluginFormat() {} + + //============================================================================== + /** Returns the format name. + + E.g. "VST", "AudioUnit", etc. + */ + virtual const String getName() const = 0; + + /** This tries to create descriptions for all the plugin types available in + a binary module file. + + The file will be some kind of DLL or bundle. + + Normally there will only be one type returned, but some plugins + (e.g. VST shells) can use a single DLL to create a set of different plugin + subtypes, so in that case, each subtype is returned as a separate object. + */ + virtual void findAllTypesForFile (OwnedArray & results, + const File& file) = 0; + + /** Tries to recreate a type from a previously generated PluginDescription. + + @see PluginDescription::createInstance + */ + virtual AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc) = 0; + + /** Should do a quick check to see if this file or directory might be a plugin of + this format. + + This is for searching for potential files, so it shouldn't actually try to + load the plugin or do anything time-consuming. + */ + virtual bool fileMightContainThisPluginType (const File& file) = 0; + + /** Returns the typical places to look for this kind of plugin. + + Note that if this returns no paths, it means that the format can't be scanned-for + (i.e. it's an internal format that doesn't live in files) + */ + virtual const FileSearchPath getDefaultLocationsToSearch() = 0; + + + //============================================================================== + juce_UseDebuggingNewOperator + + +protected: + AudioPluginFormat() throw() {} +}; + + +//============================================================================== +/** + This simply maintains a list of known AudioPluginFormats. + + @see AudioPluginFormat +*/ +class AudioPluginFormatManager : public DeletedAtShutdown +{ +public: + //============================================================================== + AudioPluginFormatManager() throw(); + + /** Destructor. */ + ~AudioPluginFormatManager() throw(); + + juce_DeclareSingleton_SingleThreaded (AudioPluginFormatManager, false); + + //============================================================================== + /** Adds any formats that it knows about, e.g. VST. + */ + void addDefaultFormats(); + + //============================================================================== + /** Returns the number of types of format that are available. + + Use getFormat() to get one of them. + */ + int getNumFormats() throw(); + + /** Returns one of the available formats. + + @see getNumFormats + */ + AudioPluginFormat* getFormat (const int index) throw(); + + //============================================================================== + /** Adds a format to the list. + + The object passed in will be owned and deleted by the manager. + */ + void addFormat (AudioPluginFormat* const format) throw(); + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + OwnedArray formats; +}; + + + +#endif // __JUCE_AUDIOPLUGINFORMAT_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/juce_AudioPluginInstance.cpp b/extras/audio plugin host/src/plugins/juce_AudioPluginInstance.cpp new file mode 100644 index 0000000000..ed89e1ecba --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_AudioPluginInstance.cpp @@ -0,0 +1,82 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#define JUCE_PLUGIN_HOST 1 + +//============================================================================== +// (Just a quick way of getting these files into the project) +#include "../../../audio plugins/wrapper/juce_AudioFilterBase.cpp" +#include "../../../audio plugins/wrapper/juce_AudioFilterEditor.cpp" + + +//============================================================================== +#include "juce_AudioPluginInstance.h" + + +//============================================================================== +bool JUCE_CALLTYPE AudioPluginInstance::getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info) +{ + info.bpm = 120.0; + info.timeSigNumerator = 4; + info.timeSigDenominator = 4; + + info.timeInSeconds = 0; + + /** For timecode, the position of the start of the edit, in seconds from 00:00:00:00. */ + info.editOriginTime = 0; + + /** The current play position in pulses-per-quarter-note. + This is the number of quarter notes since the edit start. + */ + info.ppqPosition = 0; + + /** The position of the start of the last bar, in pulses-per-quarter-note. + + This is the number of quarter notes from the start of the edit to the + start of the current bar. + + Note - this value may be unavailable on some hosts, e.g. Pro-Tools. If + it's not available, the value will be 0. + */ + info.ppqPositionOfLastBarStart = 0; + + info.frameRate = AudioFilterBase::CurrentPositionInfo::fpsUnknown; + + info.isPlaying = false; + info.isRecording = false; + + return true; +} + +void JUCE_CALLTYPE AudioPluginInstance::informHostOfParameterChange (int /*index*/, float /*newValue*/) +{ + +} diff --git a/extras/audio plugin host/src/plugins/juce_AudioPluginInstance.h b/extras/audio plugin host/src/plugins/juce_AudioPluginInstance.h new file mode 100644 index 0000000000..6c7e97a888 --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_AudioPluginInstance.h @@ -0,0 +1,123 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__ +#define __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__ + +#include "../../../audio plugins/wrapper/juce_AudioFilterBase.h" + + +//============================================================================== +/** + Base class for an active instance of a plugin. + + This derives from the same AudioFilterBase object that is used in the + plugin wrapper code, and most of its functionality is exposed by that interface, + with just a few extra methods here for using it from the host side. + + @see AudioFilterBase, AudioPluginFormat +*/ +class AudioPluginInstance : public AudioFilterBase, + private AudioFilterBase::FilterNativeCallbacks +{ +public: + //============================================================================== + /** Destructor. + + Make sure that you delete any UI components that belong to this plugin before + deleting the plugin. + */ + virtual ~AudioPluginInstance() {} + + //============================================================================== + /** Returns the plugin's name. */ + virtual const String getName() const = 0; + + /** Asks the plugin to supply a manufacturer name. */ + virtual const String getManufacturer() const = 0; + + /** Asks the plugin for its version number. */ + virtual const String getVersion() const = 0; + + /** Returns true if the plugin is an instrument rather than an effect. */ + virtual bool isInstrument() const = 0; + + /** Returns a category description for the plugin. + + E.g. "Dynamics", "Reverbs", etc. + */ + virtual const String getCategory() const = 0; + + /** Returns the class of plugin to which this belongs. + + E.g. "VST", "AU", etc + */ + virtual const String getFormatName() const = 0; + + /** Returns the binary file containing the plugin. + + This is normally the DLL or bundle file. + */ + virtual const File getFile() const = 0; + + /** Returns a unique identifier for the plugin. + + (Note that this may not be unique across different plugin formats). + */ + virtual int getUID() const = 0; + + + //============================================================================== + /** Returns true if the plugin wants midi messages. */ + virtual bool acceptsMidi() const = 0; + + /** Returns true if the plugin produces midi messages. */ + virtual bool producesMidi() const = 0; + + /** Returns the plugin's latency. + + This may not always be fixed, but should be correct just after the filter + has been prepared for playback. + */ + virtual int getSamplesLatency() const = 0; + + //============================================================================== + juce_UseDebuggingNewOperator + +protected: + AudioPluginInstance() {} + + bool JUCE_CALLTYPE getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info); + void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue); +}; + + +#endif // __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/juce_KnownPluginList.cpp b/extras/audio plugin host/src/plugins/juce_KnownPluginList.cpp new file mode 100644 index 0000000000..69261db10a --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_KnownPluginList.cpp @@ -0,0 +1,314 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "../../../../juce.h" +#include "juce_KnownPluginList.h" + + +//============================================================================== +KnownPluginList::KnownPluginList() +{ +} + +KnownPluginList::~KnownPluginList() +{ +} + +void KnownPluginList::clear() +{ + if (types.size() > 0) + { + types.clear(); + sendChangeMessage (this); + } +} + +PluginDescription* KnownPluginList::getTypeForFile (const File& file) const throw() +{ + for (int i = 0; i < types.size(); ++i) + if (types.getUnchecked(i)->file == file) + return types.getUnchecked(i); + + return 0; +} + +bool KnownPluginList::addType (const PluginDescription& type) +{ + for (int i = types.size(); --i >= 0;) + { + if (types.getUnchecked(i)->isDuplicateOf (type)) + { + // strange - found a duplicate plugin with different info.. + jassert (types.getUnchecked(i)->name == type.name); + jassert (types.getUnchecked(i)->isInstrument == type.isInstrument); + + *types.getUnchecked(i) = type; + return false; + } + } + + types.add (new PluginDescription (type)); + sendChangeMessage (this); + return true; +} + +void KnownPluginList::removeType (const int index) throw() +{ + types.remove (index); + sendChangeMessage (this); +} + +bool KnownPluginList::isListingUpToDate (const File& possiblePluginFile) const throw() +{ + if (getTypeForFile (possiblePluginFile) == 0) + return false; + + for (int i = types.size(); --i >= 0;) + { + const PluginDescription* const d = types.getUnchecked(i); + + if (d->file == possiblePluginFile + && d->lastFileModTime != possiblePluginFile.getLastModificationTime()) + { + return false; + } + } + + return true; +} + +bool KnownPluginList::scanAndAddFile (const File& possiblePluginFile, + const bool dontRescanIfAlreadyInList, + OwnedArray & typesFound) +{ + bool addedOne = false; + + if (dontRescanIfAlreadyInList + && getTypeForFile (possiblePluginFile) != 0) + { + bool needsRescanning = false; + + for (int i = types.size(); --i >= 0;) + { + const PluginDescription* const d = types.getUnchecked(i); + + if (d->file == possiblePluginFile + && d->lastFileModTime != possiblePluginFile.getLastModificationTime()) + { + needsRescanning = true; + } + else + { + typesFound.add (new PluginDescription (*d)); + } + } + + if (! needsRescanning) + return false; + } + + OwnedArray found; + + for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i) + { + AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i); + + format->findAllTypesForFile (found, possiblePluginFile); + + for (int i = 0; i < found.size(); ++i) + { + PluginDescription* const desc = found.getUnchecked(i); + jassert (desc != 0); + + if (addType (*desc)) + addedOne = true; + + typesFound.add (new PluginDescription (*desc)); + } + } + + return addedOne; +} + +void KnownPluginList::scanAndAddDragAndDroppedFiles (const StringArray& files, + OwnedArray & typesFound) +{ + for (int i = 0; i < files.size(); ++i) + { + const File f (files [i]); + + if (! scanAndAddFile (f, false, typesFound)) + { + if (f.isDirectory()) + { + StringArray s; + + { + OwnedArray subFiles; + f.findChildFiles (subFiles, File::findFilesAndDirectories, false); + + for (int j = 0; j < subFiles.size(); ++j) + s.add (subFiles.getUnchecked (j)->getFullPathName()); + } + + scanAndAddDragAndDroppedFiles (s, typesFound); + } + } + } +} + +//============================================================================== +class PluginSorter +{ +public: + KnownPluginList::SortMethod method; + + PluginSorter() throw() {} + + int compareElements (const PluginDescription* const first, + const PluginDescription* const second) const throw() + { + int diff = 0; + + if (method == KnownPluginList::sortByCategory) + diff = first->category.compareLexicographically (second->category); + else if (method == KnownPluginList::sortByManufacturer) + diff = first->manufacturerName.compareLexicographically (second->manufacturerName); + + if (diff == 0) + diff = first->name.compareLexicographically (second->name); + + return diff; + } +}; + +void KnownPluginList::sort (const SortMethod method) +{ + if (method != defaultOrder) + { + PluginSorter sorter; + sorter.method = method; + types.sort (sorter, true); + + sendChangeMessage (this); + } +} + +//============================================================================== +XmlElement* KnownPluginList::createXml() const +{ + XmlElement* const e = new XmlElement (T("KNOWNPLUGINS")); + + for (int i = 0; i < types.size(); ++i) + e->addChildElement (types.getUnchecked(i)->createXml()); + + return e; +} + +void KnownPluginList::recreateFromXml (const XmlElement& xml) +{ + clear(); + + if (xml.hasTagName (T("KNOWNPLUGINS"))) + { + forEachXmlChildElement (xml, e) + { + PluginDescription info; + + if (info.loadFromXml (*e)) + addType (info); + } + } +} + +//============================================================================== +const int menuIdBase = 0x324503f4; + +void KnownPluginList::addToMenu (PopupMenu& menu, const SortMethod sortMethod) const +{ + Array sorted; + + { + PluginSorter sorter; + sorter.method = sortMethod; + + for (int i = 0; i < types.size(); ++i) + sorted.addSorted (sorter, types.getUnchecked(i)); + } + + if (sortMethod == sortByCategory + || sortMethod == KnownPluginList::sortByManufacturer) + { + String lastSubMenuName; + PopupMenu sub; + + for (int i = 0; i < sorted.size(); ++i) + { + const PluginDescription* const pd = sorted.getUnchecked(i); + String thisSubMenuName (sortMethod == sortByCategory ? pd->category + : pd->manufacturerName); + + if (thisSubMenuName.trim().isEmpty()) + thisSubMenuName = T("Other"); + + if (thisSubMenuName != lastSubMenuName) + { + if (sub.getNumItems() > 0) + { + menu.addSubMenu (lastSubMenuName, sub); + sub.clear(); + } + + lastSubMenuName = thisSubMenuName; + } + + sub.addItem (types.indexOf (pd) + menuIdBase, pd->name, true, false); + } + + if (sub.getNumItems() > 0) + menu.addSubMenu (lastSubMenuName, sub); + } + else + { + for (int i = 0; i < sorted.size(); ++i) + { + const PluginDescription* const pd = sorted.getUnchecked(i); + menu.addItem (types.indexOf (pd) + menuIdBase, pd->name, true, false); + } + } +} + +int KnownPluginList::getIndexChosenByMenu (const int menuResultCode) const +{ + const int i = menuResultCode - menuIdBase; + + return (i >= 0 && i < types.size()) ? i : -1; +} diff --git a/extras/audio plugin host/src/plugins/juce_KnownPluginList.h b/extras/audio plugin host/src/plugins/juce_KnownPluginList.h new file mode 100644 index 0000000000..507e69a0ff --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_KnownPluginList.h @@ -0,0 +1,163 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_KNOWNPLUGINLIST_JUCEHEADER__ +#define __JUCE_KNOWNPLUGINLIST_JUCEHEADER__ + +#include "juce_PluginDescription.h" +#include "juce_AudioPluginFormat.h" + + +//============================================================================== +/** + Manages a list of plugin types. + + This can be easily edited, saved and loaded, and used to create instances of + the plugin types in it. + + @see PluginListComponent +*/ +class KnownPluginList : public ChangeBroadcaster +{ +public: + //============================================================================== + /** Creates an empty list. + */ + KnownPluginList(); + + /** Destructor. */ + ~KnownPluginList(); + + //============================================================================== + /** Clears the list. */ + void clear(); + + /** Returns the number of types currently in the list. + @see getType + */ + int getNumTypes() const throw() { return types.size(); } + + /** Returns one of the types. + @see getNumTypes + */ + PluginDescription* getType (const int index) const throw() { return types [index]; } + + /** Looks for a type in the list which comes from this file. + */ + PluginDescription* getTypeForFile (const File& file) const throw(); + + /** Adds a type manually from its description. */ + bool addType (const PluginDescription& type); + + /** Removes a type. */ + void removeType (const int index) throw(); + + /** Looks for all types that can be loaded from a given file, and adds them + to the list. + + If dontRescanIfAlreadyInList is true, then the file will only be loaded and + re-tested if it's not already in the list, or if the file's modification + time has changed since the list was created. If dontRescanIfAlreadyInList is + false, the file will always be reloaded and tested. + + Returns true if any new types were added, and all the types found in this + file (even if it was already known and hasn't been re-scanned) get returned + in the array. + */ + bool scanAndAddFile (const File& possiblePluginFile, + const bool dontRescanIfAlreadyInList, + OwnedArray & typesFound); + + /** Returns true if the specified file is already known about and if it + hasn't been modified since our entry was created. + */ + bool isListingUpToDate (const File& possiblePluginFile) const throw(); + + /** Scans and adds a bunch of files that might have been dragged-and-dropped. + + If any types are found in the files, their descriptions are returned in the array. + */ + void scanAndAddDragAndDroppedFiles (const StringArray& filenames, + OwnedArray & typesFound); + + //============================================================================== + /** Sort methods used to change the order of the plugins in the list. + */ + enum SortMethod + { + defaultOrder = 0, + sortAlphabetically, + sortByCategory, + sortByManufacturer + }; + + //============================================================================== + /** Adds all the plugin types to a popup menu so that the user can select one. + + Depending on the sort method, it may add sub-menus for categories, + manufacturers, etc. + + Use getIndexChosenByMenu() to find out the type that was chosen. + */ + void addToMenu (PopupMenu& menu, + const SortMethod sortMethod) const; + + /** Converts a menu item index that has been chosen into its index in this list. + + Returns -1 if it's not an ID that was used. + + @see addToMenu + */ + int getIndexChosenByMenu (const int menuResultCode) const; + + //============================================================================== + /** Sorts the list. */ + void sort (const SortMethod method); + + //============================================================================== + /** Creates some XML that can be used to store the state of this list. + */ + XmlElement* createXml() const; + + /** Recreates the state of this list from its stored XML format. + */ + void recreateFromXml (const XmlElement& xml); + + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + OwnedArray types; +}; + + +#endif // __JUCE_KNOWNPLUGINLIST_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/juce_PluginDescription.cpp b/extras/audio plugin host/src/plugins/juce_PluginDescription.cpp new file mode 100644 index 0000000000..61d9d4c9d5 --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_PluginDescription.cpp @@ -0,0 +1,158 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "../../../../juce.h" +#include "juce_PluginDescription.h" +#include "juce_AudioPluginFormat.h" + + +//============================================================================== +PluginDescription::PluginDescription() throw() + : uid (0), + isInstrument (false), + numInputChannels (0), + numOutputChannels (0) +{ +} + +PluginDescription::~PluginDescription() throw() +{ +} + +PluginDescription::PluginDescription (const PluginDescription& other) throw() + : name (other.name), + pluginFormatName (other.pluginFormatName), + category (other.category), + manufacturerName (other.manufacturerName), + version (other.version), + file (other.file), + uid (other.uid), + isInstrument (other.isInstrument), + lastFileModTime (other.lastFileModTime), + numInputChannels (other.numInputChannels), + numOutputChannels (other.numOutputChannels) +{ +} + +const PluginDescription& PluginDescription::operator= (const PluginDescription& other) throw() +{ + name = other.name; + pluginFormatName = other.pluginFormatName; + category = other.category; + manufacturerName = other.manufacturerName; + version = other.version; + file = other.file; + uid = other.uid; + isInstrument = other.isInstrument; + lastFileModTime = other.lastFileModTime; + numInputChannels = other.numInputChannels; + numOutputChannels = other.numOutputChannels; + + return *this; +} + +bool PluginDescription::isDuplicateOf (const PluginDescription& other) const +{ + return file == other.file + && uid == other.uid; +} + +void PluginDescription::fillInFromInstance (AudioPluginInstance& instance) throw() +{ + name = instance.getName(); + file = instance.getFile(); + uid = instance.getUID(); + lastFileModTime = file.getLastModificationTime(); + pluginFormatName = instance.getFormatName(); + category = instance.getCategory(); + manufacturerName = instance.getManufacturer(); + version = instance.getVersion(); + numInputChannels = instance.getNumInputChannels(); + numOutputChannels = instance.getNumOutputChannels(); + isInstrument = instance.isInstrument(); +} + +AudioPluginInstance* PluginDescription::createInstance() const +{ + AudioPluginInstance* result = 0; + + for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i) + { + AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i); + + result = format->createInstanceFromDescription (*this); + + if (result != 0) + break; + } + + return result; +} + +XmlElement* PluginDescription::createXml() const +{ + XmlElement* const e = new XmlElement (T("PLUGIN")); + e->setAttribute (T("name"), name); + e->setAttribute (T("format"), pluginFormatName); + e->setAttribute (T("category"), category); + e->setAttribute (T("manufacturer"), manufacturerName); + e->setAttribute (T("version"), version); + e->setAttribute (T("file"), file.getFullPathName()); + e->setAttribute (T("uid"), String::toHexString (uid)); + e->setAttribute (T("isInstrument"), isInstrument); + e->setAttribute (T("fileTime"), String::toHexString (lastFileModTime.toMilliseconds())); + e->setAttribute (T("numInputs"), numInputChannels); + e->setAttribute (T("numOutputs"), numOutputChannels); + + return e; +} + +bool PluginDescription::loadFromXml (const XmlElement& xml) +{ + if (xml.hasTagName (T("PLUGIN"))) + { + name = xml.getStringAttribute (T("name")); + pluginFormatName = xml.getStringAttribute (T("format")); + category = xml.getStringAttribute (T("category")); + manufacturerName = xml.getStringAttribute (T("manufacturer")); + version = xml.getStringAttribute (T("version")); + file = File (xml.getStringAttribute (T("file"))); + uid = xml.getStringAttribute (T("uid")).getHexValue32(); + isInstrument = xml.getBoolAttribute (T("isInstrument"), false); + lastFileModTime = Time (xml.getStringAttribute (T("fileTime")).getHexValue64()); + numInputChannels = xml.getIntAttribute (T("numInputs")); + numOutputChannels = xml.getIntAttribute (T("numOutputs")); + + return true; + } + + return false; +} diff --git a/extras/audio plugin host/src/plugins/juce_PluginDescription.h b/extras/audio plugin host/src/plugins/juce_PluginDescription.h new file mode 100644 index 0000000000..f8519c3ed3 --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_PluginDescription.h @@ -0,0 +1,144 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_PLUGINDESCRIPTION_JUCEHEADER__ +#define __JUCE_PLUGINDESCRIPTION_JUCEHEADER__ + +#include "juce_AudioPluginInstance.h" + + +//============================================================================== +/** + A small class to represent some facts about a particular type of plugin. + + This class is for storing and managing the details about a plugin without + actually having to load an instance of it. + + A KnownPluginList contains a list of PluginDescription objects. + + @see KnownPluginList +*/ +class PluginDescription +{ +public: + //============================================================================== + PluginDescription() throw(); + PluginDescription (const PluginDescription& other) throw(); + const PluginDescription& operator= (const PluginDescription& other) throw(); + ~PluginDescription() throw(); + + //============================================================================== + /** The name of the plugin. */ + String name; + + /** The plugin format, e.g. "VST", "AudioUnit", etc. + */ + String pluginFormatName; + + /** A category, such as "Dynamics", "Reverbs", etc. + */ + String category; + + /** The manufacturer. */ + String manufacturerName; + + /** The version. This string doesn't have any particular format. */ + String version; + + /** The binary module file containing the plugin. */ + File file; + + /** The last time the plugin file was changed. + This is handy when scanning for new or changed plugins. + */ + Time lastFileModTime; + + /** A unique ID for the plugin. + + Note that this might not be unique between formats, e.g. a VST and some + other format might actually have the same id. + */ + int uid; + + /** True if the plugin identifies itself as a synthesiser. */ + bool isInstrument; + + /** The number of inputs. */ + int numInputChannels; + + /** The number of outputs. */ + int numOutputChannels; + + /** Returns true if the two descriptions refer the the same plugin. + + This isn't quite as simple as them just having the same file (because of + shell plugins). + */ + bool isDuplicateOf (const PluginDescription& other) const; + + //============================================================================== + /** Fills in this description based on the given plugin. + + Returns true if it worked, false if it couldn't get the info. + */ + void fillInFromInstance (AudioPluginInstance& instance) throw(); + + //============================================================================== + /** Tries to load the type for this description, by trying all the formats + available in the AudioPluginFormat. + + The caller is responsible for deleting the object that is returned. + + Returns 0 if it can't load the plugin for some reason. + */ + AudioPluginInstance* createInstance() const; + + //============================================================================== + /** Creates an XML object containing these details. + + @see loadFromXml + */ + XmlElement* createXml() const; + + /** Reloads the info in this structure from an XML record that was previously + saved with createXML(). + + Returns true if the XML was a valid plugin description. + */ + bool loadFromXml (const XmlElement& xml); + + + //============================================================================== + juce_UseDebuggingNewOperator +}; + + +#endif // __JUCE_PLUGINDESCRIPTION_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/juce_PluginDirectoryScanner.cpp b/extras/audio plugin host/src/plugins/juce_PluginDirectoryScanner.cpp new file mode 100644 index 0000000000..d3ce592490 --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_PluginDirectoryScanner.cpp @@ -0,0 +1,148 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "../../../../juce.h" +#include "juce_PluginDirectoryScanner.h" +#include "juce_AudioPluginFormat.h" + + +//============================================================================== +PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo, + FileSearchPath directoriesToSearch, + const bool recursive, + const File& deadMansPedalFile_) + : list (listToAddTo), + deadMansPedalFile (deadMansPedalFile_), + nextIndex (0), + progress (0) +{ + directoriesToSearch.removeRedundantPaths(); + + for (int j = 0; j < directoriesToSearch.getNumPaths(); ++j) + { + DirectoryIterator iter (directoriesToSearch[j], recursive, "*", File::findFilesAndDirectories); + + while (iter.next()) + { + const File f (iter.getFile()); + + for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i) + { + AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i); + + if (format->fileMightContainThisPluginType (f)) + { + filesToScan.add (new File (f)); + break; + } + } + } + } + + // If any plugins have crashed recently when being loaded, move them to the + // end of the list to give the others a chance to load correctly.. + const StringArray crashedPlugins (getDeadMansPedalFile()); + + for (int i = 0; i < crashedPlugins.size(); ++i) + { + const File f (crashedPlugins[i]); + + for (int j = filesToScan.size(); --j >= 0;) + if (f == *filesToScan.getUnchecked (j)) + filesToScan.move (j, -1); + } +} + +PluginDirectoryScanner::~PluginDirectoryScanner() +{ +} + +//============================================================================== +const File PluginDirectoryScanner::getNextPluginFileThatWillBeScanned() const throw() +{ + File* const file = filesToScan [nextIndex]; + + if (file != 0) + return *file; + + return File::nonexistent; +} + +bool PluginDirectoryScanner::scanNextFile (const bool dontRescanIfAlreadyInList) +{ + File* const file = filesToScan [nextIndex]; + + if (file != 0) + { + if (! list.isListingUpToDate (*file)) + { + OwnedArray typesFound; + + // Add this plugin to the end of the dead-man's pedal list in case it crashes... + StringArray crashedPlugins (getDeadMansPedalFile()); + crashedPlugins.removeString (file->getFullPathName()); + crashedPlugins.add (file->getFullPathName()); + setDeadMansPedalFile (crashedPlugins); + + list.scanAndAddFile (*file, + dontRescanIfAlreadyInList, + typesFound); + + // Managed to load without crashing, so remove it from the dead-man's-pedal.. + crashedPlugins.removeString (file->getFullPathName()); + setDeadMansPedalFile (crashedPlugins); + } + + ++nextIndex; + progress = nextIndex / (float) filesToScan.size(); + } + + return nextIndex < filesToScan.size(); +} + +const StringArray PluginDirectoryScanner::getDeadMansPedalFile() throw() +{ + StringArray lines; + + if (deadMansPedalFile != File::nonexistent) + { + lines.addLines (deadMansPedalFile.loadFileAsString()); + lines.removeEmptyStrings(); + } + + return lines; +} + +void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents) throw() +{ + if (deadMansPedalFile != File::nonexistent) + deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true); +} diff --git a/extras/audio plugin host/src/plugins/juce_PluginDirectoryScanner.h b/extras/audio plugin host/src/plugins/juce_PluginDirectoryScanner.h new file mode 100644 index 0000000000..93880defec --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_PluginDirectoryScanner.h @@ -0,0 +1,116 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__ +#define __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__ + +#include "juce_KnownPluginList.h" + + +//============================================================================== +/** + Scans a directory for plugins, and adds them to a KnownPluginList. + + To use one of these, create it and call scanNextFile() repeatedly, until + it returns false. +*/ +class PluginDirectoryScanner +{ +public: + //============================================================================== + /** + Creates a scanner. + + @param listToAddResultsTo this will get the new types added to it. + @param directoriesToSearch the path to search + @param searchRecursively true to search recursively + @param deadMansPedalFile if this isn't File::nonexistent, then it will + be used as a file to store the names of any plugins + that crash during initialisation. If there are + any plugins listed in it, then these will always + be scanned after all other possible files have + been tried - in this way, even if there's a few + dodgy plugins in your path, then a couple of rescans + will still manage to find all the proper plugins. + It's probably best to choose a file in the user's + application data directory (alongside your app's + settings file) for this. The file format it uses + is just a list of filenames of the modules that + failed. + */ + PluginDirectoryScanner (KnownPluginList& listToAddResultsTo, + FileSearchPath directoriesToSearch, + const bool searchRecursively, + const File& deadMansPedalFile); + + /** Destructor. */ + ~PluginDirectoryScanner(); + + //============================================================================== + /** Tries the next likely-looking file. + + If dontRescanIfAlreadyInList is true, then the file will only be loaded and + re-tested if it's not already in the list, or if the file's modification + time has changed since the list was created. If dontRescanIfAlreadyInList is + false, the file will always be reloaded and tested. + + Returns false when there are no more files to try. + */ + bool scanNextFile (const bool dontRescanIfAlreadyInList); + + /** Returns the file that will be scanned during the next call to scanNextFile(). + + This is handy if you want to show the user which file is currently getting + scanned. + */ + const File getNextPluginFileThatWillBeScanned() const throw(); + + /** Returns the estimated progress, between 0 and 1. + */ + float getProgress() const { return progress; } + + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + KnownPluginList& list; + OwnedArray filesToScan; + File deadMansPedalFile; + int nextIndex; + float progress; + + const StringArray getDeadMansPedalFile() throw(); + void setDeadMansPedalFile (const StringArray& newContents) throw(); +}; + + +#endif // __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/juce_PluginListComponent.cpp b/extras/audio plugin host/src/plugins/juce_PluginListComponent.cpp new file mode 100644 index 0000000000..7fc0ee176a --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_PluginListComponent.cpp @@ -0,0 +1,261 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "../../../../juce.h" +#include "juce_PluginListComponent.h" +#include "juce_PluginDirectoryScanner.h" + + +//============================================================================== +PluginListComponent::PluginListComponent (KnownPluginList& listToEdit, + const File& deadMansPedalFile_, + PropertiesFile* const propertiesToUse_) + : list (listToEdit), + deadMansPedalFile (deadMansPedalFile_), + propertiesToUse (propertiesToUse_) +{ + addAndMakeVisible (listBox = new ListBox (String::empty, this)); + + addAndMakeVisible (optionsButton = new TextButton ("Options...")); + optionsButton->addButtonListener (this); + optionsButton->setTriggeredOnMouseDown (true); + + setSize (400, 600); + list.addChangeListener (this); +} + +PluginListComponent::~PluginListComponent() +{ + list.removeChangeListener (this); + deleteAllChildren(); +} + +void PluginListComponent::resized() +{ + listBox->setBounds (0, 0, getWidth(), getHeight() - 30); + optionsButton->changeWidthToFitText (24); + optionsButton->setTopLeftPosition (8, getHeight() - 28); +} + +void PluginListComponent::changeListenerCallback (void*) +{ + listBox->updateContent(); + listBox->repaint(); +} + +int PluginListComponent::getNumRows() +{ + return list.getNumTypes(); +} + +void PluginListComponent::paintListBoxItem (int row, + Graphics& g, + int width, int height, + bool rowIsSelected) +{ + if (rowIsSelected) + g.fillAll (findColour (TextEditor::highlightColourId)); + + const PluginDescription* const pd = list.getType (row); + + if (pd != 0) + { + GlyphArrangement ga; + ga.addCurtailedLineOfText (Font (height * 0.7f, Font::bold), pd->name, 8.0f, height * 0.8f, width - 10.0f, true); + + g.setColour (Colours::black); + ga.draw (g); + + float x, y, r, b; + ga.getBoundingBox (0, -1, x, y, r, b, false); + + String desc; + desc << pd->pluginFormatName + << (pd->isInstrument ? " instrument" : " effect") + << " - " + << pd->numInputChannels << (pd->numInputChannels == 1 ? " in" : " ins") + << " / " + << pd->numOutputChannels << (pd->numOutputChannels == 1 ? " out" : " outs"); + + if (pd->manufacturerName.isNotEmpty()) + desc << " - " << pd->manufacturerName; + + if (pd->version.isNotEmpty()) + desc << " - " << pd->version; + + if (pd->category.isNotEmpty()) + desc << " - category: '" << pd->category << '\''; + + g.setColour (Colours::grey); + + ga.clear(); + ga.addCurtailedLineOfText (Font (height * 0.6f), desc, r + 10.0f, height * 0.8f, width - r - 12.0f, true); + ga.draw (g); + } +} + +void PluginListComponent::deleteKeyPressed (int lastRowSelected) +{ + list.removeType (lastRowSelected); +} + +void PluginListComponent::buttonClicked (Button* b) +{ + if (optionsButton == b) + { + PopupMenu menu; + menu.addItem (1, TRANS("Clear list")); + menu.addItem (5, TRANS("Remove selected plugin from list"), listBox->getNumSelectedRows() > 0); + menu.addItem (6, TRANS("Show folder containing selected plugin"), listBox->getNumSelectedRows() > 0); + menu.addSeparator(); + menu.addItem (2, TRANS("Sort alphabetically")); + menu.addItem (3, TRANS("Sort by category")); + menu.addItem (4, TRANS("Sort by manufacturer")); + menu.addSeparator(); + + for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i) + { + AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i); + + if (format->getDefaultLocationsToSearch().getNumPaths() > 0) + menu.addItem (10 + i, "Scan for new or updated " + format->getName() + " plugins..."); + } + + const int r = menu.showAt (optionsButton); + + if (r == 1) + { + list.clear(); + } + else if (r == 2) + { + list.sort (KnownPluginList::sortAlphabetically); + } + else if (r == 3) + { + list.sort (KnownPluginList::sortByCategory); + } + else if (r == 4) + { + list.sort (KnownPluginList::sortByManufacturer); + } + else if (r == 5) + { + const SparseSet selected (listBox->getSelectedRows()); + + for (int i = list.getNumTypes(); --i >= 0;) + if (selected.contains (i)) + list.removeType (i); + } + else if (r == 6) + { + const PluginDescription* const desc = list.getType (listBox->getSelectedRow()); + + if (desc != 0) + desc->file.getParentDirectory().startAsProcess(); + } + else if (r != 0) + { + scanFor (AudioPluginFormatManager::getInstance()->getFormat (r - 10)); + } + } +} + +bool PluginListComponent::filesDropped (const StringArray& files, int, int) +{ + OwnedArray typesFound; + list.scanAndAddDragAndDroppedFiles (files, typesFound); + + return typesFound.size() > 0; +} + +void PluginListComponent::scanFor (AudioPluginFormat* format) +{ + if (format == 0) + return; + + FileSearchPath path (format->getDefaultLocationsToSearch()); + + if (propertiesToUse != 0) + path = propertiesToUse->getValue ("lastPluginScanPath_" + format->getName(), path.toString()); + + { + AlertWindow aw (TRANS("Select folders to scan..."), String::empty, AlertWindow::NoIcon); + FileSearchPathListComponent pathList; + pathList.setSize (500, 300); + pathList.setPath (path); + + aw.addCustomComponent (&pathList); + aw.addButton (TRANS("Scan"), 1, KeyPress::returnKey); + aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); + + if (aw.runModalLoop() == 0) + return; + + path = pathList.getPath(); + } + + if (propertiesToUse != 0) + { + propertiesToUse->setValue ("lastPluginScanPath_" + format->getName(), path.toString()); + propertiesToUse->saveIfNeeded(); + } + + double progress = 0.0; + + AlertWindow aw (TRANS("Scanning for plugins..."), + TRANS("Searching for all possible plugin files..."), AlertWindow::NoIcon); + + aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); + aw.addProgressBarComponent (progress); + + aw.enterModalState(); + + MessageManager::getInstance()->dispatchPendingMessages(); + + PluginDirectoryScanner scanner (list, path, true, deadMansPedalFile); + + for (;;) + { + aw.setMessage (TRANS("Testing:\n\n") + + scanner.getNextPluginFileThatWillBeScanned().getFileName()); + + MessageManager::getInstance()->dispatchPendingMessages (500); + + if (! scanner.scanNextFile (true)) + break; + + if (! aw.isCurrentlyModal()) + break; + + progress = scanner.getProgress(); + } +} diff --git a/extras/audio plugin host/src/plugins/juce_PluginListComponent.h b/extras/audio plugin host/src/plugins/juce_PluginListComponent.h new file mode 100644 index 0000000000..b6a810075d --- /dev/null +++ b/extras/audio plugin host/src/plugins/juce_PluginListComponent.h @@ -0,0 +1,95 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_PLUGINLISTCOMPONENT_JUCEHEADER__ +#define __JUCE_PLUGINLISTCOMPONENT_JUCEHEADER__ + +#include "juce_KnownPluginList.h" +#include "juce_AudioPluginFormat.h" + + +//============================================================================== +/** + A component displaying a list of plugins, with options to scan for them, + add, remove and sort them. +*/ +class PluginListComponent : public Component, + public ListBoxModel, + public ChangeListener, + public ButtonListener +{ +public: + //============================================================================== + /** + Creates the list component. + + For info about the deadMansPedalFile, see the PluginDirectoryScanner constructor. + + The properties file, if supplied is used to store the user's last search paths. + */ + PluginListComponent (KnownPluginList& listToRepresent, + const File& deadMansPedalFile, + PropertiesFile* const propertiesToUse); + + /** Destructor. */ + ~PluginListComponent(); + + //============================================================================== + /** @internal */ + void resized(); + /** @internal */ + bool filesDropped (const StringArray& files, int x, int y); + /** @internal */ + int getNumRows(); + /** @internal */ + void paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected); + /** @internal */ + void deleteKeyPressed (int lastRowSelected); + /** @internal */ + void buttonClicked (Button* b); + /** @internal */ + void changeListenerCallback (void*); + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + KnownPluginList& list; + File deadMansPedalFile; + ListBox* listBox; + TextButton* optionsButton; + PropertiesFile* propertiesToUse; + + void scanFor (AudioPluginFormat* format); +}; + + +#endif // __JUCE_PLUGINLISTCOMPONENT_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/vst/juce_VSTPluginFormat.h b/extras/audio plugin host/src/plugins/vst/juce_VSTPluginFormat.h new file mode 100644 index 0000000000..515756fc0d --- /dev/null +++ b/extras/audio plugin host/src/plugins/vst/juce_VSTPluginFormat.h @@ -0,0 +1,61 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ +#define __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ + +#include "../juce_AudioPluginFormat.h" + + +//============================================================================== +/** + Implements a plugin format manager for VSTs. +*/ +class VSTPluginFormat : public AudioPluginFormat +{ +public: + //============================================================================== + VSTPluginFormat(); + ~VSTPluginFormat(); + + //============================================================================== + const String getName() const { return "VST"; } + void findAllTypesForFile (OwnedArray & results, const File& file); + AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); + bool fileMightContainThisPluginType (const File& file); + const FileSearchPath getDefaultLocationsToSearch(); + + //============================================================================== + juce_UseDebuggingNewOperator +}; + + +#endif // __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp b/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp new file mode 100644 index 0000000000..e805bce25a --- /dev/null +++ b/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp @@ -0,0 +1,2540 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifdef _WIN32 + #define _WIN32_WINNT 0x500 + #define STRICT + #include + #include + #pragma warning (disable : 4312) +#else + #include +#endif + +#include "../../../../../juce.h" +#include "juce_VSTPluginInstance.h" +#include "../juce_PluginDescription.h" + +#if ! JUCE_WIN32 + #define _fpreset() + #define _clearfp() +#endif + +//============================================================================== +const int fxbVersionNum = 1; + +//============================================================================== +struct fxProgram +{ + long chunkMagic; // 'CcnK' + long byteSize; // of this chunk, excl. magic + byteSize + long fxMagic; // 'FxCk' + long version; + long fxID; // fx unique id + long fxVersion; + long numParams; + char prgName[28]; + float params[1]; // variable no. of parameters +}; + +struct fxSet +{ + long chunkMagic; // 'CcnK' + long byteSize; // of this chunk, excl. magic + byteSize + long fxMagic; // 'FxBk' + long version; + long fxID; // fx unique id + long fxVersion; + long numPrograms; + char future[128]; + fxProgram programs[1]; // variable no. of programs +}; + +struct fxChunkSet +{ + long chunkMagic; // 'CcnK' + long byteSize; // of this chunk, excl. magic + byteSize + long fxMagic; // 'FxCh', 'FPCh', or 'FBCh' + long version; + long fxID; // fx unique id + long fxVersion; + long numPrograms; + char future[128]; + long chunkSize; + char chunk[8]; // variable +}; + +struct fxProgramSet +{ + long chunkMagic; // 'CcnK' + long byteSize; // of this chunk, excl. magic + byteSize + long fxMagic; // 'FxCh', 'FPCh', or 'FBCh' + long version; + long fxID; // fx unique id + long fxVersion; + long numPrograms; + char name[28]; + long chunkSize; + char chunk[8]; // variable +}; + + +#ifdef JUCE_LITTLE_ENDIAN + static long swap (const long x) throw() { return (long) swapByteOrder ((uint32) x); } + + static float swapFloat (const float x) throw() + { + union { uint32 asInt; float asFloat; } n; + n.asFloat = x; + n.asInt = swapByteOrder (n.asInt); + return n.asFloat; + } +#else + #define swap(x) (x) + #define swapFloat(x) (x) +#endif + +//============================================================================== +typedef AEffect* (*MainCall) (audioMasterCallback); + +static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); + +#if JUCE_PPC + static void* audioMasterCoerced = 0; +#endif + +static int shellUIDToCreate = 0; +static int insideVSTCallback = 0; + +static Array activeWindows; + +//============================================================================== +// Change this to disable logging of various VST activities +#ifndef VST_LOGGING + #define VST_LOGGING 1 +#endif + +#if VST_LOGGING + #define log(a) Logger::writeToLog(a); +#else + #define log(a) +#endif + +//============================================================================== +#if JUCE_MAC +namespace JUCE_NAMESPACE +{ + extern bool juce_isHIViewCreatedByJuce (HIViewRef view); + extern bool juce_isWindowCreatedByJuce (WindowRef window); +} + +#if JUCE_PPC +static void* NewCFMFromMachO (void* const machofp) throw() +{ + void* result = juce_malloc (8); + + ((void**) result)[0] = machofp; + ((void**) result)[1] = result; + + return result; +} +#endif +#endif + +//============================================================================== +static VoidArray activeModules; + +//============================================================================== +class ModuleHandle : public ReferenceCountedObject +{ +public: + //============================================================================== + File file; + MainCall moduleMain; + String pluginName; + + //============================================================================== + static ModuleHandle* findOrCreateModule (const File& file) + { + for (int i = activeModules.size(); --i >= 0;) + { + ModuleHandle* const module = (ModuleHandle*) activeModules.getUnchecked(i); + + if (module->file == file) + return module; + } + + _fpreset(); // (doesn't do any harm) + ++insideVSTCallback; + shellUIDToCreate = 0; + + log ("Attempting to load VST: " + file.getFullPathName()); + + ModuleHandle* m = new ModuleHandle (file); + + if (! m->open()) + deleteAndZero (m); + + --insideVSTCallback; + _fpreset(); // (doesn't do any harm) + + return m; + } + + //============================================================================== + ModuleHandle (const File& file_) + : file (file_), + moduleMain (0), +#if JUCE_WIN32 + hModule (0) +#else + fragId (0), + resHandle (0), + bundleRef (0), + resFileId (0) +#endif + { + activeModules.add (this); + +#if JUCE_WIN32 + fullParentDirectoryPathName = file_.getParentDirectory().getFullPathName(); +#else + PlatformUtilities::makeFSSpecFromPath (&parentDirFSSpec, file_.getParentDirectory().getFullPathName()); +#endif + } + + ~ModuleHandle() + { + activeModules.removeValue (this); + + close(); + } + + //============================================================================== + juce_UseDebuggingNewOperator + + //============================================================================== +#if JUCE_WIN32 + HMODULE hModule; + String fullParentDirectoryPathName; + + static HMODULE loadDLL (const TCHAR* filename) throw() + { + HMODULE h = 0; + + __try + { + h = LoadLibrary (filename); + } + __finally + { + } + + return h; + } + + bool open() + { + static bool timePeriodSet = false; + + if (! timePeriodSet) + { + timePeriodSet = true; + timeBeginPeriod (2); + } + + pluginName = file.getFileNameWithoutExtension(); + + hModule = loadDLL (file.getFullPathName()); + + if (hModule == 0) + return false; + + moduleMain = (MainCall) GetProcAddress (hModule, "VSTPluginMain"); + + if (moduleMain == 0) + moduleMain = (MainCall) GetProcAddress (hModule, "main"); + + return moduleMain != 0; + } + + void close() + { + if (hModule != 0) + { + try + { + _fpreset(); // (doesn't do any harm) + FreeLibrary (hModule); + } + catch (...) + {} + } + } + + void closeEffect (AEffect* eff) + { + eff->dispatcher (eff, effClose, 0, 0, 0, 0); + } + +#else + CFragConnectionID fragId; + Handle resHandle; + CFBundleRef bundleRef; + FSSpec parentDirFSSpec; + short resFileId; + + bool open() + { + bool ok = false; + const String filename (file.getFullPathName()); + + if (file.hasFileExtension (T(".vst"))) + { + CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) (const char*) filename, + filename.length(), file.isDirectory()); + + if (url != 0) + { + bundleRef = CFBundleCreate (kCFAllocatorDefault, url); + CFRelease (url); + + if (bundleRef != 0) + { + if (CFBundleLoadExecutable (bundleRef)) + { + moduleMain = (MainCall) CFBundleGetFunctionPointerForName (bundleRef, CFSTR("main_macho")); + + if (moduleMain == 0) + moduleMain = (MainCall) CFBundleGetFunctionPointerForName (bundleRef, CFSTR("VSTPluginMain")); + + if (moduleMain != 0) + { + CFTypeRef name = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleName")); + + if (name != 0) + { + if (CFGetTypeID (name) == CFStringGetTypeID()) + { + char buffer[1024]; + + if (CFStringGetCString ((CFStringRef) name, buffer, sizeof (buffer), CFStringGetSystemEncoding())) + pluginName = buffer; + } + } + + if (pluginName.isEmpty()) + pluginName = file.getFileNameWithoutExtension(); + + resFileId = CFBundleOpenBundleResourceMap (bundleRef); + + ok = true; + } + } + + if (! ok) + { + CFBundleUnloadExecutable (bundleRef); + CFRelease (bundleRef); + bundleRef = 0; + } + } + } + } +#if JUCE_PPC + else + { + FSRef fn; + + if (FSPathMakeRef ((UInt8*) (const char*) filename, &fn, 0) == noErr) + { + resFileId = FSOpenResFile (&fn, fsRdPerm); + + if (resFileId != -1) + { + const int numEffs = Count1Resources ('aEff'); + + for (int i = 0; i < numEffs; ++i) + { + resHandle = Get1IndResource ('aEff', i + 1); + + if (resHandle != 0) + { + OSType type; + Str255 name; + SInt16 id; + GetResInfo (resHandle, &id, &type, name); + pluginName = String ((const char*) name + 1, name[0]); + DetachResource (resHandle); + HLock (resHandle); + + Ptr ptr; + Str255 errorText; + + OSErr err = GetMemFragment (*resHandle, GetHandleSize (resHandle), + name, kPrivateCFragCopy, + &fragId, &ptr, errorText); + + if (err == noErr) + { + moduleMain = (MainCall) newMachOFromCFM (ptr); + ok = true; + } + else + { + HUnlock (resHandle); + } + + break; + } + } + + if (! ok) + CloseResFile (resFileId); + } + } + } +#endif + + return ok; + } + + void close() + { +#if JUCE_PPC + if (fragId != 0) + { + if (moduleMain != 0) + disposeMachOFromCFM ((void*) moduleMain); + + CloseConnection (&fragId); + HUnlock (resHandle); + + if (resFileId != 0) + CloseResFile (resFileId); + } + else +#endif + if (bundleRef != 0) + { + CFBundleCloseBundleResourceMap (bundleRef, resFileId); + + if (CFGetRetainCount (bundleRef) == 1) + CFBundleUnloadExecutable (bundleRef); + + if (CFGetRetainCount (bundleRef) > 0) + CFRelease (bundleRef); + } + } + + void closeEffect (AEffect* eff) + { +#if JUCE_PPC + if (fragId != 0) + { + VoidArray thingsToDelete; + thingsToDelete.add ((void*) eff->dispatcher); + thingsToDelete.add ((void*) eff->process); + thingsToDelete.add ((void*) eff->setParameter); + thingsToDelete.add ((void*) eff->getParameter); + thingsToDelete.add ((void*) eff->processReplacing); + + eff->dispatcher (eff, effClose, 0, 0, 0, 0); + + for (int i = thingsToDelete.size(); --i >= 0;) + disposeMachOFromCFM (thingsToDelete[i]); + } + else +#endif + { + eff->dispatcher (eff, effClose, 0, 0, 0, 0); + } + } + +#if JUCE_PPC + static void* newMachOFromCFM (void* cfmfp) + { + if (cfmfp == 0) + return 0; + + UInt32* const mfp = (UInt32*) juce_malloc (sizeof (UInt32) * 6); + + mfp[0] = 0x3d800000 | ((UInt32) cfmfp >> 16); + mfp[1] = 0x618c0000 | ((UInt32) cfmfp & 0xffff); + mfp[2] = 0x800c0000; + mfp[3] = 0x804c0004; + mfp[4] = 0x7c0903a6; + mfp[5] = 0x4e800420; + + MakeDataExecutable (mfp, sizeof (UInt32) * 6); + return mfp; + } + + static void disposeMachOFromCFM (void* ptr) + { + juce_free (ptr); + } + + void coerceAEffectFunctionCalls (AEffect* eff) + { + if (fragId != 0) + { + eff->dispatcher = (AEffectDispatcherProc) newMachOFromCFM ((void*) eff->dispatcher); + eff->process = (AEffectProcessProc) newMachOFromCFM ((void*) eff->process); + eff->setParameter = (AEffectSetParameterProc) newMachOFromCFM ((void*) eff->setParameter); + eff->getParameter = (AEffectGetParameterProc) newMachOFromCFM ((void*) eff->getParameter); + eff->processReplacing = (AEffectProcessProc) newMachOFromCFM ((void*) eff->processReplacing); + } + } +#endif + +#endif +}; + + +//============================================================================== +VSTPluginInstance::VSTPluginInstance (const ReferenceCountedObjectPtr & module_) + : effect (0), + wantsMidiMessages (false), + initialised (false), + isPowerOn (false), + numAllocatedMidiEvents (0), + midiEventsToSend (0), + tempBuffer (2, 8), + channelsIn (0), + channelsOut (0), + module (module_) +{ + try + { + _fpreset(); + + ++insideVSTCallback; + + name = module->pluginName; + log (T("Creating VST instance: ") + name); + +#if JUCE_MAC + if (module->resFileId != 0) + UseResFile (module->resFileId); + +#if JUCE_PPC + if (module->fragId != 0) + { + static void* audioMasterCoerced = 0; + if (audioMasterCoerced == 0) + audioMasterCoerced = NewCFMFromMachO ((void*) &audioMaster); + + effect = module->moduleMain ((audioMasterCallback) audioMasterCoerced); + } + else +#endif +#endif + { + effect = module->moduleMain (&audioMaster); + } + + --insideVSTCallback; + + if (effect != 0 && effect->magic == kEffectMagic) + { +#if JUCE_PPC + module->coerceAEffectFunctionCalls (effect); +#endif + + jassert (effect->resvd2 == 0); + jassert (effect->object != 0); + + _fpreset(); // some dodgy plugs fuck around with this + } + else + { + effect = 0; + } + } + catch (...) + { + --insideVSTCallback; + } +} + +VSTPluginInstance::~VSTPluginInstance() +{ + { + const ScopedLock sl (lock); + + jassert (insideVSTCallback == 0); + + if (effect != 0 && effect->magic == kEffectMagic) + { + try + { +#if JUCE_MAC + if (module->resFileId != 0) + UseResFile (module->resFileId); +#endif + + // Must delete any editors before deleting the plugin instance! + jassert (getActiveEditor() == 0); + + _fpreset(); // some dodgy plugs fuck around with this + + module->closeEffect (effect); + } + catch (...) + {} + } + + effect = 0; + } + + freeMidiEvents(); + + juce_free (channelsIn); + channelsIn = 0; + juce_free (channelsOut); + channelsOut = 0; +} + +//============================================================================== +void VSTPluginInstance::initialise() +{ + if (initialised || effect == 0) + return; + + log (T("Initialising VST: ") + module->pluginName); + initialised = true; + + dispatch (effIdentify, 0, 0, 0, 0); + + { + char buffer [kVstMaxEffectNameLen + 8]; + zerostruct (buffer); + dispatch (effGetEffectName, 0, 0, buffer, 0); + + name = String (buffer); + if (name.trim().isEmpty()) + name = module->pluginName; + } + + dispatch (effSetSampleRate, 0, 0, 0, (float) sampleRate); + dispatch (effSetBlockSize, 0, jmax (16, blockSize), 0, 0); + + dispatch (effOpen, 0, 0, 0, 0); + + numOutputChannels = effect->numOutputs; + numInputChannels = effect->numInputs; + + if (getNumPrograms() > 1) + setCurrentProgram (0); + else + dispatch (effSetProgram, 0, 0, 0, 0); + + int i; + for (i = effect->numInputs; --i >= 0;) + dispatch (effConnectInput, i, 1, 0, 0); + + for (i = effect->numOutputs; --i >= 0;) + dispatch (effConnectOutput, i, 1, 0, 0); + + updateStoredProgramNames(); + + wantsMidiMessages = dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) != 0; +} + + +//============================================================================== +void JUCE_CALLTYPE VSTPluginInstance::prepareToPlay (double sampleRate_, int samplesPerBlockExpected) +{ + sampleRate = sampleRate_; + blockSize = samplesPerBlockExpected; + midiCollector.reset (sampleRate); + + juce_free (channelsIn); + channelsIn = (float**) juce_calloc (sizeof (float*) * jmax (16, getNumInputChannels() + 4)); + juce_free (channelsOut); + channelsOut = (float**) juce_calloc (sizeof (float*) * jmax (16, getNumOutputChannels() + 4)); + + vstHostTime.tempo = 120.0; + vstHostTime.timeSigNumerator = 4; + vstHostTime.timeSigDenominator = 4; + vstHostTime.sampleRate = sampleRate; + vstHostTime.samplePos = 0; + vstHostTime.flags = kVstNanosValid; /*| kVstTransportPlaying | kVstTempoValid | kVstTimeSigValid*/; + + initialise(); + + if (initialised) + { + wantsMidiMessages = wantsMidiMessages + || (dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) != 0); + + if (wantsMidiMessages) + ensureMidiEventSize (256); + else + freeMidiEvents(); + + incomingMidi.clear(); + + dispatch (effSetSampleRate, 0, 0, 0, (float) sampleRate); + dispatch (effSetBlockSize, 0, jmax (16, blockSize), 0, 0); + + tempBuffer.setSize (jmax (effect->numOutputs, effect->numInputs), blockSize); + + if (! isPowerOn) + setPower (true); + + // dodgy hack to force some plugins to initialise the sample rate.. + if ((! hasEditor()) && getNumParameters() > 0) + { + const float old = getParameter (0); + setParameter (0, (old < 0.5f) ? 1.0f : 0.0f); + setParameter (0, old); + } + + dispatch (effStartProcess, 0, 0, 0, 0); + } +} + +void JUCE_CALLTYPE VSTPluginInstance::releaseResources() +{ + if (initialised) + { + dispatch (effStopProcess, 0, 0, 0, 0); + setPower (false); + } + + midiCollector.reset (sampleRate); + tempBuffer.setSize (1, 1); + incomingMidi.clear(); + + freeMidiEvents(); + juce_free (channelsIn); + channelsIn = 0; + juce_free (channelsOut); + channelsOut = 0; +} + +void JUCE_CALLTYPE VSTPluginInstance::processBlock (const AudioSampleBuffer& input, + AudioSampleBuffer& output, + const bool accumulateOutput, + MidiBuffer& midiMessages) +{ + const int numSamples = output.getNumSamples(); + + if (initialised) + { +#if JUCE_WIN32 + vstHostTime.nanoSeconds = timeGetTime() * 1000000.0; +#else + UnsignedWide micro; + Microseconds (µ); + vstHostTime.nanoSeconds = micro.lo * 1000.0; +#endif + + if (wantsMidiMessages) + { + MidiBuffer::Iterator iter (midiMessages); + + int eventIndex = 0; + const uint8* midiData; + int numBytesOfMidiData, samplePosition; + + while (iter.getNextEvent (midiData, numBytesOfMidiData, samplePosition)) + { + if (numBytesOfMidiData < 4) + { + ensureMidiEventSize (eventIndex); + VstMidiEvent* const e + = (VstMidiEvent*) ((VstEvents*) midiEventsToSend)->events [eventIndex++]; + + // check that some plugin hasn't messed up our objects + jassert (e->type == kVstMidiType); + jassert (e->byteSize == 24); + + e->deltaFrames = jlimit (0, numSamples - 1, samplePosition); + e->noteLength = 0; + e->noteOffset = 0; + e->midiData[0] = midiData[0]; + e->midiData[1] = midiData[1]; + e->midiData[2] = midiData[2]; + e->detune = 0; + e->noteOffVelocity = 0; + } + } + + if (midiEventsToSend == 0) + ensureMidiEventSize (1); + + ((VstEvents*) midiEventsToSend)->numEvents = eventIndex; + + try + { + effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend, 0); + } + catch (...) + {} + } + + { + int i; + for (i = effect->numInputs; --i >= 0;) + channelsIn[i] = input.getSampleData (jmin (i, input.getNumChannels() - 1)); // xxx should use empty temp buffers if it runs out + + for (i = effect->numOutputs; --i >= 0;) + channelsOut[i] = output.getSampleData (jmin (i, output.getNumChannels() - 1)); + } + + _clearfp(); + + try + { + if (accumulateOutput) + { + effect->process (effect, channelsIn, channelsOut, numSamples); + } + else + { + if ((effect->flags & effFlagsCanReplacing) != 0) + { + effect->processReplacing (effect, channelsIn, channelsOut, numSamples); + } + else + { + output.clear(); + effect->process (effect, channelsIn, channelsOut, numSamples); + } + } + } + catch (...) + {} + } + else + { + // Not initialised, so just bypass.. + if (! accumulateOutput) + { + for (int i = output.getNumChannels(); --i >= 0;) + output.copyFrom (i, 0, + input, + jmin (i, input.getNumChannels() - 1), + 0, + numSamples); + } + } + + { + // copy any incoming midi.. + const ScopedLock sl (midiInLock); + + midiMessages = incomingMidi; + incomingMidi.clear(); + } +} + +//============================================================================== +void VSTPluginInstance::ensureMidiEventSize (int numEventsNeeded) +{ + if (numEventsNeeded > numAllocatedMidiEvents) + { + numEventsNeeded = (numEventsNeeded + 32) & ~31; + + const int size = 20 + sizeof (VstEvent*) * numEventsNeeded; + + if (midiEventsToSend == 0) + midiEventsToSend = juce_calloc (size); + else + midiEventsToSend = juce_realloc (midiEventsToSend, size); + + for (int i = numAllocatedMidiEvents; i < numEventsNeeded; ++i) + { + VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (sizeof (VstMidiEvent)); + e->type = kVstMidiType; + e->byteSize = 24; + + ((VstEvents*) midiEventsToSend)->events[i] = (VstEvent*) e; + } + + numAllocatedMidiEvents = numEventsNeeded; + } +} + +void VSTPluginInstance::freeMidiEvents() +{ + if (midiEventsToSend != 0) + { + for (int i = numAllocatedMidiEvents; --i >= 0;) + juce_free (((VstEvents*) midiEventsToSend)->events[i]); + + juce_free (midiEventsToSend); + midiEventsToSend = 0; + numAllocatedMidiEvents = 0; + } +} + +void VSTPluginInstance::handleMidiFromPlugin (const VstEvents* const events) +{ + if (events != 0) + { + const ScopedLock sl (midiInLock); + + for (int i = 0; i < events->numEvents; ++i) + { + const VstEvent* const e = events->events[i]; + + if (e->type == kVstMidiType) + { + incomingMidi.addEvent ((const uint8*) ((const VstMidiEvent*) e)->midiData, + 3, e->deltaFrames); + } + } + } +} + +//============================================================================== +class VSTPluginWindow : public AudioFilterEditor, + public Timer +{ +public: + //============================================================================== + VSTPluginWindow (VSTPluginInstance& plugin_) + : AudioFilterEditor (&plugin_), + plugin (plugin_), + isOpen (false), + wasShowing (false), + pluginRefusesToResize (false), + pluginWantsKeys (false), + alreadyInside (false), + recursiveResize (false) + { +#if JUCE_WIN32 + sizeCheckCount = 0; + pluginHWND = 0; +#else + pluginViewRef = 0; +#endif + + movementWatcher = new CompMovementWatcher (this); + + activeWindows.add (this); + + setOpaque (true); + setVisible (true); + } + + ~VSTPluginWindow() + { + deleteAndZero (movementWatcher); + + closePluginWindow(); + + activeWindows.removeValue (this); + plugin.editorBeingDeleted (this); + } + + //============================================================================== + void componentMovedOrResized() + { + if (recursiveResize) + return; + + Component* const topComp = getTopLevelComponent(); + + if (topComp->getPeer() != 0) + { + int x = 0, y = 0; + relativePositionToOtherComponent (topComp, x, y); + + recursiveResize = true; + +#if JUCE_MAC + if (pluginViewRef != 0) + { + HIRect r; + r.origin.x = (float) x; + r.origin.y = (float) y; + r.size.width = (float) getWidth(); + r.size.height = (float) getHeight(); + HIViewSetFrame (pluginViewRef, &r); + } + else if (pluginWindowRef != 0) + { + Rect r; + r.left = getScreenX(); + r.top = getScreenY(); + r.right = r.left + getWidth(); + r.bottom = r.top + getHeight(); + + WindowGroupRef group = GetWindowGroup (pluginWindowRef); + WindowGroupAttributes atts; + GetWindowGroupAttributes (group, &atts); + ChangeWindowGroupAttributes (group, 0, kWindowGroupAttrMoveTogether); + + SetWindowBounds (pluginWindowRef, kWindowContentRgn, &r); + + if ((atts & kWindowGroupAttrMoveTogether) != 0) + ChangeWindowGroupAttributes (group, kWindowGroupAttrMoveTogether, 0); + } + else + { + repaint(); + } +#else + if (pluginHWND != 0) + MoveWindow (pluginHWND, x, y, getWidth(), getHeight(), TRUE); +#endif + + recursiveResize = false; + } + } + + void componentVisibilityChanged() + { + const bool isShowingNow = isShowing(); + + if (wasShowing != isShowingNow) + { + wasShowing = isShowingNow; + + if (isShowingNow) + openPluginWindow(); + else + closePluginWindow(); + } + + componentMovedOrResized(); + } + + void componentPeerChanged() + { + closePluginWindow(); + openPluginWindow(); + } + + //============================================================================== + bool keyStateChanged() + { + return pluginWantsKeys; + } + + bool keyPressed (const KeyPress&) + { + return pluginWantsKeys; + } + + //============================================================================== + void paint (Graphics& g) + { + if (isOpen) + { + ComponentPeer* const peer = getPeer(); + + if (peer != 0) + { + peer->addMaskedRegion (getScreenX() - peer->getScreenX(), + getScreenY() - peer->getScreenY(), + getWidth(), getHeight()); + +#if JUCE_MAC + dispatch (effEditDraw, 0, 0, 0, 0); +#endif + } + } + else + { + g.fillAll (Colours::black); + } + } + + //============================================================================== + void timerCallback() + { +#if JUCE_WIN32 + if (--sizeCheckCount <= 0) + { + sizeCheckCount = 10; + + checkPluginWindowSize(); + } +#endif + + try + { + static bool reentrant = false; + + if (! reentrant) + { + reentrant = true; + plugin.dispatch (effEditIdle, 0, 0, 0, 0); + reentrant = false; + } + } + catch (...) + {} + } + + //============================================================================== + void mouseDown (const MouseEvent& e) + { +#if JUCE_MAC + if (! alreadyInside) + { + alreadyInside = true; + toFront (true); + dispatch (effEditMouse, e.x, e.y, 0, 0); + alreadyInside = false; + } + else + { + PostEvent (::mouseDown, 0); + } +#else + (void) e; + + toFront (true); +#endif + } + + void broughtToFront() + { + activeWindows.removeValue (this); + activeWindows.add (this); + +#if JUCE_MAC + dispatch (effEditTop, 0, 0, 0, 0); +#endif + } + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + VSTPluginInstance& plugin; + bool isOpen, wasShowing, recursiveResize; + bool pluginWantsKeys, pluginRefusesToResize, alreadyInside; + +#if JUCE_WIN32 + HWND pluginHWND; + void* originalWndProc; + int sizeCheckCount; +#else + HIViewRef pluginViewRef; + WindowRef pluginWindowRef; +#endif + + //============================================================================== + void openPluginWindow() + { + if (isOpen || getWindowHandle() == 0) + return; + + log (T("Opening VST UI: ") + plugin.getName()); + isOpen = true; + + ERect* rect = 0; + dispatch (effEditGetRect, 0, 0, &rect, 0); + dispatch (effEditOpen, 0, 0, getWindowHandle(), 0); + + // do this before and after like in the steinberg example + dispatch (effEditGetRect, 0, 0, &rect, 0); + dispatch (effGetProgram, 0, 0, 0, 0); // also in steinberg code + + // Install keyboard hooks + pluginWantsKeys = (dispatch (effKeysRequired, 0, 0, 0, 0) == 0); + +#if JUCE_WIN32 + originalWndProc = 0; + pluginHWND = GetWindow ((HWND) getWindowHandle(), GW_CHILD); + + if (pluginHWND == 0) + { + isOpen = false; + setSize (300, 150); + return; + } + + #pragma warning (push) + #pragma warning (disable: 4244) + + originalWndProc = (void*) GetWindowLongPtr (pluginHWND, GWL_WNDPROC); + + if (! pluginWantsKeys) + SetWindowLongPtr (pluginHWND, GWL_WNDPROC, (LONG_PTR) vstHookWndProc); + + #pragma warning (pop) + + int w, h; + RECT r; + GetWindowRect (pluginHWND, &r); + w = r.right - r.left; + h = r.bottom - r.top; + + if (rect != 0) + { + const int rw = rect->right - rect->left; + const int rh = rect->bottom - rect->top; + + if ((rw > 50 && rh > 50 && rw < 2000 && rh < 2000 && rw != w && rh != h) + || ((w == 0 && rw > 0) || (h == 0 && rh > 0))) + { + // very dodgy logic to decide which size is right. + if (abs (rw - w) > 350 || abs (rh - h) > 350) + { + SetWindowPos (pluginHWND, 0, + 0, 0, rw, rh, + SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); + + GetWindowRect (pluginHWND, &r); + + w = r.right - r.left; + h = r.bottom - r.top; + + pluginRefusesToResize = (w != rw) || (h != rh); + + w = rw; + h = rh; + } + } + } +#else + HIViewRef root = HIViewGetRoot ((WindowRef) getWindowHandle()); + HIViewFindByID (root, kHIViewWindowContentID, &root); + pluginViewRef = HIViewGetFirstSubview (root); + + while (pluginViewRef != 0 && juce_isHIViewCreatedByJuce (pluginViewRef)) + pluginViewRef = HIViewGetNextView (pluginViewRef); + + pluginWindowRef = 0; + + if (pluginViewRef == 0) + { + WindowGroupRef ourGroup = GetWindowGroup ((WindowRef) getWindowHandle()); + //DebugPrintWindowGroup (ourGroup); + //DebugPrintAllWindowGroups(); + + GetIndexedWindow (ourGroup, 1, + kWindowGroupContentsVisible, + &pluginWindowRef); + + if (pluginWindowRef == (WindowRef) getWindowHandle() + || juce_isWindowCreatedByJuce (pluginWindowRef)) + pluginWindowRef = 0; + } + + int w = 250, h = 150; + + if (rect != 0) + { + w = rect->right - rect->left; + h = rect->bottom - rect->top; + + if (w == 0 || h == 0) + { + w = 250; + h = 150; + } + } +#endif + + // double-check it's not too tiny + w = jmax (w, 32); + h = jmax (h, 32); + + setSize (w, h); + +#if JUCE_WIN32 + checkPluginWindowSize(); +#endif + + startTimer (18 + juce::Random::getSystemRandom().nextInt (5)); + repaint(); + } + + //============================================================================== + void closePluginWindow() + { + if (isOpen) + { + log (T("Closing VST UI: ") + plugin.getName()); + isOpen = false; + + dispatch (effEditClose, 0, 0, 0, 0); + +#if JUCE_WIN32 + #pragma warning (push) + #pragma warning (disable: 4244) + + if (pluginHWND != 0 && IsWindow (pluginHWND)) + SetWindowLongPtr (pluginHWND, GWL_WNDPROC, (LONG_PTR) originalWndProc); + + #pragma warning (pop) + + stopTimer(); + + if (pluginHWND != 0 && IsWindow (pluginHWND)) + DestroyWindow (pluginHWND); + + pluginHWND = 0; +#else + dispatch (effEditSleep, 0, 0, 0, 0); + pluginViewRef = 0; + stopTimer(); +#endif + } + } + + //============================================================================== +#if JUCE_WIN32 + void checkPluginWindowSize() throw() + { + RECT r; + GetWindowRect (pluginHWND, &r); + const int w = r.right - r.left; + const int h = r.bottom - r.top; + + if (isShowing() && w > 0 && h > 0 + && (w != getWidth() || h != getHeight()) + && ! pluginRefusesToResize) + { + setSize (w, h); + sizeCheckCount = 0; + } + } +#endif + + //============================================================================== + class CompMovementWatcher : public ComponentMovementWatcher + { + public: + CompMovementWatcher (VSTPluginWindow* const owner_) + : ComponentMovementWatcher (owner_), + owner (owner_) + { + } + + //============================================================================== + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) + { + owner->componentMovedOrResized(); + } + + void componentPeerChanged() + { + owner->componentPeerChanged(); + } + + void componentVisibilityChanged (Component&) + { + owner->componentVisibilityChanged(); + } + + private: + VSTPluginWindow* const owner; + }; + + CompMovementWatcher* movementWatcher; + + //============================================================================== + int dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) + { + return plugin.dispatch (opcode, index, value, ptr, opt); + } + + //============================================================================== + // hooks to get keyboard events from VST windows.. +#if JUCE_WIN32 + static LRESULT CALLBACK vstHookWndProc (HWND hW, UINT message, WPARAM wParam, LPARAM lParam) + { + for (int i = activeWindows.size(); --i >= 0;) + { + const VSTPluginWindow* const w = (const VSTPluginWindow*) activeWindows.getUnchecked (i); + + if (w->pluginHWND == hW) + { + if (message == WM_CHAR + || message == WM_KEYDOWN + || message == WM_SYSKEYDOWN + || message == WM_KEYUP + || message == WM_SYSKEYUP + || message == WM_APPCOMMAND) + { + SendMessage ((HWND) w->getTopLevelComponent()->getWindowHandle(), + message, wParam, lParam); + } + + return CallWindowProc ((WNDPROC) (w->originalWndProc), + (HWND) w->pluginHWND, + message, + wParam, + lParam); + } + } + + return DefWindowProc (hW, message, wParam, lParam); + } +#endif +}; + +//============================================================================== +AudioFilterEditor* JUCE_CALLTYPE VSTPluginInstance::createEditor() +{ + return new VSTPluginWindow (*this); +} + + +//============================================================================== +void VSTPluginInstance::handleAsyncUpdate() +{ + // called asynchronously to indicate that the plugin's parameters have changed.. +} + +//============================================================================== +bool VSTPluginInstance::restoreProgramSettings (const fxProgram* const prog) +{ + if (swap (prog->chunkMagic) == 'CcnK' && swap (prog->fxMagic) == 'FxCk') + { + changeProgramName (getCurrentProgram(), prog->prgName); + + for (int i = 0; i < swap (prog->numParams); ++i) + setParameter (i, swapFloat (prog->params[i])); + + return true; + } + + return false; +} + +bool VSTPluginInstance::loadFromFXBFile (const void* const data, + const int dataSize) +{ + if (dataSize < 28) + return false; + + const fxSet* const set = (const fxSet*) data; + + if ((swap (set->chunkMagic) != 'CcnK' && swap (set->chunkMagic) != 'KncC') + || swap (set->version) > fxbVersionNum) + return false; + + if (swap (set->fxMagic) == 'FxBk') + { + // bank of programs + if (swap (set->numPrograms) >= 0) + { + const int oldProg = getCurrentProgram(); + const int numParams = swap (((const fxProgram*) (set->programs))->numParams); + const int progLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); + + for (int i = 0; i < swap (set->numPrograms); ++i) + { + if (i != oldProg) + { + const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + i * progLen); + if (((const char*) prog) - ((const char*) set) >= dataSize) + return false; + + if (swap (set->numPrograms) > 0) + setCurrentProgram (i); + + if (! restoreProgramSettings (prog)) + return false; + } + } + + if (swap (set->numPrograms) > 0) + setCurrentProgram (oldProg); + + const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + oldProg * progLen); + if (((const char*) prog) - ((const char*) set) >= dataSize) + return false; + + if (! restoreProgramSettings (prog)) + return false; + } + } + else if (swap (set->fxMagic) == 'FxCk') + { + // single program + const fxProgram* const prog = (const fxProgram*) data; + + if (swap (prog->chunkMagic) != 'CcnK') + return false; + + changeProgramName (getCurrentProgram(), prog->prgName); + + for (int i = 0; i < swap (prog->numParams); ++i) + setParameter (i, swapFloat (prog->params[i])); + } + else if (swap (set->fxMagic) == 'FBCh' || swap (set->fxMagic) == 'hCBF') + { + // non-preset chunk + const fxChunkSet* const cset = (const fxChunkSet*) data; + + if (swap (cset->chunkSize) + sizeof (fxChunkSet) - 8 > (unsigned int) dataSize) + return false; + + setChunkData (cset->chunk, swap (cset->chunkSize), false); + } + else if (swap (set->fxMagic) == 'FPCh' || swap (set->fxMagic) == 'hCPF') + { + // preset chunk + const fxProgramSet* const cset = (const fxProgramSet*) data; + + if (swap (cset->chunkSize) + sizeof (fxProgramSet) - 8 > (unsigned int) dataSize) + return false; + + setChunkData (cset->chunk, swap (cset->chunkSize), true); + + changeProgramName (getCurrentProgram(), cset->name); + } + else + { + return false; + } + + return true; +} + +//============================================================================== +void VSTPluginInstance::setParamsInProgramBlock (fxProgram* const prog) throw() +{ + const int numParams = getNumParameters(); + + prog->chunkMagic = swap ('CcnK'); + prog->byteSize = 0; + prog->fxMagic = swap ('FxCk'); + prog->version = swap (fxbVersionNum); + prog->fxID = swap (getUID()); + prog->fxVersion = swap (getVersionNumber()); + prog->numParams = swap (numParams); + + getCurrentProgramName().copyToBuffer (prog->prgName, sizeof (prog->prgName) - 1); + + for (int i = 0; i < numParams; ++i) + prog->params[i] = swapFloat (getParameter (i)); +} + +bool VSTPluginInstance::saveToFXBFile (juce::MemoryBlock& dest, bool isFXB, int maxSizeMB) +{ + const int numPrograms = getNumPrograms(); + const int numParams = getNumParameters(); + + if (usesChunks()) + { + if (isFXB) + { + juce::MemoryBlock chunk; + getChunkData (chunk, false, maxSizeMB); + + const int totalLen = sizeof (fxChunkSet) + chunk.getSize() - 8; + dest.setSize (totalLen, true); + + fxChunkSet* const set = (fxChunkSet*) dest.getData(); + set->chunkMagic = swap ('CcnK'); + set->byteSize = 0; + set->fxMagic = swap ('FBCh'); + set->version = swap (fxbVersionNum); + set->fxID = swap (getUID()); + set->fxVersion = swap (getVersionNumber()); + set->numPrograms = swap (numPrograms); + set->chunkSize = swap (chunk.getSize()); + + chunk.copyTo (set->chunk, 0, chunk.getSize()); + } + else + { + juce::MemoryBlock chunk; + getChunkData (chunk, true, maxSizeMB); + + const int totalLen = sizeof (fxProgramSet) + chunk.getSize() - 8; + dest.setSize (totalLen, true); + + fxProgramSet* const set = (fxProgramSet*) dest.getData(); + set->chunkMagic = swap ('CcnK'); + set->byteSize = 0; + set->fxMagic = swap ('FPCh'); + set->version = swap (fxbVersionNum); + set->fxID = swap (getUID()); + set->fxVersion = swap (getVersionNumber()); + set->numPrograms = swap (numPrograms); + set->chunkSize = swap (chunk.getSize()); + + getCurrentProgramName().copyToBuffer (set->name, sizeof (set->name) - 1); + chunk.copyTo (set->chunk, 0, chunk.getSize()); + } + } + else + { + if (isFXB) + { + const int progLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); + const int len = (sizeof (fxSet) - sizeof (fxProgram)) + progLen * jmax (1, numPrograms); + dest.setSize (len, true); + + fxSet* const set = (fxSet*) dest.getData(); + set->chunkMagic = swap ('CcnK'); + set->byteSize = 0; + set->fxMagic = swap ('FxBk'); + set->version = swap (fxbVersionNum); + set->fxID = swap (getUID()); + set->fxVersion = swap (getVersionNumber()); + set->numPrograms = swap (numPrograms); + + const int oldProgram = getCurrentProgram(); + juce::MemoryBlock oldSettings; + createTempParameterStore (oldSettings); + + setParamsInProgramBlock ((fxProgram*) (((char*) (set->programs)) + oldProgram * progLen)); + + for (int i = 0; i < numPrograms; ++i) + { + if (i != oldProgram) + { + setCurrentProgram (i); + setParamsInProgramBlock ((fxProgram*) (((char*) (set->programs)) + i * progLen)); + } + } + + setCurrentProgram (oldProgram); + restoreFromTempParameterStore (oldSettings); + } + else + { + const int totalLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); + dest.setSize (totalLen, true); + + setParamsInProgramBlock ((fxProgram*) dest.getData()); + } + } + + return true; +} + +void VSTPluginInstance::getChunkData (juce::MemoryBlock& mb, bool isPreset, int maxSizeMB) const +{ + if (usesChunks()) + { + void* data = 0; + const int bytes = dispatch (effGetChunk, isPreset ? 1 : 0, 0, &data, 0.0f); + + if (data != 0 && bytes <= maxSizeMB * 1024 * 1024) + { + mb.setSize (bytes); + mb.copyFrom (data, 0, bytes); + } + } +} + +void VSTPluginInstance::setChunkData (const char* data, int size, bool isPreset) +{ + if (size > 0 && usesChunks()) + { + dispatch (effSetChunk, isPreset ? 1 : 0, size, (void*) data, 0.0f); + + if (! isPreset) + updateStoredProgramNames(); + } +} + +//============================================================================== +void VSTPluginInstance::timerCallback() +{ + if (dispatch (effIdle, 0, 0, 0, 0) == 0) + stopTimer(); +} + +int VSTPluginInstance::dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) const +{ + const ScopedLock sl (lock); + + ++insideVSTCallback; + int result = 0; + + try + { + if (effect != 0) + { +#if JUCE_MAC + if (module->resFileId != 0) + UseResFile (module->resFileId); + + CGrafPtr oldPort; + + if (getActiveEditor() != 0) + { + int x = 0, y = 0; + getActiveEditor()->relativePositionToOtherComponent (getActiveEditor()->getTopLevelComponent(), x, y); + + GetPort (&oldPort); + SetPortWindowPort ((WindowRef) getActiveEditor()->getWindowHandle()); + SetOrigin (-x, -y); + } +#endif + + result = effect->dispatcher (effect, opcode, index, value, ptr, opt); + +#if JUCE_MAC + if (getActiveEditor() != 0) + SetPort (oldPort); + + module->resFileId = CurResFile(); +#endif + + --insideVSTCallback; + return result; + } + } + catch (...) + { + //char s[512]; + //sprintf (s, "dispatcher (%d, %d, %d, %x, %f)", opcode, index, value, (int)ptr, opt); + } + + --insideVSTCallback; + return result; +} + +//============================================================================== +// handles non plugin-specific callbacks.. +static VstIntPtr handleGeneralCallback (VstInt32 opcode, VstInt32 index, VstInt32 value, void *ptr, float opt) +{ + (void) index; + (void) value; + (void) opt; + + switch (opcode) + { + case audioMasterCanDo: + { + static const char* canDos[] = { "supplyIdle", + "sendVstEvents", + "sendVstMidiEvent", + "sendVstTimeInfo", + "receiveVstEvents", + "receiveVstMidiEvent", + "supportShell", + "shellCategory" }; + + for (int i = 0; i < numElementsInArray (canDos); ++i) + if (strcmp (canDos[i], (const char*) ptr) == 0) + return 1; + + return 0; + } + + case audioMasterVersion: + return 0x2400; + case audioMasterCurrentId: + return shellUIDToCreate; + case audioMasterGetNumAutomatableParameters: + return 0; + case audioMasterGetAutomationState: + return 1; + + case audioMasterGetVendorVersion: + return 1; + case audioMasterGetVendorString: + case audioMasterGetProductString: + JUCEApplication::getInstance() + ->getApplicationName().copyToBuffer ((char*) ptr, jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1); + break; + + case audioMasterGetSampleRate: + return 44100; + + case audioMasterGetBlockSize: + return 512; + + case audioMasterSetOutputSampleRate: + return 0; + + default: + DBG ("*** Unhandled VST Callback: " + String ((int) opcode)); + break; + } + + return 0; +} + +// handles callbacks for a specific plugin +VstIntPtr VSTPluginInstance::handleCallback (VstInt32 opcode, VstInt32 index, VstInt32 value, void *ptr, float opt) +{ + switch (opcode) + { + case audioMasterAutomate: + // index = param num, opt = value + break; + + case audioMasterProcessEvents: + handleMidiFromPlugin ((const VstEvents*) ptr); + break; + + case audioMasterGetTime: + #ifdef _MSC_VER + #pragma warning (push) + #pragma warning (disable: 4311) + #endif + + return (VstIntPtr) &vstHostTime; + + #ifdef _MSC_VER + #pragma warning (pop) + #endif + break; + + case audioMasterIdle: + Thread::sleep (1); + if (! isTimerRunning()) + startTimer (50); + +#if JUCE_MAC + if (getActiveEditor() != 0) + dispatch (effEditIdle, 0, 0, 0, 0); +#endif + break; + + case audioMasterUpdateDisplay: + triggerAsyncUpdate(); + break; + + case audioMasterTempoAt: + // returns (10000 * bpm) + break; + + case audioMasterNeedIdle: + startTimer (50); + break; + + case audioMasterSizeWindow: + if (getActiveEditor() != 0) + getActiveEditor()->setSize (index, value); + + return 1; + + case audioMasterGetSampleRate: + return (VstIntPtr) sampleRate; + + case audioMasterGetBlockSize: + return (VstIntPtr) blockSize; + + case audioMasterWantMidi: + wantsMidiMessages = true; + break; + + case audioMasterGetDirectory: + #if JUCE_MAC + return (VstIntPtr) (void*) &module->parentDirFSSpec; + #else + return (VstIntPtr) (pointer_sized_uint) (const char*) module->fullParentDirectoryPathName; + #endif + + case audioMasterGetAutomationState: + // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write + break; + + // none of these are handled (yet).. + case audioMasterBeginEdit: + case audioMasterEndEdit: + case audioMasterSetTime: + case audioMasterPinConnected: + case audioMasterGetParameterQuantization: + case audioMasterIOChanged: + case audioMasterGetInputLatency: + case audioMasterGetOutputLatency: + case audioMasterGetPreviousPlug: + case audioMasterGetNextPlug: + case audioMasterWillReplaceOrAccumulate: + case audioMasterGetCurrentProcessLevel: + case audioMasterOfflineStart: + case audioMasterOfflineRead: + case audioMasterOfflineWrite: + case audioMasterOfflineGetCurrentPass: + case audioMasterOfflineGetCurrentMetaPass: + case audioMasterVendorSpecific: + case audioMasterSetIcon: + case audioMasterGetLanguage: + case audioMasterOpenWindow: + case audioMasterCloseWindow: + break; + + default: + return handleGeneralCallback (opcode, index, value, ptr, opt); + } + + return 0; +} + +// entry point for all callbacks from the plugin +static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt) +{ + try + { + if (effect != 0 && effect->resvd2 != 0) + { + return ((VSTPluginInstance*)(effect->resvd2)) + ->handleCallback (opcode, index, value, ptr, opt); + } + + return handleGeneralCallback (opcode, index, value, ptr, opt); + } + catch (...) + { + return 0; + } +} + +//============================================================================== +const String VSTPluginInstance::getName() const +{ + return name; +} + +const String VSTPluginInstance::getManufacturer() const +{ + char buffer [kVstMaxVendorStrLen + 8]; + zerostruct (buffer); + dispatch (effGetVendorString, 0, 0, buffer, 0); + return buffer; +} + +const String VSTPluginInstance::getVersion() const +{ + int v = dispatch (effGetVendorVersion, 0, 0, 0, 0); + + String s; + + if (v != 0) + { + int versionBits[4]; + int n = 0; + + while (v != 0) + { + versionBits [n++] = (v & 0xff); + v >>= 8; + } + + s << 'V'; + + while (n > 0) + { + s << versionBits [--n]; + + if (n > 0) + s << '.'; + } + } + + return s; +} + +int VSTPluginInstance::getVersionNumber() const throw() +{ + return effect != 0 ? effect->version : 0; +} + +const String VSTPluginInstance::getFormatName() const +{ + return "VST"; +} + +const File VSTPluginInstance::getFile() const +{ + return module->file; +} + +int VSTPluginInstance::getUID() const +{ + int uid = effect != 0 ? effect->uniqueID : 0; + + if (uid == 0) + uid = getFile().hashCode(); + + return uid; +} + +const String VSTPluginInstance::getCategory() const +{ + const char* result = 0; + + switch (dispatch (effGetPlugCategory, 0, 0, 0, 0)) + { + case kPlugCategEffect: + result = "Effect"; + break; + + case kPlugCategSynth: + result = "Synth"; + break; + + case kPlugCategAnalysis: + result = "Anaylsis"; + break; + + case kPlugCategMastering: + result = "Mastering"; + break; + + case kPlugCategSpacializer: + result = "Spacial"; + break; + + case kPlugCategRoomFx: + result = "Reverb"; + break; + + case kPlugSurroundFx: + result = "Surround"; + break; + + case kPlugCategRestoration: + result = "Restoration"; + break; + + case kPlugCategGenerator: + result = "Tone generation"; + break; + + default: + break; + } + + return result; +} + +//============================================================================== +int JUCE_CALLTYPE VSTPluginInstance::getNumParameters() +{ + return effect != 0 ? effect->numParams : 0; +} + +float JUCE_CALLTYPE VSTPluginInstance::getParameter (int index) +{ + if (effect != 0 && index >= 0 && index < effect->numParams) + { + try + { + const ScopedLock sl (lock); + return effect->getParameter (effect, index); + } + catch (...) + { + } + } + + return 0.0f; +} + +void JUCE_CALLTYPE VSTPluginInstance::setParameter (int index, float newValue) +{ + if (effect != 0 && index >= 0 && index < effect->numParams) + { + try + { + const ScopedLock sl (lock); + + if (effect->getParameter (effect, index) != newValue) + effect->setParameter (effect, index, newValue); + } + catch (...) + { + } + } +} + +const String JUCE_CALLTYPE VSTPluginInstance::getParameterName (int index) +{ + if (effect != 0) + { + jassert (index >= 0 && index < effect->numParams); + + char nm [256]; + zerostruct (nm); + dispatch (effGetParamName, index, 0, nm, 0); + return String (nm).trim(); + } + + return String::empty; +} + +const String VSTPluginInstance::getParameterLabel (int index) const +{ + if (effect != 0) + { + jassert (index >= 0 && index < effect->numParams); + + char nm [256]; + zerostruct (nm); + dispatch (effGetParamLabel, index, 0, nm, 0); + return String (nm).trim(); + } + + return String::empty; +} + +const String JUCE_CALLTYPE VSTPluginInstance::getParameterText (int index) +{ + if (effect != 0) + { + jassert (index >= 0 && index < effect->numParams); + + char nm [256]; + zerostruct (nm); + dispatch (effGetParamDisplay, index, 0, nm, 0); + return String (nm).trim(); + } + + return String::empty; +} + +bool VSTPluginInstance::isParameterAutomatable (int index) const +{ + if (effect != 0) + { + jassert (index >= 0 && index < effect->numParams); + return dispatch (effCanBeAutomated, index, 0, 0, 0) != 0; + } + + return false; +} + +void VSTPluginInstance::createTempParameterStore (juce::MemoryBlock& dest) +{ + dest.setSize (64 + 4 * getNumParameters()); + dest.fillWith (0); + + getCurrentProgramName().copyToBuffer ((char*) dest.getData(), 63); + + float* const p = (float*) (((char*) dest.getData()) + 64); + for (int i = 0; i < getNumParameters(); ++i) + p[i] = getParameter(i); +} + +void VSTPluginInstance::restoreFromTempParameterStore (const juce::MemoryBlock& m) +{ + changeProgramName (getCurrentProgram(), (const char*) m); + + float* p = (float*) (((char*) m.getData()) + 64); + for (int i = 0; i < getNumParameters(); ++i) + setParameter (i, p[i]); +} + +//============================================================================== +int JUCE_CALLTYPE VSTPluginInstance::getNumPrograms() +{ + return effect != 0 ? effect->numPrograms : 0; +} + +int JUCE_CALLTYPE VSTPluginInstance::getCurrentProgram() +{ + return dispatch (effGetProgram, 0, 0, 0, 0); +} + +void JUCE_CALLTYPE VSTPluginInstance::setCurrentProgram (int newIndex) +{ + if (getNumPrograms() > 0 && newIndex != getCurrentProgram()) + dispatch (effSetProgram, 0, jlimit (0, getNumPrograms() - 1, newIndex), 0, 0); +} + +const String JUCE_CALLTYPE VSTPluginInstance::getProgramName (int index) +{ + if (index == getCurrentProgram()) + { + return getCurrentProgramName(); + } + else if (effect != 0) + { + char nm [256]; + zerostruct (nm); + + if (dispatch (effGetProgramNameIndexed, + jlimit (0, getNumPrograms(), index), + -1, nm, 0) != 0) + { + return String (nm).trim(); + } + } + + return programNames [index]; +} + +void JUCE_CALLTYPE VSTPluginInstance::changeProgramName (int index, const String& newName) +{ + if (index == getCurrentProgram()) + { + if (getNumPrograms() > 0 && newName != getCurrentProgramName()) + dispatch (effSetProgramName, 0, 0, (void*) (const char*) newName.substring (0, 24), 0.0f); + } + else + { + jassertfalse // xxx not implemented! + } +} + +void VSTPluginInstance::updateStoredProgramNames() +{ + if (effect != 0 && getNumPrograms() > 0) + { + char nm [256]; + zerostruct (nm); + + // only do this if the plugin can't use indexed names.. + if (dispatch (effGetProgramNameIndexed, 0, -1, nm, 0) == 0) + { + const int oldProgram = getCurrentProgram(); + juce::MemoryBlock oldSettings; + createTempParameterStore (oldSettings); + + for (int i = 0; i < getNumPrograms(); ++i) + { + setCurrentProgram (i); + getCurrentProgramName(); // (this updates the list) + } + + setCurrentProgram (oldProgram); + restoreFromTempParameterStore (oldSettings); + } + } +} + +const String VSTPluginInstance::getCurrentProgramName() +{ + if (effect != 0) + { + char nm [256]; + zerostruct (nm); + dispatch (effGetProgramName, 0, 0, nm, 0); + + const int index = getCurrentProgram(); + if (programNames[index].isEmpty()) + { + while (programNames.size() < index) + programNames.add (String::empty); + + programNames.set (index, String (nm).trim()); + } + + return String (nm).trim(); + } + + return String::empty; +} + +//============================================================================== +const String VSTPluginInstance::getInputChannelName (const int index) const +{ + if (index >= 0 && index < getNumInputChannels()) + { + VstPinProperties pinProps; + if (dispatch (effGetInputProperties, index, 0, &pinProps, 0.0f) != 0) + return String (pinProps.label, sizeof (pinProps.label)); + } + + return String::empty; +} + +bool VSTPluginInstance::isInputChannelStereoPair (int index) const +{ + if (index < 0 || index >= getNumInputChannels()) + return false; + + VstPinProperties pinProps; + if (dispatch (effGetInputProperties, index, 0, &pinProps, 0.0f) != 0) + return (pinProps.flags & kVstPinIsStereo) != 0; + + return true; +} + +const String VSTPluginInstance::getOutputChannelName (const int index) const +{ + if (index >= 0 && index < getNumOutputChannels()) + { + VstPinProperties pinProps; + if (dispatch (effGetOutputProperties, index, 0, &pinProps, 0.0f) != 0) + return String (pinProps.label, sizeof (pinProps.label)); + } + + return String::empty; +} + +bool VSTPluginInstance::isOutputChannelStereoPair (int index) const +{ + if (index < 0 || index >= getNumOutputChannels()) + return false; + + VstPinProperties pinProps; + if (dispatch (effGetOutputProperties, index, 0, &pinProps, 0.0f) != 0) + return (pinProps.flags & kVstPinIsStereo) != 0; + + return true; +} + +//============================================================================== +bool VSTPluginInstance::acceptsMidi() const +{ + return wantsMidiMessages; +} + +bool VSTPluginInstance::producesMidi() const +{ + return dispatch (effCanDo, 0, 0, (void*) "sendVstMidiEvent", 0) > 0; +} + +int VSTPluginInstance::getSamplesLatency() const +{ + return effect != 0 ? effect->initialDelay : 0; +} + +void VSTPluginInstance::setPower (const bool on) +{ + dispatch (effMainsChanged, 0, on ? 1 : 0, 0, 0); + isPowerOn = on; +} + +bool VSTPluginInstance::hasEditor() const throw() +{ + return effect != 0 && (effect->flags & effFlagsHasEditor) != 0; +} + +bool VSTPluginInstance::canMono() const throw() +{ + return effect != 0 && (effect->flags & effFlagsCanMono) != 0; +} + +bool VSTPluginInstance::canReplace() const throw() +{ + return effect != 0 && (effect->flags & effFlagsCanReplacing) != 0; +} + +bool VSTPluginInstance::isOffline() const throw() +{ + return dispatch (effCanDo, 0, 0, (void*) "offline", 0) > 0; +} + +bool VSTPluginInstance::isInstrument() const +{ + return effect != 0 && (effect->flags & effFlagsIsSynth) != 0; +} + +bool VSTPluginInstance::usesChunks() const throw() +{ + return effect != 0 && (effect->flags & effFlagsProgramChunks) != 0; +} + + +//============================================================================== +const int defaultMaxSizeMB = 64; + +void JUCE_CALLTYPE VSTPluginInstance::getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData) +{ + saveToFXBFile (destData, true, defaultMaxSizeMB); +} + +void JUCE_CALLTYPE VSTPluginInstance::getCurrentProgramStateInformation (JUCE_NAMESPACE::MemoryBlock& destData) +{ + saveToFXBFile (destData, false, defaultMaxSizeMB); +} + +void JUCE_CALLTYPE VSTPluginInstance::setStateInformation (const void* data, int sizeInBytes) +{ + loadFromFXBFile (data, sizeInBytes); +} + +void JUCE_CALLTYPE VSTPluginInstance::setCurrentProgramStateInformation (const void* data, int sizeInBytes) +{ + loadFromFXBFile (data, sizeInBytes); +} + +//============================================================================== +//============================================================================== +VSTPluginFormat::VSTPluginFormat() +{ +} + +VSTPluginFormat::~VSTPluginFormat() +{ +} + +void VSTPluginFormat::findAllTypesForFile (OwnedArray & results, + const File& file) +{ + if (! fileMightContainThisPluginType (file)) + return; + + PluginDescription desc; + desc.file = file; + desc.uid = 0; + + VSTPluginInstance* instance = dynamic_cast (createInstanceFromDescription (desc)); + + if (instance == 0) + return; + + try + { +#if JUCE_MAC + if (instance->module->resFileId != 0) + UseResFile (instance->module->resFileId); +#endif + + desc.fillInFromInstance (*instance); + + VstPlugCategory category = (VstPlugCategory) instance->dispatch (effGetPlugCategory, 0, 0, 0, 0); + + if (category != kPlugCategShell) + { + // Normal plugin... + results.add (new PluginDescription (desc)); + + ++insideVSTCallback; + instance->dispatch (effOpen, 0, 0, 0, 0); + --insideVSTCallback; + } + else + { + // It's a shell plugin, so iterate all the subtypes... + char shellEffectName [64]; + + for (;;) + { + zerostruct (shellEffectName); + const int uid = instance->dispatch (effShellGetNextPlugin, 0, 0, shellEffectName, 0); + + if (uid == 0) + { + break; + } + else + { + desc.uid = uid; + desc.name = shellEffectName; + + bool alreadyThere = false; + + for (int i = results.size(); --i >= 0;) + { + PluginDescription* const d = results.getUnchecked(i); + + if (d->isDuplicateOf (desc)) + { + alreadyThere = true; + break; + } + } + + if (! alreadyThere) + results.add (new PluginDescription (desc)); + } + } + } + } + catch (...) + { + // crashed while loading... + } + + deleteAndZero (instance); +} + +AudioPluginInstance* VSTPluginFormat::createInstanceFromDescription (const PluginDescription& desc) +{ + VSTPluginInstance* result = 0; + + if (fileMightContainThisPluginType (desc.file)) + { + const File previousWorkingDirectory (File::getCurrentWorkingDirectory()); + desc.file.getParentDirectory().setAsCurrentWorkingDirectory(); + + const ReferenceCountedObjectPtr module (ModuleHandle::findOrCreateModule (desc.file)); + + if (module != 0) + { + shellUIDToCreate = desc.uid; + + result = new VSTPluginInstance (module); + + if (result->effect != 0) + { + result->effect->resvd2 = (VstIntPtr) (pointer_sized_int) result; + result->initialise(); + } + else + { + deleteAndZero (result); + } + } + + previousWorkingDirectory.setAsCurrentWorkingDirectory(); + } + + return result; +} + +bool VSTPluginFormat::fileMightContainThisPluginType (const File& f) +{ +#if JUCE_MAC + if (f.isDirectory() && f.hasFileExtension (T(".vst"))) + return true; + +#if JUCE_PPC + FSRef fileRef; + if (PlatformUtilities::makeFSRefFromPath (&fileRef, f.getFullPathName())) + { + const short resFileId = FSOpenResFile (&fileRef, fsRdPerm); + + if (resFileId != -1) + { + const int numEffects = Count1Resources ('aEff'); + CloseResFile (resFileId); + + if (numEffects > 0) + return true; + } + } +#endif + + return false; +#else + return f.existsAsFile() + && f.hasFileExtension (T(".dll")); +#endif +} + +const FileSearchPath VSTPluginFormat::getDefaultLocationsToSearch() +{ +#if JUCE_MAC + return FileSearchPath ("~/Library/Audio/Plug-Ins/VST;/Library/Audio/Plug-Ins/VST"); +#else + const String programFiles (File::getSpecialLocation (File::globalApplicationsDirectory).getFullPathName()); + + return FileSearchPath (programFiles + "\\Steinberg\\VstPlugins"); +#endif +} diff --git a/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.h b/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.h new file mode 100644 index 0000000000..d2ff680c01 --- /dev/null +++ b/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.h @@ -0,0 +1,187 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_VSTFORMAT_JUCEHEADER__ +#define __JUCE_VSTFORMAT_JUCEHEADER__ + +#include "juce_VSTPluginFormat.h" + +#undef PRAGMA_ALIGN_SUPPORTED +#define VST_FORCE_DEPRECATED 0 + +#ifdef _MSC_VER + #pragma warning (push) + #pragma warning (disable: 4996) +#endif + +/* Obviously you're going to need the Steinberg vstsdk2.4 folder in + your include path. +*/ +#include "pluginterfaces/vst2.x/aeffectx.h" + +#ifdef _MSC_VER + #pragma warning (pop) +#endif + +class ModuleHandle; +struct fxProgram; + + +//============================================================================== +/** + An instance of a plugin, created by a VSTPluginType. + +*/ +class VSTPluginInstance : public AudioPluginInstance, + private Timer, + private AsyncUpdater +{ +public: + //============================================================================== + ~VSTPluginInstance(); + + //============================================================================== + // AudioPluginInstance methods: + + const String getName() const; + const String getManufacturer() const; + const String getVersion() const; + bool isInstrument() const; + const String getCategory() const; + const String getFormatName() const; + const File getFile() const; + int getUID() const; + bool acceptsMidi() const; + bool producesMidi() const; + int getSamplesLatency() const; + + //============================================================================== + // AudioFilterBase methods: + + void JUCE_CALLTYPE prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); + void JUCE_CALLTYPE releaseResources(); + void JUCE_CALLTYPE processBlock (const AudioSampleBuffer& input, + AudioSampleBuffer& output, + const bool accumulateOutput, + MidiBuffer& midiMessages); + + AudioFilterEditor* JUCE_CALLTYPE createEditor(); + + const String JUCE_CALLTYPE getInputChannelName (const int index) const; + bool JUCE_CALLTYPE isInputChannelStereoPair (int index) const; + + const String JUCE_CALLTYPE getOutputChannelName (const int index) const; + bool JUCE_CALLTYPE isOutputChannelStereoPair (int index) const; + + //============================================================================== + int JUCE_CALLTYPE getNumParameters(); + float JUCE_CALLTYPE getParameter (int index); + void JUCE_CALLTYPE setParameter (int index, float newValue); + const String JUCE_CALLTYPE getParameterName (int index); + const String JUCE_CALLTYPE getParameterText (int index); + bool isParameterAutomatable (int index) const; + + //============================================================================== + int JUCE_CALLTYPE getNumPrograms(); + int JUCE_CALLTYPE getCurrentProgram(); + void JUCE_CALLTYPE setCurrentProgram (int index); + const String JUCE_CALLTYPE getProgramName (int index); + void JUCE_CALLTYPE changeProgramName (int index, const String& newName); + + //============================================================================== + void JUCE_CALLTYPE getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData); + void JUCE_CALLTYPE getCurrentProgramStateInformation (JUCE_NAMESPACE::MemoryBlock& destData); + void JUCE_CALLTYPE setStateInformation (const void* data, int sizeInBytes); + void JUCE_CALLTYPE setCurrentProgramStateInformation (const void* data, int sizeInBytes); + + //============================================================================== + void timerCallback(); + void handleAsyncUpdate(); + VstIntPtr handleCallback (VstInt32 opcode, VstInt32 index, VstInt32 value, void *ptr, float opt); + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + friend class VSTPluginType; + friend class VSTPluginWindow; + friend class VSTPluginFormat; + + AEffect* effect; + String name; + CriticalSection lock; + bool wantsMidiMessages, initialised, isPowerOn; + mutable StringArray programNames; + MidiMessageCollector midiCollector; + AudioSampleBuffer tempBuffer; + CriticalSection midiInLock; + MidiBuffer incomingMidi; + void* midiEventsToSend; + int numAllocatedMidiEvents; + VstTimeInfo vstHostTime; + float** channelsIn; + float** channelsOut; + + ReferenceCountedObjectPtr module; + + //============================================================================== + int dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) const; + bool restoreProgramSettings (const fxProgram* const prog); + const String getCurrentProgramName(); + void setParamsInProgramBlock (fxProgram* const prog) throw(); + void updateStoredProgramNames(); + void initialise(); + void ensureMidiEventSize (int numEventsNeeded); + void freeMidiEvents(); + void handleMidiFromPlugin (const VstEvents* const events); + void createTempParameterStore (juce::MemoryBlock& dest); + void restoreFromTempParameterStore (const juce::MemoryBlock& mb); + const String getParameterLabel (int index) const; + + bool usesChunks() const throw(); + void getChunkData (juce::MemoryBlock& mb, bool isPreset, int maxSizeMB) const; + void setChunkData (const char* data, int size, bool isPreset); + bool loadFromFXBFile (const void* data, int numBytes); + bool saveToFXBFile (juce::MemoryBlock& dest, bool isFXB, int maxSizeMB); + + int getVersionNumber() const throw(); + bool hasEditor() const throw(); + bool canMono() const throw(); + bool canReplace() const throw(); + bool isOffline() const throw(); + void setPower (const bool on); + + VSTPluginInstance (const ReferenceCountedObjectPtr & module); +}; + + + +#endif // __JUCE_VSTFORMAT_JUCEHEADER__ diff --git a/extras/audio plugins/demo/build/VST_Linux/premake.lua b/extras/audio plugins/demo/build/VST_Linux/premake.lua new file mode 100644 index 0000000000..14406e8b8d --- /dev/null +++ b/extras/audio plugins/demo/build/VST_Linux/premake.lua @@ -0,0 +1,55 @@ + +project.name = "JucePluginDemo" +project.bindir = "build" +project.libdir = "build" + +project.configs = { "Debug", "Release" } + +package = newpackage() +package.name = "JucePluginDemo" +package.kind = "dll" +package.language = "c++" + +package.objdir = "build/intermediate" +package.config["Debug"].objdir = "build/intermediate/Debug" +package.config["Release"].objdir = "build/intermediate/Release" + +package.config["Debug"].defines = { "LINUX=1", "DEBUG=1", "_DEBUG=1" } +package.config["Debug"].buildoptions = { "-O0 -ggdb -g3 -Wall" } + +package.config["Release"].defines = { "LINUX=1", "NDEBUG=1" } +package.config["Release"].buildoptions = { "-O2 -s" } + +package.includepaths = { + "/usr/include", + "../../../../../", + "/usr/include/vst/source/common", + "/usr/include/vst", + "../../src" +} + +package.libpaths = { + "../../../../../bin", + "/usr/X11R6/lib/", + "/usr/lib" +} + +package.config["Debug"].links = { + "freetype", "pthread", "rt", "X11", "GL", "GLU", "Xinerama", "asound", "juce_debug" +} + +package.config["Release"].links = { + "freetype", "pthread", "rt", "X11", "GL", "GLU", "Xinerama", "asound", "juce" +} + +package.files = { + matchfiles ( + "../../../wrapper/*.h", + "../../../wrapper/*.cpp", + "../../../wrapper/formats/VST/*.cpp" + ), + matchrecursive ( + "../../src/*.h", + "../../src/*.cpp" + ) +} diff --git a/extras/audio plugins/wrapper/formats/RTAS/juce_RTASWrapper.cpp b/extras/audio plugins/wrapper/formats/RTAS/juce_RTASWrapper.cpp index e0dac20a95..19ab3b961d 100644 --- a/extras/audio plugins/wrapper/formats/RTAS/juce_RTASWrapper.cpp +++ b/extras/audio plugins/wrapper/formats/RTAS/juce_RTASWrapper.cpp @@ -811,6 +811,9 @@ protected: void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue) { + if (juceFilter != 0) + juceFilter->setParameter (index, newValue); + SetControlValue (index + 2, floatToLong (newValue)); } diff --git a/extras/audio plugins/wrapper/formats/VST/juce_VstWrapper.cpp b/extras/audio plugins/wrapper/formats/VST/juce_VstWrapper.cpp index 301b387d04..9e3267bc36 100644 --- a/extras/audio plugins/wrapper/formats/VST/juce_VstWrapper.cpp +++ b/extras/audio plugins/wrapper/formats/VST/juce_VstWrapper.cpp @@ -1,1316 +1,1312 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-7 by Raw Material Software ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the - GNU General Public License, as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later version. - - JUCE is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with JUCE; if not, visit www.gnu.org/licenses or write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - ------------------------------------------------------------------------------ - - If you'd like to release a closed-source product which uses JUCE, commercial - licenses are also available: visit www.rawmaterialsoftware.com/juce for - more information. - - ============================================================================== -*/ - -/* - *** DON't EDIT THIS FILE!! *** - - The idea is that everyone's plugins should share this same wrapper - code, so if you start hacking around in here you're missing the point! - - If there's a bug or a function you need that can't be done without changing - some of the code in here, give me a shout so we can add it to the library, - rather than branching off and going it alone! -*/ - - -//============================================================================== -#ifdef _MSC_VER - #pragma warning (disable : 4996) -#endif - -#ifdef _WIN32 - #include -#elif defined (LINUX) - #include - #include - #include - #undef KeyPress -#else - #include -#endif - -#ifdef PRAGMA_ALIGN_SUPPORTED - #undef PRAGMA_ALIGN_SUPPORTED - #define PRAGMA_ALIGN_SUPPORTED 1 -#endif - -#include "../../juce_IncludeCharacteristics.h" - -//============================================================================== -/* These files come with the Steinberg VST SDK - to get them, you'll need to - visit the Steinberg website and jump through some hoops to sign up as a - VST developer. - - Then, you'll need to make sure your include path contains your "vstsdk2.3" or - "vstsdk2.4" directory. - - Note that the JUCE_USE_VSTSDK_2_4 macro should be defined in JucePluginCharacteristics.h -*/ -#if JUCE_USE_VSTSDK_2_4 - // VSTSDK V2.4 includes.. - #include "public.sdk/source/vst2.x/audioeffectx.h" - #include "public.sdk/source/vst2.x/aeffeditor.h" - #include "public.sdk/source/vst2.x/audioeffectx.cpp" - #include "public.sdk/source/vst2.x/audioeffect.cpp" -#else - // VSTSDK V2.3 includes.. - #include "source/common/audioeffectx.h" - #include "source/common/AEffEditor.hpp" - #include "source/common/audioeffectx.cpp" - #include "source/common/AudioEffect.cpp" - typedef long VstInt32; - typedef long VstIntPtr; -#endif - -//============================================================================== -#include "../../juce_AudioFilterBase.h" -#undef MemoryBlock - -class JuceVSTWrapper; -static bool recursionCheck = false; -static uint32 lastMasterIdleCall = 0; - -BEGIN_JUCE_NAMESPACE - extern void juce_callAnyTimersSynchronously(); - - #if JUCE_MAC - extern void juce_macDoPendingRepaintsNow(); - #elif JUCE_LINUX - extern Display* display; - extern bool juce_postMessageToSystemQueue (void* message); - #endif -END_JUCE_NAMESPACE - - -//============================================================================== -#if JUCE_WIN32 - -static HWND findMDIParentOf (HWND w) -{ - const int frameThickness = GetSystemMetrics (SM_CYFIXEDFRAME); - - while (w != 0) - { - HWND parent = GetParent (w); - - if (parent == 0) - break; - - TCHAR windowType [32]; - zeromem (windowType, sizeof (windowType)); - GetClassName (parent, windowType, 31); - - if (String (windowType).equalsIgnoreCase (T("MDIClient"))) - { - w = parent; - break; - } - - RECT windowPos; - GetWindowRect (w, &windowPos); - - RECT parentPos; - GetWindowRect (parent, &parentPos); - - int dw = (parentPos.right - parentPos.left) - (windowPos.right - windowPos.left); - int dh = (parentPos.bottom - parentPos.top) - (windowPos.bottom - windowPos.top); - - if (dw > 100 || dh > 100) - break; - - w = parent; - - if (dw == 2 * frameThickness) - break; - } - - return w; -} - -//============================================================================== -#elif JUCE_LINUX - -class SharedMessageThread : public Thread -{ -public: - SharedMessageThread() - : Thread (T("VstMessageThread")) - { - startThread (7); - } - - ~SharedMessageThread() - { - signalThreadShouldExit(); - - const int quitMessageId = 0xfffff321; - Message* const m = new Message (quitMessageId, 1, 0, 0); - - if (! juce_postMessageToSystemQueue (m)) - delete m; - - clearSingletonInstance(); - } - - void run() - { - MessageManager* const messageManager = MessageManager::getInstance(); - - const int originalThreadId = messageManager->getCurrentMessageThread(); - messageManager->setCurrentMessageThread (getThreadId()); - - while (! threadShouldExit() - && messageManager->dispatchNextMessage()) - { - } - - messageManager->setCurrentMessageThread (originalThreadId); - } - - juce_DeclareSingleton (SharedMessageThread, false) -}; - -juce_ImplementSingleton (SharedMessageThread); - -#endif - -//============================================================================== -// A component to hold the AudioFilterEditor, and cope with some housekeeping -// chores when it changes or repaints. -class EditorCompWrapper : public Component, - public AsyncUpdater -{ - JuceVSTWrapper* wrapper; - -public: - EditorCompWrapper (JuceVSTWrapper* const wrapper_, - AudioFilterEditor* const editor) - : wrapper (wrapper_) - { - setOpaque (true); - editor->setOpaque (true); - - setBounds (editor->getBounds()); - editor->setTopLeftPosition (0, 0); - addAndMakeVisible (editor); - -#if JUCE_WIN32 - addMouseListener (this, true); -#endif - } - - ~EditorCompWrapper() - { - deleteAllChildren(); - } - - void paint (Graphics& g) - { - } - - void paintOverChildren (Graphics& g) - { - // this causes an async call to masterIdle() to help - // creaky old DAWs like Nuendo repaint themselves while we're - // repainting. Otherwise they just seem to give up and sit there - // waiting. - triggerAsyncUpdate(); - } - - AudioFilterEditor* getEditorComp() const - { - return dynamic_cast (getChildComponent (0)); - } - - void resized() - { - Component* const c = getChildComponent (0); - - if (c != 0) - { -#if JUCE_LINUX - const MessageManagerLock mml; -#endif - c->setBounds (0, 0, getWidth(), getHeight()); - } - } - - void childBoundsChanged (Component* child); - void handleAsyncUpdate(); - -#if JUCE_WIN32 - void mouseDown (const MouseEvent&) - { - broughtToFront(); - } - - void broughtToFront() - { - // for hosts like nuendo, need to also pop the MDI container to the - // front when our comp is clicked on. - HWND parent = findMDIParentOf ((HWND) getWindowHandle()); - - if (parent != 0) - { - SetWindowPos (parent, - HWND_TOP, - 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE); - } - } -#endif - - //============================================================================== - juce_UseDebuggingNewOperator -}; - -static VoidArray activePlugins; - - -//============================================================================== -/** - This wraps an AudioFilterBase as an AudioEffectX... -*/ -class JuceVSTWrapper : public AudioEffectX, - private Timer, - public AudioFilterBase::FilterNativeCallbacks -{ -public: - //============================================================================== - JuceVSTWrapper (audioMasterCallback audioMaster, - AudioFilterBase* const filter_) - : AudioEffectX (audioMaster, - filter_->getNumPrograms(), - filter_->getNumParameters()), - filter (filter_) - { - filter->numInputChannels = JucePlugin_MaxNumInputChannels; - filter->numOutputChannels = JucePlugin_MaxNumOutputChannels; - - filter_->initialiseInternal (this); - - editorComp = 0; - outgoingEvents = 0; - outgoingEventSize = 0; - chunkMemoryTime = 0; - isProcessing = false; - firstResize = true; - -#if JUCE_MAC || JUCE_LINUX - hostWindow = 0; -#endif - - cEffect.flags |= effFlagsHasEditor; - - setUniqueID ((int) (JucePlugin_VSTUniqueID)); - getAeffect()->version = (long) (JucePlugin_VersionCode); - -#if JucePlugin_WantsMidiInput && ! JUCE_USE_VSTSDK_2_4 - wantEvents(); -#endif - - setNumInputs (filter->numInputChannels); - setNumOutputs (filter->numOutputChannels); - - canProcessReplacing (true); - -#if ! JUCE_USE_VSTSDK_2_4 - hasVu (false); - hasClip (false); -#endif - - isSynth ((JucePlugin_IsSynth) != 0); - noTail ((JucePlugin_SilenceInProducesSilenceOut) != 0); - setInitialDelay (JucePlugin_Latency); - programsAreChunks (true); - - VstPinProperties props; - - int i; - for (i = 0; i < filter->numInputChannels; ++i) - { - String s (i + 1); - - if (getInputProperties (i, &props)) - { - s = props.label; - - if (s.isEmpty()) - { - if ((props.flags & kVstPinIsStereo) != 0) - s = ((i & 1) == 0) ? T("left") : T("right"); - else - s = String (i + 1); - } - } - - filter->inputNames.add (s); - } - - for (i = 0; i < filter->numOutputChannels; ++i) - { - String s (i + 1); - - if (getOutputProperties (i, &props)) - { - s = props.label; - - if (s.isEmpty()) - { - if ((props.flags & kVstPinIsStereo) != 0) - s = ((i & 1) == 0) ? T("left") : T("right"); - else - s = String (i + 1); - } - } - - filter->outputNames.add (s); - } - - activePlugins.add (this); - } - - ~JuceVSTWrapper() - { - stopTimer(); - deleteEditor(); - - delete filter; - filter = 0; - - if (outgoingEvents != 0) - { - for (int i = outgoingEventSize; --i >= 0;) - juce_free (outgoingEvents->events[i]); - - juce_free (outgoingEvents); - outgoingEvents = 0; - } - - jassert (editorComp == 0); - - jassert (activePlugins.contains (this)); - activePlugins.removeValue (this); - -#if JUCE_MAC || JUCE_LINUX - if (activePlugins.size() == 0) - { -#if JUCE_LINUX - SharedMessageThread::deleteInstance(); -#endif - shutdownJuce_GUI(); - } -#endif - } - - void open() - { - startTimer (1000 / 4); - } - - void close() - { - jassert (! recursionCheck); - - stopTimer(); - deleteEditor(); - } - - //============================================================================== - bool getEffectName (char* name) - { - String (JucePlugin_Name).copyToBuffer (name, 64); - return true; - } - - bool getVendorString (char* text) - { - String (JucePlugin_Manufacturer).copyToBuffer (text, 64); - return true; - } - - bool getProductString (char* text) - { - return getEffectName (text); - } - - VstInt32 getVendorVersion() - { - return JucePlugin_VersionCode; - } - - VstPlugCategory getPlugCategory() - { - return JucePlugin_VSTCategory; - } - - VstInt32 canDo (char* text) - { - VstInt32 result = 0; - - if (strcmp (text, "receiveVstEvents") == 0 - || strcmp (text, "receiveVstMidiEvent") == 0 - || strcmp (text, "receiveVstMidiEvents") == 0) - { -#if JucePlugin_WantsMidiInput - result = 1; -#else - result = -1; -#endif - } - else if (strcmp (text, "sendVstEvents") == 0 - || strcmp (text, "sendVstMidiEvent") == 0 - || strcmp (text, "sendVstMidiEvents") == 0) - { -#if JucePlugin_ProducesMidiOutput - result = 1; -#else - result = -1; -#endif - } - else if (strcmp (text, "receiveVstTimeInfo") == 0) - { - result = 1; - } - else if (strcmp (text, "conformsToWindowRules") == 0) - { - result = 1; - } - - return result; - } - - bool keysRequired() - { - return (JucePlugin_EditorRequiresKeyboardFocus) != 0; - } - - //============================================================================== - VstInt32 processEvents (VstEvents* events) - { -#if JucePlugin_WantsMidiInput - for (int i = 0; i < events->numEvents; ++i) - { - const VstEvent* const e = events->events[i]; - - if (e != 0 && e->type == kVstMidiType) - { - const VstMidiEvent* const vme = (const VstMidiEvent*) e; - - midiEvents.addEvent ((const uint8*) vme->midiData, - 4, - vme->deltaFrames); - } - } - - return 1; -#else - return 0; -#endif - } - - void process (float** inputs, float** outputs, - const VstInt32 numSamples, const bool accumulate) - { - // if this fails, the host hasn't called resume() before processing - jassert (isProcessing); - - // (tragically, some hosts actually need this, although it's stupid to have - // to do it here..) - if (! isProcessing) - resume(); - -#if JUCE_DEBUG && ! JucePlugin_ProducesMidiOutput - const int numMidiEventsComingIn = midiEvents.getNumEvents(); -#endif - - jassert (activePlugins.contains (this)); - - { - const AudioSampleBuffer input (inputs, filter->numInputChannels, numSamples); - AudioSampleBuffer output (outputs, filter->numOutputChannels, numSamples); - - const ScopedLock sl (filter->getCallbackLock()); - - if (filter->suspended) - { - if (! accumulate) - output.clear(); - } - else - { - filter->processBlock (input, output, accumulate, midiEvents); - } - } - - if (! midiEvents.isEmpty()) - { -#if JucePlugin_ProducesMidiOutput - const int numEvents = midiEvents.getNumEvents(); - - ensureOutgoingEventSize (numEvents); - outgoingEvents->numEvents = 0; - - const uint8* midiEventData; - int midiEventSize, midiEventPosition; - MidiBuffer::Iterator i (midiEvents); - - while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition)) - { - if (midiEventSize <= 4) - { - VstMidiEvent* const vme = (VstMidiEvent*) outgoingEvents->events [outgoingEvents->numEvents++]; - - memcpy (vme->midiData, midiEventData, midiEventSize); - vme->deltaFrames = midiEventPosition; - - jassert (vme->deltaFrames >= 0 && vme->deltaFrames < numSamples); - } - } - - sendVstEventsToHost (outgoingEvents); -#else - /* This assertion is caused when you've added some events to the - midiMessages array in your processBlock() method, which usually means - that you're trying to send them somewhere. But in this case they're - getting thrown away. - - If your plugin does want to send midi messages, you'll need to set - the JucePlugin_ProducesMidiOutput macro to 1 in your - JucePluginCharacteristics.h file. - - If you don't want to produce any midi output, then you should clear the - midiMessages array at the end of your processBlock() method, to - indicate that you don't want any of the events to be passed through - to the output. - */ - jassert (midiEvents.getNumEvents() <= numMidiEventsComingIn); -#endif - - midiEvents.clear(); - } - } - - void process (float** inputs, float** outputs, VstInt32 numSamples) - { - process (inputs, outputs, numSamples, true); - } - - void processReplacing (float** inputs, float** outputs, VstInt32 numSamples) - { - process (inputs, outputs, numSamples, false); - } - - //============================================================================== - void resume() - { - isProcessing = true; - - filter->sampleRate = getSampleRate(); - - jassert (filter->sampleRate > 0); - if (filter->sampleRate <= 0) - filter->sampleRate = 44100.0; - - filter->blockSize = getBlockSize(); - jassert (filter->blockSize > 0); - - filter->prepareToPlay (filter->sampleRate, filter->blockSize); - midiEvents.clear(); - - AudioEffectX::resume(); - -#if JucePlugin_ProducesMidiOutput - ensureOutgoingEventSize (64); -#endif - -#if JucePlugin_WantsMidiInput && ! JUCE_USE_VSTSDK_2_4 - wantEvents(); -#endif - } - - void suspend() - { - AudioEffectX::suspend(); - - filter->releaseResources(); - midiEvents.clear(); - - isProcessing = false; - } - - bool JUCE_CALLTYPE getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info) - { - const VstTimeInfo* const ti = getTimeInfo (kVstPpqPosValid - | kVstTempoValid - | kVstBarsValid - //| kVstCyclePosValid - | kVstTimeSigValid - | kVstSmpteValid - | kVstClockValid); - - if (ti == 0 || ti->sampleRate <= 0) - return false; - - if ((ti->flags & kVstTempoValid) != 0) - info.bpm = ti->tempo; - else - info.bpm = 0.0; - - if ((ti->flags & kVstTimeSigValid) != 0) - { - info.timeSigNumerator = ti->timeSigNumerator; - info.timeSigDenominator = ti->timeSigDenominator; - } - else - { - info.timeSigNumerator = 4; - info.timeSigDenominator = 4; - } - - info.timeInSeconds = ti->samplePos / ti->sampleRate; - - if ((ti->flags & kVstPpqPosValid) != 0) - info.ppqPosition = ti->ppqPos; - else - info.ppqPosition = 0.0; - - if ((ti->flags & kVstBarsValid) != 0) - info.ppqPositionOfLastBarStart = ti->barStartPos; - else - info.ppqPositionOfLastBarStart = 0.0; - - if ((ti->flags & kVstSmpteValid) != 0) - { - info.frameRate = (AudioFilterBase::CurrentPositionInfo::FrameRateType) (int) ti->smpteFrameRate; - - const double fpsDivisors[] = { 24.0, 25.0, 30.0, 30.0, 30.0, 30.0, 1.0 }; - info.editOriginTime = (ti->smpteOffset / (80.0 * fpsDivisors [(int) info.frameRate])); - } - else - { - info.frameRate = AudioFilterBase::CurrentPositionInfo::fpsUnknown; - info.editOriginTime = 0; - } - - info.isRecording = (ti->flags & kVstTransportRecording) != 0; - info.isPlaying = (ti->flags & kVstTransportPlaying) != 0 || info.isRecording; - - return true; - } - - //============================================================================== - VstInt32 getProgram() - { - return filter->getCurrentProgram(); - } - - void setProgram (VstInt32 program) - { - filter->setCurrentProgram (program); - } - - void setProgramName (char* name) - { - filter->changeProgramName (filter->getCurrentProgram(), name); - } - - void getProgramName (char* name) - { - filter->getProgramName (filter->getCurrentProgram()).copyToBuffer (name, 24); - } - - bool getProgramNameIndexed (VstInt32 category, VstInt32 index, char* text) - { - if (index >= 0 && index < filter->getNumPrograms()) - { - filter->getProgramName (index).copyToBuffer (text, 24); - return true; - } - - return false; - } - - //============================================================================== - float getParameter (VstInt32 index) - { - jassert (index >= 0 && index < filter->getNumParameters()); - return filter->getParameter (index); - } - - void setParameter (VstInt32 index, float value) - { - jassert (index >= 0 && index < filter->getNumParameters()); - filter->setParameter (index, value); - } - - void getParameterDisplay (VstInt32 index, char* text) - { - jassert (index >= 0 && index < filter->getNumParameters()); - filter->getParameterText (index).copyToBuffer (text, 64); - } - - void getParameterName (VstInt32 index, char* text) - { - jassert (index >= 0 && index < filter->getNumParameters()); - filter->getParameterName (index).copyToBuffer (text, 8); - } - - void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue) - { - setParameterAutomated (index, newValue); - } - - //============================================================================== - VstInt32 getChunk (void** data, bool onlyStoreCurrentProgramData) - { - chunkMemory.setSize (0); - if (onlyStoreCurrentProgramData) - filter->getCurrentProgramStateInformation (chunkMemory); - else - filter->getStateInformation (chunkMemory); - - *data = (void*) chunkMemory; - - // because the chunk is only needed temporarily by the host (or at least you'd - // hope so) we'll give it a while and then free it in the timer callback. - chunkMemoryTime = JUCE_NAMESPACE::Time::getApproximateMillisecondCounter(); - - return chunkMemory.getSize(); - } - - VstInt32 setChunk (void* data, VstInt32 byteSize, bool onlyRestoreCurrentProgramData) - { - chunkMemory.setSize (0); - chunkMemoryTime = 0; - - if (byteSize > 0 && data != 0) - { - if (onlyRestoreCurrentProgramData) - filter->setCurrentProgramStateInformation (data, byteSize); - else - filter->setStateInformation (data, byteSize); - } - - return 0; - } - - void timerCallback() - { - if (chunkMemoryTime > 0 - && chunkMemoryTime < JUCE_NAMESPACE::Time::getApproximateMillisecondCounter() - 2000 - && ! recursionCheck) - { - chunkMemoryTime = 0; - chunkMemory.setSize (0); - } - - tryMasterIdle(); - } - - void tryMasterIdle() - { - if (Component::isMouseButtonDownAnywhere() - && ! recursionCheck) - { - const uint32 now = JUCE_NAMESPACE::Time::getMillisecondCounter(); - - if (now > lastMasterIdleCall + 20 && editorComp != 0) - { - lastMasterIdleCall = now; - - recursionCheck = true; - masterIdle(); - recursionCheck = false; - } - } - } - - void doIdleCallback() - { - // (wavelab calls this on a separate thread and causes a deadlock).. - if (MessageManager::getInstance()->isThisTheMessageThread()) - { - if (! recursionCheck) - { - const MessageManagerLock mml; - - recursionCheck = true; - - juce_callAnyTimersSynchronously(); - - for (int i = ComponentPeer::getNumPeers(); --i >= 0;) - ComponentPeer::getPeer (i)->performAnyPendingRepaintsNow(); - - recursionCheck = false; - } - } - } - - void createEditorComp() - { - if (editorComp == 0) - { -#if JUCE_LINUX - const MessageManagerLock mml; -#endif - - AudioFilterEditor* const ed = filter->createEditorIfNeeded(); - - if (ed != 0) - { - ed->setOpaque (true); - ed->setVisible (true); - - editorComp = new EditorCompWrapper (this, ed); - } - } - } - - void deleteEditor() - { - PopupMenu::dismissAllActiveMenus(); - - jassert (! recursionCheck); - recursionCheck = true; - -#if JUCE_LINUX - const MessageManagerLock mml; -#endif - - if (editorComp != 0) - { - Component* const modalComponent = Component::getCurrentlyModalComponent(); - if (modalComponent != 0) - modalComponent->exitModalState (0); - - filter->editorBeingDeleted (editorComp->getEditorComp()); - - deleteAndZero (editorComp); - - // there's some kind of component currently modal, but the host - // is trying to delete our plugin. You should try to avoid this happening.. - jassert (Component::getCurrentlyModalComponent() == 0); - } - -#if JUCE_MAC || JUCE_LINUX - hostWindow = 0; -#endif - - recursionCheck = false; - } - - VstIntPtr dispatcher (VstInt32 opCode, VstInt32 index, VstIntPtr value, void* ptr, float opt) - { - if (opCode == effEditIdle) - { - doIdleCallback(); - return 0; - } - else if (opCode == effEditOpen) - { - jassert (! recursionCheck); - - deleteEditor(); - createEditorComp(); - - if (editorComp != 0) - { -#if JUCE_LINUX - const MessageManagerLock mml; -#endif - - editorComp->setOpaque (true); - editorComp->setVisible (false); - -#if JUCE_WIN32 - editorComp->addToDesktop (0); - - hostWindow = (HWND) ptr; - HWND editorWnd = (HWND) editorComp->getWindowHandle(); - - SetParent (editorWnd, hostWindow); - - DWORD val = GetWindowLong (editorWnd, GWL_STYLE); - val = (val & ~WS_POPUP) | WS_CHILD; - SetWindowLong (editorWnd, GWL_STYLE, val); - - editorComp->setVisible (true); -#elif JUCE_LINUX - editorComp->addToDesktop (0); - - hostWindow = (Window) ptr; - - Window editorWnd = (Window) editorComp->getWindowHandle(); - - XReparentWindow (display, editorWnd, hostWindow, 0, 0); - - editorComp->setVisible (true); -#else - hostWindow = (WindowRef) ptr; - firstResize = true; - - SetAutomaticControlDragTrackingEnabledForWindow (hostWindow, true); - - WindowAttributes attributes; - GetWindowAttributes (hostWindow, &attributes); - - HIViewRef parentView = 0; - - if ((attributes & kWindowCompositingAttribute) != 0) - { - HIViewRef root = HIViewGetRoot (hostWindow); - HIViewFindByID (root, kHIViewWindowContentID, &parentView); - - if (parentView == 0) - parentView = root; - } - else - { - GetRootControl (hostWindow, (ControlRef*) &parentView); - - if (parentView == 0) - CreateRootControl (hostWindow, (ControlRef*) &parentView); - } - - jassert (parentView != 0); // agh - the host has to provide a compositing window.. - - editorComp->setVisible (true); - editorComp->addToDesktop (0, (void*) parentView); -#endif - - return 1; - } - } - else if (opCode == effEditClose) - { - deleteEditor(); - return 0; - } - else if (opCode == effEditGetRect) - { - createEditorComp(); - - if (editorComp != 0) - { - editorSize.left = 0; - editorSize.top = 0; - editorSize.right = editorComp->getWidth(); - editorSize.bottom = editorComp->getHeight(); - - *((ERect**) ptr) = &editorSize; - - return (VstIntPtr) &editorSize; - } - else - { - return 0; - } - } - - return AudioEffectX::dispatcher (opCode, index, value, ptr, opt); - } - - void resizeHostWindow (int newWidth, int newHeight) - { - if (editorComp != 0) - { -#if ! JUCE_LINUX // linux hosts shouldn't be trusted! - if (! (canHostDo ("sizeWindow") && sizeWindow (newWidth, newHeight))) -#endif - { - // some hosts don't support the sizeWindow call, so do it manually.. -#if JUCE_MAC - Rect r; - GetWindowBounds (hostWindow, kWindowContentRgn, &r); - - if (firstResize) - { - diffW = (r.right - r.left) - editorComp->getWidth(); - diffH = (r.bottom - r.top) - editorComp->getHeight(); - firstResize = false; - } - - r.right = r.left + newWidth + diffW; - r.bottom = r.top + newHeight + diffH; - - SetWindowBounds (hostWindow, kWindowContentRgn, &r); - - r.bottom -= r.top; - r.right -= r.left; - r.left = r.top = 0; - InvalWindowRect (hostWindow, &r); -#elif JUCE_LINUX - Window root; - int x, y; - unsigned int width, height, border, depth; - - XGetGeometry (display, hostWindow, &root, - &x, &y, &width, &height, &border, &depth); - - newWidth += (width + border) - editorComp->getWidth(); - newHeight += (height + border) - editorComp->getHeight(); - - XResizeWindow (display, hostWindow, newWidth, newHeight); -#else - int dw = 0; - int dh = 0; - const int frameThickness = GetSystemMetrics (SM_CYFIXEDFRAME); - - HWND w = (HWND) editorComp->getWindowHandle(); - - while (w != 0) - { - HWND parent = GetParent (w); - - if (parent == 0) - break; - - TCHAR windowType [32]; - zeromem (windowType, sizeof (windowType)); - GetClassName (parent, windowType, 31); - - if (String (windowType).equalsIgnoreCase (T("MDIClient"))) - break; - - RECT windowPos; - GetWindowRect (w, &windowPos); - - RECT parentPos; - GetWindowRect (parent, &parentPos); - - SetWindowPos (w, 0, 0, 0, - newWidth + dw, - newHeight + dh, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); - - dw = (parentPos.right - parentPos.left) - (windowPos.right - windowPos.left); - dh = (parentPos.bottom - parentPos.top) - (windowPos.bottom - windowPos.top); - - w = parent; - - if (dw == 2 * frameThickness) - break; - - if (dw > 100 || dh > 100) - w = 0; - } - - if (w != 0) - SetWindowPos (w, 0, 0, 0, - newWidth + dw, - newHeight + dh, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); -#endif - } - - if (editorComp->getPeer() != 0) - editorComp->getPeer()->handleMovedOrResized(); - } - } - - - //============================================================================== - juce_UseDebuggingNewOperator - -private: - AudioFilterBase* filter; - juce::MemoryBlock chunkMemory; - uint32 chunkMemoryTime; - EditorCompWrapper* editorComp; - ERect editorSize; - MidiBuffer midiEvents; - VstEvents* outgoingEvents; - int outgoingEventSize; - bool isProcessing; - bool firstResize; - int diffW, diffH; - - void ensureOutgoingEventSize (int numEvents) - { - if (outgoingEventSize < numEvents) - { - numEvents += 32; - const int size = 16 + sizeof (VstEvent*) * numEvents; - - if (outgoingEvents == 0) - outgoingEvents = (VstEvents*) juce_calloc (size); - else - outgoingEvents = (VstEvents*) juce_realloc (outgoingEvents, size); - - for (int i = outgoingEventSize; i < numEvents; ++i) - { - VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (sizeof (VstMidiEvent)); - e->type = kVstMidiType; - e->byteSize = 24; - - outgoingEvents->events[i] = (VstEvent*) e; - } - - outgoingEventSize = numEvents; - } - } - - const String getHostName() - { - char host[256]; - zeromem (host, sizeof (host)); - getHostProductString (host); - return host; - } - -#if JUCE_MAC - WindowRef hostWindow; -#elif JUCE_LINUX - Window hostWindow; -#else - HWND hostWindow; -#endif -}; - -//============================================================================== -void EditorCompWrapper::childBoundsChanged (Component* child) -{ - child->setTopLeftPosition (0, 0); - - const int cw = child->getWidth(); - const int ch = child->getHeight(); - - wrapper->resizeHostWindow (cw, ch); - setSize (cw, ch); - -#if JUCE_MAC - wrapper->resizeHostWindow (cw, ch); // (doing this a second time seems to be necessary in tracktion) -#endif -} - -void EditorCompWrapper::handleAsyncUpdate() -{ - wrapper->tryMasterIdle(); -} - -//============================================================================== -static AEffect* pluginEntryPoint (audioMasterCallback audioMaster) -{ -#if JUCE_MAC || JUCE_LINUX - initialiseJuce_GUI(); -#endif - - MessageManager::getInstance()->setTimeBeforeShowingWaitCursor (0); - - try - { - if (audioMaster (0, audioMasterVersion, 0, 0, 0, 0) != 0) - { - AudioFilterBase* const filter = createPluginFilter(); - - if (filter != 0) - { - JuceVSTWrapper* const wrapper = new JuceVSTWrapper (audioMaster, filter); - return wrapper->getAeffect(); - } - } - } - catch (...) - {} - - return 0; -} - - -//============================================================================== -// Mac startup code.. -#if JUCE_MAC - -extern "C" __attribute__ ((visibility("default"))) AEffect* VSTPluginMain (audioMasterCallback audioMaster) -{ - return pluginEntryPoint (audioMaster); -} - -extern "C" __attribute__ ((visibility("default"))) AEffect* main_macho (audioMasterCallback audioMaster) -{ - return pluginEntryPoint (audioMaster); -} - -//============================================================================== -// Linux startup code.. -#elif JUCE_LINUX - -extern "C" AEffect* main_plugin (audioMasterCallback audioMaster) asm ("main"); - -extern "C" AEffect* main_plugin (audioMasterCallback audioMaster) -{ - initialiseJuce_GUI(); - SharedMessageThread::getInstance(); - - return pluginEntryPoint (audioMaster); -} - -__attribute__((constructor)) void myPluginInit() -{ - // don't put initialiseJuce_GUI here... it will crash ! -} - -__attribute__((destructor)) void myPluginFini() -{ - // don't put shutdownJuce_GUI here... it will crash ! -} - -//============================================================================== -// Win32 startup code.. -#else - -extern "C" __declspec (dllexport) AEffect* VSTPluginMain (audioMasterCallback audioMaster) -{ - return pluginEntryPoint (audioMaster); -} - -extern "C" __declspec (dllexport) void* main (audioMasterCallback audioMaster) -{ - return (void*) pluginEntryPoint (audioMaster); -} - -BOOL WINAPI DllMain (HINSTANCE instance, DWORD dwReason, LPVOID) -{ - if (dwReason == DLL_PROCESS_ATTACH) - { - PlatformUtilities::setCurrentModuleInstanceHandle (instance); - initialiseJuce_GUI(); - } - else if (dwReason == DLL_PROCESS_DETACH) - { - shutdownJuce_GUI(); - } - - return TRUE; -} - -#endif +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +/* + *** DON't EDIT THIS FILE!! *** + + The idea is that everyone's plugins should share this same wrapper + code, so if you start hacking around in here you're missing the point! + + If there's a bug or a function you need that can't be done without changing + some of the code in here, give me a shout so we can add it to the library, + rather than branching off and going it alone! +*/ + + +//============================================================================== +#ifdef _MSC_VER + #pragma warning (disable : 4996) +#endif + +#ifdef _WIN32 + #include +#elif defined (LINUX) + #include + #include + #include + #undef KeyPress +#else + #include +#endif + +#ifdef PRAGMA_ALIGN_SUPPORTED + #undef PRAGMA_ALIGN_SUPPORTED + #define PRAGMA_ALIGN_SUPPORTED 1 +#endif + +#include "../../juce_IncludeCharacteristics.h" + +//============================================================================== +/* These files come with the Steinberg VST SDK - to get them, you'll need to + visit the Steinberg website and jump through some hoops to sign up as a + VST developer. + + Then, you'll need to make sure your include path contains your "vstsdk2.3" or + "vstsdk2.4" directory. + + Note that the JUCE_USE_VSTSDK_2_4 macro should be defined in JucePluginCharacteristics.h +*/ +#if JUCE_USE_VSTSDK_2_4 + // VSTSDK V2.4 includes.. + #include "public.sdk/source/vst2.x/audioeffectx.h" + #include "public.sdk/source/vst2.x/aeffeditor.h" + #include "public.sdk/source/vst2.x/audioeffectx.cpp" + #include "public.sdk/source/vst2.x/audioeffect.cpp" +#else + // VSTSDK V2.3 includes.. + #include "source/common/audioeffectx.h" + #include "source/common/AEffEditor.hpp" + #include "source/common/audioeffectx.cpp" + #include "source/common/AudioEffect.cpp" + typedef long VstInt32; + typedef long VstIntPtr; +#endif + +//============================================================================== +#include "../../juce_AudioFilterBase.h" +#undef MemoryBlock + +class JuceVSTWrapper; +static bool recursionCheck = false; +static uint32 lastMasterIdleCall = 0; + +BEGIN_JUCE_NAMESPACE + extern void juce_callAnyTimersSynchronously(); + + #if JUCE_MAC + extern void juce_macDoPendingRepaintsNow(); + #elif JUCE_LINUX + extern Display* display; + extern bool juce_postMessageToSystemQueue (void* message); + #endif +END_JUCE_NAMESPACE + + +//============================================================================== +#if JUCE_WIN32 + +static HWND findMDIParentOf (HWND w) +{ + const int frameThickness = GetSystemMetrics (SM_CYFIXEDFRAME); + + while (w != 0) + { + HWND parent = GetParent (w); + + if (parent == 0) + break; + + TCHAR windowType [32]; + zeromem (windowType, sizeof (windowType)); + GetClassName (parent, windowType, 31); + + if (String (windowType).equalsIgnoreCase (T("MDIClient"))) + { + w = parent; + break; + } + + RECT windowPos; + GetWindowRect (w, &windowPos); + + RECT parentPos; + GetWindowRect (parent, &parentPos); + + int dw = (parentPos.right - parentPos.left) - (windowPos.right - windowPos.left); + int dh = (parentPos.bottom - parentPos.top) - (windowPos.bottom - windowPos.top); + + if (dw > 100 || dh > 100) + break; + + w = parent; + + if (dw == 2 * frameThickness) + break; + } + + return w; +} + +//============================================================================== +#elif JUCE_LINUX + +class SharedMessageThread : public Thread +{ +public: + SharedMessageThread() + : Thread (T("VstMessageThread")) + { + startThread (7); + } + + ~SharedMessageThread() + { + signalThreadShouldExit(); + + const int quitMessageId = 0xfffff321; + Message* const m = new Message (quitMessageId, 1, 0, 0); + + if (! juce_postMessageToSystemQueue (m)) + delete m; + + clearSingletonInstance(); + } + + void run() + { + MessageManager* const messageManager = MessageManager::getInstance(); + + const int originalThreadId = messageManager->getCurrentMessageThread(); + messageManager->setCurrentMessageThread (getThreadId()); + + while (! threadShouldExit() + && messageManager->dispatchNextMessage()) + { + } + + messageManager->setCurrentMessageThread (originalThreadId); + } + + juce_DeclareSingleton (SharedMessageThread, false) +}; + +juce_ImplementSingleton (SharedMessageThread); + +#endif + +//============================================================================== +// A component to hold the AudioFilterEditor, and cope with some housekeeping +// chores when it changes or repaints. +class EditorCompWrapper : public Component, + public AsyncUpdater +{ + JuceVSTWrapper* wrapper; + +public: + EditorCompWrapper (JuceVSTWrapper* const wrapper_, + AudioFilterEditor* const editor) + : wrapper (wrapper_) + { + setOpaque (true); + editor->setOpaque (true); + + setBounds (editor->getBounds()); + editor->setTopLeftPosition (0, 0); + addAndMakeVisible (editor); + +#if JUCE_WIN32 + addMouseListener (this, true); +#endif + } + + ~EditorCompWrapper() + { + deleteAllChildren(); + } + + void paint (Graphics& g) + { + } + + void paintOverChildren (Graphics& g) + { + // this causes an async call to masterIdle() to help + // creaky old DAWs like Nuendo repaint themselves while we're + // repainting. Otherwise they just seem to give up and sit there + // waiting. + triggerAsyncUpdate(); + } + + AudioFilterEditor* getEditorComp() const + { + return dynamic_cast (getChildComponent (0)); + } + + void resized() + { + Component* const c = getChildComponent (0); + + if (c != 0) + { +#if JUCE_LINUX + const MessageManagerLock mml; +#endif + c->setBounds (0, 0, getWidth(), getHeight()); + } + } + + void childBoundsChanged (Component* child); + void handleAsyncUpdate(); + +#if JUCE_WIN32 + void mouseDown (const MouseEvent&) + { + broughtToFront(); + } + + void broughtToFront() + { + // for hosts like nuendo, need to also pop the MDI container to the + // front when our comp is clicked on. + HWND parent = findMDIParentOf ((HWND) getWindowHandle()); + + if (parent != 0) + { + SetWindowPos (parent, + HWND_TOP, + 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE); + } + } +#endif + + //============================================================================== + juce_UseDebuggingNewOperator +}; + +static VoidArray activePlugins; + + +//============================================================================== +/** + This wraps an AudioFilterBase as an AudioEffectX... +*/ +class JuceVSTWrapper : public AudioEffectX, + private Timer, + public AudioFilterBase::FilterNativeCallbacks +{ +public: + //============================================================================== + JuceVSTWrapper (audioMasterCallback audioMaster, + AudioFilterBase* const filter_) + : AudioEffectX (audioMaster, + filter_->getNumPrograms(), + filter_->getNumParameters()), + filter (filter_) + { + filter->numInputChannels = JucePlugin_MaxNumInputChannels; + filter->numOutputChannels = JucePlugin_MaxNumOutputChannels; + + filter_->initialiseInternal (this); + + editorComp = 0; + outgoingEvents = 0; + outgoingEventSize = 0; + chunkMemoryTime = 0; + isProcessing = false; + firstResize = true; + +#if JUCE_MAC || JUCE_LINUX + hostWindow = 0; +#endif + + cEffect.flags |= effFlagsHasEditor; + + setUniqueID ((int) (JucePlugin_VSTUniqueID)); + getAeffect()->version = (long) (JucePlugin_VersionCode); + +#if JucePlugin_WantsMidiInput && ! JUCE_USE_VSTSDK_2_4 + wantEvents(); +#endif + + setNumInputs (filter->numInputChannels); + setNumOutputs (filter->numOutputChannels); + + canProcessReplacing (true); + +#if ! JUCE_USE_VSTSDK_2_4 + hasVu (false); + hasClip (false); +#endif + + isSynth ((JucePlugin_IsSynth) != 0); + noTail ((JucePlugin_SilenceInProducesSilenceOut) != 0); + setInitialDelay (JucePlugin_Latency); + programsAreChunks (true); + + activePlugins.add (this); + } + + ~JuceVSTWrapper() + { + stopTimer(); + deleteEditor(); + + delete filter; + filter = 0; + + if (outgoingEvents != 0) + { + for (int i = outgoingEventSize; --i >= 0;) + juce_free (outgoingEvents->events[i]); + + juce_free (outgoingEvents); + outgoingEvents = 0; + } + + jassert (editorComp == 0); + + jassert (activePlugins.contains (this)); + activePlugins.removeValue (this); + +#if JUCE_MAC || JUCE_LINUX + if (activePlugins.size() == 0) + { +#if JUCE_LINUX + SharedMessageThread::deleteInstance(); +#endif + shutdownJuce_GUI(); + } +#endif + } + + void open() + { + startTimer (1000 / 4); + } + + void close() + { + jassert (! recursionCheck); + + stopTimer(); + deleteEditor(); + } + + //============================================================================== + bool getEffectName (char* name) + { + String (JucePlugin_Name).copyToBuffer (name, 64); + return true; + } + + bool getVendorString (char* text) + { + String (JucePlugin_Manufacturer).copyToBuffer (text, 64); + return true; + } + + bool getProductString (char* text) + { + return getEffectName (text); + } + + VstInt32 getVendorVersion() + { + return JucePlugin_VersionCode; + } + + VstPlugCategory getPlugCategory() + { + return JucePlugin_VSTCategory; + } + + VstInt32 canDo (char* text) + { + VstInt32 result = 0; + + if (strcmp (text, "receiveVstEvents") == 0 + || strcmp (text, "receiveVstMidiEvent") == 0 + || strcmp (text, "receiveVstMidiEvents") == 0) + { +#if JucePlugin_WantsMidiInput + result = 1; +#else + result = -1; +#endif + } + else if (strcmp (text, "sendVstEvents") == 0 + || strcmp (text, "sendVstMidiEvent") == 0 + || strcmp (text, "sendVstMidiEvents") == 0) + { +#if JucePlugin_ProducesMidiOutput + result = 1; +#else + result = -1; +#endif + } + else if (strcmp (text, "receiveVstTimeInfo") == 0) + { + result = 1; + } + else if (strcmp (text, "conformsToWindowRules") == 0) + { + result = 1; + } + + return result; + } + + bool keysRequired() + { + return (JucePlugin_EditorRequiresKeyboardFocus) != 0; + } + + bool getInputProperties (VstInt32 index, VstPinProperties* properties) + { + const String name (filter->getInputChannelName ((int) index)); + + name.copyToBuffer (properties->label, kVstMaxLabelLen - 1); + name.copyToBuffer (properties->shortLabel, kVstMaxShortLabelLen - 1); + + properties->flags = kVstPinIsActive; + + if (filter->isInputChannelStereoPair ((int) index)) + properties->flags |= kVstPinIsStereo; + + properties->arrangementType = 0; + + return true; + } + + bool getOutputProperties (VstInt32 index, VstPinProperties* properties) + { + const String name (filter->getOutputChannelName ((int) index)); + + name.copyToBuffer (properties->label, kVstMaxLabelLen - 1); + name.copyToBuffer (properties->shortLabel, kVstMaxShortLabelLen - 1); + + properties->flags = kVstPinIsActive; + + if (filter->isOutputChannelStereoPair ((int) index)) + properties->flags |= kVstPinIsStereo; + + properties->arrangementType = 0; + + return true; + } + + //============================================================================== + VstInt32 processEvents (VstEvents* events) + { +#if JucePlugin_WantsMidiInput + for (int i = 0; i < events->numEvents; ++i) + { + const VstEvent* const e = events->events[i]; + + if (e != 0 && e->type == kVstMidiType) + { + const VstMidiEvent* const vme = (const VstMidiEvent*) e; + + midiEvents.addEvent ((const uint8*) vme->midiData, + 4, + vme->deltaFrames); + } + } + + return 1; +#else + return 0; +#endif + } + + void process (float** inputs, float** outputs, + const VstInt32 numSamples, const bool accumulate) + { + // if this fails, the host hasn't called resume() before processing + jassert (isProcessing); + + // (tragically, some hosts actually need this, although it's stupid to have + // to do it here..) + if (! isProcessing) + resume(); + +#if JUCE_DEBUG && ! JucePlugin_ProducesMidiOutput + const int numMidiEventsComingIn = midiEvents.getNumEvents(); +#endif + + jassert (activePlugins.contains (this)); + + { + const AudioSampleBuffer input (inputs, filter->numInputChannels, numSamples); + AudioSampleBuffer output (outputs, filter->numOutputChannels, numSamples); + + const ScopedLock sl (filter->getCallbackLock()); + + if (filter->suspended) + { + if (! accumulate) + output.clear(); + } + else + { + filter->processBlock (input, output, accumulate, midiEvents); + } + } + + if (! midiEvents.isEmpty()) + { +#if JucePlugin_ProducesMidiOutput + const int numEvents = midiEvents.getNumEvents(); + + ensureOutgoingEventSize (numEvents); + outgoingEvents->numEvents = 0; + + const uint8* midiEventData; + int midiEventSize, midiEventPosition; + MidiBuffer::Iterator i (midiEvents); + + while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition)) + { + if (midiEventSize <= 4) + { + VstMidiEvent* const vme = (VstMidiEvent*) outgoingEvents->events [outgoingEvents->numEvents++]; + + memcpy (vme->midiData, midiEventData, midiEventSize); + vme->deltaFrames = midiEventPosition; + + jassert (vme->deltaFrames >= 0 && vme->deltaFrames < numSamples); + } + } + + sendVstEventsToHost (outgoingEvents); +#else + /* This assertion is caused when you've added some events to the + midiMessages array in your processBlock() method, which usually means + that you're trying to send them somewhere. But in this case they're + getting thrown away. + + If your plugin does want to send midi messages, you'll need to set + the JucePlugin_ProducesMidiOutput macro to 1 in your + JucePluginCharacteristics.h file. + + If you don't want to produce any midi output, then you should clear the + midiMessages array at the end of your processBlock() method, to + indicate that you don't want any of the events to be passed through + to the output. + */ + jassert (midiEvents.getNumEvents() <= numMidiEventsComingIn); +#endif + + midiEvents.clear(); + } + } + + void process (float** inputs, float** outputs, VstInt32 numSamples) + { + process (inputs, outputs, numSamples, true); + } + + void processReplacing (float** inputs, float** outputs, VstInt32 numSamples) + { + process (inputs, outputs, numSamples, false); + } + + //============================================================================== + void resume() + { + isProcessing = true; + + filter->sampleRate = getSampleRate(); + + jassert (filter->sampleRate > 0); + if (filter->sampleRate <= 0) + filter->sampleRate = 44100.0; + + filter->blockSize = getBlockSize(); + jassert (filter->blockSize > 0); + + filter->prepareToPlay (filter->sampleRate, filter->blockSize); + midiEvents.clear(); + + AudioEffectX::resume(); + +#if JucePlugin_ProducesMidiOutput + ensureOutgoingEventSize (64); +#endif + +#if JucePlugin_WantsMidiInput && ! JUCE_USE_VSTSDK_2_4 + wantEvents(); +#endif + } + + void suspend() + { + AudioEffectX::suspend(); + + filter->releaseResources(); + midiEvents.clear(); + + isProcessing = false; + } + + bool JUCE_CALLTYPE getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info) + { + const VstTimeInfo* const ti = getTimeInfo (kVstPpqPosValid + | kVstTempoValid + | kVstBarsValid + //| kVstCyclePosValid + | kVstTimeSigValid + | kVstSmpteValid + | kVstClockValid); + + if (ti == 0 || ti->sampleRate <= 0) + return false; + + if ((ti->flags & kVstTempoValid) != 0) + info.bpm = ti->tempo; + else + info.bpm = 0.0; + + if ((ti->flags & kVstTimeSigValid) != 0) + { + info.timeSigNumerator = ti->timeSigNumerator; + info.timeSigDenominator = ti->timeSigDenominator; + } + else + { + info.timeSigNumerator = 4; + info.timeSigDenominator = 4; + } + + info.timeInSeconds = ti->samplePos / ti->sampleRate; + + if ((ti->flags & kVstPpqPosValid) != 0) + info.ppqPosition = ti->ppqPos; + else + info.ppqPosition = 0.0; + + if ((ti->flags & kVstBarsValid) != 0) + info.ppqPositionOfLastBarStart = ti->barStartPos; + else + info.ppqPositionOfLastBarStart = 0.0; + + if ((ti->flags & kVstSmpteValid) != 0) + { + info.frameRate = (AudioFilterBase::CurrentPositionInfo::FrameRateType) (int) ti->smpteFrameRate; + + const double fpsDivisors[] = { 24.0, 25.0, 30.0, 30.0, 30.0, 30.0, 1.0 }; + info.editOriginTime = (ti->smpteOffset / (80.0 * fpsDivisors [(int) info.frameRate])); + } + else + { + info.frameRate = AudioFilterBase::CurrentPositionInfo::fpsUnknown; + info.editOriginTime = 0; + } + + info.isRecording = (ti->flags & kVstTransportRecording) != 0; + info.isPlaying = (ti->flags & kVstTransportPlaying) != 0 || info.isRecording; + + return true; + } + + //============================================================================== + VstInt32 getProgram() + { + return filter->getCurrentProgram(); + } + + void setProgram (VstInt32 program) + { + filter->setCurrentProgram (program); + } + + void setProgramName (char* name) + { + filter->changeProgramName (filter->getCurrentProgram(), name); + } + + void getProgramName (char* name) + { + filter->getProgramName (filter->getCurrentProgram()).copyToBuffer (name, 24); + } + + bool getProgramNameIndexed (VstInt32 category, VstInt32 index, char* text) + { + if (index >= 0 && index < filter->getNumPrograms()) + { + filter->getProgramName (index).copyToBuffer (text, 24); + return true; + } + + return false; + } + + //============================================================================== + float getParameter (VstInt32 index) + { + jassert (index >= 0 && index < filter->getNumParameters()); + return filter->getParameter (index); + } + + void setParameter (VstInt32 index, float value) + { + jassert (index >= 0 && index < filter->getNumParameters()); + filter->setParameter (index, value); + } + + void getParameterDisplay (VstInt32 index, char* text) + { + jassert (index >= 0 && index < filter->getNumParameters()); + filter->getParameterText (index).copyToBuffer (text, 64); + } + + void getParameterName (VstInt32 index, char* text) + { + jassert (index >= 0 && index < filter->getNumParameters()); + filter->getParameterName (index).copyToBuffer (text, 8); + } + + void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue) + { + setParameterAutomated (index, newValue); + } + + bool canParameterBeAutomated (VstInt32 index) + { + return filter->isParameterAutomatable ((int) index); + } + + //============================================================================== + VstInt32 getChunk (void** data, bool onlyStoreCurrentProgramData) + { + chunkMemory.setSize (0); + if (onlyStoreCurrentProgramData) + filter->getCurrentProgramStateInformation (chunkMemory); + else + filter->getStateInformation (chunkMemory); + + *data = (void*) chunkMemory; + + // because the chunk is only needed temporarily by the host (or at least you'd + // hope so) we'll give it a while and then free it in the timer callback. + chunkMemoryTime = JUCE_NAMESPACE::Time::getApproximateMillisecondCounter(); + + return chunkMemory.getSize(); + } + + VstInt32 setChunk (void* data, VstInt32 byteSize, bool onlyRestoreCurrentProgramData) + { + chunkMemory.setSize (0); + chunkMemoryTime = 0; + + if (byteSize > 0 && data != 0) + { + if (onlyRestoreCurrentProgramData) + filter->setCurrentProgramStateInformation (data, byteSize); + else + filter->setStateInformation (data, byteSize); + } + + return 0; + } + + void timerCallback() + { + if (chunkMemoryTime > 0 + && chunkMemoryTime < JUCE_NAMESPACE::Time::getApproximateMillisecondCounter() - 2000 + && ! recursionCheck) + { + chunkMemoryTime = 0; + chunkMemory.setSize (0); + } + + tryMasterIdle(); + } + + void tryMasterIdle() + { + if (Component::isMouseButtonDownAnywhere() + && ! recursionCheck) + { + const uint32 now = JUCE_NAMESPACE::Time::getMillisecondCounter(); + + if (now > lastMasterIdleCall + 20 && editorComp != 0) + { + lastMasterIdleCall = now; + + recursionCheck = true; + masterIdle(); + recursionCheck = false; + } + } + } + + void doIdleCallback() + { + // (wavelab calls this on a separate thread and causes a deadlock).. + if (MessageManager::getInstance()->isThisTheMessageThread()) + { + if (! recursionCheck) + { + const MessageManagerLock mml; + + recursionCheck = true; + + juce_callAnyTimersSynchronously(); + + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) + ComponentPeer::getPeer (i)->performAnyPendingRepaintsNow(); + + recursionCheck = false; + } + } + } + + void createEditorComp() + { + if (editorComp == 0) + { +#if JUCE_LINUX + const MessageManagerLock mml; +#endif + + AudioFilterEditor* const ed = filter->createEditorIfNeeded(); + + if (ed != 0) + { + ed->setOpaque (true); + ed->setVisible (true); + + editorComp = new EditorCompWrapper (this, ed); + } + } + } + + void deleteEditor() + { + PopupMenu::dismissAllActiveMenus(); + + jassert (! recursionCheck); + recursionCheck = true; + +#if JUCE_LINUX + const MessageManagerLock mml; +#endif + + if (editorComp != 0) + { + Component* const modalComponent = Component::getCurrentlyModalComponent(); + if (modalComponent != 0) + modalComponent->exitModalState (0); + + filter->editorBeingDeleted (editorComp->getEditorComp()); + + deleteAndZero (editorComp); + + // there's some kind of component currently modal, but the host + // is trying to delete our plugin. You should try to avoid this happening.. + jassert (Component::getCurrentlyModalComponent() == 0); + } + +#if JUCE_MAC || JUCE_LINUX + hostWindow = 0; +#endif + + recursionCheck = false; + } + + VstIntPtr dispatcher (VstInt32 opCode, VstInt32 index, VstIntPtr value, void* ptr, float opt) + { + if (opCode == effEditIdle) + { + doIdleCallback(); + return 0; + } + else if (opCode == effEditOpen) + { + jassert (! recursionCheck); + + deleteEditor(); + createEditorComp(); + + if (editorComp != 0) + { +#if JUCE_LINUX + const MessageManagerLock mml; +#endif + + editorComp->setOpaque (true); + editorComp->setVisible (false); + +#if JUCE_WIN32 + editorComp->addToDesktop (0); + + hostWindow = (HWND) ptr; + HWND editorWnd = (HWND) editorComp->getWindowHandle(); + + SetParent (editorWnd, hostWindow); + + DWORD val = GetWindowLong (editorWnd, GWL_STYLE); + val = (val & ~WS_POPUP) | WS_CHILD; + SetWindowLong (editorWnd, GWL_STYLE, val); + + editorComp->setVisible (true); +#elif JUCE_LINUX + editorComp->addToDesktop (0); + + hostWindow = (Window) ptr; + + Window editorWnd = (Window) editorComp->getWindowHandle(); + + XReparentWindow (display, editorWnd, hostWindow, 0, 0); + + editorComp->setVisible (true); +#else + hostWindow = (WindowRef) ptr; + firstResize = true; + + SetAutomaticControlDragTrackingEnabledForWindow (hostWindow, true); + + WindowAttributes attributes; + GetWindowAttributes (hostWindow, &attributes); + + HIViewRef parentView = 0; + + if ((attributes & kWindowCompositingAttribute) != 0) + { + HIViewRef root = HIViewGetRoot (hostWindow); + HIViewFindByID (root, kHIViewWindowContentID, &parentView); + + if (parentView == 0) + parentView = root; + } + else + { + GetRootControl (hostWindow, (ControlRef*) &parentView); + + if (parentView == 0) + CreateRootControl (hostWindow, (ControlRef*) &parentView); + } + + jassert (parentView != 0); // agh - the host has to provide a compositing window.. + + editorComp->setVisible (true); + editorComp->addToDesktop (0, (void*) parentView); +#endif + + return 1; + } + } + else if (opCode == effEditClose) + { + deleteEditor(); + return 0; + } + else if (opCode == effEditGetRect) + { + createEditorComp(); + + if (editorComp != 0) + { + editorSize.left = 0; + editorSize.top = 0; + editorSize.right = editorComp->getWidth(); + editorSize.bottom = editorComp->getHeight(); + + *((ERect**) ptr) = &editorSize; + + return (VstIntPtr) &editorSize; + } + else + { + return 0; + } + } + + return AudioEffectX::dispatcher (opCode, index, value, ptr, opt); + } + + void resizeHostWindow (int newWidth, int newHeight) + { + if (editorComp != 0) + { +#if ! JUCE_LINUX // linux hosts shouldn't be trusted! + if (! (canHostDo ("sizeWindow") && sizeWindow (newWidth, newHeight))) +#endif + { + // some hosts don't support the sizeWindow call, so do it manually.. +#if JUCE_MAC + Rect r; + GetWindowBounds (hostWindow, kWindowContentRgn, &r); + + if (firstResize) + { + diffW = (r.right - r.left) - editorComp->getWidth(); + diffH = (r.bottom - r.top) - editorComp->getHeight(); + firstResize = false; + } + + r.right = r.left + newWidth + diffW; + r.bottom = r.top + newHeight + diffH; + + SetWindowBounds (hostWindow, kWindowContentRgn, &r); + + r.bottom -= r.top; + r.right -= r.left; + r.left = r.top = 0; + InvalWindowRect (hostWindow, &r); +#elif JUCE_LINUX + Window root; + int x, y; + unsigned int width, height, border, depth; + + XGetGeometry (display, hostWindow, &root, + &x, &y, &width, &height, &border, &depth); + + newWidth += (width + border) - editorComp->getWidth(); + newHeight += (height + border) - editorComp->getHeight(); + + XResizeWindow (display, hostWindow, newWidth, newHeight); +#else + int dw = 0; + int dh = 0; + const int frameThickness = GetSystemMetrics (SM_CYFIXEDFRAME); + + HWND w = (HWND) editorComp->getWindowHandle(); + + while (w != 0) + { + HWND parent = GetParent (w); + + if (parent == 0) + break; + + TCHAR windowType [32]; + zeromem (windowType, sizeof (windowType)); + GetClassName (parent, windowType, 31); + + if (String (windowType).equalsIgnoreCase (T("MDIClient"))) + break; + + RECT windowPos; + GetWindowRect (w, &windowPos); + + RECT parentPos; + GetWindowRect (parent, &parentPos); + + SetWindowPos (w, 0, 0, 0, + newWidth + dw, + newHeight + dh, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); + + dw = (parentPos.right - parentPos.left) - (windowPos.right - windowPos.left); + dh = (parentPos.bottom - parentPos.top) - (windowPos.bottom - windowPos.top); + + w = parent; + + if (dw == 2 * frameThickness) + break; + + if (dw > 100 || dh > 100) + w = 0; + } + + if (w != 0) + SetWindowPos (w, 0, 0, 0, + newWidth + dw, + newHeight + dh, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); +#endif + } + + if (editorComp->getPeer() != 0) + editorComp->getPeer()->handleMovedOrResized(); + } + } + + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + AudioFilterBase* filter; + juce::MemoryBlock chunkMemory; + uint32 chunkMemoryTime; + EditorCompWrapper* editorComp; + ERect editorSize; + MidiBuffer midiEvents; + VstEvents* outgoingEvents; + int outgoingEventSize; + bool isProcessing; + bool firstResize; + int diffW, diffH; + + void ensureOutgoingEventSize (int numEvents) + { + if (outgoingEventSize < numEvents) + { + numEvents += 32; + const int size = 16 + sizeof (VstEvent*) * numEvents; + + if (outgoingEvents == 0) + outgoingEvents = (VstEvents*) juce_calloc (size); + else + outgoingEvents = (VstEvents*) juce_realloc (outgoingEvents, size); + + for (int i = outgoingEventSize; i < numEvents; ++i) + { + VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (sizeof (VstMidiEvent)); + e->type = kVstMidiType; + e->byteSize = 24; + + outgoingEvents->events[i] = (VstEvent*) e; + } + + outgoingEventSize = numEvents; + } + } + + const String getHostName() + { + char host[256]; + zeromem (host, sizeof (host)); + getHostProductString (host); + return host; + } + +#if JUCE_MAC + WindowRef hostWindow; +#elif JUCE_LINUX + Window hostWindow; +#else + HWND hostWindow; +#endif +}; + +//============================================================================== +void EditorCompWrapper::childBoundsChanged (Component* child) +{ + child->setTopLeftPosition (0, 0); + + const int cw = child->getWidth(); + const int ch = child->getHeight(); + + wrapper->resizeHostWindow (cw, ch); + setSize (cw, ch); + +#if JUCE_MAC + wrapper->resizeHostWindow (cw, ch); // (doing this a second time seems to be necessary in tracktion) +#endif +} + +void EditorCompWrapper::handleAsyncUpdate() +{ + wrapper->tryMasterIdle(); +} + +//============================================================================== +static AEffect* pluginEntryPoint (audioMasterCallback audioMaster) +{ +#if JUCE_MAC || JUCE_LINUX + initialiseJuce_GUI(); +#endif + + MessageManager::getInstance()->setTimeBeforeShowingWaitCursor (0); + + try + { + if (audioMaster (0, audioMasterVersion, 0, 0, 0, 0) != 0) + { + AudioFilterBase* const filter = createPluginFilter(); + + if (filter != 0) + { + JuceVSTWrapper* const wrapper = new JuceVSTWrapper (audioMaster, filter); + return wrapper->getAeffect(); + } + } + } + catch (...) + {} + + return 0; +} + + +//============================================================================== +// Mac startup code.. +#if JUCE_MAC + +extern "C" __attribute__ ((visibility("default"))) AEffect* VSTPluginMain (audioMasterCallback audioMaster) +{ + return pluginEntryPoint (audioMaster); +} + +extern "C" __attribute__ ((visibility("default"))) AEffect* main_macho (audioMasterCallback audioMaster) +{ + return pluginEntryPoint (audioMaster); +} + +//============================================================================== +// Linux startup code.. +#elif JUCE_LINUX + +extern "C" AEffect* main_plugin (audioMasterCallback audioMaster) asm ("main"); + +extern "C" AEffect* main_plugin (audioMasterCallback audioMaster) +{ + initialiseJuce_GUI(); + SharedMessageThread::getInstance(); + + return pluginEntryPoint (audioMaster); +} + +__attribute__((constructor)) void myPluginInit() +{ + // don't put initialiseJuce_GUI here... it will crash ! +} + +__attribute__((destructor)) void myPluginFini() +{ + // don't put shutdownJuce_GUI here... it will crash ! +} + +//============================================================================== +// Win32 startup code.. +#else + +extern "C" __declspec (dllexport) AEffect* VSTPluginMain (audioMasterCallback audioMaster) +{ + return pluginEntryPoint (audioMaster); +} + +extern "C" __declspec (dllexport) void* main (audioMasterCallback audioMaster) +{ + return (void*) pluginEntryPoint (audioMaster); +} + +BOOL WINAPI DllMain (HINSTANCE instance, DWORD dwReason, LPVOID) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + PlatformUtilities::setCurrentModuleInstanceHandle (instance); + initialiseJuce_GUI(); + } + else if (dwReason == DLL_PROCESS_DETACH) + { + shutdownJuce_GUI(); + } + + return TRUE; +} + +#endif diff --git a/extras/audio plugins/wrapper/juce_AudioFilterBase.cpp b/extras/audio plugins/wrapper/juce_AudioFilterBase.cpp index 795dfb7c2a..0458ddc41d 100644 --- a/extras/audio plugins/wrapper/juce_AudioFilterBase.cpp +++ b/extras/audio plugins/wrapper/juce_AudioFilterBase.cpp @@ -34,14 +34,14 @@ //============================================================================== AudioFilterBase::AudioFilterBase() - : suspended (false), + : sampleRate (0), + blockSize (0), numInputChannels (0), numOutputChannels (0), + suspended (false), callbacks (0), activeEditor (0) { - sampleRate = 0.0; - blockSize = 0; } AudioFilterBase::~AudioFilterBase() @@ -67,6 +67,11 @@ void AudioFilterBase::setParameterNotifyingHost (const int parameterIndex, setParameter (parameterIndex, newValue); } +bool AudioFilterBase::isParameterAutomatable (int /*index*/) const +{ + return true; +} + void AudioFilterBase::suspendProcessing (const bool shouldBeSuspended) { const ScopedLock sl (callbackLock); @@ -80,18 +85,6 @@ bool AudioFilterBase::getCurrentPositionInfo (CurrentPositionInfo& info) && callbacks->getCurrentPositionInfo (info); } -const String AudioFilterBase::getInputChannelName (const int channelIndex) const -{ - String s (inputNames [channelIndex]); - return s.isNotEmpty() ? s : String (channelIndex + 1); -} - -const String AudioFilterBase::getOutputChannelName (const int channelIndex) const -{ - String s (outputNames [channelIndex]); - return s.isNotEmpty() ? s : String (channelIndex + 1); -} - //============================================================================== void AudioFilterBase::editorBeingDeleted (AudioFilterEditor* const editor) { @@ -112,8 +105,10 @@ AudioFilterEditor* AudioFilterBase::createEditorIfNeeded() if (ed != 0) { +#if ! JUCE_PLUGIN_HOST // you must give your editor comp a size before returning it.. jassert (ed->getWidth() > 0 && ed->getHeight() > 0); +#endif const ScopedLock sl (callbackLock); activeEditor = ed; diff --git a/extras/audio plugins/wrapper/juce_AudioFilterBase.h b/extras/audio plugins/wrapper/juce_AudioFilterBase.h index a9252408d4..1560a944ba 100644 --- a/extras/audio plugins/wrapper/juce_AudioFilterBase.h +++ b/extras/audio plugins/wrapper/juce_AudioFilterBase.h @@ -207,6 +207,7 @@ public: */ bool JUCE_CALLTYPE getCurrentPositionInfo (CurrentPositionInfo& info); + //============================================================================== /** Returns the current sample rate. This can be called from your processBlock() method - it's not guaranteed @@ -225,6 +226,7 @@ public: */ int JUCE_CALLTYPE getBlockSize() const throw() { return blockSize; } + //============================================================================== /** Returns the number of input channels that the host will be sending the filter. In your JucePluginCharacteristics.h file, you specify the number of channels @@ -252,14 +254,20 @@ public: The host might not supply very useful names for channels, and this might be something like "1", "2", "left", "right", etc. */ - const String getInputChannelName (const int channelIndex) const; + virtual const String JUCE_CALLTYPE getInputChannelName (const int channelIndex) const = 0; /** Returns the name of one of the output channels, as returned by the host. The host might not supply very useful names for channels, and this might be something like "1", "2", "left", "right", etc. */ - const String getOutputChannelName (const int channelIndex) const; + virtual const String JUCE_CALLTYPE getOutputChannelName (const int channelIndex) const = 0; + + /** Returns true if the specified channel is part of a stereo pair with its neighbour. */ + virtual bool JUCE_CALLTYPE isInputChannelStereoPair (int index) const = 0; + + /** Returns true if the specified channel is part of a stereo pair with its neighbour. */ + virtual bool JUCE_CALLTYPE isOutputChannelStereoPair (int index) const = 0; //============================================================================== /** This returns a critical section that will automatically be locked while the host @@ -384,6 +392,12 @@ public: void JUCE_CALLTYPE setParameterNotifyingHost (int parameterIndex, float newValue); + /** Returns true if the host can automate this parameter. + + By default, this returns true for all parameters. + */ + virtual bool isParameterAutomatable (int index) const; + //============================================================================== /** Returns the number of preset programs the plugin supports. @@ -507,6 +521,11 @@ protected: static XmlElement* JUCE_CALLTYPE getXmlFromBinary (const void* data, const int sizeInBytes); + /** @internal */ + double sampleRate; + /** @internal */ + int numInputChannels, numOutputChannels, blockSize; + private: friend class JuceVSTWrapper; friend class JuceAU; @@ -517,9 +536,6 @@ private: CriticalSection callbackLock; bool suspended; - double sampleRate; - int blockSize, numInputChannels, numOutputChannels; - StringArray outputNames, inputNames; FilterNativeCallbacks* callbacks; diff --git a/extras/juce demo/src/BinaryData.cpp b/extras/juce demo/src/BinaryData.cpp index 66292fe04e..78e7532a8a 100644 --- a/extras/juce demo/src/BinaryData.cpp +++ b/extras/juce demo/src/BinaryData.cpp @@ -6737,1195 +6737,1195 @@ static const unsigned char temp17[] = {47,42,13,10,32,32,61,61,61,61,61,61,61,61 115,116,111,109,67,111,109,112,111,110,101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,112,117,98,108,105,99,32,84,105,109,101,114,13,10,123,13,10,32,32,32,32,105,110,116,32,98,108,111,98,88,44,32,98,108,111, 98,89,59,13,10,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,67,117,115,116,111,109,77,101,110,117,67,111,109,112,111,110,101,110,116,40, - 41,13,10,32,32,32,32,32,32,32,32,98,108,111,98,88,32,40,48,41,44,32,13,10,32,32,32,32,32,32,32,32,98,108,111,98,89,32,40,48, - 41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,115,101,116,32,111,102,102,32,97,32,116,105,109,101,114,32,116,111,32, - 109,111,118,101,32,97,32,98,108,111,98,32,97,114,111,117,110,100,32,111,110,32,116,104,105,115,32,99,111,109,112,111,110,101,110,116,32,101,118,101, - 114,121,13,10,32,32,32,32,32,32,32,32,47,47,32,51,48,48,32,109,105,108,108,105,115,101,99,111,110,100,115,32,45,32,115,101,101,32,116,104, - 101,32,116,105,109,101,114,67,97,108,108,98,97,99,107,40,41,32,109,101,116,104,111,100,46,13,10,32,32,32,32,32,32,32,32,115,116,97,114,116, - 84,105,109,101,114,32,40,51,48,48,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,67,117,115,116,111,109,77,101,110,117,67,111, - 109,112,111,110,101,110,116,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,103,101,116,73, - 100,101,97,108,83,105,122,101,32,40,105,110,116,38,32,105,100,101,97,108,87,105,100,116,104,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,105,110,116,38,32,105,100,101,97,108,72,101,105,103,104,116,41,13,10,32,32,32,32,123,13,10,32,32,32, - 32,32,32,32,32,47,47,32,116,101,108,108,115,32,116,104,101,32,109,101,110,117,32,104,111,119,32,98,105,103,32,119,101,39,100,32,108,105,107,101, - 32,116,111,32,98,101,46,46,13,10,32,32,32,32,32,32,32,32,105,100,101,97,108,87,105,100,116,104,32,61,32,50,48,48,59,13,10,32,32,32, - 32,32,32,32,32,105,100,101,97,108,72,101,105,103,104,116,32,61,32,54,48,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105, - 100,32,112,97,105,110,116,32,40,71,114,97,112,104,105,99,115,38,32,103,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,103,46, - 102,105,108,108,65,108,108,32,40,67,111,108,111,117,114,115,58,58,121,101,108,108,111,119,46,119,105,116,104,65,108,112,104,97,32,40,48,46,51,102, - 41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,103,46,115,101,116,67,111,108,111,117,114,32,40,67,111,108,111,117,114,115,58,58,112,105,110, - 107,41,59,13,10,32,32,32,32,32,32,32,32,103,46,102,105,108,108,69,108,108,105,112,115,101,32,40,40,102,108,111,97,116,41,32,98,108,111,98, - 88,44,32,40,102,108,111,97,116,41,32,98,108,111,98,89,44,32,51,48,46,48,102,44,32,52,48,46,48,102,41,59,13,10,13,10,32,32,32,32, - 32,32,32,32,103,46,115,101,116,70,111,110,116,32,40,49,52,46,48,102,44,32,70,111,110,116,58,58,105,116,97,108,105,99,41,59,13,10,32,32, - 32,32,32,32,32,32,103,46,115,101,116,67,111,108,111,117,114,32,40,67,111,108,111,117,114,115,58,58,98,108,97,99,107,41,59,13,10,13,10,32, - 32,32,32,32,32,32,32,103,46,100,114,97,119,70,105,116,116,101,100,84,101,120,116,32,40,84,40,34,116,104,105,115,32,105,115,32,97,32,99,117, - 115,116,111,109,105,115,101,100,32,109,101,110,117,32,105,116,101,109,32,40,97,108,115,111,32,100,101,109,111,110,115,116,114,97,116,105,110,103,32,116, - 104,101,32,84,105,109,101,114,32,99,108,97,115,115,41,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,52,44,32,48,44,32,103,101,116,87,105,100,116,104,40,41,32,45,32,56,44,32,103,101,116,72,101,105,103,104,116, - 40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,74,117,115,116,105,102,105,99,97, - 116,105,111,110,58,58,99,101,110,116,114,101,100,44,32,51,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,116,105, - 109,101,114,67,97,108,108,98,97,99,107,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,98,108,111,98,88,32,61,32,82,97, - 110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,73,110,116,32,40,103,101,116,87,105,100,116, - 104,40,41,41,59,13,10,32,32,32,32,32,32,32,32,98,108,111,98,89,32,61,32,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109, - 82,97,110,100,111,109,40,41,46,110,101,120,116,73,110,116,32,40,103,101,116,72,101,105,103,104,116,40,41,41,59,13,10,32,32,32,32,32,32,32, - 32,114,101,112,97,105,110,116,40,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,47,42,42,32,84,111,32,100,101,109,111,110, - 115,116,114,97,116,101,32,104,111,119,32,115,108,105,100,101,114,115,32,99,97,110,32,104,97,118,101,32,99,117,115,116,111,109,32,115,110,97,112,112, - 105,110,103,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,105,114,32,118,97,108,117,101,115,44,13,10,32,32,32,32,116,104,105,115,32,115, - 105,109,112,108,101,32,99,108,97,115,115,32,115,110,97,112,115,32,116,104,101,32,118,97,108,117,101,32,116,111,32,53,48,32,105,102,32,105,116,32, - 99,111,109,101,115,32,110,101,97,114,46,13,10,42,47,13,10,99,108,97,115,115,32,83,110,97,112,112,105,110,103,83,108,105,100,101,114,32,32,58, - 32,112,117,98,108,105,99,32,83,108,105,100,101,114,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,83,110,97,112,112,105,110,103, - 83,108,105,100,101,114,32,40,99,111,110,115,116,32,83,116,114,105,110,103,38,32,110,97,109,101,41,13,10,32,32,32,32,32,32,32,32,58,32,83, - 108,105,100,101,114,32,40,110,97,109,101,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,100,111,117,98,108,101, - 32,115,110,97,112,86,97,108,117,101,32,40,100,111,117,98,108,101,32,97,116,116,101,109,112,116,101,100,86,97,108,117,101,44,32,99,111,110,115,116, - 32,98,111,111,108,32,117,115,101,114,73,115,68,114,97,103,103,105,110,103,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,105,102, - 32,40,33,32,117,115,101,114,73,115,68,114,97,103,103,105,110,103,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32, - 97,116,116,101,109,112,116,101,100,86,97,108,117,101,59,32,32,47,47,32,105,102,32,116,104,101,121,39,114,101,32,101,110,116,101,114,105,110,103,32, - 116,104,101,32,118,97,108,117,101,32,105,110,32,116,104,101,32,116,101,120,116,45,98,111,120,44,32,100,111,110,39,116,32,109,101,115,115,32,119,105, - 116,104,32,105,116,46,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,97,116,116,101,109,112,116,101,100,86,97,108,117,101,32,62,32,52, - 48,32,38,38,32,97,116,116,101,109,112,116,101,100,86,97,108,117,101,32,60,32,54,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,114, - 101,116,117,114,110,32,53,48,46,48,59,13,10,32,32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,114, - 101,116,117,114,110,32,97,116,116,101,109,112,116,101,100,86,97,108,117,101,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,47,42,42,32, - 65,32,84,101,120,116,66,117,116,116,111,110,32,116,104,97,116,32,112,111,112,115,32,117,112,32,97,32,99,111,108,111,117,114,32,99,104,111,111,115, - 101,114,32,116,111,32,99,104,97,110,103,101,32,105,116,115,32,99,111,108,111,117,114,115,46,32,42,47,13,10,99,108,97,115,115,32,67,111,108,111, - 117,114,67,104,97,110,103,101,66,117,116,116,111,110,32,32,58,32,112,117,98,108,105,99,32,84,101,120,116,66,117,116,116,111,110,44,13,10,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,67,104,97,110,103,101,76, - 105,115,116,101,110,101,114,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,67,111,108,111,117,114,67,104,97,110,103,101,66,117,116, - 116,111,110,40,41,13,10,32,32,32,32,32,32,32,32,58,32,84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,99,108,105,99,107,32,116,111, - 32,99,104,97,110,103,101,32,99,111,108,111,117,114,46,46,46,34,41,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,101,116, - 83,105,122,101,32,40,49,48,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,99,104,97,110,103,101,87,105,100,116,104,84,111,70,105,116, - 84,101,120,116,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,67,111,108,111,117,114,67,104,97,110,103,101,66,117,116,116,111, - 110,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,99,108,105,99,107,101,100,40,41,13, - 10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,99,114,101,97,116,101,32,116,119,111,32,99,111,108,111,117,114,32,115,101,108, - 101,99,116,111,114,32,99,111,109,112,111,110,101,110,116,115,32,102,111,114,32,111,117,114,32,98,97,99,107,103,114,111,117,110,100,32,97,110,100,13, - 10,32,32,32,32,32,32,32,32,47,47,32,116,101,120,116,32,99,111,108,111,117,114,46,46,13,10,32,32,32,32,32,32,32,32,67,111,108,111,117, - 114,83,101,108,101,99,116,111,114,32,99,111,108,111,117,114,83,101,108,101,99,116,111,114,49,59,13,10,32,32,32,32,32,32,32,32,99,111,108,111, - 117,114,83,101,108,101,99,116,111,114,49,46,115,101,116,78,97,109,101,32,40,84,40,34,98,97,99,107,103,114,111,117,110,100,34,41,41,59,13,10, - 32,32,32,32,32,32,32,32,99,111,108,111,117,114,83,101,108,101,99,116,111,114,49,46,115,101,116,67,117,114,114,101,110,116,67,111,108,111,117,114, - 32,40,102,105,110,100,67,111,108,111,117,114,32,40,84,101,120,116,66,117,116,116,111,110,58,58,98,117,116,116,111,110,67,111,108,111,117,114,73,100, - 41,41,59,13,10,32,32,32,32,32,32,32,32,99,111,108,111,117,114,83,101,108,101,99,116,111,114,49,46,97,100,100,67,104,97,110,103,101,76,105, - 115,116,101,110,101,114,32,40,116,104,105,115,41,59,13,10,13,10,32,32,32,32,32,32,32,32,67,111,108,111,117,114,83,101,108,101,99,116,111,114, - 32,99,111,108,111,117,114,83,101,108,101,99,116,111,114,50,59,13,10,32,32,32,32,32,32,32,32,99,111,108,111,117,114,83,101,108,101,99,116,111, - 114,50,46,115,101,116,78,97,109,101,32,40,84,40,34,116,101,120,116,34,41,41,59,13,10,32,32,32,32,32,32,32,32,99,111,108,111,117,114,83, - 101,108,101,99,116,111,114,50,46,115,101,116,67,117,114,114,101,110,116,67,111,108,111,117,114,32,40,102,105,110,100,67,111,108,111,117,114,32,40,84, - 101,120,116,66,117,116,116,111,110,58,58,116,101,120,116,67,111,108,111,117,114,73,100,41,41,59,13,10,32,32,32,32,32,32,32,32,99,111,108,111, - 117,114,83,101,108,101,99,116,111,114,50,46,97,100,100,67,104,97,110,103,101,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,13,10,13, - 10,32,32,32,32,32,32,32,32,47,47,32,97,110,100,32,97,100,100,32,116,104,101,32,115,101,108,101,99,116,111,114,115,32,97,115,32,99,117,115, - 116,111,109,32,109,101,110,117,32,105,116,101,109,115,32,116,111,32,97,32,80,111,112,117,112,77,101,110,117,44,32,112,117,116,116,105,110,103,13,10, - 32,32,32,32,32,32,32,32,47,47,32,116,104,101,109,32,105,110,32,116,119,111,32,100,105,102,102,101,114,101,110,116,32,115,117,98,45,109,101,110, - 117,115,46,46,13,10,32,32,32,32,32,32,32,32,80,111,112,117,112,77,101,110,117,32,109,44,32,115,117,98,49,44,32,115,117,98,50,59,13,10, - 13,10,32,32,32,32,32,32,32,32,115,117,98,49,46,97,100,100,67,117,115,116,111,109,73,116,101,109,32,40,49,50,51,52,44,32,38,99,111,108, - 111,117,114,83,101,108,101,99,116,111,114,49,44,32,51,48,48,44,32,51,48,48,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32, - 32,109,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,98,97,99,107,103,114,111,117,110,100,32,99,111,108,111,117,114,34,41,44,32,115, - 117,98,49,41,59,13,10,13,10,32,32,32,32,32,32,32,32,115,117,98,50,46,97,100,100,67,117,115,116,111,109,73,116,101,109,32,40,49,50,51, - 52,44,32,38,99,111,108,111,117,114,83,101,108,101,99,116,111,114,50,44,32,51,48,48,44,32,51,48,48,44,32,102,97,108,115,101,41,59,13,10, - 32,32,32,32,32,32,32,32,109,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,116,101,120,116,32,99,111,108,111,117,114,34,41,44,32, - 115,117,98,50,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,97,110,100,32,115,104,111,119,32,116,104,101,32,109,101,110,117,32,40, - 109,111,100,97,108,108,121,41,46,46,13,10,32,32,32,32,32,32,32,32,109,46,115,104,111,119,65,116,32,40,116,104,105,115,41,59,13,10,32,32, - 32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,99,104,97,110,103,101,76,105,115,116,101,110,101,114,67,97,108,108,98,97,99,107,32,40, - 118,111,105,100,42,32,115,111,117,114,99,101,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,67,111,108,111,117,114,83,101,108,101, - 99,116,111,114,42,32,99,115,32,61,32,40,67,111,108,111,117,114,83,101,108,101,99,116,111,114,42,41,32,115,111,117,114,99,101,59,13,10,13,10, - 32,32,32,32,32,32,32,32,105,102,32,40,99,115,45,62,103,101,116,78,97,109,101,40,41,32,61,61,32,84,40,34,116,101,120,116,34,41,41,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,115,101,116,67,111,108,111,117,114,32,40,84,101,120,116,66,117,116,116,111,110,58,58,116,101,120,116, - 67,111,108,111,117,114,73,100,44,32,99,115,45,62,103,101,116,67,117,114,114,101,110,116,67,111,108,111,117,114,40,41,41,59,13,10,32,32,32,32, - 32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,101,116,67,111,108,111,117,114,32,40,84,101,120,116,66,117,116, - 116,111,110,58,58,98,117,116,116,111,110,67,111,108,111,117,114,73,100,44,32,99,115,45,62,103,101,116,67,117,114,114,101,110,116,67,111,108,111,117, - 114,40,41,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 41,13,10,32,32,32,32,32,32,32,32,58,32,98,108,111,98,88,32,40,48,41,44,13,10,32,32,32,32,32,32,32,32,32,32,98,108,111,98,89, + 32,40,48,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,115,101,116,32,111,102,102,32,97,32,116,105,109,101,114,32, + 116,111,32,109,111,118,101,32,97,32,98,108,111,98,32,97,114,111,117,110,100,32,111,110,32,116,104,105,115,32,99,111,109,112,111,110,101,110,116,32, + 101,118,101,114,121,13,10,32,32,32,32,32,32,32,32,47,47,32,51,48,48,32,109,105,108,108,105,115,101,99,111,110,100,115,32,45,32,115,101,101, + 32,116,104,101,32,116,105,109,101,114,67,97,108,108,98,97,99,107,40,41,32,109,101,116,104,111,100,46,13,10,32,32,32,32,32,32,32,32,115,116, + 97,114,116,84,105,109,101,114,32,40,51,48,48,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,67,117,115,116,111,109,77,101,110, + 117,67,111,109,112,111,110,101,110,116,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,103, + 101,116,73,100,101,97,108,83,105,122,101,32,40,105,110,116,38,32,105,100,101,97,108,87,105,100,116,104,44,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,110,116,38,32,105,100,101,97,108,72,101,105,103,104,116,41,13,10,32,32,32,32,123,13,10, + 32,32,32,32,32,32,32,32,47,47,32,116,101,108,108,115,32,116,104,101,32,109,101,110,117,32,104,111,119,32,98,105,103,32,119,101,39,100,32,108, + 105,107,101,32,116,111,32,98,101,46,46,13,10,32,32,32,32,32,32,32,32,105,100,101,97,108,87,105,100,116,104,32,61,32,50,48,48,59,13,10, + 32,32,32,32,32,32,32,32,105,100,101,97,108,72,101,105,103,104,116,32,61,32,54,48,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32, + 118,111,105,100,32,112,97,105,110,116,32,40,71,114,97,112,104,105,99,115,38,32,103,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32, + 32,103,46,102,105,108,108,65,108,108,32,40,67,111,108,111,117,114,115,58,58,121,101,108,108,111,119,46,119,105,116,104,65,108,112,104,97,32,40,48, + 46,51,102,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,103,46,115,101,116,67,111,108,111,117,114,32,40,67,111,108,111,117,114,115,58,58, + 112,105,110,107,41,59,13,10,32,32,32,32,32,32,32,32,103,46,102,105,108,108,69,108,108,105,112,115,101,32,40,40,102,108,111,97,116,41,32,98, + 108,111,98,88,44,32,40,102,108,111,97,116,41,32,98,108,111,98,89,44,32,51,48,46,48,102,44,32,52,48,46,48,102,41,59,13,10,13,10,32, + 32,32,32,32,32,32,32,103,46,115,101,116,70,111,110,116,32,40,49,52,46,48,102,44,32,70,111,110,116,58,58,105,116,97,108,105,99,41,59,13, + 10,32,32,32,32,32,32,32,32,103,46,115,101,116,67,111,108,111,117,114,32,40,67,111,108,111,117,114,115,58,58,98,108,97,99,107,41,59,13,10, + 13,10,32,32,32,32,32,32,32,32,103,46,100,114,97,119,70,105,116,116,101,100,84,101,120,116,32,40,84,40,34,116,104,105,115,32,105,115,32,97, + 32,99,117,115,116,111,109,105,115,101,100,32,109,101,110,117,32,105,116,101,109,32,40,97,108,115,111,32,100,101,109,111,110,115,116,114,97,116,105,110, + 103,32,116,104,101,32,84,105,109,101,114,32,99,108,97,115,115,41,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,52,44,32,48,44,32,103,101,116,87,105,100,116,104,40,41,32,45,32,56,44,32,103,101,116,72,101,105, + 103,104,116,40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,74,117,115,116,105,102, + 105,99,97,116,105,111,110,58,58,99,101,110,116,114,101,100,44,32,51,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100, + 32,116,105,109,101,114,67,97,108,108,98,97,99,107,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,98,108,111,98,88,32,61, + 32,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,73,110,116,32,40,103,101,116,87, + 105,100,116,104,40,41,41,59,13,10,32,32,32,32,32,32,32,32,98,108,111,98,89,32,61,32,82,97,110,100,111,109,58,58,103,101,116,83,121,115, + 116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,73,110,116,32,40,103,101,116,72,101,105,103,104,116,40,41,41,59,13,10,32,32,32,32, + 32,32,32,32,114,101,112,97,105,110,116,40,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,47,47,32,106,117,115,116,32,97,32,99,111,109,112,111,110,101,110, - 116,32,116,104,97,116,32,100,101,108,101,116,101,115,32,97,108,108,32,105,116,115,32,99,104,105,108,100,114,101,110,44,32,116,111,32,117,115,101,32, - 102,111,114,32,116,104,101,32,116,97,98,98,101,100,32,112,97,103,101,115,32,116,111,32,97,118,111,105,100,13,10,47,47,32,109,101,109,111,114,121, - 32,108,101,97,107,115,32,119,104,101,110,32,116,104,101,121,39,114,101,32,100,101,108,101,116,101,100,13,10,99,108,97,115,115,32,68,101,109,111,80, - 97,103,101,67,111,109,112,32,32,58,32,112,117,98,108,105,99,32,67,111,109,112,111,110,101,110,116,13,10,123,13,10,112,117,98,108,105,99,58,13, - 10,32,32,32,32,68,101,109,111,80,97,103,101,67,111,109,112,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32, - 32,126,68,101,109,111,80,97,103,101,67,111,109,112,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65, - 108,108,67,104,105,108,100,114,101,110,40,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,47,42,42,32,84,111,32,100,101, + 109,111,110,115,116,114,97,116,101,32,104,111,119,32,115,108,105,100,101,114,115,32,99,97,110,32,104,97,118,101,32,99,117,115,116,111,109,32,115,110, + 97,112,112,105,110,103,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,105,114,32,118,97,108,117,101,115,44,13,10,32,32,32,32,116,104,105, + 115,32,115,105,109,112,108,101,32,99,108,97,115,115,32,115,110,97,112,115,32,116,104,101,32,118,97,108,117,101,32,116,111,32,53,48,32,105,102,32, + 105,116,32,99,111,109,101,115,32,110,101,97,114,46,13,10,42,47,13,10,99,108,97,115,115,32,83,110,97,112,112,105,110,103,83,108,105,100,101,114, + 32,32,58,32,112,117,98,108,105,99,32,83,108,105,100,101,114,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,83,110,97,112,112, + 105,110,103,83,108,105,100,101,114,32,40,99,111,110,115,116,32,83,116,114,105,110,103,38,32,110,97,109,101,41,13,10,32,32,32,32,32,32,32,32, + 58,32,83,108,105,100,101,114,32,40,110,97,109,101,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,100,111,117, + 98,108,101,32,115,110,97,112,86,97,108,117,101,32,40,100,111,117,98,108,101,32,97,116,116,101,109,112,116,101,100,86,97,108,117,101,44,32,99,111, + 110,115,116,32,98,111,111,108,32,117,115,101,114,73,115,68,114,97,103,103,105,110,103,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32, + 32,105,102,32,40,33,32,117,115,101,114,73,115,68,114,97,103,103,105,110,103,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117, + 114,110,32,97,116,116,101,109,112,116,101,100,86,97,108,117,101,59,32,32,47,47,32,105,102,32,116,104,101,121,39,114,101,32,101,110,116,101,114,105, + 110,103,32,116,104,101,32,118,97,108,117,101,32,105,110,32,116,104,101,32,116,101,120,116,45,98,111,120,44,32,100,111,110,39,116,32,109,101,115,115, + 32,119,105,116,104,32,105,116,46,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,97,116,116,101,109,112,116,101,100,86,97,108,117,101,32, + 62,32,52,48,32,38,38,32,97,116,116,101,109,112,116,101,100,86,97,108,117,101,32,60,32,54,48,41,13,10,32,32,32,32,32,32,32,32,32,32, + 32,32,114,101,116,117,114,110,32,53,48,46,48,59,13,10,32,32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32, + 32,32,114,101,116,117,114,110,32,97,116,116,101,109,112,116,101,100,86,97,108,117,101,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,47, + 42,42,32,65,32,84,101,120,116,66,117,116,116,111,110,32,116,104,97,116,32,112,111,112,115,32,117,112,32,97,32,99,111,108,111,117,114,32,99,104, + 111,111,115,101,114,32,116,111,32,99,104,97,110,103,101,32,105,116,115,32,99,111,108,111,117,114,115,46,32,42,47,13,10,99,108,97,115,115,32,67, + 111,108,111,117,114,67,104,97,110,103,101,66,117,116,116,111,110,32,32,58,32,112,117,98,108,105,99,32,84,101,120,116,66,117,116,116,111,110,44,13, + 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,67,104,97,110, + 103,101,76,105,115,116,101,110,101,114,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,67,111,108,111,117,114,67,104,97,110,103,101, + 66,117,116,116,111,110,40,41,13,10,32,32,32,32,32,32,32,32,58,32,84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,99,108,105,99,107, + 32,116,111,32,99,104,97,110,103,101,32,99,111,108,111,117,114,46,46,46,34,41,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32, + 115,101,116,83,105,122,101,32,40,49,48,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,99,104,97,110,103,101,87,105,100,116,104,84,111, + 70,105,116,84,101,120,116,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,67,111,108,111,117,114,67,104,97,110,103,101,66,117, + 116,116,111,110,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,99,108,105,99,107,101,100, + 40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,99,114,101,97,116,101,32,116,119,111,32,99,111,108,111,117,114,32, + 115,101,108,101,99,116,111,114,32,99,111,109,112,111,110,101,110,116,115,32,102,111,114,32,111,117,114,32,98,97,99,107,103,114,111,117,110,100,32,97, + 110,100,13,10,32,32,32,32,32,32,32,32,47,47,32,116,101,120,116,32,99,111,108,111,117,114,46,46,13,10,32,32,32,32,32,32,32,32,67,111, + 108,111,117,114,83,101,108,101,99,116,111,114,32,99,111,108,111,117,114,83,101,108,101,99,116,111,114,49,59,13,10,32,32,32,32,32,32,32,32,99, + 111,108,111,117,114,83,101,108,101,99,116,111,114,49,46,115,101,116,78,97,109,101,32,40,84,40,34,98,97,99,107,103,114,111,117,110,100,34,41,41, + 59,13,10,32,32,32,32,32,32,32,32,99,111,108,111,117,114,83,101,108,101,99,116,111,114,49,46,115,101,116,67,117,114,114,101,110,116,67,111,108, + 111,117,114,32,40,102,105,110,100,67,111,108,111,117,114,32,40,84,101,120,116,66,117,116,116,111,110,58,58,98,117,116,116,111,110,67,111,108,111,117, + 114,73,100,41,41,59,13,10,32,32,32,32,32,32,32,32,99,111,108,111,117,114,83,101,108,101,99,116,111,114,49,46,97,100,100,67,104,97,110,103, + 101,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,13,10,13,10,32,32,32,32,32,32,32,32,67,111,108,111,117,114,83,101,108,101,99, + 116,111,114,32,99,111,108,111,117,114,83,101,108,101,99,116,111,114,50,59,13,10,32,32,32,32,32,32,32,32,99,111,108,111,117,114,83,101,108,101, + 99,116,111,114,50,46,115,101,116,78,97,109,101,32,40,84,40,34,116,101,120,116,34,41,41,59,13,10,32,32,32,32,32,32,32,32,99,111,108,111, + 117,114,83,101,108,101,99,116,111,114,50,46,115,101,116,67,117,114,114,101,110,116,67,111,108,111,117,114,32,40,102,105,110,100,67,111,108,111,117,114, + 32,40,84,101,120,116,66,117,116,116,111,110,58,58,116,101,120,116,67,111,108,111,117,114,73,100,41,41,59,13,10,32,32,32,32,32,32,32,32,99, + 111,108,111,117,114,83,101,108,101,99,116,111,114,50,46,97,100,100,67,104,97,110,103,101,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59, + 13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,97,110,100,32,97,100,100,32,116,104,101,32,115,101,108,101,99,116,111,114,115,32,97,115,32, + 99,117,115,116,111,109,32,109,101,110,117,32,105,116,101,109,115,32,116,111,32,97,32,80,111,112,117,112,77,101,110,117,44,32,112,117,116,116,105,110, + 103,13,10,32,32,32,32,32,32,32,32,47,47,32,116,104,101,109,32,105,110,32,116,119,111,32,100,105,102,102,101,114,101,110,116,32,115,117,98,45, + 109,101,110,117,115,46,46,13,10,32,32,32,32,32,32,32,32,80,111,112,117,112,77,101,110,117,32,109,44,32,115,117,98,49,44,32,115,117,98,50, + 59,13,10,13,10,32,32,32,32,32,32,32,32,115,117,98,49,46,97,100,100,67,117,115,116,111,109,73,116,101,109,32,40,49,50,51,52,44,32,38, + 99,111,108,111,117,114,83,101,108,101,99,116,111,114,49,44,32,51,48,48,44,32,51,48,48,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32, + 32,32,32,32,109,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,98,97,99,107,103,114,111,117,110,100,32,99,111,108,111,117,114,34,41, + 44,32,115,117,98,49,41,59,13,10,13,10,32,32,32,32,32,32,32,32,115,117,98,50,46,97,100,100,67,117,115,116,111,109,73,116,101,109,32,40, + 49,50,51,52,44,32,38,99,111,108,111,117,114,83,101,108,101,99,116,111,114,50,44,32,51,48,48,44,32,51,48,48,44,32,102,97,108,115,101,41, + 59,13,10,32,32,32,32,32,32,32,32,109,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,116,101,120,116,32,99,111,108,111,117,114,34, + 41,44,32,115,117,98,50,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,97,110,100,32,115,104,111,119,32,116,104,101,32,109,101,110, + 117,32,40,109,111,100,97,108,108,121,41,46,46,13,10,32,32,32,32,32,32,32,32,109,46,115,104,111,119,65,116,32,40,116,104,105,115,41,59,13, + 10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,99,104,97,110,103,101,76,105,115,116,101,110,101,114,67,97,108,108,98,97,99, + 107,32,40,118,111,105,100,42,32,115,111,117,114,99,101,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,67,111,108,111,117,114,83, + 101,108,101,99,116,111,114,42,32,99,115,32,61,32,40,67,111,108,111,117,114,83,101,108,101,99,116,111,114,42,41,32,115,111,117,114,99,101,59,13, + 10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,99,115,45,62,103,101,116,78,97,109,101,40,41,32,61,61,32,84,40,34,116,101,120,116,34, + 41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,101,116,67,111,108,111,117,114,32,40,84,101,120,116,66,117,116,116,111,110,58,58,116, + 101,120,116,67,111,108,111,117,114,73,100,44,32,99,115,45,62,103,101,116,67,117,114,114,101,110,116,67,111,108,111,117,114,40,41,41,59,13,10,32, + 32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,101,116,67,111,108,111,117,114,32,40,84,101,120,116, + 66,117,116,116,111,110,58,58,98,117,116,116,111,110,67,111,108,111,117,114,73,100,44,32,99,115,45,62,103,101,116,67,117,114,114,101,110,116,67,111, + 108,111,117,114,40,41,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,115,116,97,116,105,99,32,67,111,109, - 112,111,110,101,110,116,42,32,99,114,101,97,116,101,83,108,105,100,101,114,115,80,97,103,101,40,41,13,10,123,13,10,32,32,32,32,68,101,109,111, - 80,97,103,101,67,111,109,112,42,32,112,97,103,101,32,61,32,110,101,119,32,68,101,109,111,80,97,103,101,67,111,109,112,40,41,59,13,10,13,10, - 32,32,32,32,99,111,110,115,116,32,105,110,116,32,110,117,109,83,108,105,100,101,114,115,32,61,32,49,49,59,13,10,32,32,32,32,83,108,105,100, - 101,114,42,32,115,108,105,100,101,114,115,32,91,110,117,109,83,108,105,100,101,114,115,93,59,13,10,13,10,32,32,32,32,105,110,116,32,105,59,13, - 10,32,32,32,32,102,111,114,32,40,105,32,61,32,48,59,32,105,32,60,32,110,117,109,83,108,105,100,101,114,115,59,32,43,43,105,41,13,10,32, - 32,32,32,123,13,10,32,32,32,32,32,32,32,32,105,102,32,40,105,32,61,61,32,50,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,112, - 97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,115,108,105,100,101,114,115,91,105,93,32,61,32,110,101,119, - 32,83,110,97,112,112,105,110,103,83,108,105,100,101,114,32,40,84,40,34,115,108,105,100,101,114,34,41,41,41,59,13,10,32,32,32,32,32,32,32, - 32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98, - 108,101,32,40,115,108,105,100,101,114,115,91,105,93,32,61,32,110,101,119,32,83,108,105,100,101,114,32,40,84,40,34,115,108,105,100,101,114,34,41, - 41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,115,108,105,100,101,114,115,91,105,93,45,62,115,101,116,82,97,110,103,101,32,40,48,46,48, - 44,32,49,48,48,46,48,44,32,48,46,49,41,59,13,10,32,32,32,32,32,32,32,32,115,108,105,100,101,114,115,91,105,93,45,62,115,101,116,80, - 111,112,117,112,77,101,110,117,69,110,97,98,108,101,100,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,115,108,105,100,101,114,115, - 91,105,93,45,62,115,101,116,86,97,108,117,101,32,40,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41, - 46,110,101,120,116,68,111,117,98,108,101,40,41,32,42,32,49,48,48,46,48,44,32,102,97,108,115,101,44,32,102,97,108,115,101,41,59,13,10,32, - 32,32,32,125,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,48,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40, - 83,108,105,100,101,114,58,58,76,105,110,101,97,114,86,101,114,116,105,99,97,108,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,48,93, - 45,62,115,101,116,84,101,120,116,66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84,101,120,116,66,111,120,66,101,108,111,119,44, - 32,102,97,108,115,101,44,32,49,48,48,44,32,50,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,48,93,45,62,115,101,116,66,111, - 117,110,100,115,32,40,49,48,44,32,50,53,44,32,55,48,44,32,50,48,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,48,93,45, - 62,115,101,116,68,111,117,98,108,101,67,108,105,99,107,82,101,116,117,114,110,86,97,108,117,101,32,40,116,114,117,101,44,32,53,48,46,48,41,59, - 32,47,47,32,100,111,117,98,108,101,45,99,108,105,99,107,105,110,103,32,116,104,105,115,32,115,108,105,100,101,114,32,119,105,108,108,32,115,101,116, - 32,105,116,32,116,111,32,53,48,46,48,13,10,32,32,32,32,115,108,105,100,101,114,115,91,48,93,45,62,115,101,116,84,101,120,116,86,97,108,117, - 101,83,117,102,102,105,120,32,40,84,40,34,32,117,110,105,116,115,34,41,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,93, - 45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,76,105,110,101,97,114,86,101,114,116,105,99,97,108, - 41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,93,45,62,115,101,116,86,101,108,111,99,105,116,121,66,97,115,101,100,77,111,100,101, - 32,40,116,114,117,101,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,93,45,62,115,101,116,83,107,101,119,70,97,99,116,111,114,32, - 40,48,46,53,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,93,45,62,115,101,116,84,101,120,116,66,111,120,83,116,121,108,101,32, - 40,83,108,105,100,101,114,58,58,84,101,120,116,66,111,120,65,98,111,118,101,44,32,116,114,117,101,44,32,49,48,48,44,32,50,48,41,59,13,10, - 32,32,32,32,115,108,105,100,101,114,115,91,49,93,45,62,115,101,116,66,111,117,110,100,115,32,40,56,53,44,32,50,53,44,32,55,48,44,32,50, - 48,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,93,45,62,115,101,116,84,101,120,116,86,97,108,117,101,83,117,102,102,105,120, - 32,40,84,40,34,32,114,101,108,115,34,41,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,50,93,45,62,115,101,116,83,108,105, - 100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,76,105,110,101,97,114,72,111,114,105,122,111,110,116,97,108,41,59,13,10,32,32, - 32,32,115,108,105,100,101,114,115,91,50,93,45,62,115,101,116,84,101,120,116,66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84, - 101,120,116,66,111,120,76,101,102,116,44,32,102,97,108,115,101,44,32,56,48,44,32,50,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115, - 91,50,93,45,62,115,101,116,66,111,117,110,100,115,32,40,49,56,48,44,32,51,53,44,32,49,53,48,44,32,50,48,41,59,13,10,13,10,32,32, - 32,32,115,108,105,100,101,114,115,91,51,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,76,105, - 110,101,97,114,72,111,114,105,122,111,110,116,97,108,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,51,93,45,62,115,101,116,84,101,120, - 116,66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,78,111,84,101,120,116,66,111,120,44,32,102,97,108,115,101,44,32,48,44,32, - 48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,51,93,45,62,115,101,116,66,111,117,110,100,115,32,40,49,56,48,44,32,54,53,44, - 32,49,53,48,44,32,50,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,51,93,45,62,115,101,116,80,111,112,117,112,68,105,115,112, - 108,97,121,69,110,97,98,108,101,100,32,40,116,114,117,101,44,32,112,97,103,101,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,51,93, - 45,62,115,101,116,84,101,120,116,86,97,108,117,101,83,117,102,102,105,120,32,40,84,40,34,32,110,117,110,115,32,114,101,113,117,105,114,101,100,32, - 116,111,32,99,104,97,110,103,101,32,97,32,108,105,103,104,116,98,117,108,98,34,41,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115, - 91,52,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,73,110,99,68,101,99,66,117,116,116,111, - 110,115,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,52,93,45,62,115,101,116,84,101,120,116,66,111,120,83,116,121,108,101,32,40,83, - 108,105,100,101,114,58,58,84,101,120,116,66,111,120,76,101,102,116,44,32,102,97,108,115,101,44,32,53,48,44,32,50,48,41,59,13,10,32,32,32, - 32,115,108,105,100,101,114,115,91,52,93,45,62,115,101,116,66,111,117,110,100,115,32,40,49,56,48,44,32,49,48,53,44,32,49,48,48,44,32,50, - 48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,52,93,45,62,115,101,116,73,110,99,68,101,99,66,117,116,116,111,110,115,77,111,100, - 101,32,40,83,108,105,100,101,114,58,58,105,110,99,68,101,99,66,117,116,116,111,110,115,68,114,97,103,103,97,98,108,101,95,86,101,114,116,105,99, - 97,108,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,53,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40, - 83,108,105,100,101,114,58,58,82,111,116,97,114,121,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,53,93,45,62,115,101,116,82,111,116, - 97,114,121,80,97,114,97,109,101,116,101,114,115,32,40,102,108,111,97,116,95,80,105,32,42,32,49,46,50,102,44,32,102,108,111,97,116,95,80,105, - 32,42,32,50,46,56,102,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,53,93,45,62,115,101,116,84,101,120, - 116,66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84,101,120,116,66,111,120,82,105,103,104,116,44,32,102,97,108,115,101,44,32, - 55,48,44,32,50,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,53,93,45,62,115,101,116,66,111,117,110,100,115,32,40,49,57,48, - 44,32,49,52,53,44,32,49,50,48,44,32,52,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,53,93,45,62,115,101,116,84,101,120, - 116,86,97,108,117,101,83,117,102,102,105,120,32,40,84,40,34,32,109,109,34,41,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91, - 54,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,76,105,110,101,97,114,66,97,114,41,59,13, - 10,32,32,32,32,115,108,105,100,101,114,115,91,54,93,45,62,115,101,116,66,111,117,110,100,115,32,40,49,56,48,44,32,49,57,53,44,32,49,48, - 48,44,32,51,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,54,93,45,62,115,101,116,84,101,120,116,86,97,108,117,101,83,117,102, - 102,105,120,32,40,84,40,34,32,103,97,108,108,111,110,115,34,41,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,55,93,45,62, - 115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84,119,111,86,97,108,117,101,72,111,114,105,122,111,110,116, - 97,108,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,55,93,45,62,115,101,116,66,111,117,110,100,115,32,40,51,54,48,44,32,50,48, - 44,32,49,54,48,44,32,52,48,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,56,93,45,62,115,101,116,83,108,105,100,101,114, - 83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84,119,111,86,97,108,117,101,86,101,114,116,105,99,97,108,41,59,13,10,32,32,32,32,115, - 108,105,100,101,114,115,91,56,93,45,62,115,101,116,66,111,117,110,100,115,32,40,51,54,48,44,32,49,49,48,44,32,52,48,44,32,49,54,48,41, - 59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,57,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105, - 100,101,114,58,58,84,104,114,101,101,86,97,108,117,101,72,111,114,105,122,111,110,116,97,108,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115, - 91,57,93,45,62,115,101,116,66,111,117,110,100,115,32,40,51,54,48,44,32,55,48,44,32,49,54,48,44,32,52,48,41,59,13,10,13,10,32,32, - 32,32,115,108,105,100,101,114,115,91,49,48,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84, - 104,114,101,101,86,97,108,117,101,86,101,114,116,105,99,97,108,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,48,93,45,62,115,101, - 116,66,111,117,110,100,115,32,40,52,52,48,44,32,49,49,48,44,32,52,48,44,32,49,54,48,41,59,13,10,13,10,32,32,32,32,102,111,114,32, - 40,105,32,61,32,55,59,32,105,32,60,61,32,49,48,59,32,43,43,105,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,108, - 105,100,101,114,115,91,105,93,45,62,115,101,116,84,101,120,116,66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,78,111,84,101,120, - 116,66,111,120,44,32,102,97,108,115,101,44,32,48,44,32,48,41,59,13,10,32,32,32,32,32,32,32,32,115,108,105,100,101,114,115,91,105,93,45, - 62,115,101,116,77,105,110,86,97,108,117,101,32,40,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46, - 110,101,120,116,68,111,117,98,108,101,40,41,32,42,32,49,48,48,46,48,44,32,102,97,108,115,101,44,32,102,97,108,115,101,41,59,13,10,32,32, - 32,32,32,32,32,32,115,108,105,100,101,114,115,91,105,93,45,62,115,101,116,77,97,120,86,97,108,117,101,32,40,82,97,110,100,111,109,58,58,103, - 101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,68,111,117,98,108,101,40,41,32,42,32,49,48,48,46,48,44,32,102, - 97,108,115,101,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32,32,115,108,105,100,101,114,115,91,105,93,45,62,115,101,116,80,111, - 112,117,112,68,105,115,112,108,97,121,69,110,97,98,108,101,100,32,40,116,114,117,101,44,32,112,97,103,101,41,59,13,10,32,32,32,32,125,13,10, - 13,10,32,32,32,32,76,97,98,101,108,42,32,108,97,98,101,108,32,61,32,110,101,119,32,76,97,98,101,108,32,40,84,40,34,104,105,110,116,34, - 41,44,32,84,40,34,84,114,121,32,114,105,103,104,116,45,99,108,105,99,107,105,110,103,32,111,110,32,97,32,115,108,105,100,101,114,32,102,111,114, - 32,97,110,32,111,112,116,105,111,110,115,32,109,101,110,117,46,32,92,110,92,110,65,108,115,111,44,32,104,111,108,100,105,110,103,32,100,111,119,110, - 32,67,84,82,76,32,119,104,105,108,101,32,100,114,97,103,103,105,110,103,32,119,105,108,108,32,116,117,114,110,32,111,110,32,97,32,115,108,105,100, - 101,114,39,115,32,118,101,108,111,99,105,116,121,45,115,101,110,115,105,116,105,118,101,32,109,111,100,101,34,41,41,59,13,10,32,32,32,32,108,97, - 98,101,108,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,44,32,50,52,53,44,32,51,53,48,44,32,49,53,48,41,59,13,10,32,32,32, - 32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,108,97,98,101,108,41,59,13,10,13,10,32,32,32, - 32,114,101,116,117,114,110,32,112,97,103,101,59,13,10,125,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,47,47,32,106,117,115,116,32,97,32,99,111,109,112,111, + 110,101,110,116,32,116,104,97,116,32,100,101,108,101,116,101,115,32,97,108,108,32,105,116,115,32,99,104,105,108,100,114,101,110,44,32,116,111,32,117, + 115,101,32,102,111,114,32,116,104,101,32,116,97,98,98,101,100,32,112,97,103,101,115,32,116,111,32,97,118,111,105,100,13,10,47,47,32,109,101,109, + 111,114,121,32,108,101,97,107,115,32,119,104,101,110,32,116,104,101,121,39,114,101,32,100,101,108,101,116,101,100,13,10,99,108,97,115,115,32,68,101, + 109,111,80,97,103,101,67,111,109,112,32,32,58,32,112,117,98,108,105,99,32,67,111,109,112,111,110,101,110,116,13,10,123,13,10,112,117,98,108,105, + 99,58,13,10,32,32,32,32,68,101,109,111,80,97,103,101,67,111,109,112,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10, + 32,32,32,32,126,68,101,109,111,80,97,103,101,67,111,109,112,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,100,101,108,101, + 116,101,65,108,108,67,104,105,108,100,114,101,110,40,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,47,47,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,115,116,97,116,105,99,32,67,111,109,112,111,110,101,110,116,42,32, - 99,114,101,97,116,101,82,97,100,105,111,66,117,116,116,111,110,80,97,103,101,40,41,13,10,123,13,10,32,32,32,32,68,101,109,111,80,97,103,101, - 67,111,109,112,42,32,112,97,103,101,32,61,32,110,101,119,32,68,101,109,111,80,97,103,101,67,111,109,112,40,41,59,13,10,13,10,32,32,32,32, - 71,114,111,117,112,67,111,109,112,111,110,101,110,116,42,32,103,114,111,117,112,32,61,32,110,101,119,32,71,114,111,117,112,67,111,109,112,111,110,101, - 110,116,32,40,84,40,34,103,114,111,117,112,34,41,44,32,84,40,34,114,97,100,105,111,32,98,117,116,116,111,110,115,34,41,41,59,13,10,32,32, - 32,32,103,114,111,117,112,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,44,32,50,48,44,32,50,50,48,44,32,49,52,48,41,59,13,10, - 32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,103,114,111,117,112,41,59,13,10,13,10, - 32,32,32,32,105,110,116,32,105,59,13,10,32,32,32,32,102,111,114,32,40,105,32,61,32,48,59,32,105,32,60,32,52,59,32,43,43,105,41,13, - 10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,84,111,103,103,108,101,66,117,116,116,111,110,42,32,116,98,32,61,32,110,101,119,32,84, - 111,103,103,108,101,66,117,116,116,111,110,32,40,84,40,34,114,97,100,105,111,32,98,117,116,116,111,110,32,35,34,41,32,43,32,83,116,114,105,110, - 103,32,40,105,32,43,32,49,41,41,59,13,10,32,32,32,32,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115, - 105,98,108,101,32,40,116,98,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,82,97,100,105,111,71,114,111,117,112,73,100,32, - 40,49,50,51,52,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,66,111,117,110,100,115,32,40,52,53,44,32,52,54,32,43, - 32,105,32,42,32,50,50,44,32,49,56,48,44,32,50,50,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,84,111,111,108,116, - 105,112,32,40,84,40,34,97,32,115,101,116,32,111,102,32,109,117,116,117,97,108,108,121,45,101,120,99,108,117,115,105,118,101,32,114,97,100,105,111, - 32,98,117,116,116,111,110,115,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,105,32,61,61,32,48,41,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,84,111,103,103,108,101,83,116,97,116,101,32,40,116,114,117,101,44,32,102,97,108,115,101, - 41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,102,111,114,32,40,105,32,61,32,48,59,32,105,32,60,32,52,59,32,43,43,105,41, - 13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,68,114,97,119,97,98,108,101,80,97,116,104,32,110,111,114,109,97,108,44,32,111,118, - 101,114,59,13,10,13,10,32,32,32,32,32,32,32,32,80,97,116,104,32,112,59,13,10,32,32,32,32,32,32,32,32,112,46,97,100,100,83,116,97, - 114,32,40,48,46,48,102,44,32,48,46,48,102,44,32,105,32,43,32,53,44,32,50,48,46,48,102,44,32,53,48,46,48,102,44,32,45,48,46,50, - 102,41,59,13,10,32,32,32,32,32,32,32,32,110,111,114,109,97,108,46,115,101,116,80,97,116,104,32,40,112,41,59,13,10,32,32,32,32,32,32, - 32,32,110,111,114,109,97,108,46,115,101,116,83,111,108,105,100,70,105,108,108,32,40,67,111,108,111,117,114,115,58,58,108,105,103,104,116,98,108,117, - 101,41,59,13,10,32,32,32,32,32,32,32,32,110,111,114,109,97,108,46,115,101,116,79,117,116,108,105,110,101,32,40,52,46,48,102,44,32,67,111, - 108,111,117,114,115,58,58,98,108,97,99,107,41,59,13,10,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,80,97,116,104,32,40, - 112,41,59,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,83,111,108,105,100,70,105,108,108,32,40,67,111,108,111,117,114,115,58, - 58,98,108,117,101,41,59,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,79,117,116,108,105,110,101,32,40,52,46,48,102,44,32, - 67,111,108,111,117,114,115,58,58,98,108,97,99,107,41,59,13,10,13,10,32,32,32,32,32,32,32,32,68,114,97,119,97,98,108,101,66,117,116,116, - 111,110,42,32,100,98,32,61,32,110,101,119,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,40,83,116,114,105,110,103,32,40,105,32,43, - 32,53,41,32,43,32,84,40,34,32,112,111,105,110,116,115,34,41,44,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,58,58,73,109,97,103, - 101,65,98,111,118,101,84,101,120,116,76,97,98,101,108,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,73,109,97,103,101,115, - 32,40,38,110,111,114,109,97,108,44,32,38,111,118,101,114,44,32,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,112,97,103,101,45,62,97, - 100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,100,98,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,67, - 108,105,99,107,105,110,103,84,111,103,103,108,101,115,83,116,97,116,101,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45, - 62,115,101,116,82,97,100,105,111,71,114,111,117,112,73,100,32,40,50,51,52,53,54,41,59,13,10,13,10,32,32,32,32,32,32,32,32,99,111,110, - 115,116,32,105,110,116,32,98,117,116,116,111,110,83,105,122,101,32,61,32,53,48,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116, - 66,111,117,110,100,115,32,40,50,53,32,43,32,105,32,42,32,98,117,116,116,111,110,83,105,122,101,44,32,49,56,48,44,32,98,117,116,116,111,110, - 83,105,122,101,44,32,98,117,116,116,111,110,83,105,122,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,105,32,61,61,32,48, - 41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,84,111,103,103,108,101,83,116,97,116,101,32,40,116,114,117,101,44, - 32,102,97,108,115,101,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,102,111,114,32,40,105,32,61,32,48,59,32,105,32,60,32,52, - 59,32,43,43,105,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,84,101,120,116,66,117,116,116,111,110,42,32,116,98,32,61,32, - 110,101,119,32,84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,98,117,116,116,111,110,32,34,41,32,43,32,83,116,114,105,110,103,32,40,105, - 32,43,32,49,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98, - 108,101,32,40,116,98,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,67,108,105,99,107,105,110,103,84,111,103,103,108,101,115, - 83,116,97,116,101,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,82,97,100,105,111,71,114,111,117,112, - 73,100,32,40,51,52,53,54,55,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,67,111,108,111,117,114,32,40,84,101,120,116, - 66,117,116,116,111,110,58,58,98,117,116,116,111,110,67,111,108,111,117,114,73,100,44,32,67,111,108,111,117,114,115,58,58,119,104,105,116,101,41,59, - 13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,67,111,108,111,117,114,32,40,84,101,120,116,66,117,116,116,111,110,58,58,98,117,116, - 116,111,110,79,110,67,111,108,111,117,114,73,100,44,32,67,111,108,111,117,114,115,58,58,98,108,117,101,118,105,111,108,101,116,46,98,114,105,103,104, - 116,101,114,40,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,32,43,32,105, - 32,42,32,53,53,44,32,50,54,48,44,32,53,53,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,67,111,110, - 110,101,99,116,101,100,69,100,103,101,115,32,40,40,40,105,32,33,61,32,48,41,32,63,32,66,117,116,116,111,110,58,58,67,111,110,110,101,99,116, - 101,100,79,110,76,101,102,116,32,58,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,124,32,40,40,105,32,33,61,32,51,41,32,63,32,66,117,116,116,111,110,58,58,67,111,110,110,101,99,116,101,100,79,110, - 82,105,103,104,116,32,58,32,48,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,105,32,61,61,32,48,41,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,84,111,103,103,108,101,83,116,97,116,101,32,40,116,114,117,101,44,32,102,97,108,115,101, - 41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,114,101,116,117,114,110,32,112,97,103,101,59,13,10,125,13,10,13,10,47,47,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,115,116,97,116,105,99,32, + 67,111,109,112,111,110,101,110,116,42,32,99,114,101,97,116,101,83,108,105,100,101,114,115,80,97,103,101,40,41,13,10,123,13,10,32,32,32,32,68, + 101,109,111,80,97,103,101,67,111,109,112,42,32,112,97,103,101,32,61,32,110,101,119,32,68,101,109,111,80,97,103,101,67,111,109,112,40,41,59,13, + 10,13,10,32,32,32,32,99,111,110,115,116,32,105,110,116,32,110,117,109,83,108,105,100,101,114,115,32,61,32,49,49,59,13,10,32,32,32,32,83, + 108,105,100,101,114,42,32,115,108,105,100,101,114,115,32,91,110,117,109,83,108,105,100,101,114,115,93,59,13,10,13,10,32,32,32,32,105,110,116,32, + 105,59,13,10,32,32,32,32,102,111,114,32,40,105,32,61,32,48,59,32,105,32,60,32,110,117,109,83,108,105,100,101,114,115,59,32,43,43,105,41, + 13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,105,102,32,40,105,32,61,61,32,50,41,13,10,32,32,32,32,32,32,32,32,32,32, + 32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,115,108,105,100,101,114,115,91,105,93,32,61,32, + 110,101,119,32,83,110,97,112,112,105,110,103,83,108,105,100,101,114,32,40,84,40,34,115,108,105,100,101,114,34,41,41,41,59,13,10,32,32,32,32, + 32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105, + 115,105,98,108,101,32,40,115,108,105,100,101,114,115,91,105,93,32,61,32,110,101,119,32,83,108,105,100,101,114,32,40,84,40,34,115,108,105,100,101, + 114,34,41,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,115,108,105,100,101,114,115,91,105,93,45,62,115,101,116,82,97,110,103,101,32,40, + 48,46,48,44,32,49,48,48,46,48,44,32,48,46,49,41,59,13,10,32,32,32,32,32,32,32,32,115,108,105,100,101,114,115,91,105,93,45,62,115, + 101,116,80,111,112,117,112,77,101,110,117,69,110,97,98,108,101,100,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,115,108,105,100, + 101,114,115,91,105,93,45,62,115,101,116,86,97,108,117,101,32,40,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111, + 109,40,41,46,110,101,120,116,68,111,117,98,108,101,40,41,32,42,32,49,48,48,46,48,44,32,102,97,108,115,101,44,32,102,97,108,115,101,41,59, + 13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,48,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108, + 101,32,40,83,108,105,100,101,114,58,58,76,105,110,101,97,114,86,101,114,116,105,99,97,108,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115, + 91,48,93,45,62,115,101,116,84,101,120,116,66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84,101,120,116,66,111,120,66,101,108, + 111,119,44,32,102,97,108,115,101,44,32,49,48,48,44,32,50,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,48,93,45,62,115,101, + 116,66,111,117,110,100,115,32,40,49,48,44,32,50,53,44,32,55,48,44,32,50,48,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91, + 48,93,45,62,115,101,116,68,111,117,98,108,101,67,108,105,99,107,82,101,116,117,114,110,86,97,108,117,101,32,40,116,114,117,101,44,32,53,48,46, + 48,41,59,32,47,47,32,100,111,117,98,108,101,45,99,108,105,99,107,105,110,103,32,116,104,105,115,32,115,108,105,100,101,114,32,119,105,108,108,32, + 115,101,116,32,105,116,32,116,111,32,53,48,46,48,13,10,32,32,32,32,115,108,105,100,101,114,115,91,48,93,45,62,115,101,116,84,101,120,116,86, + 97,108,117,101,83,117,102,102,105,120,32,40,84,40,34,32,117,110,105,116,115,34,41,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115, + 91,49,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,76,105,110,101,97,114,86,101,114,116,105, + 99,97,108,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,93,45,62,115,101,116,86,101,108,111,99,105,116,121,66,97,115,101,100,77, + 111,100,101,32,40,116,114,117,101,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,93,45,62,115,101,116,83,107,101,119,70,97,99,116, + 111,114,32,40,48,46,53,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,93,45,62,115,101,116,84,101,120,116,66,111,120,83,116,121, + 108,101,32,40,83,108,105,100,101,114,58,58,84,101,120,116,66,111,120,65,98,111,118,101,44,32,116,114,117,101,44,32,49,48,48,44,32,50,48,41, + 59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,93,45,62,115,101,116,66,111,117,110,100,115,32,40,56,53,44,32,50,53,44,32,55,48, + 44,32,50,48,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,93,45,62,115,101,116,84,101,120,116,86,97,108,117,101,83,117,102, + 102,105,120,32,40,84,40,34,32,114,101,108,115,34,41,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,50,93,45,62,115,101,116, + 83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,76,105,110,101,97,114,72,111,114,105,122,111,110,116,97,108,41,59,13, + 10,32,32,32,32,115,108,105,100,101,114,115,91,50,93,45,62,115,101,116,84,101,120,116,66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114, + 58,58,84,101,120,116,66,111,120,76,101,102,116,44,32,102,97,108,115,101,44,32,56,48,44,32,50,48,41,59,13,10,32,32,32,32,115,108,105,100, + 101,114,115,91,50,93,45,62,115,101,116,66,111,117,110,100,115,32,40,49,56,48,44,32,51,53,44,32,49,53,48,44,32,50,48,41,59,13,10,13, + 10,32,32,32,32,115,108,105,100,101,114,115,91,51,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58, + 58,76,105,110,101,97,114,72,111,114,105,122,111,110,116,97,108,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,51,93,45,62,115,101,116, + 84,101,120,116,66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,78,111,84,101,120,116,66,111,120,44,32,102,97,108,115,101,44,32, + 48,44,32,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,51,93,45,62,115,101,116,66,111,117,110,100,115,32,40,49,56,48,44,32, + 54,53,44,32,49,53,48,44,32,50,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,51,93,45,62,115,101,116,80,111,112,117,112,68, + 105,115,112,108,97,121,69,110,97,98,108,101,100,32,40,116,114,117,101,44,32,112,97,103,101,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115, + 91,51,93,45,62,115,101,116,84,101,120,116,86,97,108,117,101,83,117,102,102,105,120,32,40,84,40,34,32,110,117,110,115,32,114,101,113,117,105,114, + 101,100,32,116,111,32,99,104,97,110,103,101,32,97,32,108,105,103,104,116,98,117,108,98,34,41,41,59,13,10,13,10,32,32,32,32,115,108,105,100, + 101,114,115,91,52,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,73,110,99,68,101,99,66,117, + 116,116,111,110,115,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,52,93,45,62,115,101,116,84,101,120,116,66,111,120,83,116,121,108,101, + 32,40,83,108,105,100,101,114,58,58,84,101,120,116,66,111,120,76,101,102,116,44,32,102,97,108,115,101,44,32,53,48,44,32,50,48,41,59,13,10, + 32,32,32,32,115,108,105,100,101,114,115,91,52,93,45,62,115,101,116,66,111,117,110,100,115,32,40,49,56,48,44,32,49,48,53,44,32,49,48,48, + 44,32,50,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,52,93,45,62,115,101,116,73,110,99,68,101,99,66,117,116,116,111,110,115, + 77,111,100,101,32,40,83,108,105,100,101,114,58,58,105,110,99,68,101,99,66,117,116,116,111,110,115,68,114,97,103,103,97,98,108,101,95,86,101,114, + 116,105,99,97,108,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,53,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108, + 101,32,40,83,108,105,100,101,114,58,58,82,111,116,97,114,121,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,53,93,45,62,115,101,116, + 82,111,116,97,114,121,80,97,114,97,109,101,116,101,114,115,32,40,102,108,111,97,116,95,80,105,32,42,32,49,46,50,102,44,32,102,108,111,97,116, + 95,80,105,32,42,32,50,46,56,102,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,53,93,45,62,115,101,116, + 84,101,120,116,66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84,101,120,116,66,111,120,82,105,103,104,116,44,32,102,97,108,115, + 101,44,32,55,48,44,32,50,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,53,93,45,62,115,101,116,66,111,117,110,100,115,32,40, + 49,57,48,44,32,49,52,53,44,32,49,50,48,44,32,52,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,53,93,45,62,115,101,116, + 84,101,120,116,86,97,108,117,101,83,117,102,102,105,120,32,40,84,40,34,32,109,109,34,41,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101, + 114,115,91,54,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,76,105,110,101,97,114,66,97,114, + 41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,54,93,45,62,115,101,116,66,111,117,110,100,115,32,40,49,56,48,44,32,49,57,53,44, + 32,49,48,48,44,32,51,48,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,54,93,45,62,115,101,116,84,101,120,116,86,97,108,117,101, + 83,117,102,102,105,120,32,40,84,40,34,32,103,97,108,108,111,110,115,34,41,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,55, + 93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84,119,111,86,97,108,117,101,72,111,114,105,122, + 111,110,116,97,108,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,55,93,45,62,115,101,116,66,111,117,110,100,115,32,40,51,54,48,44, + 32,50,48,44,32,49,54,48,44,32,52,48,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,56,93,45,62,115,101,116,83,108,105, + 100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84,119,111,86,97,108,117,101,86,101,114,116,105,99,97,108,41,59,13,10,32,32, + 32,32,115,108,105,100,101,114,115,91,56,93,45,62,115,101,116,66,111,117,110,100,115,32,40,51,54,48,44,32,49,49,48,44,32,52,48,44,32,49, + 54,48,41,59,13,10,13,10,32,32,32,32,115,108,105,100,101,114,115,91,57,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40, + 83,108,105,100,101,114,58,58,84,104,114,101,101,86,97,108,117,101,72,111,114,105,122,111,110,116,97,108,41,59,13,10,32,32,32,32,115,108,105,100, + 101,114,115,91,57,93,45,62,115,101,116,66,111,117,110,100,115,32,40,51,54,48,44,32,55,48,44,32,49,54,48,44,32,52,48,41,59,13,10,13, + 10,32,32,32,32,115,108,105,100,101,114,115,91,49,48,93,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114, + 58,58,84,104,114,101,101,86,97,108,117,101,86,101,114,116,105,99,97,108,41,59,13,10,32,32,32,32,115,108,105,100,101,114,115,91,49,48,93,45, + 62,115,101,116,66,111,117,110,100,115,32,40,52,52,48,44,32,49,49,48,44,32,52,48,44,32,49,54,48,41,59,13,10,13,10,32,32,32,32,102, + 111,114,32,40,105,32,61,32,55,59,32,105,32,60,61,32,49,48,59,32,43,43,105,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32, + 32,115,108,105,100,101,114,115,91,105,93,45,62,115,101,116,84,101,120,116,66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,78,111, + 84,101,120,116,66,111,120,44,32,102,97,108,115,101,44,32,48,44,32,48,41,59,13,10,32,32,32,32,32,32,32,32,115,108,105,100,101,114,115,91, + 105,93,45,62,115,101,116,77,105,110,86,97,108,117,101,32,40,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109, + 40,41,46,110,101,120,116,68,111,117,98,108,101,40,41,32,42,32,49,48,48,46,48,44,32,102,97,108,115,101,44,32,102,97,108,115,101,41,59,13, + 10,32,32,32,32,32,32,32,32,115,108,105,100,101,114,115,91,105,93,45,62,115,101,116,77,97,120,86,97,108,117,101,32,40,82,97,110,100,111,109, + 58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,68,111,117,98,108,101,40,41,32,42,32,49,48,48,46,48, + 44,32,102,97,108,115,101,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32,32,115,108,105,100,101,114,115,91,105,93,45,62,115,101, + 116,80,111,112,117,112,68,105,115,112,108,97,121,69,110,97,98,108,101,100,32,40,116,114,117,101,44,32,112,97,103,101,41,59,13,10,32,32,32,32, + 125,13,10,13,10,32,32,32,32,76,97,98,101,108,42,32,108,97,98,101,108,32,61,32,110,101,119,32,76,97,98,101,108,32,40,84,40,34,104,105, + 110,116,34,41,44,32,84,40,34,84,114,121,32,114,105,103,104,116,45,99,108,105,99,107,105,110,103,32,111,110,32,97,32,115,108,105,100,101,114,32, + 102,111,114,32,97,110,32,111,112,116,105,111,110,115,32,109,101,110,117,46,32,92,110,92,110,65,108,115,111,44,32,104,111,108,100,105,110,103,32,100, + 111,119,110,32,67,84,82,76,32,119,104,105,108,101,32,100,114,97,103,103,105,110,103,32,119,105,108,108,32,116,117,114,110,32,111,110,32,97,32,115, + 108,105,100,101,114,39,115,32,118,101,108,111,99,105,116,121,45,115,101,110,115,105,116,105,118,101,32,109,111,100,101,34,41,41,59,13,10,32,32,32, + 32,108,97,98,101,108,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,44,32,50,52,53,44,32,51,53,48,44,32,49,53,48,41,59,13,10, + 32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,108,97,98,101,108,41,59,13,10,13,10, + 32,32,32,32,114,101,116,117,114,110,32,112,97,103,101,59,13,10,125,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,99,108, - 97,115,115,32,66,117,116,116,111,110,115,80,97,103,101,32,32,32,58,32,112,117,98,108,105,99,32,67,111,109,112,111,110,101,110,116,44,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,66,117,116,116,111,110,76,105,115,116,101,110, - 101,114,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,66,117,116,116,111,110,115,80,97,103,101,32,40,66,117,116,116,111,110,76, - 105,115,116,101,110,101,114,42,32,98,117,116,116,111,110,76,105,115,116,101,110,101,114,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32, - 32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,115,116,97,116,105,99,32,67,111,109,112,111,110,101,110, + 116,42,32,99,114,101,97,116,101,82,97,100,105,111,66,117,116,116,111,110,80,97,103,101,40,41,13,10,123,13,10,32,32,32,32,68,101,109,111,80, + 97,103,101,67,111,109,112,42,32,112,97,103,101,32,61,32,110,101,119,32,68,101,109,111,80,97,103,101,67,111,109,112,40,41,59,13,10,13,10,32, + 32,32,32,71,114,111,117,112,67,111,109,112,111,110,101,110,116,42,32,103,114,111,117,112,32,61,32,110,101,119,32,71,114,111,117,112,67,111,109,112, + 111,110,101,110,116,32,40,84,40,34,103,114,111,117,112,34,41,44,32,84,40,34,114,97,100,105,111,32,98,117,116,116,111,110,115,34,41,41,59,13, + 10,32,32,32,32,103,114,111,117,112,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,44,32,50,48,44,32,50,50,48,44,32,49,52,48,41, + 59,13,10,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,103,114,111,117,112,41,59,13, + 10,13,10,32,32,32,32,105,110,116,32,105,59,13,10,32,32,32,32,102,111,114,32,40,105,32,61,32,48,59,32,105,32,60,32,52,59,32,43,43, + 105,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,84,111,103,103,108,101,66,117,116,116,111,110,42,32,116,98,32,61,32,110,101, + 119,32,84,111,103,103,108,101,66,117,116,116,111,110,32,40,84,40,34,114,97,100,105,111,32,98,117,116,116,111,110,32,35,34,41,32,43,32,83,116, + 114,105,110,103,32,40,105,32,43,32,49,41,41,59,13,10,32,32,32,32,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101, + 86,105,115,105,98,108,101,32,40,116,98,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,82,97,100,105,111,71,114,111,117,112, + 73,100,32,40,49,50,51,52,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,66,111,117,110,100,115,32,40,52,53,44,32,52, + 54,32,43,32,105,32,42,32,50,50,44,32,49,56,48,44,32,50,50,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,84,111, + 111,108,116,105,112,32,40,84,40,34,97,32,115,101,116,32,111,102,32,109,117,116,117,97,108,108,121,45,101,120,99,108,117,115,105,118,101,32,114,97, + 100,105,111,32,98,117,116,116,111,110,115,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,105,32,61,61,32,48,41,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,84,111,103,103,108,101,83,116,97,116,101,32,40,116,114,117,101,44,32,102,97, + 108,115,101,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,102,111,114,32,40,105,32,61,32,48,59,32,105,32,60,32,52,59,32,43, + 43,105,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,68,114,97,119,97,98,108,101,80,97,116,104,32,110,111,114,109,97,108,44, + 32,111,118,101,114,59,13,10,13,10,32,32,32,32,32,32,32,32,80,97,116,104,32,112,59,13,10,32,32,32,32,32,32,32,32,112,46,97,100,100, + 83,116,97,114,32,40,48,46,48,102,44,32,48,46,48,102,44,32,105,32,43,32,53,44,32,50,48,46,48,102,44,32,53,48,46,48,102,44,32,45, + 48,46,50,102,41,59,13,10,32,32,32,32,32,32,32,32,110,111,114,109,97,108,46,115,101,116,80,97,116,104,32,40,112,41,59,13,10,32,32,32, + 32,32,32,32,32,110,111,114,109,97,108,46,115,101,116,83,111,108,105,100,70,105,108,108,32,40,67,111,108,111,117,114,115,58,58,108,105,103,104,116, + 98,108,117,101,41,59,13,10,32,32,32,32,32,32,32,32,110,111,114,109,97,108,46,115,101,116,79,117,116,108,105,110,101,32,40,52,46,48,102,44, + 32,67,111,108,111,117,114,115,58,58,98,108,97,99,107,41,59,13,10,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,80,97,116, + 104,32,40,112,41,59,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,83,111,108,105,100,70,105,108,108,32,40,67,111,108,111,117, + 114,115,58,58,98,108,117,101,41,59,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,79,117,116,108,105,110,101,32,40,52,46,48, + 102,44,32,67,111,108,111,117,114,115,58,58,98,108,97,99,107,41,59,13,10,13,10,32,32,32,32,32,32,32,32,68,114,97,119,97,98,108,101,66, + 117,116,116,111,110,42,32,100,98,32,61,32,110,101,119,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,40,83,116,114,105,110,103,32,40, + 105,32,43,32,53,41,32,43,32,84,40,34,32,112,111,105,110,116,115,34,41,44,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,58,58,73, + 109,97,103,101,65,98,111,118,101,84,101,120,116,76,97,98,101,108,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,73,109,97, + 103,101,115,32,40,38,110,111,114,109,97,108,44,32,38,111,118,101,114,44,32,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,112,97,103,101, + 45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,100,98,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115, + 101,116,67,108,105,99,107,105,110,103,84,111,103,103,108,101,115,83,116,97,116,101,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32, + 100,98,45,62,115,101,116,82,97,100,105,111,71,114,111,117,112,73,100,32,40,50,51,52,53,54,41,59,13,10,13,10,32,32,32,32,32,32,32,32, + 99,111,110,115,116,32,105,110,116,32,98,117,116,116,111,110,83,105,122,101,32,61,32,53,48,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62, + 115,101,116,66,111,117,110,100,115,32,40,50,53,32,43,32,105,32,42,32,98,117,116,116,111,110,83,105,122,101,44,32,49,56,48,44,32,98,117,116, + 116,111,110,83,105,122,101,44,32,98,117,116,116,111,110,83,105,122,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,105,32,61, + 61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,84,111,103,103,108,101,83,116,97,116,101,32,40,116,114, + 117,101,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,102,111,114,32,40,105,32,61,32,48,59,32,105,32, + 60,32,52,59,32,43,43,105,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,84,101,120,116,66,117,116,116,111,110,42,32,116,98, + 32,61,32,110,101,119,32,84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,98,117,116,116,111,110,32,34,41,32,43,32,83,116,114,105,110,103, + 32,40,105,32,43,32,49,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105, + 115,105,98,108,101,32,40,116,98,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,67,108,105,99,107,105,110,103,84,111,103,103, + 108,101,115,83,116,97,116,101,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,82,97,100,105,111,71,114, + 111,117,112,73,100,32,40,51,52,53,54,55,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,67,111,108,111,117,114,32,40,84, + 101,120,116,66,117,116,116,111,110,58,58,98,117,116,116,111,110,67,111,108,111,117,114,73,100,44,32,67,111,108,111,117,114,115,58,58,119,104,105,116, + 101,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,67,111,108,111,117,114,32,40,84,101,120,116,66,117,116,116,111,110,58,58, + 98,117,116,116,111,110,79,110,67,111,108,111,117,114,73,100,44,32,67,111,108,111,117,114,115,58,58,98,108,117,101,118,105,111,108,101,116,46,98,114, + 105,103,104,116,101,114,40,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,32, + 43,32,105,32,42,32,53,53,44,32,50,54,48,44,32,53,53,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116, + 67,111,110,110,101,99,116,101,100,69,100,103,101,115,32,40,40,40,105,32,33,61,32,48,41,32,63,32,66,117,116,116,111,110,58,58,67,111,110,110, + 101,99,116,101,100,79,110,76,101,102,116,32,58,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,124,32,40,40,105,32,33,61,32,51,41,32,63,32,66,117,116,116,111,110,58,58,67,111,110,110,101,99,116,101, + 100,79,110,82,105,103,104,116,32,58,32,48,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,105,32,61,61,32,48,41,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,116,98,45,62,115,101,116,84,111,103,103,108,101,83,116,97,116,101,32,40,116,114,117,101,44,32,102,97, + 108,115,101,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,114,101,116,117,114,110,32,112,97,103,101,59,13,10,125,13,10,13,10,47, + 47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13, + 10,99,108,97,115,115,32,66,117,116,116,111,110,115,80,97,103,101,32,32,32,58,32,112,117,98,108,105,99,32,67,111,109,112,111,110,101,110,116,44, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,66,117,116,116,111,110,76,105,115, + 116,101,110,101,114,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,66,117,116,116,111,110,115,80,97,103,101,32,40,66,117,116,116, + 111,110,76,105,115,116,101,110,101,114,42,32,98,117,116,116,111,110,76,105,115,116,101,110,101,114,41,13,10,32,32,32,32,123,13,10,32,32,32,32, + 32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,13,10,32,32,32,32,32,32,32,32,47,47,32,99,114,101,97,116,101,32,115,111,109,101,32,100,114,97,119,97,98,108,101,115,32,116,111,32,117, - 115,101,32,102,111,114,32,111,117,114,32,100,114,97,119,97,98,108,101,32,98,117,116,116,111,110,115,46,46,46,13,10,32,32,32,32,32,32,32,32, - 68,114,97,119,97,98,108,101,80,97,116,104,32,110,111,114,109,97,108,44,32,111,118,101,114,59,13,10,13,10,32,32,32,32,32,32,32,32,80,97, - 116,104,32,112,59,13,10,32,32,32,32,32,32,32,32,112,46,97,100,100,83,116,97,114,32,40,48,46,48,102,44,32,48,46,48,102,44,32,53,44, - 32,50,48,46,48,102,44,32,53,48,46,48,102,44,32,48,46,50,102,41,59,13,10,32,32,32,32,32,32,32,32,110,111,114,109,97,108,46,115,101, - 116,80,97,116,104,32,40,112,41,59,13,10,32,32,32,32,32,32,32,32,110,111,114,109,97,108,46,115,101,116,83,111,108,105,100,70,105,108,108,32, - 40,67,111,108,111,117,114,115,58,58,114,101,100,41,59,13,10,13,10,32,32,32,32,32,32,32,32,112,46,99,108,101,97,114,40,41,59,13,10,32, - 32,32,32,32,32,32,32,112,46,97,100,100,83,116,97,114,32,40,48,46,48,102,44,32,48,46,48,102,44,32,55,44,32,51,48,46,48,102,44,32, - 53,48,46,48,102,44,32,48,46,48,102,41,59,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,80,97,116,104,32,40,112,41,59, - 13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,83,111,108,105,100,70,105,108,108,32,40,67,111,108,111,117,114,115,58,58,112,105, - 110,107,41,59,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,79,117,116,108,105,110,101,32,40,53,46,48,102,44,32,67,111,108, - 111,117,114,115,58,58,98,108,97,99,107,41,59,13,10,13,10,32,32,32,32,32,32,32,32,68,114,97,119,97,98,108,101,73,109,97,103,101,32,100, - 111,119,110,59,13,10,32,32,32,32,32,32,32,32,100,111,119,110,46,115,101,116,73,109,97,103,101,32,40,73,109,97,103,101,67,97,99,104,101,58, - 58,103,101,116,70,114,111,109,77,101,109,111,114,121,32,40,66,105,110,97,114,121,68,97,116,97,58,58,106,117,99,101,95,112,110,103,44,32,66,105, - 110,97,114,121,68,97,116,97,58,58,106,117,99,101,95,112,110,103,83,105,122,101,41,44,32,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32, - 32,100,111,119,110,46,115,101,116,79,118,101,114,108,97,121,67,111,108,111,117,114,32,40,67,111,108,111,117,114,115,58,58,98,108,97,99,107,46,119, - 105,116,104,65,108,112,104,97,32,40,48,46,51,102,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61, + 61,61,61,61,13,10,32,32,32,32,32,32,32,32,47,47,32,99,114,101,97,116,101,32,115,111,109,101,32,100,114,97,119,97,98,108,101,115,32,116, + 111,32,117,115,101,32,102,111,114,32,111,117,114,32,100,114,97,119,97,98,108,101,32,98,117,116,116,111,110,115,46,46,46,13,10,32,32,32,32,32, + 32,32,32,68,114,97,119,97,98,108,101,80,97,116,104,32,110,111,114,109,97,108,44,32,111,118,101,114,59,13,10,13,10,32,32,32,32,32,32,32, + 32,80,97,116,104,32,112,59,13,10,32,32,32,32,32,32,32,32,112,46,97,100,100,83,116,97,114,32,40,48,46,48,102,44,32,48,46,48,102,44, + 32,53,44,32,50,48,46,48,102,44,32,53,48,46,48,102,44,32,48,46,50,102,41,59,13,10,32,32,32,32,32,32,32,32,110,111,114,109,97,108, + 46,115,101,116,80,97,116,104,32,40,112,41,59,13,10,32,32,32,32,32,32,32,32,110,111,114,109,97,108,46,115,101,116,83,111,108,105,100,70,105, + 108,108,32,40,67,111,108,111,117,114,115,58,58,114,101,100,41,59,13,10,13,10,32,32,32,32,32,32,32,32,112,46,99,108,101,97,114,40,41,59, + 13,10,32,32,32,32,32,32,32,32,112,46,97,100,100,83,116,97,114,32,40,48,46,48,102,44,32,48,46,48,102,44,32,55,44,32,51,48,46,48, + 102,44,32,53,48,46,48,102,44,32,48,46,48,102,41,59,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,80,97,116,104,32,40, + 112,41,59,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,83,111,108,105,100,70,105,108,108,32,40,67,111,108,111,117,114,115,58, + 58,112,105,110,107,41,59,13,10,32,32,32,32,32,32,32,32,111,118,101,114,46,115,101,116,79,117,116,108,105,110,101,32,40,53,46,48,102,44,32, + 67,111,108,111,117,114,115,58,58,98,108,97,99,107,41,59,13,10,13,10,32,32,32,32,32,32,32,32,68,114,97,119,97,98,108,101,73,109,97,103, + 101,32,100,111,119,110,59,13,10,32,32,32,32,32,32,32,32,100,111,119,110,46,115,101,116,73,109,97,103,101,32,40,73,109,97,103,101,67,97,99, + 104,101,58,58,103,101,116,70,114,111,109,77,101,109,111,114,121,32,40,66,105,110,97,114,121,68,97,116,97,58,58,106,117,99,101,95,112,110,103,44, + 32,66,105,110,97,114,121,68,97,116,97,58,58,106,117,99,101,95,112,110,103,83,105,122,101,41,44,32,116,114,117,101,41,59,13,10,32,32,32,32, + 32,32,32,32,100,111,119,110,46,115,101,116,79,118,101,114,108,97,121,67,111,108,111,117,114,32,40,67,111,108,111,117,114,115,58,58,98,108,97,99, + 107,46,119,105,116,104,65,108,112,104,97,32,40,48,46,51,102,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,47, - 47,32,99,114,101,97,116,101,32,97,110,32,105,109,97,103,101,45,97,98,111,118,101,45,116,101,120,116,32,98,117,116,116,111,110,32,102,114,111,109, - 32,116,104,101,115,101,32,100,114,97,119,97,98,108,101,115,46,46,13,10,32,32,32,32,32,32,32,32,68,114,97,119,97,98,108,101,66,117,116,116, - 111,110,42,32,100,98,32,61,32,110,101,119,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,40,84,40,34,66,117,116,116,111,110,32,49, - 34,41,44,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,58,58,73,109,97,103,101,65,98,111,118,101,84,101,120,116,76,97,98,101,108,41, - 59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,73,109,97,103,101,115,32,40,38,110,111,114,109,97,108,44,32,38,111,118,101,114, - 44,32,38,100,111,119,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40, - 100,98,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,51,48,44,32,56,48,44, - 32,56,48,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,84,111,111,108,116,105,112,32,40,84,40,34,116,104,105,115,32,105, - 115,32,97,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,119,105,116,104,32,97,32,108,97,98,101,108,34,41,41,59,13,10,13,10,32, - 32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32, + 32,32,47,47,32,99,114,101,97,116,101,32,97,110,32,105,109,97,103,101,45,97,98,111,118,101,45,116,101,120,116,32,98,117,116,116,111,110,32,102, + 114,111,109,32,116,104,101,115,101,32,100,114,97,119,97,98,108,101,115,46,46,13,10,32,32,32,32,32,32,32,32,68,114,97,119,97,98,108,101,66, + 117,116,116,111,110,42,32,100,98,32,61,32,110,101,119,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,40,84,40,34,66,117,116,116,111, + 110,32,49,34,41,44,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,58,58,73,109,97,103,101,65,98,111,118,101,84,101,120,116,76,97,98, + 101,108,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,73,109,97,103,101,115,32,40,38,110,111,114,109,97,108,44,32,38,111, + 118,101,114,44,32,38,100,111,119,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108, + 101,32,40,100,98,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,51,48,44,32, + 56,48,44,32,56,48,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,84,111,111,108,116,105,112,32,40,84,40,34,116,104,105, + 115,32,105,115,32,97,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,119,105,116,104,32,97,32,108,97,98,101,108,34,41,41,59,13,10, + 13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,47,47,32,99,114,101,97,116,101,32,97,110,32,105,109,97,103,101,45,111,110,108,121, - 32,98,117,116,116,111,110,32,102,114,111,109,32,116,104,101,115,101,32,100,114,97,119,97,98,108,101,115,46,46,13,10,32,32,32,32,32,32,32,32, - 100,98,32,61,32,110,101,119,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,40,84,40,34,66,117,116,116,111,110,32,50,34,41,44,32, - 68,114,97,119,97,98,108,101,66,117,116,116,111,110,58,58,73,109,97,103,101,70,105,116,116,101,100,41,59,13,10,32,32,32,32,32,32,32,32,100, - 98,45,62,115,101,116,73,109,97,103,101,115,32,40,38,110,111,114,109,97,108,44,32,38,111,118,101,114,44,32,38,100,111,119,110,41,59,13,10,32, - 32,32,32,32,32,32,32,100,98,45,62,115,101,116,67,108,105,99,107,105,110,103,84,111,103,103,108,101,115,83,116,97,116,101,32,40,116,114,117,101, - 41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,100,98,41,59,13,10,32, - 32,32,32,32,32,32,32,100,98,45,62,115,101,116,66,111,117,110,100,115,32,40,57,48,44,32,51,48,44,32,56,48,44,32,56,48,41,59,13,10, - 32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,84,111,111,108,116,105,112,32,40,84,40,34,116,104,105,115,32,105,115,32,97,110,32,105,109, - 97,103,101,45,111,110,108,121,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,34,41,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45, - 62,97,100,100,66,117,116,116,111,110,76,105,115,116,101,110,101,114,32,40,98,117,116,116,111,110,76,105,115,116,101,110,101,114,41,59,13,10,13,10, - 32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,47,47,32,99,114,101,97,116,101,32,97,110,32,105,109,97,103,101,45,111, + 110,108,121,32,98,117,116,116,111,110,32,102,114,111,109,32,116,104,101,115,101,32,100,114,97,119,97,98,108,101,115,46,46,13,10,32,32,32,32,32, + 32,32,32,100,98,32,61,32,110,101,119,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,40,84,40,34,66,117,116,116,111,110,32,50,34, + 41,44,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,58,58,73,109,97,103,101,70,105,116,116,101,100,41,59,13,10,32,32,32,32,32,32, + 32,32,100,98,45,62,115,101,116,73,109,97,103,101,115,32,40,38,110,111,114,109,97,108,44,32,38,111,118,101,114,44,32,38,100,111,119,110,41,59, + 13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,67,108,105,99,107,105,110,103,84,111,103,103,108,101,115,83,116,97,116,101,32,40,116, + 114,117,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,100,98,41,59, + 13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,66,111,117,110,100,115,32,40,57,48,44,32,51,48,44,32,56,48,44,32,56,48,41, + 59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,84,111,111,108,116,105,112,32,40,84,40,34,116,104,105,115,32,105,115,32,97,110, + 32,105,109,97,103,101,45,111,110,108,121,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,34,41,41,59,13,10,32,32,32,32,32,32,32,32, + 100,98,45,62,97,100,100,66,117,116,116,111,110,76,105,115,116,101,110,101,114,32,40,98,117,116,116,111,110,76,105,115,116,101,110,101,114,41,59,13, + 10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,47,47,32,99,114,101,97,116,101,32,97,110,32,105,109,97,103,101,45,111,110,45, - 98,117,116,116,111,110,45,115,104,97,112,101,32,98,117,116,116,111,110,32,102,114,111,109,32,116,104,101,32,115,97,109,101,32,100,114,97,119,97,98, - 108,101,115,46,46,13,10,32,32,32,32,32,32,32,32,100,98,32,61,32,110,101,119,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,40, - 84,40,34,66,117,116,116,111,110,32,51,34,41,44,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,58,58,73,109,97,103,101,79,110,66,117, - 116,116,111,110,66,97,99,107,103,114,111,117,110,100,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,73,109,97,103,101,115,32, - 40,38,110,111,114,109,97,108,44,32,48,44,32,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105, - 115,105,98,108,101,32,40,100,98,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,48,44, - 32,51,48,44,32,49,49,48,44,32,50,53,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,84,111,111,108,116,105,112,32,40, - 84,40,34,116,104,105,115,32,105,115,32,97,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,111,110,32,97,32,115,116,97,110,100,97,114, - 100,32,98,117,116,116,111,110,32,98,97,99,107,103,114,111,117,110,100,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,47,47,32,99,114,101,97,116,101,32,97,110,32,105,109,97,103,101,45, + 111,110,45,98,117,116,116,111,110,45,115,104,97,112,101,32,98,117,116,116,111,110,32,102,114,111,109,32,116,104,101,32,115,97,109,101,32,100,114,97, + 119,97,98,108,101,115,46,46,13,10,32,32,32,32,32,32,32,32,100,98,32,61,32,110,101,119,32,68,114,97,119,97,98,108,101,66,117,116,116,111, + 110,32,40,84,40,34,66,117,116,116,111,110,32,51,34,41,44,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,58,58,73,109,97,103,101,79, + 110,66,117,116,116,111,110,66,97,99,107,103,114,111,117,110,100,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,73,109,97,103, + 101,115,32,40,38,110,111,114,109,97,108,44,32,48,44,32,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107, + 101,86,105,115,105,98,108,101,32,40,100,98,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,66,111,117,110,100,115,32,40,50, + 48,48,44,32,51,48,44,32,49,49,48,44,32,50,53,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,84,111,111,108,116,105, + 112,32,40,84,40,34,116,104,105,115,32,105,115,32,97,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,111,110,32,97,32,115,116,97,110, + 100,97,114,100,32,98,117,116,116,111,110,32,98,97,99,107,103,114,111,117,110,100,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32, - 32,32,32,32,32,100,98,32,61,32,110,101,119,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,40,84,40,34,66,117,116,116,111,110,32, - 52,34,41,44,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,58,58,73,109,97,103,101,79,110,66,117,116,116,111,110,66,97,99,107,103,114, - 111,117,110,100,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,73,109,97,103,101,115,32,40,38,110,111,114,109,97,108,44,32, - 38,111,118,101,114,44,32,38,100,111,119,110,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,67,108,105,99,107,105,110,103,84, - 111,103,103,108,101,115,83,116,97,116,101,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,66,97,99,107, - 103,114,111,117,110,100,67,111,108,111,117,114,115,32,40,67,111,108,111,117,114,115,58,58,119,104,105,116,101,44,32,67,111,108,111,117,114,115,58,58, - 121,101,108,108,111,119,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,100, - 98,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,48,44,32,55,48,44,32,53,48,44, - 32,53,48,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,84,111,111,108,116,105,112,32,40,84,40,34,116,104,105,115,32,105, - 115,32,97,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,111,110,32,97,32,115,116,97,110,100,97,114,100,32,98,117,116,116,111,110,32, - 98,97,99,107,103,114,111,117,110,100,34,41,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,97,100,100,66,117,116,116,111,110,76,105,115, - 116,101,110,101,114,32,40,98,117,116,116,111,110,76,105,115,116,101,110,101,114,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10, + 32,32,32,32,32,32,32,32,100,98,32,61,32,110,101,119,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,40,84,40,34,66,117,116,116, + 111,110,32,52,34,41,44,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,58,58,73,109,97,103,101,79,110,66,117,116,116,111,110,66,97,99, + 107,103,114,111,117,110,100,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,73,109,97,103,101,115,32,40,38,110,111,114,109,97, + 108,44,32,38,111,118,101,114,44,32,38,100,111,119,110,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,67,108,105,99,107,105, + 110,103,84,111,103,103,108,101,115,83,116,97,116,101,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,66, + 97,99,107,103,114,111,117,110,100,67,111,108,111,117,114,115,32,40,67,111,108,111,117,114,115,58,58,119,104,105,116,101,44,32,67,111,108,111,117,114, + 115,58,58,121,101,108,108,111,119,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101, + 32,40,100,98,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,48,44,32,55,48,44,32, + 53,48,44,32,53,48,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,115,101,116,84,111,111,108,116,105,112,32,40,84,40,34,116,104,105, + 115,32,105,115,32,97,32,68,114,97,119,97,98,108,101,66,117,116,116,111,110,32,111,110,32,97,32,115,116,97,110,100,97,114,100,32,98,117,116,116, + 111,110,32,98,97,99,107,103,114,111,117,110,100,34,41,41,59,13,10,32,32,32,32,32,32,32,32,100,98,45,62,97,100,100,66,117,116,116,111,110, + 76,105,115,116,101,110,101,114,32,40,98,117,116,116,111,110,76,105,115,116,101,110,101,114,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32, - 32,32,32,32,32,72,121,112,101,114,108,105,110,107,66,117,116,116,111,110,42,32,104,121,112,101,114,108,105,110,107,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,61,32,110,101,119,32,72,121,112,101,114,108,105,110,107,66,117,116,116,111,110,32,40,84,40,34,116,104,105,115,32,105,115,32,97, - 32,72,121,112,101,114,108,105,110,107,66,117,116,116,111,110,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,85,82,76,32,40,84,40,34,104,116,116,112,58,47,47,119,119,119,46,114,97,119,109, - 97,116,101,114,105,97,108,115,111,102,116,119,97,114,101,46,99,111,109,47,106,117,99,101,34,41,41,41,59,13,10,13,10,32,32,32,32,32,32,32, - 32,104,121,112,101,114,108,105,110,107,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,49,51,48,44,32,50,48,48,44,32,50,52,41, - 59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,104,121,112,101,114,108,105,110,107,41, - 59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10, + 32,32,32,32,32,32,32,32,72,121,112,101,114,108,105,110,107,66,117,116,116,111,110,42,32,104,121,112,101,114,108,105,110,107,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,61,32,110,101,119,32,72,121,112,101,114,108,105,110,107,66,117,116,116,111,110,32,40,84,40,34,116,104,105,115,32,105, + 115,32,97,32,72,121,112,101,114,108,105,110,107,66,117,116,116,111,110,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,85,82,76,32,40,84,40,34,104,116,116,112,58,47,47,119,119,119,46,114, + 97,119,109,97,116,101,114,105,97,108,115,111,102,116,119,97,114,101,46,99,111,109,47,106,117,99,101,34,41,41,41,59,13,10,13,10,32,32,32,32, + 32,32,32,32,104,121,112,101,114,108,105,110,107,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,49,51,48,44,32,50,48,48,44,32, + 50,52,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,104,121,112,101,114,108,105, + 110,107,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,73,109,97,103,101,66,117,116,116,111,110,42,32,105,109,97,103, - 101,66,117,116,116,111,110,32,61,32,110,101,119,32,73,109,97,103,101,66,117,116,116,111,110,32,40,84,40,34,105,109,97,103,101,98,117,116,116,111, - 110,34,41,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,105,109,97,103,101,66, - 117,116,116,111,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32,73,109,97,103,101,42,32,106,117,99,101,73,109,97,103,101,32,61,32,73,109, - 97,103,101,67,97,99,104,101,58,58,103,101,116,70,114,111,109,77,101,109,111,114,121,32,40,66,105,110,97,114,121,68,97,116,97,58,58,106,117,99, - 101,95,112,110,103,44,32,66,105,110,97,114,121,68,97,116,97,58,58,106,117,99,101,95,112,110,103,83,105,122,101,41,59,13,10,32,32,32,32,32, - 32,32,32,73,109,97,103,101,67,97,99,104,101,58,58,105,110,99,82,101,102,101,114,101,110,99,101,67,111,117,110,116,32,40,106,117,99,101,73,109, - 97,103,101,41,59,13,10,32,32,32,32,32,32,32,32,73,109,97,103,101,67,97,99,104,101,58,58,105,110,99,82,101,102,101,114,101,110,99,101,67, - 111,117,110,116,32,40,106,117,99,101,73,109,97,103,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,109,97,103,101,66,117,116,116,111,110, - 45,62,115,101,116,73,109,97,103,101,115,32,40,116,114,117,101,44,32,116,114,117,101,44,32,116,114,117,101,44,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,73,109,97,103,101,44,32,48,46,55,102,44, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,73,109,97,103,101,66,117,116,116,111,110,42,32,105, + 109,97,103,101,66,117,116,116,111,110,32,61,32,110,101,119,32,73,109,97,103,101,66,117,116,116,111,110,32,40,84,40,34,105,109,97,103,101,98,117, + 116,116,111,110,34,41,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,105,109,97, + 103,101,66,117,116,116,111,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32,73,109,97,103,101,42,32,106,117,99,101,73,109,97,103,101,32,61, + 32,73,109,97,103,101,67,97,99,104,101,58,58,103,101,116,70,114,111,109,77,101,109,111,114,121,32,40,66,105,110,97,114,121,68,97,116,97,58,58, + 106,117,99,101,95,112,110,103,44,32,66,105,110,97,114,121,68,97,116,97,58,58,106,117,99,101,95,112,110,103,83,105,122,101,41,59,13,10,32,32, + 32,32,32,32,32,32,73,109,97,103,101,67,97,99,104,101,58,58,105,110,99,82,101,102,101,114,101,110,99,101,67,111,117,110,116,32,40,106,117,99, + 101,73,109,97,103,101,41,59,13,10,32,32,32,32,32,32,32,32,73,109,97,103,101,67,97,99,104,101,58,58,105,110,99,82,101,102,101,114,101,110, + 99,101,67,111,117,110,116,32,40,106,117,99,101,73,109,97,103,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,109,97,103,101,66,117,116, + 116,111,110,45,62,115,101,116,73,109,97,103,101,115,32,40,116,114,117,101,44,32,116,114,117,101,44,32,116,114,117,101,44,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,73,109,97,103,101,44,32,48,46, + 55,102,44,32,67,111,108,111,117,114,115,58,58,116,114,97,110,115,112,97,114,101,110,116,66,108,97,99,107,44,13,10,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,73,109,97,103,101,44,32,49,46,48,102,44, 32,67,111,108,111,117,114,115,58,58,116,114,97,110,115,112,97,114,101,110,116,66,108,97,99,107,44,13,10,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,73,109,97,103,101,44,32,49,46,48,102,44,32,67,111, - 108,111,117,114,115,58,58,116,114,97,110,115,112,97,114,101,110,116,66,108,97,99,107,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,73,109,97,103,101,44,32,49,46,48,102,44,32,67,111,108,111,117, - 114,115,58,58,112,105,110,107,46,119,105,116,104,65,108,112,104,97,32,40,48,46,56,102,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,48,46,53,102,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,109, - 97,103,101,66,117,116,116,111,110,45,62,115,101,116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110,32,40,49,48,44,32,49,54,48,41,59, - 13,10,32,32,32,32,32,32,32,32,105,109,97,103,101,66,117,116,116,111,110,45,62,115,101,116,84,111,111,108,116,105,112,32,40,84,40,34,105,109, - 97,103,101,32,98,117,116,116,111,110,32,45,32,115,104,111,119,105,110,103,32,97,108,112,104,97,45,99,104,97,110,110,101,108,32,104,105,116,45,116, - 101,115,116,105,110,103,32,97,110,100,32,99,111,108,111,117,114,32,111,118,101,114,108,97,121,32,119,104,101,110,32,99,108,105,99,107,101,100,34,41, - 41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 108,111,117,114,115,58,58,112,105,110,107,46,119,105,116,104,65,108,112,104,97,32,40,48,46,56,102,41,44,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,48,46,53,102,41,59,13,10,13,10,32,32,32,32,32,32,32, + 32,105,109,97,103,101,66,117,116,116,111,110,45,62,115,101,116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110,32,40,49,48,44,32,49,54, + 48,41,59,13,10,32,32,32,32,32,32,32,32,105,109,97,103,101,66,117,116,116,111,110,45,62,115,101,116,84,111,111,108,116,105,112,32,40,84,40, + 34,105,109,97,103,101,32,98,117,116,116,111,110,32,45,32,115,104,111,119,105,110,103,32,97,108,112,104,97,45,99,104,97,110,110,101,108,32,104,105, + 116,45,116,101,115,116,105,110,103,32,97,110,100,32,99,111,108,111,117,114,32,111,118,101,114,108,97,121,32,119,104,101,110,32,99,108,105,99,107,101, + 100,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,67,111,108,111,117,114,67,104,97,110,103,101,66,117,116,116, - 111,110,42,32,99,111,108,111,117,114,67,104,97,110,103,101,66,117,116,116,111,110,32,61,32,110,101,119,32,67,111,108,111,117,114,67,104,97,110,103, - 101,66,117,116,116,111,110,40,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,99, - 111,108,111,117,114,67,104,97,110,103,101,66,117,116,116,111,110,41,59,13,10,32,32,32,32,32,32,32,32,99,111,108,111,117,114,67,104,97,110,103, - 101,66,117,116,116,111,110,45,62,115,101,116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110,32,40,51,53,48,44,32,51,48,41,59,13,10, - 13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,67,111,108,111,117,114,67,104,97,110,103,101,66, + 117,116,116,111,110,42,32,99,111,108,111,117,114,67,104,97,110,103,101,66,117,116,116,111,110,32,61,32,110,101,119,32,67,111,108,111,117,114,67,104, + 97,110,103,101,66,117,116,116,111,110,40,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101, + 32,40,99,111,108,111,117,114,67,104,97,110,103,101,66,117,116,116,111,110,41,59,13,10,32,32,32,32,32,32,32,32,99,111,108,111,117,114,67,104, + 97,110,103,101,66,117,116,116,111,110,45,62,115,101,116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110,32,40,51,53,48,44,32,51,48,41, + 59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,97,110,105,109,97,116,101,66,117,116,116,111,110,32,61,32,110,101,119,32, - 84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,99,108,105,99,107,32,116,111,32,97,110,105,109,97,116,101,46,46,46,34,41,41,59,13,10, - 32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,97,110,105,109,97,116,101,66,117,116,116,111,110, - 41,59,13,10,32,32,32,32,32,32,32,32,97,110,105,109,97,116,101,66,117,116,116,111,110,45,62,99,104,97,110,103,101,87,105,100,116,104,84,111, - 70,105,116,84,101,120,116,32,40,50,52,41,59,13,10,32,32,32,32,32,32,32,32,97,110,105,109,97,116,101,66,117,116,116,111,110,45,62,115,101, - 116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110,32,40,51,53,48,44,32,55,48,41,59,13,10,32,32,32,32,32,32,32,32,97,110,105, - 109,97,116,101,66,117,116,116,111,110,45,62,97,100,100,66,117,116,116,111,110,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,13,10,32, - 32,32,32,125,13,10,13,10,32,32,32,32,126,66,117,116,116,111,110,115,80,97,103,101,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32, - 32,32,32,100,101,108,101,116,101,65,108,108,67,104,105,108,100,114,101,110,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111, - 105,100,32,98,117,116,116,111,110,67,108,105,99,107,101,100,32,40,66,117,116,116,111,110,42,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32, - 32,32,32,102,111,114,32,40,105,110,116,32,105,32,61,32,103,101,116,78,117,109,67,104,105,108,100,67,111,109,112,111,110,101,110,116,115,40,41,59, - 32,45,45,105,32,62,61,32,48,59,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40, - 103,101,116,67,104,105,108,100,67,111,109,112,111,110,101,110,116,32,40,105,41,32,33,61,32,97,110,105,109,97,116,101,66,117,116,116,111,110,41,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,97,110,105,109,97,116,111,114, - 46,97,110,105,109,97,116,101,67,111,109,112,111,110,101,110,116,32,40,103,101,116,67,104,105,108,100,67,111,109,112,111,110,101,110,116,32,40,105,41, - 44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,82,101,99,116,97,110,103,108,101,32,40,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109, - 40,41,46,110,101,120,116,73,110,116,32,40,103,101,116,87,105,100,116,104,40,41,32,47,32,50,41,44,13,10,32,32,32,32,32,32,32,32,32,32, + 61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,97,110,105,109,97,116,101,66,117,116,116,111,110,32,61,32,110, + 101,119,32,84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,99,108,105,99,107,32,116,111,32,97,110,105,109,97,116,101,46,46,46,34,41,41, + 59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,97,110,105,109,97,116,101,66,117,116, + 116,111,110,41,59,13,10,32,32,32,32,32,32,32,32,97,110,105,109,97,116,101,66,117,116,116,111,110,45,62,99,104,97,110,103,101,87,105,100,116, + 104,84,111,70,105,116,84,101,120,116,32,40,50,52,41,59,13,10,32,32,32,32,32,32,32,32,97,110,105,109,97,116,101,66,117,116,116,111,110,45, + 62,115,101,116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110,32,40,51,53,48,44,32,55,48,41,59,13,10,32,32,32,32,32,32,32,32, + 97,110,105,109,97,116,101,66,117,116,116,111,110,45,62,97,100,100,66,117,116,116,111,110,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59, + 13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,66,117,116,116,111,110,115,80,97,103,101,40,41,13,10,32,32,32,32,123,13,10,32,32, + 32,32,32,32,32,32,100,101,108,101,116,101,65,108,108,67,104,105,108,100,114,101,110,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32, + 32,118,111,105,100,32,98,117,116,116,111,110,67,108,105,99,107,101,100,32,40,66,117,116,116,111,110,42,41,13,10,32,32,32,32,123,13,10,32,32, + 32,32,32,32,32,32,102,111,114,32,40,105,110,116,32,105,32,61,32,103,101,116,78,117,109,67,104,105,108,100,67,111,109,112,111,110,101,110,116,115, + 40,41,59,32,45,45,105,32,62,61,32,48,59,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105, + 102,32,40,103,101,116,67,104,105,108,100,67,111,109,112,111,110,101,110,116,32,40,105,41,32,33,61,32,97,110,105,109,97,116,101,66,117,116,116,111, + 110,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,97,110,105,109,97, + 116,111,114,46,97,110,105,109,97,116,101,67,111,109,112,111,110,101,110,116,32,40,103,101,116,67,104,105,108,100,67,111,109,112,111,110,101,110,116,32, + 40,105,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,82,101,99,116,97,110,103,108,101,32,40,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110, + 100,111,109,40,41,46,110,101,120,116,73,110,116,32,40,103,101,116,87,105,100,116,104,40,41,32,47,32,50,41,44,13,10,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,73,110,116,32,40,103, - 101,116,72,101,105,103,104,116,40,41,32,47,32,50,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,54,48,32,43,32,82,97,110, - 100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,73,110,116,32,40,103,101,116,87,105,100,116,104, - 40,41,32,47,32,51,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,49,54,32,43,32,82,97,110,100,111,109,58,58,103,101,116, - 83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,73,110,116,32,40,103,101,116,72,101,105,103,104,116,40,41,32,47,32,54,41, - 41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,53,48,48,32,43,32,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110, - 101,120,116,73,110,116,32,40,50,48,48,48,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100, - 111,109,40,41,46,110,101,120,116,68,111,117,98,108,101,40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109, - 82,97,110,100,111,109,40,41,46,110,101,120,116,68,111,117,98,108,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10, - 32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,13,10,112,114,105,118,97,116,101,58,13,10,32,32,32,32,84,101,120,116,66,117, - 116,116,111,110,42,32,97,110,105,109,97,116,101,66,117,116,116,111,110,59,13,10,32,32,32,32,67,111,109,112,111,110,101,110,116,65,110,105,109,97, - 116,111,114,32,97,110,105,109,97,116,111,114,59,13,10,125,59,13,10,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 32,32,32,32,32,32,32,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,73,110,116, + 32,40,103,101,116,72,101,105,103,104,116,40,41,32,47,32,50,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,54,48,32,43,32, + 82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,73,110,116,32,40,103,101,116,87,105, + 100,116,104,40,41,32,47,32,51,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,49,54,32,43,32,82,97,110,100,111,109,58,58, + 103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,73,110,116,32,40,103,101,116,72,101,105,103,104,116,40,41,32,47, + 32,54,41,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,53,48,48,32,43,32,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40, + 41,46,110,101,120,116,73,110,116,32,40,50,48,48,48,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82, + 97,110,100,111,109,40,41,46,110,101,120,116,68,111,117,98,108,101,40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,82,97,110,100,111,109,58,58,103,101,116,83,121,115, + 116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,68,111,117,98,108,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32, + 125,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,13,10,112,114,105,118,97,116,101,58,13,10,32,32,32,32,84,101,120, + 116,66,117,116,116,111,110,42,32,97,110,105,109,97,116,101,66,117,116,116,111,110,59,13,10,32,32,32,32,67,111,109,112,111,110,101,110,116,65,110, + 105,109,97,116,111,114,32,97,110,105,109,97,116,111,114,59,13,10,125,59,13,10,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,115,116,97,116,105,99,32,67,111,109,112,111,110,101,110, - 116,42,32,99,114,101,97,116,101,77,105,115,99,80,97,103,101,40,41,13,10,123,13,10,32,32,32,32,68,101,109,111,80,97,103,101,67,111,109,112, - 42,32,112,97,103,101,32,61,32,110,101,119,32,68,101,109,111,80,97,103,101,67,111,109,112,40,41,59,13,10,13,10,32,32,32,32,84,101,120,116, - 69,100,105,116,111,114,42,32,116,101,120,116,69,100,105,116,111,114,32,61,32,110,101,119,32,84,101,120,116,69,100,105,116,111,114,40,41,59,13,10, - 32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,116,101,120,116,69,100,105,116,111,114,41, - 59,13,10,32,32,32,32,116,101,120,116,69,100,105,116,111,114,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,50,53,44,32,50,48, - 48,44,32,50,52,41,59,13,10,32,32,32,32,116,101,120,116,69,100,105,116,111,114,45,62,115,101,116,84,101,120,116,32,40,84,40,34,115,105,110, - 103,108,101,45,108,105,110,101,32,116,101,120,116,32,98,111,120,34,41,41,59,13,10,13,10,32,32,32,32,116,101,120,116,69,100,105,116,111,114,32, - 61,32,110,101,119,32,84,101,120,116,69,100,105,116,111,114,32,40,84,40,34,112,97,115,115,119,111,114,100,34,41,44,32,40,116,99,104,97,114,41, - 32,48,120,50,48,50,50,41,59,13,10,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40, - 116,101,120,116,69,100,105,116,111,114,41,59,13,10,32,32,32,32,116,101,120,116,69,100,105,116,111,114,45,62,115,101,116,66,111,117,110,100,115,32, - 40,49,48,44,32,53,53,44,32,50,48,48,44,32,50,52,41,59,13,10,32,32,32,32,116,101,120,116,69,100,105,116,111,114,45,62,115,101,116,84, - 101,120,116,32,40,84,40,34,112,97,115,115,119,111,114,100,34,41,41,59,13,10,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,115,116,97,116,105,99,32,67,111,109,112,111, + 110,101,110,116,42,32,99,114,101,97,116,101,77,105,115,99,80,97,103,101,40,41,13,10,123,13,10,32,32,32,32,68,101,109,111,80,97,103,101,67, + 111,109,112,42,32,112,97,103,101,32,61,32,110,101,119,32,68,101,109,111,80,97,103,101,67,111,109,112,40,41,59,13,10,13,10,32,32,32,32,84, + 101,120,116,69,100,105,116,111,114,42,32,116,101,120,116,69,100,105,116,111,114,32,61,32,110,101,119,32,84,101,120,116,69,100,105,116,111,114,40,41, + 59,13,10,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,116,101,120,116,69,100,105,116, + 111,114,41,59,13,10,32,32,32,32,116,101,120,116,69,100,105,116,111,114,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,50,53,44, + 32,50,48,48,44,32,50,52,41,59,13,10,32,32,32,32,116,101,120,116,69,100,105,116,111,114,45,62,115,101,116,84,101,120,116,32,40,84,40,34, + 115,105,110,103,108,101,45,108,105,110,101,32,116,101,120,116,32,98,111,120,34,41,41,59,13,10,13,10,32,32,32,32,116,101,120,116,69,100,105,116, + 111,114,32,61,32,110,101,119,32,84,101,120,116,69,100,105,116,111,114,32,40,84,40,34,112,97,115,115,119,111,114,100,34,41,44,32,40,116,99,104, + 97,114,41,32,48,120,50,48,50,50,41,59,13,10,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108, + 101,32,40,116,101,120,116,69,100,105,116,111,114,41,59,13,10,32,32,32,32,116,101,120,116,69,100,105,116,111,114,45,62,115,101,116,66,111,117,110, + 100,115,32,40,49,48,44,32,53,53,44,32,50,48,48,44,32,50,52,41,59,13,10,32,32,32,32,116,101,120,116,69,100,105,116,111,114,45,62,115, + 101,116,84,101,120,116,32,40,84,40,34,112,97,115,115,119,111,114,100,34,41,41,59,13,10,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,67,111,109,98,111,66, - 111,120,42,32,99,111,109,98,111,66,111,120,32,61,32,110,101,119,32,67,111,109,98,111,66,111,120,32,40,84,40,34,99,111,109,98,111,34,41,41, - 59,13,10,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,99,111,109,98,111,66,111,120, - 41,59,13,10,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101,116,66,111,117,110,100,115,32,40,51,48,48,44,32,50,53,44,32,50,48, - 48,44,32,50,52,41,59,13,10,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101,116,69,100,105,116,97,98,108,101,84,101,120,116,32,40, - 116,114,117,101,41,59,13,10,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101,116,74,117,115,116,105,102,105,99,97,116,105,111,110,84,121, - 112,101,32,40,74,117,115,116,105,102,105,99,97,116,105,111,110,58,58,99,101,110,116,114,101,100,41,59,13,10,13,10,32,32,32,32,105,110,116,32, - 105,59,13,10,32,32,32,32,102,111,114,32,40,105,32,61,32,49,59,32,105,32,60,32,49,48,48,59,32,43,43,105,41,13,10,32,32,32,32,32, - 32,32,32,99,111,109,98,111,66,111,120,45,62,97,100,100,73,116,101,109,32,40,84,40,34,99,111,109,98,111,32,98,111,120,32,105,116,101,109,32, - 34,41,32,43,32,83,116,114,105,110,103,32,40,105,41,44,32,105,41,59,13,10,13,10,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101, - 116,83,101,108,101,99,116,101,100,73,100,32,40,49,41,59,13,10,13,10,32,32,32,32,68,114,97,103,79,110,116,111,68,101,115,107,116,111,112,68, - 101,109,111,67,111,109,112,42,32,100,32,61,32,110,101,119,32,68,114,97,103,79,110,116,111,68,101,115,107,116,111,112,68,101,109,111,67,111,109,112, - 32,40,112,97,103,101,41,59,13,10,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,100, - 41,59,13,10,32,32,32,32,100,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,44,32,49,48,48,44,32,50,48,48,44,32,56,48,41,59, - 13,10,13,10,32,32,32,32,114,101,116,117,114,110,32,112,97,103,101,59,13,10,125,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,67,111,109, + 98,111,66,111,120,42,32,99,111,109,98,111,66,111,120,32,61,32,110,101,119,32,67,111,109,98,111,66,111,120,32,40,84,40,34,99,111,109,98,111, + 34,41,41,59,13,10,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,99,111,109,98,111, + 66,111,120,41,59,13,10,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101,116,66,111,117,110,100,115,32,40,51,48,48,44,32,50,53,44, + 32,50,48,48,44,32,50,52,41,59,13,10,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101,116,69,100,105,116,97,98,108,101,84,101,120, + 116,32,40,116,114,117,101,41,59,13,10,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101,116,74,117,115,116,105,102,105,99,97,116,105,111, + 110,84,121,112,101,32,40,74,117,115,116,105,102,105,99,97,116,105,111,110,58,58,99,101,110,116,114,101,100,41,59,13,10,13,10,32,32,32,32,105, + 110,116,32,105,59,13,10,32,32,32,32,102,111,114,32,40,105,32,61,32,49,59,32,105,32,60,32,49,48,48,59,32,43,43,105,41,13,10,32,32, + 32,32,32,32,32,32,99,111,109,98,111,66,111,120,45,62,97,100,100,73,116,101,109,32,40,84,40,34,99,111,109,98,111,32,98,111,120,32,105,116, + 101,109,32,34,41,32,43,32,83,116,114,105,110,103,32,40,105,41,44,32,105,41,59,13,10,13,10,32,32,32,32,99,111,109,98,111,66,111,120,45, + 62,115,101,116,83,101,108,101,99,116,101,100,73,100,32,40,49,41,59,13,10,13,10,32,32,32,32,68,114,97,103,79,110,116,111,68,101,115,107,116, + 111,112,68,101,109,111,67,111,109,112,42,32,100,32,61,32,110,101,119,32,68,114,97,103,79,110,116,111,68,101,115,107,116,111,112,68,101,109,111,67, + 111,109,112,32,40,112,97,103,101,41,59,13,10,32,32,32,32,112,97,103,101,45,62,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101, + 32,40,100,41,59,13,10,32,32,32,32,100,45,62,115,101,116,66,111,117,110,100,115,32,40,50,48,44,32,49,48,48,44,32,50,48,48,44,32,56, + 48,41,59,13,10,13,10,32,32,32,32,114,101,116,117,114,110,32,112,97,103,101,59,13,10,125,13,10,13,10,47,47,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,99,108,97,115,115,32,84,111,111,108,98, - 97,114,68,101,109,111,67,111,109,112,32,32,32,58,32,112,117,98,108,105,99,32,67,111,109,112,111,110,101,110,116,44,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,83,108,105,100,101,114,76,105,115,116,101,110,101, - 114,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,66,117,116, - 116,111,110,76,105,115,116,101,110,101,114,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,84,111,111,108,98,97,114,68,101,109,111, - 67,111,109,112,32,40,65,112,112,108,105,99,97,116,105,111,110,67,111,109,109,97,110,100,77,97,110,97,103,101,114,42,32,99,111,109,109,97,110,100, - 77,97,110,97,103,101,114,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,67,114,101,97,116,101,32,97,110,100,32,97, - 100,100,32,116,104,101,32,116,111,111,108,98,97,114,46,46,46,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115, - 105,98,108,101,32,40,116,111,111,108,98,97,114,32,61,32,110,101,119,32,84,111,111,108,98,97,114,40,41,41,59,13,10,13,10,32,32,32,32,32, - 32,32,32,47,47,32,65,110,100,32,117,115,101,32,111,117,114,32,105,116,101,109,32,102,97,99,116,111,114,121,32,116,111,32,97,100,100,32,97,32, - 115,101,116,32,111,102,32,100,101,102,97,117,108,116,32,105,99,111,110,115,32,116,111,32,105,116,46,46,46,13,10,32,32,32,32,32,32,32,32,116, - 111,111,108,98,97,114,45,62,97,100,100,68,101,102,97,117,108,116,73,116,101,109,115,32,40,102,97,99,116,111,114,121,41,59,13,10,13,10,32,32, - 32,32,32,32,32,32,47,47,32,78,111,119,32,119,101,39,108,108,32,106,117,115,116,32,99,114,101,97,116,101,32,116,104,101,32,111,116,104,101,114, - 32,115,108,105,100,101,114,115,32,97,110,100,32,98,117,116,116,111,110,115,32,111,110,32,116,104,101,32,100,101,109,111,32,112,97,103,101,44,32,119, - 104,105,99,104,32,97,100,106,117,115,116,13,10,32,32,32,32,32,32,32,32,47,47,32,116,104,101,32,116,111,111,108,98,97,114,39,115,32,112,114, - 111,112,101,114,116,105,101,115,46,46,46,13,10,32,32,32,32,32,32,32,32,76,97,98,101,108,42,32,105,110,102,111,32,61,32,110,101,119,32,76, - 97,98,101,108,32,40,83,116,114,105,110,103,58,58,101,109,112,116,121,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,34,65,115,32,119,101, - 108,108,32,97,115,32,115,104,111,119,105,110,103,32,111,102,102,32,116,111,111,108,98,97,114,115,44,32,116,104,105,115,32,100,101,109,111,32,105,108, - 108,117,115,116,114,97,116,101,115,32,104,111,119,32,116,111,32,115,116,111,114,101,32,34,13,10,32,32,32,32,32,32,32,32,32,32,32,32,34,97, - 32,115,101,116,32,111,102,32,83,86,71,32,102,105,108,101,115,32,105,110,32,97,32,90,105,112,32,102,105,108,101,44,32,101,109,98,101,100,32,116, - 104,97,116,32,105,110,32,121,111,117,114,32,97,112,112,108,105,99,97,116,105,111,110,44,32,97,110,100,32,114,101,97,100,32,34,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,34,116,104,101,109,32,98,97,99,107,32,105,110,32,97,116,32,114,117,110,116,105,109,101,46,92,110,92,110,84,104, - 101,32,105,99,111,110,32,105,109,97,103,101,115,32,104,101,114,101,32,97,114,101,32,116,97,107,101,110,32,102,114,111,109,32,116,104,101,32,111,112, - 101,110,45,115,111,117,114,99,101,32,34,13,10,32,32,32,32,32,32,32,32,32,32,32,32,34,84,97,110,103,111,32,105,99,111,110,32,112,114,111, - 106,101,99,116,46,34,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,105, - 110,102,111,41,59,13,10,32,32,32,32,32,32,32,32,105,110,102,111,45,62,115,101,116,74,117,115,116,105,102,105,99,97,116,105,111,110,84,121,112, - 101,32,40,74,117,115,116,105,102,105,99,97,116,105,111,110,58,58,116,111,112,76,101,102,116,41,59,13,10,32,32,32,32,32,32,32,32,105,110,102, - 111,45,62,115,101,116,66,111,117,110,100,115,32,40,56,48,44,32,56,48,44,32,52,53,48,44,32,49,48,48,41,59,13,10,32,32,32,32,32,32, - 32,32,105,110,102,111,45,62,115,101,116,73,110,116,101,114,99,101,112,116,115,77,111,117,115,101,67,108,105,99,107,115,32,40,102,97,108,115,101,44, - 32,102,97,108,115,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,100, - 101,112,116,104,83,108,105,100,101,114,32,61,32,110,101,119,32,83,108,105,100,101,114,32,40,84,40,34,116,111,111,108,98,97,114,32,100,101,112,116, - 104,58,34,41,41,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105,100,101,114,45,62,115,101,116,82,97,110,103,101,32,40, - 49,48,46,48,44,32,50,48,48,46,48,44,32,49,46,48,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105,100,101,114,45, - 62,115,101,116,86,97,108,117,101,32,40,53,48,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105, - 100,101,114,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,76,105,110,101,97,114,72,111,114,105,122, - 111,110,116,97,108,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105,100,101,114,45,62,115,101,116,84,101,120,116,66,111,120, - 83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84,101,120,116,66,111,120,76,101,102,116,44,32,102,97,108,115,101,44,32,56,48,44,32,50, - 48,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105,100,101,114,45,62,97,100,100,76,105,115,116,101,110,101,114,32,40,116, - 104,105,115,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105,100,101,114,45,62,115,101,116,66,111,117,110,100,115,32,40,56, - 48,44,32,50,49,48,44,32,51,48,48,44,32,50,50,41,59,13,10,32,32,32,32,32,32,32,32,40,110,101,119,32,76,97,98,101,108,32,40,100, - 101,112,116,104,83,108,105,100,101,114,45,62,103,101,116,78,97,109,101,40,41,44,32,100,101,112,116,104,83,108,105,100,101,114,45,62,103,101,116,78, - 97,109,101,40,41,41,41,45,62,97,116,116,97,99,104,84,111,67,111,109,112,111,110,101,110,116,32,40,100,101,112,116,104,83,108,105,100,101,114,44, - 32,102,97,108,115,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,111, - 114,105,101,110,116,97,116,105,111,110,66,117,116,116,111,110,32,61,32,110,101,119,32,84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,118,101, - 114,116,105,99,97,108,47,104,111,114,105,122,111,110,116,97,108,34,41,41,41,59,13,10,32,32,32,32,32,32,32,32,111,114,105,101,110,116,97,116, - 105,111,110,66,117,116,116,111,110,45,62,97,100,100,66,117,116,116,111,110,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,13,10,32,32, - 32,32,32,32,32,32,111,114,105,101,110,116,97,116,105,111,110,66,117,116,116,111,110,45,62,99,104,97,110,103,101,87,105,100,116,104,84,111,70,105, - 116,84,101,120,116,32,40,50,50,41,59,13,10,32,32,32,32,32,32,32,32,111,114,105,101,110,116,97,116,105,111,110,66,117,116,116,111,110,45,62, - 115,101,116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110,32,40,100,101,112,116,104,83,108,105,100,101,114,45,62,103,101,116,88,40,41,44, - 32,100,101,112,116,104,83,108,105,100,101,114,45,62,103,101,116,66,111,116,116,111,109,40,41,32,43,32,50,48,41,59,13,10,13,10,32,32,32,32, - 32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,99,117,115,116,111,109,105,115,101,66,117,116,116,111,110,32,61, - 32,110,101,119,32,84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,99,117,115,116,111,109,105,115,101,46,46,46,34,41,41,41,59,13,10,32, - 32,32,32,32,32,32,32,99,117,115,116,111,109,105,115,101,66,117,116,116,111,110,45,62,97,100,100,66,117,116,116,111,110,76,105,115,116,101,110,101, - 114,32,40,116,104,105,115,41,59,13,10,32,32,32,32,32,32,32,32,99,117,115,116,111,109,105,115,101,66,117,116,116,111,110,45,62,99,104,97,110, - 103,101,87,105,100,116,104,84,111,70,105,116,84,101,120,116,32,40,50,50,41,59,13,10,32,32,32,32,32,32,32,32,99,117,115,116,111,109,105,115, - 101,66,117,116,116,111,110,45,62,115,101,116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110,32,40,111,114,105,101,110,116,97,116,105,111,110, - 66,117,116,116,111,110,45,62,103,101,116,82,105,103,104,116,40,41,32,43,32,50,48,44,32,111,114,105,101,110,116,97,116,105,111,110,66,117,116,116, - 111,110,45,62,103,101,116,89,40,41,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,84,111,111,108,98,97,114,68,101,109,111,67, - 111,109,112,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65,108,108,67,104,105,108,100,114,101,110,40, - 41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,114,101,115,105,122,101,100,40,41,13,10,32,32,32,32,123,13,10, - 32,32,32,32,32,32,32,32,105,102,32,40,116,111,111,108,98,97,114,45,62,105,115,86,101,114,116,105,99,97,108,40,41,41,13,10,32,32,32,32, - 32,32,32,32,32,32,32,32,116,111,111,108,98,97,114,45,62,115,101,116,66,111,117,110,100,115,32,40,48,44,32,48,44,32,40,105,110,116,41,32, - 100,101,112,116,104,83,108,105,100,101,114,45,62,103,101,116,86,97,108,117,101,40,41,44,32,103,101,116,72,101,105,103,104,116,40,41,41,59,13,10, - 32,32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,111,111,108,98,97,114,45,62,115,101,116,66,111, - 117,110,100,115,32,40,48,44,32,48,44,32,103,101,116,87,105,100,116,104,40,41,44,32,40,105,110,116,41,32,100,101,112,116,104,83,108,105,100,101, - 114,45,62,103,101,116,86,97,108,117,101,40,41,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,115,108,105,100,101, - 114,86,97,108,117,101,67,104,97,110,103,101,100,32,40,83,108,105,100,101,114,42,32,115,108,105,100,101,114,41,13,10,32,32,32,32,123,13,10,32, - 32,32,32,32,32,32,32,114,101,115,105,122,101,100,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,98,117,116, - 116,111,110,67,108,105,99,107,101,100,32,40,66,117,116,116,111,110,42,32,98,117,116,116,111,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32, - 32,32,32,32,105,102,32,40,98,117,116,116,111,110,32,61,61,32,111,114,105,101,110,116,97,116,105,111,110,66,117,116,116,111,110,41,13,10,32,32, - 32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,111,111,108,98,97,114,45,62,115,101,116,86,101,114,116,105,99,97, - 108,32,40,33,32,116,111,111,108,98,97,114,45,62,105,115,86,101,114,116,105,99,97,108,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32, - 32,32,114,101,115,105,122,101,100,40,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102, - 32,40,98,117,116,116,111,110,32,61,61,32,99,117,115,116,111,109,105,115,101,66,117,116,116,111,110,41,13,10,32,32,32,32,32,32,32,32,123,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,116,111,111,108,98,97,114,45,62,115,104,111,119,67,117,115,116,111,109,105,115,97,116,105,111,110,68, - 105,97,108,111,103,32,40,102,97,99,116,111,114,121,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,13,10,112,114, - 105,118,97,116,101,58,13,10,32,32,32,32,84,111,111,108,98,97,114,42,32,116,111,111,108,98,97,114,59,13,10,32,32,32,32,83,108,105,100,101, - 114,42,32,100,101,112,116,104,83,108,105,100,101,114,59,13,10,32,32,32,32,84,101,120,116,66,117,116,116,111,110,42,32,111,114,105,101,110,116,97, - 116,105,111,110,66,117,116,116,111,110,59,13,10,32,32,32,32,84,101,120,116,66,117,116,116,111,110,42,32,99,117,115,116,111,109,105,115,101,66,117, - 116,116,111,110,59,13,10,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,99,108,97,115,115,32,84,111, + 111,108,98,97,114,68,101,109,111,67,111,109,112,32,32,32,58,32,112,117,98,108,105,99,32,67,111,109,112,111,110,101,110,116,44,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,83,108,105,100,101,114,76,105,115,116, + 101,110,101,114,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32, + 66,117,116,116,111,110,76,105,115,116,101,110,101,114,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,84,111,111,108,98,97,114,68, + 101,109,111,67,111,109,112,32,40,65,112,112,108,105,99,97,116,105,111,110,67,111,109,109,97,110,100,77,97,110,97,103,101,114,42,32,99,111,109,109, + 97,110,100,77,97,110,97,103,101,114,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,67,114,101,97,116,101,32,97,110, + 100,32,97,100,100,32,116,104,101,32,116,111,111,108,98,97,114,46,46,46,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101, + 86,105,115,105,98,108,101,32,40,116,111,111,108,98,97,114,32,61,32,110,101,119,32,84,111,111,108,98,97,114,40,41,41,59,13,10,13,10,32,32, + 32,32,32,32,32,32,47,47,32,65,110,100,32,117,115,101,32,111,117,114,32,105,116,101,109,32,102,97,99,116,111,114,121,32,116,111,32,97,100,100, + 32,97,32,115,101,116,32,111,102,32,100,101,102,97,117,108,116,32,105,99,111,110,115,32,116,111,32,105,116,46,46,46,13,10,32,32,32,32,32,32, + 32,32,116,111,111,108,98,97,114,45,62,97,100,100,68,101,102,97,117,108,116,73,116,101,109,115,32,40,102,97,99,116,111,114,121,41,59,13,10,13, + 10,32,32,32,32,32,32,32,32,47,47,32,78,111,119,32,119,101,39,108,108,32,106,117,115,116,32,99,114,101,97,116,101,32,116,104,101,32,111,116, + 104,101,114,32,115,108,105,100,101,114,115,32,97,110,100,32,98,117,116,116,111,110,115,32,111,110,32,116,104,101,32,100,101,109,111,32,112,97,103,101, + 44,32,119,104,105,99,104,32,97,100,106,117,115,116,13,10,32,32,32,32,32,32,32,32,47,47,32,116,104,101,32,116,111,111,108,98,97,114,39,115, + 32,112,114,111,112,101,114,116,105,101,115,46,46,46,13,10,32,32,32,32,32,32,32,32,76,97,98,101,108,42,32,105,110,102,111,32,61,32,110,101, + 119,32,76,97,98,101,108,32,40,83,116,114,105,110,103,58,58,101,109,112,116,121,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,34,65,115, + 32,119,101,108,108,32,97,115,32,115,104,111,119,105,110,103,32,111,102,102,32,116,111,111,108,98,97,114,115,44,32,116,104,105,115,32,100,101,109,111, + 32,105,108,108,117,115,116,114,97,116,101,115,32,104,111,119,32,116,111,32,115,116,111,114,101,32,34,13,10,32,32,32,32,32,32,32,32,32,32,32, + 32,34,97,32,115,101,116,32,111,102,32,83,86,71,32,102,105,108,101,115,32,105,110,32,97,32,90,105,112,32,102,105,108,101,44,32,101,109,98,101, + 100,32,116,104,97,116,32,105,110,32,121,111,117,114,32,97,112,112,108,105,99,97,116,105,111,110,44,32,97,110,100,32,114,101,97,100,32,34,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,34,116,104,101,109,32,98,97,99,107,32,105,110,32,97,116,32,114,117,110,116,105,109,101,46,92,110,92, + 110,84,104,101,32,105,99,111,110,32,105,109,97,103,101,115,32,104,101,114,101,32,97,114,101,32,116,97,107,101,110,32,102,114,111,109,32,116,104,101, + 32,111,112,101,110,45,115,111,117,114,99,101,32,34,13,10,32,32,32,32,32,32,32,32,32,32,32,32,34,84,97,110,103,111,32,105,99,111,110,32, + 112,114,111,106,101,99,116,46,34,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101, + 32,40,105,110,102,111,41,59,13,10,32,32,32,32,32,32,32,32,105,110,102,111,45,62,115,101,116,74,117,115,116,105,102,105,99,97,116,105,111,110, + 84,121,112,101,32,40,74,117,115,116,105,102,105,99,97,116,105,111,110,58,58,116,111,112,76,101,102,116,41,59,13,10,32,32,32,32,32,32,32,32, + 105,110,102,111,45,62,115,101,116,66,111,117,110,100,115,32,40,56,48,44,32,56,48,44,32,52,53,48,44,32,49,48,48,41,59,13,10,32,32,32, + 32,32,32,32,32,105,110,102,111,45,62,115,101,116,73,110,116,101,114,99,101,112,116,115,77,111,117,115,101,67,108,105,99,107,115,32,40,102,97,108, + 115,101,44,32,102,97,108,115,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101, + 32,40,100,101,112,116,104,83,108,105,100,101,114,32,61,32,110,101,119,32,83,108,105,100,101,114,32,40,84,40,34,116,111,111,108,98,97,114,32,100, + 101,112,116,104,58,34,41,41,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105,100,101,114,45,62,115,101,116,82,97,110,103, + 101,32,40,49,48,46,48,44,32,50,48,48,46,48,44,32,49,46,48,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105,100, + 101,114,45,62,115,101,116,86,97,108,117,101,32,40,53,48,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104, + 83,108,105,100,101,114,45,62,115,101,116,83,108,105,100,101,114,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,76,105,110,101,97,114,72,111, + 114,105,122,111,110,116,97,108,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105,100,101,114,45,62,115,101,116,84,101,120,116, + 66,111,120,83,116,121,108,101,32,40,83,108,105,100,101,114,58,58,84,101,120,116,66,111,120,76,101,102,116,44,32,102,97,108,115,101,44,32,56,48, + 44,32,50,48,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105,100,101,114,45,62,97,100,100,76,105,115,116,101,110,101,114, + 32,40,116,104,105,115,41,59,13,10,32,32,32,32,32,32,32,32,100,101,112,116,104,83,108,105,100,101,114,45,62,115,101,116,66,111,117,110,100,115, + 32,40,56,48,44,32,50,49,48,44,32,51,48,48,44,32,50,50,41,59,13,10,32,32,32,32,32,32,32,32,40,110,101,119,32,76,97,98,101,108, + 32,40,100,101,112,116,104,83,108,105,100,101,114,45,62,103,101,116,78,97,109,101,40,41,44,32,100,101,112,116,104,83,108,105,100,101,114,45,62,103, + 101,116,78,97,109,101,40,41,41,41,45,62,97,116,116,97,99,104,84,111,67,111,109,112,111,110,101,110,116,32,40,100,101,112,116,104,83,108,105,100, + 101,114,44,32,102,97,108,115,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101, + 32,40,111,114,105,101,110,116,97,116,105,111,110,66,117,116,116,111,110,32,61,32,110,101,119,32,84,101,120,116,66,117,116,116,111,110,32,40,84,40, + 34,118,101,114,116,105,99,97,108,47,104,111,114,105,122,111,110,116,97,108,34,41,41,41,59,13,10,32,32,32,32,32,32,32,32,111,114,105,101,110, + 116,97,116,105,111,110,66,117,116,116,111,110,45,62,97,100,100,66,117,116,116,111,110,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,13, + 10,32,32,32,32,32,32,32,32,111,114,105,101,110,116,97,116,105,111,110,66,117,116,116,111,110,45,62,99,104,97,110,103,101,87,105,100,116,104,84, + 111,70,105,116,84,101,120,116,32,40,50,50,41,59,13,10,32,32,32,32,32,32,32,32,111,114,105,101,110,116,97,116,105,111,110,66,117,116,116,111, + 110,45,62,115,101,116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110,32,40,100,101,112,116,104,83,108,105,100,101,114,45,62,103,101,116,88, + 40,41,44,32,100,101,112,116,104,83,108,105,100,101,114,45,62,103,101,116,66,111,116,116,111,109,40,41,32,43,32,50,48,41,59,13,10,13,10,32, + 32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,99,117,115,116,111,109,105,115,101,66,117,116,116,111, + 110,32,61,32,110,101,119,32,84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,99,117,115,116,111,109,105,115,101,46,46,46,34,41,41,41,59, + 13,10,32,32,32,32,32,32,32,32,99,117,115,116,111,109,105,115,101,66,117,116,116,111,110,45,62,97,100,100,66,117,116,116,111,110,76,105,115,116, + 101,110,101,114,32,40,116,104,105,115,41,59,13,10,32,32,32,32,32,32,32,32,99,117,115,116,111,109,105,115,101,66,117,116,116,111,110,45,62,99, + 104,97,110,103,101,87,105,100,116,104,84,111,70,105,116,84,101,120,116,32,40,50,50,41,59,13,10,32,32,32,32,32,32,32,32,99,117,115,116,111, + 109,105,115,101,66,117,116,116,111,110,45,62,115,101,116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110,32,40,111,114,105,101,110,116,97,116, + 105,111,110,66,117,116,116,111,110,45,62,103,101,116,82,105,103,104,116,40,41,32,43,32,50,48,44,32,111,114,105,101,110,116,97,116,105,111,110,66, + 117,116,116,111,110,45,62,103,101,116,89,40,41,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,84,111,111,108,98,97,114,68,101, + 109,111,67,111,109,112,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65,108,108,67,104,105,108,100,114, + 101,110,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,114,101,115,105,122,101,100,40,41,13,10,32,32,32,32, + 123,13,10,32,32,32,32,32,32,32,32,105,102,32,40,116,111,111,108,98,97,114,45,62,105,115,86,101,114,116,105,99,97,108,40,41,41,13,10,32, + 32,32,32,32,32,32,32,32,32,32,32,116,111,111,108,98,97,114,45,62,115,101,116,66,111,117,110,100,115,32,40,48,44,32,48,44,32,40,105,110, + 116,41,32,100,101,112,116,104,83,108,105,100,101,114,45,62,103,101,116,86,97,108,117,101,40,41,44,32,103,101,116,72,101,105,103,104,116,40,41,41, + 59,13,10,32,32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,111,111,108,98,97,114,45,62,115,101, + 116,66,111,117,110,100,115,32,40,48,44,32,48,44,32,103,101,116,87,105,100,116,104,40,41,44,32,40,105,110,116,41,32,100,101,112,116,104,83,108, + 105,100,101,114,45,62,103,101,116,86,97,108,117,101,40,41,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,115,108, + 105,100,101,114,86,97,108,117,101,67,104,97,110,103,101,100,32,40,83,108,105,100,101,114,42,32,115,108,105,100,101,114,41,13,10,32,32,32,32,123, + 13,10,32,32,32,32,32,32,32,32,114,101,115,105,122,101,100,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32, + 98,117,116,116,111,110,67,108,105,99,107,101,100,32,40,66,117,116,116,111,110,42,32,98,117,116,116,111,110,41,13,10,32,32,32,32,123,13,10,32, + 32,32,32,32,32,32,32,105,102,32,40,98,117,116,116,111,110,32,61,61,32,111,114,105,101,110,116,97,116,105,111,110,66,117,116,116,111,110,41,13, + 10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,111,111,108,98,97,114,45,62,115,101,116,86,101,114,116, + 105,99,97,108,32,40,33,32,116,111,111,108,98,97,114,45,62,105,115,86,101,114,116,105,99,97,108,40,41,41,59,13,10,32,32,32,32,32,32,32, + 32,32,32,32,32,114,101,115,105,122,101,100,40,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,101,108,115,101, + 32,105,102,32,40,98,117,116,116,111,110,32,61,61,32,99,117,115,116,111,109,105,115,101,66,117,116,116,111,110,41,13,10,32,32,32,32,32,32,32, + 32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,111,111,108,98,97,114,45,62,115,104,111,119,67,117,115,116,111,109,105,115,97,116,105, + 111,110,68,105,97,108,111,103,32,40,102,97,99,116,111,114,121,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,13, + 10,112,114,105,118,97,116,101,58,13,10,32,32,32,32,84,111,111,108,98,97,114,42,32,116,111,111,108,98,97,114,59,13,10,32,32,32,32,83,108, + 105,100,101,114,42,32,100,101,112,116,104,83,108,105,100,101,114,59,13,10,32,32,32,32,84,101,120,116,66,117,116,116,111,110,42,32,111,114,105,101, + 110,116,97,116,105,111,110,66,117,116,116,111,110,59,13,10,32,32,32,32,84,101,120,116,66,117,116,116,111,110,42,32,99,117,115,116,111,109,105,115, + 101,66,117,116,116,111,110,59,13,10,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,99,108,97,115,115,32,68,101,109,111,84,111,111,108,98,97,114,73,116,101,109, - 70,97,99,116,111,114,121,32,32,32,58,32,112,117,98,108,105,99,32,84,111,111,108,98,97,114,73,116,101,109,70,97,99,116,111,114,121,13,10,32, - 32,32,32,123,13,10,32,32,32,32,112,117,98,108,105,99,58,13,10,32,32,32,32,32,32,32,32,68,101,109,111,84,111,111,108,98,97,114,73,116, - 101,109,70,97,99,116,111,114,121,40,41,32,123,125,13,10,32,32,32,32,32,32,32,32,126,68,101,109,111,84,111,111,108,98,97,114,73,116,101,109, - 70,97,99,116,111,114,121,40,41,32,123,125,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,99,108,97,115,115,32,68,101,109,111,84,111,111,108,98,97,114,73, + 116,101,109,70,97,99,116,111,114,121,32,32,32,58,32,112,117,98,108,105,99,32,84,111,111,108,98,97,114,73,116,101,109,70,97,99,116,111,114,121, + 13,10,32,32,32,32,123,13,10,32,32,32,32,112,117,98,108,105,99,58,13,10,32,32,32,32,32,32,32,32,68,101,109,111,84,111,111,108,98,97, + 114,73,116,101,109,70,97,99,116,111,114,121,40,41,32,123,125,13,10,32,32,32,32,32,32,32,32,126,68,101,109,111,84,111,111,108,98,97,114,73, + 116,101,109,70,97,99,116,111,114,121,40,41,32,123,125,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,47,47,32,69,97,99, - 104,32,116,121,112,101,32,111,102,32,105,116,101,109,32,97,32,116,111,111,108,98,97,114,32,99,97,110,32,99,111,110,116,97,105,110,32,109,117,115, - 116,32,98,101,32,103,105,118,101,110,32,97,32,117,110,105,113,117,101,32,73,68,46,32,84,104,101,115,101,13,10,32,32,32,32,32,32,32,32,47, - 47,32,97,114,101,32,116,104,101,32,111,110,101,115,32,119,101,39,108,108,32,117,115,101,32,105,110,32,116,104,105,115,32,100,101,109,111,46,13,10, - 32,32,32,32,32,32,32,32,101,110,117,109,32,68,101,109,111,84,111,111,108,98,97,114,73,116,101,109,73,100,115,13,10,32,32,32,32,32,32,32, - 32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,111,99,95,110,101,119,32,32,32,32,32,32,32,32,32,61,32,49,44,13,10,32,32, - 32,32,32,32,32,32,32,32,32,32,100,111,99,95,111,112,101,110,32,32,32,32,32,32,32,32,61,32,50,44,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,100,111,99,95,115,97,118,101,32,32,32,32,32,32,32,32,61,32,51,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,111, - 99,95,115,97,118,101,65,115,32,32,32,32,32,32,61,32,52,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,101,100,105,116,95,99,111,112, - 121,32,32,32,32,32,32,32,61,32,53,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,101,100,105,116,95,99,117,116,32,32,32,32,32,32, - 32,32,61,32,54,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,101,100,105,116,95,112,97,115,116,101,32,32,32,32,32,32,61,32,55,44, - 13,10,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,76,111,103,111,66,117,116,116,111,110,32,32,61,32,56,44,13,10,32,32,32,32, - 32,32,32,32,32,32,32,32,99,117,115,116,111,109,67,111,109,98,111,66,111,120,32,32,61,32,57,13,10,32,32,32,32,32,32,32,32,125,59,13, - 10,13,10,32,32,32,32,32,32,32,32,118,111,105,100,32,103,101,116,65,108,108,84,111,111,108,98,97,114,73,116,101,109,73,100,115,32,40,65,114, - 114,97,121,32,60,105,110,116,62,38,32,105,100,115,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 47,47,32,84,104,105,115,32,114,101,116,117,114,110,115,32,116,104,101,32,99,111,109,112,108,101,116,101,32,108,105,115,116,32,111,102,32,97,108,108, - 32,105,116,101,109,32,73,68,115,32,116,104,97,116,32,97,114,101,32,97,108,108,111,119,101,100,32,116,111,13,10,32,32,32,32,32,32,32,32,32, - 32,32,32,47,47,32,103,111,32,105,110,32,111,117,114,32,116,111,111,108,98,97,114,46,32,65,110,121,32,105,116,101,109,115,32,121,111,117,32,109, - 105,103,104,116,32,119,97,110,116,32,116,111,32,97,100,100,32,109,117,115,116,32,98,101,32,108,105,115,116,101,100,32,104,101,114,101,46,32,84,104, - 101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,111,114,100,101,114,32,105,110,32,119,104,105,99,104,32,116,104,101,121,32,97,114, - 101,32,108,105,115,116,101,100,32,119,105,108,108,32,98,101,32,117,115,101,100,32,98,121,32,116,104,101,32,116,111,111,108,98,97,114,32,99,117,115, - 116,111,109,105,115,97,116,105,111,110,32,112,97,110,101,108,46,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100, - 32,40,100,111,99,95,110,101,119,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,111,112, - 101,110,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,115,97,118,101,41,59,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,115,97,118,101,65,115,41,59,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,101,100,105,116,95,99,111,112,121,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 105,100,115,46,97,100,100,32,40,101,100,105,116,95,99,117,116,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100, - 32,40,101,100,105,116,95,112,97,115,116,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,106,117,99, - 101,76,111,103,111,66,117,116,116,111,110,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,99,117,115,116, - 111,109,67,111,109,98,111,66,111,120,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,73,102,32,121,111,117,39,114,101, - 32,103,111,105,110,103,32,116,111,32,117,115,101,32,115,101,112,97,114,97,116,111,114,115,44,32,116,104,101,110,32,116,104,101,121,32,109,117,115,116, - 32,97,108,115,111,32,98,101,32,97,100,100,101,100,32,101,120,112,108,105,99,105,116,108,121,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47, - 47,32,116,111,32,116,104,101,32,108,105,115,116,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,115,101,112, - 97,114,97,116,111,114,66,97,114,73,100,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,115,112,97,99, - 101,114,73,100,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,102,108,101,120,105,98,108,101,83,112,97, - 99,101,114,73,100,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,118,111,105,100,32,103,101,116,68,101, - 102,97,117,108,116,73,116,101,109,83,101,116,32,40,65,114,114,97,121,32,60,105,110,116,62,38,32,105,100,115,41,13,10,32,32,32,32,32,32,32, - 32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,84,104,105,115,32,114,101,116,117,114,110,115,32,97,110,32,111,114,100,101,114, - 101,100,32,108,105,115,116,32,111,102,32,116,104,101,32,115,101,116,32,111,102,32,105,116,101,109,115,32,116,104,97,116,32,109,97,107,101,32,117,112, - 32,97,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,116,111,111,108,98,97,114,39,115,32,100,101,102,97,117,108,116,32,115,101,116, - 46,32,78,111,116,32,97,108,108,32,105,116,101,109,115,32,110,101,101,100,32,116,111,32,98,101,32,111,110,32,116,104,105,115,32,108,105,115,116,44, - 32,97,110,100,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,105,116,101,109,115,32,99,97,110,32,97,112,112,101,97,114,32,109,117, - 108,116,105,112,108,101,32,116,105,109,101,115,32,40,101,46,103,46,32,116,104,101,32,115,101,112,97,114,97,116,111,114,115,32,117,115,101,100,32,104, - 101,114,101,41,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,110,101,119,41,59,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,111,112,101,110,41,59,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,115,97,118,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115, - 46,97,100,100,32,40,100,111,99,95,115,97,118,101,65,115,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32, - 40,115,112,97,99,101,114,73,100,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,115,101,112,97,114,97, - 116,111,114,66,97,114,73,100,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,101,100,105,116,95,99,111, - 112,121,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,101,100,105,116,95,99,117,116,41,59,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,101,100,105,116,95,112,97,115,116,101,41,59,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,115,101,112,97,114,97,116,111,114,66,97,114,73,100,41,59,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,105,100,115,46,97,100,100,32,40,102,108,101,120,105,98,108,101,83,112,97,99,101,114,73,100,41,59,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,99,117,115,116,111,109,67,111,109,98,111,66,111,120,41,59,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,105,100,115,46,97,100,100,32,40,102,108,101,120,105,98,108,101,83,112,97,99,101,114,73,100,41,59,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,115,101,112,97,114,97,116,111,114,66,97,114,73,100,41,59,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,105,100,115,46,97,100,100,32,40,106,117,99,101,76,111,103,111,66,117,116,116,111,110,41,59,13,10,32,32,32,32,32,32,32,32, - 125,13,10,13,10,32,32,32,32,32,32,32,32,84,111,111,108,98,97,114,73,116,101,109,67,111,109,112,111,110,101,110,116,42,32,99,114,101,97,116, - 101,73,116,101,109,32,40,99,111,110,115,116,32,105,110,116,32,105,116,101,109,73,100,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,115,119,105,116,99,104,32,40,105,116,101,109,73,100,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,100,111,99,95,110,101,119,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,114,101,116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,105, - 116,101,109,73,100,44,32,84,40,34,110,101,119,34,41,44,32,84,40,34,100,111,99,117,109,101,110,116,45,110,101,119,46,115,118,103,34,41,41,59, - 13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,100,111,99,95,111,112,101,110,58,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86, - 71,32,40,105,116,101,109,73,100,44,32,84,40,34,111,112,101,110,34,41,44,32,84,40,34,100,111,99,117,109,101,110,116,45,111,112,101,110,46,115, - 118,103,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,100,111,99,95,115,97,118,101,58,13,10,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112, - 70,105,108,101,83,86,71,32,40,105,116,101,109,73,100,44,32,84,40,34,115,97,118,101,34,41,44,32,84,40,34,100,111,99,117,109,101,110,116,45, - 115,97,118,101,46,115,118,103,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,100,111,99,95,115,97,118, - 101,65,115,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111, - 110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,105,116,101,109,73,100,44,32,84,40,34,115,97,118,101,32,97,115,34,41,44,32,84, - 40,34,100,111,99,117,109,101,110,116,45,115,97,118,101,45,97,115,46,115,118,103,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32, - 32,32,99,97,115,101,32,101,100,105,116,95,99,111,112,121,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114, - 110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,105,116,101,109,73,100,44,32,84,40, - 34,99,111,112,121,34,41,44,32,84,40,34,101,100,105,116,45,99,111,112,121,46,115,118,103,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,99,97,115,101,32,101,100,105,116,95,99,117,116,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116, - 117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,105,116,101,109,73,100,44,32, - 84,40,34,99,117,116,34,41,44,32,84,40,34,101,100,105,116,45,99,117,116,46,115,118,103,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,99,97,115,101,32,101,100,105,116,95,112,97,115,116,101,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114, - 101,116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,105,116,101,109,73,100, - 44,32,84,40,34,112,97,115,116,101,34,41,44,32,84,40,34,101,100,105,116,45,112,97,115,116,101,46,115,118,103,34,41,41,59,13,10,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,106,117,99,101,76,111,103,111,66,117,116,116,111,110,58,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,110,101,119,32,84,111,111,108,98,97,114,66,117,116,116,111,110,32,40,105,116,101,109,73, - 100,44,32,84,40,34,106,117,99,101,33,34,41,44,32,68,114,97,119,97,98,108,101,58,58,99,114,101,97,116,101,70,114,111,109,73,109,97,103,101, - 68,97,116,97,32,40,66,105,110,97,114,121,68,97,116,97,58,58,106,117,99,101,95,112,110,103,44,32,66,105,110,97,114,121,68,97,116,97,58,58, - 106,117,99,101,95,112,110,103,83,105,122,101,41,44,32,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,99, - 117,115,116,111,109,67,111,109,98,111,66,111,120,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,110, - 101,119,32,67,117,115,116,111,109,84,111,111,108,98,97,114,67,111,109,98,111,66,111,120,32,40,105,116,101,109,73,100,41,59,13,10,13,10,32,32, - 32,32,32,32,32,32,32,32,32,32,100,101,102,97,117,108,116,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97, - 107,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32, - 48,59,13,10,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,112,114,105,118,97,116,101,58,13,10,32,32,32,32,32,32,32,32,83, - 116,114,105,110,103,65,114,114,97,121,32,105,99,111,110,78,97,109,101,115,59,13,10,32,32,32,32,32,32,32,32,79,119,110,101,100,65,114,114,97, - 121,32,60,68,114,97,119,97,98,108,101,62,32,105,99,111,110,115,70,114,111,109,90,105,112,70,105,108,101,59,13,10,13,10,32,32,32,32,32,32, - 32,32,47,47,32,84,104,105,115,32,105,115,32,97,32,108,105,116,116,108,101,32,117,116,105,108,105,116,121,32,116,111,32,99,114,101,97,116,101,32, - 97,32,98,117,116,116,111,110,32,119,105,116,104,32,111,110,101,32,111,102,32,116,104,101,32,83,86,71,32,105,109,97,103,101,115,32,105,110,13,10, - 32,32,32,32,32,32,32,32,47,47,32,111,117,114,32,101,109,98,101,100,100,101,100,32,90,73,80,32,102,105,108,101,32,34,105,99,111,110,115,46, - 122,105,112,34,13,10,32,32,32,32,32,32,32,32,84,111,111,108,98,97,114,66,117,116,116,111,110,42,32,99,114,101,97,116,101,66,117,116,116,111, - 110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,99,111,110,115,116,32,105,110,116,32,105,116,101,109,73,100,44,32,99,111,110,115,116, - 32,83,116,114,105,110,103,38,32,116,101,120,116,44,32,99,111,110,115,116,32,83,116,114,105,110,103,38,32,102,105,108,101,110,97,109,101,41,13,10, - 32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,105,99,111,110,115,70,114,111,109,90,105,112,70, - 105,108,101,46,115,105,122,101,40,41,32,61,61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,47,47,32,73,102,32,119,101,39,118,101,32,110,111,116,32,97,108,114,101,97,100,121,32,100,111,110,101,32,115,111, - 44,32,108,111,97,100,32,97,108,108,32,116,104,101,32,105,109,97,103,101,115,32,102,114,111,109,32,116,104,101,32,122,105,112,32,102,105,108,101,46, - 46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,77,101,109,111,114,121,73,110,112,117,116,83,116,114,101,97,109,32,105,99,111, - 110,115,70,105,108,101,83,116,114,101,97,109,32,40,66,105,110,97,114,121,68,97,116,97,58,58,105,99,111,110,115,95,122,105,112,44,32,66,105,110, - 97,114,121,68,97,116,97,58,58,105,99,111,110,115,95,122,105,112,83,105,122,101,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,90,105,112,70,105,108,101,32,105,99,111,110,115,32,40,38,105,99,111,110,115,70,105,108,101,83,116,114,101,97,109, - 44,32,102,97,108,115,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,102,111,114,32,40,105,110,116,32,105,32, - 61,32,48,59,32,105,32,60,32,105,99,111,110,115,46,103,101,116,78,117,109,69,110,116,114,105,101,115,40,41,59,32,43,43,105,41,13,10,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,73,110,112, - 117,116,83,116,114,101,97,109,42,32,115,118,103,70,105,108,101,83,116,114,101,97,109,32,61,32,105,99,111,110,115,46,99,114,101,97,116,101,83,116, - 114,101,97,109,70,111,114,69,110,116,114,121,32,40,105,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,105,102,32,40,115,118,103,70,105,108,101,83,116,114,101,97,109,32,33,61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,99,111,110,78,97,109, - 101,115,46,97,100,100,32,40,105,99,111,110,115,46,103,101,116,69,110,116,114,121,40,105,41,45,62,102,105,108,101,110,97,109,101,41,59,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,99,111,110,115,70,114,111,109,90,105,112,70,105,108,101,46, - 97,100,100,32,40,68,114,97,119,97,98,108,101,58,58,99,114,101,97,116,101,70,114,111,109,73,109,97,103,101,68,97,116,97,83,116,114,101,97,109, - 32,40,42,115,118,103,70,105,108,101,83,116,114,101,97,109,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,100,101,108,101,116,101,32,115,118,103,70,105,108,101,83,116,114,101,97,109,59,13,10,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,68,114,97,119,97,98,108,101,42,32,105,109,97,103,101,32,61,32,105, - 99,111,110,115,70,114,111,109,90,105,112,70,105,108,101,32,91,105,99,111,110,78,97,109,101,115,46,105,110,100,101,120,79,102,32,40,102,105,108,101, - 110,97,109,101,41,93,45,62,99,114,101,97,116,101,67,111,112,121,40,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114, - 110,32,110,101,119,32,84,111,111,108,98,97,114,66,117,116,116,111,110,32,40,105,116,101,109,73,100,44,32,116,101,120,116,44,32,105,109,97,103,101, - 44,32,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,48,59,13,10,32,32,32,32,32,32,32,32, - 125,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,68,101,109,111,110,115,116,114,97,116,101,115,32,104,111,119,32,116,111,32,112,117,116,32, - 97,32,99,117,115,116,111,109,32,99,111,109,112,111,110,101,110,116,32,105,110,116,111,32,97,32,116,111,111,108,98,97,114,32,45,32,116,104,105,115, - 32,111,110,101,32,99,111,110,116,97,105,110,115,13,10,32,32,32,32,32,32,32,32,47,47,32,97,32,67,111,109,98,111,66,111,120,46,13,10,32, - 32,32,32,32,32,32,32,99,108,97,115,115,32,67,117,115,116,111,109,84,111,111,108,98,97,114,67,111,109,98,111,66,111,120,32,58,32,112,117,98, - 108,105,99,32,84,111,111,108,98,97,114,73,116,101,109,67,111,109,112,111,110,101,110,116,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32, - 32,32,32,32,32,112,117,98,108,105,99,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,67,117,115,116,111,109,84,111,111,108,98,97,114,67, - 111,109,98,111,66,111,120,32,40,99,111,110,115,116,32,105,110,116,32,116,111,111,108,98,97,114,73,116,101,109,73,100,41,13,10,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,58,32,84,111,111,108,98,97,114,73,116,101,109,67,111,109,112,111,110,101,110,116,32,40,116,111,111,108,98, - 97,114,73,116,101,109,73,100,44,32,84,40,34,67,117,115,116,111,109,32,84,111,111,108,98,97,114,32,73,116,101,109,34,41,44,32,102,97,108,115, - 101,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,97,100,100,65,110, - 100,77,97,107,101,86,105,115,105,98,108,101,32,40,99,111,109,98,111,66,111,120,32,61,32,110,101,119,32,67,111,109,98,111,66,111,120,32,40,84, - 40,34,100,101,109,111,32,116,111,111,108,98,97,114,32,99,111,109,98,111,32,98,111,120,34,41,41,41,59,13,10,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,102,111,114,32,40,105,110,116,32,105,32,61,32,49,59,32,105,32,60,32,50,48,59,32,43,43,105,41,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,109,98,111,66,111,120,45,62,97,100,100,73,116,101,109,32,40,84,40, - 34,84,111,111,108,98,97,114,32,67,111,109,98,111,66,111,120,32,105,116,101,109,32,34,41,32,43,32,83,116,114,105,110,103,32,40,105,41,44,32, - 105,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101,116,83,101,108,101, - 99,116,101,100,73,100,32,40,49,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115, - 101,116,69,100,105,116,97,98,108,101,84,101,120,116,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,126,67,117,115,116,111,109,84,111,111,108,98,97,114,67,111,109,98,111,66,111,120,40,41,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,100,101,108,101,116,101,32,99,111,109, - 98,111,66,111,120,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,111,111, - 108,32,103,101,116,84,111,111,108,98,97,114,73,116,101,109,83,105,122,101,115,32,40,105,110,116,32,116,111,111,108,98,97,114,68,101,112,116,104,44, - 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 98,111,111,108,32,105,115,84,111,111,108,98,97,114,86,101,114,116,105,99,97,108,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,110,116,38,32,112,114,101,102,101,114,114,101,100,83,105,122, - 101,44,32,105,110,116,38,32,109,105,110,83,105,122,101,44,32,105,110,116,38,32,109,97,120,83,105,122,101,41,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,105,115,84,111,111,108,98,97,114,86,101,114,116, - 105,99,97,108,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,102,97,108,115,101,59, - 13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,114,101,102,101,114,114,101,100,83,105,122,101,32,61,32,50,53,48,59, - 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,109,105,110,83,105,122,101,32,61,32,56,48,59,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,109,97,120,83,105,122,101,32,61,32,51,48,48,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,114,101,116,117,114,110,32,116,114,117,101,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,118,111,105,100,32,112,97,105,110,116,66,117,116,116,111,110,65,114,101,97,32,40,71,114,97,112,104,105,99,115,38,44,32,105,110,116, - 44,32,105,110,116,44,32,98,111,111,108,44,32,98,111,111,108,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32, - 32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,118,111,105,100,32,99,111,110,116,101,110,116,65,114,101,97, - 67,104,97,110,103,101,100,32,40,99,111,110,115,116,32,82,101,99,116,97,110,103,108,101,38,32,99,111,110,116,101,110,116,65,114,101,97,41,13,10, - 32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,109,98,111,66,111,120,45, - 62,115,101,116,83,105,122,101,32,40,99,111,110,116,101,110,116,65,114,101,97,46,103,101,116,87,105,100,116,104,40,41,32,45,32,50,44,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,106,109,105,110,32,40, - 99,111,110,116,101,110,116,65,114,101,97,46,103,101,116,72,101,105,103,104,116,40,41,32,45,32,50,44,32,50,50,41,41,59,13,10,13,10,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101,116,67,101,110,116,114,101,80,111,115,105,116,105,111, - 110,32,40,99,111,110,116,101,110,116,65,114,101,97,46,103,101,116,67,101,110,116,114,101,88,40,41,44,32,99,111,110,116,101,110,116,65,114,101,97, - 46,103,101,116,67,101,110,116,114,101,89,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32, - 32,32,112,114,105,118,97,116,101,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,67,111,109,98,111,66,111,120,42,32,99,111,109,98,111,66, - 111,120,59,13,10,32,32,32,32,32,32,32,32,125,59,13,10,32,32,32,32,125,59,13,10,13,10,32,32,32,32,68,101,109,111,84,111,111,108,98, - 97,114,73,116,101,109,70,97,99,116,111,114,121,32,102,97,99,116,111,114,121,59,13,10,125,59,13,10,13,10,47,47,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,47,47,32, + 69,97,99,104,32,116,121,112,101,32,111,102,32,105,116,101,109,32,97,32,116,111,111,108,98,97,114,32,99,97,110,32,99,111,110,116,97,105,110,32, + 109,117,115,116,32,98,101,32,103,105,118,101,110,32,97,32,117,110,105,113,117,101,32,73,68,46,32,84,104,101,115,101,13,10,32,32,32,32,32,32, + 32,32,47,47,32,97,114,101,32,116,104,101,32,111,110,101,115,32,119,101,39,108,108,32,117,115,101,32,105,110,32,116,104,105,115,32,100,101,109,111, + 46,13,10,32,32,32,32,32,32,32,32,101,110,117,109,32,68,101,109,111,84,111,111,108,98,97,114,73,116,101,109,73,100,115,13,10,32,32,32,32, + 32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,111,99,95,110,101,119,32,32,32,32,32,32,32,32,32,61,32,49,44,13, + 10,32,32,32,32,32,32,32,32,32,32,32,32,100,111,99,95,111,112,101,110,32,32,32,32,32,32,32,32,61,32,50,44,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,100,111,99,95,115,97,118,101,32,32,32,32,32,32,32,32,61,32,51,44,13,10,32,32,32,32,32,32,32,32,32,32,32, + 32,100,111,99,95,115,97,118,101,65,115,32,32,32,32,32,32,61,32,52,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,101,100,105,116,95, + 99,111,112,121,32,32,32,32,32,32,32,61,32,53,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,101,100,105,116,95,99,117,116,32,32,32, + 32,32,32,32,32,61,32,54,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,101,100,105,116,95,112,97,115,116,101,32,32,32,32,32,32,61, + 32,55,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,76,111,103,111,66,117,116,116,111,110,32,32,61,32,56,44,13,10,32, + 32,32,32,32,32,32,32,32,32,32,32,99,117,115,116,111,109,67,111,109,98,111,66,111,120,32,32,61,32,57,13,10,32,32,32,32,32,32,32,32, + 125,59,13,10,13,10,32,32,32,32,32,32,32,32,118,111,105,100,32,103,101,116,65,108,108,84,111,111,108,98,97,114,73,116,101,109,73,100,115,32, + 40,65,114,114,97,121,32,60,105,110,116,62,38,32,105,100,115,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,47,47,32,84,104,105,115,32,114,101,116,117,114,110,115,32,116,104,101,32,99,111,109,112,108,101,116,101,32,108,105,115,116,32,111,102,32, + 97,108,108,32,105,116,101,109,32,73,68,115,32,116,104,97,116,32,97,114,101,32,97,108,108,111,119,101,100,32,116,111,13,10,32,32,32,32,32,32, + 32,32,32,32,32,32,47,47,32,103,111,32,105,110,32,111,117,114,32,116,111,111,108,98,97,114,46,32,65,110,121,32,105,116,101,109,115,32,121,111, + 117,32,109,105,103,104,116,32,119,97,110,116,32,116,111,32,97,100,100,32,109,117,115,116,32,98,101,32,108,105,115,116,101,100,32,104,101,114,101,46, + 32,84,104,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,111,114,100,101,114,32,105,110,32,119,104,105,99,104,32,116,104,101,121, + 32,97,114,101,32,108,105,115,116,101,100,32,119,105,108,108,32,98,101,32,117,115,101,100,32,98,121,32,116,104,101,32,116,111,111,108,98,97,114,32, + 99,117,115,116,111,109,105,115,97,116,105,111,110,32,112,97,110,101,108,46,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46, + 97,100,100,32,40,100,111,99,95,110,101,119,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99, + 95,111,112,101,110,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,115,97,118,101,41,59, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,115,97,118,101,65,115,41,59,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,101,100,105,116,95,99,111,112,121,41,59,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,105,100,115,46,97,100,100,32,40,101,100,105,116,95,99,117,116,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46, + 97,100,100,32,40,101,100,105,116,95,112,97,115,116,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40, + 106,117,99,101,76,111,103,111,66,117,116,116,111,110,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,99, + 117,115,116,111,109,67,111,109,98,111,66,111,120,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,73,102,32,121,111,117, + 39,114,101,32,103,111,105,110,103,32,116,111,32,117,115,101,32,115,101,112,97,114,97,116,111,114,115,44,32,116,104,101,110,32,116,104,101,121,32,109, + 117,115,116,32,97,108,115,111,32,98,101,32,97,100,100,101,100,32,101,120,112,108,105,99,105,116,108,121,13,10,32,32,32,32,32,32,32,32,32,32, + 32,32,47,47,32,116,111,32,116,104,101,32,108,105,115,116,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40, + 115,101,112,97,114,97,116,111,114,66,97,114,73,100,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,115, + 112,97,99,101,114,73,100,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,102,108,101,120,105,98,108,101, + 83,112,97,99,101,114,73,100,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,118,111,105,100,32,103,101, + 116,68,101,102,97,117,108,116,73,116,101,109,83,101,116,32,40,65,114,114,97,121,32,60,105,110,116,62,38,32,105,100,115,41,13,10,32,32,32,32, + 32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,84,104,105,115,32,114,101,116,117,114,110,115,32,97,110,32,111,114, + 100,101,114,101,100,32,108,105,115,116,32,111,102,32,116,104,101,32,115,101,116,32,111,102,32,105,116,101,109,115,32,116,104,97,116,32,109,97,107,101, + 32,117,112,32,97,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,116,111,111,108,98,97,114,39,115,32,100,101,102,97,117,108,116,32, + 115,101,116,46,32,78,111,116,32,97,108,108,32,105,116,101,109,115,32,110,101,101,100,32,116,111,32,98,101,32,111,110,32,116,104,105,115,32,108,105, + 115,116,44,32,97,110,100,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,105,116,101,109,115,32,99,97,110,32,97,112,112,101,97,114, + 32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,32,40,101,46,103,46,32,116,104,101,32,115,101,112,97,114,97,116,111,114,115,32,117,115,101, + 100,32,104,101,114,101,41,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,110,101,119,41,59, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,111,112,101,110,41,59,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,100,111,99,95,115,97,118,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32, + 105,100,115,46,97,100,100,32,40,100,111,99,95,115,97,118,101,65,115,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97, + 100,100,32,40,115,112,97,99,101,114,73,100,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,115,101,112, + 97,114,97,116,111,114,66,97,114,73,100,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,101,100,105,116, + 95,99,111,112,121,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,101,100,105,116,95,99,117,116,41,59, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,101,100,105,116,95,112,97,115,116,101,41,59,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,115,101,112,97,114,97,116,111,114,66,97,114,73,100,41,59,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,102,108,101,120,105,98,108,101,83,112,97,99,101,114,73,100,41,59,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,99,117,115,116,111,109,67,111,109,98,111,66,111,120,41,59,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,102,108,101,120,105,98,108,101,83,112,97,99,101,114,73,100,41,59,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,115,101,112,97,114,97,116,111,114,66,97,114,73,100,41,59,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,105,100,115,46,97,100,100,32,40,106,117,99,101,76,111,103,111,66,117,116,116,111,110,41,59,13,10,32,32,32,32,32, + 32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,84,111,111,108,98,97,114,73,116,101,109,67,111,109,112,111,110,101,110,116,42,32,99,114, + 101,97,116,101,73,116,101,109,32,40,99,111,110,115,116,32,105,110,116,32,105,116,101,109,73,100,41,13,10,32,32,32,32,32,32,32,32,123,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,115,119,105,116,99,104,32,40,105,116,101,109,73,100,41,13,10,32,32,32,32,32,32,32,32,32,32,32, + 32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,100,111,99,95,110,101,119,58,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,114,101,116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86,71, + 32,40,105,116,101,109,73,100,44,32,84,40,34,110,101,119,34,41,44,32,84,40,34,100,111,99,117,109,101,110,116,45,110,101,119,46,115,118,103,34, + 41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,100,111,99,95,111,112,101,110,58,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112,70,105,108, + 101,83,86,71,32,40,105,116,101,109,73,100,44,32,84,40,34,111,112,101,110,34,41,44,32,84,40,34,100,111,99,117,109,101,110,116,45,111,112,101, + 110,46,115,118,103,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,100,111,99,95,115,97,118,101,58,13, + 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109, + 90,105,112,70,105,108,101,83,86,71,32,40,105,116,101,109,73,100,44,32,84,40,34,115,97,118,101,34,41,44,32,84,40,34,100,111,99,117,109,101, + 110,116,45,115,97,118,101,46,115,118,103,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,100,111,99,95, + 115,97,118,101,65,115,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,99,114,101,97,116,101,66,117, + 116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,105,116,101,109,73,100,44,32,84,40,34,115,97,118,101,32,97,115,34,41, + 44,32,84,40,34,100,111,99,117,109,101,110,116,45,115,97,118,101,45,97,115,46,115,118,103,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32, + 32,32,32,32,32,99,97,115,101,32,101,100,105,116,95,99,111,112,121,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101, + 116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,105,116,101,109,73,100,44, + 32,84,40,34,99,111,112,121,34,41,44,32,84,40,34,101,100,105,116,45,99,111,112,121,46,115,118,103,34,41,41,59,13,10,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,99,97,115,101,32,101,100,105,116,95,99,117,116,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 114,101,116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,105,116,101,109,73, + 100,44,32,84,40,34,99,117,116,34,41,44,32,84,40,34,101,100,105,116,45,99,117,116,46,115,118,103,34,41,41,59,13,10,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,99,97,115,101,32,101,100,105,116,95,112,97,115,116,101,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,114,101,116,117,114,110,32,99,114,101,97,116,101,66,117,116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,105,116,101, + 109,73,100,44,32,84,40,34,112,97,115,116,101,34,41,44,32,84,40,34,101,100,105,116,45,112,97,115,116,101,46,115,118,103,34,41,41,59,13,10, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115,101,32,106,117,99,101,76,111,103,111,66,117,116,116,111,110,58,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,110,101,119,32,84,111,111,108,98,97,114,66,117,116,116,111,110,32,40,105,116, + 101,109,73,100,44,32,84,40,34,106,117,99,101,33,34,41,44,32,68,114,97,119,97,98,108,101,58,58,99,114,101,97,116,101,70,114,111,109,73,109, + 97,103,101,68,97,116,97,32,40,66,105,110,97,114,121,68,97,116,97,58,58,106,117,99,101,95,112,110,103,44,32,66,105,110,97,114,121,68,97,116, + 97,58,58,106,117,99,101,95,112,110,103,83,105,122,101,41,44,32,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,97,115, + 101,32,99,117,115,116,111,109,67,111,109,98,111,66,111,120,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114, + 110,32,110,101,119,32,67,117,115,116,111,109,84,111,111,108,98,97,114,67,111,109,98,111,66,111,120,32,40,105,116,101,109,73,100,41,59,13,10,13, + 10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,102,97,117,108,116,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,98, + 114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117, + 114,110,32,48,59,13,10,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,112,114,105,118,97,116,101,58,13,10,32,32,32,32,32,32, + 32,32,83,116,114,105,110,103,65,114,114,97,121,32,105,99,111,110,78,97,109,101,115,59,13,10,32,32,32,32,32,32,32,32,79,119,110,101,100,65, + 114,114,97,121,32,60,68,114,97,119,97,98,108,101,62,32,105,99,111,110,115,70,114,111,109,90,105,112,70,105,108,101,59,13,10,13,10,32,32,32, + 32,32,32,32,32,47,47,32,84,104,105,115,32,105,115,32,97,32,108,105,116,116,108,101,32,117,116,105,108,105,116,121,32,116,111,32,99,114,101,97, + 116,101,32,97,32,98,117,116,116,111,110,32,119,105,116,104,32,111,110,101,32,111,102,32,116,104,101,32,83,86,71,32,105,109,97,103,101,115,32,105, + 110,13,10,32,32,32,32,32,32,32,32,47,47,32,111,117,114,32,101,109,98,101,100,100,101,100,32,90,73,80,32,102,105,108,101,32,34,105,99,111, + 110,115,46,122,105,112,34,13,10,32,32,32,32,32,32,32,32,84,111,111,108,98,97,114,66,117,116,116,111,110,42,32,99,114,101,97,116,101,66,117, + 116,116,111,110,70,114,111,109,90,105,112,70,105,108,101,83,86,71,32,40,99,111,110,115,116,32,105,110,116,32,105,116,101,109,73,100,44,32,99,111, + 110,115,116,32,83,116,114,105,110,103,38,32,116,101,120,116,44,32,99,111,110,115,116,32,83,116,114,105,110,103,38,32,102,105,108,101,110,97,109,101, + 41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,105,99,111,110,115,70,114,111,109,90, + 105,112,70,105,108,101,46,115,105,122,101,40,41,32,61,61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,73,102,32,119,101,39,118,101,32,110,111,116,32,97,108,114,101,97,100,121,32,100,111,110,101, + 32,115,111,44,32,108,111,97,100,32,97,108,108,32,116,104,101,32,105,109,97,103,101,115,32,102,114,111,109,32,116,104,101,32,122,105,112,32,102,105, + 108,101,46,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,77,101,109,111,114,121,73,110,112,117,116,83,116,114,101,97,109,32, + 105,99,111,110,115,70,105,108,101,83,116,114,101,97,109,32,40,66,105,110,97,114,121,68,97,116,97,58,58,105,99,111,110,115,95,122,105,112,44,32, + 66,105,110,97,114,121,68,97,116,97,58,58,105,99,111,110,115,95,122,105,112,83,105,122,101,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,90,105,112,70,105,108,101,32,105,99,111,110,115,32,40,38,105,99,111,110,115,70,105,108,101,83,116,114, + 101,97,109,44,32,102,97,108,115,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,102,111,114,32,40,105,110,116, + 32,105,32,61,32,48,59,32,105,32,60,32,105,99,111,110,115,46,103,101,116,78,117,109,69,110,116,114,105,101,115,40,41,59,32,43,43,105,41,13, + 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 73,110,112,117,116,83,116,114,101,97,109,42,32,115,118,103,70,105,108,101,83,116,114,101,97,109,32,61,32,105,99,111,110,115,46,99,114,101,97,116, + 101,83,116,114,101,97,109,70,111,114,69,110,116,114,121,32,40,105,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,105,102,32,40,115,118,103,70,105,108,101,83,116,114,101,97,109,32,33,61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,99,111,110, + 78,97,109,101,115,46,97,100,100,32,40,105,99,111,110,115,46,103,101,116,69,110,116,114,121,40,105,41,45,62,102,105,108,101,110,97,109,101,41,59, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,99,111,110,115,70,114,111,109,90,105,112,70,105, + 108,101,46,97,100,100,32,40,68,114,97,119,97,98,108,101,58,58,99,114,101,97,116,101,70,114,111,109,73,109,97,103,101,68,97,116,97,83,116,114, + 101,97,109,32,40,42,115,118,103,70,105,108,101,83,116,114,101,97,109,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,100,101,108,101,116,101,32,115,118,103,70,105,108,101,83,116,114,101,97,109,59,13,10,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,68,114,97,119,97,98,108,101,42,32,105,109,97,103,101,32, + 61,32,105,99,111,110,115,70,114,111,109,90,105,112,70,105,108,101,32,91,105,99,111,110,78,97,109,101,115,46,105,110,100,101,120,79,102,32,40,102, + 105,108,101,110,97,109,101,41,93,45,62,99,114,101,97,116,101,67,111,112,121,40,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,114,101, + 116,117,114,110,32,110,101,119,32,84,111,111,108,98,97,114,66,117,116,116,111,110,32,40,105,116,101,109,73,100,44,32,116,101,120,116,44,32,105,109, + 97,103,101,44,32,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,48,59,13,10,32,32,32,32,32, + 32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,68,101,109,111,110,115,116,114,97,116,101,115,32,104,111,119,32,116,111,32,112, + 117,116,32,97,32,99,117,115,116,111,109,32,99,111,109,112,111,110,101,110,116,32,105,110,116,111,32,97,32,116,111,111,108,98,97,114,32,45,32,116, + 104,105,115,32,111,110,101,32,99,111,110,116,97,105,110,115,13,10,32,32,32,32,32,32,32,32,47,47,32,97,32,67,111,109,98,111,66,111,120,46, + 13,10,32,32,32,32,32,32,32,32,99,108,97,115,115,32,67,117,115,116,111,109,84,111,111,108,98,97,114,67,111,109,98,111,66,111,120,32,58,32, + 112,117,98,108,105,99,32,84,111,111,108,98,97,114,73,116,101,109,67,111,109,112,111,110,101,110,116,13,10,32,32,32,32,32,32,32,32,123,13,10, + 32,32,32,32,32,32,32,32,112,117,98,108,105,99,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,67,117,115,116,111,109,84,111,111,108,98, + 97,114,67,111,109,98,111,66,111,120,32,40,99,111,110,115,116,32,105,110,116,32,116,111,111,108,98,97,114,73,116,101,109,73,100,41,13,10,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,58,32,84,111,111,108,98,97,114,73,116,101,109,67,111,109,112,111,110,101,110,116,32,40,116,111, + 111,108,98,97,114,73,116,101,109,73,100,44,32,84,40,34,67,117,115,116,111,109,32,84,111,111,108,98,97,114,32,73,116,101,109,34,41,44,32,102, + 97,108,115,101,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,97,100, + 100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,99,111,109,98,111,66,111,120,32,61,32,110,101,119,32,67,111,109,98,111,66,111,120, + 32,40,84,40,34,100,101,109,111,32,116,111,111,108,98,97,114,32,99,111,109,98,111,32,98,111,120,34,41,41,41,59,13,10,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,102,111,114,32,40,105,110,116,32,105,32,61,32,49,59,32,105,32,60,32,50,48,59,32,43,43,105,41, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,109,98,111,66,111,120,45,62,97,100,100,73,116,101,109,32, + 40,84,40,34,84,111,111,108,98,97,114,32,67,111,109,98,111,66,111,120,32,105,116,101,109,32,34,41,32,43,32,83,116,114,105,110,103,32,40,105, + 41,44,32,105,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101,116,83, + 101,108,101,99,116,101,100,73,100,32,40,49,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,109,98,111,66,111,120, + 45,62,115,101,116,69,100,105,116,97,98,108,101,84,101,120,116,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125, + 13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,126,67,117,115,116,111,109,84,111,111,108,98,97,114,67,111,109,98,111,66,111,120,40,41, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,100,101,108,101,116,101,32, + 99,111,109,98,111,66,111,120,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32, + 98,111,111,108,32,103,101,116,84,111,111,108,98,97,114,73,116,101,109,83,105,122,101,115,32,40,105,110,116,32,116,111,111,108,98,97,114,68,101,112, + 116,104,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,98,111,111,108,32,105,115,84,111,111,108,98,97,114,86,101,114,116,105,99,97,108,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,110,116,38,32,112,114,101,102,101,114,114,101,100, + 83,105,122,101,44,32,105,110,116,38,32,109,105,110,83,105,122,101,44,32,105,110,116,38,32,109,97,120,83,105,122,101,41,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,105,115,84,111,111,108,98,97,114,86, + 101,114,116,105,99,97,108,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,102,97,108, + 115,101,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,114,101,102,101,114,114,101,100,83,105,122,101,32,61,32,50, + 53,48,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,109,105,110,83,105,122,101,32,61,32,56,48,59,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,109,97,120,83,105,122,101,32,61,32,51,48,48,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,114,101,116,117,114,110,32,116,114,117,101,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,118,111,105,100,32,112,97,105,110,116,66,117,116,116,111,110,65,114,101,97,32,40,71,114,97,112,104,105,99,115,38,44,32, + 105,110,116,44,32,105,110,116,44,32,98,111,111,108,44,32,98,111,111,108,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32, + 32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,118,111,105,100,32,99,111,110,116,101,110,116,65, + 114,101,97,67,104,97,110,103,101,100,32,40,99,111,110,115,116,32,82,101,99,116,97,110,103,108,101,38,32,99,111,110,116,101,110,116,65,114,101,97, + 41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,109,98,111,66, + 111,120,45,62,115,101,116,83,105,122,101,32,40,99,111,110,116,101,110,116,65,114,101,97,46,103,101,116,87,105,100,116,104,40,41,32,45,32,50,44, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,106,109,105, + 110,32,40,99,111,110,116,101,110,116,65,114,101,97,46,103,101,116,72,101,105,103,104,116,40,41,32,45,32,50,44,32,50,50,41,41,59,13,10,13, + 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,109,98,111,66,111,120,45,62,115,101,116,67,101,110,116,114,101,80,111,115,105, + 116,105,111,110,32,40,99,111,110,116,101,110,116,65,114,101,97,46,103,101,116,67,101,110,116,114,101,88,40,41,44,32,99,111,110,116,101,110,116,65, + 114,101,97,46,103,101,116,67,101,110,116,114,101,89,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32, + 32,32,32,32,32,112,114,105,118,97,116,101,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,67,111,109,98,111,66,111,120,42,32,99,111,109, + 98,111,66,111,120,59,13,10,32,32,32,32,32,32,32,32,125,59,13,10,32,32,32,32,125,59,13,10,13,10,32,32,32,32,68,101,109,111,84,111, + 111,108,98,97,114,73,116,101,109,70,97,99,116,111,114,121,32,102,97,99,116,111,114,121,59,13,10,125,59,13,10,13,10,47,47,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,99,108,97,115,115,32,68,101, - 109,111,84,97,98,98,101,100,67,111,109,112,111,110,101,110,116,32,32,58,32,112,117,98,108,105,99,32,84,97,98,98,101,100,67,111,109,112,111,110, - 101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105, - 99,32,66,117,116,116,111,110,76,105,115,116,101,110,101,114,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,68,101,109,111,84,97, - 98,98,101,100,67,111,109,112,111,110,101,110,116,32,40,65,112,112,108,105,99,97,116,105,111,110,67,111,109,109,97,110,100,77,97,110,97,103,101,114, - 42,32,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41,13,10,32,32,32,32,32,32,32,32,58,32,84,97,98,98,101,100,67,111,109,112,111, - 110,101,110,116,32,40,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115,65,116,84,111,112,41,13,10,32,32,32,32,123, - 13,10,32,32,32,32,32,32,32,32,97,100,100,84,97,98,32,40,84,40,34,115,108,105,100,101,114,115,34,41,44,32,32,32,32,32,32,32,103,101, - 116,82,97,110,100,111,109,66,114,105,103,104,116,67,111,108,111,117,114,40,41,44,32,99,114,101,97,116,101,83,108,105,100,101,114,115,80,97,103,101, - 40,41,44,32,32,32,32,32,32,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,84,97,98,32,40,84,40,34,116,111,111,108, - 98,97,114,115,34,41,44,32,32,32,32,32,32,103,101,116,82,97,110,100,111,109,66,114,105,103,104,116,67,111,108,111,117,114,40,41,44,32,110,101, - 119,32,84,111,111,108,98,97,114,68,101,109,111,67,111,109,112,32,40,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41,44,32,32,32,32,116, - 114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,84,97,98,32,40,84,40,34,98,117,116,116,111,110,115,34,41,44,32,32,32,32, - 32,32,32,103,101,116,82,97,110,100,111,109,66,114,105,103,104,116,67,111,108,111,117,114,40,41,44,32,110,101,119,32,66,117,116,116,111,110,115,80, - 97,103,101,32,40,116,104,105,115,41,44,32,32,32,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,84,97,98,32,40,84,40, - 34,114,97,100,105,111,32,98,117,116,116,111,110,115,34,41,44,32,103,101,116,82,97,110,100,111,109,66,114,105,103,104,116,67,111,108,111,117,114,40, - 41,44,32,99,114,101,97,116,101,82,97,100,105,111,66,117,116,116,111,110,80,97,103,101,40,41,44,32,32,116,114,117,101,41,59,13,10,32,32,32, - 32,32,32,32,32,97,100,100,84,97,98,32,40,84,40,34,109,105,115,99,32,119,105,100,103,101,116,115,34,41,44,32,32,103,101,116,82,97,110,100, - 111,109,66,114,105,103,104,116,67,111,108,111,117,114,40,41,44,32,99,114,101,97,116,101,77,105,115,99,80,97,103,101,40,41,44,32,32,32,32,32, - 32,32,32,32,116,114,117,101,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,68,101,109,111,84,97,98,98,101,100,67,111,109,112, - 111,110,101,110,116,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,98,117,116,116,111,110, - 67,108,105,99,107,101,100,32,40,66,117,116,116,111,110,42,32,98,117,116,116,111,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32, - 32,66,117,98,98,108,101,77,101,115,115,97,103,101,67,111,109,112,111,110,101,110,116,42,32,98,109,99,32,61,32,110,101,119,32,66,117,98,98,108, - 101,77,101,115,115,97,103,101,67,111,109,112,111,110,101,110,116,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,68,101,115,107, - 116,111,112,58,58,99,97,110,85,115,101,83,101,109,105,84,114,97,110,115,112,97,114,101,110,116,87,105,110,100,111,119,115,40,41,41,13,10,32,32, - 32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,109,99,45,62,115,101,116,65,108,119,97,121,115,79,110,84,111,112, - 32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,109,99,45,62,97,100,100,84,111,68,101,115,107,116,111,112,32, - 40,48,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,123, - 13,10,32,32,32,32,32,32,32,32,32,32,32,32,97,100,100,67,104,105,108,100,67,111,109,112,111,110,101,110,116,32,40,98,109,99,41,59,13,10, - 32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,98,109,99,45,62,115,104,111,119,65,116,32,40,98,117,116,116,111,110, - 44,32,84,40,34,84,104,105,115,32,105,115,32,97,32,100,101,109,111,32,111,102,32,116,104,101,32,66,117,98,98,108,101,77,101,115,115,97,103,101, - 67,111,109,112,111,110,101,110,116,44,32,119,104,105,99,104,32,108,101,116,115,32,121,111,117,32,112,111,112,32,117,112,32,97,32,109,101,115,115,97, - 103,101,32,112,111,105,110,116,105,110,103,32,97,116,32,97,32,99,111,109,112,111,110,101,110,116,32,111,114,32,115,111,109,101,119,104,101,114,101,32, - 111,110,32,116,104,101,32,115,99,114,101,101,110,46,92,110,92,110,84,104,101,32,109,101,115,115,97,103,101,32,98,117,98,98,108,101,115,32,119,105, - 108,108,32,100,105,115,97,112,112,101,97,114,32,97,102,116,101,114,32,97,32,116,105,109,101,111,117,116,32,112,101,114,105,111,100,44,32,111,114,32, - 119,104,101,110,32,116,104,101,32,109,111,117,115,101,32,105,115,32,99,108,105,99,107,101,100,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,50,48,48,48,44,32,116,114,117,101,44,32,116,114,117,101,41,59,13,10,32,32,32,32,125,13,10,13, - 10,32,32,32,32,115,116,97,116,105,99,32,99,111,110,115,116,32,67,111,108,111,117,114,32,103,101,116,82,97,110,100,111,109,66,114,105,103,104,116, - 67,111,108,111,117,114,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,67,111,108,111,117,114,32,40, - 82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,70,108,111,97,116,40,41,44,32,48, - 46,49,102,44,32,48,46,57,55,102,44,32,49,46,48,102,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,13,10,47,47,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,99,108,97,115,115, + 32,68,101,109,111,84,97,98,98,101,100,67,111,109,112,111,110,101,110,116,32,32,58,32,112,117,98,108,105,99,32,84,97,98,98,101,100,67,111,109, + 112,111,110,101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117, + 98,108,105,99,32,66,117,116,116,111,110,76,105,115,116,101,110,101,114,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,68,101,109, + 111,84,97,98,98,101,100,67,111,109,112,111,110,101,110,116,32,40,65,112,112,108,105,99,97,116,105,111,110,67,111,109,109,97,110,100,77,97,110,97, + 103,101,114,42,32,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41,13,10,32,32,32,32,32,32,32,32,58,32,84,97,98,98,101,100,67,111, + 109,112,111,110,101,110,116,32,40,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115,65,116,84,111,112,41,13,10,32,32, + 32,32,123,13,10,32,32,32,32,32,32,32,32,97,100,100,84,97,98,32,40,84,40,34,115,108,105,100,101,114,115,34,41,44,32,32,32,32,32,32, + 32,103,101,116,82,97,110,100,111,109,66,114,105,103,104,116,67,111,108,111,117,114,40,41,44,32,99,114,101,97,116,101,83,108,105,100,101,114,115,80, + 97,103,101,40,41,44,32,32,32,32,32,32,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,84,97,98,32,40,84,40,34,116, + 111,111,108,98,97,114,115,34,41,44,32,32,32,32,32,32,103,101,116,82,97,110,100,111,109,66,114,105,103,104,116,67,111,108,111,117,114,40,41,44, + 32,110,101,119,32,84,111,111,108,98,97,114,68,101,109,111,67,111,109,112,32,40,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41,44,32,32, + 32,32,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,84,97,98,32,40,84,40,34,98,117,116,116,111,110,115,34,41,44,32, + 32,32,32,32,32,32,103,101,116,82,97,110,100,111,109,66,114,105,103,104,116,67,111,108,111,117,114,40,41,44,32,110,101,119,32,66,117,116,116,111, + 110,115,80,97,103,101,32,40,116,104,105,115,41,44,32,32,32,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,84,97,98,32, + 40,84,40,34,114,97,100,105,111,32,98,117,116,116,111,110,115,34,41,44,32,103,101,116,82,97,110,100,111,109,66,114,105,103,104,116,67,111,108,111, + 117,114,40,41,44,32,99,114,101,97,116,101,82,97,100,105,111,66,117,116,116,111,110,80,97,103,101,40,41,44,32,32,116,114,117,101,41,59,13,10, + 32,32,32,32,32,32,32,32,97,100,100,84,97,98,32,40,84,40,34,109,105,115,99,32,119,105,100,103,101,116,115,34,41,44,32,32,103,101,116,82, + 97,110,100,111,109,66,114,105,103,104,116,67,111,108,111,117,114,40,41,44,32,99,114,101,97,116,101,77,105,115,99,80,97,103,101,40,41,44,32,32, + 32,32,32,32,32,32,32,116,114,117,101,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,68,101,109,111,84,97,98,98,101,100,67, + 111,109,112,111,110,101,110,116,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,98,117,116, + 116,111,110,67,108,105,99,107,101,100,32,40,66,117,116,116,111,110,42,32,98,117,116,116,111,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32, + 32,32,32,32,66,117,98,98,108,101,77,101,115,115,97,103,101,67,111,109,112,111,110,101,110,116,42,32,98,109,99,32,61,32,110,101,119,32,66,117, + 98,98,108,101,77,101,115,115,97,103,101,67,111,109,112,111,110,101,110,116,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,68, + 101,115,107,116,111,112,58,58,99,97,110,85,115,101,83,101,109,105,84,114,97,110,115,112,97,114,101,110,116,87,105,110,100,111,119,115,40,41,41,13, + 10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,109,99,45,62,115,101,116,65,108,119,97,121,115,79,110, + 84,111,112,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,109,99,45,62,97,100,100,84,111,68,101,115,107,116, + 111,112,32,40,48,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32, + 32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,97,100,100,67,104,105,108,100,67,111,109,112,111,110,101,110,116,32,40,98,109,99,41, + 59,13,10,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32,32,32,32,32,98,109,99,45,62,115,104,111,119,65,116,32,40,98,117,116, + 116,111,110,44,32,84,40,34,84,104,105,115,32,105,115,32,97,32,100,101,109,111,32,111,102,32,116,104,101,32,66,117,98,98,108,101,77,101,115,115, + 97,103,101,67,111,109,112,111,110,101,110,116,44,32,119,104,105,99,104,32,108,101,116,115,32,121,111,117,32,112,111,112,32,117,112,32,97,32,109,101, + 115,115,97,103,101,32,112,111,105,110,116,105,110,103,32,97,116,32,97,32,99,111,109,112,111,110,101,110,116,32,111,114,32,115,111,109,101,119,104,101, + 114,101,32,111,110,32,116,104,101,32,115,99,114,101,101,110,46,92,110,92,110,84,104,101,32,109,101,115,115,97,103,101,32,98,117,98,98,108,101,115, + 32,119,105,108,108,32,100,105,115,97,112,112,101,97,114,32,97,102,116,101,114,32,97,32,116,105,109,101,111,117,116,32,112,101,114,105,111,100,44,32, + 111,114,32,119,104,101,110,32,116,104,101,32,109,111,117,115,101,32,105,115,32,99,108,105,99,107,101,100,46,34,41,44,13,10,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,50,48,48,48,44,32,116,114,117,101,44,32,116,114,117,101,41,59,13,10,32,32,32,32,125, + 13,10,13,10,32,32,32,32,115,116,97,116,105,99,32,99,111,110,115,116,32,67,111,108,111,117,114,32,103,101,116,82,97,110,100,111,109,66,114,105, + 103,104,116,67,111,108,111,117,114,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,67,111,108,111,117, + 114,32,40,82,97,110,100,111,109,58,58,103,101,116,83,121,115,116,101,109,82,97,110,100,111,109,40,41,46,110,101,120,116,70,108,111,97,116,40,41, + 44,32,48,46,49,102,44,32,48,46,57,55,102,44,32,49,46,48,102,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,13,10,47,47, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,99,108,97, - 115,115,32,68,101,109,111,66,97,99,107,103,114,111,117,110,100,84,104,114,101,97,100,32,32,58,32,112,117,98,108,105,99,32,84,104,114,101,97,100, - 87,105,116,104,80,114,111,103,114,101,115,115,87,105,110,100,111,119,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,68,101,109,111, - 66,97,99,107,103,114,111,117,110,100,84,104,114,101,97,100,40,41,13,10,32,32,32,32,32,32,32,32,58,32,84,104,114,101,97,100,87,105,116,104, - 80,114,111,103,114,101,115,115,87,105,110,100,111,119,32,40,84,40,34,98,117,115,121,32,100,111,105,110,103,32,115,111,109,101,32,105,109,112,111,114, - 116,97,110,116,32,116,104,105,110,103,115,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114,117,101,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114,117,101,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32, - 115,101,116,83,116,97,116,117,115,77,101,115,115,97,103,101,32,40,84,40,34,71,101,116,116,105,110,103,32,114,101,97,100,121,46,46,46,34,41,41, - 59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,68,101,109,111,66,97,99,107,103,114,111,117,110,100,84,104,114,101,97,100,40,41,13, - 10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,114,117,110,40,41,13,10,32,32,32,32,123,13,10, - 32,32,32,32,32,32,32,32,99,111,110,115,116,32,105,110,116,32,116,104,105,110,103,115,84,111,68,111,32,61,32,49,48,59,13,10,13,10,32,32, - 32,32,32,32,32,32,102,111,114,32,40,105,110,116,32,105,32,61,32,48,59,32,105,32,60,32,116,104,105,110,103,115,84,111,68,111,59,32,43,43, - 105,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,109,117,115,116,32,99,104,101,99,107, - 32,116,104,105,115,32,97,115,32,111,102,116,101,110,32,97,115,32,112,111,115,115,105,98,108,101,44,32,98,101,99,97,117,115,101,32,116,104,105,115, - 32,105,115,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,104,111,119,32,119,101,32,107,110,111,119,32,105,102,32,116,104,101,32,117, - 115,101,114,39,115,32,112,114,101,115,115,101,100,32,39,99,97,110,99,101,108,39,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40, - 116,104,114,101,97,100,83,104,111,117,108,100,69,120,105,116,40,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101, - 97,107,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,116,104,105,115,32,119,105,108,108,32,117,112,100,97,116,101,32,116, - 104,101,32,112,114,111,103,114,101,115,115,32,98,97,114,32,111,110,32,116,104,101,32,100,105,97,108,111,103,32,98,111,120,13,10,32,32,32,32,32, - 32,32,32,32,32,32,32,115,101,116,80,114,111,103,114,101,115,115,32,40,105,32,47,32,40,100,111,117,98,108,101,41,32,116,104,105,110,103,115,84, - 111,68,111,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,119,97,105,116,32,40,53,48,48,41,59,13,10,13,10,32,32,32,32, - 32,32,32,32,32,32,32,32,115,101,116,83,116,97,116,117,115,77,101,115,115,97,103,101,32,40,83,116,114,105,110,103,32,40,116,104,105,110,103,115, - 84,111,68,111,32,45,32,105,41,32,43,32,84,40,34,32,116,104,105,110,103,115,32,108,101,102,116,32,116,111,32,100,111,46,46,46,34,41,41,59, - 13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10, + 99,108,97,115,115,32,68,101,109,111,66,97,99,107,103,114,111,117,110,100,84,104,114,101,97,100,32,32,58,32,112,117,98,108,105,99,32,84,104,114, + 101,97,100,87,105,116,104,80,114,111,103,114,101,115,115,87,105,110,100,111,119,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,68, + 101,109,111,66,97,99,107,103,114,111,117,110,100,84,104,114,101,97,100,40,41,13,10,32,32,32,32,32,32,32,32,58,32,84,104,114,101,97,100,87, + 105,116,104,80,114,111,103,114,101,115,115,87,105,110,100,111,119,32,40,84,40,34,98,117,115,121,32,100,111,105,110,103,32,115,111,109,101,32,105,109, + 112,111,114,116,97,110,116,32,116,104,105,110,103,115,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114,117,101,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114,117,101,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32, + 32,32,32,115,101,116,83,116,97,116,117,115,77,101,115,115,97,103,101,32,40,84,40,34,71,101,116,116,105,110,103,32,114,101,97,100,121,46,46,46, + 34,41,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,68,101,109,111,66,97,99,107,103,114,111,117,110,100,84,104,114,101,97,100, + 40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,114,117,110,40,41,13,10,32,32,32,32, + 123,13,10,32,32,32,32,32,32,32,32,99,111,110,115,116,32,105,110,116,32,116,104,105,110,103,115,84,111,68,111,32,61,32,49,48,59,13,10,13, + 10,32,32,32,32,32,32,32,32,102,111,114,32,40,105,110,116,32,105,32,61,32,48,59,32,105,32,60,32,116,104,105,110,103,115,84,111,68,111,59, + 32,43,43,105,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,109,117,115,116,32,99,104, + 101,99,107,32,116,104,105,115,32,97,115,32,111,102,116,101,110,32,97,115,32,112,111,115,115,105,98,108,101,44,32,98,101,99,97,117,115,101,32,116, + 104,105,115,32,105,115,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,104,111,119,32,119,101,32,107,110,111,119,32,105,102,32,116,104, + 101,32,117,115,101,114,39,115,32,112,114,101,115,115,101,100,32,39,99,97,110,99,101,108,39,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105, + 102,32,40,116,104,114,101,97,100,83,104,111,117,108,100,69,120,105,116,40,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 98,114,101,97,107,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,116,104,105,115,32,119,105,108,108,32,117,112,100,97,116, + 101,32,116,104,101,32,112,114,111,103,114,101,115,115,32,98,97,114,32,111,110,32,116,104,101,32,100,105,97,108,111,103,32,98,111,120,13,10,32,32, + 32,32,32,32,32,32,32,32,32,32,115,101,116,80,114,111,103,114,101,115,115,32,40,105,32,47,32,40,100,111,117,98,108,101,41,32,116,104,105,110, + 103,115,84,111,68,111,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,119,97,105,116,32,40,53,48,48,41,59,13,10,13,10,32, + 32,32,32,32,32,32,32,32,32,32,32,115,101,116,83,116,97,116,117,115,77,101,115,115,97,103,101,32,40,83,116,114,105,110,103,32,40,116,104,105, + 110,103,115,84,111,68,111,32,45,32,105,41,32,43,32,84,40,34,32,116,104,105,110,103,115,32,108,101,102,116,32,116,111,32,100,111,46,46,46,34, + 41,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,47,42,42,32,65,32,68,105,97,108,111,103, - 87,105,110,100,111,119,32,99,111,110,116,97,105,110,105,110,103,32,97,32,67,111,108,111,117,114,83,101,108,101,99,116,111,114,32,99,111,109,112,111, - 110,101,110,116,32,42,47,13,10,99,108,97,115,115,32,67,111,108,111,117,114,83,101,108,101,99,116,111,114,68,105,97,108,111,103,87,105,110,100,111, - 119,32,32,58,32,112,117,98,108,105,99,32,68,105,97,108,111,103,87,105,110,100,111,119,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32, - 32,32,67,111,108,111,117,114,83,101,108,101,99,116,111,114,68,105,97,108,111,103,87,105,110,100,111,119,40,41,13,10,32,32,32,32,32,32,32,32, - 58,32,68,105,97,108,111,103,87,105,110,100,111,119,32,40,84,40,34,67,111,108,111,117,114,32,115,101,108,101,99,116,111,114,32,100,101,109,111,34, - 41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,67,111,108,111,117,114,115,58,58,108,105,103, - 104,116,103,114,101,121,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114,117,101,41,13,10, - 32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,101,116,67,111,110,116,101,110,116,67,111,109,112,111,110,101,110,116,32,40,110,101,119,32, - 67,111,108,111,117,114,83,101,108,101,99,116,111,114,40,41,41,59,13,10,32,32,32,32,32,32,32,32,99,101,110,116,114,101,87,105,116,104,83,105, - 122,101,32,40,52,48,48,44,32,52,48,48,41,59,13,10,32,32,32,32,32,32,32,32,115,101,116,82,101,115,105,122,97,98,108,101,32,40,116,114, - 117,101,44,32,116,114,117,101,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,67,111,108,111,117,114,83,101,108,101,99,116,111,114, - 68,105,97,108,111,103,87,105,110,100,111,119,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100, - 32,99,108,111,115,101,66,117,116,116,111,110,80,114,101,115,115,101,100,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47, - 32,119,101,32,101,120,112,101,99,116,32,116,104,105,115,32,99,111,109,112,111,110,101,110,116,32,116,111,32,98,101,32,114,117,110,32,119,105,116,104, - 105,110,32,97,32,109,111,100,97,108,32,108,111,111,112,44,32,115,111,32,119,104,101,110,32,116,104,101,32,99,108,111,115,101,13,10,32,32,32,32, - 32,32,32,32,47,47,32,98,117,116,116,111,110,32,105,115,32,99,108,105,99,107,101,100,44,32,119,101,32,99,97,110,32,109,97,107,101,32,105,116, - 32,105,110,118,105,115,105,98,108,101,32,116,111,32,99,97,117,115,101,32,116,104,101,32,108,111,111,112,32,116,111,32,101,120,105,116,32,97,110,100, - 32,116,104,101,13,10,32,32,32,32,32,32,32,32,47,47,32,99,97,108,108,105,110,103,32,99,111,100,101,32,119,105,108,108,32,100,101,108,101,116, - 101,32,116,104,105,115,32,111,98,106,101,99,116,46,13,10,32,32,32,32,32,32,32,32,115,101,116,86,105,115,105,98,108,101,32,40,102,97,108,115, - 101,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,35,105,102,32,74,85,67,69,95,77,65,67,13,10,13,10,47,47,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,47,42,42,32,65,32,68,105,97, + 108,111,103,87,105,110,100,111,119,32,99,111,110,116,97,105,110,105,110,103,32,97,32,67,111,108,111,117,114,83,101,108,101,99,116,111,114,32,99,111, + 109,112,111,110,101,110,116,32,42,47,13,10,99,108,97,115,115,32,67,111,108,111,117,114,83,101,108,101,99,116,111,114,68,105,97,108,111,103,87,105, + 110,100,111,119,32,32,58,32,112,117,98,108,105,99,32,68,105,97,108,111,103,87,105,110,100,111,119,13,10,123,13,10,112,117,98,108,105,99,58,13, + 10,32,32,32,32,67,111,108,111,117,114,83,101,108,101,99,116,111,114,68,105,97,108,111,103,87,105,110,100,111,119,40,41,13,10,32,32,32,32,32, + 32,32,32,58,32,68,105,97,108,111,103,87,105,110,100,111,119,32,40,84,40,34,67,111,108,111,117,114,32,115,101,108,101,99,116,111,114,32,100,101, + 109,111,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,67,111,108,111,117,114,115,58,58, + 108,105,103,104,116,103,114,101,121,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114,117,101, + 41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,101,116,67,111,110,116,101,110,116,67,111,109,112,111,110,101,110,116,32,40,110, + 101,119,32,67,111,108,111,117,114,83,101,108,101,99,116,111,114,40,41,41,59,13,10,32,32,32,32,32,32,32,32,99,101,110,116,114,101,87,105,116, + 104,83,105,122,101,32,40,52,48,48,44,32,52,48,48,41,59,13,10,32,32,32,32,32,32,32,32,115,101,116,82,101,115,105,122,97,98,108,101,32, + 40,116,114,117,101,44,32,116,114,117,101,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,67,111,108,111,117,114,83,101,108,101,99, + 116,111,114,68,105,97,108,111,103,87,105,110,100,111,119,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118, + 111,105,100,32,99,108,111,115,101,66,117,116,116,111,110,80,114,101,115,115,101,100,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32, + 32,47,47,32,119,101,32,101,120,112,101,99,116,32,116,104,105,115,32,99,111,109,112,111,110,101,110,116,32,116,111,32,98,101,32,114,117,110,32,119, + 105,116,104,105,110,32,97,32,109,111,100,97,108,32,108,111,111,112,44,32,115,111,32,119,104,101,110,32,116,104,101,32,99,108,111,115,101,13,10,32, + 32,32,32,32,32,32,32,47,47,32,98,117,116,116,111,110,32,105,115,32,99,108,105,99,107,101,100,44,32,119,101,32,99,97,110,32,109,97,107,101, + 32,105,116,32,105,110,118,105,115,105,98,108,101,32,116,111,32,99,97,117,115,101,32,116,104,101,32,108,111,111,112,32,116,111,32,101,120,105,116,32, + 97,110,100,32,116,104,101,13,10,32,32,32,32,32,32,32,32,47,47,32,99,97,108,108,105,110,103,32,99,111,100,101,32,119,105,108,108,32,100,101, + 108,101,116,101,32,116,104,105,115,32,111,98,106,101,99,116,46,13,10,32,32,32,32,32,32,32,32,115,101,116,86,105,115,105,98,108,101,32,40,102, + 97,108,115,101,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,35,105,102,32,74,85,67,69,95,77,65,67,13,10,13,10,47,47,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,47,42,42,32, - 84,104,105,115,32,112,111,112,115,32,111,112,101,110,32,97,32,100,105,97,108,111,103,32,98,111,120,32,97,110,100,32,119,97,105,116,115,32,102,111, - 114,32,121,111,117,32,116,111,32,112,114,101,115,115,32,107,101,121,115,32,111,110,32,121,111,117,114,32,65,112,112,108,101,32,82,101,109,111,116,101, - 44,13,10,32,32,32,32,119,104,105,99,104,32,105,116,32,100,101,115,99,114,105,98,101,115,32,105,110,32,116,104,101,32,98,111,120,46,13,10,42, - 47,13,10,99,108,97,115,115,32,65,112,112,108,101,82,101,109,111,116,101,84,101,115,116,87,105,110,100,111,119,32,32,58,32,112,117,98,108,105,99, - 32,65,108,101,114,116,87,105,110,100,111,119,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,112,117,98,108,105,99,32,65,112,112,108,101,82,101,109,111,116,101,68,101,118,105,99,101,13,10,123,13,10,112,117,98,108,105, - 99,58,13,10,32,32,32,32,65,112,112,108,101,82,101,109,111,116,101,84,101,115,116,87,105,110,100,111,119,40,41,13,10,32,32,32,32,32,32,32, - 32,58,32,65,108,101,114,116,87,105,110,100,111,119,32,40,34,65,112,112,108,101,32,82,101,109,111,116,101,32,67,111,110,116,114,111,108,32,84,101, - 115,116,33,34,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,34,73,102,32,121,111,117,39,118,101, - 32,103,111,116,32,97,110,32,65,112,112,108,101,32,82,101,109,111,116,101,44,32,112,114,101,115,115,32,115,111,109,101,32,98,117,116,116,111,110,115, - 32,110,111,119,46,46,46,34,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87, - 105,110,100,111,119,58,58,78,111,73,99,111,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,97,100,100,66,117,116,116,111,110, - 32,40,84,40,34,100,111,110,101,34,41,44,32,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,40,84,111,32,111,112,101,110,32, - 116,104,101,32,100,101,118,105,99,101,32,105,110,32,110,111,110,45,101,120,99,108,117,115,105,118,101,32,109,111,100,101,44,32,112,97,115,115,32,39, - 102,97,108,115,101,39,32,105,110,32,104,101,114,101,41,46,46,13,10,32,32,32,32,32,32,32,32,105,102,32,40,33,32,115,116,97,114,116,32,40, - 116,114,117,101,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,101,116,77,101,115,115,97,103,101,32,40,34,67,111,117,108,100,110,39, - 116,32,111,112,101,110,32,116,104,101,32,114,101,109,111,116,101,32,99,111,110,116,114,111,108,32,100,101,118,105,99,101,33,34,41,59,13,10,32,32, - 32,32,125,13,10,13,10,32,32,32,32,126,65,112,112,108,101,82,101,109,111,116,101,84,101,115,116,87,105,110,100,111,119,40,41,13,10,32,32,32, - 32,123,13,10,32,32,32,32,32,32,32,32,115,116,111,112,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,98, - 117,116,116,111,110,80,114,101,115,115,101,100,32,40,99,111,110,115,116,32,66,117,116,116,111,110,84,121,112,101,32,98,117,116,116,111,110,73,100,44, - 32,99,111,110,115,116,32,98,111,111,108,32,105,115,68,111,119,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,83,116,114,105, - 110,103,32,100,101,115,99,59,13,10,13,10,32,32,32,32,32,32,32,32,115,119,105,116,99,104,32,40,98,117,116,116,111,110,73,100,41,13,10,32, - 32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,109,101,110,117,66,117,116,116,111,110,58,13,10,32,32,32,32, - 32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,109,101,110,117,32,98,117,116,116,111,110,32,40,115,104,111,114,116,41,34,59,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,112,108,97,121,66,117,116,116, - 111,110,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,112,108,97,121,32,98,117,116,116,111,110,34,59,13,10, - 32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,112,108,117,115,66,117,116, - 116,111,110,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,112,108,117,115,32,98,117,116,116,111,110,34,59,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,109,105,110,117,115,66, - 117,116,116,111,110,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,109,105,110,117,115,32,98,117,116,116,111,110, - 34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,114,105,103, - 104,116,66,117,116,116,111,110,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,114,105,103,104,116,32,98,117,116, - 116,111,110,32,40,115,104,111,114,116,41,34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32, - 32,32,32,99,97,115,101,32,108,101,102,116,66,117,116,116,111,110,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32, - 34,108,101,102,116,32,98,117,116,116,111,110,32,40,115,104,111,114,116,41,34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97, - 107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,114,105,103,104,116,66,117,116,116,111,110,95,76,111,110,103,58,13,10,32,32,32,32, - 32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,114,105,103,104,116,32,98,117,116,116,111,110,32,40,108,111,110,103,41,34,59,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,108,101,102,116,66,117,116,116, - 111,110,95,76,111,110,103,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,108,101,102,116,32,98,117,116,116,111, - 110,32,40,108,111,110,103,41,34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32, - 99,97,115,101,32,109,101,110,117,66,117,116,116,111,110,95,76,111,110,103,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32, - 61,32,34,109,101,110,117,32,98,117,116,116,111,110,32,40,108,111,110,103,41,34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101, - 97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,112,108,97,121,66,117,116,116,111,110,83,108,101,101,112,77,111,100,101,58,13,10, - 32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,112,108,97,121,32,40,115,108,101,101,112,32,109,111,100,101,41,34,59,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,115,119,105,116,99,104, - 101,100,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,114,101,109,111,116,101,32,115,119,105,116,99,104,101,100, - 34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32, - 32,32,32,32,32,105,102,32,40,105,115,68,111,119,110,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,60,60,32,34,32, - 45,45,32,91,100,111,119,110,93,34,59,13,10,32,32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100, - 101,115,99,32,60,60,32,34,32,45,45,32,91,117,112,93,34,59,13,10,13,10,32,32,32,32,32,32,32,32,115,101,116,77,101,115,115,97,103,101, - 32,40,100,101,115,99,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,35,101,110,100,105,102,13,10,13,10,47,47,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,47, + 42,42,32,84,104,105,115,32,112,111,112,115,32,111,112,101,110,32,97,32,100,105,97,108,111,103,32,98,111,120,32,97,110,100,32,119,97,105,116,115, + 32,102,111,114,32,121,111,117,32,116,111,32,112,114,101,115,115,32,107,101,121,115,32,111,110,32,121,111,117,114,32,65,112,112,108,101,32,82,101,109, + 111,116,101,44,13,10,32,32,32,32,119,104,105,99,104,32,105,116,32,100,101,115,99,114,105,98,101,115,32,105,110,32,116,104,101,32,98,111,120,46, + 13,10,42,47,13,10,99,108,97,115,115,32,65,112,112,108,101,82,101,109,111,116,101,84,101,115,116,87,105,110,100,111,119,32,32,58,32,112,117,98, + 108,105,99,32,65,108,101,114,116,87,105,110,100,111,119,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,65,112,112,108,101,82,101,109,111,116,101,68,101,118,105,99,101,13,10,123,13,10,112,117, + 98,108,105,99,58,13,10,32,32,32,32,65,112,112,108,101,82,101,109,111,116,101,84,101,115,116,87,105,110,100,111,119,40,41,13,10,32,32,32,32, + 32,32,32,32,58,32,65,108,101,114,116,87,105,110,100,111,119,32,40,34,65,112,112,108,101,32,82,101,109,111,116,101,32,67,111,110,116,114,111,108, + 32,84,101,115,116,33,34,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,34,73,102,32,121,111,117, + 39,118,101,32,103,111,116,32,97,110,32,65,112,112,108,101,32,82,101,109,111,116,101,44,32,112,114,101,115,115,32,115,111,109,101,32,98,117,116,116, + 111,110,115,32,110,111,119,46,46,46,34,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101, + 114,116,87,105,110,100,111,119,58,58,78,111,73,99,111,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,97,100,100,66,117,116, + 116,111,110,32,40,84,40,34,100,111,110,101,34,41,44,32,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,40,84,111,32,111,112, + 101,110,32,116,104,101,32,100,101,118,105,99,101,32,105,110,32,110,111,110,45,101,120,99,108,117,115,105,118,101,32,109,111,100,101,44,32,112,97,115, + 115,32,39,102,97,108,115,101,39,32,105,110,32,104,101,114,101,41,46,46,13,10,32,32,32,32,32,32,32,32,105,102,32,40,33,32,115,116,97,114, + 116,32,40,116,114,117,101,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,101,116,77,101,115,115,97,103,101,32,40,34,67,111,117,108, + 100,110,39,116,32,111,112,101,110,32,116,104,101,32,114,101,109,111,116,101,32,99,111,110,116,114,111,108,32,100,101,118,105,99,101,33,34,41,59,13, + 10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,65,112,112,108,101,82,101,109,111,116,101,84,101,115,116,87,105,110,100,111,119,40,41,13,10, + 32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,116,111,112,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105, + 100,32,98,117,116,116,111,110,80,114,101,115,115,101,100,32,40,99,111,110,115,116,32,66,117,116,116,111,110,84,121,112,101,32,98,117,116,116,111,110, + 73,100,44,32,99,111,110,115,116,32,98,111,111,108,32,105,115,68,111,119,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,83, + 116,114,105,110,103,32,100,101,115,99,59,13,10,13,10,32,32,32,32,32,32,32,32,115,119,105,116,99,104,32,40,98,117,116,116,111,110,73,100,41, + 13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,109,101,110,117,66,117,116,116,111,110,58,13,10,32, + 32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,109,101,110,117,32,98,117,116,116,111,110,32,40,115,104,111,114,116,41,34,59, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,112,108,97,121,66, + 117,116,116,111,110,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,112,108,97,121,32,98,117,116,116,111,110,34, + 59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,112,108,117,115, + 66,117,116,116,111,110,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,112,108,117,115,32,98,117,116,116,111,110, + 34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,109,105,110, + 117,115,66,117,116,116,111,110,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,109,105,110,117,115,32,98,117,116, + 116,111,110,34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32, + 114,105,103,104,116,66,117,116,116,111,110,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,114,105,103,104,116,32, + 98,117,116,116,111,110,32,40,115,104,111,114,116,41,34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32, + 32,32,32,32,32,32,99,97,115,101,32,108,101,102,116,66,117,116,116,111,110,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99, + 32,61,32,34,108,101,102,116,32,98,117,116,116,111,110,32,40,115,104,111,114,116,41,34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98, + 114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,114,105,103,104,116,66,117,116,116,111,110,95,76,111,110,103,58,13,10,32, + 32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,114,105,103,104,116,32,98,117,116,116,111,110,32,40,108,111,110,103,41,34,59, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,108,101,102,116,66, + 117,116,116,111,110,95,76,111,110,103,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,108,101,102,116,32,98,117, + 116,116,111,110,32,40,108,111,110,103,41,34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32, + 32,32,32,99,97,115,101,32,109,101,110,117,66,117,116,116,111,110,95,76,111,110,103,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101, + 115,99,32,61,32,34,109,101,110,117,32,98,117,116,116,111,110,32,40,108,111,110,103,41,34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32, + 98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,112,108,97,121,66,117,116,116,111,110,83,108,101,101,112,77,111,100,101, + 58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,112,108,97,121,32,40,115,108,101,101,112,32,109,111,100,101,41, + 34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,99,97,115,101,32,115,119,105, + 116,99,104,101,100,58,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,61,32,34,114,101,109,111,116,101,32,115,119,105,116,99, + 104,101,100,34,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97,107,59,13,10,32,32,32,32,32,32,32,32,125,13,10,13,10, + 32,32,32,32,32,32,32,32,105,102,32,40,105,115,68,111,119,110,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,101,115,99,32,60,60, + 32,34,32,45,45,32,91,100,111,119,110,93,34,59,13,10,32,32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32, + 32,32,100,101,115,99,32,60,60,32,34,32,45,45,32,91,117,112,93,34,59,13,10,13,10,32,32,32,32,32,32,32,32,115,101,116,77,101,115,115, + 97,103,101,32,40,100,101,115,99,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,35,101,110,100,105,102,13,10,13,10,47,47,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,99,111,110,115,116, - 32,105,110,116,32,110,117,109,71,114,111,117,112,115,32,61,32,52,59,13,10,13,10,99,108,97,115,115,32,87,105,100,103,101,116,115,68,101,109,111, - 32,32,58,32,112,117,98,108,105,99,32,67,111,109,112,111,110,101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,112,117,98,108,105,99,32,66,117,116,116,111,110,76,105,115,116,101,110,101,114,13,10,123,13,10,32,32,32,32,84,101,120,116,66,117, - 116,116,111,110,42,32,109,101,110,117,66,117,116,116,111,110,59,13,10,32,32,32,32,84,111,103,103,108,101,66,117,116,116,111,110,42,32,101,110,97, - 98,108,101,66,117,116,116,111,110,59,13,10,13,10,32,32,32,32,68,101,109,111,84,97,98,98,101,100,67,111,109,112,111,110,101,110,116,42,32,116, - 97,98,115,59,13,10,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,99,111, + 110,115,116,32,105,110,116,32,110,117,109,71,114,111,117,112,115,32,61,32,52,59,13,10,13,10,99,108,97,115,115,32,87,105,100,103,101,116,115,68, + 101,109,111,32,32,58,32,112,117,98,108,105,99,32,67,111,109,112,111,110,101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,112,117,98,108,105,99,32,66,117,116,116,111,110,76,105,115,116,101,110,101,114,13,10,123,13,10,32,32,32,32,84,101,120, + 116,66,117,116,116,111,110,42,32,109,101,110,117,66,117,116,116,111,110,59,13,10,32,32,32,32,84,111,103,103,108,101,66,117,116,116,111,110,42,32, + 101,110,97,98,108,101,66,117,116,116,111,110,59,13,10,13,10,32,32,32,32,68,101,109,111,84,97,98,98,101,100,67,111,109,112,111,110,101,110,116, + 42,32,116,97,98,115,59,13,10,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,87,105,100,103,101,116,115,68,101,109,111,32,40, - 65,112,112,108,105,99,97,116,105,111,110,67,111,109,109,97,110,100,77,97,110,97,103,101,114,42,32,99,111,109,109,97,110,100,77,97,110,97,103,101, - 114,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,101,116,78,97,109,101,32,40,84,40,34,87,105,100,103,101,116,115,34,41, - 41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,116,97,98,115,32,61,32, - 110,101,119,32,68,101,109,111,84,97,98,98,101,100,67,111,109,112,111,110,101,110,116,32,40,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41, - 41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,87,105,100,103,101,116,115,68,101,109, + 111,32,40,65,112,112,108,105,99,97,116,105,111,110,67,111,109,109,97,110,100,77,97,110,97,103,101,114,42,32,99,111,109,109,97,110,100,77,97,110, + 97,103,101,114,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,101,116,78,97,109,101,32,40,84,40,34,87,105,100,103,101,116, + 115,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,116,97,98,115, + 32,61,32,110,101,119,32,68,101,109,111,84,97,98,98,101,100,67,111,109,112,111,110,101,110,116,32,40,99,111,109,109,97,110,100,77,97,110,97,103, + 101,114,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,109,101,110,117,66,117,116,116,111,110,32,61,32,110,101,119, - 32,84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,99,108,105,99,107,32,102,111,114,32,97,32,112,111,112,117,112,32,109,101,110,117,46,46, - 34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,84,40,34,99,108,105,99,107,32,102,111,114,32,97,32,100,101,109,111,32,111,102,32,116,104,101,32,100,105,102,102,101,114,101,110,116,32,116, - 121,112,101,115,32,111,102,32,105,116,101,109,32,121,111,117,32,99,97,110,32,112,117,116,32,105,110,116,111,32,97,32,112,111,112,117,112,32,109,101, - 110,117,46,46,46,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40, - 109,101,110,117,66,117,116,116,111,110,41,59,13,10,32,32,32,32,32,32,32,32,109,101,110,117,66,117,116,116,111,110,45,62,115,101,116,66,111,117, - 110,100,115,32,40,49,48,44,32,49,48,44,32,50,48,48,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,109,101,110,117,66,117,116,116, - 111,110,45,62,97,100,100,66,117,116,116,111,110,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,13,10,32,32,32,32,32,32,32,32,109, - 101,110,117,66,117,116,116,111,110,45,62,115,101,116,84,114,105,103,103,101,114,101,100,79,110,77,111,117,115,101,68,111,119,110,32,40,116,114,117,101, - 41,59,32,47,47,32,98,101,99,97,117,115,101,32,116,104,105,115,32,98,117,116,116,111,110,32,112,111,112,115,32,117,112,32,97,32,109,101,110,117, - 44,32,116,104,105,115,32,108,101,116,115,32,117,115,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,104,111,108,100,32,100,111,119,110, - 32,116,104,101,32,98,117,116,116,111,110,32,97,110,100,32,100,114,97,103,32,115,116,114,97,105,103,104,116,32,111,110,116,111,32,116,104,101,32,109, - 101,110,117,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,109,101,110,117,66,117,116,116,111,110,32,61,32, + 110,101,119,32,84,101,120,116,66,117,116,116,111,110,32,40,84,40,34,99,108,105,99,107,32,102,111,114,32,97,32,112,111,112,117,112,32,109,101,110, + 117,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,84,40,34,99,108,105,99,107,32,102,111,114,32,97,32,100,101,109,111,32,111,102,32,116,104,101,32,100,105,102,102,101,114,101,110, + 116,32,116,121,112,101,115,32,111,102,32,105,116,101,109,32,121,111,117,32,99,97,110,32,112,117,116,32,105,110,116,111,32,97,32,112,111,112,117,112, + 32,109,101,110,117,46,46,46,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108, + 101,32,40,109,101,110,117,66,117,116,116,111,110,41,59,13,10,32,32,32,32,32,32,32,32,109,101,110,117,66,117,116,116,111,110,45,62,115,101,116, + 66,111,117,110,100,115,32,40,49,48,44,32,49,48,44,32,50,48,48,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,109,101,110,117,66, + 117,116,116,111,110,45,62,97,100,100,66,117,116,116,111,110,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,13,10,32,32,32,32,32,32, + 32,32,109,101,110,117,66,117,116,116,111,110,45,62,115,101,116,84,114,105,103,103,101,114,101,100,79,110,77,111,117,115,101,68,111,119,110,32,40,116, + 114,117,101,41,59,32,47,47,32,98,101,99,97,117,115,101,32,116,104,105,115,32,98,117,116,116,111,110,32,112,111,112,115,32,117,112,32,97,32,109, + 101,110,117,44,32,116,104,105,115,32,108,101,116,115,32,117,115,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,104,111,108,100,32,100, + 111,119,110,32,116,104,101,32,98,117,116,116,111,110,32,97,110,100,32,100,114,97,103,32,115,116,114,97,105,103,104,116,32,111,110,116,111,32,116,104, + 101,32,109,101,110,117,13,10,13,10,32,32,32,32,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,101,110,97,98,108,101,66,117,116,116,111,110,32,61,32, - 110,101,119,32,84,111,103,103,108,101,66,117,116,116,111,110,32,40,84,40,34,101,110,97,98,108,101,47,100,105,115,97,98,108,101,32,99,111,109,112, - 111,110,101,110,116,115,34,41,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,101, - 110,97,98,108,101,66,117,116,116,111,110,41,59,13,10,32,32,32,32,32,32,32,32,101,110,97,98,108,101,66,117,116,116,111,110,45,62,115,101,116, - 66,111,117,110,100,115,32,40,50,51,48,44,32,49,48,44,32,49,56,48,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,101,110,97,98, - 108,101,66,117,116,116,111,110,45,62,115,101,116,84,111,111,108,116,105,112,32,40,84,40,34,116,111,103,103,108,101,32,98,117,116,116,111,110,34,41, - 41,59,13,10,32,32,32,32,32,32,32,32,101,110,97,98,108,101,66,117,116,116,111,110,45,62,115,101,116,84,111,103,103,108,101,83,116,97,116,101, - 32,40,116,114,117,101,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32,32,101,110,97,98,108,101,66,117,116,116,111,110,45,62,97, - 100,100,66,117,116,116,111,110,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126, - 87,105,100,103,101,116,115,68,101,109,111,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65,108,108,67, - 104,105,108,100,114,101,110,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,114,101,115,105,122,101,100,40,41,13, - 10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,116,97,98,115,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,52,48,44, - 32,103,101,116,87,105,100,116,104,40,41,32,45,32,50,48,44,32,103,101,116,72,101,105,103,104,116,40,41,32,45,32,53,48,41,59,13,10,32,32, - 32,32,125,13,10,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,101,110,97,98,108,101,66,117,116,116,111,110, + 32,61,32,110,101,119,32,84,111,103,103,108,101,66,117,116,116,111,110,32,40,84,40,34,101,110,97,98,108,101,47,100,105,115,97,98,108,101,32,99, + 111,109,112,111,110,101,110,116,115,34,41,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101, + 32,40,101,110,97,98,108,101,66,117,116,116,111,110,41,59,13,10,32,32,32,32,32,32,32,32,101,110,97,98,108,101,66,117,116,116,111,110,45,62, + 115,101,116,66,111,117,110,100,115,32,40,50,51,48,44,32,49,48,44,32,49,56,48,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,101, + 110,97,98,108,101,66,117,116,116,111,110,45,62,115,101,116,84,111,111,108,116,105,112,32,40,84,40,34,116,111,103,103,108,101,32,98,117,116,116,111, + 110,34,41,41,59,13,10,32,32,32,32,32,32,32,32,101,110,97,98,108,101,66,117,116,116,111,110,45,62,115,101,116,84,111,103,103,108,101,83,116, + 97,116,101,32,40,116,114,117,101,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32,32,101,110,97,98,108,101,66,117,116,116,111,110, + 45,62,97,100,100,66,117,116,116,111,110,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32, + 32,32,126,87,105,100,103,101,116,115,68,101,109,111,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65, + 108,108,67,104,105,108,100,114,101,110,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,114,101,115,105,122,101,100, + 40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,116,97,98,115,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32, + 52,48,44,32,103,101,116,87,105,100,116,104,40,41,32,45,32,50,48,44,32,103,101,116,72,101,105,103,104,116,40,41,32,45,32,53,48,41,59,13, + 10,32,32,32,32,125,13,10,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,118,111,105,100,32,98,117,116,116,111,110,67,108,105,99,107,101,100,32,40,66,117,116, - 116,111,110,42,32,98,117,116,116,111,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,105,102,32,40,98,117,116,116,111,110,32, - 61,61,32,101,110,97,98,108,101,66,117,116,116,111,110,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32, - 32,99,111,110,115,116,32,98,111,111,108,32,101,110,97,98,108,101,100,32,61,32,101,110,97,98,108,101,66,117,116,116,111,110,45,62,103,101,116,84, - 111,103,103,108,101,83,116,97,116,101,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,101,110,117,66,117,116,116,111,110,45, - 62,115,101,116,69,110,97,98,108,101,100,32,40,101,110,97,98,108,101,100,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,97,98,115, - 45,62,115,101,116,69,110,97,98,108,101,100,32,40,101,110,97,98,108,101,100,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32, - 32,32,32,32,101,108,115,101,32,105,102,32,40,98,117,116,116,111,110,32,61,61,32,109,101,110,117,66,117,116,116,111,110,41,13,10,32,32,32,32, - 32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,80,111,112,117,112,77,101,110,117,32,109,59,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,109,46,97,100,100,73,116,101,109,32,40,49,44,32,84,40,34,78,111,114,109,97,108,32,105,116,101,109,34,41,41,59,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,73,116,101,109,32,40,50,44,32,84,40,34,68,105,115,97,98,108,101,100,32,105,116,101, - 109,34,41,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,73,116,101,109,32,40,51,44,32, - 84,40,34,84,105,99,107,101,100,32,105,116,101,109,34,41,44,32,116,114,117,101,44,32,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,109,46,97,100,100,67,111,108,111,117,114,101,100,73,116,101,109,32,40,52,44,32,84,40,34,67,111,108,111,117,114,101,100,32,105,116, - 101,109,34,41,44,32,67,111,108,111,117,114,115,58,58,103,114,101,101,110,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100, - 100,83,101,112,97,114,97,116,111,114,40,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,67,117,115,116,111,109,73,116, - 101,109,32,40,53,44,32,110,101,119,32,67,117,115,116,111,109,77,101,110,117,67,111,109,112,111,110,101,110,116,40,41,41,59,13,10,13,10,32,32, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,118,111,105,100,32,98,117,116,116,111,110,67,108,105,99,107,101,100,32,40, + 66,117,116,116,111,110,42,32,98,117,116,116,111,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,105,102,32,40,98,117,116,116, + 111,110,32,61,61,32,101,110,97,98,108,101,66,117,116,116,111,110,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32, + 32,32,32,32,99,111,110,115,116,32,98,111,111,108,32,101,110,97,98,108,101,100,32,61,32,101,110,97,98,108,101,66,117,116,116,111,110,45,62,103, + 101,116,84,111,103,103,108,101,83,116,97,116,101,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,101,110,117,66,117,116,116, + 111,110,45,62,115,101,116,69,110,97,98,108,101,100,32,40,101,110,97,98,108,101,100,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116, + 97,98,115,45,62,115,101,116,69,110,97,98,108,101,100,32,40,101,110,97,98,108,101,100,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32, + 32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,98,117,116,116,111,110,32,61,61,32,109,101,110,117,66,117,116,116,111,110,41,13,10,32, + 32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,80,111,112,117,112,77,101,110,117,32,109,59,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,109,46,97,100,100,73,116,101,109,32,40,49,44,32,84,40,34,78,111,114,109,97,108,32,105,116,101,109,34,41,41,59, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,73,116,101,109,32,40,50,44,32,84,40,34,68,105,115,97,98,108,101,100,32, + 105,116,101,109,34,41,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,73,116,101,109,32,40, + 51,44,32,84,40,34,84,105,99,107,101,100,32,105,116,101,109,34,41,44,32,116,114,117,101,44,32,116,114,117,101,41,59,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,109,46,97,100,100,67,111,108,111,117,114,101,100,73,116,101,109,32,40,52,44,32,84,40,34,67,111,108,111,117,114,101,100, + 32,105,116,101,109,34,41,44,32,67,111,108,111,117,114,115,58,58,103,114,101,101,110,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109, + 46,97,100,100,83,101,112,97,114,97,116,111,114,40,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,67,117,115,116,111, + 109,73,116,101,109,32,40,53,44,32,110,101,119,32,67,117,115,116,111,109,77,101,110,117,67,111,109,112,111,110,101,110,116,40,41,41,59,13,10,13, + 10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,101,112,97,114,97,116,111,114,40,41,59,13,10,13,10,32,32,32,32,32,32, + 32,32,32,32,32,32,80,111,112,117,112,77,101,110,117,32,116,97,98,115,77,101,110,117,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116, + 97,98,115,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,48,49,44,32,84,40,34,83,104,111,119,32,116,97,98,115,32,97,116,32,116, + 104,101,32,116,111,112,34,41,44,32,116,114,117,101,44,32,116,97,98,115,45,62,103,101,116,79,114,105,101,110,116,97,116,105,111,110,40,41,32,61, + 61,32,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115,65,116,84,111,112,41,59,13,10,32,32,32,32,32,32,32,32, + 32,32,32,32,116,97,98,115,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,48,50,44,32,84,40,34,83,104,111,119,32,116,97,98,115, + 32,97,116,32,116,104,101,32,98,111,116,116,111,109,34,41,44,32,116,114,117,101,44,32,116,97,98,115,45,62,103,101,116,79,114,105,101,110,116,97, + 116,105,111,110,40,41,32,61,61,32,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115,65,116,66,111,116,116,111,109,41, + 59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,97,98,115,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,48,51,44,32,84, + 40,34,83,104,111,119,32,116,97,98,115,32,97,116,32,116,104,101,32,108,101,102,116,34,41,44,32,116,114,117,101,44,32,116,97,98,115,45,62,103, + 101,116,79,114,105,101,110,116,97,116,105,111,110,40,41,32,61,61,32,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115, + 65,116,76,101,102,116,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,97,98,115,77,101,110,117,46,97,100,100,73,116,101,109,32,40, + 49,48,48,52,44,32,84,40,34,83,104,111,119,32,116,97,98,115,32,97,116,32,116,104,101,32,114,105,103,104,116,34,41,44,32,116,114,117,101,44, + 32,116,97,98,115,45,62,103,101,116,79,114,105,101,110,116,97,116,105,111,110,40,41,32,61,61,32,84,97,98,98,101,100,66,117,116,116,111,110,66, + 97,114,58,58,84,97,98,115,65,116,82,105,103,104,116,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,117,98,77, + 101,110,117,32,40,84,40,34,84,97,98,32,112,111,115,105,116,105,111,110,34,41,44,32,116,97,98,115,77,101,110,117,41,59,13,10,13,10,32,32, 32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,101,112,97,114,97,116,111,114,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32, - 32,32,32,80,111,112,117,112,77,101,110,117,32,116,97,98,115,77,101,110,117,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,97,98,115, - 77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,48,49,44,32,84,40,34,83,104,111,119,32,116,97,98,115,32,97,116,32,116,104,101,32, - 116,111,112,34,41,44,32,116,114,117,101,44,32,116,97,98,115,45,62,103,101,116,79,114,105,101,110,116,97,116,105,111,110,40,41,32,61,61,32,84, - 97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115,65,116,84,111,112,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32, - 32,116,97,98,115,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,48,50,44,32,84,40,34,83,104,111,119,32,116,97,98,115,32,97,116, - 32,116,104,101,32,98,111,116,116,111,109,34,41,44,32,116,114,117,101,44,32,116,97,98,115,45,62,103,101,116,79,114,105,101,110,116,97,116,105,111, - 110,40,41,32,61,61,32,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115,65,116,66,111,116,116,111,109,41,59,13,10, - 32,32,32,32,32,32,32,32,32,32,32,32,116,97,98,115,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,48,51,44,32,84,40,34,83, - 104,111,119,32,116,97,98,115,32,97,116,32,116,104,101,32,108,101,102,116,34,41,44,32,116,114,117,101,44,32,116,97,98,115,45,62,103,101,116,79, - 114,105,101,110,116,97,116,105,111,110,40,41,32,61,61,32,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115,65,116,76, - 101,102,116,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,97,98,115,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,48, - 52,44,32,84,40,34,83,104,111,119,32,116,97,98,115,32,97,116,32,116,104,101,32,114,105,103,104,116,34,41,44,32,116,114,117,101,44,32,116,97, - 98,115,45,62,103,101,116,79,114,105,101,110,116,97,116,105,111,110,40,41,32,61,61,32,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58, - 58,84,97,98,115,65,116,82,105,103,104,116,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,117,98,77,101,110,117, - 32,40,84,40,34,84,97,98,32,112,111,115,105,116,105,111,110,34,41,44,32,116,97,98,115,77,101,110,117,41,59,13,10,13,10,32,32,32,32,32, - 32,32,32,32,32,32,32,109,46,97,100,100,83,101,112,97,114,97,116,111,114,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 80,111,112,117,112,77,101,110,117,32,100,105,97,108,111,103,77,101,110,117,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111, - 103,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,48,44,32,84,40,34,83,104,111,119,32,97,32,112,108,97,105,110,32,97,108,101,114, - 116,45,119,105,110,100,111,119,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46, - 97,100,100,73,116,101,109,32,40,49,48,49,44,32,84,40,34,83,104,111,119,32,97,110,32,97,108,101,114,116,45,119,105,110,100,111,119,32,119,105, - 116,104,32,97,32,39,119,97,114,110,105,110,103,39,32,105,99,111,110,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 100,105,97,108,111,103,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,50,44,32,84,40,34,83,104,111,119,32,97,110,32,97,108,101,114, - 116,45,119,105,110,100,111,119,32,119,105,116,104,32,97,110,32,39,105,110,102,111,39,32,105,99,111,110,46,46,46,34,41,41,59,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,51,44,32,84,40,34,83,104,111, - 119,32,97,110,32,97,108,101,114,116,45,119,105,110,100,111,119,32,119,105,116,104,32,97,32,39,113,117,101,115,116,105,111,110,39,32,105,99,111,110, - 46,46,46,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100,83,101,112, - 97,114,97,116,111,114,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100,73, - 116,101,109,32,40,49,49,48,44,32,84,40,34,83,104,111,119,32,97,110,32,111,107,47,99,97,110,99,101,108,32,97,108,101,114,116,45,119,105,110, - 100,111,119,46,46,46,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100, + 32,32,32,80,111,112,117,112,77,101,110,117,32,100,105,97,108,111,103,77,101,110,117,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105, + 97,108,111,103,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,48,44,32,84,40,34,83,104,111,119,32,97,32,112,108,97,105,110,32,97, + 108,101,114,116,45,119,105,110,100,111,119,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101, + 110,117,46,97,100,100,73,116,101,109,32,40,49,48,49,44,32,84,40,34,83,104,111,119,32,97,110,32,97,108,101,114,116,45,119,105,110,100,111,119, + 32,119,105,116,104,32,97,32,39,119,97,114,110,105,110,103,39,32,105,99,111,110,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,50,44,32,84,40,34,83,104,111,119,32,97,110,32,97, + 108,101,114,116,45,119,105,110,100,111,119,32,119,105,116,104,32,97,110,32,39,105,110,102,111,39,32,105,99,111,110,46,46,46,34,41,41,59,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,48,51,44,32,84,40,34, + 83,104,111,119,32,97,110,32,97,108,101,114,116,45,119,105,110,100,111,119,32,119,105,116,104,32,97,32,39,113,117,101,115,116,105,111,110,39,32,105, + 99,111,110,46,46,46,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100, 83,101,112,97,114,97,116,111,114,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97, - 100,100,73,116,101,109,32,40,49,49,49,44,32,84,40,34,83,104,111,119,32,97,110,32,97,108,101,114,116,45,119,105,110,100,111,119,32,119,105,116, - 104,32,115,111,109,101,32,101,120,116,114,97,32,99,111,109,112,111,110,101,110,116,115,46,46,46,34,41,41,59,13,10,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100,83,101,112,97,114,97,116,111,114,40,41,59,13,10,13,10,32,32,32,32, - 32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,49,50,44,32,84,40,34,83,104,111,119, - 32,97,32,84,104,114,101,97,100,87,105,116,104,80,114,111,103,114,101,115,115,87,105,110,100,111,119,32,100,101,109,111,46,46,46,34,41,41,59,13, - 10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,65,108,101,114,116,87,105,110, - 100,111,119,32,100,101,109,111,110,115,116,114,97,116,105,111,110,115,34,41,44,32,100,105,97,108,111,103,77,101,110,117,41,59,13,10,13,10,32,32, - 32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,101,112,97,114,97,116,111,114,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32, - 32,32,32,109,46,97,100,100,73,116,101,109,32,40,49,50,48,44,32,84,40,34,83,104,111,119,32,97,32,99,111,108,111,117,114,32,115,101,108,101, - 99,116,111,114,32,100,101,109,111,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,101,112,97,114, - 97,116,111,114,40,41,59,13,10,13,10,35,105,102,32,74,85,67,69,95,77,65,67,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97, - 100,100,73,116,101,109,32,40,49,52,48,44,32,84,40,34,82,117,110,32,116,104,101,32,65,112,112,108,101,32,82,101,109,111,116,101,32,67,111,110, - 116,114,111,108,32,116,101,115,116,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,101,112,97,114, - 97,116,111,114,40,41,59,13,10,35,101,110,100,105,102,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,80,111,112,117,112,77,101,110,117, - 32,110,97,116,105,118,101,70,105,108,101,67,104,111,111,115,101,114,115,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,110,97,116,105,118,101, - 70,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32,40,49,50,49,44,32,84,40,34,39,76,111,97,100,39,32,102,105,108, - 101,32,98,114,111,119,115,101,114,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,110,97,116,105,118,101,70,105,108,101, - 67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32,40,49,50,52,44,32,84,40,34,39,76,111,97,100,39,32,102,105,108,101,32,98,114, - 111,119,115,101,114,32,119,105,116,104,32,97,110,32,105,109,97,103,101,32,102,105,108,101,32,112,114,101,118,105,101,119,46,46,46,34,41,41,59,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,110,97,116,105,118,101,70,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32, - 40,49,50,50,44,32,84,40,34,39,83,97,118,101,39,32,102,105,108,101,32,98,114,111,119,115,101,114,46,46,46,34,41,41,59,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,110,97,116,105,118,101,70,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32,40,49,50,51, - 44,32,84,40,34,39,67,104,111,111,115,101,32,100,105,114,101,99,116,111,114,121,39,32,102,105,108,101,32,98,114,111,119,115,101,114,46,46,46,34, - 41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,80,111,112,117,112,77,101,110,117,32,106,117,99,101,70,105,108,101,67,104,111, - 111,115,101,114,115,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,70,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100, - 73,116,101,109,32,40,49,51,49,44,32,84,40,34,39,76,111,97,100,39,32,102,105,108,101,32,98,114,111,119,115,101,114,46,46,46,34,41,41,59, - 13,10,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,70,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32,40, - 49,51,52,44,32,84,40,34,39,76,111,97,100,39,32,102,105,108,101,32,98,114,111,119,115,101,114,32,119,105,116,104,32,97,110,32,105,109,97,103, - 101,32,102,105,108,101,32,112,114,101,118,105,101,119,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,70, - 105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32,40,49,51,50,44,32,84,40,34,39,83,97,118,101,39,32,102,105,108,101, - 32,98,114,111,119,115,101,114,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,70,105,108,101,67,104,111, - 111,115,101,114,115,46,97,100,100,73,116,101,109,32,40,49,51,51,44,32,84,40,34,39,67,104,111,111,115,101,32,100,105,114,101,99,116,111,114,121, - 39,32,102,105,108,101,32,98,114,111,119,115,101,114,46,46,46,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,80,111,112, - 117,112,77,101,110,117,32,102,105,108,101,67,104,111,111,115,101,114,115,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,102,105,108,101,67,104, - 111,111,115,101,114,115,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,79,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,100, - 105,97,108,111,103,115,34,41,44,32,110,97,116,105,118,101,70,105,108,101,67,104,111,111,115,101,114,115,41,59,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,102,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,74,117,99,101,32,100,105,97, - 108,111,103,115,34,41,44,32,106,117,99,101,70,105,108,101,67,104,111,111,115,101,114,115,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32, - 32,32,109,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,70,105,108,101,32,99,104,111,111,115,101,114,32,100,105,97,108,111,103,115,34, - 41,44,32,102,105,108,101,67,104,111,111,115,101,114,115,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,110,116,32,114,101,115, - 117,108,116,32,61,32,109,46,115,104,111,119,65,116,32,40,109,101,110,117,66,117,116,116,111,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,105,102,32,40,114,101,115,117,108,116,32,33,61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,117,115,101,114,32,99,104,111,115,101,32,115,111,109,101,116,104,105,110,103,32,102,114,111, - 109,32,116,104,101,32,109,101,110,117,46,46,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,114,101,115,117, - 108,116,32,62,61,32,49,48,48,32,38,38,32,114,101,115,117,108,116,32,60,32,49,48,53,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58, - 65,108,101,114,116,73,99,111,110,84,121,112,101,32,105,99,111,110,32,61,32,65,108,101,114,116,87,105,110,100,111,119,58,58,78,111,73,99,111,110, - 59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49, - 48,49,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,99,111,110,32,61,32,65,108,101,114, - 116,87,105,110,100,111,119,58,58,87,97,114,110,105,110,103,73,99,111,110,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,48,50,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,105,99,111,110,32,61,32,65,108,101,114,116,87,105,110,100,111,119,58,58,73,110,102,111,73,99,111,110, - 59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61, - 61,32,49,48,51,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,99,111,110,32,61,32,65, - 108,101,114,116,87,105,110,100,111,119,58,58,81,117,101,115,116,105,111,110,73,99,111,110,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104,111,119,77,101,115,115,97,103,101,66,111,120,32,40,105,99, - 111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,84,104,105,115,32,105,115,32,97,110,32,65,108,101,114,116,87,105,110,100,111,119,34, - 41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,65,110,100,32,116,104,105,115,32,105,115,32,116,104,101,32,65,108,101,114,116,87,105,110, - 100,111,119,39,115,32,109,101,115,115,97,103,101,46,32,66,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32, - 98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,46, - 34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,111,107,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49, - 49,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,98,111,111,108,32,117,115,101,114,80,105,99,107,101,100,79,107,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,61,32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104,111,119,79,107,67,97,110,99,101,108,66,111,120,32,40,65, - 108,101,114,116,87,105,110,100,111,119,58,58,81,117,101,115,116,105,111,110,73,99,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, + 100,100,73,116,101,109,32,40,49,49,48,44,32,84,40,34,83,104,111,119,32,97,110,32,111,107,47,99,97,110,99,101,108,32,97,108,101,114,116,45, + 119,105,110,100,111,119,46,46,46,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46, + 97,100,100,83,101,112,97,114,97,116,111,114,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110, + 117,46,97,100,100,73,116,101,109,32,40,49,49,49,44,32,84,40,34,83,104,111,119,32,97,110,32,97,108,101,114,116,45,119,105,110,100,111,119,32, + 119,105,116,104,32,115,111,109,101,32,101,120,116,114,97,32,99,111,109,112,111,110,101,110,116,115,46,46,46,34,41,41,59,13,10,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100,83,101,112,97,114,97,116,111,114,40,41,59,13,10,13,10,32, + 32,32,32,32,32,32,32,32,32,32,32,100,105,97,108,111,103,77,101,110,117,46,97,100,100,73,116,101,109,32,40,49,49,50,44,32,84,40,34,83, + 104,111,119,32,97,32,84,104,114,101,97,100,87,105,116,104,80,114,111,103,114,101,115,115,87,105,110,100,111,119,32,100,101,109,111,46,46,46,34,41, + 41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,65,108,101,114,116, + 87,105,110,100,111,119,32,100,101,109,111,110,115,116,114,97,116,105,111,110,115,34,41,44,32,100,105,97,108,111,103,77,101,110,117,41,59,13,10,13, + 10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,101,112,97,114,97,116,111,114,40,41,59,13,10,13,10,32,32,32,32,32,32, + 32,32,32,32,32,32,109,46,97,100,100,73,116,101,109,32,40,49,50,48,44,32,84,40,34,83,104,111,119,32,97,32,99,111,108,111,117,114,32,115, + 101,108,101,99,116,111,114,32,100,101,109,111,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,101, + 112,97,114,97,116,111,114,40,41,59,13,10,13,10,35,105,102,32,74,85,67,69,95,77,65,67,13,10,32,32,32,32,32,32,32,32,32,32,32,32, + 109,46,97,100,100,73,116,101,109,32,40,49,52,48,44,32,84,40,34,82,117,110,32,116,104,101,32,65,112,112,108,101,32,82,101,109,111,116,101,32, + 67,111,110,116,114,111,108,32,116,101,115,116,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,46,97,100,100,83,101, + 112,97,114,97,116,111,114,40,41,59,13,10,35,101,110,100,105,102,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,80,111,112,117,112,77, + 101,110,117,32,110,97,116,105,118,101,70,105,108,101,67,104,111,111,115,101,114,115,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,110,97,116, + 105,118,101,70,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32,40,49,50,49,44,32,84,40,34,39,76,111,97,100,39,32, + 102,105,108,101,32,98,114,111,119,115,101,114,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,110,97,116,105,118,101,70, + 105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32,40,49,50,52,44,32,84,40,34,39,76,111,97,100,39,32,102,105,108,101, + 32,98,114,111,119,115,101,114,32,119,105,116,104,32,97,110,32,105,109,97,103,101,32,102,105,108,101,32,112,114,101,118,105,101,119,46,46,46,34,41, + 41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,110,97,116,105,118,101,70,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116, + 101,109,32,40,49,50,50,44,32,84,40,34,39,83,97,118,101,39,32,102,105,108,101,32,98,114,111,119,115,101,114,46,46,46,34,41,41,59,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,110,97,116,105,118,101,70,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32,40, + 49,50,51,44,32,84,40,34,39,67,104,111,111,115,101,32,100,105,114,101,99,116,111,114,121,39,32,102,105,108,101,32,98,114,111,119,115,101,114,46, + 46,46,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,80,111,112,117,112,77,101,110,117,32,106,117,99,101,70,105,108,101, + 67,104,111,111,115,101,114,115,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,70,105,108,101,67,104,111,111,115,101,114,115,46, + 97,100,100,73,116,101,109,32,40,49,51,49,44,32,84,40,34,39,76,111,97,100,39,32,102,105,108,101,32,98,114,111,119,115,101,114,46,46,46,34, + 41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,70,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116,101, + 109,32,40,49,51,52,44,32,84,40,34,39,76,111,97,100,39,32,102,105,108,101,32,98,114,111,119,115,101,114,32,119,105,116,104,32,97,110,32,105, + 109,97,103,101,32,102,105,108,101,32,112,114,101,118,105,101,119,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,106,117, + 99,101,70,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32,40,49,51,50,44,32,84,40,34,39,83,97,118,101,39,32,102, + 105,108,101,32,98,114,111,119,115,101,114,46,46,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,106,117,99,101,70,105,108,101, + 67,104,111,111,115,101,114,115,46,97,100,100,73,116,101,109,32,40,49,51,51,44,32,84,40,34,39,67,104,111,111,115,101,32,100,105,114,101,99,116, + 111,114,121,39,32,102,105,108,101,32,98,114,111,119,115,101,114,46,46,46,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32, + 80,111,112,117,112,77,101,110,117,32,102,105,108,101,67,104,111,111,115,101,114,115,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,102,105,108, + 101,67,104,111,111,115,101,114,115,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,79,112,101,114,97,116,105,110,103,32,115,121,115,116,101, + 109,32,100,105,97,108,111,103,115,34,41,44,32,110,97,116,105,118,101,70,105,108,101,67,104,111,111,115,101,114,115,41,59,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,102,105,108,101,67,104,111,111,115,101,114,115,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,74,117,99,101,32, + 100,105,97,108,111,103,115,34,41,44,32,106,117,99,101,70,105,108,101,67,104,111,111,115,101,114,115,41,59,13,10,13,10,32,32,32,32,32,32,32, + 32,32,32,32,32,109,46,97,100,100,83,117,98,77,101,110,117,32,40,84,40,34,70,105,108,101,32,99,104,111,111,115,101,114,32,100,105,97,108,111, + 103,115,34,41,44,32,102,105,108,101,67,104,111,111,115,101,114,115,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,110,116,32, + 114,101,115,117,108,116,32,61,32,109,46,115,104,111,119,65,116,32,40,109,101,110,117,66,117,116,116,111,110,41,59,13,10,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,105,102,32,40,114,101,115,117,108,116,32,33,61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,117,115,101,114,32,99,104,111,115,101,32,115,111,109,101,116,104,105,110,103,32, + 102,114,111,109,32,116,104,101,32,109,101,110,117,46,46,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,114, + 101,115,117,108,116,32,62,61,32,49,48,48,32,38,38,32,114,101,115,117,108,116,32,60,32,49,48,53,41,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111, + 119,58,58,65,108,101,114,116,73,99,111,110,84,121,112,101,32,105,99,111,110,32,61,32,65,108,101,114,116,87,105,110,100,111,119,58,58,78,111,73, + 99,111,110,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,114,101,115,117,108,116,32,61, + 61,32,49,48,49,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,99,111,110,32,61,32,65, + 108,101,114,116,87,105,110,100,111,119,58,58,87,97,114,110,105,110,103,73,99,111,110,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,48,50,41,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,99,111,110,32,61,32,65,108,101,114,116,87,105,110,100,111,119,58,58,73,110,102,111,73, + 99,111,110,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108, + 116,32,61,61,32,49,48,51,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,99,111,110,32, + 61,32,65,108,101,114,116,87,105,110,100,111,119,58,58,81,117,101,115,116,105,111,110,73,99,111,110,59,13,10,13,10,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104,111,119,77,101,115,115,97,103,101,66,111,120,32, + 40,105,99,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,84,104,105,115,32,105,115,32,97,110,32,65,108,101,114,116,87,105,110,100, + 111,119,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,65,110,100,32,116,104,105,115,32,105,115,32,116,104,101,32,65,108,101,114,116, + 87,105,110,100,111,119,39,115,32,109,101,115,115,97,103,101,46,32,66,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108, + 97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108, + 97,104,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,111,107,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61, + 61,32,49,49,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,98,111,111,108,32,117,115,101,114,80,105,99,107,101,100,79,107,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,61,32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104,111,119,79,107,67,97,110,99,101,108,66,111,120, + 32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,81,117,101,115,116,105,111,110,73,99,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,84,40,34,84,104,105,115,32,105,115,32,97,110,32,111,107,47,99,97,110,99,101,108,32,65,108,101,114,116,87,105,110,100,111,119,34,41, + 32,32,32,32,32,32,84,40,34,84,104,105,115,32,105,115,32,97,110,32,111,107,47,99,97,110,99,101,108,32,65,108,101,114,116,87,105,110,100,111, + 119,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,65,110,100,32,116,104,105,115,32,105,115,32,116,104,101, + 32,65,108,101,114,116,87,105,110,100,111,119,39,115,32,109,101,115,115,97,103,101,46,32,66,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98, + 108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98, + 108,97,104,32,98,108,97,104,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,49,49,41,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87, + 105,110,100,111,119,32,119,32,40,84,40,34,65,108,101,114,116,87,105,110,100,111,119,32,100,101,109,111,46,46,34,41,44,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,84,104,105,115,32,65,108, + 101,114,116,87,105,110,100,111,119,32,104,97,115,32,97,32,99,111,117,112,108,101,32,111,102,32,101,120,116,114,97,32,99,111,109,112,111,110,101,110, + 116,115,32,97,100,100,101,100,32,116,111,32,115,104,111,119,32,104,111,119,32,116,111,32,97,100,100,32,100,114,111,112,45,100,111,119,110,32,108,105, + 115,116,115,32,97,110,100,32,116,101,120,116,32,101,110,116,114,121,32,98,111,120,101,115,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58,81,117, + 101,115,116,105,111,110,73,99,111,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,119,46,97,100, + 100,84,101,120,116,69,100,105,116,111,114,32,40,84,40,34,116,101,120,116,34,41,44,32,84,40,34,101,110,116,101,114,32,115,111,109,101,32,116,101, + 120,116,32,104,101,114,101,34,41,44,32,84,40,34,116,101,120,116,32,102,105,101,108,100,58,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,83,116,114,105,110,103,65,114,114,97,121,32,111,112,116,105,111,110,115,59,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,112,116,105,111,110,115,46,97,100,100,32,40,84,40,34,111,112,116,105,111,110,32,49,34, + 41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,112,116,105,111,110,115,46,97,100,100,32,40,84,40, + 34,111,112,116,105,111,110,32,50,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,112,116,105,111, + 110,115,46,97,100,100,32,40,84,40,34,111,112,116,105,111,110,32,51,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,111,112,116,105,111,110,115,46,97,100,100,32,40,84,40,34,111,112,116,105,111,110,32,52,34,41,41,59,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,119,46,97,100,100,67,111,109,98,111,66,111,120,32,40,84,40,34,111,112,116,105,111,110,34, + 41,44,32,111,112,116,105,111,110,115,44,32,84,40,34,115,111,109,101,32,111,112,116,105,111,110,115,34,41,41,59,13,10,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,119,46,97,100,100,66,117,116,116,111,110,32,40,84,40,34,111,107,34,41,44,32,49,44,32, + 75,101,121,80,114,101,115,115,32,40,75,101,121,80,114,101,115,115,58,58,114,101,116,117,114,110,75,101,121,44,32,48,44,32,48,41,41,59,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,119,46,97,100,100,66,117,116,116,111,110,32,40,84,40,34,99,97,110,99, + 101,108,34,41,44,32,48,44,32,75,101,121,80,114,101,115,115,32,40,75,101,121,80,114,101,115,115,58,58,101,115,99,97,112,101,75,101,121,44,32, + 48,44,32,48,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,119,46,114,117,110, + 77,111,100,97,108,76,111,111,112,40,41,32,33,61,32,48,41,32,47,47,32,105,115,32,116,104,101,121,32,112,105,99,107,101,100,32,39,111,107,39, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,47,47,32,116,104,105,115,32,105,115,32,116,104,101,32,105,116,101,109,32,116,104,101,121,32,99,104,111,115,101,32, + 105,110,32,116,104,101,32,100,114,111,112,45,100,111,119,110,32,108,105,115,116,46,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,99,111,110,115,116,32,105,110,116,32,111,112,116,105,111,110,73,110,100,101,120,67,104,111,115,101,110,32,61,32,119, + 46,103,101,116,67,111,109,98,111,66,111,120,67,111,109,112,111,110,101,110,116,32,40,84,40,34,111,112,116,105,111,110,34,41,41,45,62,103,101,116, + 83,101,108,101,99,116,101,100,73,116,101,109,73,110,100,101,120,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,47,47,32,116,104,105,115,32,105,115,32,116,104,101,32,116,101,120,116,32,116,104,101,121,32,101,110,116,101,114,101,100, + 46,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,83,116,114,105,110,103,32,116,101,120,116,32, + 61,32,119,46,103,101,116,84,101,120,116,69,100,105,116,111,114,67,111,110,116,101,110,116,115,32,40,84,40,34,116,101,120,116,34,41,41,59,13,10, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49, + 49,50,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,68,101,109,111,66,97,99,107,103,114,111,117,110,100,84,104,114,101,97,100,32,100,101,109,111,84,104,114,101,97,100,59,13,10,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,100,101,109,111,84,104,114,101,97,100,46,114,117,110,84,104, + 114,101,97,100,40,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,116,104,114,101,97,100,32,102,105,110,105,115,104,101,100,32,110,111,114,109,97, + 108,108,121,46,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100, + 111,119,58,58,115,104,111,119,77,101,115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,87,97,114,110,105,110,103, + 73,99,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,80,114,111,103,114,101,115,115,32,119,105,110,100,111,119,34,41, 44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,65,110,100,32,116,104,105,115,32,105,115,32,116,104,101,32,65,108, - 101,114,116,87,105,110,100,111,119,39,115,32,109,101,115,115,97,103,101,46,32,66,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104, - 32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104,32,98,108,97,104, - 32,98,108,97,104,46,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,49,49,41,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100, - 111,119,32,119,32,40,84,40,34,65,108,101,114,116,87,105,110,100,111,119,32,100,101,109,111,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,84,104,105,115,32,65,108,101,114,116, - 87,105,110,100,111,119,32,104,97,115,32,97,32,99,111,117,112,108,101,32,111,102,32,101,120,116,114,97,32,99,111,109,112,111,110,101,110,116,115,32, - 97,100,100,101,100,32,116,111,32,115,104,111,119,32,104,111,119,32,116,111,32,97,100,100,32,100,114,111,112,45,100,111,119,110,32,108,105,115,116,115, - 32,97,110,100,32,116,101,120,116,32,101,110,116,114,121,32,98,111,120,101,115,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58,81,117,101,115,116, - 105,111,110,73,99,111,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,119,46,97,100,100,84,101, - 120,116,69,100,105,116,111,114,32,40,84,40,34,116,101,120,116,34,41,44,32,84,40,34,101,110,116,101,114,32,115,111,109,101,32,116,101,120,116,32, - 104,101,114,101,34,41,44,32,84,40,34,116,101,120,116,32,102,105,101,108,100,58,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,83,116,114,105,110,103,65,114,114,97,121,32,111,112,116,105,111,110,115,59,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,111,112,116,105,111,110,115,46,97,100,100,32,40,84,40,34,111,112,116,105,111,110,32,49,34,41,41,59, - 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,112,116,105,111,110,115,46,97,100,100,32,40,84,40,34,111,112, - 116,105,111,110,32,50,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,112,116,105,111,110,115,46, - 97,100,100,32,40,84,40,34,111,112,116,105,111,110,32,51,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,111,112,116,105,111,110,115,46,97,100,100,32,40,84,40,34,111,112,116,105,111,110,32,52,34,41,41,59,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,119,46,97,100,100,67,111,109,98,111,66,111,120,32,40,84,40,34,111,112,116,105,111,110,34,41,44,32, - 111,112,116,105,111,110,115,44,32,84,40,34,115,111,109,101,32,111,112,116,105,111,110,115,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,119,46,97,100,100,66,117,116,116,111,110,32,40,84,40,34,111,107,34,41,44,32,49,44,32,75,101,121, - 80,114,101,115,115,32,40,75,101,121,80,114,101,115,115,58,58,114,101,116,117,114,110,75,101,121,44,32,48,44,32,48,41,41,59,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,119,46,97,100,100,66,117,116,116,111,110,32,40,84,40,34,99,97,110,99,101,108,34, - 41,44,32,48,44,32,75,101,121,80,114,101,115,115,32,40,75,101,121,80,114,101,115,115,58,58,101,115,99,97,112,101,75,101,121,44,32,48,44,32, - 48,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,119,46,114,117,110,77,111,100, - 97,108,76,111,111,112,40,41,32,33,61,32,48,41,32,47,47,32,105,115,32,116,104,101,121,32,112,105,99,107,101,100,32,39,111,107,39,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,47,47,32,116,104,105,115,32,105,115,32,116,104,101,32,105,116,101,109,32,116,104,101,121,32,99,104,111,115,101,32,105,110,32, - 116,104,101,32,100,114,111,112,45,100,111,119,110,32,108,105,115,116,46,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,99,111,110,115,116,32,105,110,116,32,111,112,116,105,111,110,73,110,100,101,120,67,104,111,115,101,110,32,61,32,119,46,103,101, - 116,67,111,109,98,111,66,111,120,67,111,109,112,111,110,101,110,116,32,40,84,40,34,111,112,116,105,111,110,34,41,41,45,62,103,101,116,83,101,108, - 101,99,116,101,100,73,116,101,109,73,110,100,101,120,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,47,47,32,116,104,105,115,32,105,115,32,116,104,101,32,116,101,120,116,32,116,104,101,121,32,101,110,116,101,114,101,100,46,46,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,83,116,114,105,110,103,32,116,101,120,116,32,61,32,119, - 46,103,101,116,84,101,120,116,69,100,105,116,111,114,67,111,110,116,101,110,116,115,32,40,84,40,34,116,101,120,116,34,41,41,59,13,10,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,49,50,41, - 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,68,101,109,111,66,97,99,107,103,114,111,117,110,100,84,104,114,101,97,100,32,100,101,109,111,84,104,114,101,97,100,59,13,10,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,100,101,109,111,84,104,114,101,97,100,46,114,117,110,84,104,114,101,97, - 100,40,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,116,104,114,101,97,100,32,102,105,110,105,115,104,101,100,32,110,111,114,109,97,108,108,121, - 46,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58, - 58,115,104,111,119,77,101,115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,87,97,114,110,105,110,103,73,99,111, - 110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,80,114,111,103,114,101,115,115,32,119,105,110,100,111,119,34,41,44,13,10, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,84,104,114,101,97,100,32,102,105,110,105,115,104,101,100,32,111,107,33,34,41,41,59,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,117,115,101,114,32,112,114,101,115,115,101,100,32,116,104,101,32,99,97,110, - 99,101,108,32,98,117,116,116,111,110,46,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108, - 101,114,116,87,105,110,100,111,119,58,58,115,104,111,119,77,101,115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58, - 87,97,114,110,105,110,103,73,99,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,80,114,111,103,114,101,115,115,32,119, - 105,110,100,111,119,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,89,111,117,32,112,114,101,115,115,101,100,32,99,97, - 110,99,101,108,33,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40, - 114,101,115,117,108,116,32,61,61,32,49,50,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,67,111,108,111,117,114,83,101,108,101,99,116,111,114,68,105,97,108,111,103,87,105,110,100,111, - 119,32,99,111,108,111,117,114,68,105,97,108,111,103,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,47, - 47,32,116,104,105,115,32,119,105,108,108,32,114,117,110,32,97,110,32,101,118,101,110,116,32,108,111,111,112,32,117,110,116,105,108,32,116,104,101,32, - 100,105,97,108,111,103,39,115,32,99,108,111,115,101,66,117,116,116,111,110,80,114,101,115,115,101,100,40,41,13,10,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,47,47,32,109,101,116,104,111,100,32,99,97,117,115,101,115,32,116,104,101,32,108,111,111,112,32,116,111,32, - 101,120,105,116,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,108,111,117,114,68,105,97,108,111,103,46, - 114,117,110,77,111,100,97,108,76,111,111,112,40,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,52,48,41,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,35,105,102,32,74,85,67,69,95,77,65,67,13,10,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,65,112,112,108,101,82,101,109,111,116,101,84,101,115,116,87,105,110,100,111,119,32,116,101,115,116,59,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,101,115,116,46,114,117,110,77,111,100,97,108,76,111,111,112,40,41,59,13, - 10,35,101,110,100,105,102,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,62,61,32,49,50,49,32,38,38,32,114,101,115,117,108,116,32,60,32,49, - 51,57,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,99,111,110,115,116,32,98,111,111,108,32,117,115,101,78,97,116,105,118,101,86,101,114,115,105,111,110,32,61,32,114,101,115,117,108,116, - 32,60,32,49,51,48,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,114,101,115,117,108,116,32, - 62,32,49,51,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,115,117,108,116,32,45, - 61,32,49,48,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,114,101,115,117,108,116,32, - 61,61,32,49,50,49,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,67,104,111,111,115,101,114,32,102,99,32,40,84,40,34,67,104,111,111,115, - 101,32,97,32,102,105,108,101,32,116,111,32,111,112,101,110,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,58,58,103,101,116,67,117,114,114,101,110,116, - 87,111,114,107,105,110,103,68,105,114,101,99,116,111,114,121,40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,42,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,117,115,101,78,97,116,105,118,101,86, - 101,114,115,105,111,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40, - 102,99,46,98,114,111,119,115,101,70,111,114,70,105,108,101,84,111,79,112,101,110,40,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,70,105,108,101,32,99,104,111,115,101,110,70,105,108,101,32,61,32,102,99,46,103,101,116,82,101,115,117,108,116,40,41,59,13,10,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58, - 115,104,111,119,77,101,115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,73,110,102,111,73,99,111,110,44,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,84,104,114,101,97,100,32,102,105,110,105,115,104,101,100,32,111,107,33,34,41, + 41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,117,115,101,114,32,112,114,101,115,115,101,100,32,116,104,101,32, + 99,97,110,99,101,108,32,98,117,116,116,111,110,46,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104,111,119,77,101,115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111, + 119,58,58,87,97,114,110,105,110,103,73,99,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,80,114,111,103,114,101,115, + 115,32,119,105,110,100,111,119,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,89,111,117,32,112,114,101,115,115,101,100, + 32,99,97,110,99,101,108,33,34,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,13,10,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105, + 102,32,40,114,101,115,117,108,116,32,61,61,32,49,50,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,67,111,108,111,117,114,83,101,108,101,99,116,111,114,68,105,97,108,111,103,87,105, + 110,100,111,119,32,99,111,108,111,117,114,68,105,97,108,111,103,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,47,47,32,116,104,105,115,32,119,105,108,108,32,114,117,110,32,97,110,32,101,118,101,110,116,32,108,111,111,112,32,117,110,116,105,108,32,116, + 104,101,32,100,105,97,108,111,103,39,115,32,99,108,111,115,101,66,117,116,116,111,110,80,114,101,115,115,101,100,40,41,13,10,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,109,101,116,104,111,100,32,99,97,117,115,101,115,32,116,104,101,32,108,111,111,112,32, + 116,111,32,101,120,105,116,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,111,108,111,117,114,68,105,97,108, + 111,103,46,114,117,110,77,111,100,97,108,76,111,111,112,40,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,52,48,41,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,35,105,102,32,74,85,67,69,95,77,65,67,13,10,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,65,112,112,108,101,82,101,109,111,116,101,84,101,115,116,87,105,110,100,111,119,32,116,101,115,116,59, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,101,115,116,46,114,117,110,77,111,100,97,108,76,111,111,112,40, + 41,59,13,10,35,101,110,100,105,102,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,62,61,32,49,50,49,32,38,38,32,114,101,115,117,108,116,32, + 60,32,49,51,57,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,99,111,110,115,116,32,98,111,111,108,32,117,115,101,78,97,116,105,118,101,86,101,114,115,105,111,110,32,61,32,114,101,115, + 117,108,116,32,60,32,49,51,48,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,114,101,115,117, + 108,116,32,62,32,49,51,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,114,101,115,117,108, + 116,32,45,61,32,49,48,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,114,101,115,117, + 108,116,32,61,61,32,49,50,49,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,67,104,111,111,115,101,114,32,102,99,32,40,84,40,34,67,104, + 111,111,115,101,32,97,32,102,105,108,101,32,116,111,32,111,112,101,110,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,58,58,103,101,116,67,117,114,114, + 101,110,116,87,111,114,107,105,110,103,68,105,114,101,99,116,111,114,121,40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,42,34,41,44,13,10,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,117,115,101,78,97,116,105, + 118,101,86,101,114,115,105,111,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105, + 102,32,40,102,99,46,98,114,111,119,115,101,70,111,114,70,105,108,101,84,111,79,112,101,110,40,41,41,13,10,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,70,105,108,101,32,99,104,111,115,101,110,70,105,108,101,32,61,32,102,99,46,103,101,116,82,101,115,117,108,116,40,41,59,13,10, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111, + 119,58,58,115,104,111,119,77,101,115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,73,110,102,111,73,99,111,110, + 44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,70,105,108,101,32,67,104,111,111,115,101,114,46,46,46,34,41, + 44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,89,111,117,32,112,105,99,107,101,100,58,32,34,41,32,43,32, + 99,104,111,115,101,110,70,105,108,101,46,103,101,116,70,117,108,108,80,97,116,104,78,97,109,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61, + 32,49,50,52,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,73,109,97,103,101,80,114,101,118,105,101,119,67,111,109,112,111,110,101,110,116,32,105,109,97,103, + 101,80,114,101,118,105,101,119,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,109,97,103,101, + 80,114,101,118,105,101,119,46,115,101,116,83,105,122,101,32,40,50,48,48,44,32,50,48,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,67,104,111,111,115,101,114,32,102,99,32,40,84,40,34,67,104,111,111,115,101, + 32,97,110,32,105,109,97,103,101,32,116,111,32,111,112,101,110,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,58,58,103,101,116,67,117,114,114,101,110, + 116,87,111,114,107,105,110,103,68,105,114,101,99,116,111,114,121,40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,42,46,106,112,103,59,42,46,106,112,101,103,59,42,46, + 112,110,103,59,42,46,103,105,102,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,117,115,101,78,97,116,105,118,101,86,101,114,115,105,111,110,41,59,13,10,13,10,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,102,99,46,98,114,111,119,115,101,70,111,114,70,105,108,101, + 84,111,79,112,101,110,32,40,38,105,109,97,103,101,80,114,101,118,105,101,119,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 70,105,108,101,32,99,104,111,115,101,110,70,105,108,101,32,61,32,102,99,46,103,101,116,82,101,115,117,108,116,40,41,59,13,10,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104, + 111,119,77,101,115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,73,110,102,111,73,99,111,110,44,13,10,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,70,105,108,101,32,67,104,111,111,115,101,114,46,46,46,34,41,44,13,10, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,70,105,108,101,32,67,104,111,111,115,101,114,46,46,46,34,41,44,13,10,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,89,111,117,32,112,105,99,107,101,100,58,32,34,41,32,43,32,99,104,111, - 115,101,110,70,105,108,101,46,103,101,116,70,117,108,108,80,97,116,104,78,97,109,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,50, - 52,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,73,109,97,103,101,80,114,101,118,105,101,119,67,111,109,112,111,110,101,110,116,32,105,109,97,103,101,80,114, - 101,118,105,101,119,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,109,97,103,101,80,114,101, - 118,105,101,119,46,115,101,116,83,105,122,101,32,40,50,48,48,44,32,50,48,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,67,104,111,111,115,101,114,32,102,99,32,40,84,40,34,67,104,111,111,115,101,32,97,110, - 32,105,109,97,103,101,32,116,111,32,111,112,101,110,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,58,58,103,101,116,67,117,114,114,101,110,116,87,111, - 114,107,105,110,103,68,105,114,101,99,116,111,114,121,40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,42,46,106,112,103,59,42,46,106,112,101,103,59,42,46,112,110,103, - 59,42,46,103,105,102,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,117,115,101,78,97,116,105,118,101,86,101,114,115,105,111,110,41,59,13,10,13,10,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,102,99,46,98,114,111,119,115,101,70,111,114,70,105,108,101,84,111,79, - 112,101,110,32,40,38,105,109,97,103,101,80,114,101,118,105,101,119,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108, - 101,32,99,104,111,115,101,110,70,105,108,101,32,61,32,102,99,46,103,101,116,82,101,115,117,108,116,40,41,59,13,10,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104,111,119,77, - 101,115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,73,110,102,111,73,99,111,110,44,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,89,111,117,32,112,105,99,107,101,100,58,32,34,41,32,43,32,99,104,111,115,101, + 110,70,105,108,101,46,103,101,116,70,117,108,108,80,97,116,104,78,97,109,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,50,50,41, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,70,105,108,101,67,104,111,111,115,101,114,32,102,99,32,40,84,40,34,67,104,111,111,115,101,32,97,32,102,105,108, + 101,32,116,111,32,115,97,118,101,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,58,58,103,101,116,67,117,114,114,101,110,116,87,111,114,107,105,110,103, + 68,105,114,101,99,116,111,114,121,40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,42,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,117,115,101,78,97,116,105,118,101,86,101,114,115,105,111,110,41, + 59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,102,99,46,98,114,111,119, + 115,101,70,111,114,70,105,108,101,84,111,83,97,118,101,32,40,116,114,117,101,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 70,105,108,101,32,99,104,111,115,101,110,70,105,108,101,32,61,32,102,99,46,103,101,116,82,101,115,117,108,116,40,41,59,13,10,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104, + 111,119,77,101,115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,73,110,102,111,73,99,111,110,44,13,10,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,70,105,108,101,32,67,104,111,111,115,101,114,46,46,46,34,41,44,13,10,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,70,105,108,101,32,67,104,111,111,115,101,114,46,46,46,34,41,44,13,10,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,89,111,117,32,112,105,99,107,101,100,58,32,34,41,32,43,32,99,104,111,115,101,110,70,105, - 108,101,46,103,101,116,70,117,108,108,80,97,116,104,78,97,109,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,50,50,41,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,70,105,108,101,67,104,111,111,115,101,114,32,102,99,32,40,84,40,34,67,104,111,111,115,101,32,97,32,102,105,108,101,32,116, - 111,32,115,97,118,101,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,89,111,117,32,112,105,99,107,101,100,58,32,34,41,32,43,32,99,104,111,115,101, + 110,70,105,108,101,46,103,101,116,70,117,108,108,80,97,116,104,78,97,109,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,50,51,41, + 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,70,105,108,101,67,104,111,111,115,101,114,32,102,99,32,40,84,40,34,67,104,111,111,115,101,32,97,32,100,105,114, + 101,99,116,111,114,121,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,58,58,103,101,116,67,117,114,114,101,110,116,87,111,114,107,105,110,103,68,105,114, 101,99,116,111,114,121,40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,84,40,34,42,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,117,115,101,78,97,116,105,118,101,86,101,114,115,105,111,110,41,59,13,10, 13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,102,99,46,98,114,111,119,115,101,70, - 111,114,70,105,108,101,84,111,83,97,118,101,32,40,116,114,117,101,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108, - 101,32,99,104,111,115,101,110,70,105,108,101,32,61,32,102,99,46,103,101,116,82,101,115,117,108,116,40,41,59,13,10,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104,111,119,77, - 101,115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,73,110,102,111,73,99,111,110,44,13,10,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,70,105,108,101,32,67,104,111,111,115,101,114,46,46,46,34,41,44,13,10,32,32,32,32,32, + 111,114,68,105,114,101,99,116,111,114,121,40,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,32,99,104,111,115, + 101,110,68,105,114,101,99,116,111,114,121,32,61,32,102,99,46,103,101,116,82,101,115,117,108,116,40,41,59,13,10,13,10,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104,111,119,77,101, + 115,115,97,103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,73,110,102,111,73,99,111,110,44,13,10,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,84,40,34,89,111,117,32,112,105,99,107,101,100,58,32,34,41,32,43,32,99,104,111,115,101,110,70,105, - 108,101,46,103,101,116,70,117,108,108,80,97,116,104,78,97,109,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,50,51,41,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,70,105,108,101,67,104,111,111,115,101,114,32,102,99,32,40,84,40,34,67,104,111,111,115,101,32,97,32,100,105,114,101,99,116, - 111,114,121,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,58,58,103,101,116,67,117,114,114,101,110,116,87,111,114,107,105,110,103,68,105,114,101,99,116, - 111,114,121,40,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,84,40,34,42,34,41,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,117,115,101,78,97,116,105,118,101,86,101,114,115,105,111,110,41,59,13,10,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,102,99,46,98,114,111,119,115,101,70,111,114,68, - 105,114,101,99,116,111,114,121,40,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,70,105,108,101,32,99,104,111,115,101,110,68, - 105,114,101,99,116,111,114,121,32,61,32,102,99,46,103,101,116,82,101,115,117,108,116,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,65,108,101,114,116,87,105,110,100,111,119,58,58,115,104,111,119,77,101,115,115,97, - 103,101,66,111,120,32,40,65,108,101,114,116,87,105,110,100,111,119,58,58,73,110,102,111,73,99,111,110,44,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,84,40,34,70,105,108,101,32,67,104,111,111,115,101,114,46,46,46,34,41,44,13,10,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,84,40,34,70,105,108,101,32,67,104,111,111,115,101,114,46,46,46,34,41,44,13,10,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,84,40,34,89,111,117,32,112,105,99,107,101,100,58,32,34,41,32,43,32,99,104,111,115,101,110,68,105,114,101,99,116, - 111,114,121,46,103,101,116,70,117,108,108,80,97,116,104,78,97,109,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114, - 101,115,117,108,116,32,61,61,32,49,48,48,49,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,97,98,115,45,62,115,101,116,79,114,105,101,110,116,97,116,105,111,110,32,40,84,97,98, - 98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115,65,116,84,111,112,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61, - 32,49,48,48,50,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,116,97,98,115,45,62,115,101,116,79,114,105,101,110,116,97,116,105,111,110,32,40,84,97,98,98,101,100,66,117,116,116,111, - 110,66,97,114,58,58,84,97,98,115,65,116,66,111,116,116,111,109,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13, - 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,48,48,51, - 41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,116,97,98,115,45,62,115,101,116,79,114,105,101,110,116,97,116,105,111,110,32,40,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58, - 58,84,97,98,115,65,116,76,101,102,116,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,48,48,52,41,13,10,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,97,98,115,45, - 62,115,101,116,79,114,105,101,110,116,97,116,105,111,110,32,40,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115,65,116, - 82,105,103,104,116,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 125,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61, + 32,32,32,32,32,32,32,32,32,32,32,84,40,34,89,111,117,32,112,105,99,107,101,100,58,32,34,41,32,43,32,99,104,111,115,101,110,68,105,114, + 101,99,116,111,114,121,46,103,101,116,70,117,108,108,80,97,116,104,78,97,109,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102, + 32,40,114,101,115,117,108,116,32,61,61,32,49,48,48,49,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,97,98,115,45,62,115,101,116,79,114,105,101,110,116,97,116,105,111,110,32,40, + 84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98,115,65,116,84,111,112,41,59,13,10,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116, + 32,61,61,32,49,48,48,50,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,116,97,98,115,45,62,115,101,116,79,114,105,101,110,116,97,116,105,111,110,32,40,84,97,98,98,101,100,66,117, + 116,116,111,110,66,97,114,58,58,84,97,98,115,65,116,66,111,116,116,111,109,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,125,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49, + 48,48,51,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,116,97,98,115,45,62,115,101,116,79,114,105,101,110,116,97,116,105,111,110,32,40,84,97,98,98,101,100,66,117,116,116,111,110,66, + 97,114,58,58,84,97,98,115,65,116,76,101,102,116,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,101,115,117,108,116,32,61,61,32,49,48,48,52,41,13,10,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,97, + 98,115,45,62,115,101,116,79,114,105,101,110,116,97,116,105,111,110,32,40,84,97,98,98,101,100,66,117,116,116,111,110,66,97,114,58,58,84,97,98, + 115,65,116,82,105,103,104,116,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,32, + 32,32,32,125,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,13,10,47,47,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,67,111,109,112,111,110,101,110,116, - 42,32,99,114,101,97,116,101,87,105,100,103,101,116,115,68,101,109,111,32,40,65,112,112,108,105,99,97,116,105,111,110,67,111,109,109,97,110,100,77, - 97,110,97,103,101,114,42,32,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41,13,10,123,13,10,32,32,32,32,114,101,116,117,114,110,32,110, - 101,119,32,87,105,100,103,101,116,115,68,101,109,111,32,40,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41,59,13,10,125,13,10,0,0}; + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,67,111,109,112,111,110, + 101,110,116,42,32,99,114,101,97,116,101,87,105,100,103,101,116,115,68,101,109,111,32,40,65,112,112,108,105,99,97,116,105,111,110,67,111,109,109,97, + 110,100,77,97,110,97,103,101,114,42,32,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41,13,10,123,13,10,32,32,32,32,114,101,116,117,114, + 110,32,110,101,119,32,87,105,100,103,101,116,115,68,101,109,111,32,40,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41,59,13,10,125,13,10,0,0}; const char* BinaryData::widgetsdemo_cpp = (const char*) temp17; diff --git a/extras/juce demo/src/BinaryData.h b/extras/juce demo/src/BinaryData.h index 21fa2e5dd8..61c36ae4be 100644 --- a/extras/juce demo/src/BinaryData.h +++ b/extras/juce demo/src/BinaryData.h @@ -54,7 +54,7 @@ namespace BinaryData const int treeviewdemo_cppSize = 7534; extern const char* widgetsdemo_cpp; - const int widgetsdemo_cppSize = 52997; + const int widgetsdemo_cppSize = 53000; }; diff --git a/extras/juce demo/src/binarydata/WidgetsDemo.cpp b/extras/juce demo/src/binarydata/WidgetsDemo.cpp index aec2d6bc87..9dd7eff920 100644 --- a/extras/juce demo/src/binarydata/WidgetsDemo.cpp +++ b/extras/juce demo/src/binarydata/WidgetsDemo.cpp @@ -175,8 +175,8 @@ class CustomMenuComponent : public PopupMenuCustomComponent, public: CustomMenuComponent() - blobX (0), - blobY (0) + : blobX (0), + blobY (0) { // set off a timer to move a blob around on this component every // 300 milliseconds - see the timerCallback() method. diff --git a/extras/juce demo/src/demos/WidgetsDemo.cpp b/extras/juce demo/src/demos/WidgetsDemo.cpp index 519da9714c..9dd7eff920 100644 --- a/extras/juce demo/src/demos/WidgetsDemo.cpp +++ b/extras/juce demo/src/demos/WidgetsDemo.cpp @@ -175,7 +175,7 @@ class CustomMenuComponent : public PopupMenuCustomComponent, public: CustomMenuComponent() - : blobX (0), + : blobX (0), blobY (0) { // set off a timer to move a blob around on this component every diff --git a/extras/the jucer/src/ui/jucer_MainWindow.cpp b/extras/the jucer/src/ui/jucer_MainWindow.cpp index dcd8724726..ea1927882d 100644 --- a/extras/the jucer/src/ui/jucer_MainWindow.cpp +++ b/extras/the jucer/src/ui/jucer_MainWindow.cpp @@ -113,6 +113,7 @@ MainWindow::MainWindow() } addKeyListener (commandManager->getKeyMappings()); + commandManager->addListener (this); // don't want the window to take focus when the title-bar is clicked.. setWantsKeyboardFocus (false); diff --git a/src/juce_app_includes.h b/src/juce_app_includes.h index c1f8a5ef84..ca580d9a5d 100644 --- a/src/juce_app_includes.h +++ b/src/juce_app_includes.h @@ -569,6 +569,9 @@ #ifndef __JUCE_FILEPREVIEWCOMPONENT_JUCEHEADER__ #include "juce_appframework/gui/components/filebrowser/juce_FilePreviewComponent.h" #endif +#ifndef __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__ + #include "juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.h" +#endif #ifndef __JUCE_FILETREECOMPONENT_JUCEHEADER__ #include "juce_appframework/gui/components/filebrowser/juce_FileTreeComponent.h" #endif diff --git a/src/juce_appframework/documents/juce_FileBasedDocument.cpp b/src/juce_appframework/documents/juce_FileBasedDocument.cpp index b5d7281d99..4339c19b87 100644 --- a/src/juce_appframework/documents/juce_FileBasedDocument.cpp +++ b/src/juce_appframework/documents/juce_FileBasedDocument.cpp @@ -256,7 +256,7 @@ FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool w if (f.existsAsFile() || f.getParentDirectory().isDirectory()) f = f.getSiblingFile (legalFilename); else - f = File::getCurrentWorkingDirectory().getChildFile (legalFilename); + f = File::getSpecialLocation (File::userDocumentsDirectory).getChildFile (legalFilename); f = f.withFileExtension (fileExtension) .getNonexistentSibling (true); @@ -267,8 +267,11 @@ FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool w { setLastDocumentOpened (fc.getResult()); - return saveAs (fc.getResult(), - false, false, true); + File chosen (fc.getResult()); + if (chosen.getFileExtension().isEmpty()) + chosen = chosen.withFileExtension (fileExtension); + + return saveAs (f, false, false, true); } return userCancelledSave; diff --git a/src/juce_appframework/gui/components/filebrowser/juce_FileChooser.h b/src/juce_appframework/gui/components/filebrowser/juce_FileChooser.h index 6cc2728f27..a78000b417 100644 --- a/src/juce_appframework/gui/components/filebrowser/juce_FileChooser.h +++ b/src/juce_appframework/gui/components/filebrowser/juce_FileChooser.h @@ -49,7 +49,7 @@ void loadMooseFile() { FileChooser myChooser ("Please select the moose you want to load...", - File (SystemStats::getUserHomeDirectory()), + File::getSpecialLocation (File::userHomeDirectory), "*.moose"); if (myChooser.browseForFileToOpen()) diff --git a/src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp b/src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp new file mode 100644 index 0000000000..79ea51d714 --- /dev/null +++ b/src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp @@ -0,0 +1,279 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "../../../../juce_core/basics/juce_StandardHeader.h" + +BEGIN_JUCE_NAMESPACE + +#include "juce_FileSearchPathListComponent.h" +#include "../lookandfeel/juce_LookAndFeel.h" +#include "../filebrowser/juce_FileChooser.h" +#include "../../../../juce_core/text/juce_LocalisedStrings.h" +#include "../buttons/juce_TextButton.h" +#include "../buttons/juce_DrawableButton.h" +#include "../../graphics/drawables/juce_DrawablePath.h" + + +//============================================================================== +FileSearchPathListComponent::FileSearchPathListComponent() +{ + addAndMakeVisible (listBox = new ListBox (String::empty, this)); + listBox->setColour (ListBox::backgroundColourId, Colours::black.withAlpha (0.02f)); + listBox->setColour (ListBox::outlineColourId, Colours::black.withAlpha (0.1f)); + listBox->setOutlineThickness (1); + + addAndMakeVisible (addButton = new TextButton ("+")); + addButton->addButtonListener (this); + addButton->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop); + + addAndMakeVisible (removeButton = new TextButton ("-")); + removeButton->addButtonListener (this); + removeButton->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop); + + addAndMakeVisible (changeButton = new TextButton (TRANS("change..."))); + changeButton->addButtonListener (this); + + addAndMakeVisible (upButton = new DrawableButton (String::empty, DrawableButton::ImageOnButtonBackground)); + upButton->addButtonListener (this); + + { + Path arrowPath; + arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0, 40.0f, 100.0f, 50.0f); + DrawablePath arrowImage; + arrowImage.setSolidFill (Colours::black.withAlpha (0.4f)); + arrowImage.setPath (arrowPath); + + ((DrawableButton*) upButton)->setImages (&arrowImage); + } + + addAndMakeVisible (downButton = new DrawableButton (String::empty, DrawableButton::ImageOnButtonBackground)); + downButton->addButtonListener (this); + + { + Path arrowPath; + arrowPath.addArrow (50.0f, 0.0f, 50.0f, 100.0f, 40.0f, 100.0f, 50.0f); + DrawablePath arrowImage; + arrowImage.setSolidFill (Colours::black.withAlpha (0.4f)); + arrowImage.setPath (arrowPath); + + ((DrawableButton*) downButton)->setImages (&arrowImage); + } + + updateButtons(); +} + +FileSearchPathListComponent::~FileSearchPathListComponent() +{ + deleteAllChildren(); +} + +void FileSearchPathListComponent::updateButtons() throw() +{ + const bool anythingSelected = listBox->getNumSelectedRows() > 0; + + removeButton->setEnabled (anythingSelected); + changeButton->setEnabled (anythingSelected); + upButton->setEnabled (anythingSelected); + downButton->setEnabled (anythingSelected); +} + +void FileSearchPathListComponent::changed() throw() +{ + listBox->updateContent(); + listBox->repaint(); + updateButtons(); +} + +//============================================================================== +void FileSearchPathListComponent::setPath (const FileSearchPath& newPath) +{ + if (newPath.toString() != path.toString()) + { + path = newPath; + changed(); + } +} + +void FileSearchPathListComponent::setDefaultBrowseTarget (const File& newDefaultDirectory) throw() +{ + defaultBrowseTarget = newDefaultDirectory; +} + +//============================================================================== +int FileSearchPathListComponent::getNumRows() +{ + return path.getNumPaths(); +} + +void FileSearchPathListComponent::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) +{ + if (rowIsSelected) + g.fillAll (findColour (TextEditor::highlightColourId)); + + g.setColour (findColour (ListBox::textColourId)); + Font f (height * 0.7f); + f.setHorizontalScale (0.9f); + g.setFont (f); + + g.drawText (path [rowNumber].getFullPathName(), + 4, 0, width - 6, height, + Justification::centredLeft, true); +} + +void FileSearchPathListComponent::deleteKeyPressed (int row) +{ + if (row >= 0 && row < path.getNumPaths()) + { + path.remove (row); + changed(); + } +} + +void FileSearchPathListComponent::returnKeyPressed (int row) +{ + FileChooser chooser (TRANS("Change folder..."), path [row], T("*")); + + if (chooser.browseForDirectory()) + { + path.remove (row); + path.add (chooser.getResult(), row); + changed(); + } +} + +void FileSearchPathListComponent::listBoxItemDoubleClicked (int row, const MouseEvent&) +{ + returnKeyPressed (row); +} + +void FileSearchPathListComponent::selectedRowsChanged (int) +{ + updateButtons(); +} + +void FileSearchPathListComponent::paint (Graphics& g) +{ + g.fillAll (findColour (backgroundColourId)); +} + +void FileSearchPathListComponent::resized() +{ + const int buttonH = 22; + const int buttonY = getHeight() - buttonH - 4; + listBox->setBounds (2, 2, getWidth() - 4, buttonY - 5); + + addButton->setBounds (2, buttonY, buttonH, buttonH); + removeButton->setBounds (addButton->getRight(), buttonY, buttonH, buttonH); + + ((TextButton*) changeButton)->changeWidthToFitText (buttonH); + downButton->setSize (buttonH * 2, buttonH); + upButton->setSize (buttonH * 2, buttonH); + + downButton->setTopRightPosition (getWidth() - 2, buttonY); + upButton->setTopRightPosition (downButton->getX() - 4, buttonY); + changeButton->setTopRightPosition (upButton->getX() - 8, buttonY); +} + +bool FileSearchPathListComponent::filesDropped (const StringArray& filenames, int /*mouseX*/, int mouseY) +{ + bool usedAny = false; + + for (int i = filenames.size(); --i >= 0;) + { + const File f (filenames[i]); + + if (f.isDirectory()) + { + const int row = listBox->getRowContainingPosition (0, mouseY - listBox->getY()); + path.add (f, row); + changed(); + usedAny = true; + } + } + + return usedAny; +} + +void FileSearchPathListComponent::buttonClicked (Button* button) +{ + const int currentRow = listBox->getSelectedRow(); + + if (button == removeButton) + { + deleteKeyPressed (currentRow); + } + else if (button == addButton) + { + File start (defaultBrowseTarget); + + if (start == File::nonexistent) + start = path [0]; + + if (start == File::nonexistent) + start = File::getCurrentWorkingDirectory(); + + FileChooser chooser (TRANS("Add a folder..."), start, T("*")); + + if (chooser.browseForDirectory()) + { + path.add (chooser.getResult(), currentRow); + } + } + else if (button == changeButton) + { + returnKeyPressed (currentRow); + } + else if (button == upButton) + { + if (currentRow > 0 && currentRow < path.getNumPaths()) + { + const File f (path[currentRow]); + path.remove (currentRow); + path.add (f, currentRow - 1); + listBox->selectRow (currentRow - 1); + } + } + else if (button == downButton) + { + if (currentRow >= 0 && currentRow < path.getNumPaths()-1) + { + const File f (path[currentRow]); + path.remove (currentRow); + path.add (f, currentRow + 1); + listBox->selectRow (currentRow + 1); + } + } + + changed(); +} + + +END_JUCE_NAMESPACE diff --git a/src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.h b/src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.h new file mode 100644 index 0000000000..17861d9994 --- /dev/null +++ b/src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.h @@ -0,0 +1,134 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__ +#define __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__ + +#include "../controls/juce_ListBox.h" +#include "../buttons/juce_Button.h" +#include "../../../../juce_core/io/files/juce_FileSearchPath.h" + + +//============================================================================== +/** + Shows a set of file paths in a list, allowing them to be added, removed or + re-ordered. + + @see FileSearchPath +*/ +class JUCE_API FileSearchPathListComponent : public Component, + public SettableTooltipClient, + private ButtonListener, + private ListBoxModel +{ +public: + //============================================================================== + /** Creates an empty FileSearchPathListComponent. + + */ + FileSearchPathListComponent(); + + /** Destructor. */ + ~FileSearchPathListComponent(); + + //============================================================================== + /** Returns the path as it is currently shown. */ + const FileSearchPath& getPath() const throw() { return path; } + + /** Changes the current path. */ + void setPath (const FileSearchPath& newPath); + + /** Sets a file or directory to be the default starting point for the browser to show. + + This is only used if the current file hasn't been set. + */ + void setDefaultBrowseTarget (const File& newDefaultDirectory) throw(); + + /** A set of colour IDs to use to change the colour of various aspects of the label. + + These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() + methods. + + @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour + */ + enum ColourIds + { + backgroundColourId = 0x1004100, /**< The background colour to fill the component with. + Make this transparent if you don't want the background to be filled. */ + }; + + //============================================================================== + /** @internal */ + int getNumRows(); + /** @internal */ + void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected); + /** @internal */ + void deleteKeyPressed (int lastRowSelected); + /** @internal */ + void returnKeyPressed (int lastRowSelected); + /** @internal */ + void listBoxItemDoubleClicked (int row, const MouseEvent&); + /** @internal */ + void selectedRowsChanged (int lastRowSelected); + /** @internal */ + void resized(); + /** @internal */ + void paint (Graphics& g); + /** @internal */ + bool filesDropped (const StringArray& filenames, int mouseX, int mouseY); + /** @internal */ + void buttonClicked (Button* button); + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + //============================================================================== + FileSearchPath path; + File defaultBrowseTarget; + + ListBox* listBox; + Button* addButton; + Button* removeButton; + Button* changeButton; + Button* upButton; + Button* downButton; + + void changed() throw(); + void updateButtons() throw(); + + FileSearchPathListComponent (const FileSearchPathListComponent&); + const FileSearchPathListComponent& operator= (const FileSearchPathListComponent&); +}; + + + +#endif // __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__ diff --git a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp index 8c3af896d5..ffe428539c 100644 --- a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -56,6 +56,7 @@ BEGIN_JUCE_NAMESPACE #include "../controls/juce_TreeView.h" #include "../filebrowser/juce_FilenameComponent.h" #include "../filebrowser/juce_DirectoryContentsDisplayComponent.h" +#include "../filebrowser/juce_FileSearchPathListComponent.h" #include "../layout/juce_GroupComponent.h" #include "../properties/juce_PropertyComponent.h" #include "../juce_Desktop.h" @@ -193,7 +194,9 @@ LookAndFeel::LookAndFeel() MidiKeyboardComponent::upDownButtonArrowColourId, 0xff000000, ColourSelector::backgroundColourId, 0xffe5e5e5, - ColourSelector::labelTextColourId, 0xff000000 + ColourSelector::labelTextColourId, 0xff000000, + + FileSearchPathListComponent::backgroundColourId, 0xffffffff, }; for (int i = 0; i < numElementsInArray (standardColours); i += 2) diff --git a/src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp b/src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp index b7d2a1f547..e4cdded509 100644 --- a/src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp +++ b/src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp @@ -70,6 +70,7 @@ extern bool juce_makeOpenGLContextCurrent (void* context); extern void juce_swapOpenGLBuffers (void* context); extern void juce_updateOpenGLWindowPos (void* context, Component* owner, Component* topComp); extern void juce_repaintOpenGLWindow (void* context); +extern bool juce_isActiveOpenGLContext (void* context) throw(); static VoidArray activeGLWindows (2); @@ -139,6 +140,11 @@ public: return context != 0 && juce_makeOpenGLContextCurrent (context); } + bool isActive() const throw() + { + return context != 0 && juce_isActiveOpenGLContext (context); + } + void swapBuffers() const { if (context != 0) @@ -222,6 +228,26 @@ void OpenGLComponent::makeCurrentContextInactive() juce_makeOpenGLContextCurrent (0); } +bool OpenGLComponent::isActiveContext() const throw() +{ + const InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData; + + return context != 0 && context->isActive(); +} + +OpenGLComponent* OpenGLComponent::getCurrentlyActiveContextComponent() throw() +{ + for (int i = activeGLWindows.size(); --i >= 0;) + { + OpenGLComponent* const component = (OpenGLComponent*) activeGLWindows.getUnchecked(i); + + if (component->isActiveContext()) + return component; + } + + return 0; +} + void OpenGLComponent::swapBuffers() { InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData; diff --git a/src/juce_appframework/gui/components/special/juce_OpenGLComponent.h b/src/juce_appframework/gui/components/special/juce_OpenGLComponent.h index f42b50292a..8c6f13ab59 100644 --- a/src/juce_appframework/gui/components/special/juce_OpenGLComponent.h +++ b/src/juce_appframework/gui/components/special/juce_OpenGLComponent.h @@ -78,6 +78,17 @@ public: */ void makeCurrentContextInactive(); + /** Returns true if this component is the active openGL context for the + current thread. + */ + bool isActiveContext() const throw(); + + /** Returns the OpenGLComponent that is currently the active context for + the current thread. + */ + static OpenGLComponent* getCurrentlyActiveContextComponent() throw(); + + //============================================================================== /** Flips the openGL buffers over. */ void swapBuffers();