diff --git a/build/linux/JUCE.make b/build/linux/JUCE.make index 276e383608..701b2bc20f 100644 --- a/build/linux/JUCE.make +++ b/build/linux/JUCE.make @@ -131,6 +131,7 @@ OBJECTS := \ $(OBJDIR)/juce_AudioThumbnailCache.o \ $(OBJDIR)/juce_FlacAudioFormat.o \ $(OBJDIR)/juce_OggVorbisAudioFormat.o \ + $(OBJDIR)/juce_QuickTimeAudioFormat.o \ $(OBJDIR)/juce_WavAudioFormat.o \ $(OBJDIR)/bitmath.o \ $(OBJDIR)/bitreader.o \ @@ -926,6 +927,11 @@ $(OBJDIR)/juce_OggVorbisAudioFormat.o: ../../src/juce_appframework/audio/audio_f @echo $(notdir $<) @$(CXX) $(CXXFLAGS) -o $@ -c $< +$(OBJDIR)/juce_QuickTimeAudioFormat.o: ../../src/juce_appframework/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CXX) $(CXXFLAGS) -o $@ -c $< + $(OBJDIR)/juce_WavAudioFormat.o: ../../src/juce_appframework/audio/audio_file_formats/juce_WavAudioFormat.cpp -@$(CMD_MKOBJDIR) @echo $(notdir $<) diff --git a/build/linux/platform_specific_code/juce_linux_Files.cpp b/build/linux/platform_specific_code/juce_linux_Files.cpp index 2da857e5d7..f916d3ffe3 100644 --- a/build/linux/platform_specific_code/juce_linux_Files.cpp +++ b/build/linux/platform_specific_code/juce_linux_Files.cpp @@ -198,6 +198,11 @@ bool File::isOnHardDisk() const throw() return true; } +bool File::isHidden() const throw() +{ + return getFileName().startsWithChar (T('.')); +} + //============================================================================== const File File::getSpecialLocation (const SpecialLocationType type) { diff --git a/build/macosx/Juce.xcodeproj/project.pbxproj b/build/macosx/Juce.xcodeproj/project.pbxproj index b61f4c2cd6..6546c6e7b4 100644 --- a/build/macosx/Juce.xcodeproj/project.pbxproj +++ b/build/macosx/Juce.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 84022DFC0DAE4CB9004CF59A /* juce_mac_AudioCDBurner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84022DFA0DAE4CB9004CF59A /* juce_mac_AudioCDBurner.cpp */; }; 84022DFD0DAE4CB9004CF59A /* juce_mac_HTTPStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 84022DFB0DAE4CB9004CF59A /* juce_mac_HTTPStream.h */; }; 84052DE408D095D200BEC0F0 /* juce_ToneGeneratorAudioSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84052DE208D095D200BEC0F0 /* juce_ToneGeneratorAudioSource.cpp */; }; 84052DE508D095D200BEC0F0 /* juce_ToneGeneratorAudioSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 84052DE308D095D200BEC0F0 /* juce_ToneGeneratorAudioSource.h */; }; @@ -204,6 +203,7 @@ 846927DF0A49ABE600314975 /* juce_RectanglePlacement.h in Headers */ = {isa = PBXBuildFile; fileRef = 846927DD0A49ABE600314975 /* juce_RectanglePlacement.h */; }; 846927E10A49ABFD00314975 /* juce_SVGParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 846927E00A49ABFD00314975 /* juce_SVGParser.cpp */; }; 847824810D7816A00082A5C5 /* juce_AudioCDBurner.h in Headers */ = {isa = PBXBuildFile; fileRef = 8478247F0D7816A00082A5C5 /* juce_AudioCDBurner.h */; }; + 847D06470DD88D1100DF6A61 /* juce_mac_Network.mm in Sources */ = {isa = PBXBuildFile; fileRef = 847D06460DD88D1100DF6A61 /* juce_mac_Network.mm */; }; 847F72DB0C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 847F72D70C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.cpp */; }; 847F72DC0C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 847F72D80C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.h */; }; 847F72DD0C2702A000CBECEC /* juce_FileTreeComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 847F72D90C2702A000CBECEC /* juce_FileTreeComponent.cpp */; }; @@ -225,7 +225,6 @@ 84A4882C08A22E2400752A2B /* juce_mac_Files.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A4882108A22E2400752A2B /* juce_mac_Files.cpp */; }; 84A4882D08A22E2400752A2B /* juce_mac_Fonts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A4882208A22E2400752A2B /* juce_mac_Fonts.cpp */; }; 84A4882E08A22E2400752A2B /* juce_mac_Messaging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A4882308A22E2400752A2B /* juce_mac_Messaging.cpp */; }; - 84A4882F08A22E2400752A2B /* juce_mac_Network.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A4882408A22E2400752A2B /* juce_mac_Network.cpp */; }; 84A4883008A22E2400752A2B /* juce_mac_SystemStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A4882508A22E2400752A2B /* juce_mac_SystemStats.cpp */; }; 84A4883108A22E2400752A2B /* juce_mac_Threads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A4882608A22E2400752A2B /* juce_mac_Threads.cpp */; }; 84A4883208A22E2400752A2B /* juce_mac_Windowing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A4882708A22E2400752A2B /* juce_mac_Windowing.cpp */; }; @@ -584,6 +583,7 @@ 84BC4E300C8DD38C00FA249B /* juce_GenericAudioProcessorEditor.h in Headers */ = {isa = PBXBuildFile; fileRef = 84BC4E280C8DD38C00FA249B /* juce_GenericAudioProcessorEditor.h */; }; 84C0EA5E0B3DDF2400EDF9D9 /* juce_IIRFilterAudioSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84C0EA5C0B3DDF2400EDF9D9 /* juce_IIRFilterAudioSource.cpp */; }; 84C0EA5F0B3DDF2400EDF9D9 /* juce_IIRFilterAudioSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 84C0EA5D0B3DDF2400EDF9D9 /* juce_IIRFilterAudioSource.h */; }; + 84CE8A410DC5D7D600799A0E /* juce_mac_AudioCDBurner.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84CE8A400DC5D7D600799A0E /* juce_mac_AudioCDBurner.mm */; }; 84D296BD09B763190026C535 /* juce_PropertiesFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D296BB09B763190026C535 /* juce_PropertiesFile.cpp */; }; 84D296BE09B763190026C535 /* juce_PropertiesFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D296BC09B763190026C535 /* juce_PropertiesFile.h */; }; 84E8209409729D2A0097675B /* juce_AudioFormatManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84E8209209729D2A0097675B /* juce_AudioFormatManager.cpp */; }; @@ -693,7 +693,6 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 84022DFA0DAE4CB9004CF59A /* juce_mac_AudioCDBurner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = juce_mac_AudioCDBurner.cpp; sourceTree = ""; }; 84022DFB0DAE4CB9004CF59A /* juce_mac_HTTPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = juce_mac_HTTPStream.h; sourceTree = ""; }; 84052DE208D095D200BEC0F0 /* juce_ToneGeneratorAudioSource.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_ToneGeneratorAudioSource.cpp; sourceTree = ""; }; 84052DE308D095D200BEC0F0 /* juce_ToneGeneratorAudioSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_ToneGeneratorAudioSource.h; sourceTree = ""; }; @@ -893,6 +892,7 @@ 846927DD0A49ABE600314975 /* juce_RectanglePlacement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_RectanglePlacement.h; sourceTree = ""; }; 846927E00A49ABFD00314975 /* juce_SVGParser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_SVGParser.cpp; sourceTree = ""; }; 8478247F0D7816A00082A5C5 /* juce_AudioCDBurner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_AudioCDBurner.h; sourceTree = ""; }; + 847D06460DD88D1100DF6A61 /* juce_mac_Network.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_Network.mm; sourceTree = ""; }; 847F72D70C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DirectoryContentsDisplayComponent.cpp; path = filebrowser/juce_DirectoryContentsDisplayComponent.cpp; sourceTree = ""; }; 847F72D80C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_DirectoryContentsDisplayComponent.h; path = filebrowser/juce_DirectoryContentsDisplayComponent.h; sourceTree = ""; }; 847F72D90C2702A000CBECEC /* juce_FileTreeComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileTreeComponent.cpp; path = filebrowser/juce_FileTreeComponent.cpp; sourceTree = ""; }; @@ -914,7 +914,6 @@ 84A4882108A22E2400752A2B /* juce_mac_Files.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_mac_Files.cpp; path = platform_specific_code/juce_mac_Files.cpp; sourceTree = SOURCE_ROOT; }; 84A4882208A22E2400752A2B /* juce_mac_Fonts.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_mac_Fonts.cpp; path = platform_specific_code/juce_mac_Fonts.cpp; sourceTree = SOURCE_ROOT; }; 84A4882308A22E2400752A2B /* juce_mac_Messaging.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_mac_Messaging.cpp; path = platform_specific_code/juce_mac_Messaging.cpp; sourceTree = SOURCE_ROOT; }; - 84A4882408A22E2400752A2B /* juce_mac_Network.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_mac_Network.cpp; path = platform_specific_code/juce_mac_Network.cpp; sourceTree = SOURCE_ROOT; }; 84A4882508A22E2400752A2B /* juce_mac_SystemStats.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_mac_SystemStats.cpp; path = platform_specific_code/juce_mac_SystemStats.cpp; sourceTree = SOURCE_ROOT; }; 84A4882608A22E2400752A2B /* juce_mac_Threads.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_mac_Threads.cpp; path = platform_specific_code/juce_mac_Threads.cpp; sourceTree = SOURCE_ROOT; }; 84A4882708A22E2400752A2B /* juce_mac_Windowing.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_mac_Windowing.cpp; path = platform_specific_code/juce_mac_Windowing.cpp; sourceTree = SOURCE_ROOT; }; @@ -1273,6 +1272,7 @@ 84BC4E280C8DD38C00FA249B /* juce_GenericAudioProcessorEditor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_GenericAudioProcessorEditor.h; sourceTree = ""; }; 84C0EA5C0B3DDF2400EDF9D9 /* juce_IIRFilterAudioSource.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_IIRFilterAudioSource.cpp; path = ../../src/juce_appframework/audio/audio_sources/juce_IIRFilterAudioSource.cpp; sourceTree = SOURCE_ROOT; }; 84C0EA5D0B3DDF2400EDF9D9 /* juce_IIRFilterAudioSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_IIRFilterAudioSource.h; path = ../../src/juce_appframework/audio/audio_sources/juce_IIRFilterAudioSource.h; sourceTree = SOURCE_ROOT; }; + 84CE8A400DC5D7D600799A0E /* juce_mac_AudioCDBurner.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_AudioCDBurner.mm; sourceTree = ""; }; 84D296BB09B763190026C535 /* juce_PropertiesFile.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_PropertiesFile.cpp; sourceTree = ""; }; 84D296BC09B763190026C535 /* juce_PropertiesFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_PropertiesFile.h; sourceTree = ""; }; 84E8209209729D2A0097675B /* juce_AudioFormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_AudioFormatManager.cpp; sourceTree = ""; }; @@ -1379,7 +1379,7 @@ 84FED3C80CAA96DA00003997 /* juce_FileDragAndDropTarget.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_FileDragAndDropTarget.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; }; + D2AAC046055464E500DB518D /* libjuce.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjuce.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1419,7 +1419,7 @@ 1AB674ADFE9D54B511CA2CBB /* Products */ = { isa = PBXGroup; children = ( - D2AAC046055464E500DB518D /* libjucedebug.a */, + D2AAC046055464E500DB518D /* libjuce.a */, ); name = Products; sourceTree = ""; @@ -1542,7 +1542,7 @@ 84A4881C08A22E2400752A2B /* mac specific code */ = { isa = PBXGroup; children = ( - 84022DFA0DAE4CB9004CF59A /* juce_mac_AudioCDBurner.cpp */, + 84CE8A400DC5D7D600799A0E /* juce_mac_AudioCDBurner.mm */, 84A4881E08A22E2400752A2B /* juce_mac_CoreAudio.cpp */, 84A4881F08A22E2400752A2B /* juce_mac_CoreMidi.cpp */, 84A4882008A22E2400752A2B /* juce_mac_FileChooser.cpp */, @@ -1551,7 +1551,7 @@ 84A06BE209CADB06006A43BD /* juce_mac_NamedPipe.cpp */, 84A4882208A22E2400752A2B /* juce_mac_Fonts.cpp */, 84A4882308A22E2400752A2B /* juce_mac_Messaging.cpp */, - 84A4882408A22E2400752A2B /* juce_mac_Network.cpp */, + 847D06460DD88D1100DF6A61 /* juce_mac_Network.mm */, 84A4882508A22E2400752A2B /* juce_mac_SystemStats.cpp */, 84A4882608A22E2400752A2B /* juce_mac_Threads.cpp */, 84A4882708A22E2400752A2B /* juce_mac_Windowing.cpp */, @@ -2924,7 +2924,7 @@ ); name = Juce; productName = Juce; - productReference = D2AAC046055464E500DB518D /* libjucedebug.a */; + productReference = D2AAC046055464E500DB518D /* libjuce.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ @@ -2955,7 +2955,6 @@ 84A4882C08A22E2400752A2B /* juce_mac_Files.cpp in Sources */, 84A4882D08A22E2400752A2B /* juce_mac_Fonts.cpp in Sources */, 84A4882E08A22E2400752A2B /* juce_mac_Messaging.cpp in Sources */, - 84A4882F08A22E2400752A2B /* juce_mac_Network.cpp in Sources */, 84A4883008A22E2400752A2B /* juce_mac_SystemStats.cpp in Sources */, 84A4883108A22E2400752A2B /* juce_mac_Threads.cpp in Sources */, 84A4883208A22E2400752A2B /* juce_mac_Windowing.cpp in Sources */, @@ -3319,7 +3318,8 @@ 8495BB8E0D8067B2001D9C0B /* juce_AudioThumbnailCache.cpp in Sources */, 8495BB940D806BDA001D9C0B /* juce_FileInputSource.cpp in Sources */, 84581EEA0D9148C500AE1A4C /* juce_QuickTimeAudioFormat.cpp in Sources */, - 84022DFC0DAE4CB9004CF59A /* juce_mac_AudioCDBurner.cpp in Sources */, + 84CE8A410DC5D7D600799A0E /* juce_mac_AudioCDBurner.mm in Sources */, + 847D06470DD88D1100DF6A61 /* juce_mac_Network.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/build/macosx/juce.xcconfig b/build/macosx/juce.xcconfig index 215fbb97d4..f2e188ba4b 100644 --- a/build/macosx/juce.xcconfig +++ b/build/macosx/juce.xcconfig @@ -1,4 +1,4 @@ -ARCHS = i386 +ARCHS = i386 ppc // For 10.2 (and later) compatibility, use these values: //GCC_VERSION_ppc = 3.3 @@ -8,10 +8,10 @@ ARCHS = i386 //SDKROOT_ppc = $(DEVELOPER_SDK_DIR)/MacOSX10.2.8.sdk // For 10.3 (and later) compatibility, use these instead: - MACOSX_DEPLOYMENT_TARGET = 10.5 -// MACOSX_DEPLOYMENT_TARGET_ppc = 10.3 - SDKROOT = $(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk -// SDKROOT_ppc = $(DEVELOPER_SDK_DIR)/MacOSX10.3.9.sdk +MACOSX_DEPLOYMENT_TARGET_ppc = 10.3 +MACOSX_DEPLOYMENT_TARGET = 10.4 +SDKROOT_ppc = $(DEVELOPER_SDK_DIR)/MacOSX10.3.9.sdk +SDKROOT = $(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk // For 10.4 (and later) compatibility, use these instead: // MACOSX_DEPLOYMENT_TARGET = 10.4 diff --git a/build/macosx/platform_specific_code/juce_mac_AudioCDBurner.cpp b/build/macosx/platform_specific_code/juce_mac_AudioCDBurner.cpp index fe928fdcf8..48eec767c7 100644 --- a/build/macosx/platform_specific_code/juce_mac_AudioCDBurner.cpp +++ b/build/macosx/platform_specific_code/juce_mac_AudioCDBurner.cpp @@ -29,48 +29,82 @@ ============================================================================== */ -#include "../../../src/juce_core/basics/juce_StandardHeader.h" +/*#include "../../../src/juce_core/basics/juce_StandardHeader.h" #include +extern "C" +{ + int juce_findDiskBurnerDevices (const char** devices); + void* juce_openDiskBurnerDevice (int deviceIndex); + void juce_deleteDiskBurnerDevice (void* diskBurnerDevice); + bool juce_isDiskPresentInDevice (void* diskBurnerDevice); + int juce_getNumAvailableAudioBlocks (void* diskBurnerDevice); + typedef bool (*diskBurnCallback) (void* userRef, float progress); + void juce_performBurn (void* diskBurnerDevice, diskBurnCallback callback); +} + BEGIN_JUCE_NAMESPACE #include "../../../src/juce_appframework/audio/audio_file_formats/juce_AudioCDBurner.h" - //============================================================================== AudioCDBurner::AudioCDBurner (const int deviceIndex) : internal (0) { + internal = juce_openDiskBurnerDevice (deviceIndex); } AudioCDBurner::~AudioCDBurner() { + if (internal != 0) + juce_deleteDiskBurnerDevice (internal); } AudioCDBurner* AudioCDBurner::openDevice (const int deviceIndex) { - return 0; + AudioCDBurner* b = new AudioCDBurner (deviceIndex); + + if (b->internal == 0) + deleteAndZero (b); + + return b; } const StringArray AudioCDBurner::findAvailableDevices() { + int num = juce_findDiskBurnerDevices (0); + char** names = (char**) juce_calloc (sizeof (char*) * num); + for (int i = num; --i >= 0;) + names[i] = (char*) juce_calloc (2048); + + juce_findDiskBurnerDevices ((const char**) names); + StringArray s; + for (int i = num; --i >= 0;) + { + s.add (String::fromUTF8 ((juce::uint8*) names[i])); + juce_free (names[i]); + } + return s; } bool AudioCDBurner::isDiskPresent() const { - return false; + return juce_isDiskPresentInDevice (internal); } int AudioCDBurner::getNumAvailableAudioBlocks() const { - return 0; + return juce_getNumAvailableAudioBlocks (internal); } bool AudioCDBurner::addAudioTrack (AudioFormatReader& source, int numSamples) { + juce_BeginAudioTrack (internal); + juce_AddSamplesToAudioTrack (internal, samples, num); + juce_EndAudioTrack (internal); return false; } @@ -85,4 +119,4 @@ const String AudioCDBurner::burn (BurnProgressListener* listener, return String::empty; } -END_JUCE_NAMESPACE \ No newline at end of file +END_JUCE_NAMESPACE*/ \ No newline at end of file diff --git a/build/macosx/platform_specific_code/juce_mac_AudioCDBurner.mm b/build/macosx/platform_specific_code/juce_mac_AudioCDBurner.mm new file mode 100644 index 0000000000..9243a7e41b --- /dev/null +++ b/build/macosx/platform_specific_code/juce_mac_AudioCDBurner.mm @@ -0,0 +1,453 @@ +/* + ============================================================================== + + 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 "../../../src/juce_core/basics/juce_StandardHeader.h" + +#if JUCE_USE_CDBURNER + +#import +#import + +BEGIN_JUCE_NAMESPACE + #include "../../../src/juce_appframework/audio/audio_file_formats/juce_AudioCDBurner.h" + #include "../../../src/juce_appframework/audio/audio_sources/juce_AudioSource.h" + #include "../../../src/juce_appframework/audio/dsp/juce_AudioDataConverters.h" + #include "../../../src/juce_core/threads/juce_Thread.h" +END_JUCE_NAMESPACE + + +//============================================================================== +@interface OpenDiskDevice : NSObject +{ + DRDevice* device; + + NSMutableArray* tracks; +} + +- (OpenDiskDevice*) initWithDevice: (DRDevice*) device; +- (void) dealloc; +- (bool) isDiskPresent; +- (int) getNumAvailableAudioBlocks; +- (void) addSourceTrack: (juce::AudioSource*) source numSamples: (int) numSamples_; +- (void) burn: (juce::AudioCDBurner::BurnProgressListener*) listener errorString: (juce::String*) error + ejectAfterwards: (bool) shouldEject isFake: (bool) peformFakeBurnForTesting; +@end + +//============================================================================== +@interface AudioTrackProducer : NSObject +{ + juce::AudioSource* source; + int readPosition, lengthInFrames; +} + +- (AudioTrackProducer*) init: (int) lengthInFrames; +- (AudioTrackProducer*) initWithAudioSource: (juce::AudioSource*) source numSamples: (int) lengthInSamples; +- (void) dealloc; +- (void) setupTrackProperties: (DRTrack*) track; + +- (void) cleanupTrackAfterBurn: (DRTrack*) track; +- (BOOL) cleanupTrackAfterVerification:(DRTrack*)track; +- (uint64_t) estimateLengthOfTrack:(DRTrack*)track; +- (BOOL) prepareTrack:(DRTrack*)track forBurn:(DRBurn*)burn + toMedia:(NSDictionary*)mediaInfo; +- (BOOL) prepareTrackForVerification:(DRTrack*)track; +- (uint32_t) produceDataForTrack:(DRTrack*)track intoBuffer:(char*)buffer + length:(uint32_t)bufferLength atAddress:(uint64_t)address + blockSize:(uint32_t)blockSize ioFlags:(uint32_t*)flags; +- (uint32_t) producePreGapForTrack:(DRTrack*)track + intoBuffer:(char*)buffer length:(uint32_t)bufferLength + atAddress:(uint64_t)address blockSize:(uint32_t)blockSize + ioFlags:(uint32_t*)flags; +- (BOOL) verifyDataForTrack:(DRTrack*)track inBuffer:(const char*)buffer + length:(uint32_t)bufferLength atAddress:(uint64_t)address + blockSize:(uint32_t)blockSize ioFlags:(uint32_t*)flags; +- (uint32_t) producePreGapForTrack:(DRTrack*)track + intoBuffer:(char*)buffer length:(uint32_t)bufferLength + atAddress:(uint64_t)address blockSize:(uint32_t)blockSize + ioFlags:(uint32_t*)flags; +@end + +//============================================================================== +@implementation OpenDiskDevice + +- (OpenDiskDevice*) initWithDevice: (DRDevice*) device_ +{ + [super init]; + + device = device_; + tracks = [[NSMutableArray alloc] init]; + return self; +} + +- (void) dealloc +{ + [tracks release]; + [super dealloc]; +} + +- (bool) isDiskPresent +{ + NSLog ([[device status] description]); + return [device isValid]; +} + +- (int) getNumAvailableAudioBlocks +{ + NSLog ([[device status] description]); + return [[[[device status] objectForKey: DRDeviceMediaInfoKey] + objectForKey: DRDeviceMediaBlocksFreeKey] intValue]; +} + +- (void) addSourceTrack: (juce::AudioSource*) source_ numSamples: (int) numSamples_ +{ + AudioTrackProducer* p = [[AudioTrackProducer alloc] initWithAudioSource: source_ numSamples: numSamples_]; + DRTrack* t = [[DRTrack alloc] initWithProducer: p]; + [p setupTrackProperties: t]; + + [tracks addObject: t]; + + [t release]; + [p release]; +} + +- (void) burn: (juce::AudioCDBurner::BurnProgressListener*) listener errorString: (juce::String*) error + ejectAfterwards: (bool) shouldEject isFake: (bool) peformFakeBurnForTesting +{ + DRBurn* burn = [DRBurn burnForDevice: device]; + + if (! [device acquireExclusiveAccess]) + { + *error = "Couldn't open or write to the CD device"; + return; + } + + [device acquireMediaReservation]; + + NSMutableDictionary* d = [[burn properties] mutableCopy]; + [d setObject: [NSNumber numberWithBool: peformFakeBurnForTesting] forKey: DRBurnTestingKey]; + [d setObject: [NSNumber numberWithBool: false] forKey: DRBurnVerifyDiscKey]; + [burn setProperties: d]; + [d release]; + + [burn writeLayout: tracks]; + + for (;;) + { + juce::Thread::sleep (300); + float progress = [[[burn status] objectForKey: DRStatusPercentCompleteKey] floatValue]; + + if (listener != 0 && listener->audioCDBurnProgress (progress)) + { + [burn abort]; + *error = "User cancelled the write operation"; + break; + } + + if ([[[burn status] objectForKey: DRStatusStateKey] isEqualTo: DRStatusStateFailed]) + { + *error = "Write operation failed"; + break; + } + else if ([[[burn status] objectForKey: DRStatusStateKey] isEqualTo: DRStatusStateDone]) + { + if (shouldEject) + [device openTray]; + + break; + } + NSString* err = (NSString*) [[[burn status] objectForKey: DRErrorStatusKey] + objectForKey: DRErrorStatusErrorStringKey]; + + if ([err length] > 0) + { + *error = juce::String::fromUTF8 ((juce::uint8*) [err UTF8String]); + break; + } + } + + [device releaseMediaReservation]; + [device releaseExclusiveAccess]; +} +@end + +//============================================================================== +@implementation AudioTrackProducer + +- (AudioTrackProducer*) init: (int) lengthInFrames_ +{ + lengthInFrames = lengthInFrames_; + readPosition = 0; + return self; +} + +- (void) setupTrackProperties: (DRTrack*) track +{ + NSMutableDictionary* p = [[track properties] mutableCopy]; + [p setObject: [DRMSF msfWithFrames: lengthInFrames] forKey: DRTrackLengthKey]; + [p setObject: [NSNumber numberWithUnsignedShort: 2048] forKey: DRBlockSizeKey]; + [p setObject: [NSNumber numberWithInt: 16] forKey: DRDataFormKey]; + [p setObject: [NSNumber numberWithInt: 8] forKey: DRBlockTypeKey]; + [p setObject: [NSNumber numberWithInt: 4] forKey: DRTrackModeKey]; + [p setObject: [NSNumber numberWithInt: 0] forKey: DRSessionFormatKey]; + [track setProperties: p]; + [p release]; +} + +- (AudioTrackProducer*) initWithAudioSource: (juce::AudioSource*) source_ numSamples: (int) lengthInSamples +{ + AudioTrackProducer* s = [self init: lengthInSamples / (44100 / 75)]; + + if (s != nil) + s->source = source_; + + return s; +} + +- (void) dealloc +{ + if (source != 0) + { + source->releaseResources(); + delete source; + } + + [super dealloc]; +} + +- (void) cleanupTrackAfterBurn: (DRTrack*) track +{ +} + +- (BOOL) cleanupTrackAfterVerification:(DRTrack*)track +{ + return true; +} + +- (uint64_t) estimateLengthOfTrack:(DRTrack*)track +{ + return lengthInFrames; +} + +- (BOOL) prepareTrack:(DRTrack*)track forBurn:(DRBurn*)burn + toMedia:(NSDictionary*)mediaInfo +{ + if (source != 0) + source->prepareToPlay (44100 / 75, 44100); + + readPosition = 0; + return true; +} + +- (BOOL) prepareTrackForVerification:(DRTrack*)track +{ + if (source != 0) + source->prepareToPlay (44100 / 75, 44100); + + return true; +} + +- (uint32_t) produceDataForTrack:(DRTrack*)track intoBuffer:(char*)buffer + length:(uint32_t)bufferLength atAddress:(uint64_t)address + blockSize:(uint32_t)blockSize ioFlags:(uint32_t*)flags +{ + if (source != 0) + { + const int numSamples = juce::jmin (bufferLength / 4, (lengthInFrames * (44100 / 75)) - readPosition); + + if (numSamples > 0) + { + juce::AudioSampleBuffer tempBuffer (2, numSamples); + + juce::AudioSourceChannelInfo info; + info.buffer = &tempBuffer; + info.startSample = 0; + info.numSamples = numSamples; + + source->getNextAudioBlock (info); + + juce::AudioDataConverters::convertFloatToInt16LE (tempBuffer.getSampleData (0), + buffer, numSamples, 4); + juce::AudioDataConverters::convertFloatToInt16LE (tempBuffer.getSampleData (1), + buffer + 2, numSamples, 4); + + readPosition += numSamples; + } + + return numSamples * 4; + } + + return 0; +} + +- (uint32_t) producePreGapForTrack:(DRTrack*)track + intoBuffer:(char*)buffer length:(uint32_t)bufferLength + atAddress:(uint64_t)address blockSize:(uint32_t)blockSize + ioFlags:(uint32_t*)flags +{ + zeromem (buffer, bufferLength); + return bufferLength; +} + +- (BOOL) verifyDataForTrack:(DRTrack*)track inBuffer:(const char*)buffer + length:(uint32_t)bufferLength atAddress:(uint64_t)address + blockSize:(uint32_t)blockSize ioFlags:(uint32_t*)flags +{ + return true; +} + +@end + + +BEGIN_JUCE_NAMESPACE + +//============================================================================== +AudioCDBurner::AudioCDBurner (const int deviceIndex) + : internal (0) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + OpenDiskDevice* dev = [[OpenDiskDevice alloc] initWithDevice: [[DRDevice devices] objectAtIndex: deviceIndex]]; + + internal = (void*) dev; + [pool release]; +} + +AudioCDBurner::~AudioCDBurner() +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + OpenDiskDevice* dev = (OpenDiskDevice*) internal; + + if (dev != 0) + [dev release]; + + [pool release]; +} + +AudioCDBurner* AudioCDBurner::openDevice (const int deviceIndex) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + AudioCDBurner* b = new AudioCDBurner (deviceIndex); + + if (b->internal == 0) + deleteAndZero (b); + + [pool release]; + return b; +} + +static NSArray* findDiskBurnerDevices() +{ + NSMutableArray* results = [NSMutableArray array]; + NSArray* devs = [DRDevice devices]; + + if (devs != 0) + { + int num = [devs count]; + int i; + for (i = 0; i < num; ++i) + { + NSDictionary* dic = [[devs objectAtIndex: i] info]; + NSString* name = [dic valueForKey: DRDeviceProductNameKey]; + if (name != nil) + [results addObject: name]; + } + } + + return results; +} + +const StringArray AudioCDBurner::findAvailableDevices() +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSArray* names = findDiskBurnerDevices(); + StringArray s; + + for (int i = 0; i < [names count]; ++i) + s.add (String::fromUTF8 ((juce::uint8*) [[names objectAtIndex: i] UTF8String])); + + [pool release]; + return s; +} + +bool AudioCDBurner::isDiskPresent() const +{ + OpenDiskDevice* dev = (OpenDiskDevice*) internal; + + return dev != 0 && [dev isDiskPresent]; +} + +int AudioCDBurner::getNumAvailableAudioBlocks() const +{ + OpenDiskDevice* dev = (OpenDiskDevice*) internal; + + return [dev getNumAvailableAudioBlocks]; +} + +bool AudioCDBurner::addAudioTrack (AudioSource* source, int numSamps) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + OpenDiskDevice* dev = (OpenDiskDevice*) internal; + + if (dev != 0) + { + [dev addSourceTrack: source numSamples: numSamps]; + [pool release]; + return true; + } + + [pool release]; + return false; +} + +const String AudioCDBurner::burn (juce::AudioCDBurner::BurnProgressListener* listener, + const bool peformFakeBurnForTesting, + const bool ejectDiscAfterwards) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + juce::String error ("Couldn't open or write to the CD device"); + + OpenDiskDevice* dev = (OpenDiskDevice*) internal; + + if (dev != 0) + { + error = juce::String::empty; + [dev burn: listener + errorString: &error + ejectAfterwards: ejectDiscAfterwards + isFake: peformFakeBurnForTesting]; + } + + [pool release]; + return error; +} + +END_JUCE_NAMESPACE + +#endif diff --git a/build/macosx/platform_specific_code/juce_mac_Files.cpp b/build/macosx/platform_specific_code/juce_mac_Files.cpp index ba4d1e17da..1235988115 100644 --- a/build/macosx/platform_specific_code/juce_mac_Files.cpp +++ b/build/macosx/platform_specific_code/juce_mac_Files.cpp @@ -1,815 +1,835 @@ -/* - ============================================================================== - - 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 "../../../src/juce_core/basics/juce_StandardHeader.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -BEGIN_JUCE_NAMESPACE - - -#include "../../../src/juce_core/io/files/juce_FileInputStream.h" -#include "../../../src/juce_core/io/files/juce_FileOutputStream.h" -#include "../../../src/juce_core/io/network/juce_URL.h" -#include "../../../src/juce_core/basics/juce_SystemStats.h" -#include "../../../src/juce_core/misc/juce_PlatformUtilities.h" -#include "../../../src/juce_core/io/files/juce_NamedPipe.h" -#include "../../../src/juce_core/threads/juce_InterProcessLock.h" -#include "../../../src/juce_core/threads/juce_Thread.h" - -//============================================================================== -/* - Note that a lot of methods that you'd expect to find in this file actually - live in juce_posix_SharedCode.cpp! -*/ -#include "juce_posix_SharedCode.cpp" - - -//============================================================================== -static File executableFile; - - -//============================================================================== -void PlatformUtilities::copyToStr255 (Str255& d, const String& s) -{ - unsigned char* t = (unsigned char*) d; - t[0] = jmin (254, s.length()); - s.copyToBuffer ((char*) t + 1, 254); -} - -void PlatformUtilities::copyToStr63 (Str63& d, const String& s) -{ - unsigned char* t = (unsigned char*) d; - t[0] = jmin (62, s.length()); - s.copyToBuffer ((char*) t + 1, 62); -} - -const String PlatformUtilities::cfStringToJuceString (CFStringRef cfString) -{ - String result; - - if (cfString != 0) - { -#if JUCE_STRINGS_ARE_UNICODE - CFRange range = { 0, CFStringGetLength (cfString) }; - UniChar* const u = (UniChar*) juce_malloc (sizeof (UniChar) * (range.length + 1)); - - CFStringGetCharacters (cfString, range, u); - u[range.length] = 0; - - result = convertUTF16ToString (u); - - juce_free (u); -#else - const int len = CFStringGetLength (cfString); - char* buffer = (char*) juce_malloc (len + 1); - CFStringGetCString (cfString, buffer, len + 1, CFStringGetSystemEncoding()); - result = buffer; - juce_free (buffer); -#endif - } - - return result; -} - -CFStringRef PlatformUtilities::juceStringToCFString (const String& s) -{ -#if JUCE_STRINGS_ARE_UNICODE - const int len = s.length(); - const juce_wchar* t = (const juce_wchar*) s; - - UniChar* temp = (UniChar*) juce_malloc (sizeof (UniChar) * len + 4); - - for (int i = 0; i <= len; ++i) - temp[i] = t[i]; - - CFStringRef result = CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len); - juce_free (temp); - - return result; - -#else - return CFStringCreateWithCString (kCFAllocatorDefault, - (const char*) s, - CFStringGetSystemEncoding()); -#endif -} - -const String PlatformUtilities::convertUTF16ToString (const UniChar* utf16) -{ - String s; - - while (*utf16 != 0) - s += (juce_wchar) *utf16++; - - return s; -} - -const String PlatformUtilities::convertToPrecomposedUnicode (const String& s) -{ - UnicodeMapping map; - - map.unicodeEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault, - kUnicodeNoSubset, - kTextEncodingDefaultFormat); - - map.otherEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault, - kUnicodeCanonicalCompVariant, - kTextEncodingDefaultFormat); - - map.mappingVersion = kUnicodeUseLatestMapping; - - UnicodeToTextInfo conversionInfo = 0; - String result; - - if (CreateUnicodeToTextInfo (&map, &conversionInfo) == noErr) - { - const int len = s.length(); - - UniChar* const tempIn = (UniChar*) juce_calloc (sizeof (UniChar) * len + 4); - UniChar* const tempOut = (UniChar*) juce_calloc (sizeof (UniChar) * len + 4); - - for (int i = 0; i <= len; ++i) - tempIn[i] = s[i]; - - ByteCount bytesRead = 0; - ByteCount outputBufferSize = 0; - - if (ConvertFromUnicodeToText (conversionInfo, - len * sizeof (UniChar), tempIn, - kUnicodeDefaultDirectionMask, - 0, 0, 0, 0, - len * sizeof (UniChar), &bytesRead, - &outputBufferSize, tempOut) == noErr) - { - result.preallocateStorage (bytesRead / sizeof (UniChar) + 2); - - tchar* t = const_cast ((const tchar*) result); - - int i; - for (i = 0; i < bytesRead / sizeof (UniChar); ++i) - t[i] = (tchar) tempOut[i]; - - t[i] = 0; - } - - juce_free (tempIn); - juce_free (tempOut); - - DisposeUnicodeToTextInfo (&conversionInfo); - } - - return result; -} - -//============================================================================== -const unsigned int macTimeToUnixTimeDiff = 0x7c25be90; - -static uint64 utcDateTimeToUnixTime (const UTCDateTime& d) throw() -{ - if (d.highSeconds == 0 && d.lowSeconds == 0 && d.fraction == 0) - return 0; - - return (((((uint64) d.highSeconds) << 32) | (uint64) d.lowSeconds) * 1000) - + ((d.fraction * 1000) >> 16) - - 2082844800000ll; -} - -static void unixTimeToUtcDateTime (uint64 t, UTCDateTime& d) throw() -{ - if (t != 0) - t += 2082844800000ll; - - d.highSeconds = (t / 1000) >> 32; - d.lowSeconds = (t / 1000) & (uint64) 0xffffffff; - d.fraction = ((t % 1000) << 16) / 1000; -} - -void juce_getFileTimes (const String& fileName, - int64& modificationTime, - int64& accessTime, - int64& creationTime) throw() -{ - modificationTime = 0; - accessTime = 0; - creationTime = 0; - - FSRef fileRef; - if (PlatformUtilities::makeFSRefFromPath (&fileRef, fileName)) - { - FSRefParam info; - zerostruct (info); - - info.ref = &fileRef; - info.whichInfo = kFSCatInfoAllDates; - - FSCatalogInfo catInfo; - info.catInfo = &catInfo; - - if (PBGetCatalogInfoSync (&info) == noErr) - { - creationTime = utcDateTimeToUnixTime (catInfo.createDate); - accessTime = utcDateTimeToUnixTime (catInfo.accessDate); - modificationTime = utcDateTimeToUnixTime (catInfo.contentModDate); - } - } -} - -bool juce_setFileTimes (const String& fileName, - int64 modificationTime, - int64 accessTime, - int64 creationTime) throw() -{ - FSRef fileRef; - if (PlatformUtilities::makeFSRefFromPath (&fileRef, fileName)) - { - FSRefParam info; - zerostruct (info); - - info.ref = &fileRef; - info.whichInfo = kFSCatInfoAllDates; - - FSCatalogInfo catInfo; - info.catInfo = &catInfo; - - if (PBGetCatalogInfoSync (&info) == noErr) - { - if (creationTime != 0) - unixTimeToUtcDateTime (creationTime, catInfo.createDate); - - if (modificationTime != 0) - unixTimeToUtcDateTime (modificationTime, catInfo.contentModDate); - - if (accessTime != 0) - unixTimeToUtcDateTime (accessTime, catInfo.accessDate); - - return PBSetCatalogInfoSync (&info) == noErr; - } - } - - return false; -} - -bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw() -{ - const char* const fileNameUTF8 = fileName.toUTF8(); - - struct stat info; - const int res = stat (fileNameUTF8, &info); - - bool ok = false; - - if (res == 0) - { - info.st_mode &= 0777; // Just permissions - - if (isReadOnly) - info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); - else - // Give everybody write permission? - info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; - - ok = chmod (fileNameUTF8, info.st_mode) == 0; - } - - return ok; -} - -bool juce_copyFile (const String& src, const String& dst) throw() -{ - const File destFile (dst); - - if (! destFile.create()) - return false; - - FSRef srcRef, dstRef; - - if (! (PlatformUtilities::makeFSRefFromPath (&srcRef, src) - && PlatformUtilities::makeFSRefFromPath (&dstRef, dst))) - { - return false; - } - - int okForks = 0; - - CatPositionRec iter; - iter.initialize = 0; - HFSUniStr255 forkName; - - // can't just copy the data because this is a bloody Mac, so we need to copy each - // fork separately... - while (FSIterateForks (&srcRef, &iter, &forkName, 0, 0) == noErr) - { - SInt16 srcForkNum = 0, dstForkNum = 0; - OSErr err = FSOpenFork (&srcRef, forkName.length, forkName.unicode, fsRdPerm, &srcForkNum); - - if (err == noErr) - { - err = FSOpenFork (&dstRef, forkName.length, forkName.unicode, fsRdWrPerm, &dstForkNum); - - if (err == noErr) - { - MemoryBlock buf (32768); - SInt64 pos = 0; - - for (;;) - { - ByteCount bytesRead = 0; - err = FSReadFork (srcForkNum, fsFromStart, pos, buf.getSize(), (char*) buf, &bytesRead); - - if (bytesRead > 0) - { - err = FSWriteFork (dstForkNum, fsFromStart, pos, bytesRead, (const char*) buf, &bytesRead); - pos += bytesRead; - } - - if (err != noErr) - { - if (err == eofErr) - ++okForks; - - break; - } - } - - FSFlushFork (dstForkNum); - FSCloseFork (dstForkNum); - } - - FSCloseFork (srcForkNum); - } - } - - if (okForks > 0) // some files seem to be ok even if not all their forks get copied.. - { - // copy permissions.. - struct stat info; - if (juce_stat (src, info)) - chmod (dst.toUTF8(), info.st_mode & 0777); - - return true; - } - - return false; -} - -const StringArray juce_getFileSystemRoots() throw() -{ - StringArray s; - s.add (T("/")); - return s; -} - -//============================================================================== -static bool isFileOnDriveType (const File* const f, const char** types) throw() -{ - struct statfs buf; - - if (doStatFS (f, buf)) - { - const String type (buf.f_fstypename); - - while (*types != 0) - if (type.equalsIgnoreCase (*types++)) - return true; - } - - return false; -} - -bool File::isOnCDRomDrive() const throw() -{ - static const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", 0 }; - - return isFileOnDriveType (this, (const char**) cdTypes); -} - -bool File::isOnHardDisk() const throw() -{ - static const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", 0 }; - - return ! (isOnCDRomDrive() || isFileOnDriveType (this, (const char**) nonHDTypes)); -} - - -//============================================================================== -const File File::getSpecialLocation (const SpecialLocationType type) -{ - const char* resultPath = 0; - - switch (type) - { - case userHomeDirectory: - resultPath = getenv ("HOME"); - - if (resultPath == 0) - { - struct passwd* const pw = getpwuid (getuid()); - if (pw != 0) - resultPath = pw->pw_dir; - } - - break; - - case userDocumentsDirectory: - resultPath = "~/Documents"; - break; - - case userDesktopDirectory: - resultPath = "~/Desktop"; - break; - - case userApplicationDataDirectory: - resultPath = "~/Library"; - break; - - case commonApplicationDataDirectory: - resultPath = "/Library"; - break; - - case globalApplicationsDirectory: - resultPath = "/Applications"; - break; - - case userMusicDirectory: - resultPath = "~/Music"; - break; - - case userMoviesDirectory: - resultPath = "~/Movies"; - break; - - case tempDirectory: - { - File tmp (T("~/Library/Caches/") + executableFile.getFileNameWithoutExtension()); - - tmp.createDirectory(); - return tmp.getFullPathName(); - } - - case currentExecutableFile: - return executableFile; - - case currentApplicationFile: - { - const File parent (executableFile.getParentDirectory()); - - return parent.getFullPathName().endsWithIgnoreCase (T("Contents/MacOS")) - ? parent.getParentDirectory().getParentDirectory() - : executableFile; - } - - default: - jassertfalse // unknown type? - break; - } - - if (resultPath != 0) - return File (PlatformUtilities::convertToPrecomposedUnicode (resultPath)); - - return File::nonexistent; -} - -void juce_setCurrentExecutableFileName (const String& filename) throw() -{ - executableFile = File::getCurrentWorkingDirectory() - .getChildFile (PlatformUtilities::convertToPrecomposedUnicode (filename)); -} - -void juce_setCurrentExecutableFileNameFromBundleId (const String& bundleId) throw() -{ - CFStringRef bundleIdStringRef = PlatformUtilities::juceStringToCFString (bundleId); - CFBundleRef bundleRef = CFBundleGetBundleWithIdentifier (bundleIdStringRef); - CFRelease (bundleIdStringRef); - - if (bundleRef != 0) - { - CFURLRef exeURLRef = CFBundleCopyExecutableURL (bundleRef); - - if (exeURLRef != 0) - { - CFStringRef pathStringRef = CFURLCopyFileSystemPath (exeURLRef, kCFURLPOSIXPathStyle); - CFRelease (exeURLRef); - - if (pathStringRef != 0) - { - juce_setCurrentExecutableFileName (PlatformUtilities::cfStringToJuceString (pathStringRef)); - CFRelease (pathStringRef); - } - } - } -} - -//============================================================================== -const File File::getCurrentWorkingDirectory() throw() -{ - char buf [2048]; - getcwd (buf, sizeof(buf)); - - return File (PlatformUtilities::convertToPrecomposedUnicode (buf)); -} - -bool File::setAsCurrentWorkingDirectory() const throw() -{ - return chdir (getFullPathName().toUTF8()) == 0; -} - -//============================================================================== -struct FindFileStruct -{ - String parentDir, wildCard; - DIR* dir; - - bool getNextMatch (String& result, bool* const isDir, bool* const isHidden, int64* const fileSize, - Time* const modTime, Time* const creationTime, bool* const isReadOnly) throw() - { - const char* const wildCardUTF8 = wildCard.toUTF8(); - - for (;;) - { - struct dirent* const de = readdir (dir); - - if (de == 0) - break; - - if (fnmatch (wildCardUTF8, de->d_name, 0) == 0) - { - result = PlatformUtilities::convertToPrecomposedUnicode (String::fromUTF8 ((const uint8*) de->d_name)); - - const String path (parentDir + result); - - if (isDir != 0 || fileSize != 0) - { - struct stat info; - const bool statOk = juce_stat (path, info); - - if (isDir != 0) - *isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0)); - - if (isHidden != 0) - *isHidden = (de->d_name[0] == '.'); - - if (fileSize != 0) - *fileSize = statOk ? info.st_size : 0; - } - - if (modTime != 0 || creationTime != 0) - { - int64 m, a, c; - juce_getFileTimes (path, m, a, c); - - if (modTime != 0) - *modTime = m; - - if (creationTime != 0) - *creationTime = c; - } - - if (isReadOnly != 0) - *isReadOnly = ! juce_canWriteToFile (path); - - return true; - } - } - - return false; - } -}; - -// returns 0 on failure -void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile, - bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) throw() -{ - DIR* const d = opendir (directory.toUTF8()); - - if (d != 0) - { - FindFileStruct* const ff = new FindFileStruct(); - ff->parentDir = directory; - - if (!ff->parentDir.endsWithChar (File::separator)) - ff->parentDir += File::separator; - - ff->wildCard = wildCard; - ff->dir = d; - - if (ff->getNextMatch (firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly)) - { - return ff; - } - else - { - firstResultFile = String::empty; - isDir = false; - closedir (d); - delete ff; - } - } - - return 0; -} - -bool juce_findFileNext (void* handle, String& resultFile, - bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) throw() -{ - FindFileStruct* const ff = (FindFileStruct*) handle; - - if (ff != 0) - return ff->getNextMatch (resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); - - return false; -} - -void juce_findFileClose (void* handle) throw() -{ - FindFileStruct* const ff = (FindFileStruct*)handle; - - if (ff != 0) - { - closedir (ff->dir); - delete ff; - } -} - -//============================================================================== -bool juce_launchExecutable (const String& pathAndArguments) throw() -{ - char* const argv[4] = { "/bin/sh", "-c", (char*) (const char*) pathAndArguments, 0 }; - - const int cpid = fork(); - - if (cpid == 0) - { - // Child process - if (execve (argv[0], argv, 0) < 0) - exit (0); - } - else - { - if (cpid < 0) - return false; - } - - return true; -} - -bool juce_launchFile (const String& fileName, - const String& parameters) throw() -{ - bool ok = false; - - if (fileName.startsWithIgnoreCase (T("http:")) - || fileName.startsWithIgnoreCase (T("https:")) - || fileName.startsWithIgnoreCase (T("ftp:")) - || fileName.startsWithIgnoreCase (T("file:"))) - { - CFStringRef urlString = PlatformUtilities::juceStringToCFString (fileName); - - if (urlString != 0) - { - CFURLRef url = CFURLCreateWithString (kCFAllocatorDefault, - urlString, 0); - CFRelease (urlString); - - if (url != 0) - { - ok = (LSOpenCFURLRef (url, 0) == noErr); - CFRelease (url); - } - } - } - else - { - FSRef ref; - if (PlatformUtilities::makeFSRefFromPath (&ref, fileName)) - { - if (juce_isDirectory (fileName) && parameters.isNotEmpty()) - { - // if we're launching a bundled app with a document.. - StringArray docs; - docs.addTokens (parameters, true); - FSRef* docRefs = new FSRef [docs.size()]; - - for (int i = 0; i < docs.size(); ++i) - PlatformUtilities::makeFSRefFromPath (docRefs + i, docs[i]); - - LSLaunchFSRefSpec ors; - ors.appRef = &ref; - ors.numDocs = docs.size(); - ors.itemRefs = docRefs; - ors.passThruParams = 0; - ors.launchFlags = kLSLaunchDefaults; - ors.asyncRefCon = 0; - - FSRef actual; - ok = (LSOpenFromRefSpec (&ors, &actual) == noErr); - - delete docRefs; - } - else - { - if (parameters.isNotEmpty()) - ok = juce_launchExecutable (T("\"") + fileName + T("\" ") + parameters); - else - ok = (LSOpenFSRef (&ref, 0) == noErr); - } - } - } - - return ok; -} - -//============================================================================== -bool PlatformUtilities::makeFSSpecFromPath (FSSpec* fs, const String& path) -{ - FSRef ref; - - return makeFSRefFromPath (&ref, path) - && FSGetCatalogInfo (&ref, kFSCatInfoNone, 0, 0, fs, 0) == noErr; -} - -bool PlatformUtilities::makeFSRefFromPath (FSRef* destFSRef, const String& path) -{ - return FSPathMakeRef ((const UInt8*) path.toUTF8(), destFSRef, 0) == noErr; -} - -const String PlatformUtilities::makePathFromFSRef (FSRef* file) -{ - uint8 path [2048]; - zeromem (path, sizeof (path)); - - String result; - - if (FSRefMakePath (file, (UInt8*) path, sizeof (path) - 1) == noErr) - result = String::fromUTF8 (path); - - return PlatformUtilities::convertToPrecomposedUnicode (result); -} - -//============================================================================== -OSType PlatformUtilities::getTypeOfFile (const String& filename) -{ - FSRef fs; - if (makeFSRefFromPath (&fs, filename)) - { - LSItemInfoRecord info; - - if (LSCopyItemInfoForRef (&fs, kLSRequestTypeCreator, &info) == noErr) - return info.filetype; - } - - return 0; -} - -bool PlatformUtilities::isBundle (const String& filename) -{ - FSRef fs; - if (makeFSRefFromPath (&fs, filename)) - { - LSItemInfoRecord info; - - if (LSCopyItemInfoForRef (&fs, kLSItemInfoIsPackage, &info) == noErr) - return (info.flags & kLSItemInfoIsPackage) != 0; - } - - return false; -} - - -END_JUCE_NAMESPACE +/* + ============================================================================== + + 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 "../../../src/juce_core/basics/juce_StandardHeader.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BEGIN_JUCE_NAMESPACE + + +#include "../../../src/juce_core/io/files/juce_FileInputStream.h" +#include "../../../src/juce_core/io/files/juce_FileOutputStream.h" +#include "../../../src/juce_core/io/network/juce_URL.h" +#include "../../../src/juce_core/basics/juce_SystemStats.h" +#include "../../../src/juce_core/misc/juce_PlatformUtilities.h" +#include "../../../src/juce_core/io/files/juce_NamedPipe.h" +#include "../../../src/juce_core/threads/juce_InterProcessLock.h" +#include "../../../src/juce_core/threads/juce_Thread.h" + +//============================================================================== +/* + Note that a lot of methods that you'd expect to find in this file actually + live in juce_posix_SharedCode.cpp! +*/ +#include "juce_posix_SharedCode.cpp" + + +//============================================================================== +static File executableFile; + + +//============================================================================== +void PlatformUtilities::copyToStr255 (Str255& d, const String& s) +{ + unsigned char* t = (unsigned char*) d; + t[0] = jmin (254, s.length()); + s.copyToBuffer ((char*) t + 1, 254); +} + +void PlatformUtilities::copyToStr63 (Str63& d, const String& s) +{ + unsigned char* t = (unsigned char*) d; + t[0] = jmin (62, s.length()); + s.copyToBuffer ((char*) t + 1, 62); +} + +const String PlatformUtilities::cfStringToJuceString (CFStringRef cfString) +{ + String result; + + if (cfString != 0) + { +#if JUCE_STRINGS_ARE_UNICODE + CFRange range = { 0, CFStringGetLength (cfString) }; + UniChar* const u = (UniChar*) juce_malloc (sizeof (UniChar) * (range.length + 1)); + + CFStringGetCharacters (cfString, range, u); + u[range.length] = 0; + + result = convertUTF16ToString (u); + + juce_free (u); +#else + const int len = CFStringGetLength (cfString); + char* buffer = (char*) juce_malloc (len + 1); + CFStringGetCString (cfString, buffer, len + 1, CFStringGetSystemEncoding()); + result = buffer; + juce_free (buffer); +#endif + } + + return result; +} + +CFStringRef PlatformUtilities::juceStringToCFString (const String& s) +{ +#if JUCE_STRINGS_ARE_UNICODE + const int len = s.length(); + const juce_wchar* t = (const juce_wchar*) s; + + UniChar* temp = (UniChar*) juce_malloc (sizeof (UniChar) * len + 4); + + for (int i = 0; i <= len; ++i) + temp[i] = t[i]; + + CFStringRef result = CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len); + juce_free (temp); + + return result; + +#else + return CFStringCreateWithCString (kCFAllocatorDefault, + (const char*) s, + CFStringGetSystemEncoding()); +#endif +} + +const String PlatformUtilities::convertUTF16ToString (const UniChar* utf16) +{ + String s; + + while (*utf16 != 0) + s += (juce_wchar) *utf16++; + + return s; +} + +const String PlatformUtilities::convertToPrecomposedUnicode (const String& s) +{ + UnicodeMapping map; + + map.unicodeEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault, + kUnicodeNoSubset, + kTextEncodingDefaultFormat); + + map.otherEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault, + kUnicodeCanonicalCompVariant, + kTextEncodingDefaultFormat); + + map.mappingVersion = kUnicodeUseLatestMapping; + + UnicodeToTextInfo conversionInfo = 0; + String result; + + if (CreateUnicodeToTextInfo (&map, &conversionInfo) == noErr) + { + const int len = s.length(); + + UniChar* const tempIn = (UniChar*) juce_calloc (sizeof (UniChar) * len + 4); + UniChar* const tempOut = (UniChar*) juce_calloc (sizeof (UniChar) * len + 4); + + for (int i = 0; i <= len; ++i) + tempIn[i] = s[i]; + + ByteCount bytesRead = 0; + ByteCount outputBufferSize = 0; + + if (ConvertFromUnicodeToText (conversionInfo, + len * sizeof (UniChar), tempIn, + kUnicodeDefaultDirectionMask, + 0, 0, 0, 0, + len * sizeof (UniChar), &bytesRead, + &outputBufferSize, tempOut) == noErr) + { + result.preallocateStorage (bytesRead / sizeof (UniChar) + 2); + + tchar* t = const_cast ((const tchar*) result); + + int i; + for (i = 0; i < bytesRead / sizeof (UniChar); ++i) + t[i] = (tchar) tempOut[i]; + + t[i] = 0; + } + + juce_free (tempIn); + juce_free (tempOut); + + DisposeUnicodeToTextInfo (&conversionInfo); + } + + return result; +} + +//============================================================================== +const unsigned int macTimeToUnixTimeDiff = 0x7c25be90; + +static uint64 utcDateTimeToUnixTime (const UTCDateTime& d) throw() +{ + if (d.highSeconds == 0 && d.lowSeconds == 0 && d.fraction == 0) + return 0; + + return (((((uint64) d.highSeconds) << 32) | (uint64) d.lowSeconds) * 1000) + + ((d.fraction * 1000) >> 16) + - 2082844800000ll; +} + +static void unixTimeToUtcDateTime (uint64 t, UTCDateTime& d) throw() +{ + if (t != 0) + t += 2082844800000ll; + + d.highSeconds = (t / 1000) >> 32; + d.lowSeconds = (t / 1000) & (uint64) 0xffffffff; + d.fraction = ((t % 1000) << 16) / 1000; +} + +void juce_getFileTimes (const String& fileName, + int64& modificationTime, + int64& accessTime, + int64& creationTime) throw() +{ + modificationTime = 0; + accessTime = 0; + creationTime = 0; + + FSRef fileRef; + if (PlatformUtilities::makeFSRefFromPath (&fileRef, fileName)) + { + FSRefParam info; + zerostruct (info); + + info.ref = &fileRef; + info.whichInfo = kFSCatInfoAllDates; + + FSCatalogInfo catInfo; + info.catInfo = &catInfo; + + if (PBGetCatalogInfoSync (&info) == noErr) + { + creationTime = utcDateTimeToUnixTime (catInfo.createDate); + accessTime = utcDateTimeToUnixTime (catInfo.accessDate); + modificationTime = utcDateTimeToUnixTime (catInfo.contentModDate); + } + } +} + +bool juce_setFileTimes (const String& fileName, + int64 modificationTime, + int64 accessTime, + int64 creationTime) throw() +{ + FSRef fileRef; + if (PlatformUtilities::makeFSRefFromPath (&fileRef, fileName)) + { + FSRefParam info; + zerostruct (info); + + info.ref = &fileRef; + info.whichInfo = kFSCatInfoAllDates; + + FSCatalogInfo catInfo; + info.catInfo = &catInfo; + + if (PBGetCatalogInfoSync (&info) == noErr) + { + if (creationTime != 0) + unixTimeToUtcDateTime (creationTime, catInfo.createDate); + + if (modificationTime != 0) + unixTimeToUtcDateTime (modificationTime, catInfo.contentModDate); + + if (accessTime != 0) + unixTimeToUtcDateTime (accessTime, catInfo.accessDate); + + return PBSetCatalogInfoSync (&info) == noErr; + } + } + + return false; +} + +bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw() +{ + const char* const fileNameUTF8 = fileName.toUTF8(); + + struct stat info; + const int res = stat (fileNameUTF8, &info); + + bool ok = false; + + if (res == 0) + { + info.st_mode &= 0777; // Just permissions + + if (isReadOnly) + info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + else + // Give everybody write permission? + info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + + ok = chmod (fileNameUTF8, info.st_mode) == 0; + } + + return ok; +} + +bool juce_copyFile (const String& src, const String& dst) throw() +{ + const File destFile (dst); + + if (! destFile.create()) + return false; + + FSRef srcRef, dstRef; + + if (! (PlatformUtilities::makeFSRefFromPath (&srcRef, src) + && PlatformUtilities::makeFSRefFromPath (&dstRef, dst))) + { + return false; + } + + int okForks = 0; + + CatPositionRec iter; + iter.initialize = 0; + HFSUniStr255 forkName; + + // can't just copy the data because this is a bloody Mac, so we need to copy each + // fork separately... + while (FSIterateForks (&srcRef, &iter, &forkName, 0, 0) == noErr) + { + SInt16 srcForkNum = 0, dstForkNum = 0; + OSErr err = FSOpenFork (&srcRef, forkName.length, forkName.unicode, fsRdPerm, &srcForkNum); + + if (err == noErr) + { + err = FSOpenFork (&dstRef, forkName.length, forkName.unicode, fsRdWrPerm, &dstForkNum); + + if (err == noErr) + { + MemoryBlock buf (32768); + SInt64 pos = 0; + + for (;;) + { + ByteCount bytesRead = 0; + err = FSReadFork (srcForkNum, fsFromStart, pos, buf.getSize(), (char*) buf, &bytesRead); + + if (bytesRead > 0) + { + err = FSWriteFork (dstForkNum, fsFromStart, pos, bytesRead, (const char*) buf, &bytesRead); + pos += bytesRead; + } + + if (err != noErr) + { + if (err == eofErr) + ++okForks; + + break; + } + } + + FSFlushFork (dstForkNum); + FSCloseFork (dstForkNum); + } + + FSCloseFork (srcForkNum); + } + } + + if (okForks > 0) // some files seem to be ok even if not all their forks get copied.. + { + // copy permissions.. + struct stat info; + if (juce_stat (src, info)) + chmod (dst.toUTF8(), info.st_mode & 0777); + + return true; + } + + return false; +} + +const StringArray juce_getFileSystemRoots() throw() +{ + StringArray s; + s.add (T("/")); + return s; +} + +//============================================================================== +static bool isFileOnDriveType (const File* const f, const char** types) throw() +{ + struct statfs buf; + + if (doStatFS (f, buf)) + { + const String type (buf.f_fstypename); + + while (*types != 0) + if (type.equalsIgnoreCase (*types++)) + return true; + } + + return false; +} + +bool File::isOnCDRomDrive() const throw() +{ + static const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", 0 }; + + return isFileOnDriveType (this, (const char**) cdTypes); +} + +bool File::isOnHardDisk() const throw() +{ + static const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", 0 }; + + return ! (isOnCDRomDrive() || isFileOnDriveType (this, (const char**) nonHDTypes)); +} + +static bool juce_isHiddenFile (const String& path) throw() +{ + FSRef ref; + if (! PlatformUtilities::makeFSRefFromPath (&ref, path)) + return false; + + FSCatalogInfo info; + FSGetCatalogInfo (&ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &info, 0, 0, 0); + + if ((info.nodeFlags & kFSNodeIsDirectoryBit) != 0) + return (((FolderInfo*) &info.finderInfo)->finderFlags & kIsInvisible) != 0; + + return (((FileInfo*) &info.finderInfo)->finderFlags & kIsInvisible) != 0; +} + +bool File::isHidden() const throw() +{ + return juce_isHiddenFile (getFullPathName()); +} + +//============================================================================== +const File File::getSpecialLocation (const SpecialLocationType type) +{ + const char* resultPath = 0; + + switch (type) + { + case userHomeDirectory: + resultPath = getenv ("HOME"); + + if (resultPath == 0) + { + struct passwd* const pw = getpwuid (getuid()); + if (pw != 0) + resultPath = pw->pw_dir; + } + + break; + + case userDocumentsDirectory: + resultPath = "~/Documents"; + break; + + case userDesktopDirectory: + resultPath = "~/Desktop"; + break; + + case userApplicationDataDirectory: + resultPath = "~/Library"; + break; + + case commonApplicationDataDirectory: + resultPath = "/Library"; + break; + + case globalApplicationsDirectory: + resultPath = "/Applications"; + break; + + case userMusicDirectory: + resultPath = "~/Music"; + break; + + case userMoviesDirectory: + resultPath = "~/Movies"; + break; + + case tempDirectory: + { + File tmp (T("~/Library/Caches/") + executableFile.getFileNameWithoutExtension()); + + tmp.createDirectory(); + return tmp.getFullPathName(); + } + + case currentExecutableFile: + return executableFile; + + case currentApplicationFile: + { + const File parent (executableFile.getParentDirectory()); + + return parent.getFullPathName().endsWithIgnoreCase (T("Contents/MacOS")) + ? parent.getParentDirectory().getParentDirectory() + : executableFile; + } + + default: + jassertfalse // unknown type? + break; + } + + if (resultPath != 0) + return File (PlatformUtilities::convertToPrecomposedUnicode (resultPath)); + + return File::nonexistent; +} + +void juce_setCurrentExecutableFileName (const String& filename) throw() +{ + executableFile = File::getCurrentWorkingDirectory() + .getChildFile (PlatformUtilities::convertToPrecomposedUnicode (filename)); +} + +void juce_setCurrentExecutableFileNameFromBundleId (const String& bundleId) throw() +{ + CFStringRef bundleIdStringRef = PlatformUtilities::juceStringToCFString (bundleId); + CFBundleRef bundleRef = CFBundleGetBundleWithIdentifier (bundleIdStringRef); + CFRelease (bundleIdStringRef); + + if (bundleRef != 0) + { + CFURLRef exeURLRef = CFBundleCopyExecutableURL (bundleRef); + + if (exeURLRef != 0) + { + CFStringRef pathStringRef = CFURLCopyFileSystemPath (exeURLRef, kCFURLPOSIXPathStyle); + CFRelease (exeURLRef); + + if (pathStringRef != 0) + { + juce_setCurrentExecutableFileName (PlatformUtilities::cfStringToJuceString (pathStringRef)); + CFRelease (pathStringRef); + } + } + } +} + +//============================================================================== +const File File::getCurrentWorkingDirectory() throw() +{ + char buf [2048]; + getcwd (buf, sizeof(buf)); + + return File (PlatformUtilities::convertToPrecomposedUnicode (buf)); +} + +bool File::setAsCurrentWorkingDirectory() const throw() +{ + return chdir (getFullPathName().toUTF8()) == 0; +} + +//============================================================================== +struct FindFileStruct +{ + String parentDir, wildCard; + DIR* dir; + + bool getNextMatch (String& result, bool* const isDir, bool* const isHidden, int64* const fileSize, + Time* const modTime, Time* const creationTime, bool* const isReadOnly) throw() + { + const char* const wildCardUTF8 = wildCard.toUTF8(); + + for (;;) + { + struct dirent* const de = readdir (dir); + + if (de == 0) + break; + + if (fnmatch (wildCardUTF8, de->d_name, 0) == 0) + { + result = PlatformUtilities::convertToPrecomposedUnicode (String::fromUTF8 ((const uint8*) de->d_name)); + + const String path (parentDir + result); + + if (isDir != 0 || fileSize != 0) + { + struct stat info; + const bool statOk = juce_stat (path, info); + + if (isDir != 0) + *isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0)); + + if (isHidden != 0) + *isHidden = (de->d_name[0] == '.') + || juce_isHiddenFile (path); + + if (fileSize != 0) + *fileSize = statOk ? info.st_size : 0; + } + + if (modTime != 0 || creationTime != 0) + { + int64 m, a, c; + juce_getFileTimes (path, m, a, c); + + if (modTime != 0) + *modTime = m; + + if (creationTime != 0) + *creationTime = c; + } + + if (isReadOnly != 0) + *isReadOnly = ! juce_canWriteToFile (path); + + return true; + } + } + + return false; + } +}; + +// returns 0 on failure +void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile, + bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) throw() +{ + DIR* const d = opendir (directory.toUTF8()); + + if (d != 0) + { + FindFileStruct* const ff = new FindFileStruct(); + ff->parentDir = directory; + + if (!ff->parentDir.endsWithChar (File::separator)) + ff->parentDir += File::separator; + + ff->wildCard = wildCard; + ff->dir = d; + + if (ff->getNextMatch (firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly)) + { + return ff; + } + else + { + firstResultFile = String::empty; + isDir = false; + closedir (d); + delete ff; + } + } + + return 0; +} + +bool juce_findFileNext (void* handle, String& resultFile, + bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) throw() +{ + FindFileStruct* const ff = (FindFileStruct*) handle; + + if (ff != 0) + return ff->getNextMatch (resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); + + return false; +} + +void juce_findFileClose (void* handle) throw() +{ + FindFileStruct* const ff = (FindFileStruct*)handle; + + if (ff != 0) + { + closedir (ff->dir); + delete ff; + } +} + +//============================================================================== +bool juce_launchExecutable (const String& pathAndArguments) throw() +{ + char* const argv[4] = { "/bin/sh", "-c", (char*) (const char*) pathAndArguments, 0 }; + + const int cpid = fork(); + + if (cpid == 0) + { + // Child process + if (execve (argv[0], argv, 0) < 0) + exit (0); + } + else + { + if (cpid < 0) + return false; + } + + return true; +} + +bool juce_launchFile (const String& fileName, + const String& parameters) throw() +{ + bool ok = false; + + if (fileName.startsWithIgnoreCase (T("http:")) + || fileName.startsWithIgnoreCase (T("https:")) + || fileName.startsWithIgnoreCase (T("ftp:")) + || fileName.startsWithIgnoreCase (T("file:"))) + { + CFStringRef urlString = PlatformUtilities::juceStringToCFString (fileName); + + if (urlString != 0) + { + CFURLRef url = CFURLCreateWithString (kCFAllocatorDefault, + urlString, 0); + CFRelease (urlString); + + if (url != 0) + { + ok = (LSOpenCFURLRef (url, 0) == noErr); + CFRelease (url); + } + } + } + else + { + FSRef ref; + if (PlatformUtilities::makeFSRefFromPath (&ref, fileName)) + { + if (juce_isDirectory (fileName) && parameters.isNotEmpty()) + { + // if we're launching a bundled app with a document.. + StringArray docs; + docs.addTokens (parameters, true); + FSRef* docRefs = new FSRef [docs.size()]; + + for (int i = 0; i < docs.size(); ++i) + PlatformUtilities::makeFSRefFromPath (docRefs + i, docs[i]); + + LSLaunchFSRefSpec ors; + ors.appRef = &ref; + ors.numDocs = docs.size(); + ors.itemRefs = docRefs; + ors.passThruParams = 0; + ors.launchFlags = kLSLaunchDefaults; + ors.asyncRefCon = 0; + + FSRef actual; + ok = (LSOpenFromRefSpec (&ors, &actual) == noErr); + + delete docRefs; + } + else + { + if (parameters.isNotEmpty()) + ok = juce_launchExecutable (T("\"") + fileName + T("\" ") + parameters); + else + ok = (LSOpenFSRef (&ref, 0) == noErr); + } + } + } + + return ok; +} + +//============================================================================== +bool PlatformUtilities::makeFSSpecFromPath (FSSpec* fs, const String& path) +{ + FSRef ref; + + return makeFSRefFromPath (&ref, path) + && FSGetCatalogInfo (&ref, kFSCatInfoNone, 0, 0, fs, 0) == noErr; +} + +bool PlatformUtilities::makeFSRefFromPath (FSRef* destFSRef, const String& path) +{ + return FSPathMakeRef ((const UInt8*) path.toUTF8(), destFSRef, 0) == noErr; +} + +const String PlatformUtilities::makePathFromFSRef (FSRef* file) +{ + uint8 path [2048]; + zeromem (path, sizeof (path)); + + String result; + + if (FSRefMakePath (file, (UInt8*) path, sizeof (path) - 1) == noErr) + result = String::fromUTF8 (path); + + return PlatformUtilities::convertToPrecomposedUnicode (result); +} + +//============================================================================== +OSType PlatformUtilities::getTypeOfFile (const String& filename) +{ + FSRef fs; + if (makeFSRefFromPath (&fs, filename)) + { + LSItemInfoRecord info; + + if (LSCopyItemInfoForRef (&fs, kLSRequestTypeCreator, &info) == noErr) + return info.filetype; + } + + return 0; +} + +bool PlatformUtilities::isBundle (const String& filename) +{ + FSRef fs; + if (makeFSRefFromPath (&fs, filename)) + { + LSItemInfoRecord info; + + if (LSCopyItemInfoForRef (&fs, kLSItemInfoIsPackage, &info) == noErr) + return (info.flags & kLSItemInfoIsPackage) != 0; + } + + return false; +} + + +END_JUCE_NAMESPACE diff --git a/build/macosx/platform_specific_code/juce_mac_HTTPStream.h b/build/macosx/platform_specific_code/juce_mac_HTTPStream.h index bacae504ea..29837bfd5b 100644 --- a/build/macosx/platform_specific_code/juce_mac_HTTPStream.h +++ b/build/macosx/platform_specific_code/juce_mac_HTTPStream.h @@ -1,393 +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. - - ============================================================================== -*/ - -#ifndef __JUCE_MAC_HTTPSTREAM_JUCEHEADER__ -#define __JUCE_MAC_HTTPSTREAM_JUCEHEADER__ - -// (This file gets included by the mac + linux networking code) - - -//============================================================================== -/** A HTTP input stream that uses sockets. -*/ -class JUCE_HTTPSocketStream -{ -public: - //============================================================================== - JUCE_HTTPSocketStream() - : statusCode (0), - readPosition (0), - socketHandle (-1), - levelsOfRedirection (0), - timeoutSeconds (15) - { - } - - ~JUCE_HTTPSocketStream() - { - closeSocket(); - } - - //============================================================================== - bool open (const String& url, - const String& headers, - const MemoryBlock& postData, - const bool isPost) - { - closeSocket(); - - String hostName, hostPath; - int hostPort; - - if (! decomposeURL (url, hostName, hostPath, hostPort)) - return false; - - struct hostent* const host - = gethostbyname ((const char*) hostName.toUTF8()); - - if (host == 0) - return false; - - struct sockaddr_in address; - zerostruct (address); - memcpy ((void*) &address.sin_addr, (const void*) host->h_addr, host->h_length); - address.sin_family = host->h_addrtype; - address.sin_port = htons (hostPort); - - socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0); - - if (socketHandle == -1) - return false; - - int receiveBufferSize = 16384; - setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize)); - setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0); - - if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1) - { - closeSocket(); - return false; - } - - String proxyURL (getenv ("http_proxy")); - - if (! proxyURL.startsWithIgnoreCase (T("http://"))) - proxyURL = String::empty; - - const MemoryBlock requestHeader (createRequestHeader (hostName, hostPath, - proxyURL, url, - hostPort, - headers, postData, - isPost)); - - if (send (socketHandle, requestHeader.getData(), requestHeader.getSize(), 0) - != requestHeader.getSize()) - { - closeSocket(); - return false; - } - - const String responseHeader (readResponse()); - - if (responseHeader.isNotEmpty()) - { - //DBG (responseHeader); - - StringArray lines; - lines.addLines (responseHeader); - - statusCode = responseHeader.fromFirstOccurrenceOf (T(" "), false, false) - .substring (0, 3).getIntValue(); - - - //int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue(); - //bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked"); - - String location (findHeaderItem (lines, T("Location:"))); - - if (statusCode >= 300 && statusCode < 400 - && location.isNotEmpty()) - { - if (! location.startsWithIgnoreCase (T("http://"))) - location = T("http://") + location; - - if (levelsOfRedirection++ < 3) - return open (location, headers, postData, isPost); - } - else - { - levelsOfRedirection = 0; - return true; - } - } - - closeSocket(); - return false; - } - - //============================================================================== - int read (void* buffer, int bytesToRead) - { - fd_set readbits; - FD_ZERO (&readbits); - FD_SET (socketHandle, &readbits); - - struct timeval tv; - tv.tv_sec = timeoutSeconds; - tv.tv_usec = 0; - - if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) - return 0; // (timeout) - - const int bytesRead = jmax (0, recv (socketHandle, buffer, bytesToRead, MSG_WAITALL)); - readPosition += bytesRead; - return bytesRead; - } - - //============================================================================== - int statusCode, readPosition; - - //============================================================================== - juce_UseDebuggingNewOperator - -private: - int socketHandle, levelsOfRedirection; - const int timeoutSeconds; - - //============================================================================== - void closeSocket() - { - if (socketHandle >= 0) - close (socketHandle); - - socketHandle = -1; - } - - const MemoryBlock createRequestHeader (const String& hostName, - const String& hostPath, - const String& proxyURL, - const String& originalURL, - const int hostPort, - const String& headers, - const MemoryBlock& postData, - const bool isPost) - { - String header (isPost ? "POST " : "GET "); - - if (proxyURL.isEmpty()) - { - header << hostPath << " HTTP/1.1\r\nHost: " - << hostName << ':' << hostPort; - } - else - { - String proxyName, proxyPath; - int proxyPort; - - if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort)) - return MemoryBlock(); - - header << originalURL << " HTTP/1.1\r\nHost: " - << proxyName << ':' << proxyPort; - - /* xxx needs finishing - const char* proxyAuth = getenv ("http_proxy_auth"); - if (proxyAuth != 0) - header << T("\r\nProxy-Authorization: ") << Base64Encode (proxyAuth); - */ - } - - header << "\r\nUser-Agent: JUCE/" - << JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION - << "\r\nConnection: Close\r\n" - << headers << "\r\n"; - - MemoryBlock mb; - mb.append (header.toUTF8(), (int) strlen (header.toUTF8())); - mb.append (postData.getData(), postData.getSize()); - - return mb; - } - - const String readResponse() - { - int bytesRead = 0, numConsecutiveLFs = 0; - MemoryBlock buffer (1024, true); - - while (numConsecutiveLFs < 2 && bytesRead < 32768) - { - fd_set readbits; - FD_ZERO (&readbits); - FD_SET (socketHandle, &readbits); - - struct timeval tv; - tv.tv_sec = timeoutSeconds; - tv.tv_usec = 0; - - if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) - return String::empty; // (timeout) - - buffer.ensureSize (bytesRead + 8, true); - char* const dest = (char*) buffer.getData() + bytesRead; - - if (recv (socketHandle, dest, 1, 0) == -1) - return String::empty; - - const char lastByte = *dest; - ++bytesRead; - - if (lastByte == '\n') - ++numConsecutiveLFs; - else if (lastByte != '\r') - numConsecutiveLFs = 0; - } - - const String header (String::fromUTF8 ((const uint8*) buffer.getData())); - - if (header.startsWithIgnoreCase (T("HTTP/"))) - return header.trimEnd(); - - return String::empty; - } - - //============================================================================== - static bool decomposeURL (const String& url, - String& host, String& path, int& port) - { - if (! url.startsWithIgnoreCase (T("http://"))) - return false; - - const int nextSlash = url.indexOfChar (7, '/'); - int nextColon = url.indexOfChar (7, ':'); - if (nextColon > nextSlash && nextSlash > 0) - nextColon = -1; - - if (nextColon >= 0) - { - host = url.substring (7, nextColon); - - if (nextSlash >= 0) - port = url.substring (nextColon + 1, nextSlash).getIntValue(); - else - port = url.substring (nextColon + 1).getIntValue(); - } - else - { - port = 80; - - if (nextSlash >= 0) - host = url.substring (7, nextSlash); - else - host = url.substring (7); - } - - if (nextSlash >= 0) - path = url.substring (nextSlash); - else - path = T("/"); - - return true; - } - - //============================================================================== - static const String findHeaderItem (const StringArray& lines, const String& itemName) - { - for (int i = 0; i < lines.size(); ++i) - if (lines[i].startsWithIgnoreCase (itemName)) - return lines[i].substring (itemName.length()).trim(); - - return String::empty; - } -}; - - -//============================================================================== -bool juce_isOnLine() -{ - return true; -} - -void* juce_openInternetFile (const String& url, - const String& headers, - const MemoryBlock& postData, - const bool isPost, - URL::OpenStreamProgressCallback* callback, - void* callbackContext) -{ - JUCE_HTTPSocketStream* const s = new JUCE_HTTPSocketStream(); - - if (s->open (url, headers, postData, isPost)) - return s; - - delete s; - return 0; -} - -void juce_closeInternetFile (void* handle) -{ - JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; - - if (s != 0) - delete s; -} - -int juce_getStatusCodeFor (void* handle) -{ - JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; - - if (s != 0) - return s->statusCode; - - return 0; -} - -int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) -{ - JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; - - if (s != 0) - return s->read (buffer, bytesToRead); - - return 0; -} - -int juce_seekInInternetFile (void* handle, int newPosition) -{ - JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; - - if (s != 0) - return s->readPosition; - - return 0; -} - - -#endif // __JUCE_MAC_HTTPSTREAM_JUCEHEADER__ +/* + ============================================================================== + + 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_MAC_HTTPSTREAM_JUCEHEADER__ +#define __JUCE_MAC_HTTPSTREAM_JUCEHEADER__ + +// (This file gets included by the mac + linux networking code) + +//============================================================================== +/** A HTTP input stream that uses sockets. +*/ +class JUCE_HTTPSocketStream +{ +public: + //============================================================================== + JUCE_HTTPSocketStream() + : statusCode (0), + readPosition (0), + socketHandle (-1), + levelsOfRedirection (0), + timeoutSeconds (15) + { + } + + ~JUCE_HTTPSocketStream() + { + closeSocket(); + } + + //============================================================================== + bool open (const String& url, + const String& headers, + const MemoryBlock& postData, + const bool isPost, + URL::OpenStreamProgressCallback* callback, + void* callbackContext) + { + closeSocket(); + + String hostName, hostPath; + int hostPort; + + if (! decomposeURL (url, hostName, hostPath, hostPort)) + return false; + + struct hostent* const host + = gethostbyname ((const char*) hostName.toUTF8()); + + if (host == 0) + return false; + + struct sockaddr_in address; + zerostruct (address); + memcpy ((void*) &address.sin_addr, (const void*) host->h_addr, host->h_length); + address.sin_family = host->h_addrtype; + address.sin_port = htons (hostPort); + + socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0); + + if (socketHandle == -1) + return false; + + int receiveBufferSize = 16384; + setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize)); + setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0); + +#if JUCE_MAC + setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0); +#endif + + if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1) + { + closeSocket(); + return false; + } + + String proxyURL (getenv ("http_proxy")); + + if (! proxyURL.startsWithIgnoreCase (T("http://"))) + proxyURL = String::empty; + + const MemoryBlock requestHeader (createRequestHeader (hostName, hostPath, + proxyURL, url, + hostPort, + headers, postData, + isPost)); + + int totalHeaderSent = 0; + + while (totalHeaderSent < requestHeader.getSize()) + { + const int numToSend = jmin (1024, requestHeader.getSize() - totalHeaderSent); + + if (send (socketHandle, + ((const char*) requestHeader.getData()) + totalHeaderSent, + numToSend, 0) + != numToSend) + { + closeSocket(); + return false; + } + + totalHeaderSent += numToSend; + + if (callback != 0 && ! callback (callbackContext, totalHeaderSent, requestHeader.getSize())) + { + closeSocket(); + return false; + } + } + + const String responseHeader (readResponse()); + + if (responseHeader.isNotEmpty()) + { + //DBG (responseHeader); + + StringArray lines; + lines.addLines (responseHeader); + + statusCode = responseHeader.fromFirstOccurrenceOf (T(" "), false, false) + .substring (0, 3).getIntValue(); + + + //int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue(); + //bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked"); + + String location (findHeaderItem (lines, T("Location:"))); + + if (statusCode >= 300 && statusCode < 400 + && location.isNotEmpty()) + { + if (! location.startsWithIgnoreCase (T("http://"))) + location = T("http://") + location; + + if (levelsOfRedirection++ < 3) + return open (location, headers, postData, isPost, callback, callbackContext); + } + else + { + levelsOfRedirection = 0; + return true; + } + } + + closeSocket(); + return false; + } + + //============================================================================== + int read (void* buffer, int bytesToRead) + { + fd_set readbits; + FD_ZERO (&readbits); + FD_SET (socketHandle, &readbits); + + struct timeval tv; + tv.tv_sec = timeoutSeconds; + tv.tv_usec = 0; + + if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) + return 0; // (timeout) + + const int bytesRead = jmax (0, recv (socketHandle, buffer, bytesToRead, MSG_WAITALL)); + readPosition += bytesRead; + return bytesRead; + } + + //============================================================================== + int statusCode, readPosition; + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + int socketHandle, levelsOfRedirection; + const int timeoutSeconds; + + //============================================================================== + void closeSocket() + { + if (socketHandle >= 0) + close (socketHandle); + + socketHandle = -1; + } + + const MemoryBlock createRequestHeader (const String& hostName, + const String& hostPath, + const String& proxyURL, + const String& originalURL, + const int hostPort, + const String& headers, + const MemoryBlock& postData, + const bool isPost) + { + String header (isPost ? "POST " : "GET "); + + if (proxyURL.isEmpty()) + { + header << hostPath << " HTTP/1.0\r\nHost: " + << hostName << ':' << hostPort; + } + else + { + String proxyName, proxyPath; + int proxyPort; + + if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort)) + return MemoryBlock(); + + header << originalURL << " HTTP/1.0\r\nHost: " + << proxyName << ':' << proxyPort; + + /* xxx needs finishing + const char* proxyAuth = getenv ("http_proxy_auth"); + if (proxyAuth != 0) + header << T("\r\nProxy-Authorization: ") << Base64Encode (proxyAuth); + */ + } + + header << "\r\nUser-Agent: JUCE/" + << JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION + << "\r\nConnection: Close\r\nContent-Length: " + << postData.getSize() << "\r\n" + << headers << "\r\n"; + + MemoryBlock mb; + mb.append (header.toUTF8(), (int) strlen (header.toUTF8())); + mb.append (postData.getData(), postData.getSize()); + + return mb; + } + + const String readResponse() + { + int bytesRead = 0, numConsecutiveLFs = 0; + MemoryBlock buffer (1024, true); + + while (numConsecutiveLFs < 2 && bytesRead < 32768) + { + fd_set readbits; + FD_ZERO (&readbits); + FD_SET (socketHandle, &readbits); + + struct timeval tv; + tv.tv_sec = timeoutSeconds; + tv.tv_usec = 0; + + if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) + return String::empty; // (timeout) + + buffer.ensureSize (bytesRead + 8, true); + char* const dest = (char*) buffer.getData() + bytesRead; + + if (recv (socketHandle, dest, 1, 0) == -1) + return String::empty; + + const char lastByte = *dest; + ++bytesRead; + + if (lastByte == '\n') + ++numConsecutiveLFs; + else if (lastByte != '\r') + numConsecutiveLFs = 0; + } + + const String header (String::fromUTF8 ((const uint8*) buffer.getData())); + + if (header.startsWithIgnoreCase (T("HTTP/"))) + return header.trimEnd(); + + return String::empty; + } + + //============================================================================== + static bool decomposeURL (const String& url, + String& host, String& path, int& port) + { + if (! url.startsWithIgnoreCase (T("http://"))) + return false; + + const int nextSlash = url.indexOfChar (7, '/'); + int nextColon = url.indexOfChar (7, ':'); + if (nextColon > nextSlash && nextSlash > 0) + nextColon = -1; + + if (nextColon >= 0) + { + host = url.substring (7, nextColon); + + if (nextSlash >= 0) + port = url.substring (nextColon + 1, nextSlash).getIntValue(); + else + port = url.substring (nextColon + 1).getIntValue(); + } + else + { + port = 80; + + if (nextSlash >= 0) + host = url.substring (7, nextSlash); + else + host = url.substring (7); + } + + if (nextSlash >= 0) + path = url.substring (nextSlash); + else + path = T("/"); + + return true; + } + + //============================================================================== + static const String findHeaderItem (const StringArray& lines, const String& itemName) + { + for (int i = 0; i < lines.size(); ++i) + if (lines[i].startsWithIgnoreCase (itemName)) + return lines[i].substring (itemName.length()).trim(); + + return String::empty; + } +}; + +//============================================================================== +bool juce_isOnLine() +{ + return true; +} + +void* juce_openInternetFile (const String& url, + const String& headers, + const MemoryBlock& postData, + const bool isPost, + URL::OpenStreamProgressCallback* callback, + void* callbackContext) +{ + JUCE_HTTPSocketStream* const s = new JUCE_HTTPSocketStream(); + + if (s->open (url, headers, postData, isPost, + callback, callbackContext)) + return s; + + delete s; + return 0; +} + +void juce_closeInternetFile (void* handle) +{ + JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; + + if (s != 0) + delete s; +} + +int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) +{ + JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; + + if (s != 0) + return s->read (buffer, bytesToRead); + + return 0; +} + +int juce_seekInInternetFile (void* handle, int newPosition) +{ + JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; + + if (s != 0) + return s->readPosition; + + return 0; +} + + +#endif // __JUCE_MAC_HTTPSTREAM_JUCEHEADER__ diff --git a/build/macosx/platform_specific_code/juce_mac_Network.mm b/build/macosx/platform_specific_code/juce_mac_Network.mm new file mode 100644 index 0000000000..3acabffeb0 --- /dev/null +++ b/build/macosx/platform_specific_code/juce_mac_Network.mm @@ -0,0 +1,202 @@ +/* + ============================================================================== + + 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 "../../../src/juce_core/basics/juce_StandardHeader.h" + +#import +#import +#import +#import +#import +#import + +#include +#include +#include +#include +#include +#include + +BEGIN_JUCE_NAMESPACE + +#include "../../../src/juce_core/text/juce_String.h" +#include "../../../src/juce_core/basics/juce_Time.h" +#include "../../../src/juce_core/basics/juce_SystemStats.h" +#include "../../../src/juce_core/threads/juce_ScopedLock.h" +#include "../../../src/juce_core/threads/juce_WaitableEvent.h" +#include "../../../src/juce_core/threads/juce_Thread.h" +#include "../../../src/juce_core/containers/juce_MemoryBlock.h" +#include "../../../src/juce_core/text/juce_StringArray.h" +#include "../../../src/juce_core/misc/juce_PlatformUtilities.h" +#include "../../../src/juce_core/io/network/juce_URL.h" + +#include "juce_mac_HTTPStream.h" + +//============================================================================== +static bool GetEthernetIterator (io_iterator_t* matchingServices) throw() +{ + mach_port_t masterPort; + + if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS) + { + CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass); + + if (dict != 0) + { + CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (propDict != 0) + { + CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue); + + CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict); + CFRelease (propDict); + } + } + + return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS; + } + + return false; +} + +int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw() +{ + int numResults = 0; + io_iterator_t it; + + if (GetEthernetIterator (&it)) + { + io_object_t i; + + while ((i = IOIteratorNext (it)) != 0) + { + io_object_t controller; + + if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS) + { + CFTypeRef data = IORegistryEntryCreateCFProperty (controller, + CFSTR (kIOMACAddress), + kCFAllocatorDefault, + 0); + if (data != 0) + { + UInt8 addr [kIOEthernetAddressSize]; + zeromem (addr, sizeof (addr)); + + CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr); + CFRelease (data); + + int64 a = 0; + for (int i = 6; --i >= 0;) + a = (a << 8) | addr[i]; + + if (! littleEndian) + a = (int64) swapByteOrder ((uint64) a); + + if (numResults < maxNum) + { + *addresses++ = a; + ++numResults; + } + } + + IOObjectRelease (controller); + } + + IOObjectRelease (i); + } + + IOObjectRelease (it); + } + + return numResults; +} + +//============================================================================== +class AutoPool +{ +public: + AutoPool() { pool = [[NSAutoreleasePool alloc] init]; } + ~AutoPool() { [pool release]; } + +private: + NSAutoreleasePool* pool; +}; + +//============================================================================== +bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress, + const String& emailSubject, + const String& bodyText, + const StringArray& filesToAttach) +{ + const AutoPool pool; + + String script; + script << "tell application \"Mail\"\r\n" + "set newMessage to make new outgoing message with properties {subject:\"" + << emailSubject.replace (T("\""), T("\\\"")) + << "\", content:\"" + << bodyText.replace (T("\""), T("\\\"")) + << "\" & return & return}\r\n" + "tell newMessage\r\n" + "set visible to true\r\n" + "set sender to \"sdfsdfsdfewf\"\r\n" + "make new to recipient at end of to recipients with properties {address:\"" + << targetEmailAddress + << "\"}\r\n"; + + for (int i = 0; i < filesToAttach.size(); ++i) + { + script << "tell content\r\n" + "make new attachment with properties {file name:\"" + << filesToAttach[i].replace (T("\""), T("\\\"")) + << "\"} at after the last paragraph\r\n" + "end tell\r\n"; + } + + script << "end tell\r\n" + "end tell\r\n"; + + NSAppleScript* s = [[NSAppleScript alloc] + initWithSource: [NSString stringWithUTF8String: (const char*) script.toUTF8()]]; + NSDictionary* error = 0; + [s executeAndReturnError: &error]; + [s release]; + + return false; +} + + +END_JUCE_NAMESPACE diff --git a/build/macosx/platform_specific_code/juce_mac_Windowing.cpp b/build/macosx/platform_specific_code/juce_mac_Windowing.cpp index 9d6dde4477..a181bdcdf4 100644 --- a/build/macosx/platform_specific_code/juce_mac_Windowing.cpp +++ b/build/macosx/platform_specific_code/juce_mac_Windowing.cpp @@ -191,8 +191,8 @@ public: CMProfileRef prof; CMGetSystemProfile (&prof); colourspace = CGColorSpaceCreateWithPlatformColorSpace (prof); - provider = CGDataProviderCreateWithData (0, imageData, h * lineStride, 0); + CMCloseProfile (prof); } MacBitmapImage::~MacBitmapImage() @@ -806,10 +806,18 @@ public: Rect w; GetWindowBounds (windowRef, windowRegionToUse, &w); - RgnHandle rgn = NewRgn(); - SetRectRgn (rgn, 0, 0, w.right - w.left, w.bottom - w.top); - UpdateControls (windowRef, rgn); - DisposeRgn (rgn); + const int offsetInWindowX = component->getScreenX() - getScreenX(); + const int offsetInWindowY = component->getScreenY() - getScreenY(); + + for (RectangleList::Iterator i (repainter->getRegionsNeedingRepaint()); i.next();) + { + const Rectangle& r = *i.getRectangle(); + w.left = offsetInWindowX + r.getX(); + w.top = offsetInWindowY + r.getY(); + w.right = offsetInWindowX + r.getRight(); + w.bottom = offsetInWindowY + r.getBottom(); + InvalWindowRect (windowRef, &w); + } } else { diff --git a/build/win32/platform_specific_code/juce_win32_AudioCDReader.cpp b/build/win32/platform_specific_code/juce_win32_AudioCDReader.cpp index ceb9d76e4b..4dcdc17de3 100644 --- a/build/win32/platform_specific_code/juce_win32_AudioCDReader.cpp +++ b/build/win32/platform_specific_code/juce_win32_AudioCDReader.cpp @@ -2348,7 +2348,8 @@ int AudioCDBurner::getNumAvailableAudioBlocks() const } const String AudioCDBurner::burn (AudioCDBurner::BurnProgressListener* listener, - const bool ejectDiscAfterwards) + const bool ejectDiscAfterwards, + const bool performFakeBurnForTesting) { CDBurnerInfo* const info = (CDBurnerInfo*) internal; @@ -2359,7 +2360,7 @@ const String AudioCDBurner::burn (AudioCDBurner::BurnProgressListener* listener, UINT_PTR cookie; HRESULT hr = info->discMaster->ProgressAdvise (info, &cookie); - hr = info->discMaster->RecordDisc (FALSE, // set this to TRUE to make it do a fake burn, without actually writing to the disc + hr = info->discMaster->RecordDisc (performFakeBurnForTesting, ejectDiscAfterwards); String error; @@ -2381,69 +2382,11 @@ const String AudioCDBurner::burn (AudioCDBurner::BurnProgressListener* listener, return error; } -bool AudioCDBurner::addAudioTrack (AudioFormatReader& source, int numSamples) +bool AudioCDBurner::addAudioTrack (AudioSource* source, int numSamples) { - CDBurnerInfo* const info = (CDBurnerInfo*) internal; - - long bytesPerBlock; - HRESULT hr = info->redbook->GetAudioBlockSize (&bytesPerBlock); - - const int samplesPerBlock = bytesPerBlock / 4; - bool ok = true; + if (source == 0) + return false; - hr = info->redbook->CreateAudioTrack ((long) numSamples / (bytesPerBlock * 4)); - - byte* const buffer = (byte*) juce_malloc (bytesPerBlock); - - int* sourceBuffers[2]; - sourceBuffers[0] = (int*) juce_malloc (samplesPerBlock * 4); - sourceBuffers[1] = (int*) juce_malloc (samplesPerBlock * 4); - - int samplesDone = 0; - - for (;;) - { - zeromem (buffer, bytesPerBlock); - - if (! source.read (sourceBuffers, samplesDone, samplesPerBlock)) - { - ok = false; - break; - } - - short* destBuffer = (short*) buffer; - - for (int j = 0; j < samplesPerBlock; ++j) - { - *destBuffer++ = (short) (sourceBuffers [0][j] >> 16); - *destBuffer++ = (short) (sourceBuffers [jmin (1, source.numChannels - 1)][j] >> 16); - } - - hr = info->redbook->AddAudioTrackBlocks (buffer, bytesPerBlock); - - if (hr != S_OK) - { - ok = false; - break; - } - - samplesDone += samplesPerBlock; - - if (samplesDone >= numSamples) - break; - } - - juce_free (sourceBuffers[0]); - juce_free (sourceBuffers[1]); - juce_free (buffer); - - hr = info->redbook->CloseAudioTrack(); - - return ok && hr == S_OK; -} - -bool AudioCDBurner::addAudioTrack (AudioSource& source, int numSamples) -{ CDBurnerInfo* const info = (CDBurnerInfo*) internal; long bytesPerBlock; @@ -2459,7 +2402,7 @@ bool AudioCDBurner::addAudioTrack (AudioSource& source, int numSamples) AudioSampleBuffer sourceBuffer (2, samplesPerBlock); int samplesDone = 0; - source.prepareToPlay (samplesPerBlock, 44100.0); + source->prepareToPlay (samplesPerBlock, 44100.0); while (ok) { @@ -2470,7 +2413,7 @@ bool AudioCDBurner::addAudioTrack (AudioSource& source, int numSamples) info.startSample = 0; sourceBuffer.clear(); - source.getNextAudioBlock (info); + source->getNextAudioBlock (info); } zeromem (buffer, bytesPerBlock); @@ -2496,6 +2439,8 @@ bool AudioCDBurner::addAudioTrack (AudioSource& source, int numSamples) hr = info->redbook->CloseAudioTrack(); + delete source; + return ok && hr == S_OK; } diff --git a/build/win32/platform_specific_code/juce_win32_Files.cpp b/build/win32/platform_specific_code/juce_win32_Files.cpp index 1a79dc75b9..7f33545df0 100644 --- a/build/win32/platform_specific_code/juce_win32_Files.cpp +++ b/build/win32/platform_specific_code/juce_win32_Files.cpp @@ -117,6 +117,11 @@ bool juce_setFileReadOnly (const String& fileName, return SetFileAttributes (fileName, attr) != FALSE; } +bool File::isHidden() const throw() +{ + return (GetFileAttributes (getFullPathName()) & FILE_ATTRIBUTE_HIDDEN) != 0; +} + //============================================================================== bool juce_deleteFile (const String& fileName) throw() { diff --git a/build/win32/platform_specific_code/juce_win32_Network.cpp b/build/win32/platform_specific_code/juce_win32_Network.cpp index bc9b7fa9e1..10d3a80b8c 100644 --- a/build/win32/platform_specific_code/juce_win32_Network.cpp +++ b/build/win32/platform_specific_code/juce_win32_Network.cpp @@ -225,26 +225,6 @@ int juce_seekInInternetFile (void* handle, int newPosition) } } -int juce_getStatusCodeFor (void* handle) -{ - DWORD result = 404; - const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; - - if (crs != 0) - { - DWORD index = 0; - DWORD size = sizeof (result); - - HttpQueryInfo (crs->request, - HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, - &result, - &size, - &index); - } - - return (int) result; -} - void juce_closeInternetFile (void* handle) { if (handle != 0) diff --git a/extras/juce demo/src/BinaryData.cpp b/extras/juce demo/src/BinaryData.cpp index b587a4fc9b..b6dd4e31b5 100644 --- a/extras/juce demo/src/BinaryData.cpp +++ b/extras/juce demo/src/BinaryData.cpp @@ -2,592 +2,576 @@ #include "BinaryData.h" -static const unsigned char temp1[] = {47,42,13,10,32,32,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, +static const unsigned char temp1[] = {47,42,10,32,32,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,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,13,10,32,32,32,84,104,105,115,32,102,105,108,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,74,85,67,69, - 32,108,105,98,114,97,114,121,32,45,32,34,74,117,108,101,115,39,32,85,116,105,108,105,116,121,32,67,108,97,115,115,32,69,120,116,101,110,115,105, - 111,110,115,34,13,10,32,32,32,67,111,112,121,114,105,103,104,116,32,50,48,48,52,45,55,32,98,121,32,82,97,119,32,77,97,116,101,114,105,97, - 108,32,83,111,102,116,119,97,114,101,32,108,116,100,46,13,10,13,10,32,32,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, + 61,61,61,10,10,32,32,32,84,104,105,115,32,102,105,108,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,74,85,67,69,32,108,105, + 98,114,97,114,121,32,45,32,34,74,117,108,101,115,39,32,85,116,105,108,105,116,121,32,67,108,97,115,115,32,69,120,116,101,110,115,105,111,110,115, + 34,10,32,32,32,67,111,112,121,114,105,103,104,116,32,50,48,48,52,45,55,32,98,121,32,82,97,119,32,77,97,116,101,114,105,97,108,32,83,111, + 102,116,119,97,114,101,32,108,116,100,46,10,10,32,32,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, - 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,13,10,13,10,32,32,32,74,85,67,69,32,99,97,110,32,98,101,32,114,101, - 100,105,115,116,114,105,98,117,116,101,100,32,97,110,100,47,111,114,32,109,111,100,105,102,105,101,100,32,117,110,100,101,114,32,116,104,101,32,116,101, - 114,109,115,32,111,102,32,116,104,101,13,10,32,32,32,71,78,85,32,71,101,110,101,114,97,108,32,80,117,98,108,105,99,32,76,105,99,101,110,115, - 101,44,32,97,115,32,112,117,98,108,105,115,104,101,100,32,98,121,32,116,104,101,32,70,114,101,101,32,83,111,102,116,119,97,114,101,32,70,111,117, - 110,100,97,116,105,111,110,59,13,10,32,32,32,101,105,116,104,101,114,32,118,101,114,115,105,111,110,32,50,32,111,102,32,116,104,101,32,76,105,99, - 101,110,115,101,44,32,111,114,32,40,97,116,32,121,111,117,114,32,111,112,116,105,111,110,41,32,97,110,121,32,108,97,116,101,114,32,118,101,114,115, - 105,111,110,46,13,10,13,10,32,32,32,74,85,67,69,32,105,115,32,100,105,115,116,114,105,98,117,116,101,100,32,105,110,32,116,104,101,32,104,111, - 112,101,32,116,104,97,116,32,105,116,32,119,105,108,108,32,98,101,32,117,115,101,102,117,108,44,13,10,32,32,32,98,117,116,32,87,73,84,72,79, - 85,84,32,65,78,89,32,87,65,82,82,65,78,84,89,59,32,119,105,116,104,111,117,116,32,101,118,101,110,32,116,104,101,32,105,109,112,108,105,101, - 100,32,119,97,114,114,97,110,116,121,32,111,102,13,10,32,32,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,32,111,114,32,70,73,84, - 78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,46,32,32,83,101,101,32,116,104,101,13, - 10,32,32,32,71,78,85,32,71,101,110,101,114,97,108,32,80,117,98,108,105,99,32,76,105,99,101,110,115,101,32,102,111,114,32,109,111,114,101,32, - 100,101,116,97,105,108,115,46,13,10,13,10,32,32,32,89,111,117,32,115,104,111,117,108,100,32,104,97,118,101,32,114,101,99,101,105,118,101,100,32, - 97,32,99,111,112,121,32,111,102,32,116,104,101,32,71,78,85,32,71,101,110,101,114,97,108,32,80,117,98,108,105,99,32,76,105,99,101,110,115,101, - 13,10,32,32,32,97,108,111,110,103,32,119,105,116,104,32,74,85,67,69,59,32,105,102,32,110,111,116,44,32,118,105,115,105,116,32,119,119,119,46, - 103,110,117,46,111,114,103,47,108,105,99,101,110,115,101,115,32,111,114,32,119,114,105,116,101,32,116,111,32,116,104,101,13,10,32,32,32,70,114,101, - 101,32,83,111,102,116,119,97,114,101,32,70,111,117,110,100,97,116,105,111,110,44,32,73,110,99,46,44,32,53,57,32,84,101,109,112,108,101,32,80, - 108,97,99,101,44,32,83,117,105,116,101,32,51,51,48,44,13,10,32,32,32,66,111,115,116,111,110,44,32,77,65,32,48,50,49,49,49,45,49,51, - 48,55,32,85,83,65,13,10,13,10,32,32,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, + 45,45,45,45,45,45,45,45,45,45,45,45,45,10,10,32,32,32,74,85,67,69,32,99,97,110,32,98,101,32,114,101,100,105,115,116,114,105,98,117, + 116,101,100,32,97,110,100,47,111,114,32,109,111,100,105,102,105,101,100,32,117,110,100,101,114,32,116,104,101,32,116,101,114,109,115,32,111,102,32,116, + 104,101,10,32,32,32,71,78,85,32,71,101,110,101,114,97,108,32,80,117,98,108,105,99,32,76,105,99,101,110,115,101,44,32,97,115,32,112,117,98, + 108,105,115,104,101,100,32,98,121,32,116,104,101,32,70,114,101,101,32,83,111,102,116,119,97,114,101,32,70,111,117,110,100,97,116,105,111,110,59,10, + 32,32,32,101,105,116,104,101,114,32,118,101,114,115,105,111,110,32,50,32,111,102,32,116,104,101,32,76,105,99,101,110,115,101,44,32,111,114,32,40, + 97,116,32,121,111,117,114,32,111,112,116,105,111,110,41,32,97,110,121,32,108,97,116,101,114,32,118,101,114,115,105,111,110,46,10,10,32,32,32,74, + 85,67,69,32,105,115,32,100,105,115,116,114,105,98,117,116,101,100,32,105,110,32,116,104,101,32,104,111,112,101,32,116,104,97,116,32,105,116,32,119, + 105,108,108,32,98,101,32,117,115,101,102,117,108,44,10,32,32,32,98,117,116,32,87,73,84,72,79,85,84,32,65,78,89,32,87,65,82,82,65,78, + 84,89,59,32,119,105,116,104,111,117,116,32,101,118,101,110,32,116,104,101,32,105,109,112,108,105,101,100,32,119,97,114,114,97,110,116,121,32,111,102, + 10,32,32,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,32,111,114,32,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82, + 84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,46,32,32,83,101,101,32,116,104,101,10,32,32,32,71,78,85,32,71,101,110,101,114,97,108, + 32,80,117,98,108,105,99,32,76,105,99,101,110,115,101,32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46,10,10,32,32,32,89,111, + 117,32,115,104,111,117,108,100,32,104,97,118,101,32,114,101,99,101,105,118,101,100,32,97,32,99,111,112,121,32,111,102,32,116,104,101,32,71,78,85, + 32,71,101,110,101,114,97,108,32,80,117,98,108,105,99,32,76,105,99,101,110,115,101,10,32,32,32,97,108,111,110,103,32,119,105,116,104,32,74,85, + 67,69,59,32,105,102,32,110,111,116,44,32,118,105,115,105,116,32,119,119,119,46,103,110,117,46,111,114,103,47,108,105,99,101,110,115,101,115,32,111, + 114,32,119,114,105,116,101,32,116,111,32,116,104,101,10,32,32,32,70,114,101,101,32,83,111,102,116,119,97,114,101,32,70,111,117,110,100,97,116,105, + 111,110,44,32,73,110,99,46,44,32,53,57,32,84,101,109,112,108,101,32,80,108,97,99,101,44,32,83,117,105,116,101,32,51,51,48,44,10,32,32, + 32,66,111,115,116,111,110,44,32,77,65,32,48,50,49,49,49,45,49,51,48,55,32,85,83,65,10,10,32,32,45,45,45,45,45,45,45,45,45,45, 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, - 45,45,45,45,45,45,45,45,45,45,13,10,13,10,32,32,32,73,102,32,121,111,117,39,100,32,108,105,107,101,32,116,111,32,114,101,108,101,97,115, - 101,32,97,32,99,108,111,115,101,100,45,115,111,117,114,99,101,32,112,114,111,100,117,99,116,32,119,104,105,99,104,32,117,115,101,115,32,74,85,67, - 69,44,32,99,111,109,109,101,114,99,105,97,108,13,10,32,32,32,108,105,99,101,110,115,101,115,32,97,114,101,32,97,108,115,111,32,97,118,97,105, - 108,97,98,108,101,58,32,118,105,115,105,116,32,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,32,102,111,114,13,10,32,32,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,46,13,10,13,10,32,32,61,61,61, + 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,10,10,32,32,32,73,102,32,121,111,117,39, + 100,32,108,105,107,101,32,116,111,32,114,101,108,101,97,115,101,32,97,32,99,108,111,115,101,100,45,115,111,117,114,99,101,32,112,114,111,100,117,99, + 116,32,119,104,105,99,104,32,117,115,101,115,32,74,85,67,69,44,32,99,111,109,109,101,114,99,105,97,108,10,32,32,32,108,105,99,101,110,115,101, + 115,32,97,114,101,32,97,108,115,111,32,97,118,97,105,108,97,98,108,101,58,32,118,105,115,105,116,32,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,32,102,111,114,10,32,32,32,109,111,114,101,32,105,110,102,111,114,109,97, + 116,105,111,110,46,10,10,32,32,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,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,42,47,13, - 10,13,10,35,105,110,99,108,117,100,101,32,34,46,46,47,106,117,99,101,100,101,109,111,95,104,101,97,100,101,114,115,46,104,34,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,10,42,47,10,10,35,105,110,99,108,117,100,101,32,34,46,46,47,106,117,99,101,100,101,109,111,95,104,101,97,100,101,114, + 115,46,104,34,10,10,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,13,10,47,42,42,32,79,117,114,32,100,101,109,111,32,115,121,110,116,104,32,111,110,108,121,32,104,97,115,32,111,110,101,32,116,121,112,101,32, - 111,102,32,115,111,117,110,100,44,32,97,110,100,32,105,116,39,115,32,118,101,114,121,32,98,97,115,105,99,46,46,13,10,42,47,13,10,99,108,97, - 115,115,32,83,105,110,101,87,97,118,101,83,111,117,110,100,32,58,32,112,117,98,108,105,99,32,83,121,110,116,104,101,115,105,115,101,114,83,111,117, - 110,100,13,10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,83,105,110,101,87,97,118,101,83,111,117,110,100,32,40,99,111,110,115,116, - 32,66,105,116,65,114,114,97,121,38,32,109,105,100,105,78,111,116,101,115,95,41,13,10,32,32,32,32,32,32,32,32,58,32,109,105,100,105,78,111, - 116,101,115,32,40,109,105,100,105,78,111,116,101,115,95,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,98,111, - 111,108,32,97,112,112,108,105,101,115,84,111,78,111,116,101,32,40,99,111,110,115,116,32,105,110,116,32,109,105,100,105,78,111,116,101,78,117,109,98, - 101,114,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,109,105,100,105,78,111,116,101,115,32,91,109,105, - 100,105,78,111,116,101,78,117,109,98,101,114,93,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,98,111,111,108,32,97,112,112,108,105,101, - 115,84,111,67,104,97,110,110,101,108,32,40,99,111,110,115,116,32,105,110,116,32,109,105,100,105,67,104,97,110,110,101,108,41,32,32,32,32,32,32, - 32,32,32,32,32,123,32,114,101,116,117,114,110,32,116,114,117,101,59,32,125,13,10,13,10,112,114,105,118,97,116,101,58,13,10,32,32,32,32,47, - 47,32,116,104,105,115,32,119,105,108,108,32,99,111,110,116,97,105,110,32,116,104,101,32,110,111,116,101,115,32,116,104,97,116,32,116,104,105,115,32, - 115,111,117,110,100,32,105,115,32,97,116,116,97,99,104,101,100,32,116,111,46,13,10,32,32,32,32,66,105,116,65,114,114,97,121,32,109,105,100,105, - 78,111,116,101,115,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,10,47,42,42,32,79,117,114,32,100,101,109,111,32,115,121,110,116,104,32,111,110,108,121,32,104,97,115,32,111,110,101,32, + 116,121,112,101,32,111,102,32,115,111,117,110,100,44,32,97,110,100,32,105,116,39,115,32,118,101,114,121,32,98,97,115,105,99,46,46,10,42,47,10, + 99,108,97,115,115,32,83,105,110,101,87,97,118,101,83,111,117,110,100,32,58,32,112,117,98,108,105,99,32,83,121,110,116,104,101,115,105,115,101,114, + 83,111,117,110,100,10,123,10,112,117,98,108,105,99,58,10,32,32,32,32,83,105,110,101,87,97,118,101,83,111,117,110,100,32,40,99,111,110,115,116, + 32,66,105,116,65,114,114,97,121,38,32,109,105,100,105,78,111,116,101,115,95,41,10,32,32,32,32,32,32,32,32,58,32,109,105,100,105,78,111,116, + 101,115,32,40,109,105,100,105,78,111,116,101,115,95,41,10,32,32,32,32,123,10,32,32,32,32,125,10,10,32,32,32,32,98,111,111,108,32,97,112, + 112,108,105,101,115,84,111,78,111,116,101,32,40,99,111,110,115,116,32,105,110,116,32,109,105,100,105,78,111,116,101,78,117,109,98,101,114,41,10,32, + 32,32,32,123,10,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,109,105,100,105,78,111,116,101,115,32,91,109,105,100,105,78,111,116,101,78, + 117,109,98,101,114,93,59,10,32,32,32,32,125,10,10,32,32,32,32,98,111,111,108,32,97,112,112,108,105,101,115,84,111,67,104,97,110,110,101,108, + 32,40,99,111,110,115,116,32,105,110,116,32,109,105,100,105,67,104,97,110,110,101,108,41,32,32,32,32,32,32,32,32,32,32,32,123,32,114,101,116, + 117,114,110,32,116,114,117,101,59,32,125,10,10,112,114,105,118,97,116,101,58,10,32,32,32,32,47,47,32,116,104,105,115,32,119,105,108,108,32,99, + 111,110,116,97,105,110,32,116,104,101,32,110,111,116,101,115,32,116,104,97,116,32,116,104,105,115,32,115,111,117,110,100,32,105,115,32,97,116,116,97, + 99,104,101,100,32,116,111,46,10,32,32,32,32,66,105,116,65,114,114,97,121,32,109,105,100,105,78,111,116,101,115,59,10,125,59,10,10,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,13,10,47,42,42,32,79,117,114,32,100,101,109,111,32,115,121,110,116,104,32,118,111,105, - 99,101,32,106,117,115,116,32,112,108,97,121,115,32,97,32,115,105,110,101,32,119,97,118,101,46,46,13,10,42,47,13,10,99,108,97,115,115,32,83, - 105,110,101,87,97,118,101,86,111,105,99,101,32,32,58,32,112,117,98,108,105,99,32,83,121,110,116,104,101,115,105,115,101,114,86,111,105,99,101,13, - 10,123,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,83,105,110,101,87,97,118,101,86,111,105,99,101,40,41,13,10,32,32,32,32,32,32, - 32,32,58,32,97,110,103,108,101,68,101,108,116,97,32,40,48,46,48,41,44,13,10,32,32,32,32,32,32,32,32,32,32,116,97,105,108,79,102,102, - 32,40,48,46,48,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,98,111,111,108,32,99,97,110,80,108,97,121, - 83,111,117,110,100,32,40,83,121,110,116,104,101,115,105,115,101,114,83,111,117,110,100,42,32,115,111,117,110,100,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,100,121,110,97,109,105,99,95,99,97,115,116,32,60,83,105,110,101,87,97,118,101,83,111,117, - 110,100,42,62,32,40,115,111,117,110,100,41,32,33,61,32,48,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,115,116, - 97,114,116,78,111,116,101,32,40,99,111,110,115,116,32,105,110,116,32,109,105,100,105,78,111,116,101,78,117,109,98,101,114,44,32,99,111,110,115,116, - 32,102,108,111,97,116,32,118,101,108,111,99,105,116,121,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,83,121, - 110,116,104,101,115,105,115,101,114,83,111,117,110,100,42,32,115,111,117,110,100,44,32,99,111,110,115,116,32,105,110,116,32,99,117,114,114,101,110,116, - 80,105,116,99,104,87,104,101,101,108,80,111,115,105,116,105,111,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,99,117,114,114, - 101,110,116,65,110,103,108,101,32,61,32,48,46,48,59,13,10,32,32,32,32,32,32,32,32,108,101,118,101,108,32,61,32,118,101,108,111,99,105,116, - 121,32,42,32,48,46,49,53,59,13,10,32,32,32,32,32,32,32,32,116,97,105,108,79,102,102,32,61,32,48,46,48,59,13,10,13,10,32,32,32, - 32,32,32,32,32,100,111,117,98,108,101,32,99,121,99,108,101,115,80,101,114,83,101,99,111,110,100,32,61,32,77,105,100,105,77,101,115,115,97,103, - 101,58,58,103,101,116,77,105,100,105,78,111,116,101,73,110,72,101,114,116,122,32,40,109,105,100,105,78,111,116,101,78,117,109,98,101,114,41,59,13, - 10,32,32,32,32,32,32,32,32,100,111,117,98,108,101,32,99,121,99,108,101,115,80,101,114,83,97,109,112,108,101,32,61,32,99,121,99,108,101,115, - 80,101,114,83,101,99,111,110,100,32,47,32,103,101,116,83,97,109,112,108,101,82,97,116,101,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32, - 97,110,103,108,101,68,101,108,116,97,32,61,32,99,121,99,108,101,115,80,101,114,83,97,109,112,108,101,32,42,32,50,46,48,32,42,32,100,111,117, - 98,108,101,95,80,105,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,115,116,111,112,78,111,116,101,32,40,99,111,110, - 115,116,32,98,111,111,108,32,97,108,108,111,119,84,97,105,108,79,102,102,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,105,102, - 32,40,97,108,108,111,119,84,97,105,108,79,102,102,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,115,116,97,114,116,32,97,32,116,97,105,108,45,111,102,102,32,98,121,32,115,101,116,116,105,110,103,32,116,104,105,115,32,102,108,97,103, - 46,32,84,104,101,32,114,101,110,100,101,114,32,99,97,108,108,98,97,99,107,32,119,105,108,108,32,112,105,99,107,32,117,112,32,111,110,13,10,32, - 32,32,32,32,32,32,32,32,32,32,32,47,47,32,116,104,105,115,32,97,110,100,32,100,111,32,97,32,102,97,100,101,32,111,117,116,44,32,99,97, - 108,108,105,110,103,32,99,108,101,97,114,67,117,114,114,101,110,116,78,111,116,101,40,41,32,119,104,101,110,32,105,116,39,115,32,102,105,110,105,115, - 104,101,100,46,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,116,97,105,108,79,102,102,32,61,61,32,48,46,48,41,32, - 47,47,32,119,101,32,111,110,108,121,32,110,101,101,100,32,116,111,32,98,101,103,105,110,32,97,32,116,97,105,108,45,111,102,102,32,105,102,32,105, - 116,39,115,32,110,111,116,32,97,108,114,101,97,100,121,32,100,111,105,110,103,32,115,111,32,45,32,116,104,101,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,47,47,32,115,116,111,112,78,111,116,101,32,109,101,116,104, - 111,100,32,99,111,117,108,100,32,98,101,32,99,97,108,108,101,100,32,109,111,114,101,32,116,104,97,110,32,111,110,99,101,46,13,10,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,116,97,105,108,79,102,102,32,61,32,49,46,48,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,47,47,32,119, - 101,39,114,101,32,98,101,105,110,103,32,116,111,108,100,32,116,111,32,115,116,111,112,32,112,108,97,121,105,110,103,32,105,109,109,101,100,105,97,116, - 101,108,121,44,32,115,111,32,114,101,115,101,116,32,101,118,101,114,121,116,104,105,110,103,46,46,13,10,13,10,32,32,32,32,32,32,32,32,32,32, - 32,32,99,108,101,97,114,67,117,114,114,101,110,116,78,111,116,101,40,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,97,110,103,108,101, - 68,101,108,116,97,32,61,32,48,46,48,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111, - 105,100,32,112,105,116,99,104,87,104,101,101,108,77,111,118,101,100,32,40,99,111,110,115,116,32,105,110,116,32,110,101,119,86,97,108,117,101,41,13, - 10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,99,97,110,39,116,32,98,101,32,98,111,116,104,101,114,101,100,32,105,109,112, - 108,101,109,101,110,116,105,110,103,32,116,104,105,115,32,102,111,114,32,116,104,101,32,100,101,109,111,33,13,10,32,32,32,32,125,13,10,13,10,32, - 32,32,32,118,111,105,100,32,99,111,110,116,114,111,108,108,101,114,77,111,118,101,100,32,40,99,111,110,115,116,32,105,110,116,32,99,111,110,116,114, - 111,108,108,101,114,78,117,109,98,101,114,44,32,99,111,110,115,116,32,105,110,116,32,110,101,119,86,97,108,117,101,41,13,10,32,32,32,32,123,13, - 10,32,32,32,32,32,32,32,32,47,47,32,110,111,116,32,105,110,116,101,114,101,115,116,101,100,32,105,110,32,99,111,110,116,114,111,108,108,101,114, - 115,32,105,110,32,116,104,105,115,32,99,97,115,101,46,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,114,101,110,100,101, - 114,78,101,120,116,66,108,111,99,107,32,40,65,117,100,105,111,83,97,109,112,108,101,66,117,102,102,101,114,38,32,111,117,116,112,117,116,66,117,102, - 102,101,114,44,32,105,110,116,32,115,116,97,114,116,83,97,109,112,108,101,44,32,105,110,116,32,110,117,109,83,97,109,112,108,101,115,41,13,10,32, - 32,32,32,123,13,10,32,32,32,32,32,32,32,32,105,102,32,40,97,110,103,108,101,68,101,108,116,97,32,33,61,32,48,46,48,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,116,97,105,108,79,102,102,32,62,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,119,104,105,108,101,32,40,45,45,110, - 117,109,83,97,109,112,108,101,115,32,62,61,32,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,99,111,110,115,116,32,102,108,111,97,116,32,99,117,114,114,101,110,116,83,97,109,112,108, - 101,32,61,32,40,102,108,111,97,116,41,32,40,115,105,110,32,40,99,117,114,114,101,110,116,65,110,103,108,101,41,32,42,32,108,101,118,101,108,32, - 42,32,116,97,105,108,79,102,102,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,102,111,114,32,40, - 105,110,116,32,105,32,61,32,111,117,116,112,117,116,66,117,102,102,101,114,46,103,101,116,78,117,109,67,104,97,110,110,101,108,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,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,42,111,117,116,112, - 117,116,66,117,102,102,101,114,46,103,101,116,83,97,109,112,108,101,68,97,116,97,32,40,105,44,32,115,116,97,114,116,83,97,109,112,108,101,41,32, - 43,61,32,99,117,114,114,101,110,116,83,97,109,112,108,101,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,99,117,114,114,101,110,116,65,110,103,108,101,32,43,61,32,97,110,103,108,101,68,101,108,116,97,59,13,10,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,43,43,115,116,97,114,116,83,97,109,112,108,101,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,116,97,105,108,79,102,102,32,42,61,32,48,46,57,57,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,116,97,105,108,79,102,102,32,60,61,32,48,46,48,48,53,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,99,108, - 101,97,114,67,117,114,114,101,110,116,78,111,116,101,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,97,110,103,108,101,68,101,108,116,97,32,61,32,48,46,48,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,98,114,101,97,107,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,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,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, - 32,32,119,104,105,108,101,32,40,45,45,110,117,109,83,97,109,112,108,101,115,32,62,61,32,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,99,111,110,115,116,32,102,108,111,97,116,32, - 99,117,114,114,101,110,116,83,97,109,112,108,101,32,61,32,40,102,108,111,97,116,41,32,40,115,105,110,32,40,99,117,114,114,101,110,116,65,110,103, - 108,101,41,32,42,32,108,101,118,101,108,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,102,111,114, - 32,40,105,110,116,32,105,32,61,32,111,117,116,112,117,116,66,117,102,102,101,114,46,103,101,116,78,117,109,67,104,97,110,110,101,108,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,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,42,111,117, - 116,112,117,116,66,117,102,102,101,114,46,103,101,116,83,97,109,112,108,101,68,97,116,97,32,40,105,44,32,115,116,97,114,116,83,97,109,112,108,101, - 41,32,43,61,32,99,117,114,114,101,110,116,83,97,109,112,108,101,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,99,117,114,114,101,110,116,65,110,103,108,101,32,43,61,32,97,110,103,108,101,68,101,108,116,97,59,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,43,43,115,116,97,114,116,83,97,109,112,108,101,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, - 13,10,112,114,105,118,97,116,101,58,13,10,32,32,32,32,100,111,117,98,108,101,32,99,117,114,114,101,110,116,65,110,103,108,101,44,32,97,110,103, - 108,101,68,101,108,116,97,44,32,108,101,118,101,108,44,32,116,97,105,108,79,102,102,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,10,47, + 42,42,32,79,117,114,32,100,101,109,111,32,115,121,110,116,104,32,118,111,105,99,101,32,106,117,115,116,32,112,108,97,121,115,32,97,32,115,105,110, + 101,32,119,97,118,101,46,46,10,42,47,10,99,108,97,115,115,32,83,105,110,101,87,97,118,101,86,111,105,99,101,32,32,58,32,112,117,98,108,105, + 99,32,83,121,110,116,104,101,115,105,115,101,114,86,111,105,99,101,10,123,10,112,117,98,108,105,99,58,10,32,32,32,32,83,105,110,101,87,97,118, + 101,86,111,105,99,101,40,41,10,32,32,32,32,32,32,32,32,58,32,97,110,103,108,101,68,101,108,116,97,32,40,48,46,48,41,44,10,32,32,32, + 32,32,32,32,32,32,32,116,97,105,108,79,102,102,32,40,48,46,48,41,10,32,32,32,32,123,10,32,32,32,32,125,10,10,32,32,32,32,98,111, + 111,108,32,99,97,110,80,108,97,121,83,111,117,110,100,32,40,83,121,110,116,104,101,115,105,115,101,114,83,111,117,110,100,42,32,115,111,117,110,100, + 41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,100,121,110,97,109,105,99,95,99,97,115,116,32,60,83,105,110, + 101,87,97,118,101,83,111,117,110,100,42,62,32,40,115,111,117,110,100,41,32,33,61,32,48,59,10,32,32,32,32,125,10,10,32,32,32,32,118,111, + 105,100,32,115,116,97,114,116,78,111,116,101,32,40,99,111,110,115,116,32,105,110,116,32,109,105,100,105,78,111,116,101,78,117,109,98,101,114,44,32, + 99,111,110,115,116,32,102,108,111,97,116,32,118,101,108,111,99,105,116,121,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,83,121,110,116,104,101,115,105,115,101,114,83,111,117,110,100,42,32,115,111,117,110,100,44,32,99,111,110,115,116,32,105,110,116,32,99,117,114, + 114,101,110,116,80,105,116,99,104,87,104,101,101,108,80,111,115,105,116,105,111,110,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,99,117, + 114,114,101,110,116,65,110,103,108,101,32,61,32,48,46,48,59,10,32,32,32,32,32,32,32,32,108,101,118,101,108,32,61,32,118,101,108,111,99,105, + 116,121,32,42,32,48,46,49,53,59,10,32,32,32,32,32,32,32,32,116,97,105,108,79,102,102,32,61,32,48,46,48,59,10,10,32,32,32,32,32, + 32,32,32,100,111,117,98,108,101,32,99,121,99,108,101,115,80,101,114,83,101,99,111,110,100,32,61,32,77,105,100,105,77,101,115,115,97,103,101,58, + 58,103,101,116,77,105,100,105,78,111,116,101,73,110,72,101,114,116,122,32,40,109,105,100,105,78,111,116,101,78,117,109,98,101,114,41,59,10,32,32, + 32,32,32,32,32,32,100,111,117,98,108,101,32,99,121,99,108,101,115,80,101,114,83,97,109,112,108,101,32,61,32,99,121,99,108,101,115,80,101,114, + 83,101,99,111,110,100,32,47,32,103,101,116,83,97,109,112,108,101,82,97,116,101,40,41,59,10,10,32,32,32,32,32,32,32,32,97,110,103,108,101, + 68,101,108,116,97,32,61,32,99,121,99,108,101,115,80,101,114,83,97,109,112,108,101,32,42,32,50,46,48,32,42,32,100,111,117,98,108,101,95,80, + 105,59,10,32,32,32,32,125,10,10,32,32,32,32,118,111,105,100,32,115,116,111,112,78,111,116,101,32,40,99,111,110,115,116,32,98,111,111,108,32, + 97,108,108,111,119,84,97,105,108,79,102,102,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,105,102,32,40,97,108,108,111,119,84,97,105, + 108,79,102,102,41,10,32,32,32,32,32,32,32,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,115,116,97,114,116,32,97,32,116, + 97,105,108,45,111,102,102,32,98,121,32,115,101,116,116,105,110,103,32,116,104,105,115,32,102,108,97,103,46,32,84,104,101,32,114,101,110,100,101,114, + 32,99,97,108,108,98,97,99,107,32,119,105,108,108,32,112,105,99,107,32,117,112,32,111,110,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47, + 32,116,104,105,115,32,97,110,100,32,100,111,32,97,32,102,97,100,101,32,111,117,116,44,32,99,97,108,108,105,110,103,32,99,108,101,97,114,67,117, + 114,114,101,110,116,78,111,116,101,40,41,32,119,104,101,110,32,105,116,39,115,32,102,105,110,105,115,104,101,100,46,10,10,32,32,32,32,32,32,32, + 32,32,32,32,32,105,102,32,40,116,97,105,108,79,102,102,32,61,61,32,48,46,48,41,32,47,47,32,119,101,32,111,110,108,121,32,110,101,101,100, + 32,116,111,32,98,101,103,105,110,32,97,32,116,97,105,108,45,111,102,102,32,105,102,32,105,116,39,115,32,110,111,116,32,97,108,114,101,97,100,121, + 32,100,111,105,110,103,32,115,111,32,45,32,116,104,101,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,47,47,32,115,116,111,112,78,111,116,101,32,109,101,116,104,111,100,32,99,111,117,108,100,32,98,101,32,99,97,108,108, + 101,100,32,109,111,114,101,32,116,104,97,110,32,111,110,99,101,46,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,97,105,108,79, + 102,102,32,61,32,49,46,48,59,10,32,32,32,32,32,32,32,32,125,10,32,32,32,32,32,32,32,32,101,108,115,101,10,32,32,32,32,32,32,32, + 32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,119,101,39,114,101,32,98,101,105,110,103,32,116,111,108,100,32,116,111,32,115,116, + 111,112,32,112,108,97,121,105,110,103,32,105,109,109,101,100,105,97,116,101,108,121,44,32,115,111,32,114,101,115,101,116,32,101,118,101,114,121,116,104, + 105,110,103,46,46,10,10,32,32,32,32,32,32,32,32,32,32,32,32,99,108,101,97,114,67,117,114,114,101,110,116,78,111,116,101,40,41,59,10,32, + 32,32,32,32,32,32,32,32,32,32,32,97,110,103,108,101,68,101,108,116,97,32,61,32,48,46,48,59,10,32,32,32,32,32,32,32,32,125,10,32, + 32,32,32,125,10,10,32,32,32,32,118,111,105,100,32,112,105,116,99,104,87,104,101,101,108,77,111,118,101,100,32,40,99,111,110,115,116,32,105,110, + 116,32,110,101,119,86,97,108,117,101,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,47,47,32,99,97,110,39,116,32,98,101,32,98,111, + 116,104,101,114,101,100,32,105,109,112,108,101,109,101,110,116,105,110,103,32,116,104,105,115,32,102,111,114,32,116,104,101,32,100,101,109,111,33,10,32, + 32,32,32,125,10,10,32,32,32,32,118,111,105,100,32,99,111,110,116,114,111,108,108,101,114,77,111,118,101,100,32,40,99,111,110,115,116,32,105,110, + 116,32,99,111,110,116,114,111,108,108,101,114,78,117,109,98,101,114,44,32,99,111,110,115,116,32,105,110,116,32,110,101,119,86,97,108,117,101,41,10, + 32,32,32,32,123,10,32,32,32,32,32,32,32,32,47,47,32,110,111,116,32,105,110,116,101,114,101,115,116,101,100,32,105,110,32,99,111,110,116,114, + 111,108,108,101,114,115,32,105,110,32,116,104,105,115,32,99,97,115,101,46,10,32,32,32,32,125,10,10,32,32,32,32,118,111,105,100,32,114,101,110, + 100,101,114,78,101,120,116,66,108,111,99,107,32,40,65,117,100,105,111,83,97,109,112,108,101,66,117,102,102,101,114,38,32,111,117,116,112,117,116,66, + 117,102,102,101,114,44,32,105,110,116,32,115,116,97,114,116,83,97,109,112,108,101,44,32,105,110,116,32,110,117,109,83,97,109,112,108,101,115,41,10, + 32,32,32,32,123,10,32,32,32,32,32,32,32,32,105,102,32,40,97,110,103,108,101,68,101,108,116,97,32,33,61,32,48,46,48,41,10,32,32,32, + 32,32,32,32,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,116,97,105,108,79,102,102,32,62,32,48,41,10,32,32,32,32, + 32,32,32,32,32,32,32,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,119,104,105,108,101,32,40,45,45,110,117,109,83,97, + 109,112,108,101,115,32,62,61,32,48,41,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,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,102,108,111,97,116,32,99,117,114,114,101,110,116,83,97,109,112,108,101,32,61,32,40,102, + 108,111,97,116,41,32,40,115,105,110,32,40,99,117,114,114,101,110,116,65,110,103,108,101,41,32,42,32,108,101,118,101,108,32,42,32,116,97,105,108, + 79,102,102,41,59,10,10,32,32,32,32,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, + 111,117,116,112,117,116,66,117,102,102,101,114,46,103,101,116,78,117,109,67,104,97,110,110,101,108,115,40,41,59,32,45,45,105,32,62,61,32,48,59, + 41,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,42,111,117,116,112,117,116,66,117,102,102,101,114,46, + 103,101,116,83,97,109,112,108,101,68,97,116,97,32,40,105,44,32,115,116,97,114,116,83,97,109,112,108,101,41,32,43,61,32,99,117,114,114,101,110, + 116,83,97,109,112,108,101,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,117,114,114,101,110,116,65,110,103, + 108,101,32,43,61,32,97,110,103,108,101,68,101,108,116,97,59,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,43,43, + 115,116,97,114,116,83,97,109,112,108,101,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,97,105,108,79,102, + 102,32,42,61,32,48,46,57,57,59,10,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,116,97,105,108, + 79,102,102,32,60,61,32,48,46,48,48,53,41,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,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,108,101,97,114,67,117,114,114,101,110,116,78,111,116,101,40,41,59,10, + 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,97,110,103,108,101,68,101,108,116,97,32,61,32,48,46, + 48,59,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,98,114,101,97,107,59,10,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,125,10,32,32,32,32,32,32, + 32,32,32,32,32,32,125,10,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,10,32,32,32,32,32,32,32,32,32,32,32,32,123,10,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,119,104,105,108,101,32,40,45,45,110,117,109,83,97,109,112,108,101,115,32,62,61,32,48,41, + 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,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,102,108,111,97,116,32,99,117,114,114,101,110,116,83,97,109,112,108,101,32,61,32,40,102,108,111,97,116,41,32,40,115,105,110,32, + 40,99,117,114,114,101,110,116,65,110,103,108,101,41,32,42,32,108,101,118,101,108,41,59,10,10,32,32,32,32,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,111,117,116,112,117,116,66,117,102,102,101,114,46,103,101,116,78,117,109,67,104, + 97,110,110,101,108,115,40,41,59,32,45,45,105,32,62,61,32,48,59,41,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,42,111,117,116,112,117,116,66,117,102,102,101,114,46,103,101,116,83,97,109,112,108,101,68,97,116,97,32,40,105,44,32,115,116,97, + 114,116,83,97,109,112,108,101,41,32,43,61,32,99,117,114,114,101,110,116,83,97,109,112,108,101,59,10,10,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,99,117,114,114,101,110,116,65,110,103,108,101,32,43,61,32,97,110,103,108,101,68,101,108,116,97,59,10,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,43,43,115,116,97,114,116,83,97,109,112,108,101,59,10,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,125,10,32,32,32,32,32,32,32,32,32,32,32,32,125,10,32,32,32,32,32,32,32,32,125,10,32,32,32,32,125,10, + 10,112,114,105,118,97,116,101,58,10,32,32,32,32,100,111,117,98,108,101,32,99,117,114,114,101,110,116,65,110,103,108,101,44,32,97,110,103,108,101, + 68,101,108,116,97,44,32,108,101,118,101,108,44,32,116,97,105,108,79,102,102,59,10,125,59,10,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,47,42,42,32,84,104, - 105,115,32,105,115,32,97,110,32,97,117,100,105,111,32,115,111,117,114,99,101,32,116,104,97,116,32,115,116,114,101,97,109,115,32,116,104,101,32,111, - 117,116,112,117,116,32,111,102,32,111,117,114,32,100,101,109,111,32,115,121,110,116,104,46,13,10,42,47,13,10,99,108,97,115,115,32,83,121,110,116, - 104,65,117,100,105,111,83,111,117,114,99,101,32,32,58,32,112,117,98,108,105,99,32,65,117,100,105,111,83,111,117,114,99,101,13,10,123,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,10,47,42,42,32,84,104,105,115,32,105,115,32, + 97,110,32,97,117,100,105,111,32,115,111,117,114,99,101,32,116,104,97,116,32,115,116,114,101,97,109,115,32,116,104,101,32,111,117,116,112,117,116,32, + 111,102,32,111,117,114,32,100,101,109,111,32,115,121,110,116,104,46,10,42,47,10,99,108,97,115,115,32,83,121,110,116,104,65,117,100,105,111,83,111, + 117,114,99,101,32,32,58,32,112,117,98,108,105,99,32,65,117,100,105,111,83,111,117,114,99,101,10,123,10,112,117,98,108,105,99,58,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,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,47,47,32,116,104,105,115,32,99,111,108,108,101,99,116,115,32,114,101,97,108,45, - 116,105,109,101,32,109,105,100,105,32,109,101,115,115,97,103,101,115,32,102,114,111,109,32,116,104,101,32,109,105,100,105,32,105,110,112,117,116,32,100, - 101,118,105,99,101,44,32,97,110,100,13,10,32,32,32,32,47,47,32,116,117,114,110,115,32,116,104,101,109,32,105,110,116,111,32,98,108,111,99,107, - 115,32,116,104,97,116,32,119,101,32,99,97,110,32,112,114,111,99,101,115,115,32,105,110,32,111,117,114,32,97,117,100,105,111,32,99,97,108,108,98, - 97,99,107,13,10,32,32,32,32,77,105,100,105,77,101,115,115,97,103,101,67,111,108,108,101,99,116,111,114,32,109,105,100,105,67,111,108,108,101,99, - 116,111,114,59,13,10,13,10,32,32,32,32,47,47,32,116,104,105,115,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,115,116,97,116,101, - 32,111,102,32,119,104,105,99,104,32,107,101,121,115,32,111,110,32,111,117,114,32,111,110,45,115,99,114,101,101,110,32,107,101,121,98,111,97,114,100, - 32,97,114,101,32,104,101,108,100,13,10,32,32,32,32,47,47,32,100,111,119,110,46,32,87,104,101,110,32,116,104,101,32,109,111,117,115,101,32,105, - 115,32,99,108,105,99,107,101,100,32,111,110,32,116,104,101,32,107,101,121,98,111,97,114,100,32,99,111,109,112,111,110,101,110,116,44,32,116,104,105, - 115,32,111,98,106,101,99,116,32,97,108,115,111,13,10,32,32,32,32,47,47,32,103,101,110,101,114,97,116,101,115,32,109,105,100,105,32,109,101,115, - 115,97,103,101,115,32,102,111,114,32,116,104,105,115,44,32,119,104,105,99,104,32,119,101,32,99,97,110,32,112,97,115,115,32,111,110,32,116,111,32, - 111,117,114,32,115,121,110,116,104,46,13,10,32,32,32,32,77,105,100,105,75,101,121,98,111,97,114,100,83,116,97,116,101,32,107,101,121,98,111,97, - 114,100,83,116,97,116,101,59,13,10,13,10,32,32,32,32,47,47,32,116,104,101,32,115,121,110,116,104,32,105,116,115,101,108,102,33,13,10,32,32, - 32,32,83,121,110,116,104,101,115,105,115,101,114,32,115,121,110,116,104,59,13,10,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61, + 61,10,32,32,32,32,47,47,32,116,104,105,115,32,99,111,108,108,101,99,116,115,32,114,101,97,108,45,116,105,109,101,32,109,105,100,105,32,109,101, + 115,115,97,103,101,115,32,102,114,111,109,32,116,104,101,32,109,105,100,105,32,105,110,112,117,116,32,100,101,118,105,99,101,44,32,97,110,100,10,32, + 32,32,32,47,47,32,116,117,114,110,115,32,116,104,101,109,32,105,110,116,111,32,98,108,111,99,107,115,32,116,104,97,116,32,119,101,32,99,97,110, + 32,112,114,111,99,101,115,115,32,105,110,32,111,117,114,32,97,117,100,105,111,32,99,97,108,108,98,97,99,107,10,32,32,32,32,77,105,100,105,77, + 101,115,115,97,103,101,67,111,108,108,101,99,116,111,114,32,109,105,100,105,67,111,108,108,101,99,116,111,114,59,10,10,32,32,32,32,47,47,32,116, + 104,105,115,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,115,116,97,116,101,32,111,102,32,119,104,105,99,104,32,107,101,121,115,32,111, + 110,32,111,117,114,32,111,110,45,115,99,114,101,101,110,32,107,101,121,98,111,97,114,100,32,97,114,101,32,104,101,108,100,10,32,32,32,32,47,47, + 32,100,111,119,110,46,32,87,104,101,110,32,116,104,101,32,109,111,117,115,101,32,105,115,32,99,108,105,99,107,101,100,32,111,110,32,116,104,101,32, + 107,101,121,98,111,97,114,100,32,99,111,109,112,111,110,101,110,116,44,32,116,104,105,115,32,111,98,106,101,99,116,32,97,108,115,111,10,32,32,32, + 32,47,47,32,103,101,110,101,114,97,116,101,115,32,109,105,100,105,32,109,101,115,115,97,103,101,115,32,102,111,114,32,116,104,105,115,44,32,119,104, + 105,99,104,32,119,101,32,99,97,110,32,112,97,115,115,32,111,110,32,116,111,32,111,117,114,32,115,121,110,116,104,46,10,32,32,32,32,77,105,100, + 105,75,101,121,98,111,97,114,100,83,116,97,116,101,32,107,101,121,98,111,97,114,100,83,116,97,116,101,59,10,10,32,32,32,32,47,47,32,116,104, + 101,32,115,121,110,116,104,32,105,116,115,101,108,102,33,10,32,32,32,32,83,121,110,116,104,101,115,105,115,101,114,32,115,121,110,116,104,59,10,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,61,61,61,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,83,121,110,116,104,65, - 117,100,105,111,83,111,117,114,99,101,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,119,101,39,108,108,32,98,101, - 32,109,105,120,105,110,103,32,116,119,111,32,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,32,111,102,32,115,111,117,110,100,44,32,115,111, - 32,104,101,114,101,32,119,101,39,108,108,32,99,114,101,97,116,101,32,116,119,111,13,10,32,32,32,32,32,32,32,32,47,47,32,115,101,116,115,32, - 111,102,32,110,111,116,101,32,109,97,112,115,44,32,112,117,116,116,105,110,103,32,101,97,99,104,32,115,111,117,110,100,32,111,110,32,97,32,100,105, - 102,102,101,114,101,110,116,32,111,99,116,97,118,101,32,111,102,32,116,104,101,32,107,101,121,98,111,97,114,100,58,13,10,32,32,32,32,32,32,32, - 32,66,105,116,65,114,114,97,121,32,115,105,110,101,119,97,118,101,78,111,116,101,115,44,32,115,97,109,112,108,101,114,78,111,116,101,115,59,13,10, - 13,10,32,32,32,32,32,32,32,32,105,110,116,32,105,59,13,10,32,32,32,32,32,32,32,32,102,111,114,32,40,105,32,61,32,48,59,32,105,32, - 60,32,49,50,56,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,105,102,32,40, - 40,40,105,32,47,32,49,50,41,32,38,32,49,41,32,33,61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,115,105, - 110,101,119,97,118,101,78,111,116,101,115,46,115,101,116,66,105,116,32,40,105,41,59,13,10,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,115,97,109,112,108,101,114,78,111,116,101,115,46,115,101,116,66,105,116,32,40, - 105,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,47,47,32,97,100,100,32,97,32,119,97,118,101,32, + 61,61,61,61,10,32,32,32,32,83,121,110,116,104,65,117,100,105,111,83,111,117,114,99,101,40,41,10,32,32,32,32,123,10,32,32,32,32,32,32, + 32,32,47,47,32,119,101,39,108,108,32,98,101,32,109,105,120,105,110,103,32,116,119,111,32,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115, + 32,111,102,32,115,111,117,110,100,44,32,115,111,32,104,101,114,101,32,119,101,39,108,108,32,99,114,101,97,116,101,32,116,119,111,10,32,32,32,32, + 32,32,32,32,47,47,32,115,101,116,115,32,111,102,32,110,111,116,101,32,109,97,112,115,44,32,112,117,116,116,105,110,103,32,101,97,99,104,32,115, + 111,117,110,100,32,111,110,32,97,32,100,105,102,102,101,114,101,110,116,32,111,99,116,97,118,101,32,111,102,32,116,104,101,32,107,101,121,98,111,97, + 114,100,58,10,32,32,32,32,32,32,32,32,66,105,116,65,114,114,97,121,32,115,105,110,101,119,97,118,101,78,111,116,101,115,44,32,115,97,109,112, + 108,101,114,78,111,116,101,115,59,10,10,32,32,32,32,32,32,32,32,105,110,116,32,105,59,10,32,32,32,32,32,32,32,32,102,111,114,32,40,105, + 32,61,32,48,59,32,105,32,60,32,49,50,56,59,32,43,43,105,41,10,32,32,32,32,32,32,32,32,123,10,32,32,32,32,32,32,32,32,32,32, + 32,32,105,102,32,40,40,40,105,32,47,32,49,50,41,32,38,32,49,41,32,33,61,32,48,41,10,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,115,105,110,101,119,97,118,101,78,111,116,101,115,46,115,101,116,66,105,116,32,40,105,41,59,10,32,32,32,32,32,32,32,32,32,32,32, + 32,101,108,115,101,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,115,97,109,112,108,101,114,78,111,116,101,115,46,115,101,116,66,105, + 116,32,40,105,41,59,10,32,32,32,32,32,32,32,32,125,10,10,32,32,32,32,32,32,32,32,47,47,32,97,100,100,32,97,32,119,97,118,101,32, 115,111,117,110,100,44,32,119,104,105,99,104,32,119,105,108,108,32,103,101,116,32,97,112,112,108,105,101,100,32,116,111,32,115,111,109,101,32,111,102, - 32,116,104,101,32,110,111,116,101,115,46,46,13,10,32,32,32,32,32,32,32,32,115,121,110,116,104,46,97,100,100,83,111,117,110,100,32,40,110,101, - 119,32,83,105,110,101,87,97,118,101,83,111,117,110,100,32,40,115,105,110,101,119,97,118,101,78,111,116,101,115,41,41,59,13,10,13,10,32,32,32, - 32,32,32,32,32,47,47,32,103,105,118,101,32,111,117,114,32,115,121,110,116,104,32,97,32,102,101,119,32,118,111,105,99,101,115,32,116,104,97,116, - 32,99,97,110,32,112,108,97,121,32,116,104,101,32,119,97,118,101,32,115,111,117,110,100,46,46,13,10,32,32,32,32,32,32,32,32,102,111,114,32, - 40,105,32,61,32,52,59,32,45,45,105,32,62,61,32,48,59,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,121,110,116,104,46,97,100, - 100,86,111,105,99,101,32,40,110,101,119,32,83,105,110,101,87,97,118,101,86,111,105,99,101,40,41,41,59,13,10,13,10,32,32,32,32,32,32,32, - 32,87,97,118,65,117,100,105,111,70,111,114,109,97,116,32,119,97,118,70,111,114,109,97,116,59,13,10,32,32,32,32,32,32,32,32,65,117,100,105, - 111,70,111,114,109,97,116,82,101,97,100,101,114,42,32,97,117,100,105,111,82,101,97,100,101,114,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 61,32,119,97,118,70,111,114,109,97,116,46,99,114,101,97,116,101,82,101,97,100,101,114,70,111,114,32,40,110,101,119,32,77,101,109,111,114,121,73, - 110,112,117,116,83,116,114,101,97,109,32,40,66,105,110,97,114,121,68,97,116,97,58,58,99,101,108,108,111,95,119,97,118,44,13,10,32,32,32,32, + 32,116,104,101,32,110,111,116,101,115,46,46,10,32,32,32,32,32,32,32,32,115,121,110,116,104,46,97,100,100,83,111,117,110,100,32,40,110,101,119, + 32,83,105,110,101,87,97,118,101,83,111,117,110,100,32,40,115,105,110,101,119,97,118,101,78,111,116,101,115,41,41,59,10,10,32,32,32,32,32,32, + 32,32,47,47,32,103,105,118,101,32,111,117,114,32,115,121,110,116,104,32,97,32,102,101,119,32,118,111,105,99,101,115,32,116,104,97,116,32,99,97, + 110,32,112,108,97,121,32,116,104,101,32,119,97,118,101,32,115,111,117,110,100,46,46,10,32,32,32,32,32,32,32,32,102,111,114,32,40,105,32,61, + 32,52,59,32,45,45,105,32,62,61,32,48,59,41,10,32,32,32,32,32,32,32,32,32,32,32,32,115,121,110,116,104,46,97,100,100,86,111,105,99, + 101,32,40,110,101,119,32,83,105,110,101,87,97,118,101,86,111,105,99,101,40,41,41,59,10,10,32,32,32,32,32,32,32,32,87,97,118,65,117,100, + 105,111,70,111,114,109,97,116,32,119,97,118,70,111,114,109,97,116,59,10,32,32,32,32,32,32,32,32,65,117,100,105,111,70,111,114,109,97,116,82, + 101,97,100,101,114,42,32,97,117,100,105,111,82,101,97,100,101,114,10,32,32,32,32,32,32,32,32,32,32,32,32,61,32,119,97,118,70,111,114,109, + 97,116,46,99,114,101,97,116,101,82,101,97,100,101,114,70,111,114,32,40,110,101,119,32,77,101,109,111,114,121,73,110,112,117,116,83,116,114,101,97, + 109,32,40,66,105,110,97,114,121,68,97,116,97,58,58,99,101,108,108,111,95,119,97,118,44,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,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,66,105,110,97,114,121,68,97,116,97,58,58,99,101,108,108,111,95,119,97, - 118,83,105,122,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,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,102,97,108,115,101,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,116,114,117,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,115,121,110,116,104,46,97,100,100,83,111,117,110,100,32,40,110,101,119,32, - 83,97,109,112,108,101,114,83,111,117,110,100,32,40,84,40,34,100,101,109,111,32,115,111,117,110,100,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,42,97,117,100,105,111, - 82,101,97,100,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,32,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,115,97,109,112,108,101,114,78,111,116,101,115,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,55,52,44,32,32,32,47,47,32,114,111,111, - 116,32,109,105,100,105,32,110,111,116,101,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,48,46,49,44,32,32,47,47,32,97,116,116,97,99,107,32,116,105,109,101,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,48, - 46,49,44,32,32,47,47,32,114,101,108,101,97,115,101,32,116,105,109,101,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,49,48,46,48,32,32,47,47,32,109,97,120,105,109,117,109, - 32,115,97,109,112,108,101,32,108,101,110,103,116,104,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,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,32, - 97,117,100,105,111,82,101,97,100,101,114,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,97,110,100,32,103,105,118,101,32,116,104,101,32, - 115,121,110,116,104,32,115,111,109,101,32,115,97,109,112,108,101,114,32,118,111,105,99,101,115,32,116,111,32,112,108,97,121,32,116,104,101,32,115,97, - 109,112,108,101,100,32,115,111,117,110,100,46,46,13,10,32,32,32,32,32,32,32,32,102,111,114,32,40,105,32,61,32,52,59,32,45,45,105,32,62, - 61,32,48,59,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,121,110,116,104,46,97,100,100,86,111,105,99,101,32,40,110,101,119,32,83, - 97,109,112,108,101,114,86,111,105,99,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,112,114,101,112,97, - 114,101,84,111,80,108,97,121,32,40,105,110,116,32,115,97,109,112,108,101,115,80,101,114,66,108,111,99,107,69,120,112,101,99,116,101,100,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,100,111,117,98,108,101,32,115,97,109,112,108,101,82,97,116, - 101,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,109,105,100,105,67,111,108,108,101,99,116,111,114,46,114,101,115,101,116,32,40, - 115,97,109,112,108,101,82,97,116,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,115,121,110,116,104,46,115,101,116,67,117,114,114,101,110,116, - 80,108,97,121,98,97,99,107,83,97,109,112,108,101,82,97,116,101,32,40,115,97,109,112,108,101,82,97,116,101,41,59,13,10,32,32,32,32,125,13, - 10,13,10,32,32,32,32,118,111,105,100,32,114,101,108,101,97,115,101,82,101,115,111,117,114,99,101,115,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,78,101,120,116,65,117,100,105,111,66,108,111,99,107,32,40,99,111,110,115, - 116,32,65,117,100,105,111,83,111,117,114,99,101,67,104,97,110,110,101,108,73,110,102,111,38,32,98,117,102,102,101,114,84,111,70,105,108,108,41,13, - 10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,116,104,101,32,115,121,110,116,104,32,97,108,119,97,121,115,32,97,100,100,115, - 32,105,116,115,32,111,117,116,112,117,116,32,116,111,32,116,104,101,32,97,117,100,105,111,32,98,117,102,102,101,114,44,32,115,111,32,119,101,32,104, - 97,118,101,32,116,111,32,99,108,101,97,114,32,105,116,13,10,32,32,32,32,32,32,32,32,47,47,32,102,105,114,115,116,46,46,13,10,32,32,32, - 32,32,32,32,32,98,117,102,102,101,114,84,111,70,105,108,108,46,99,108,101,97,114,65,99,116,105,118,101,66,117,102,102,101,114,82,101,103,105,111, - 110,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,102,105,108,108,32,97,32,109,105,100,105,32,98,117,102,102,101,114,32,119,105, - 116,104,32,105,110,99,111,109,105,110,103,32,109,101,115,115,97,103,101,115,32,102,114,111,109,32,116,104,101,32,109,105,100,105,32,105,110,112,117,116, - 46,13,10,32,32,32,32,32,32,32,32,77,105,100,105,66,117,102,102,101,114,32,105,110,99,111,109,105,110,103,77,105,100,105,59,13,10,32,32,32, - 32,32,32,32,32,109,105,100,105,67,111,108,108,101,99,116,111,114,46,114,101,109,111,118,101,78,101,120,116,66,108,111,99,107,79,102,77,101,115,115, - 97,103,101,115,32,40,105,110,99,111,109,105,110,103,77,105,100,105,44,32,98,117,102,102,101,114,84,111,70,105,108,108,46,110,117,109,83,97,109,112, - 108,101,115,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,112,97,115,115,32,116,104,101,115,101,32,109,101,115,115,97,103,101,115,32, - 116,111,32,116,104,101,32,107,101,121,98,111,97,114,100,32,115,116,97,116,101,32,115,111,32,116,104,97,116,32,105,116,32,99,97,110,32,117,112,100, - 97,116,101,32,116,104,101,32,99,111,109,112,111,110,101,110,116,13,10,32,32,32,32,32,32,32,32,47,47,32,116,111,32,115,104,111,119,32,111,110, - 45,115,99,114,101,101,110,32,119,104,105,99,104,32,107,101,121,115,32,97,114,101,32,98,101,105,110,103,32,112,114,101,115,115,101,100,32,111,110,32, - 116,104,101,32,112,104,121,115,105,99,97,108,32,109,105,100,105,32,107,101,121,98,111,97,114,100,46,13,10,32,32,32,32,32,32,32,32,47,47,32, - 84,104,105,115,32,99,97,108,108,32,119,105,108,108,32,97,108,115,111,32,97,100,100,32,109,105,100,105,32,109,101,115,115,97,103,101,115,32,116,111, - 32,116,104,101,32,98,117,102,102,101,114,32,119,104,105,99,104,32,119,101,114,101,32,103,101,110,101,114,97,116,101,100,32,98,121,13,10,32,32,32, - 32,32,32,32,32,47,47,32,116,104,101,32,109,111,117,115,101,45,99,108,105,99,107,105,110,103,32,111,110,32,116,104,101,32,111,110,45,115,99,114, - 101,101,110,32,107,101,121,98,111,97,114,100,46,13,10,32,32,32,32,32,32,32,32,107,101,121,98,111,97,114,100,83,116,97,116,101,46,112,114,111, - 99,101,115,115,78,101,120,116,77,105,100,105,66,117,102,102,101,114,32,40,105,110,99,111,109,105,110,103,77,105,100,105,44,32,48,44,32,98,117,102, - 102,101,114,84,111,70,105,108,108,46,110,117,109,83,97,109,112,108,101,115,44,32,116,114,117,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32, - 47,47,32,97,110,100,32,110,111,119,32,103,101,116,32,116,104,101,32,115,121,110,116,104,32,116,111,32,112,114,111,99,101,115,115,32,116,104,101,32, - 109,105,100,105,32,101,118,101,110,116,115,32,97,110,100,32,103,101,110,101,114,97,116,101,32,105,116,115,32,111,117,116,112,117,116,46,13,10,32,32, - 32,32,32,32,32,32,115,121,110,116,104,46,114,101,110,100,101,114,78,101,120,116,66,108,111,99,107,32,40,42,98,117,102,102,101,114,84,111,70,105, - 108,108,46,98,117,102,102,101,114,44,32,105,110,99,111,109,105,110,103,77,105,100,105,44,32,48,44,32,98,117,102,102,101,114,84,111,70,105,108,108, - 46,110,117,109,83,97,109,112,108,101,115,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, + 32,32,32,32,32,32,32,32,32,32,66,105,110,97,114,121,68,97,116,97,58,58,99,101,108,108,111,95,119,97,118,83,105,122,101,44,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,32,32,32,32,32,102,97,108,115,101,41,44,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,116,114,117,101,41,59,10,10,32,32, + 32,32,32,32,32,32,115,121,110,116,104,46,97,100,100,83,111,117,110,100,32,40,110,101,119,32,83,97,109,112,108,101,114,83,111,117,110,100,32,40, + 84,40,34,100,101,109,111,32,115,111,117,110,100,34,41,44,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,42,97,117,100,105,111,82,101,97,100,101,114,44,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,115,97,109,112,108, + 101,114,78,111,116,101,115,44,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,55,52,44,32,32,32,47,47,32,114,111,111,116,32,109,105,100,105,32,110,111,116,101,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,48,46,49, + 44,32,32,47,47,32,97,116,116,97,99,107,32,116,105,109,101,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,48,46,49,44,32,32,47,47,32,114,101,108,101,97,115,101,32,116,105,109, + 101,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,49,48,46,48,32,32,47,47,32,109,97,120,105,109,117,109,32,115,97,109,112,108,101,32,108,101,110,103,116,104,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,41,41,59, + 10,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,32,97,117,100,105,111,82,101,97,100,101,114,59,10,10,32,32,32,32,32,32,32,32,47, + 47,32,97,110,100,32,103,105,118,101,32,116,104,101,32,115,121,110,116,104,32,115,111,109,101,32,115,97,109,112,108,101,114,32,118,111,105,99,101,115, + 32,116,111,32,112,108,97,121,32,116,104,101,32,115,97,109,112,108,101,100,32,115,111,117,110,100,46,46,10,32,32,32,32,32,32,32,32,102,111,114, + 32,40,105,32,61,32,52,59,32,45,45,105,32,62,61,32,48,59,41,10,32,32,32,32,32,32,32,32,32,32,32,32,115,121,110,116,104,46,97,100, + 100,86,111,105,99,101,32,40,110,101,119,32,83,97,109,112,108,101,114,86,111,105,99,101,40,41,41,59,10,32,32,32,32,125,10,10,32,32,32,32, + 118,111,105,100,32,112,114,101,112,97,114,101,84,111,80,108,97,121,32,40,105,110,116,32,115,97,109,112,108,101,115,80,101,114,66,108,111,99,107,69, + 120,112,101,99,116,101,100,44,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,111,117,98,108,101,32, + 115,97,109,112,108,101,82,97,116,101,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,109,105,100,105,67,111,108,108,101,99,116,111,114,46, + 114,101,115,101,116,32,40,115,97,109,112,108,101,82,97,116,101,41,59,10,10,32,32,32,32,32,32,32,32,115,121,110,116,104,46,115,101,116,67,117, + 114,114,101,110,116,80,108,97,121,98,97,99,107,83,97,109,112,108,101,82,97,116,101,32,40,115,97,109,112,108,101,82,97,116,101,41,59,10,32,32, + 32,32,125,10,10,32,32,32,32,118,111,105,100,32,114,101,108,101,97,115,101,82,101,115,111,117,114,99,101,115,40,41,10,32,32,32,32,123,10,32, + 32,32,32,125,10,10,32,32,32,32,118,111,105,100,32,103,101,116,78,101,120,116,65,117,100,105,111,66,108,111,99,107,32,40,99,111,110,115,116,32, + 65,117,100,105,111,83,111,117,114,99,101,67,104,97,110,110,101,108,73,110,102,111,38,32,98,117,102,102,101,114,84,111,70,105,108,108,41,10,32,32, + 32,32,123,10,32,32,32,32,32,32,32,32,47,47,32,116,104,101,32,115,121,110,116,104,32,97,108,119,97,121,115,32,97,100,100,115,32,105,116,115, + 32,111,117,116,112,117,116,32,116,111,32,116,104,101,32,97,117,100,105,111,32,98,117,102,102,101,114,44,32,115,111,32,119,101,32,104,97,118,101,32, + 116,111,32,99,108,101,97,114,32,105,116,10,32,32,32,32,32,32,32,32,47,47,32,102,105,114,115,116,46,46,10,32,32,32,32,32,32,32,32,98, + 117,102,102,101,114,84,111,70,105,108,108,46,99,108,101,97,114,65,99,116,105,118,101,66,117,102,102,101,114,82,101,103,105,111,110,40,41,59,10,10, + 32,32,32,32,32,32,32,32,47,47,32,102,105,108,108,32,97,32,109,105,100,105,32,98,117,102,102,101,114,32,119,105,116,104,32,105,110,99,111,109, + 105,110,103,32,109,101,115,115,97,103,101,115,32,102,114,111,109,32,116,104,101,32,109,105,100,105,32,105,110,112,117,116,46,10,32,32,32,32,32,32, + 32,32,77,105,100,105,66,117,102,102,101,114,32,105,110,99,111,109,105,110,103,77,105,100,105,59,10,32,32,32,32,32,32,32,32,109,105,100,105,67, + 111,108,108,101,99,116,111,114,46,114,101,109,111,118,101,78,101,120,116,66,108,111,99,107,79,102,77,101,115,115,97,103,101,115,32,40,105,110,99,111, + 109,105,110,103,77,105,100,105,44,32,98,117,102,102,101,114,84,111,70,105,108,108,46,110,117,109,83,97,109,112,108,101,115,41,59,10,10,32,32,32, + 32,32,32,32,32,47,47,32,112,97,115,115,32,116,104,101,115,101,32,109,101,115,115,97,103,101,115,32,116,111,32,116,104,101,32,107,101,121,98,111, + 97,114,100,32,115,116,97,116,101,32,115,111,32,116,104,97,116,32,105,116,32,99,97,110,32,117,112,100,97,116,101,32,116,104,101,32,99,111,109,112, + 111,110,101,110,116,10,32,32,32,32,32,32,32,32,47,47,32,116,111,32,115,104,111,119,32,111,110,45,115,99,114,101,101,110,32,119,104,105,99,104, + 32,107,101,121,115,32,97,114,101,32,98,101,105,110,103,32,112,114,101,115,115,101,100,32,111,110,32,116,104,101,32,112,104,121,115,105,99,97,108,32, + 109,105,100,105,32,107,101,121,98,111,97,114,100,46,10,32,32,32,32,32,32,32,32,47,47,32,84,104,105,115,32,99,97,108,108,32,119,105,108,108, + 32,97,108,115,111,32,97,100,100,32,109,105,100,105,32,109,101,115,115,97,103,101,115,32,116,111,32,116,104,101,32,98,117,102,102,101,114,32,119,104, + 105,99,104,32,119,101,114,101,32,103,101,110,101,114,97,116,101,100,32,98,121,10,32,32,32,32,32,32,32,32,47,47,32,116,104,101,32,109,111,117, + 115,101,45,99,108,105,99,107,105,110,103,32,111,110,32,116,104,101,32,111,110,45,115,99,114,101,101,110,32,107,101,121,98,111,97,114,100,46,10,32, + 32,32,32,32,32,32,32,107,101,121,98,111,97,114,100,83,116,97,116,101,46,112,114,111,99,101,115,115,78,101,120,116,77,105,100,105,66,117,102,102, + 101,114,32,40,105,110,99,111,109,105,110,103,77,105,100,105,44,32,48,44,32,98,117,102,102,101,114,84,111,70,105,108,108,46,110,117,109,83,97,109, + 112,108,101,115,44,32,116,114,117,101,41,59,10,10,32,32,32,32,32,32,32,32,47,47,32,97,110,100,32,110,111,119,32,103,101,116,32,116,104,101, + 32,115,121,110,116,104,32,116,111,32,112,114,111,99,101,115,115,32,116,104,101,32,109,105,100,105,32,101,118,101,110,116,115,32,97,110,100,32,103,101, + 110,101,114,97,116,101,32,105,116,115,32,111,117,116,112,117,116,46,10,32,32,32,32,32,32,32,32,115,121,110,116,104,46,114,101,110,100,101,114,78, + 101,120,116,66,108,111,99,107,32,40,42,98,117,102,102,101,114,84,111,70,105,108,108,46,98,117,102,102,101,114,44,32,105,110,99,111,109,105,110,103, + 77,105,100,105,44,32,48,44,32,98,117,102,102,101,114,84,111,70,105,108,108,46,110,117,109,83,97,109,112,108,101,115,41,59,10,32,32,32,32,125, + 10,125,59,10,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,61,61,61,61,61,61,61,61,61,61,13,10,99,108,97,115,115,32,65,117,100,105, - 111,73,110,112,117,116,87,97,118,101,102,111,114,109,68,105,115,112,108,97,121,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,32,32,32,32,32,32,32,32,32,112, - 117,98,108,105,99,32,84,105,109,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, - 32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,65,117,100,105,111,73,79,68,101,118,105,99,101,67,97,108,108,98,97,99,107,13,10,123, - 13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,65,117,100,105,111,73,110,112,117,116,87,97,118,101,102,111,114,109,68,105,115,112,108,97,121, - 40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,98,117,102,102,101,114,80,111,115,32,61,32,48,59,13,10,32,32,32,32,32, - 32,32,32,98,117,102,102,101,114,83,105,122,101,32,61,32,50,48,52,56,59,13,10,32,32,32,32,32,32,32,32,99,105,114,99,117,108,97,114,66, - 117,102,102,101,114,32,61,32,40,102,108,111,97,116,42,41,32,106,117,99,101,95,99,97,108,108,111,99,32,40,115,105,122,101,111,102,32,40,102,108, - 111,97,116,41,32,42,32,98,117,102,102,101,114,83,105,122,101,41,59,13,10,32,32,32,32,32,32,32,32,99,117,114,114,101,110,116,73,110,112,117, - 116,76,101,118,101,108,32,61,32,48,46,48,102,59,13,10,32,32,32,32,32,32,32,32,110,117,109,83,97,109,112,108,101,115,73,110,32,61,32,48, - 59,13,10,13,10,32,32,32,32,32,32,32,32,115,101,116,79,112,97,113,117,101,32,40,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32, - 115,116,97,114,116,84,105,109,101,114,32,40,49,48,48,48,32,47,32,53,48,41,59,32,32,47,47,32,114,101,112,97,105,110,116,32,101,118,101,114, - 121,32,49,47,53,48,32,111,102,32,97,32,115,101,99,111,110,100,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,65,117,100,105,111,73, - 110,112,117,116,87,97,118,101,102,111,114,109,68,105,115,112,108,97,121,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,106,117, - 99,101,95,102,114,101,101,32,40,99,105,114,99,117,108,97,114,66,117,102,102,101,114,41,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,98,108,97,99,107,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,108,105,103,104,116,103,114,101,101,110,41,59,13,10,13,10,32,32,32,32, - 32,32,32,32,99,111,110,115,116,32,102,108,111,97,116,32,104,97,108,102,72,101,105,103,104,116,32,61,32,103,101,116,72,101,105,103,104,116,40,41, - 32,42,32,48,46,53,102,59,13,10,13,10,32,32,32,32,32,32,32,32,105,110,116,32,98,112,32,61,32,98,117,102,102,101,114,80,111,115,59,13, - 10,13,10,32,32,32,32,32,32,32,32,102,111,114,32,40,105,110,116,32,120,32,61,32,103,101,116,87,105,100,116,104,40,41,59,32,45,45,120,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,99,111,110,115,116,32,105,110,116, - 32,115,97,109,112,108,101,115,65,103,111,32,61,32,103,101,116,87,105,100,116,104,40,41,32,45,32,120,59,13,10,32,32,32,32,32,32,32,32,32, - 32,32,32,99,111,110,115,116,32,102,108,111,97,116,32,108,101,118,101,108,32,61,32,99,105,114,99,117,108,97,114,66,117,102,102,101,114,32,91,40, - 98,112,32,43,32,98,117,102,102,101,114,83,105,122,101,32,45,32,115,97,109,112,108,101,115,65,103,111,41,32,37,32,98,117,102,102,101,114,83,105, - 122,101,93,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,108,101,118,101,108,32,62,32,48,46,48,49,102,41,13,10, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,103,46,100,114,97,119,76,105,110,101,32,40,40,102,108,111,97,116,41,32,120,44,32,104, - 97,108,102,72,101,105,103,104,116,32,45,32,104,97,108,102,72,101,105,103,104,116,32,42,32,108,101,118,101,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,40,102,108,111,97,116,41,32,120,44,32,104,97,108,102,72,101,105,103, - 104,116,32,43,32,104,97,108,102,72,101,105,103,104,116,32,42,32,108,101,118,101,108,41,59,13,10,32,32,32,32,32,32,32,32,125,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,114,101,112,97,105,110,116,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,97,100, - 100,83,97,109,112,108,101,32,40,99,111,110,115,116,32,102,108,111,97,116,32,115,97,109,112,108,101,41,13,10,32,32,32,32,123,13,10,32,32,32, - 32,32,32,32,32,99,117,114,114,101,110,116,73,110,112,117,116,76,101,118,101,108,32,43,61,32,102,97,98,115,102,32,40,115,97,109,112,108,101,41, - 59,13,10,13,10,32,32,32,32,32,32,32,32,99,111,110,115,116,32,105,110,116,32,115,97,109,112,108,101,115,84,111,65,118,101,114,97,103,101,32, - 61,32,49,50,56,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,43,43,110,117,109,83,97,109,112,108,101,115,73,110,32,62,32,115, - 97,109,112,108,101,115,84,111,65,118,101,114,97,103,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,99,105,114,99,117,108,97,114,66,117,102,102,101,114,32,91,98,117,102,102,101,114,80,111,115,43,43,32,37,32,98,117,102,102,101,114,83,105,122, - 101,93,32,61,32,99,117,114,114,101,110,116,73,110,112,117,116,76,101,118,101,108,32,47,32,115,97,109,112,108,101,115,84,111,65,118,101,114,97,103, - 101,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,110,117,109,83,97,109,112,108,101,115,73,110,32,61,32,48,59,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,99,117,114,114,101,110,116,73,110,112,117,116,76,101,118,101,108,32,61,32,48,46,48,102,59,13,10,32,32,32,32, - 32,32,32,32,125,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,97,117,100,105,111,68,101,118,105,99,101,73,79,67,97, - 108,108,98,97,99,107,32,40,99,111,110,115,116,32,102,108,111,97,116,42,42,32,105,110,112,117,116,67,104,97,110,110,101,108,68,97,116,97,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,105,110,116,32,116,111,116, - 97,108,78,117,109,73,110,112,117,116,67,104,97,110,110,101,108,115,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,102,108,111,97,116,42,42,32,111,117,116,112,117,116,67,104,97,110,110,101,108,68,97,116,97,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,105,110,116,32,116,111,116, - 97,108,78,117,109,79,117,116,112,117,116,67,104,97,110,110,101,108,115,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,105,110,116,32,110,117,109,83,97,109,112,108,101,115,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,48,59,32,105,32,60,32,116,111,116,97,108,78,117,109,73,110,112,117,116,67, - 104,97,110,110,101,108,115,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,105,102, - 32,40,105,110,112,117,116,67,104,97,110,110,101,108,68,97,116,97,32,91,105,93,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,102,111,114,32,40,105,110,116,32,106,32,61,32,48,59,32,106,32,60, - 32,110,117,109,83,97,109,112,108,101,115,59,32,43,43,106,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,97, - 100,100,83,97,109,112,108,101,32,40,105,110,112,117,116,67,104,97,110,110,101,108,68,97,116,97,32,91,105,93,91,106,93,41,59,13,10,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,32,32, - 32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,97,117,100,105,111,68,101,118,105,99,101,65,98, - 111,117,116,84,111,83,116,97,114,116,32,40,65,117,100,105,111,73,79,68,101,118,105,99,101,42,41,13,10,32,32,32,32,123,13,10,32,32,32,32, + 61,61,61,61,61,10,99,108,97,115,115,32,65,117,100,105,111,73,110,112,117,116,87,97,118,101,102,111,114,109,68,105,115,112,108,97,121,32,32,58, + 32,112,117,98,108,105,99,32,67,111,109,112,111,110,101,110,116,44,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,112,117,98,108,105,99,32,84,105,109,101,114,44,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,112,117,98,108,105,99,32,65,117,100,105,111,73,79,68,101,118, + 105,99,101,67,97,108,108,98,97,99,107,10,123,10,112,117,98,108,105,99,58,10,32,32,32,32,65,117,100,105,111,73,110,112,117,116,87,97,118,101, + 102,111,114,109,68,105,115,112,108,97,121,40,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,98,117,102,102,101,114,80,111,115,32,61,32, + 48,59,10,32,32,32,32,32,32,32,32,98,117,102,102,101,114,83,105,122,101,32,61,32,50,48,52,56,59,10,32,32,32,32,32,32,32,32,99,105, + 114,99,117,108,97,114,66,117,102,102,101,114,32,61,32,40,102,108,111,97,116,42,41,32,106,117,99,101,95,99,97,108,108,111,99,32,40,115,105,122, + 101,111,102,32,40,102,108,111,97,116,41,32,42,32,98,117,102,102,101,114,83,105,122,101,41,59,10,32,32,32,32,32,32,32,32,99,117,114,114,101, + 110,116,73,110,112,117,116,76,101,118,101,108,32,61,32,48,46,48,102,59,10,32,32,32,32,32,32,32,32,110,117,109,83,97,109,112,108,101,115,73, + 110,32,61,32,48,59,10,10,32,32,32,32,32,32,32,32,115,101,116,79,112,97,113,117,101,32,40,116,114,117,101,41,59,10,32,32,32,32,32,32, + 32,32,115,116,97,114,116,84,105,109,101,114,32,40,49,48,48,48,32,47,32,53,48,41,59,32,32,47,47,32,114,101,112,97,105,110,116,32,101,118, + 101,114,121,32,49,47,53,48,32,111,102,32,97,32,115,101,99,111,110,100,10,32,32,32,32,125,10,10,32,32,32,32,126,65,117,100,105,111,73,110, + 112,117,116,87,97,118,101,102,111,114,109,68,105,115,112,108,97,121,40,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,106,117,99,101,95, + 102,114,101,101,32,40,99,105,114,99,117,108,97,114,66,117,102,102,101,114,41,59,10,32,32,32,32,125,10,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,10,32,32,32,32,123,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,98,108,97,99,107,41,59,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,108,105,103,104,116,103,114,101,101,110,41,59,10,10,32,32,32,32,32,32,32,32,99,111,110,115,116,32,102, + 108,111,97,116,32,104,97,108,102,72,101,105,103,104,116,32,61,32,103,101,116,72,101,105,103,104,116,40,41,32,42,32,48,46,53,102,59,10,10,32, + 32,32,32,32,32,32,32,105,110,116,32,98,112,32,61,32,98,117,102,102,101,114,80,111,115,59,10,10,32,32,32,32,32,32,32,32,102,111,114,32, + 40,105,110,116,32,120,32,61,32,103,101,116,87,105,100,116,104,40,41,59,32,45,45,120,32,62,61,32,48,59,41,10,32,32,32,32,32,32,32,32, + 123,10,32,32,32,32,32,32,32,32,32,32,32,32,99,111,110,115,116,32,105,110,116,32,115,97,109,112,108,101,115,65,103,111,32,61,32,103,101,116, + 87,105,100,116,104,40,41,32,45,32,120,59,10,32,32,32,32,32,32,32,32,32,32,32,32,99,111,110,115,116,32,102,108,111,97,116,32,108,101,118, + 101,108,32,61,32,99,105,114,99,117,108,97,114,66,117,102,102,101,114,32,91,40,98,112,32,43,32,98,117,102,102,101,114,83,105,122,101,32,45,32, + 115,97,109,112,108,101,115,65,103,111,41,32,37,32,98,117,102,102,101,114,83,105,122,101,93,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32, + 105,102,32,40,108,101,118,101,108,32,62,32,48,46,48,49,102,41,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,103,46,100,114,97, + 119,76,105,110,101,32,40,40,102,108,111,97,116,41,32,120,44,32,104,97,108,102,72,101,105,103,104,116,32,45,32,104,97,108,102,72,101,105,103,104, + 116,32,42,32,108,101,118,101,108,44,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,40, + 102,108,111,97,116,41,32,120,44,32,104,97,108,102,72,101,105,103,104,116,32,43,32,104,97,108,102,72,101,105,103,104,116,32,42,32,108,101,118,101, + 108,41,59,10,32,32,32,32,32,32,32,32,125,10,32,32,32,32,125,10,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,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,114,101,112,97,105,110,116,40,41,59,10,32,32,32,32,125,10,10,32,32, + 32,32,118,111,105,100,32,97,100,100,83,97,109,112,108,101,32,40,99,111,110,115,116,32,102,108,111,97,116,32,115,97,109,112,108,101,41,10,32,32, + 32,32,123,10,32,32,32,32,32,32,32,32,99,117,114,114,101,110,116,73,110,112,117,116,76,101,118,101,108,32,43,61,32,102,97,98,115,102,32,40, + 115,97,109,112,108,101,41,59,10,10,32,32,32,32,32,32,32,32,99,111,110,115,116,32,105,110,116,32,115,97,109,112,108,101,115,84,111,65,118,101, + 114,97,103,101,32,61,32,49,50,56,59,10,10,32,32,32,32,32,32,32,32,105,102,32,40,43,43,110,117,109,83,97,109,112,108,101,115,73,110,32, + 62,32,115,97,109,112,108,101,115,84,111,65,118,101,114,97,103,101,41,10,32,32,32,32,32,32,32,32,123,10,32,32,32,32,32,32,32,32,32,32, + 32,32,99,105,114,99,117,108,97,114,66,117,102,102,101,114,32,91,98,117,102,102,101,114,80,111,115,43,43,32,37,32,98,117,102,102,101,114,83,105, + 122,101,93,32,61,32,99,117,114,114,101,110,116,73,110,112,117,116,76,101,118,101,108,32,47,32,115,97,109,112,108,101,115,84,111,65,118,101,114,97, + 103,101,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,110,117,109,83,97,109,112,108,101,115,73,110,32,61,32,48,59,10,32,32,32,32,32, + 32,32,32,32,32,32,32,99,117,114,114,101,110,116,73,110,112,117,116,76,101,118,101,108,32,61,32,48,46,48,102,59,10,32,32,32,32,32,32,32, + 32,125,10,32,32,32,32,125,10,10,32,32,32,32,118,111,105,100,32,97,117,100,105,111,68,101,118,105,99,101,73,79,67,97,108,108,98,97,99,107, + 32,40,99,111,110,115,116,32,102,108,111,97,116,42,42,32,105,110,112,117,116,67,104,97,110,110,101,108,68,97,116,97,44,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,105,110,116,32,116,111,116,97,108,78,117,109,73,110, + 112,117,116,67,104,97,110,110,101,108,115,44,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,102,108,111,97,116,42,42,32,111,117,116,112,117,116,67,104,97,110,110,101,108,68,97,116,97,44,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,105,110,116,32,116,111,116,97,108,78,117,109,79,117,116,112, + 117,116,67,104,97,110,110,101,108,115,44,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,105,110,116,32,110,117,109,83,97,109,112,108,101,115,41,10,32,32,32,32,123,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,111,116,97,108,78,117,109,73,110,112,117,116,67,104,97,110,110,101,108,115,59,32,43,43,105, + 41,10,32,32,32,32,32,32,32,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,105,110,112,117,116,67,104,97,110,110,101,108, + 68,97,116,97,32,91,105,93,32,33,61,32,48,41,10,32,32,32,32,32,32,32,32,32,32,32,32,123,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,106,32,61,32,48,59,32,106,32,60,32,110,117,109,83,97,109,112,108,101,115,59,32,43,43,106, + 41,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,97,100,100,83,97,109,112,108,101,32,40,105,110,112,117,116,67,104, + 97,110,110,101,108,68,97,116,97,32,91,105,93,91,106,93,41,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,98,114,101,97, + 107,59,10,32,32,32,32,32,32,32,32,32,32,32,32,125,10,32,32,32,32,32,32,32,32,125,10,32,32,32,32,125,10,10,32,32,32,32,118,111, + 105,100,32,97,117,100,105,111,68,101,118,105,99,101,65,98,111,117,116,84,111,83,116,97,114,116,32,40,65,117,100,105,111,73,79,68,101,118,105,99, + 101,42,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,122,101,114,111,109,101,109,32,40,99,105,114,99,117,108,97,114,66,117,102,102,101, + 114,44,32,115,105,122,101,111,102,32,40,102,108,111,97,116,41,32,42,32,98,117,102,102,101,114,83,105,122,101,41,59,10,32,32,32,32,125,10,10, + 32,32,32,32,118,111,105,100,32,97,117,100,105,111,68,101,118,105,99,101,83,116,111,112,112,101,100,40,41,10,32,32,32,32,123,10,32,32,32,32, 32,32,32,32,122,101,114,111,109,101,109,32,40,99,105,114,99,117,108,97,114,66,117,102,102,101,114,44,32,115,105,122,101,111,102,32,40,102,108,111, - 97,116,41,32,42,32,98,117,102,102,101,114,83,105,122,101,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,97,117, - 100,105,111,68,101,118,105,99,101,83,116,111,112,112,101,100,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,122,101,114,111,109, - 101,109,32,40,99,105,114,99,117,108,97,114,66,117,102,102,101,114,44,32,115,105,122,101,111,102,32,40,102,108,111,97,116,41,32,42,32,98,117,102, - 102,101,114,83,105,122,101,41,59,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,102,108,111,97,116,42, - 32,99,105,114,99,117,108,97,114,66,117,102,102,101,114,59,13,10,32,32,32,32,102,108,111,97,116,32,99,117,114,114,101,110,116,73,110,112,117,116, - 76,101,118,101,108,59,13,10,32,32,32,32,105,110,116,32,118,111,108,97,116,105,108,101,32,98,117,102,102,101,114,80,111,115,44,32,98,117,102,102, - 101,114,83,105,122,101,44,32,110,117,109,83,97,109,112,108,101,115,73,110,59,13,10,125,59,13,10,13,10,13,10,47,47,61,61,61,61,61,61,61, + 97,116,41,32,42,32,98,117,102,102,101,114,83,105,122,101,41,59,10,32,32,32,32,125,10,10,112,114,105,118,97,116,101,58,10,32,32,32,32,102, + 108,111,97,116,42,32,99,105,114,99,117,108,97,114,66,117,102,102,101,114,59,10,32,32,32,32,102,108,111,97,116,32,99,117,114,114,101,110,116,73, + 110,112,117,116,76,101,118,101,108,59,10,32,32,32,32,105,110,116,32,118,111,108,97,116,105,108,101,32,98,117,102,102,101,114,80,111,115,44,32,98, + 117,102,102,101,114,83,105,122,101,44,32,110,117,109,83,97,109,112,108,101,115,73,110,59,10,125,59,10,10,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,13,10,99,108,97,115,115,32,65, - 117,100,105,111,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,112,117,98,108,105,99,32,70,105,108,101,110,97,109,101,67,111,109,112,111,110,101,110,116,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,112,117,98,108,105,99,32,66,117,116,116,111,110,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,112,117,98,108,105,99,32,67,104,97,110,103,101, - 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,112,117,98,108,105,99,32,65,117,100, - 105,111,73,79,68,101,118,105,99,101,67,97,108,108,98,97,99,107,13,10,123,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,10,99,108,97,115,115,32,65,117,100, + 105,111,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,10,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,70,105,108,101,110,97,109,101,67,111,109,112,111,110,101,110,116,76,105,115,116,101,110,101,114,44, + 10,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,44,10,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,44,10,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,117,100,105,111,73,79,68,101, + 118,105,99,101,67,97,108,108,98,97,99,107,10,123,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,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,70,105,108,101,110,97,109, - 101,67,111,109,112,111,110,101,110,116,42,32,102,105,108,101,67,104,111,111,115,101,114,59,13,10,32,32,32,32,84,101,120,116,66,117,116,116,111,110, - 42,32,112,108,97,121,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,115,116,111,112,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,97,117,100,105,111,83,101,116,116,105,110,103,115,66,117,116,116,111,110,59, - 13,10,13,10,32,32,32,32,77,105,100,105,75,101,121,98,111,97,114,100,67,111,109,112,111,110,101,110,116,42,32,107,101,121,98,111,97,114,100,67, - 111,109,112,111,110,101,110,116,59,13,10,32,32,32,32,65,117,100,105,111,73,110,112,117,116,87,97,118,101,102,111,114,109,68,105,115,112,108,97,121, - 42,32,119,97,118,101,102,111,114,109,67,111,109,112,111,110,101,110,116,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,10,32,32,32,32,70,105,108,101,110,97,109,101,67,111,109,112,111,110,101,110, + 116,42,32,102,105,108,101,67,104,111,111,115,101,114,59,10,32,32,32,32,84,101,120,116,66,117,116,116,111,110,42,32,112,108,97,121,66,117,116,116, + 111,110,59,10,32,32,32,32,84,101,120,116,66,117,116,116,111,110,42,32,115,116,111,112,66,117,116,116,111,110,59,10,32,32,32,32,84,101,120,116, + 66,117,116,116,111,110,42,32,97,117,100,105,111,83,101,116,116,105,110,103,115,66,117,116,116,111,110,59,10,10,32,32,32,32,77,105,100,105,75,101, + 121,98,111,97,114,100,67,111,109,112,111,110,101,110,116,42,32,107,101,121,98,111,97,114,100,67,111,109,112,111,110,101,110,116,59,10,32,32,32,32, + 65,117,100,105,111,73,110,112,117,116,87,97,118,101,102,111,114,109,68,105,115,112,108,97,121,42,32,119,97,118,101,102,111,114,109,67,111,109,112,111, + 110,101,110,116,59,10,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,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,47,47,32,116,104,105, - 115,32,119,114,97,112,115,32,116,104,101,32,97,99,116,117,97,108,32,97,117,100,105,111,32,100,101,118,105,99,101,13,10,32,32,32,32,65,117,100, - 105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,32,97,117,100,105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,59,13,10,13,10,32, - 32,32,32,47,47,32,116,104,105,115,32,97,108,108,111,119,115,32,97,110,32,97,117,100,105,111,32,115,111,117,114,99,101,32,116,111,32,98,101,32, - 115,116,114,101,97,109,101,100,32,116,111,32,116,104,101,32,73,79,32,100,101,118,105,99,101,13,10,32,32,32,32,65,117,100,105,111,83,111,117,114, - 99,101,80,108,97,121,101,114,32,97,117,100,105,111,83,111,117,114,99,101,80,108,97,121,101,114,59,13,10,13,10,32,32,32,32,47,47,32,116,104, - 105,115,32,99,111,110,116,114,111,108,115,32,116,104,101,32,112,108,97,121,98,97,99,107,32,111,102,32,97,32,112,111,115,105,116,105,111,110,97,98, - 108,101,32,97,117,100,105,111,32,115,116,114,101,97,109,44,32,104,97,110,100,108,105,110,103,32,116,104,101,13,10,32,32,32,32,47,47,32,115,116, - 97,114,116,105,110,103,47,115,116,111,112,112,105,110,103,32,97,110,100,32,115,97,109,112,108,101,45,114,97,116,101,32,99,111,110,118,101,114,115,105, - 111,110,13,10,32,32,32,32,65,117,100,105,111,84,114,97,110,115,112,111,114,116,83,111,117,114,99,101,32,116,114,97,110,115,112,111,114,116,83,111, - 117,114,99,101,59,13,10,13,10,32,32,32,32,47,47,32,116,104,105,115,32,115,111,117,114,99,101,32,99,111,110,116,97,105,110,115,32,111,117,114, - 32,115,121,110,116,104,44,32,97,110,100,32,103,101,110,101,114,97,116,101,115,32,105,116,115,32,111,117,116,112,117,116,13,10,32,32,32,32,83,121, - 110,116,104,65,117,100,105,111,83,111,117,114,99,101,32,115,121,110,116,104,83,111,117,114,99,101,59,13,10,13,10,32,32,32,32,47,47,32,116,104, - 105,115,32,115,111,117,114,99,101,32,105,115,32,117,115,101,100,32,116,111,32,109,105,120,32,116,111,103,101,116,104,101,114,32,116,104,101,32,111,117, - 116,112,117,116,32,102,114,111,109,32,111,117,114,32,115,121,110,116,104,32,115,111,117,114,99,101,13,10,32,32,32,32,47,47,32,97,110,100,32,119, - 97,118,101,32,112,108,97,121,101,114,32,115,111,117,114,99,101,13,10,32,32,32,32,77,105,120,101,114,65,117,100,105,111,83,111,117,114,99,101,32, - 109,105,120,101,114,83,111,117,114,99,101,59,13,10,13,10,32,32,32,32,47,47,32,116,104,105,115,32,105,115,32,116,104,101,32,97,99,116,117,97, - 108,32,115,116,114,101,97,109,32,116,104,97,116,39,115,32,103,111,105,110,103,32,116,111,32,114,101,97,100,32,102,114,111,109,32,116,104,101,32,97, - 117,100,105,111,32,102,105,108,101,46,13,10,32,32,32,32,65,117,100,105,111,70,111,114,109,97,116,82,101,97,100,101,114,83,111,117,114,99,101,42, - 32,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,59,13,10,13,10,32,32,32,32,70,105,108,101,32,99,117,114, - 114,101,110,116,70,105,108,101,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,10,32,32,32,32,47,47,32,116,104,105,115,32,119,114,97,112,115,32,116,104,101,32,97,99,116,117,97,108, + 32,97,117,100,105,111,32,100,101,118,105,99,101,10,32,32,32,32,65,117,100,105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,32,97,117,100, + 105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,59,10,10,32,32,32,32,47,47,32,116,104,105,115,32,97,108,108,111,119,115,32,97,110,32, + 97,117,100,105,111,32,115,111,117,114,99,101,32,116,111,32,98,101,32,115,116,114,101,97,109,101,100,32,116,111,32,116,104,101,32,73,79,32,100,101, + 118,105,99,101,10,32,32,32,32,65,117,100,105,111,83,111,117,114,99,101,80,108,97,121,101,114,32,97,117,100,105,111,83,111,117,114,99,101,80,108, + 97,121,101,114,59,10,10,32,32,32,32,47,47,32,116,104,105,115,32,99,111,110,116,114,111,108,115,32,116,104,101,32,112,108,97,121,98,97,99,107, + 32,111,102,32,97,32,112,111,115,105,116,105,111,110,97,98,108,101,32,97,117,100,105,111,32,115,116,114,101,97,109,44,32,104,97,110,100,108,105,110, + 103,32,116,104,101,10,32,32,32,32,47,47,32,115,116,97,114,116,105,110,103,47,115,116,111,112,112,105,110,103,32,97,110,100,32,115,97,109,112,108, + 101,45,114,97,116,101,32,99,111,110,118,101,114,115,105,111,110,10,32,32,32,32,65,117,100,105,111,84,114,97,110,115,112,111,114,116,83,111,117,114, + 99,101,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,59,10,10,32,32,32,32,47,47,32,116,104,105,115,32,115,111,117,114,99,101,32, + 99,111,110,116,97,105,110,115,32,111,117,114,32,115,121,110,116,104,44,32,97,110,100,32,103,101,110,101,114,97,116,101,115,32,105,116,115,32,111,117, + 116,112,117,116,10,32,32,32,32,83,121,110,116,104,65,117,100,105,111,83,111,117,114,99,101,32,115,121,110,116,104,83,111,117,114,99,101,59,10,10, + 32,32,32,32,47,47,32,116,104,105,115,32,115,111,117,114,99,101,32,105,115,32,117,115,101,100,32,116,111,32,109,105,120,32,116,111,103,101,116,104, + 101,114,32,116,104,101,32,111,117,116,112,117,116,32,102,114,111,109,32,111,117,114,32,115,121,110,116,104,32,115,111,117,114,99,101,10,32,32,32,32, + 47,47,32,97,110,100,32,119,97,118,101,32,112,108,97,121,101,114,32,115,111,117,114,99,101,10,32,32,32,32,77,105,120,101,114,65,117,100,105,111, + 83,111,117,114,99,101,32,109,105,120,101,114,83,111,117,114,99,101,59,10,10,32,32,32,32,47,47,32,116,104,105,115,32,105,115,32,116,104,101,32, + 97,99,116,117,97,108,32,115,116,114,101,97,109,32,116,104,97,116,39,115,32,103,111,105,110,103,32,116,111,32,114,101,97,100,32,102,114,111,109,32, + 116,104,101,32,97,117,100,105,111,32,102,105,108,101,46,10,32,32,32,32,65,117,100,105,111,70,111,114,109,97,116,82,101,97,100,101,114,83,111,117, + 114,99,101,42,32,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,59,10,10,32,32,32,32,70,105,108,101,32,99, + 117,114,114,101,110,116,70,105,108,101,59,10,10,112,117,98,108,105,99,58,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,61,61,61,61,13,10,32,32,32,32,65,117,100,105,111,68,101,109, - 111,40,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,65,117,100,105,111,34,41,41, - 59,13,10,13,10,32,32,32,32,32,32,32,32,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,32,61,32,48,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,10,32,32,32,32,65,117,100,105,111,68,101,109,111,40, + 41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,115,101,116,78,97,109,101,32,40,84,40,34,65,117,100,105,111,34,41,41,59,10,10,32, + 32,32,32,32,32,32,32,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,32,61,32,48,59,10,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,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,32,32,32,32,65,117,100,105,111,70,111,114,109,97,116,77,97,110,97,103,101,114, - 32,102,111,114,109,97,116,77,97,110,97,103,101,114,59,13,10,32,32,32,32,32,32,32,32,102,111,114,109,97,116,77,97,110,97,103,101,114,46,114, - 101,103,105,115,116,101,114,66,97,115,105,99,70,111,114,109,97,116,115,40,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,102,105,108,101,67,104,111,111,115,101,114,32,61,32,110,101,119,32,70,105,108,101,110,97,109,101,67, - 111,109,112,111,110,101,110,116,32,40,84,40,34,97,117,100,105,111,102,105,108,101,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,32,32,32,32,32,70,105,108,101,58,58,110,111,110,101,120,105,115,116,101,110,116,44,13,10,32,32,32,32,32,32,32,32,32, + 61,61,61,61,10,32,32,32,32,32,32,32,32,65,117,100,105,111,70,111,114,109,97,116,77,97,110,97,103,101,114,32,102,111,114,109,97,116,77,97, + 110,97,103,101,114,59,10,32,32,32,32,32,32,32,32,102,111,114,109,97,116,77,97,110,97,103,101,114,46,114,101,103,105,115,116,101,114,66,97,115, + 105,99,70,111,114,109,97,116,115,40,41,59,10,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,102,105,108,101,67,104,111,111,115,101,114,32,61,32,110,101,119,32,70,105,108,101,110,97,109,101,67,111,109,112,111,110,101,110,116,32,40,84,40, + 34,97,117,100,105,111,102,105,108,101,34,41,44,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,32,32,32,32,32,70,105, + 108,101,58,58,110,111,110,101,120,105,115,116,101,110,116,44,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,32,32,32,32, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114,117,101,44,32,102,97,108,115,101,44,32,102,97,108,115,101,44,13,10,32,32,32,32, + 32,116,114,117,101,44,32,102,97,108,115,101,44,32,102,97,108,115,101,44,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, - 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,102,111,114,109,97,116,77,97,110,97,103,101,114,46,103,101,116,87,105,108, - 100,99,97,114,100,70,111,114,65,108,108,70,111,114,109,97,116,115,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,102,111,114,109,97,116,77,97,110,97,103,101,114,46,103,101,116,87,105,108,100,99,97,114,100,70,111,114,65,108,108,70,111,114,109, + 97,116,115,40,41,44,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,32,32,32,32,32,83,116,114,105,110,103,58,58,101, + 109,112,116,121,44,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,32,32,32,32,32,84,40,34,40,99,104,111,111,115,101, + 32,97,32,87,65,86,32,111,114,32,65,73,70,70,32,102,105,108,101,32,116,111,32,112,108,97,121,41,34,41,41,41,59,10,32,32,32,32,32,32, + 32,32,102,105,108,101,67,104,111,111,115,101,114,45,62,97,100,100,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,10,32,32,32,32,32, + 32,32,32,102,105,108,101,67,104,111,111,115,101,114,45,62,115,101,116,66,114,111,119,115,101,66,117,116,116,111,110,84,101,120,116,32,40,84,40,34, + 98,114,111,119,115,101,34,41,41,59,10,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,112, + 108,97,121,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,112,108,97,121,34,41,44,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,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,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,104,101,114,101,32,116,111,32,112,108,97,121,32,116,104,101, + 32,99,117,114,114,101,110,116,32,97,117,100,105,111,32,102,105,108,101,34,41,41,41,59,10,32,32,32,32,32,32,32,32,112,108,97,121,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,10,32,32,32,32,32,32,32,32,112, + 108,97,121,66,117,116,116,111,110,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,108,105,103,104,116,103,114,101,101,110,41,59,10,32,32,32,32,32,32,32,32, + 112,108,97,121,66,117,116,116,111,110,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,108,105,103,104,116,103,114,101,101,110,41,59,10,32,32,32,32,32, + 32,32,32,112,108,97,121,66,117,116,116,111,110,45,62,115,101,116,67,111,110,110,101,99,116,101,100,69,100,103,101,115,32,40,66,117,116,116,111,110, + 58,58,67,111,110,110,101,99,116,101,100,79,110,82,105,103,104,116,41,59,10,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,115,116,111,112,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,115,116,111,112,34,41,44,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,99,108,105,99,107,32,104,101,114,101,32,116, + 111,32,112,108,97,121,32,116,104,101,32,99,117,114,114,101,110,116,32,97,117,100,105,111,32,102,105,108,101,34,41,41,41,59,10,32,32,32,32,32, + 32,32,32,115,116,111,112,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, + 10,32,32,32,32,32,32,32,32,115,116,111,112,66,117,116,116,111,110,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,114,101,100,41,59,10,32,32,32,32,32, + 32,32,32,115,116,111,112,66,117,116,116,111,110,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,114,101,100,41,59,10,32,32,32,32,32,32,32,32,115, + 116,111,112,66,117,116,116,111,110,45,62,115,101,116,67,111,110,110,101,99,116,101,100,69,100,103,101,115,32,40,66,117,116,116,111,110,58,58,67,111, + 110,110,101,99,116,101,100,79,110,76,101,102,116,41,59,10,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,117,100,105,111,83,101,116,116,105,110,103,115,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,115,104,111,119,32,97,117,100,105,111,32,115,101,116,116,105,110,103,115,46,46,46,34,41,44,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,40,99,104,111,111,115,101,32,97,32,87,65,86,32,111,114,32,65,73,70,70,32,102,105,108,101,32,116,111,32, - 112,108,97,121,41,34,41,41,41,59,13,10,32,32,32,32,32,32,32,32,102,105,108,101,67,104,111,111,115,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,102,105,108,101,67,104,111,111,115,101,114,45,62,115,101,116,66,114, - 111,119,115,101,66,117,116,116,111,110,84,101,120,116,32,40,84,40,34,98,114,111,119,115,101,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,112,108,97,121,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,112,108,97,121,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, - 99,108,105,99,107,32,104,101,114,101,32,116,111,32,112,108,97,121,32,116,104,101,32,99,117,114,114,101,110,116,32,97,117,100,105,111,32,102,105,108, - 101,34,41,41,41,59,13,10,32,32,32,32,32,32,32,32,112,108,97,121,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,112,108,97,121,66,117,116,116,111,110,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,108,105,103,104,116,103,114,101,101,110,41,59,13,10,32,32,32,32,32,32,32,32,112,108,97,121,66,117,116,116,111,110,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,108,105,103,104,116,103,114,101,101,110,41,59,13,10,32,32,32,32,32,32,32,32,112,108,97,121,66,117,116,116,111,110,45, - 62,115,101,116,67,111,110,110,101,99,116,101,100,69,100,103,101,115,32,40,66,117,116,116,111,110,58,58,67,111,110,110,101,99,116,101,100,79,110,82, - 105,103,104,116,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,115,116,111, - 112,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,115,116,111,112,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,99,108,105,99,107,32,104,101,114,101,32,116,111,32,112,108,97,121,32,116,104,101,32, - 99,117,114,114,101,110,116,32,97,117,100,105,111,32,102,105,108,101,34,41,41,41,59,13,10,32,32,32,32,32,32,32,32,115,116,111,112,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, - 115,116,111,112,66,117,116,116,111,110,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,114,101,100,41,59,13,10,32,32,32,32,32,32,32,32,115,116,111,112,66, - 117,116,116,111,110,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,114,101,100,41,59,13,10,32,32,32,32,32,32,32,32,115,116,111,112,66,117,116,116, - 111,110,45,62,115,101,116,67,111,110,110,101,99,116,101,100,69,100,103,101,115,32,40,66,117,116,116,111,110,58,58,67,111,110,110,101,99,116,101,100, - 79,110,76,101,102,116,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,97, - 117,100,105,111,83,101,116,116,105,110,103,115,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, - 115,104,111,119,32,97,117,100,105,111,32,115,101,116,116,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,32,32,32,32,32,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,104,101,114,101,32,116,111,32,99,104,97,110,103,101,32,116,104,101,32, - 97,117,100,105,111,32,100,101,118,105,99,101,32,115,101,116,116,105,110,103,115,34,41,41,41,59,13,10,32,32,32,32,32,32,32,32,97,117,100,105, - 111,83,101,116,116,105,110,103,115,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,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,107,101,121,98,111,97,114, - 100,67,111,109,112,111,110,101,110,116,32,61,32,110,101,119,32,77,105,100,105,75,101,121,98,111,97,114,100,67,111,109,112,111,110,101,110,116,32,40, - 115,121,110,116,104,83,111,117,114,99,101,46,107,101,121,98,111,97,114,100,83,116,97,116,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,84,40,34,99,108,105,99,107,32,104,101,114,101,32,116,111,32,99,104,97,110,103,101,32, + 116,104,101,32,97,117,100,105,111,32,100,101,118,105,99,101,32,115,101,116,116,105,110,103,115,34,41,41,41,59,10,32,32,32,32,32,32,32,32,97, + 117,100,105,111,83,101,116,116,105,110,103,115,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,10,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,107,101,121,98,111,97, + 114,100,67,111,109,112,111,110,101,110,116,32,61,32,110,101,119,32,77,105,100,105,75,101,121,98,111,97,114,100,67,111,109,112,111,110,101,110,116,32, + 40,115,121,110,116,104,83,111,117,114,99,101,46,107,101,121,98,111,97,114,100,83,116,97,116,101,44,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,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,77,105,100,105,75,101,121,98,111,97,114,100,67,111,109,112,111,110, - 101,110,116,58,58,104,111,114,105,122,111,110,116,97,108,75,101,121,98,111,97,114,100,41,41,59,13,10,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,119,97,118,101,102,111,114,109,67,111,109,112,111,110,101,110,116,32,61,32,110, - 101,119,32,65,117,100,105,111,73,110,112,117,116,87,97,118,101,102,111,114,109,68,105,115,112,108,97,121,40,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,61,61,61,13,10,32,32,32,32,32,32,32,32,47,47,32,114,101,103,105,115,116,101,114,32,102,111,114,32,115,116,97,114,116,47,115,116,111,112, - 32,109,101,115,115,97,103,101,115,32,102,114,111,109,32,116,104,101,32,116,114,97,110,115,112,111,114,116,32,115,111,117,114,99,101,46,46,13,10,32, - 32,32,32,32,32,32,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,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,105,110,105,116,105,97,108,105,115,101,32,116,104, - 101,32,100,101,118,105,99,101,32,109,97,110,97,103,101,114,32,119,105,116,104,32,110,111,32,115,101,116,116,105,110,103,115,32,115,111,32,116,104,97, - 116,32,105,116,32,112,105,99,107,115,32,97,13,10,32,32,32,32,32,32,32,32,47,47,32,100,101,102,97,117,108,116,32,100,101,118,105,99,101,32, - 116,111,32,117,115,101,46,13,10,32,32,32,32,32,32,32,32,99,111,110,115,116,32,83,116,114,105,110,103,32,101,114,114,111,114,32,40,97,117,100, - 105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,46,105,110,105,116,105,97,108,105,115,101,32,40,49,44,32,47,42,32,110,117,109,98,101,114, - 32,111,102,32,105,110,112,117,116,32,99,104,97,110,110,101,108,115,32,42,47,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 101,110,116,58,58,104,111,114,105,122,111,110,116,97,108,75,101,121,98,111,97,114,100,41,41,59,10,10,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,119,97,118,101,102,111,114,109,67,111,109,112,111,110,101,110,116,32,61,32,110,101,119,32, + 65,117,100,105,111,73,110,112,117,116,87,97,118,101,102,111,114,109,68,105,115,112,108,97,121,40,41,41,59,10,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,61,61,61,10, + 32,32,32,32,32,32,32,32,47,47,32,114,101,103,105,115,116,101,114,32,102,111,114,32,115,116,97,114,116,47,115,116,111,112,32,109,101,115,115,97, + 103,101,115,32,102,114,111,109,32,116,104,101,32,116,114,97,110,115,112,111,114,116,32,115,111,117,114,99,101,46,46,10,32,32,32,32,32,32,32,32, + 116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,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,10,10,32,32,32,32,32,32,32,32,47,47,32,97,110,100,32,105,110,105,116,105,97,108,105,115,101,32,116,104,101,32,100,101,118,105,99,101,32, + 109,97,110,97,103,101,114,32,119,105,116,104,32,110,111,32,115,101,116,116,105,110,103,115,32,115,111,32,116,104,97,116,32,105,116,32,112,105,99,107, + 115,32,97,10,32,32,32,32,32,32,32,32,47,47,32,100,101,102,97,117,108,116,32,100,101,118,105,99,101,32,116,111,32,117,115,101,46,10,32,32, + 32,32,32,32,32,32,99,111,110,115,116,32,83,116,114,105,110,103,32,101,114,114,111,114,32,40,97,117,100,105,111,68,101,118,105,99,101,77,97,110, + 97,103,101,114,46,105,110,105,116,105,97,108,105,115,101,32,40,49,44,32,47,42,32,110,117,109,98,101,114,32,111,102,32,105,110,112,117,116,32,99, + 104,97,110,110,101,108,115,32,42,47,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,50,44,32,47,42,32,110,117,109,98, + 101,114,32,111,102,32,111,117,116,112,117,116,32,99,104,97,110,110,101,108,115,32,42,47,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,50,44,32,47,42,32,110,117,109,98,101,114,32,111,102,32,111,117,116,112,117,116,32,99,104,97,110,110,101,108,115,32,42,47,13,10,32,32, + 32,32,32,32,48,44,32,47,42,32,110,111,32,88,77,76,32,115,101,116,116,105,110,103,115,46,46,32,42,47,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,32,32,32,32,32,32,32,48,44,32,47,42,32,110,111,32,88,77,76,32,115,101,116,116,105,110,103,115,46,46, - 32,42,47,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,116,114,117,101,32,32,47,42,32,115,101,108,101,99,116,32, - 100,101,102,97,117,108,116,32,100,101,118,105,99,101,32,111,110,32,102,97,105,108,117,114,101,32,42,47,41,41,59,13,10,13,10,32,32,32,32,32, - 32,32,32,105,102,32,40,101,114,114,111,114,46,105,115,78,111,116,69,109,112,116,121,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,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,84,40,34,65,117,100,105,111,32,68,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,32,32,32,32,32,32,32,32,32,32, - 32,32,32,32,32,32,32,84,40,34,67,111,117,108,100,110,39,116,32,111,112,101,110,32,97,110,32,111,117,116,112,117,116,32,100,101,118,105,99,101, - 33,92,110,92,110,34,41,32,43,32,101,114,114,111,114,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,47,47,32,97,100,100,32,116,104,101,32,116,119, - 111,32,97,117,100,105,111,32,115,111,117,114,99,101,115,32,116,111,32,111,117,114,32,109,105,120,101,114,46,46,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,109,105,120,101,114,83,111,117,114,99,101,46,97,100,100,73,110,112,117,116,83,111,117,114,99,101,32,40,38,116,114,97,110,115,112,111, - 114,116,83,111,117,114,99,101,44,32,102,97,108,115,101,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,109,105,120,101,114,83,111,117,114, - 99,101,46,97,100,100,73,110,112,117,116,83,111,117,114,99,101,32,40,38,115,121,110,116,104,83,111,117,114,99,101,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,47,47,32,46,46,97,110,100,32,99,111,110,110,101,99,116,32,116,104,101,32,109,105,120, - 101,114,32,116,111,32,111,117,114,32,115,111,117,114,99,101,32,112,108,97,121,101,114,46,13,10,32,32,32,32,32,32,32,32,32,32,32,32,97,117, - 100,105,111,83,111,117,114,99,101,80,108,97,121,101,114,46,115,101,116,83,111,117,114,99,101,32,40,38,109,105,120,101,114,83,111,117,114,99,101,41, - 59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,115,116,97,114,116,32,116,104,101,32,73,79,32,100,101,118,105,99,101,32, - 112,117,108,108,105,110,103,32,105,116,115,32,100,97,116,97,32,102,114,111,109,32,111,117,114,32,99,97,108,108,98,97,99,107,46,46,13,10,32,32, - 32,32,32,32,32,32,32,32,32,32,97,117,100,105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,46,115,101,116,65,117,100,105,111,67,97,108, - 108,98,97,99,107,32,40,116,104,105,115,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,97,110,100,32,119,101,32,110, - 101,101,100,32,116,111,32,115,101,110,100,32,109,105,100,105,32,105,110,112,117,116,32,116,111,32,111,117,114,32,115,121,110,116,104,32,102,111,114,32, - 112,114,111,99,101,115,115,105,110,103,13,10,32,32,32,32,32,32,32,32,32,32,32,32,97,117,100,105,111,68,101,118,105,99,101,77,97,110,97,103, - 101,114,46,97,100,100,77,105,100,105,73,110,112,117,116,67,97,108,108,98,97,99,107,32,40,83,116,114,105,110,103,58,58,101,109,112,116,121,44,32, - 38,115,121,110,116,104,83,111,117,114,99,101,46,109,105,100,105,67,111,108,108,101,99,116,111,114,41,59,13,10,32,32,32,32,32,32,32,32,125,13, - 10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,65,117,100,105,111,68,101,109,111,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32, - 32,32,32,97,117,100,105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,46,114,101,109,111,118,101,77,105,100,105,73,110,112,117,116,67,97,108, - 108,98,97,99,107,32,40,38,115,121,110,116,104,83,111,117,114,99,101,46,109,105,100,105,67,111,108,108,101,99,116,111,114,41,59,13,10,32,32,32, - 32,32,32,32,32,97,117,100,105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,46,115,101,116,65,117,100,105,111,67,97,108,108,98,97,99,107, - 32,40,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,114,101,109,111,118,101,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,116,114,97,110,115,112,111, - 114,116,83,111,117,114,99,101,46,115,101,116,83,111,117,114,99,101,32,40,48,41,59,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65, - 110,100,90,101,114,111,32,40,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,41,59,13,10,13,10,32,32,32,32, - 32,32,32,32,97,117,100,105,111,83,111,117,114,99,101,80,108,97,121,101,114,46,115,101,116,83,111,117,114,99,101,32,40,48,41,59,13,10,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,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, + 32,32,32,32,32,32,32,32,32,32,116,114,117,101,32,32,47,42,32,115,101,108,101,99,116,32,100,101,102,97,117,108,116,32,100,101,118,105,99,101, + 32,111,110,32,102,97,105,108,117,114,101,32,42,47,41,41,59,10,10,32,32,32,32,32,32,32,32,105,102,32,40,101,114,114,111,114,46,105,115,78, + 111,116,69,109,112,116,121,40,41,41,10,32,32,32,32,32,32,32,32,123,10,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,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,65,117,100,105,111,32,68,101,109,111,34,41,44,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,67,111,117,108,100,110,39,116,32,111, + 112,101,110,32,97,110,32,111,117,116,112,117,116,32,100,101,118,105,99,101,33,92,110,92,110,34,41,32,43,32,101,114,114,111,114,41,59,10,32,32, + 32,32,32,32,32,32,125,10,32,32,32,32,32,32,32,32,101,108,115,101,10,32,32,32,32,32,32,32,32,123,10,32,32,32,32,32,32,32,32,32, + 32,32,32,47,47,32,97,100,100,32,116,104,101,32,116,119,111,32,97,117,100,105,111,32,115,111,117,114,99,101,115,32,116,111,32,111,117,114,32,109, + 105,120,101,114,46,46,10,32,32,32,32,32,32,32,32,32,32,32,32,109,105,120,101,114,83,111,117,114,99,101,46,97,100,100,73,110,112,117,116,83, + 111,117,114,99,101,32,40,38,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,44,32,102,97,108,115,101,41,59,10,32,32,32,32,32,32,32, + 32,32,32,32,32,109,105,120,101,114,83,111,117,114,99,101,46,97,100,100,73,110,112,117,116,83,111,117,114,99,101,32,40,38,115,121,110,116,104,83, + 111,117,114,99,101,44,32,102,97,108,115,101,41,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,46,46,97,110,100,32,99,111,110, + 110,101,99,116,32,116,104,101,32,109,105,120,101,114,32,116,111,32,111,117,114,32,115,111,117,114,99,101,32,112,108,97,121,101,114,46,10,32,32,32, + 32,32,32,32,32,32,32,32,32,97,117,100,105,111,83,111,117,114,99,101,80,108,97,121,101,114,46,115,101,116,83,111,117,114,99,101,32,40,38,109, + 105,120,101,114,83,111,117,114,99,101,41,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,115,116,97,114,116,32,116,104,101,32,73, + 79,32,100,101,118,105,99,101,32,112,117,108,108,105,110,103,32,105,116,115,32,100,97,116,97,32,102,114,111,109,32,111,117,114,32,99,97,108,108,98, + 97,99,107,46,46,10,32,32,32,32,32,32,32,32,32,32,32,32,97,117,100,105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,46,115,101,116, + 65,117,100,105,111,67,97,108,108,98,97,99,107,32,40,116,104,105,115,41,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,97,110, + 100,32,119,101,32,110,101,101,100,32,116,111,32,115,101,110,100,32,109,105,100,105,32,105,110,112,117,116,32,116,111,32,111,117,114,32,115,121,110,116, + 104,32,102,111,114,32,112,114,111,99,101,115,115,105,110,103,10,32,32,32,32,32,32,32,32,32,32,32,32,97,117,100,105,111,68,101,118,105,99,101, + 77,97,110,97,103,101,114,46,97,100,100,77,105,100,105,73,110,112,117,116,67,97,108,108,98,97,99,107,32,40,83,116,114,105,110,103,58,58,101,109, + 112,116,121,44,32,38,115,121,110,116,104,83,111,117,114,99,101,46,109,105,100,105,67,111,108,108,101,99,116,111,114,41,59,10,32,32,32,32,32,32, + 32,32,125,10,32,32,32,32,125,10,10,32,32,32,32,126,65,117,100,105,111,68,101,109,111,40,41,10,32,32,32,32,123,10,32,32,32,32,32,32, + 32,32,97,117,100,105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,46,114,101,109,111,118,101,77,105,100,105,73,110,112,117,116,67,97,108,108, + 98,97,99,107,32,40,38,115,121,110,116,104,83,111,117,114,99,101,46,109,105,100,105,67,111,108,108,101,99,116,111,114,41,59,10,32,32,32,32,32, + 32,32,32,97,117,100,105,111,68,101,118,105,99,101,77,97,110,97,103,101,114,46,115,101,116,65,117,100,105,111,67,97,108,108,98,97,99,107,32,40, + 48,41,59,10,10,32,32,32,32,32,32,32,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,114,101,109,111,118,101,67,104,97,110,103, + 101,76,105,115,116,101,110,101,114,32,40,116,104,105,115,41,59,10,10,32,32,32,32,32,32,32,32,116,114,97,110,115,112,111,114,116,83,111,117,114, + 99,101,46,115,101,116,83,111,117,114,99,101,32,40,48,41,59,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65,110,100,90,101,114,111,32, + 40,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,41,59,10,10,32,32,32,32,32,32,32,32,97,117,100,105,111, + 83,111,117,114,99,101,80,108,97,121,101,114,46,115,101,116,83,111,117,114,99,101,32,40,48,41,59,10,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,10,32,32,32,32,125,10,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,13,10,32,32,32,32,118,111,105,100,32,97,117,100,105,111,68,101,118,105,99,101,73,79,67,97,108,108,98,97,99,107,32,40,99,111,110, - 115,116,32,102,108,111,97,116,42,42,32,105,110,112,117,116,67,104,97,110,110,101,108,68,97,116,97,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,105,110,116,32,116,111,116,97,108,78,117,109,73,110,112,117,116,67, - 104,97,110,110,101,108,115,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,102,108,111,97,116,42,42,32,111,117,116,112,117,116,67,104,97,110,110,101,108,68,97,116,97,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,105,110,116,32,116,111,116,97,108,78,117,109,79,117,116,112,117,116, - 67,104,97,110,110,101,108,115,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,105,110,116,32,110,117,109,83,97,109,112,108,101,115,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,112,97, - 115,115,32,116,104,101,32,97,117,100,105,111,32,99,97,108,108,98,97,99,107,32,111,110,32,116,111,32,111,117,114,32,112,108,97,121,101,114,32,115, - 111,117,114,99,101,44,32,97,110,100,32,97,108,115,111,32,116,104,101,32,119,97,118,101,102,111,114,109,32,100,105,115,112,108,97,121,32,99,111,109, - 112,13,10,32,32,32,32,32,32,32,32,97,117,100,105,111,83,111,117,114,99,101,80,108,97,121,101,114,46,97,117,100,105,111,68,101,118,105,99,101, - 73,79,67,97,108,108,98,97,99,107,32,40,105,110,112,117,116,67,104,97,110,110,101,108,68,97,116,97,44,32,116,111,116,97,108,78,117,109,73,110, - 112,117,116,67,104,97,110,110,101,108,115,44,32,111,117,116,112,117,116,67,104,97,110,110,101,108,68,97,116,97,44,32,116,111,116,97,108,78,117,109, - 79,117,116,112,117,116,67,104,97,110,110,101,108,115,44,32,110,117,109,83,97,109,112,108,101,115,41,59,13,10,32,32,32,32,32,32,32,32,119,97, - 118,101,102,111,114,109,67,111,109,112,111,110,101,110,116,45,62,97,117,100,105,111,68,101,118,105,99,101,73,79,67,97,108,108,98,97,99,107,32,40, - 105,110,112,117,116,67,104,97,110,110,101,108,68,97,116,97,44,32,116,111,116,97,108,78,117,109,73,110,112,117,116,67,104,97,110,110,101,108,115,44, - 32,111,117,116,112,117,116,67,104,97,110,110,101,108,68,97,116,97,44,32,116,111,116,97,108,78,117,109,79,117,116,112,117,116,67,104,97,110,110,101, - 108,115,44,32,110,117,109,83,97,109,112,108,101,115,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,97,117,100,105, - 111,68,101,118,105,99,101,65,98,111,117,116,84,111,83,116,97,114,116,32,40,65,117,100,105,111,73,79,68,101,118,105,99,101,42,32,100,101,118,105, - 99,101,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,97,117,100,105,111,83,111,117,114,99,101,80,108,97,121,101,114,46,97,117, - 100,105,111,68,101,118,105,99,101,65,98,111,117,116,84,111,83,116,97,114,116,32,40,100,101,118,105,99,101,41,59,13,10,32,32,32,32,32,32,32, - 32,119,97,118,101,102,111,114,109,67,111,109,112,111,110,101,110,116,45,62,97,117,100,105,111,68,101,118,105,99,101,65,98,111,117,116,84,111,83,116, - 97,114,116,32,40,100,101,118,105,99,101,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,97,117,100,105,111,68,101, - 118,105,99,101,83,116,111,112,112,101,100,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,97,117,100,105,111,83,111,117,114,99, - 101,80,108,97,121,101,114,46,97,117,100,105,111,68,101,118,105,99,101,83,116,111,112,112,101,100,40,41,59,13,10,32,32,32,32,32,32,32,32,119, - 97,118,101,102,111,114,109,67,111,109,112,111,110,101,110,116,45,62,97,117,100,105,111,68,101,118,105,99,101,83,116,111,112,112,101,100,40,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,10,32,32,32,32,118,111,105,100,32,97, + 117,100,105,111,68,101,118,105,99,101,73,79,67,97,108,108,98,97,99,107,32,40,99,111,110,115,116,32,102,108,111,97,116,42,42,32,105,110,112,117, + 116,67,104,97,110,110,101,108,68,97,116,97,44,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,105,110,116,32,116,111,116,97,108,78,117,109,73,110,112,117,116,67,104,97,110,110,101,108,115,44,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,102,108,111,97,116,42,42,32,111,117,116,112,117,116,67, + 104,97,110,110,101,108,68,97,116,97,44,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,105,110,116,32,116,111,116,97,108,78,117,109,79,117,116,112,117,116,67,104,97,110,110,101,108,115,44,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,105,110,116,32,110,117,109,83,97,109,112,108,101,115,41,10, + 32,32,32,32,123,10,32,32,32,32,32,32,32,32,47,47,32,112,97,115,115,32,116,104,101,32,97,117,100,105,111,32,99,97,108,108,98,97,99,107, + 32,111,110,32,116,111,32,111,117,114,32,112,108,97,121,101,114,32,115,111,117,114,99,101,44,32,97,110,100,32,97,108,115,111,32,116,104,101,32,119, + 97,118,101,102,111,114,109,32,100,105,115,112,108,97,121,32,99,111,109,112,10,32,32,32,32,32,32,32,32,97,117,100,105,111,83,111,117,114,99,101, + 80,108,97,121,101,114,46,97,117,100,105,111,68,101,118,105,99,101,73,79,67,97,108,108,98,97,99,107,32,40,105,110,112,117,116,67,104,97,110,110, + 101,108,68,97,116,97,44,32,116,111,116,97,108,78,117,109,73,110,112,117,116,67,104,97,110,110,101,108,115,44,32,111,117,116,112,117,116,67,104,97, + 110,110,101,108,68,97,116,97,44,32,116,111,116,97,108,78,117,109,79,117,116,112,117,116,67,104,97,110,110,101,108,115,44,32,110,117,109,83,97,109, + 112,108,101,115,41,59,10,32,32,32,32,32,32,32,32,119,97,118,101,102,111,114,109,67,111,109,112,111,110,101,110,116,45,62,97,117,100,105,111,68, + 101,118,105,99,101,73,79,67,97,108,108,98,97,99,107,32,40,105,110,112,117,116,67,104,97,110,110,101,108,68,97,116,97,44,32,116,111,116,97,108, + 78,117,109,73,110,112,117,116,67,104,97,110,110,101,108,115,44,32,111,117,116,112,117,116,67,104,97,110,110,101,108,68,97,116,97,44,32,116,111,116, + 97,108,78,117,109,79,117,116,112,117,116,67,104,97,110,110,101,108,115,44,32,110,117,109,83,97,109,112,108,101,115,41,59,10,32,32,32,32,125,10, + 10,32,32,32,32,118,111,105,100,32,97,117,100,105,111,68,101,118,105,99,101,65,98,111,117,116,84,111,83,116,97,114,116,32,40,65,117,100,105,111, + 73,79,68,101,118,105,99,101,42,32,100,101,118,105,99,101,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,97,117,100,105,111,83,111,117, + 114,99,101,80,108,97,121,101,114,46,97,117,100,105,111,68,101,118,105,99,101,65,98,111,117,116,84,111,83,116,97,114,116,32,40,100,101,118,105,99, + 101,41,59,10,32,32,32,32,32,32,32,32,119,97,118,101,102,111,114,109,67,111,109,112,111,110,101,110,116,45,62,97,117,100,105,111,68,101,118,105, + 99,101,65,98,111,117,116,84,111,83,116,97,114,116,32,40,100,101,118,105,99,101,41,59,10,32,32,32,32,125,10,10,32,32,32,32,118,111,105,100, + 32,97,117,100,105,111,68,101,118,105,99,101,83,116,111,112,112,101,100,40,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,97,117,100,105, + 111,83,111,117,114,99,101,80,108,97,121,101,114,46,97,117,100,105,111,68,101,118,105,99,101,83,116,111,112,112,101,100,40,41,59,10,32,32,32,32, + 32,32,32,32,119,97,118,101,102,111,114,109,67,111,109,112,111,110,101,110,116,45,62,97,117,100,105,111,68,101,118,105,99,101,83,116,111,112,112,101, + 100,40,41,59,10,32,32,32,32,125,10,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,61,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,47,47,32,112,114,105,110,116,32,115,111,109,101,32,116,101,120,116,32, - 116,111,32,101,120,112,108,97,105,110,32,119,104,97,116,32,115,116,97,116,101,32,119,101,39,114,101,32,105,110,46,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,98,108,97,99,107,41,59,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,41,59,13,10,13,10,32,32,32,32,32,32,32,32,83,116,114,105,110,103,32,115, - 59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,105,115,80,108,97,121,105, - 110,103,40,41,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,32,61,32,84,40,34,112,108,97,121,105,110,103,34,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,32,61,32,84,40,34,115,116,111,112,112,101,100,34,41, - 59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,32, - 61,61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,32,43,61,32,84,40,34,32,45,32,110,111,32,115,111,117,114,99,101,32, - 102,105,108,101,32,115,101,108,101,99,116,101,100,34,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,32,43,61,32,84,40,34,32,45,32,102,105,108,101,58,32,92,34,34,41,32,43,32,99,117,114,114,101,110,116,70,105,108,101,46, - 103,101,116,70,117,108,108,80,97,116,104,78,97,109,101,40,41,32,43,32,84,40,34,92,34,34,41,59,13,10,13,10,32,32,32,32,32,32,32,32, - 103,46,100,114,97,119,84,101,120,116,32,40,115,44,32,50,53,48,44,32,53,48,44,32,103,101,116,87,105,100,116,104,40,41,32,45,32,50,53,48, - 44,32,50,52,44,32,74,117,115,116,105,102,105,99,97,116,105,111,110,58,58,99,101,110,116,114,101,100,76,101,102,116,44,32,116,114,117,101,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,102,105,108,101,67,104,111,111,115,101,114,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,49,48,44,32,103,101, - 116,87,105,100,116,104,40,41,32,45,32,50,48,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,112,108,97,121,66,117,116,116,111,110,45, - 62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,53,48,44,32,49,48,48,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,115, - 116,111,112,66,117,116,116,111,110,45,62,115,101,116,66,111,117,110,100,115,32,40,49,49,48,44,32,53,48,44,32,49,48,48,44,32,50,52,41,59, - 13,10,32,32,32,32,32,32,32,32,97,117,100,105,111,83,101,116,116,105,110,103,115,66,117,116,116,111,110,45,62,115,101,116,66,111,117,110,100,115, - 32,40,49,48,44,32,49,50,48,44,32,50,48,48,44,32,50,52,41,59,13,10,32,32,32,32,32,32,32,32,97,117,100,105,111,83,101,116,116,105, - 110,103,115,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,40,41,59,13,10,32,32,32,32, - 32,32,32,32,107,101,121,98,111,97,114,100,67,111,109,112,111,110,101,110,116,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,50,48, - 48,44,32,103,101,116,87,105,100,116,104,40,41,32,45,32,50,48,44,32,54,48,41,59,13,10,32,32,32,32,32,32,32,32,119,97,118,101,102,111, - 114,109,67,111,109,112,111,110,101,110,116,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,51,48,48,44,32,52,48,48,44,32,56,48, - 41,59,13,10,13,10,32,32,32,32,32,32,32,32,117,112,100,97,116,101,66,117,116,116,111,110,115,40,41,59,13,10,32,32,32,32,125,13,10,13, - 10,32,32,32,32,118,111,105,100,32,117,112,100,97,116,101,66,117,116,116,111,110,115,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32, - 32,32,112,108,97,121,66,117,116,116,111,110,45,62,115,101,116,69,110,97,98,108,101,100,32,40,99,117,114,114,101,110,116,65,117,100,105,111,70,105, - 108,101,83,111,117,114,99,101,32,33,61,32,48,32,38,38,32,33,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,105,115,80,108,97, - 121,105,110,103,40,41,41,59,13,10,32,32,32,32,32,32,32,32,115,116,111,112,66,117,116,116,111,110,45,62,115,101,116,69,110,97,98,108,101,100, - 32,40,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,105,115,80,108,97,121,105,110,103,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,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,112,108,97,121,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,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,115,101,116,80,111,115,105,116,105,111,110,32,40,48,46,48, - 41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,115,116,97,114,116,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, - 115,116,111,112,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,114,97,110, - 115,112,111,114,116,83,111,117,114,99,101,46,115,116,111,112,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,97,117,100,105,111,83,101,116,116,105,110,103,115,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,47,47,32,67,114,101,97,116,101,32,97,110,32,65,117,100, - 105,111,68,101,118,105,99,101,83,101,108,101,99,116,111,114,67,111,109,112,111,110,101,110,116,32,119,104,105,99,104,32,99,111,110,116,97,105,110,115, - 32,116,104,101,32,97,117,100,105,111,32,99,104,111,105,99,101,32,119,105,100,103,101,116,115,46,46,46,13,10,13,10,32,32,32,32,32,32,32,32, - 32,32,32,32,65,117,100,105,111,68,101,118,105,99,101,83,101,108,101,99,116,111,114,67,111,109,112,111,110,101,110,116,32,97,117,100,105,111,83,101, - 116,116,105,110,103,115,67,111,109,112,32,40,97,117,100,105,111,68,101,118,105,99,101,77,97,110,97,103,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,32,32,32,32,32,32,32,32,32,32,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,44,32,49,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,32, - 50,44,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,32,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, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,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,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,47,47,32,112,114,105,110,116,32,115,111,109,101,32,116,101,120,116,32,116, + 111,32,101,120,112,108,97,105,110,32,119,104,97,116,32,115,116,97,116,101,32,119,101,39,114,101,32,105,110,46,10,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,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,41,59,10,10,32,32,32,32,32,32,32,32,83,116,114,105,110,103,32,115,59,10,10,32,32,32, + 32,32,32,32,32,105,102,32,40,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,105,115,80,108,97,121,105,110,103,40,41,41,10,32,32, + 32,32,32,32,32,32,32,32,32,32,115,32,61,32,84,40,34,112,108,97,121,105,110,103,34,41,59,10,32,32,32,32,32,32,32,32,101,108,115,101, + 10,32,32,32,32,32,32,32,32,32,32,32,32,115,32,61,32,84,40,34,115,116,111,112,112,101,100,34,41,59,10,10,32,32,32,32,32,32,32,32, + 105,102,32,40,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,32,61,61,32,48,41,10,32,32,32,32,32,32,32, + 32,32,32,32,32,115,32,43,61,32,84,40,34,32,45,32,110,111,32,115,111,117,114,99,101,32,102,105,108,101,32,115,101,108,101,99,116,101,100,34, + 41,59,10,32,32,32,32,32,32,32,32,101,108,115,101,10,32,32,32,32,32,32,32,32,32,32,32,32,115,32,43,61,32,84,40,34,32,45,32,102, + 105,108,101,58,32,92,34,34,41,32,43,32,99,117,114,114,101,110,116,70,105,108,101,46,103,101,116,70,117,108,108,80,97,116,104,78,97,109,101,40, + 41,32,43,32,84,40,34,92,34,34,41,59,10,10,32,32,32,32,32,32,32,32,103,46,100,114,97,119,84,101,120,116,32,40,115,44,32,50,53,48, + 44,32,53,48,44,32,103,101,116,87,105,100,116,104,40,41,32,45,32,50,53,48,44,32,50,52,44,32,74,117,115,116,105,102,105,99,97,116,105,111, + 110,58,58,99,101,110,116,114,101,100,76,101,102,116,44,32,116,114,117,101,41,59,10,32,32,32,32,125,10,10,32,32,32,32,118,111,105,100,32,114, + 101,115,105,122,101,100,40,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,102,105,108,101,67,104,111,111,115,101,114,45,62,115,101,116,66, + 111,117,110,100,115,32,40,49,48,44,32,49,48,44,32,103,101,116,87,105,100,116,104,40,41,32,45,32,50,48,44,32,50,52,41,59,10,32,32,32, + 32,32,32,32,32,112,108,97,121,66,117,116,116,111,110,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,53,48,44,32,49,48,48,44, + 32,50,52,41,59,10,32,32,32,32,32,32,32,32,115,116,111,112,66,117,116,116,111,110,45,62,115,101,116,66,111,117,110,100,115,32,40,49,49,48, + 44,32,53,48,44,32,49,48,48,44,32,50,52,41,59,10,32,32,32,32,32,32,32,32,97,117,100,105,111,83,101,116,116,105,110,103,115,66,117,116, + 116,111,110,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,49,50,48,44,32,50,48,48,44,32,50,52,41,59,10,32,32,32,32,32, + 32,32,32,97,117,100,105,111,83,101,116,116,105,110,103,115,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,40,41,59,10,32,32,32,32,32,32,32,32,107,101,121,98,111,97,114,100,67,111,109,112,111,110,101,110,116,45,62,115,101,116,66,111, + 117,110,100,115,32,40,49,48,44,32,50,48,48,44,32,103,101,116,87,105,100,116,104,40,41,32,45,32,50,48,44,32,54,48,41,59,10,32,32,32, + 32,32,32,32,32,119,97,118,101,102,111,114,109,67,111,109,112,111,110,101,110,116,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,51, + 48,48,44,32,52,48,48,44,32,56,48,41,59,10,10,32,32,32,32,32,32,32,32,117,112,100,97,116,101,66,117,116,116,111,110,115,40,41,59,10, + 32,32,32,32,125,10,10,32,32,32,32,118,111,105,100,32,117,112,100,97,116,101,66,117,116,116,111,110,115,40,41,10,32,32,32,32,123,10,32,32, + 32,32,32,32,32,32,112,108,97,121,66,117,116,116,111,110,45,62,115,101,116,69,110,97,98,108,101,100,32,40,99,117,114,114,101,110,116,65,117,100, + 105,111,70,105,108,101,83,111,117,114,99,101,32,33,61,32,48,32,38,38,32,33,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,105, + 115,80,108,97,121,105,110,103,40,41,41,59,10,32,32,32,32,32,32,32,32,115,116,111,112,66,117,116,116,111,110,45,62,115,101,116,69,110,97,98, + 108,101,100,32,40,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,105,115,80,108,97,121,105,110,103,40,41,41,59,10,32,32,32,32,32, + 32,32,32,114,101,112,97,105,110,116,40,41,59,10,32,32,32,32,125,10,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,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,105,102,32,40,98, + 117,116,116,111,110,32,61,61,32,112,108,97,121,66,117,116,116,111,110,41,10,32,32,32,32,32,32,32,32,123,10,32,32,32,32,32,32,32,32,32, + 32,32,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,115,101,116,80,111,115,105,116,105,111,110,32,40,48,46,48,41,59,10,32,32, + 32,32,32,32,32,32,32,32,32,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,115,116,97,114,116,40,41,59,10,32,32,32,32,32, + 32,32,32,125,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,115,116,111,112,66,117,116,116, + 111,110,41,10,32,32,32,32,32,32,32,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99, + 101,46,115,116,111,112,40,41,59,10,32,32,32,32,32,32,32,32,125,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,97,117,100,105,111,83,101,116,116,105,110,103,115,66,117,116,116,111,110,41,10,32,32,32,32,32,32,32,32,123,10,32,32, + 32,32,32,32,32,32,32,32,32,32,47,47,32,67,114,101,97,116,101,32,97,110,32,65,117,100,105,111,68,101,118,105,99,101,83,101,108,101,99,116, + 111,114,67,111,109,112,111,110,101,110,116,32,119,104,105,99,104,32,99,111,110,116,97,105,110,115,32,116,104,101,32,97,117,100,105,111,32,99,104,111, + 105,99,101,32,119,105,100,103,101,116,115,46,46,46,10,10,32,32,32,32,32,32,32,32,32,32,32,32,65,117,100,105,111,68,101,118,105,99,101,83, + 101,108,101,99,116,111,114,67,111,109,112,111,110,101,110,116,32,97,117,100,105,111,83,101,116,116,105,110,103,115,67,111,109,112,32,40,97,117,100,105, + 111,68,101,118,105,99,101,77,97,110,97,103,101,114,44,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,32,48,44,32,49, + 44,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,32,50,44,32,50,44,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,32,32,32,32,32,32,32,102,97,108,115,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32, - 46,46,46,97,110,100,32,115,104,111,119,32,105,116,32,105,110,32,97,32,68,105,97,108,111,103,87,105,110,100,111,119,46,46,46,13,10,32,32,32, - 32,32,32,32,32,32,32,32,32,97,117,100,105,111,83,101,116,116,105,110,103,115,67,111,109,112,46,115,101,116,83,105,122,101,32,40,53,48,48,44, - 32,52,48,48,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,68,105,97,108,111,103,87,105,110,100,111,119,58,58,115,104,111,119, - 77,111,100,97,108,68,105,97,108,111,103,32,40,84,40,34,65,117,100,105,111,32,83,101,116,116,105,110,103,115,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,38,97, - 117,100,105,111,83,101,116,116,105,110,103,115,67,111,109,112,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,116,104,105,115,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,67,111,108,111,117,114,115,58, - 58,97,122,117,114,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,32,32,32,32,32,32,32,116,114,117,101,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,13,10, - 32,32,32,32,118,111,105,100,32,102,105,108,101,110,97,109,101,67,111,109,112,111,110,101,110,116,67,104,97,110,103,101,100,32,40,70,105,108,101,110, - 97,109,101,67,111,109,112,111,110,101,110,116,42,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,116,104,105,115,32,105, - 115,32,99,97,108,108,101,100,32,119,104,101,110,32,116,104,101,32,117,115,101,114,32,99,104,97,110,103,101,115,32,116,104,101,32,102,105,108,101,110, - 97,109,101,32,105,110,32,116,104,101,32,102,105,108,101,32,99,104,111,111,115,101,114,32,98,111,120,13,10,13,10,32,32,32,32,32,32,32,32,70, - 105,108,101,32,97,117,100,105,111,70,105,108,101,32,40,102,105,108,101,67,104,111,111,115,101,114,45,62,103,101,116,67,117,114,114,101,110,116,70,105, - 108,101,40,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,117,110,108,111,97,100,32,116,104,101,32,112,114,101,118,105,111,117,115, - 32,102,105,108,101,32,115,111,117,114,99,101,32,97,110,100,32,100,101,108,101,116,101,32,105,116,46,46,13,10,32,32,32,32,32,32,32,32,116,114, - 97,110,115,112,111,114,116,83,111,117,114,99,101,46,115,116,111,112,40,41,59,13,10,32,32,32,32,32,32,32,32,116,114,97,110,115,112,111,114,116, - 83,111,117,114,99,101,46,115,101,116,83,111,117,114,99,101,32,40,48,41,59,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65,110,100, - 90,101,114,111,32,40,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,41,59,13,10,13,10,32,32,32,32,32,32, - 32,32,47,47,32,99,114,101,97,116,101,32,97,32,110,101,119,32,102,105,108,101,32,115,111,117,114,99,101,32,102,114,111,109,32,116,104,101,32,102, - 105,108,101,46,46,13,10,13,10,32,32,32,32,32,32,32,32,47,47,32,103,101,116,32,97,32,102,111,114,109,97,116,32,109,97,110,97,103,101,114, - 32,97,110,100,32,115,101,116,32,105,116,32,117,112,32,119,105,116,104,32,116,104,101,32,98,97,115,105,99,32,116,121,112,101,115,32,40,119,97,118, - 32,97,110,100,32,97,105,102,102,41,46,13,10,32,32,32,32,32,32,32,32,65,117,100,105,111,70,111,114,109,97,116,77,97,110,97,103,101,114,32, - 102,111,114,109,97,116,77,97,110,97,103,101,114,59,13,10,32,32,32,32,32,32,32,32,102,111,114,109,97,116,77,97,110,97,103,101,114,46,114,101, - 103,105,115,116,101,114,66,97,115,105,99,70,111,114,109,97,116,115,40,41,59,13,10,13,10,32,32,32,32,32,32,32,32,65,117,100,105,111,70,111, - 114,109,97,116,82,101,97,100,101,114,42,32,114,101,97,100,101,114,32,61,32,102,111,114,109,97,116,77,97,110,97,103,101,114,46,99,114,101,97,116, - 101,82,101,97,100,101,114,70,111,114,32,40,97,117,100,105,111,70,105,108,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,114, - 101,97,100,101,114,32,33,61,32,48,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,117,114,114, - 101,110,116,70,105,108,101,32,61,32,97,117,100,105,111,70,105,108,101,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32,99,117,114,114, - 101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,32,61,32,110,101,119,32,65,117,100,105,111,70,111,114,109,97,116,82,101,97,100, - 101,114,83,111,117,114,99,101,32,40,114,101,97,100,101,114,44,32,116,114,117,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,32,32,32,32, - 47,47,32,46,46,97,110,100,32,112,108,117,103,32,105,116,32,105,110,116,111,32,111,117,114,32,116,114,97,110,115,112,111,114,116,32,115,111,117,114, - 99,101,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,114,97,110,115,112,111,114,116,83,111,117,114,99,101,46,115,101,116,83,111,117,114,99, - 101,32,40,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,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,32,32,32,51,50,55,54,56,44,32,47,47,32,116,101,108, - 108,115,32,105,116,32,116,111,32,98,117,102,102,101,114,32,116,104,105,115,32,109,97,110,121,32,115,97,109,112,108,101,115,32,97,104,101,97,100,13, + 32,32,32,32,32,32,32,32,116,114,117,101,44,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,32,102,97,108,115,101,41, + 59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,46,46,46,97,110,100,32,115,104,111,119,32,105,116,32,105,110,32,97,32,68,105, + 97,108,111,103,87,105,110,100,111,119,46,46,46,10,32,32,32,32,32,32,32,32,32,32,32,32,97,117,100,105,111,83,101,116,116,105,110,103,115,67, + 111,109,112,46,115,101,116,83,105,122,101,32,40,53,48,48,44,32,52,48,48,41,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,68,105,97, + 108,111,103,87,105,110,100,111,119,58,58,115,104,111,119,77,111,100,97,108,68,105,97,108,111,103,32,40,84,40,34,65,117,100,105,111,32,83,101,116, + 116,105,110,103,115,34,41,44,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,38,97,117,100,105,111,83,101,116,116,105,110,103,115,67,111,109,112,44,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,116,104,105,115,44, 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, - 114,101,97,100,101,114,45,62,115,97,109,112,108,101,82,97,116,101,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,117,112,100,97,116,101,66,117,116,116,111,110,115,40,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,41,13,10,32,32,32,32,123,13,10,32,32, - 32,32,32,32,32,32,47,47,32,99,97,108,108,98,97,99,107,32,102,114,111,109,32,116,104,101,32,116,114,97,110,115,112,111,114,116,32,115,111,117, - 114,99,101,32,116,111,32,116,101,108,108,32,117,115,32,116,104,97,116,32,112,108,97,121,32,104,97,115,13,10,32,32,32,32,32,32,32,32,47,47, - 32,115,116,97,114,116,101,100,32,111,114,32,115,116,111,112,112,101,100,44,32,115,111,32,117,112,100,97,116,101,32,111,117,114,32,98,117,116,116,111, - 110,115,46,46,13,10,32,32,32,32,32,32,32,32,117,112,100,97,116,101,66,117,116,116,111,110,115,40,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, + 32,32,32,32,67,111,108,111,117,114,115,58,58,97,122,117,114,101,44,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,116,114,117,101,41,59,10,32,32,32,32,32,32,32,32,125,10, + 32,32,32,32,125,10,10,32,32,32,32,118,111,105,100,32,102,105,108,101,110,97,109,101,67,111,109,112,111,110,101,110,116,67,104,97,110,103,101,100, + 32,40,70,105,108,101,110,97,109,101,67,111,109,112,111,110,101,110,116,42,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,47,47,32,116, + 104,105,115,32,105,115,32,99,97,108,108,101,100,32,119,104,101,110,32,116,104,101,32,117,115,101,114,32,99,104,97,110,103,101,115,32,116,104,101,32, + 102,105,108,101,110,97,109,101,32,105,110,32,116,104,101,32,102,105,108,101,32,99,104,111,111,115,101,114,32,98,111,120,10,10,32,32,32,32,32,32, + 32,32,70,105,108,101,32,97,117,100,105,111,70,105,108,101,32,40,102,105,108,101,67,104,111,111,115,101,114,45,62,103,101,116,67,117,114,114,101,110, + 116,70,105,108,101,40,41,41,59,10,10,32,32,32,32,32,32,32,32,47,47,32,117,110,108,111,97,100,32,116,104,101,32,112,114,101,118,105,111,117, + 115,32,102,105,108,101,32,115,111,117,114,99,101,32,97,110,100,32,100,101,108,101,116,101,32,105,116,46,46,10,32,32,32,32,32,32,32,32,116,114, + 97,110,115,112,111,114,116,83,111,117,114,99,101,46,115,116,111,112,40,41,59,10,32,32,32,32,32,32,32,32,116,114,97,110,115,112,111,114,116,83, + 111,117,114,99,101,46,115,101,116,83,111,117,114,99,101,32,40,48,41,59,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65,110,100,90,101, + 114,111,32,40,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114,99,101,41,59,10,10,32,32,32,32,32,32,32,32,47,47, + 32,99,114,101,97,116,101,32,97,32,110,101,119,32,102,105,108,101,32,115,111,117,114,99,101,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46, + 46,10,10,32,32,32,32,32,32,32,32,47,47,32,103,101,116,32,97,32,102,111,114,109,97,116,32,109,97,110,97,103,101,114,32,97,110,100,32,115, + 101,116,32,105,116,32,117,112,32,119,105,116,104,32,116,104,101,32,98,97,115,105,99,32,116,121,112,101,115,32,40,119,97,118,32,97,110,100,32,97, + 105,102,102,41,46,10,32,32,32,32,32,32,32,32,65,117,100,105,111,70,111,114,109,97,116,77,97,110,97,103,101,114,32,102,111,114,109,97,116,77, + 97,110,97,103,101,114,59,10,32,32,32,32,32,32,32,32,102,111,114,109,97,116,77,97,110,97,103,101,114,46,114,101,103,105,115,116,101,114,66,97, + 115,105,99,70,111,114,109,97,116,115,40,41,59,10,10,32,32,32,32,32,32,32,32,65,117,100,105,111,70,111,114,109,97,116,82,101,97,100,101,114, + 42,32,114,101,97,100,101,114,32,61,32,102,111,114,109,97,116,77,97,110,97,103,101,114,46,99,114,101,97,116,101,82,101,97,100,101,114,70,111,114, + 32,40,97,117,100,105,111,70,105,108,101,41,59,10,10,32,32,32,32,32,32,32,32,105,102,32,40,114,101,97,100,101,114,32,33,61,32,48,41,10, + 32,32,32,32,32,32,32,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,99,117,114,114,101,110,116,70,105,108,101,32,61,32,97,117,100,105, + 111,70,105,108,101,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101,83,111,117,114, + 99,101,32,61,32,110,101,119,32,65,117,100,105,111,70,111,114,109,97,116,82,101,97,100,101,114,83,111,117,114,99,101,32,40,114,101,97,100,101,114, + 44,32,116,114,117,101,41,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,47,47,32,46,46,97,110,100,32,112,108,117,103,32,105,116,32,105, + 110,116,111,32,111,117,114,32,116,114,97,110,115,112,111,114,116,32,115,111,117,114,99,101,10,32,32,32,32,32,32,32,32,32,32,32,32,116,114,97, + 110,115,112,111,114,116,83,111,117,114,99,101,46,115,101,116,83,111,117,114,99,101,32,40,99,117,114,114,101,110,116,65,117,100,105,111,70,105,108,101, + 83,111,117,114,99,101,44,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,51,50,55,54,56,44,32,47,47,32,116,101,108,108,115,32,105,116,32,116,111,32,98,117,102,102,101,114,32,116,104,105,115, + 32,109,97,110,121,32,115,97,109,112,108,101,115,32,97,104,101,97,100,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,114,101,97,100,101,114,45,62,115,97,109,112,108,101,82,97,116,101,41,59,10, + 32,32,32,32,32,32,32,32,125,10,10,32,32,32,32,32,32,32,32,117,112,100,97,116,101,66,117,116,116,111,110,115,40,41,59,10,32,32,32,32, + 125,10,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,41,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,47,47,32,99,97,108,108,98,97,99,107,32,102,114,111,109,32,116,104,101,32,116,114, + 97,110,115,112,111,114,116,32,115,111,117,114,99,101,32,116,111,32,116,101,108,108,32,117,115,32,116,104,97,116,32,112,108,97,121,32,104,97,115,10, + 32,32,32,32,32,32,32,32,47,47,32,115,116,97,114,116,101,100,32,111,114,32,115,116,111,112,112,101,100,44,32,115,111,32,117,112,100,97,116,101, + 32,111,117,114,32,98,117,116,116,111,110,115,46,46,10,32,32,32,32,32,32,32,32,117,112,100,97,116,101,66,117,116,116,111,110,115,40,41,59,10, + 32,32,32,32,125,10,125,59,10,10,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,13,10,67,111,109,112,111,110,101,110,116,42,32,99,114,101,97,116,101,65,117,100,105,111,68,101,109,111,40,41,13,10,123, - 13,10,32,32,32,32,114,101,116,117,114,110,32,110,101,119,32,65,117,100,105,111,68,101,109,111,40,41,59,13,10,125,13,10,0,0}; + 61,61,61,61,61,61,61,61,61,61,61,10,67,111,109,112,111,110,101,110,116,42,32,99,114,101,97,116,101,65,117,100,105,111,68,101,109,111,40,41, + 10,123,10,32,32,32,32,114,101,116,117,114,110,32,110,101,119,32,65,117,100,105,111,68,101,109,111,40,41,59,10,125,10,0,0}; const char* BinaryData::audiodemo_cpp = (const char*) temp1; static const unsigned char temp2[] = {82,73,70,70,4,181,0,0,87,65,86,69,102,109,116,32,16,0,0,0,1,0,1,0,34,86,0,0,68,172,0,0,2,0,16,0,98,101,120,116, diff --git a/extras/juce demo/src/BinaryData.h b/extras/juce demo/src/BinaryData.h index a218384e39..506685a930 100644 --- a/extras/juce demo/src/BinaryData.h +++ b/extras/juce demo/src/BinaryData.h @@ -6,7 +6,7 @@ namespace BinaryData { extern const char* audiodemo_cpp; - const int audiodemo_cppSize = 23434; + const int audiodemo_cppSize = 22793; extern const char* cello_wav; const int cello_wavSize = 46348; diff --git a/extras/juce demo/src/binarydata/AudioDemo.cpp b/extras/juce demo/src/binarydata/AudioDemo.cpp index ee410345b8..a11aef18dd 100644 --- a/extras/juce demo/src/binarydata/AudioDemo.cpp +++ b/extras/juce demo/src/binarydata/AudioDemo.cpp @@ -1,641 +1,641 @@ -/* - ============================================================================== - - 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 "../jucedemo_headers.h" - - -//============================================================================== -/** Our demo synth only has one type of sound, and it's very basic.. -*/ -class SineWaveSound : public SynthesiserSound -{ -public: - SineWaveSound (const BitArray& midiNotes_) - : midiNotes (midiNotes_) - { - } - - bool appliesToNote (const int midiNoteNumber) - { - return midiNotes [midiNoteNumber]; - } - - bool appliesToChannel (const int midiChannel) { return true; } - -private: - // this will contain the notes that this sound is attached to. - BitArray midiNotes; -}; - - -//============================================================================== -/** Our demo synth voice just plays a sine wave.. -*/ -class SineWaveVoice : public SynthesiserVoice -{ -public: - SineWaveVoice() - : angleDelta (0.0), - tailOff (0.0) - { - } - - bool canPlaySound (SynthesiserSound* sound) - { - return dynamic_cast (sound) != 0; - } - - void startNote (const int midiNoteNumber, const float velocity, - SynthesiserSound* sound, const int currentPitchWheelPosition) - { - currentAngle = 0.0; - level = velocity * 0.15; - tailOff = 0.0; - - double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber); - double cyclesPerSample = cyclesPerSecond / getSampleRate(); - - angleDelta = cyclesPerSample * 2.0 * double_Pi; - } - - void stopNote (const bool allowTailOff) - { - if (allowTailOff) - { - // start a tail-off by setting this flag. The render callback will pick up on - // this and do a fade out, calling clearCurrentNote() when it's finished. - - if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the - // stopNote method could be called more than once. - tailOff = 1.0; - } - else - { - // we're being told to stop playing immediately, so reset everything.. - - clearCurrentNote(); - angleDelta = 0.0; - } - } - - void pitchWheelMoved (const int newValue) - { - // can't be bothered implementing this for the demo! - } - - void controllerMoved (const int controllerNumber, const int newValue) - { - // not interested in controllers in this case. - } - - void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) - { - if (angleDelta != 0.0) - { - if (tailOff > 0) - { - while (--numSamples >= 0) - { - const float currentSample = (float) (sin (currentAngle) * level * tailOff); - - for (int i = outputBuffer.getNumChannels(); --i >= 0;) - *outputBuffer.getSampleData (i, startSample) += currentSample; - - currentAngle += angleDelta; - ++startSample; - - tailOff *= 0.99; - - if (tailOff <= 0.005) - { - clearCurrentNote(); - - angleDelta = 0.0; - break; - } - } - } - else - { - while (--numSamples >= 0) - { - const float currentSample = (float) (sin (currentAngle) * level); - - for (int i = outputBuffer.getNumChannels(); --i >= 0;) - *outputBuffer.getSampleData (i, startSample) += currentSample; - - currentAngle += angleDelta; - ++startSample; - } - } - } - } - -private: - double currentAngle, angleDelta, level, tailOff; -}; - -//============================================================================== -/** This is an audio source that streams the output of our demo synth. -*/ -class SynthAudioSource : public AudioSource -{ -public: - //============================================================================== - // this collects real-time midi messages from the midi input device, and - // turns them into blocks that we can process in our audio callback - MidiMessageCollector midiCollector; - - // this represents the state of which keys on our on-screen keyboard are held - // down. When the mouse is clicked on the keyboard component, this object also - // generates midi messages for this, which we can pass on to our synth. - MidiKeyboardState keyboardState; - - // the synth itself! - Synthesiser synth; - - //============================================================================== - SynthAudioSource() - { - // we'll be mixing two different types of sound, so here we'll create two - // sets of note maps, putting each sound on a different octave of the keyboard: - BitArray sinewaveNotes, samplerNotes; - - int i; - for (i = 0; i < 128; ++i) - { - if (((i / 12) & 1) != 0) - sinewaveNotes.setBit (i); - else - samplerNotes.setBit (i); - } - - // add a wave sound, which will get applied to some of the notes.. - synth.addSound (new SineWaveSound (sinewaveNotes)); - - // give our synth a few voices that can play the wave sound.. - for (i = 4; --i >= 0;) - synth.addVoice (new SineWaveVoice()); - - WavAudioFormat wavFormat; - AudioFormatReader* audioReader - = wavFormat.createReaderFor (new MemoryInputStream (BinaryData::cello_wav, - BinaryData::cello_wavSize, - false), - true); - - synth.addSound (new SamplerSound (T("demo sound"), - *audioReader, - samplerNotes, - 74, // root midi note - 0.1, // attack time - 0.1, // release time - 10.0 // maximum sample length - )); - - delete audioReader; - - // and give the synth some sampler voices to play the sampled sound.. - for (i = 4; --i >= 0;) - synth.addVoice (new SamplerVoice()); - } - - void prepareToPlay (int samplesPerBlockExpected, - double sampleRate) - { - midiCollector.reset (sampleRate); - - synth.setCurrentPlaybackSampleRate (sampleRate); - } - - void releaseResources() - { - } - - void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) - { - // the synth always adds its output to the audio buffer, so we have to clear it - // first.. - bufferToFill.clearActiveBufferRegion(); - - // fill a midi buffer with incoming messages from the midi input. - MidiBuffer incomingMidi; - midiCollector.removeNextBlockOfMessages (incomingMidi, bufferToFill.numSamples); - - // pass these messages to the keyboard state so that it can update the component - // to show on-screen which keys are being pressed on the physical midi keyboard. - // This call will also add midi messages to the buffer which were generated by - // the mouse-clicking on the on-screen keyboard. - keyboardState.processNextMidiBuffer (incomingMidi, 0, bufferToFill.numSamples, true); - - // and now get the synth to process the midi events and generate its output. - synth.renderNextBlock (*bufferToFill.buffer, incomingMidi, 0, bufferToFill.numSamples); - } -}; - -//============================================================================== -class AudioInputWaveformDisplay : public Component, - public Timer, - public AudioIODeviceCallback -{ -public: - AudioInputWaveformDisplay() - { - bufferPos = 0; - bufferSize = 2048; - circularBuffer = (float*) juce_calloc (sizeof (float) * bufferSize); - currentInputLevel = 0.0f; - numSamplesIn = 0; - - setOpaque (true); - startTimer (1000 / 50); // repaint every 1/50 of a second - } - - ~AudioInputWaveformDisplay() - { - juce_free (circularBuffer); - } - - void paint (Graphics& g) - { - g.fillAll (Colours::black); - g.setColour (Colours::lightgreen); - - const float halfHeight = getHeight() * 0.5f; - - int bp = bufferPos; - - for (int x = getWidth(); --x >= 0;) - { - const int samplesAgo = getWidth() - x; - const float level = circularBuffer [(bp + bufferSize - samplesAgo) % bufferSize]; - - if (level > 0.01f) - g.drawLine ((float) x, halfHeight - halfHeight * level, - (float) x, halfHeight + halfHeight * level); - } - } - - void timerCallback() - { - repaint(); - } - - void addSample (const float sample) - { - currentInputLevel += fabsf (sample); - - const int samplesToAverage = 128; - - if (++numSamplesIn > samplesToAverage) - { - circularBuffer [bufferPos++ % bufferSize] = currentInputLevel / samplesToAverage; - - numSamplesIn = 0; - currentInputLevel = 0.0f; - } - } - - void audioDeviceIOCallback (const float** inputChannelData, - int totalNumInputChannels, - float** outputChannelData, - int totalNumOutputChannels, - int numSamples) - { - for (int i = 0; i < totalNumInputChannels; ++i) - { - if (inputChannelData [i] != 0) - { - for (int j = 0; j < numSamples; ++j) - addSample (inputChannelData [i][j]); - - break; - } - } - } - - void audioDeviceAboutToStart (AudioIODevice*) - { - zeromem (circularBuffer, sizeof (float) * bufferSize); - } - - void audioDeviceStopped() - { - zeromem (circularBuffer, sizeof (float) * bufferSize); - } - -private: - float* circularBuffer; - float currentInputLevel; - int volatile bufferPos, bufferSize, numSamplesIn; -}; - - -//============================================================================== -class AudioDemo : public Component, - public FilenameComponentListener, - public ButtonListener, - public ChangeListener, - public AudioIODeviceCallback -{ - //============================================================================== - FilenameComponent* fileChooser; - TextButton* playButton; - TextButton* stopButton; - TextButton* audioSettingsButton; - - MidiKeyboardComponent* keyboardComponent; - AudioInputWaveformDisplay* waveformComponent; - - //============================================================================== - // this wraps the actual audio device - AudioDeviceManager audioDeviceManager; - - // this allows an audio source to be streamed to the IO device - AudioSourcePlayer audioSourcePlayer; - - // this controls the playback of a positionable audio stream, handling the - // starting/stopping and sample-rate conversion - AudioTransportSource transportSource; - - // this source contains our synth, and generates its output - SynthAudioSource synthSource; - - // this source is used to mix together the output from our synth source - // and wave player source - MixerAudioSource mixerSource; - - // this is the actual stream that's going to read from the audio file. - AudioFormatReaderSource* currentAudioFileSource; - - File currentFile; - -public: - //============================================================================== - AudioDemo() - { - setName (T("Audio")); - - currentAudioFileSource = 0; - - //============================================================================== - AudioFormatManager formatManager; - formatManager.registerBasicFormats(); - - addAndMakeVisible (fileChooser = new FilenameComponent (T("audiofile"), - File::nonexistent, - true, false, false, - formatManager.getWildcardForAllFormats(), - String::empty, - T("(choose a WAV or AIFF file to play)"))); - fileChooser->addListener (this); - fileChooser->setBrowseButtonText (T("browse")); - - addAndMakeVisible (playButton = new TextButton (T("play"), - T("click here to play the current audio file"))); - playButton->addButtonListener (this); - playButton->setColour (TextButton::buttonColourId, Colours::lightgreen); - playButton->setColour (TextButton::buttonOnColourId, Colours::lightgreen); - playButton->setConnectedEdges (Button::ConnectedOnRight); - - addAndMakeVisible (stopButton = new TextButton (T("stop"), - T("click here to play the current audio file"))); - stopButton->addButtonListener (this); - stopButton->setColour (TextButton::buttonColourId, Colours::red); - stopButton->setColour (TextButton::buttonOnColourId, Colours::red); - stopButton->setConnectedEdges (Button::ConnectedOnLeft); - - addAndMakeVisible (audioSettingsButton = new TextButton (T("show audio settings..."), - T("click here to change the audio device settings"))); - audioSettingsButton->addButtonListener (this); - - addAndMakeVisible (keyboardComponent = new MidiKeyboardComponent (synthSource.keyboardState, - MidiKeyboardComponent::horizontalKeyboard)); - - - addAndMakeVisible (waveformComponent = new AudioInputWaveformDisplay()); - - //============================================================================== - // register for start/stop messages from the transport source.. - transportSource.addChangeListener (this); - - // and initialise the device manager with no settings so that it picks a - // default device to use. - const String error (audioDeviceManager.initialise (1, /* number of input channels */ - 2, /* number of output channels */ - 0, /* no XML settings.. */ - true /* select default device on failure */)); - - if (error.isNotEmpty()) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, - T("Audio Demo"), - T("Couldn't open an output device!\n\n") + error); - } - else - { - // add the two audio sources to our mixer.. - mixerSource.addInputSource (&transportSource, false); - mixerSource.addInputSource (&synthSource, false); - - // ..and connect the mixer to our source player. - audioSourcePlayer.setSource (&mixerSource); - - // start the IO device pulling its data from our callback.. - audioDeviceManager.setAudioCallback (this); - - // and we need to send midi input to our synth for processing - audioDeviceManager.addMidiInputCallback (String::empty, &synthSource.midiCollector); - } - } - - ~AudioDemo() - { - audioDeviceManager.removeMidiInputCallback (&synthSource.midiCollector); - audioDeviceManager.setAudioCallback (0); - - transportSource.removeChangeListener (this); - - transportSource.setSource (0); - deleteAndZero (currentAudioFileSource); - - audioSourcePlayer.setSource (0); - - deleteAllChildren(); - } - - //============================================================================== - void audioDeviceIOCallback (const float** inputChannelData, - int totalNumInputChannels, - float** outputChannelData, - int totalNumOutputChannels, - int numSamples) - { - // pass the audio callback on to our player source, and also the waveform display comp - audioSourcePlayer.audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples); - waveformComponent->audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples); - } - - void audioDeviceAboutToStart (AudioIODevice* device) - { - audioSourcePlayer.audioDeviceAboutToStart (device); - waveformComponent->audioDeviceAboutToStart (device); - } - - void audioDeviceStopped() - { - audioSourcePlayer.audioDeviceStopped(); - waveformComponent->audioDeviceStopped(); - } - - //============================================================================== - void paint (Graphics& g) - { - // print some text to explain what state we're in. - - g.setColour (Colours::black); - g.setFont (14.0f); - - String s; - - if (transportSource.isPlaying()) - s = T("playing"); - else - s = T("stopped"); - - if (currentAudioFileSource == 0) - s += T(" - no source file selected"); - else - s += T(" - file: \"") + currentFile.getFullPathName() + T("\""); - - g.drawText (s, 250, 50, getWidth() - 250, 24, Justification::centredLeft, true); - } - - void resized() - { - fileChooser->setBounds (10, 10, getWidth() - 20, 24); - playButton->setBounds (10, 50, 100, 24); - stopButton->setBounds (110, 50, 100, 24); - audioSettingsButton->setBounds (10, 120, 200, 24); - audioSettingsButton->changeWidthToFitText(); - keyboardComponent->setBounds (10, 200, getWidth() - 20, 60); - waveformComponent->setBounds (10, 300, 400, 80); - - updateButtons(); - } - - void updateButtons() - { - playButton->setEnabled (currentAudioFileSource != 0 && ! transportSource.isPlaying()); - stopButton->setEnabled (transportSource.isPlaying()); - repaint(); - } - - void buttonClicked (Button* button) - { - if (button == playButton) - { - transportSource.setPosition (0.0); - transportSource.start(); - } - else if (button == stopButton) - { - transportSource.stop(); - } - else if (button == audioSettingsButton) - { - // Create an AudioDeviceSelectorComponent which contains the audio choice widgets... - - AudioDeviceSelectorComponent audioSettingsComp (audioDeviceManager, - 0, 1, - 2, 2, - true, - false); - - // ...and show it in a DialogWindow... - audioSettingsComp.setSize (500, 400); - - DialogWindow::showModalDialog (T("Audio Settings"), - &audioSettingsComp, - this, - Colours::azure, - true); - } - } - - void filenameComponentChanged (FilenameComponent*) - { - // this is called when the user changes the filename in the file chooser box - - File audioFile (fileChooser->getCurrentFile()); - - // unload the previous file source and delete it.. - transportSource.stop(); - transportSource.setSource (0); - deleteAndZero (currentAudioFileSource); - - // create a new file source from the file.. - - // get a format manager and set it up with the basic types (wav and aiff). - AudioFormatManager formatManager; - formatManager.registerBasicFormats(); - - AudioFormatReader* reader = formatManager.createReaderFor (audioFile); - - if (reader != 0) - { - currentFile = audioFile; - - currentAudioFileSource = new AudioFormatReaderSource (reader, true); - - // ..and plug it into our transport source - transportSource.setSource (currentAudioFileSource, - 32768, // tells it to buffer this many samples ahead - reader->sampleRate); - } - - updateButtons(); - } - - void changeListenerCallback (void*) - { - // callback from the transport source to tell us that play has - // started or stopped, so update our buttons.. - updateButtons(); - } -}; - - -//============================================================================== -Component* createAudioDemo() -{ - return new AudioDemo(); -} +/* + ============================================================================== + + 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 "../jucedemo_headers.h" + + +//============================================================================== +/** Our demo synth only has one type of sound, and it's very basic.. +*/ +class SineWaveSound : public SynthesiserSound +{ +public: + SineWaveSound (const BitArray& midiNotes_) + : midiNotes (midiNotes_) + { + } + + bool appliesToNote (const int midiNoteNumber) + { + return midiNotes [midiNoteNumber]; + } + + bool appliesToChannel (const int midiChannel) { return true; } + +private: + // this will contain the notes that this sound is attached to. + BitArray midiNotes; +}; + + +//============================================================================== +/** Our demo synth voice just plays a sine wave.. +*/ +class SineWaveVoice : public SynthesiserVoice +{ +public: + SineWaveVoice() + : angleDelta (0.0), + tailOff (0.0) + { + } + + bool canPlaySound (SynthesiserSound* sound) + { + return dynamic_cast (sound) != 0; + } + + void startNote (const int midiNoteNumber, const float velocity, + SynthesiserSound* sound, const int currentPitchWheelPosition) + { + currentAngle = 0.0; + level = velocity * 0.15; + tailOff = 0.0; + + double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber); + double cyclesPerSample = cyclesPerSecond / getSampleRate(); + + angleDelta = cyclesPerSample * 2.0 * double_Pi; + } + + void stopNote (const bool allowTailOff) + { + if (allowTailOff) + { + // start a tail-off by setting this flag. The render callback will pick up on + // this and do a fade out, calling clearCurrentNote() when it's finished. + + if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the + // stopNote method could be called more than once. + tailOff = 1.0; + } + else + { + // we're being told to stop playing immediately, so reset everything.. + + clearCurrentNote(); + angleDelta = 0.0; + } + } + + void pitchWheelMoved (const int newValue) + { + // can't be bothered implementing this for the demo! + } + + void controllerMoved (const int controllerNumber, const int newValue) + { + // not interested in controllers in this case. + } + + void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) + { + if (angleDelta != 0.0) + { + if (tailOff > 0) + { + while (--numSamples >= 0) + { + const float currentSample = (float) (sin (currentAngle) * level * tailOff); + + for (int i = outputBuffer.getNumChannels(); --i >= 0;) + *outputBuffer.getSampleData (i, startSample) += currentSample; + + currentAngle += angleDelta; + ++startSample; + + tailOff *= 0.99; + + if (tailOff <= 0.005) + { + clearCurrentNote(); + + angleDelta = 0.0; + break; + } + } + } + else + { + while (--numSamples >= 0) + { + const float currentSample = (float) (sin (currentAngle) * level); + + for (int i = outputBuffer.getNumChannels(); --i >= 0;) + *outputBuffer.getSampleData (i, startSample) += currentSample; + + currentAngle += angleDelta; + ++startSample; + } + } + } + } + +private: + double currentAngle, angleDelta, level, tailOff; +}; + +//============================================================================== +/** This is an audio source that streams the output of our demo synth. +*/ +class SynthAudioSource : public AudioSource +{ +public: + //============================================================================== + // this collects real-time midi messages from the midi input device, and + // turns them into blocks that we can process in our audio callback + MidiMessageCollector midiCollector; + + // this represents the state of which keys on our on-screen keyboard are held + // down. When the mouse is clicked on the keyboard component, this object also + // generates midi messages for this, which we can pass on to our synth. + MidiKeyboardState keyboardState; + + // the synth itself! + Synthesiser synth; + + //============================================================================== + SynthAudioSource() + { + // we'll be mixing two different types of sound, so here we'll create two + // sets of note maps, putting each sound on a different octave of the keyboard: + BitArray sinewaveNotes, samplerNotes; + + int i; + for (i = 0; i < 128; ++i) + { + if (((i / 12) & 1) != 0) + sinewaveNotes.setBit (i); + else + samplerNotes.setBit (i); + } + + // add a wave sound, which will get applied to some of the notes.. + synth.addSound (new SineWaveSound (sinewaveNotes)); + + // give our synth a few voices that can play the wave sound.. + for (i = 4; --i >= 0;) + synth.addVoice (new SineWaveVoice()); + + WavAudioFormat wavFormat; + AudioFormatReader* audioReader + = wavFormat.createReaderFor (new MemoryInputStream (BinaryData::cello_wav, + BinaryData::cello_wavSize, + false), + true); + + synth.addSound (new SamplerSound (T("demo sound"), + *audioReader, + samplerNotes, + 74, // root midi note + 0.1, // attack time + 0.1, // release time + 10.0 // maximum sample length + )); + + delete audioReader; + + // and give the synth some sampler voices to play the sampled sound.. + for (i = 4; --i >= 0;) + synth.addVoice (new SamplerVoice()); + } + + void prepareToPlay (int samplesPerBlockExpected, + double sampleRate) + { + midiCollector.reset (sampleRate); + + synth.setCurrentPlaybackSampleRate (sampleRate); + } + + void releaseResources() + { + } + + void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) + { + // the synth always adds its output to the audio buffer, so we have to clear it + // first.. + bufferToFill.clearActiveBufferRegion(); + + // fill a midi buffer with incoming messages from the midi input. + MidiBuffer incomingMidi; + midiCollector.removeNextBlockOfMessages (incomingMidi, bufferToFill.numSamples); + + // pass these messages to the keyboard state so that it can update the component + // to show on-screen which keys are being pressed on the physical midi keyboard. + // This call will also add midi messages to the buffer which were generated by + // the mouse-clicking on the on-screen keyboard. + keyboardState.processNextMidiBuffer (incomingMidi, 0, bufferToFill.numSamples, true); + + // and now get the synth to process the midi events and generate its output. + synth.renderNextBlock (*bufferToFill.buffer, incomingMidi, 0, bufferToFill.numSamples); + } +}; + +//============================================================================== +class AudioInputWaveformDisplay : public Component, + public Timer, + public AudioIODeviceCallback +{ +public: + AudioInputWaveformDisplay() + { + bufferPos = 0; + bufferSize = 2048; + circularBuffer = (float*) juce_calloc (sizeof (float) * bufferSize); + currentInputLevel = 0.0f; + numSamplesIn = 0; + + setOpaque (true); + startTimer (1000 / 50); // repaint every 1/50 of a second + } + + ~AudioInputWaveformDisplay() + { + juce_free (circularBuffer); + } + + void paint (Graphics& g) + { + g.fillAll (Colours::black); + g.setColour (Colours::lightgreen); + + const float halfHeight = getHeight() * 0.5f; + + int bp = bufferPos; + + for (int x = getWidth(); --x >= 0;) + { + const int samplesAgo = getWidth() - x; + const float level = circularBuffer [(bp + bufferSize - samplesAgo) % bufferSize]; + + if (level > 0.01f) + g.drawLine ((float) x, halfHeight - halfHeight * level, + (float) x, halfHeight + halfHeight * level); + } + } + + void timerCallback() + { + repaint(); + } + + void addSample (const float sample) + { + currentInputLevel += fabsf (sample); + + const int samplesToAverage = 128; + + if (++numSamplesIn > samplesToAverage) + { + circularBuffer [bufferPos++ % bufferSize] = currentInputLevel / samplesToAverage; + + numSamplesIn = 0; + currentInputLevel = 0.0f; + } + } + + void audioDeviceIOCallback (const float** inputChannelData, + int totalNumInputChannels, + float** outputChannelData, + int totalNumOutputChannels, + int numSamples) + { + for (int i = 0; i < totalNumInputChannels; ++i) + { + if (inputChannelData [i] != 0) + { + for (int j = 0; j < numSamples; ++j) + addSample (inputChannelData [i][j]); + + break; + } + } + } + + void audioDeviceAboutToStart (AudioIODevice*) + { + zeromem (circularBuffer, sizeof (float) * bufferSize); + } + + void audioDeviceStopped() + { + zeromem (circularBuffer, sizeof (float) * bufferSize); + } + +private: + float* circularBuffer; + float currentInputLevel; + int volatile bufferPos, bufferSize, numSamplesIn; +}; + + +//============================================================================== +class AudioDemo : public Component, + public FilenameComponentListener, + public ButtonListener, + public ChangeListener, + public AudioIODeviceCallback +{ + //============================================================================== + FilenameComponent* fileChooser; + TextButton* playButton; + TextButton* stopButton; + TextButton* audioSettingsButton; + + MidiKeyboardComponent* keyboardComponent; + AudioInputWaveformDisplay* waveformComponent; + + //============================================================================== + // this wraps the actual audio device + AudioDeviceManager audioDeviceManager; + + // this allows an audio source to be streamed to the IO device + AudioSourcePlayer audioSourcePlayer; + + // this controls the playback of a positionable audio stream, handling the + // starting/stopping and sample-rate conversion + AudioTransportSource transportSource; + + // this source contains our synth, and generates its output + SynthAudioSource synthSource; + + // this source is used to mix together the output from our synth source + // and wave player source + MixerAudioSource mixerSource; + + // this is the actual stream that's going to read from the audio file. + AudioFormatReaderSource* currentAudioFileSource; + + File currentFile; + +public: + //============================================================================== + AudioDemo() + { + setName (T("Audio")); + + currentAudioFileSource = 0; + + //============================================================================== + AudioFormatManager formatManager; + formatManager.registerBasicFormats(); + + addAndMakeVisible (fileChooser = new FilenameComponent (T("audiofile"), + File::nonexistent, + true, false, false, + formatManager.getWildcardForAllFormats(), + String::empty, + T("(choose a WAV or AIFF file to play)"))); + fileChooser->addListener (this); + fileChooser->setBrowseButtonText (T("browse")); + + addAndMakeVisible (playButton = new TextButton (T("play"), + T("click here to play the current audio file"))); + playButton->addButtonListener (this); + playButton->setColour (TextButton::buttonColourId, Colours::lightgreen); + playButton->setColour (TextButton::buttonOnColourId, Colours::lightgreen); + playButton->setConnectedEdges (Button::ConnectedOnRight); + + addAndMakeVisible (stopButton = new TextButton (T("stop"), + T("click here to play the current audio file"))); + stopButton->addButtonListener (this); + stopButton->setColour (TextButton::buttonColourId, Colours::red); + stopButton->setColour (TextButton::buttonOnColourId, Colours::red); + stopButton->setConnectedEdges (Button::ConnectedOnLeft); + + addAndMakeVisible (audioSettingsButton = new TextButton (T("show audio settings..."), + T("click here to change the audio device settings"))); + audioSettingsButton->addButtonListener (this); + + addAndMakeVisible (keyboardComponent = new MidiKeyboardComponent (synthSource.keyboardState, + MidiKeyboardComponent::horizontalKeyboard)); + + + addAndMakeVisible (waveformComponent = new AudioInputWaveformDisplay()); + + //============================================================================== + // register for start/stop messages from the transport source.. + transportSource.addChangeListener (this); + + // and initialise the device manager with no settings so that it picks a + // default device to use. + const String error (audioDeviceManager.initialise (1, /* number of input channels */ + 2, /* number of output channels */ + 0, /* no XML settings.. */ + true /* select default device on failure */)); + + if (error.isNotEmpty()) + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + T("Audio Demo"), + T("Couldn't open an output device!\n\n") + error); + } + else + { + // add the two audio sources to our mixer.. + mixerSource.addInputSource (&transportSource, false); + mixerSource.addInputSource (&synthSource, false); + + // ..and connect the mixer to our source player. + audioSourcePlayer.setSource (&mixerSource); + + // start the IO device pulling its data from our callback.. + audioDeviceManager.setAudioCallback (this); + + // and we need to send midi input to our synth for processing + audioDeviceManager.addMidiInputCallback (String::empty, &synthSource.midiCollector); + } + } + + ~AudioDemo() + { + audioDeviceManager.removeMidiInputCallback (&synthSource.midiCollector); + audioDeviceManager.setAudioCallback (0); + + transportSource.removeChangeListener (this); + + transportSource.setSource (0); + deleteAndZero (currentAudioFileSource); + + audioSourcePlayer.setSource (0); + + deleteAllChildren(); + } + + //============================================================================== + void audioDeviceIOCallback (const float** inputChannelData, + int totalNumInputChannels, + float** outputChannelData, + int totalNumOutputChannels, + int numSamples) + { + // pass the audio callback on to our player source, and also the waveform display comp + audioSourcePlayer.audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples); + waveformComponent->audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples); + } + + void audioDeviceAboutToStart (AudioIODevice* device) + { + audioSourcePlayer.audioDeviceAboutToStart (device); + waveformComponent->audioDeviceAboutToStart (device); + } + + void audioDeviceStopped() + { + audioSourcePlayer.audioDeviceStopped(); + waveformComponent->audioDeviceStopped(); + } + + //============================================================================== + void paint (Graphics& g) + { + // print some text to explain what state we're in. + + g.setColour (Colours::black); + g.setFont (14.0f); + + String s; + + if (transportSource.isPlaying()) + s = T("playing"); + else + s = T("stopped"); + + if (currentAudioFileSource == 0) + s += T(" - no source file selected"); + else + s += T(" - file: \"") + currentFile.getFullPathName() + T("\""); + + g.drawText (s, 250, 50, getWidth() - 250, 24, Justification::centredLeft, true); + } + + void resized() + { + fileChooser->setBounds (10, 10, getWidth() - 20, 24); + playButton->setBounds (10, 50, 100, 24); + stopButton->setBounds (110, 50, 100, 24); + audioSettingsButton->setBounds (10, 120, 200, 24); + audioSettingsButton->changeWidthToFitText(); + keyboardComponent->setBounds (10, 200, getWidth() - 20, 60); + waveformComponent->setBounds (10, 300, 400, 80); + + updateButtons(); + } + + void updateButtons() + { + playButton->setEnabled (currentAudioFileSource != 0 && ! transportSource.isPlaying()); + stopButton->setEnabled (transportSource.isPlaying()); + repaint(); + } + + void buttonClicked (Button* button) + { + if (button == playButton) + { + transportSource.setPosition (0.0); + transportSource.start(); + } + else if (button == stopButton) + { + transportSource.stop(); + } + else if (button == audioSettingsButton) + { + // Create an AudioDeviceSelectorComponent which contains the audio choice widgets... + + AudioDeviceSelectorComponent audioSettingsComp (audioDeviceManager, + 0, 1, + 2, 2, + true, + false); + + // ...and show it in a DialogWindow... + audioSettingsComp.setSize (500, 400); + + DialogWindow::showModalDialog (T("Audio Settings"), + &audioSettingsComp, + this, + Colours::azure, + true); + } + } + + void filenameComponentChanged (FilenameComponent*) + { + // this is called when the user changes the filename in the file chooser box + + File audioFile (fileChooser->getCurrentFile()); + + // unload the previous file source and delete it.. + transportSource.stop(); + transportSource.setSource (0); + deleteAndZero (currentAudioFileSource); + + // create a new file source from the file.. + + // get a format manager and set it up with the basic types (wav and aiff). + AudioFormatManager formatManager; + formatManager.registerBasicFormats(); + + AudioFormatReader* reader = formatManager.createReaderFor (audioFile); + + if (reader != 0) + { + currentFile = audioFile; + + currentAudioFileSource = new AudioFormatReaderSource (reader, true); + + // ..and plug it into our transport source + transportSource.setSource (currentAudioFileSource, + 32768, // tells it to buffer this many samples ahead + reader->sampleRate); + } + + updateButtons(); + } + + void changeListenerCallback (void*) + { + // callback from the transport source to tell us that play has + // started or stopped, so update our buttons.. + updateButtons(); + } +}; + + +//============================================================================== +Component* createAudioDemo() +{ + return new AudioDemo(); +} diff --git a/extras/juce demo/src/demos/AudioDemo.cpp b/extras/juce demo/src/demos/AudioDemo.cpp index ee410345b8..a11aef18dd 100644 --- a/extras/juce demo/src/demos/AudioDemo.cpp +++ b/extras/juce demo/src/demos/AudioDemo.cpp @@ -1,641 +1,641 @@ -/* - ============================================================================== - - 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 "../jucedemo_headers.h" - - -//============================================================================== -/** Our demo synth only has one type of sound, and it's very basic.. -*/ -class SineWaveSound : public SynthesiserSound -{ -public: - SineWaveSound (const BitArray& midiNotes_) - : midiNotes (midiNotes_) - { - } - - bool appliesToNote (const int midiNoteNumber) - { - return midiNotes [midiNoteNumber]; - } - - bool appliesToChannel (const int midiChannel) { return true; } - -private: - // this will contain the notes that this sound is attached to. - BitArray midiNotes; -}; - - -//============================================================================== -/** Our demo synth voice just plays a sine wave.. -*/ -class SineWaveVoice : public SynthesiserVoice -{ -public: - SineWaveVoice() - : angleDelta (0.0), - tailOff (0.0) - { - } - - bool canPlaySound (SynthesiserSound* sound) - { - return dynamic_cast (sound) != 0; - } - - void startNote (const int midiNoteNumber, const float velocity, - SynthesiserSound* sound, const int currentPitchWheelPosition) - { - currentAngle = 0.0; - level = velocity * 0.15; - tailOff = 0.0; - - double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber); - double cyclesPerSample = cyclesPerSecond / getSampleRate(); - - angleDelta = cyclesPerSample * 2.0 * double_Pi; - } - - void stopNote (const bool allowTailOff) - { - if (allowTailOff) - { - // start a tail-off by setting this flag. The render callback will pick up on - // this and do a fade out, calling clearCurrentNote() when it's finished. - - if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the - // stopNote method could be called more than once. - tailOff = 1.0; - } - else - { - // we're being told to stop playing immediately, so reset everything.. - - clearCurrentNote(); - angleDelta = 0.0; - } - } - - void pitchWheelMoved (const int newValue) - { - // can't be bothered implementing this for the demo! - } - - void controllerMoved (const int controllerNumber, const int newValue) - { - // not interested in controllers in this case. - } - - void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) - { - if (angleDelta != 0.0) - { - if (tailOff > 0) - { - while (--numSamples >= 0) - { - const float currentSample = (float) (sin (currentAngle) * level * tailOff); - - for (int i = outputBuffer.getNumChannels(); --i >= 0;) - *outputBuffer.getSampleData (i, startSample) += currentSample; - - currentAngle += angleDelta; - ++startSample; - - tailOff *= 0.99; - - if (tailOff <= 0.005) - { - clearCurrentNote(); - - angleDelta = 0.0; - break; - } - } - } - else - { - while (--numSamples >= 0) - { - const float currentSample = (float) (sin (currentAngle) * level); - - for (int i = outputBuffer.getNumChannels(); --i >= 0;) - *outputBuffer.getSampleData (i, startSample) += currentSample; - - currentAngle += angleDelta; - ++startSample; - } - } - } - } - -private: - double currentAngle, angleDelta, level, tailOff; -}; - -//============================================================================== -/** This is an audio source that streams the output of our demo synth. -*/ -class SynthAudioSource : public AudioSource -{ -public: - //============================================================================== - // this collects real-time midi messages from the midi input device, and - // turns them into blocks that we can process in our audio callback - MidiMessageCollector midiCollector; - - // this represents the state of which keys on our on-screen keyboard are held - // down. When the mouse is clicked on the keyboard component, this object also - // generates midi messages for this, which we can pass on to our synth. - MidiKeyboardState keyboardState; - - // the synth itself! - Synthesiser synth; - - //============================================================================== - SynthAudioSource() - { - // we'll be mixing two different types of sound, so here we'll create two - // sets of note maps, putting each sound on a different octave of the keyboard: - BitArray sinewaveNotes, samplerNotes; - - int i; - for (i = 0; i < 128; ++i) - { - if (((i / 12) & 1) != 0) - sinewaveNotes.setBit (i); - else - samplerNotes.setBit (i); - } - - // add a wave sound, which will get applied to some of the notes.. - synth.addSound (new SineWaveSound (sinewaveNotes)); - - // give our synth a few voices that can play the wave sound.. - for (i = 4; --i >= 0;) - synth.addVoice (new SineWaveVoice()); - - WavAudioFormat wavFormat; - AudioFormatReader* audioReader - = wavFormat.createReaderFor (new MemoryInputStream (BinaryData::cello_wav, - BinaryData::cello_wavSize, - false), - true); - - synth.addSound (new SamplerSound (T("demo sound"), - *audioReader, - samplerNotes, - 74, // root midi note - 0.1, // attack time - 0.1, // release time - 10.0 // maximum sample length - )); - - delete audioReader; - - // and give the synth some sampler voices to play the sampled sound.. - for (i = 4; --i >= 0;) - synth.addVoice (new SamplerVoice()); - } - - void prepareToPlay (int samplesPerBlockExpected, - double sampleRate) - { - midiCollector.reset (sampleRate); - - synth.setCurrentPlaybackSampleRate (sampleRate); - } - - void releaseResources() - { - } - - void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) - { - // the synth always adds its output to the audio buffer, so we have to clear it - // first.. - bufferToFill.clearActiveBufferRegion(); - - // fill a midi buffer with incoming messages from the midi input. - MidiBuffer incomingMidi; - midiCollector.removeNextBlockOfMessages (incomingMidi, bufferToFill.numSamples); - - // pass these messages to the keyboard state so that it can update the component - // to show on-screen which keys are being pressed on the physical midi keyboard. - // This call will also add midi messages to the buffer which were generated by - // the mouse-clicking on the on-screen keyboard. - keyboardState.processNextMidiBuffer (incomingMidi, 0, bufferToFill.numSamples, true); - - // and now get the synth to process the midi events and generate its output. - synth.renderNextBlock (*bufferToFill.buffer, incomingMidi, 0, bufferToFill.numSamples); - } -}; - -//============================================================================== -class AudioInputWaveformDisplay : public Component, - public Timer, - public AudioIODeviceCallback -{ -public: - AudioInputWaveformDisplay() - { - bufferPos = 0; - bufferSize = 2048; - circularBuffer = (float*) juce_calloc (sizeof (float) * bufferSize); - currentInputLevel = 0.0f; - numSamplesIn = 0; - - setOpaque (true); - startTimer (1000 / 50); // repaint every 1/50 of a second - } - - ~AudioInputWaveformDisplay() - { - juce_free (circularBuffer); - } - - void paint (Graphics& g) - { - g.fillAll (Colours::black); - g.setColour (Colours::lightgreen); - - const float halfHeight = getHeight() * 0.5f; - - int bp = bufferPos; - - for (int x = getWidth(); --x >= 0;) - { - const int samplesAgo = getWidth() - x; - const float level = circularBuffer [(bp + bufferSize - samplesAgo) % bufferSize]; - - if (level > 0.01f) - g.drawLine ((float) x, halfHeight - halfHeight * level, - (float) x, halfHeight + halfHeight * level); - } - } - - void timerCallback() - { - repaint(); - } - - void addSample (const float sample) - { - currentInputLevel += fabsf (sample); - - const int samplesToAverage = 128; - - if (++numSamplesIn > samplesToAverage) - { - circularBuffer [bufferPos++ % bufferSize] = currentInputLevel / samplesToAverage; - - numSamplesIn = 0; - currentInputLevel = 0.0f; - } - } - - void audioDeviceIOCallback (const float** inputChannelData, - int totalNumInputChannels, - float** outputChannelData, - int totalNumOutputChannels, - int numSamples) - { - for (int i = 0; i < totalNumInputChannels; ++i) - { - if (inputChannelData [i] != 0) - { - for (int j = 0; j < numSamples; ++j) - addSample (inputChannelData [i][j]); - - break; - } - } - } - - void audioDeviceAboutToStart (AudioIODevice*) - { - zeromem (circularBuffer, sizeof (float) * bufferSize); - } - - void audioDeviceStopped() - { - zeromem (circularBuffer, sizeof (float) * bufferSize); - } - -private: - float* circularBuffer; - float currentInputLevel; - int volatile bufferPos, bufferSize, numSamplesIn; -}; - - -//============================================================================== -class AudioDemo : public Component, - public FilenameComponentListener, - public ButtonListener, - public ChangeListener, - public AudioIODeviceCallback -{ - //============================================================================== - FilenameComponent* fileChooser; - TextButton* playButton; - TextButton* stopButton; - TextButton* audioSettingsButton; - - MidiKeyboardComponent* keyboardComponent; - AudioInputWaveformDisplay* waveformComponent; - - //============================================================================== - // this wraps the actual audio device - AudioDeviceManager audioDeviceManager; - - // this allows an audio source to be streamed to the IO device - AudioSourcePlayer audioSourcePlayer; - - // this controls the playback of a positionable audio stream, handling the - // starting/stopping and sample-rate conversion - AudioTransportSource transportSource; - - // this source contains our synth, and generates its output - SynthAudioSource synthSource; - - // this source is used to mix together the output from our synth source - // and wave player source - MixerAudioSource mixerSource; - - // this is the actual stream that's going to read from the audio file. - AudioFormatReaderSource* currentAudioFileSource; - - File currentFile; - -public: - //============================================================================== - AudioDemo() - { - setName (T("Audio")); - - currentAudioFileSource = 0; - - //============================================================================== - AudioFormatManager formatManager; - formatManager.registerBasicFormats(); - - addAndMakeVisible (fileChooser = new FilenameComponent (T("audiofile"), - File::nonexistent, - true, false, false, - formatManager.getWildcardForAllFormats(), - String::empty, - T("(choose a WAV or AIFF file to play)"))); - fileChooser->addListener (this); - fileChooser->setBrowseButtonText (T("browse")); - - addAndMakeVisible (playButton = new TextButton (T("play"), - T("click here to play the current audio file"))); - playButton->addButtonListener (this); - playButton->setColour (TextButton::buttonColourId, Colours::lightgreen); - playButton->setColour (TextButton::buttonOnColourId, Colours::lightgreen); - playButton->setConnectedEdges (Button::ConnectedOnRight); - - addAndMakeVisible (stopButton = new TextButton (T("stop"), - T("click here to play the current audio file"))); - stopButton->addButtonListener (this); - stopButton->setColour (TextButton::buttonColourId, Colours::red); - stopButton->setColour (TextButton::buttonOnColourId, Colours::red); - stopButton->setConnectedEdges (Button::ConnectedOnLeft); - - addAndMakeVisible (audioSettingsButton = new TextButton (T("show audio settings..."), - T("click here to change the audio device settings"))); - audioSettingsButton->addButtonListener (this); - - addAndMakeVisible (keyboardComponent = new MidiKeyboardComponent (synthSource.keyboardState, - MidiKeyboardComponent::horizontalKeyboard)); - - - addAndMakeVisible (waveformComponent = new AudioInputWaveformDisplay()); - - //============================================================================== - // register for start/stop messages from the transport source.. - transportSource.addChangeListener (this); - - // and initialise the device manager with no settings so that it picks a - // default device to use. - const String error (audioDeviceManager.initialise (1, /* number of input channels */ - 2, /* number of output channels */ - 0, /* no XML settings.. */ - true /* select default device on failure */)); - - if (error.isNotEmpty()) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, - T("Audio Demo"), - T("Couldn't open an output device!\n\n") + error); - } - else - { - // add the two audio sources to our mixer.. - mixerSource.addInputSource (&transportSource, false); - mixerSource.addInputSource (&synthSource, false); - - // ..and connect the mixer to our source player. - audioSourcePlayer.setSource (&mixerSource); - - // start the IO device pulling its data from our callback.. - audioDeviceManager.setAudioCallback (this); - - // and we need to send midi input to our synth for processing - audioDeviceManager.addMidiInputCallback (String::empty, &synthSource.midiCollector); - } - } - - ~AudioDemo() - { - audioDeviceManager.removeMidiInputCallback (&synthSource.midiCollector); - audioDeviceManager.setAudioCallback (0); - - transportSource.removeChangeListener (this); - - transportSource.setSource (0); - deleteAndZero (currentAudioFileSource); - - audioSourcePlayer.setSource (0); - - deleteAllChildren(); - } - - //============================================================================== - void audioDeviceIOCallback (const float** inputChannelData, - int totalNumInputChannels, - float** outputChannelData, - int totalNumOutputChannels, - int numSamples) - { - // pass the audio callback on to our player source, and also the waveform display comp - audioSourcePlayer.audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples); - waveformComponent->audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples); - } - - void audioDeviceAboutToStart (AudioIODevice* device) - { - audioSourcePlayer.audioDeviceAboutToStart (device); - waveformComponent->audioDeviceAboutToStart (device); - } - - void audioDeviceStopped() - { - audioSourcePlayer.audioDeviceStopped(); - waveformComponent->audioDeviceStopped(); - } - - //============================================================================== - void paint (Graphics& g) - { - // print some text to explain what state we're in. - - g.setColour (Colours::black); - g.setFont (14.0f); - - String s; - - if (transportSource.isPlaying()) - s = T("playing"); - else - s = T("stopped"); - - if (currentAudioFileSource == 0) - s += T(" - no source file selected"); - else - s += T(" - file: \"") + currentFile.getFullPathName() + T("\""); - - g.drawText (s, 250, 50, getWidth() - 250, 24, Justification::centredLeft, true); - } - - void resized() - { - fileChooser->setBounds (10, 10, getWidth() - 20, 24); - playButton->setBounds (10, 50, 100, 24); - stopButton->setBounds (110, 50, 100, 24); - audioSettingsButton->setBounds (10, 120, 200, 24); - audioSettingsButton->changeWidthToFitText(); - keyboardComponent->setBounds (10, 200, getWidth() - 20, 60); - waveformComponent->setBounds (10, 300, 400, 80); - - updateButtons(); - } - - void updateButtons() - { - playButton->setEnabled (currentAudioFileSource != 0 && ! transportSource.isPlaying()); - stopButton->setEnabled (transportSource.isPlaying()); - repaint(); - } - - void buttonClicked (Button* button) - { - if (button == playButton) - { - transportSource.setPosition (0.0); - transportSource.start(); - } - else if (button == stopButton) - { - transportSource.stop(); - } - else if (button == audioSettingsButton) - { - // Create an AudioDeviceSelectorComponent which contains the audio choice widgets... - - AudioDeviceSelectorComponent audioSettingsComp (audioDeviceManager, - 0, 1, - 2, 2, - true, - false); - - // ...and show it in a DialogWindow... - audioSettingsComp.setSize (500, 400); - - DialogWindow::showModalDialog (T("Audio Settings"), - &audioSettingsComp, - this, - Colours::azure, - true); - } - } - - void filenameComponentChanged (FilenameComponent*) - { - // this is called when the user changes the filename in the file chooser box - - File audioFile (fileChooser->getCurrentFile()); - - // unload the previous file source and delete it.. - transportSource.stop(); - transportSource.setSource (0); - deleteAndZero (currentAudioFileSource); - - // create a new file source from the file.. - - // get a format manager and set it up with the basic types (wav and aiff). - AudioFormatManager formatManager; - formatManager.registerBasicFormats(); - - AudioFormatReader* reader = formatManager.createReaderFor (audioFile); - - if (reader != 0) - { - currentFile = audioFile; - - currentAudioFileSource = new AudioFormatReaderSource (reader, true); - - // ..and plug it into our transport source - transportSource.setSource (currentAudioFileSource, - 32768, // tells it to buffer this many samples ahead - reader->sampleRate); - } - - updateButtons(); - } - - void changeListenerCallback (void*) - { - // callback from the transport source to tell us that play has - // started or stopped, so update our buttons.. - updateButtons(); - } -}; - - -//============================================================================== -Component* createAudioDemo() -{ - return new AudioDemo(); -} +/* + ============================================================================== + + 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 "../jucedemo_headers.h" + + +//============================================================================== +/** Our demo synth only has one type of sound, and it's very basic.. +*/ +class SineWaveSound : public SynthesiserSound +{ +public: + SineWaveSound (const BitArray& midiNotes_) + : midiNotes (midiNotes_) + { + } + + bool appliesToNote (const int midiNoteNumber) + { + return midiNotes [midiNoteNumber]; + } + + bool appliesToChannel (const int midiChannel) { return true; } + +private: + // this will contain the notes that this sound is attached to. + BitArray midiNotes; +}; + + +//============================================================================== +/** Our demo synth voice just plays a sine wave.. +*/ +class SineWaveVoice : public SynthesiserVoice +{ +public: + SineWaveVoice() + : angleDelta (0.0), + tailOff (0.0) + { + } + + bool canPlaySound (SynthesiserSound* sound) + { + return dynamic_cast (sound) != 0; + } + + void startNote (const int midiNoteNumber, const float velocity, + SynthesiserSound* sound, const int currentPitchWheelPosition) + { + currentAngle = 0.0; + level = velocity * 0.15; + tailOff = 0.0; + + double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber); + double cyclesPerSample = cyclesPerSecond / getSampleRate(); + + angleDelta = cyclesPerSample * 2.0 * double_Pi; + } + + void stopNote (const bool allowTailOff) + { + if (allowTailOff) + { + // start a tail-off by setting this flag. The render callback will pick up on + // this and do a fade out, calling clearCurrentNote() when it's finished. + + if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the + // stopNote method could be called more than once. + tailOff = 1.0; + } + else + { + // we're being told to stop playing immediately, so reset everything.. + + clearCurrentNote(); + angleDelta = 0.0; + } + } + + void pitchWheelMoved (const int newValue) + { + // can't be bothered implementing this for the demo! + } + + void controllerMoved (const int controllerNumber, const int newValue) + { + // not interested in controllers in this case. + } + + void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) + { + if (angleDelta != 0.0) + { + if (tailOff > 0) + { + while (--numSamples >= 0) + { + const float currentSample = (float) (sin (currentAngle) * level * tailOff); + + for (int i = outputBuffer.getNumChannels(); --i >= 0;) + *outputBuffer.getSampleData (i, startSample) += currentSample; + + currentAngle += angleDelta; + ++startSample; + + tailOff *= 0.99; + + if (tailOff <= 0.005) + { + clearCurrentNote(); + + angleDelta = 0.0; + break; + } + } + } + else + { + while (--numSamples >= 0) + { + const float currentSample = (float) (sin (currentAngle) * level); + + for (int i = outputBuffer.getNumChannels(); --i >= 0;) + *outputBuffer.getSampleData (i, startSample) += currentSample; + + currentAngle += angleDelta; + ++startSample; + } + } + } + } + +private: + double currentAngle, angleDelta, level, tailOff; +}; + +//============================================================================== +/** This is an audio source that streams the output of our demo synth. +*/ +class SynthAudioSource : public AudioSource +{ +public: + //============================================================================== + // this collects real-time midi messages from the midi input device, and + // turns them into blocks that we can process in our audio callback + MidiMessageCollector midiCollector; + + // this represents the state of which keys on our on-screen keyboard are held + // down. When the mouse is clicked on the keyboard component, this object also + // generates midi messages for this, which we can pass on to our synth. + MidiKeyboardState keyboardState; + + // the synth itself! + Synthesiser synth; + + //============================================================================== + SynthAudioSource() + { + // we'll be mixing two different types of sound, so here we'll create two + // sets of note maps, putting each sound on a different octave of the keyboard: + BitArray sinewaveNotes, samplerNotes; + + int i; + for (i = 0; i < 128; ++i) + { + if (((i / 12) & 1) != 0) + sinewaveNotes.setBit (i); + else + samplerNotes.setBit (i); + } + + // add a wave sound, which will get applied to some of the notes.. + synth.addSound (new SineWaveSound (sinewaveNotes)); + + // give our synth a few voices that can play the wave sound.. + for (i = 4; --i >= 0;) + synth.addVoice (new SineWaveVoice()); + + WavAudioFormat wavFormat; + AudioFormatReader* audioReader + = wavFormat.createReaderFor (new MemoryInputStream (BinaryData::cello_wav, + BinaryData::cello_wavSize, + false), + true); + + synth.addSound (new SamplerSound (T("demo sound"), + *audioReader, + samplerNotes, + 74, // root midi note + 0.1, // attack time + 0.1, // release time + 10.0 // maximum sample length + )); + + delete audioReader; + + // and give the synth some sampler voices to play the sampled sound.. + for (i = 4; --i >= 0;) + synth.addVoice (new SamplerVoice()); + } + + void prepareToPlay (int samplesPerBlockExpected, + double sampleRate) + { + midiCollector.reset (sampleRate); + + synth.setCurrentPlaybackSampleRate (sampleRate); + } + + void releaseResources() + { + } + + void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) + { + // the synth always adds its output to the audio buffer, so we have to clear it + // first.. + bufferToFill.clearActiveBufferRegion(); + + // fill a midi buffer with incoming messages from the midi input. + MidiBuffer incomingMidi; + midiCollector.removeNextBlockOfMessages (incomingMidi, bufferToFill.numSamples); + + // pass these messages to the keyboard state so that it can update the component + // to show on-screen which keys are being pressed on the physical midi keyboard. + // This call will also add midi messages to the buffer which were generated by + // the mouse-clicking on the on-screen keyboard. + keyboardState.processNextMidiBuffer (incomingMidi, 0, bufferToFill.numSamples, true); + + // and now get the synth to process the midi events and generate its output. + synth.renderNextBlock (*bufferToFill.buffer, incomingMidi, 0, bufferToFill.numSamples); + } +}; + +//============================================================================== +class AudioInputWaveformDisplay : public Component, + public Timer, + public AudioIODeviceCallback +{ +public: + AudioInputWaveformDisplay() + { + bufferPos = 0; + bufferSize = 2048; + circularBuffer = (float*) juce_calloc (sizeof (float) * bufferSize); + currentInputLevel = 0.0f; + numSamplesIn = 0; + + setOpaque (true); + startTimer (1000 / 50); // repaint every 1/50 of a second + } + + ~AudioInputWaveformDisplay() + { + juce_free (circularBuffer); + } + + void paint (Graphics& g) + { + g.fillAll (Colours::black); + g.setColour (Colours::lightgreen); + + const float halfHeight = getHeight() * 0.5f; + + int bp = bufferPos; + + for (int x = getWidth(); --x >= 0;) + { + const int samplesAgo = getWidth() - x; + const float level = circularBuffer [(bp + bufferSize - samplesAgo) % bufferSize]; + + if (level > 0.01f) + g.drawLine ((float) x, halfHeight - halfHeight * level, + (float) x, halfHeight + halfHeight * level); + } + } + + void timerCallback() + { + repaint(); + } + + void addSample (const float sample) + { + currentInputLevel += fabsf (sample); + + const int samplesToAverage = 128; + + if (++numSamplesIn > samplesToAverage) + { + circularBuffer [bufferPos++ % bufferSize] = currentInputLevel / samplesToAverage; + + numSamplesIn = 0; + currentInputLevel = 0.0f; + } + } + + void audioDeviceIOCallback (const float** inputChannelData, + int totalNumInputChannels, + float** outputChannelData, + int totalNumOutputChannels, + int numSamples) + { + for (int i = 0; i < totalNumInputChannels; ++i) + { + if (inputChannelData [i] != 0) + { + for (int j = 0; j < numSamples; ++j) + addSample (inputChannelData [i][j]); + + break; + } + } + } + + void audioDeviceAboutToStart (AudioIODevice*) + { + zeromem (circularBuffer, sizeof (float) * bufferSize); + } + + void audioDeviceStopped() + { + zeromem (circularBuffer, sizeof (float) * bufferSize); + } + +private: + float* circularBuffer; + float currentInputLevel; + int volatile bufferPos, bufferSize, numSamplesIn; +}; + + +//============================================================================== +class AudioDemo : public Component, + public FilenameComponentListener, + public ButtonListener, + public ChangeListener, + public AudioIODeviceCallback +{ + //============================================================================== + FilenameComponent* fileChooser; + TextButton* playButton; + TextButton* stopButton; + TextButton* audioSettingsButton; + + MidiKeyboardComponent* keyboardComponent; + AudioInputWaveformDisplay* waveformComponent; + + //============================================================================== + // this wraps the actual audio device + AudioDeviceManager audioDeviceManager; + + // this allows an audio source to be streamed to the IO device + AudioSourcePlayer audioSourcePlayer; + + // this controls the playback of a positionable audio stream, handling the + // starting/stopping and sample-rate conversion + AudioTransportSource transportSource; + + // this source contains our synth, and generates its output + SynthAudioSource synthSource; + + // this source is used to mix together the output from our synth source + // and wave player source + MixerAudioSource mixerSource; + + // this is the actual stream that's going to read from the audio file. + AudioFormatReaderSource* currentAudioFileSource; + + File currentFile; + +public: + //============================================================================== + AudioDemo() + { + setName (T("Audio")); + + currentAudioFileSource = 0; + + //============================================================================== + AudioFormatManager formatManager; + formatManager.registerBasicFormats(); + + addAndMakeVisible (fileChooser = new FilenameComponent (T("audiofile"), + File::nonexistent, + true, false, false, + formatManager.getWildcardForAllFormats(), + String::empty, + T("(choose a WAV or AIFF file to play)"))); + fileChooser->addListener (this); + fileChooser->setBrowseButtonText (T("browse")); + + addAndMakeVisible (playButton = new TextButton (T("play"), + T("click here to play the current audio file"))); + playButton->addButtonListener (this); + playButton->setColour (TextButton::buttonColourId, Colours::lightgreen); + playButton->setColour (TextButton::buttonOnColourId, Colours::lightgreen); + playButton->setConnectedEdges (Button::ConnectedOnRight); + + addAndMakeVisible (stopButton = new TextButton (T("stop"), + T("click here to play the current audio file"))); + stopButton->addButtonListener (this); + stopButton->setColour (TextButton::buttonColourId, Colours::red); + stopButton->setColour (TextButton::buttonOnColourId, Colours::red); + stopButton->setConnectedEdges (Button::ConnectedOnLeft); + + addAndMakeVisible (audioSettingsButton = new TextButton (T("show audio settings..."), + T("click here to change the audio device settings"))); + audioSettingsButton->addButtonListener (this); + + addAndMakeVisible (keyboardComponent = new MidiKeyboardComponent (synthSource.keyboardState, + MidiKeyboardComponent::horizontalKeyboard)); + + + addAndMakeVisible (waveformComponent = new AudioInputWaveformDisplay()); + + //============================================================================== + // register for start/stop messages from the transport source.. + transportSource.addChangeListener (this); + + // and initialise the device manager with no settings so that it picks a + // default device to use. + const String error (audioDeviceManager.initialise (1, /* number of input channels */ + 2, /* number of output channels */ + 0, /* no XML settings.. */ + true /* select default device on failure */)); + + if (error.isNotEmpty()) + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + T("Audio Demo"), + T("Couldn't open an output device!\n\n") + error); + } + else + { + // add the two audio sources to our mixer.. + mixerSource.addInputSource (&transportSource, false); + mixerSource.addInputSource (&synthSource, false); + + // ..and connect the mixer to our source player. + audioSourcePlayer.setSource (&mixerSource); + + // start the IO device pulling its data from our callback.. + audioDeviceManager.setAudioCallback (this); + + // and we need to send midi input to our synth for processing + audioDeviceManager.addMidiInputCallback (String::empty, &synthSource.midiCollector); + } + } + + ~AudioDemo() + { + audioDeviceManager.removeMidiInputCallback (&synthSource.midiCollector); + audioDeviceManager.setAudioCallback (0); + + transportSource.removeChangeListener (this); + + transportSource.setSource (0); + deleteAndZero (currentAudioFileSource); + + audioSourcePlayer.setSource (0); + + deleteAllChildren(); + } + + //============================================================================== + void audioDeviceIOCallback (const float** inputChannelData, + int totalNumInputChannels, + float** outputChannelData, + int totalNumOutputChannels, + int numSamples) + { + // pass the audio callback on to our player source, and also the waveform display comp + audioSourcePlayer.audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples); + waveformComponent->audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples); + } + + void audioDeviceAboutToStart (AudioIODevice* device) + { + audioSourcePlayer.audioDeviceAboutToStart (device); + waveformComponent->audioDeviceAboutToStart (device); + } + + void audioDeviceStopped() + { + audioSourcePlayer.audioDeviceStopped(); + waveformComponent->audioDeviceStopped(); + } + + //============================================================================== + void paint (Graphics& g) + { + // print some text to explain what state we're in. + + g.setColour (Colours::black); + g.setFont (14.0f); + + String s; + + if (transportSource.isPlaying()) + s = T("playing"); + else + s = T("stopped"); + + if (currentAudioFileSource == 0) + s += T(" - no source file selected"); + else + s += T(" - file: \"") + currentFile.getFullPathName() + T("\""); + + g.drawText (s, 250, 50, getWidth() - 250, 24, Justification::centredLeft, true); + } + + void resized() + { + fileChooser->setBounds (10, 10, getWidth() - 20, 24); + playButton->setBounds (10, 50, 100, 24); + stopButton->setBounds (110, 50, 100, 24); + audioSettingsButton->setBounds (10, 120, 200, 24); + audioSettingsButton->changeWidthToFitText(); + keyboardComponent->setBounds (10, 200, getWidth() - 20, 60); + waveformComponent->setBounds (10, 300, 400, 80); + + updateButtons(); + } + + void updateButtons() + { + playButton->setEnabled (currentAudioFileSource != 0 && ! transportSource.isPlaying()); + stopButton->setEnabled (transportSource.isPlaying()); + repaint(); + } + + void buttonClicked (Button* button) + { + if (button == playButton) + { + transportSource.setPosition (0.0); + transportSource.start(); + } + else if (button == stopButton) + { + transportSource.stop(); + } + else if (button == audioSettingsButton) + { + // Create an AudioDeviceSelectorComponent which contains the audio choice widgets... + + AudioDeviceSelectorComponent audioSettingsComp (audioDeviceManager, + 0, 1, + 2, 2, + true, + false); + + // ...and show it in a DialogWindow... + audioSettingsComp.setSize (500, 400); + + DialogWindow::showModalDialog (T("Audio Settings"), + &audioSettingsComp, + this, + Colours::azure, + true); + } + } + + void filenameComponentChanged (FilenameComponent*) + { + // this is called when the user changes the filename in the file chooser box + + File audioFile (fileChooser->getCurrentFile()); + + // unload the previous file source and delete it.. + transportSource.stop(); + transportSource.setSource (0); + deleteAndZero (currentAudioFileSource); + + // create a new file source from the file.. + + // get a format manager and set it up with the basic types (wav and aiff). + AudioFormatManager formatManager; + formatManager.registerBasicFormats(); + + AudioFormatReader* reader = formatManager.createReaderFor (audioFile); + + if (reader != 0) + { + currentFile = audioFile; + + currentAudioFileSource = new AudioFormatReaderSource (reader, true); + + // ..and plug it into our transport source + transportSource.setSource (currentAudioFileSource, + 32768, // tells it to buffer this many samples ahead + reader->sampleRate); + } + + updateButtons(); + } + + void changeListenerCallback (void*) + { + // callback from the transport source to tell us that play has + // started or stopped, so update our buttons.. + updateButtons(); + } +}; + + +//============================================================================== +Component* createAudioDemo() +{ + return new AudioDemo(); +} diff --git a/src/juce_appframework/audio/audio_file_formats/juce_AudioCDBurner.h b/src/juce_appframework/audio/audio_file_formats/juce_AudioCDBurner.h index 862a5ae5f3..49d9870c6e 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_AudioCDBurner.h +++ b/src/juce_appframework/audio/audio_file_formats/juce_AudioCDBurner.h @@ -1,89 +1,113 @@ -/* - ============================================================================== - - 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_AUDIOCDBURNER_JUCEHEADER__ -#define __JUCE_AUDIOCDBURNER_JUCEHEADER__ - -#include "juce_AudioFormatReader.h" -#include "../audio_sources/juce_AudioSource.h" - - -//============================================================================== -/** -*/ -class AudioCDBurner -{ -public: - //============================================================================== - static const StringArray findAvailableDevices(); - static AudioCDBurner* openDevice (const int deviceIndex); - - ~AudioCDBurner(); - - //============================================================================== - bool isDiskPresent() const; - - int getNumAvailableAudioBlocks() const; - - bool addAudioTrack (AudioFormatReader& source, int numSamples); - bool addAudioTrack (AudioSource& source, int numSamples); - - /** - - Return true to cancel the current burn operation - */ - class BurnProgressListener - { - public: - BurnProgressListener() throw() {} - virtual ~BurnProgressListener() {} - - /** Called at intervals to report on the progress of the AudioCDBurner. - - To cancel the burn, return true from this. - */ - virtual bool audioCDBurnProgress (float proportionComplete) = 0; - }; - - const String burn (BurnProgressListener* listener, - const bool ejectDiscAfterwards); - - //============================================================================== - juce_UseDebuggingNewOperator - -private: - AudioCDBurner (const int deviceIndex); - - void* internal; -}; - - -#endif // __JUCE_AUDIOCDBURNER_JUCEHEADER__ +/* + ============================================================================== + + 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_AUDIOCDBURNER_JUCEHEADER__ +#define __JUCE_AUDIOCDBURNER_JUCEHEADER__ + +#include "juce_AudioFormatReader.h" +#include "../audio_sources/juce_AudioSource.h" + + +//============================================================================== +/** +*/ +class AudioCDBurner +{ +public: + //============================================================================== + /** Returns a list of available optical drives. + + Use openDevice() to open one of the items from this list. + */ + static const StringArray findAvailableDevices(); + + /** Tries to open one of the optical drives. + + The deviceIndex is an index into the array returned by findAvailableDevices(). + */ + static AudioCDBurner* openDevice (const int deviceIndex); + + /** Destructor. */ + ~AudioCDBurner(); + + //============================================================================== + /** Returns true if there's a writable disk in the drive. + */ + bool isDiskPresent() const; + + /** Returns the number of free blocks on the disk. + + There are 75 blocks per second, at 44100Hz. + */ + int getNumAvailableAudioBlocks() const; + + /** Adds a track to be written. + + The source passed-in here will be kept by this object, and it will + be used and deleted at some point in the future, either during the + burn() method or when this AudioCDBurner object is deleted. Your caller + method shouldn't keep a reference to it or use it again after passing + it in here. + */ + bool addAudioTrack (AudioSource* source, int numSamples); + + /** + + Return true to cancel the current burn operation + */ + class BurnProgressListener + { + public: + BurnProgressListener() throw() {} + virtual ~BurnProgressListener() {} + + /** Called at intervals to report on the progress of the AudioCDBurner. + + To cancel the burn, return true from this. + */ + virtual bool audioCDBurnProgress (float proportionComplete) = 0; + }; + + const String burn (BurnProgressListener* listener, + const bool ejectDiscAfterwards, + const bool peformFakeBurnForTesting); + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + AudioCDBurner (const int deviceIndex); + + void* internal; +}; + + +#endif // __JUCE_AUDIOCDBURNER_JUCEHEADER__ diff --git a/src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnail.cpp b/src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnail.cpp index c6c8b5c0c6..c6549b6423 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnail.cpp +++ b/src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnail.cpp @@ -76,8 +76,8 @@ static void swapEndiannessIfNeeded (AudioThumbnailDataFormat* const d) AudioThumbnail::AudioThumbnail (const int orginalSamplesPerThumbnailSample_, AudioFormatManager& formatManagerToUse_, AudioThumbnailCache& cacheToUse) - : cache (cacheToUse), - formatManagerToUse (formatManagerToUse_), + : formatManagerToUse (formatManagerToUse_), + cache (cacheToUse), source (0), reader (0), orginalSamplesPerThumbnailSample (orginalSamplesPerThumbnailSample_) diff --git a/src/juce_appframework/gui/components/controls/juce_ComboBox.cpp b/src/juce_appframework/gui/components/controls/juce_ComboBox.cpp index cd5f54774e..46fed16013 100644 --- a/src/juce_appframework/gui/components/controls/juce_ComboBox.cpp +++ b/src/juce_appframework/gui/components/controls/juce_ComboBox.cpp @@ -181,13 +181,13 @@ void ComboBox::changeItemText (const int itemId, item->name = newText; } -void ComboBox::clear() +void ComboBox::clear (const bool dontSendChangeMessage) { items.clear(); separatorPending = false; if (! label->isEditable()) - setSelectedItemIndex (-1); + setSelectedItemIndex (-1, dontSendChangeMessage); } //============================================================================== diff --git a/src/juce_appframework/gui/components/controls/juce_ComboBox.h b/src/juce_appframework/gui/components/controls/juce_ComboBox.h index 87581ed9d7..a3d6496ec5 100644 --- a/src/juce_appframework/gui/components/controls/juce_ComboBox.h +++ b/src/juce_appframework/gui/components/controls/juce_ComboBox.h @@ -164,9 +164,12 @@ public: /** Removes all the items from the drop-down list. + If this call causes the content to be cleared, then a change-message + will be broadcast unless dontSendChangeMessage is true. + @see addItem, removeItem, getNumItems */ - void clear(); + void clear (const bool dontSendChangeMessage = false); /** Returns the number of items that have been added to the list. diff --git a/src/juce_appframework/gui/components/controls/juce_TreeView.cpp b/src/juce_appframework/gui/components/controls/juce_TreeView.cpp index 3f7ec9768d..db7696580c 100644 --- a/src/juce_appframework/gui/components/controls/juce_TreeView.cpp +++ b/src/juce_appframework/gui/components/controls/juce_TreeView.cpp @@ -627,8 +627,8 @@ bool TreeView::keyPressed (const KeyPress& key) void TreeView::itemsChanged() throw() { needsRecalculating = true; - triggerAsyncUpdate(); repaint(); + triggerAsyncUpdate(); } void TreeView::handleAsyncUpdate() diff --git a/src/juce_core/io/files/juce_File.h b/src/juce_core/io/files/juce_File.h index 212edc2183..7e8f0f98cf 100644 --- a/src/juce_core/io/files/juce_File.h +++ b/src/juce_core/io/files/juce_File.h @@ -346,6 +346,12 @@ public: bool setReadOnly (const bool shouldBeReadOnly, const bool applyRecursively = false) const throw(); + /** Returns true if this file is a hidden or system file. + + The criteria for deciding whether a file is hidden are platform-dependent. + */ + bool isHidden() const throw(); + //============================================================================== /** Returns the last modification time of this file. diff --git a/src/juce_core/io/network/juce_URL.cpp b/src/juce_core/io/network/juce_URL.cpp index 0f9f1b12f9..5a2a71347c 100644 --- a/src/juce_core/io/network/juce_URL.cpp +++ b/src/juce_core/io/network/juce_URL.cpp @@ -167,7 +167,6 @@ void* juce_openInternetFile (const String& url, void juce_closeInternetFile (void* handle); int juce_readFromInternetFile (void* handle, void* dest, int bytesToRead); int juce_seekInInternetFile (void* handle, int newPosition); -int juce_getStatusCodeFor (void* handle); //============================================================================== @@ -204,11 +203,6 @@ public: return handle == 0; } - int getErrorCode() const - { - return juce_getStatusCodeFor (handle); - } - //============================================================================== int64 getTotalLength() {