| @@ -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 $<) | |||
| @@ -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) | |||
| { | |||
| @@ -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 = "<group>"; }; | |||
| 84022DFB0DAE4CB9004CF59A /* juce_mac_HTTPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = juce_mac_HTTPStream.h; sourceTree = "<group>"; }; | |||
| 84052DE208D095D200BEC0F0 /* juce_ToneGeneratorAudioSource.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_ToneGeneratorAudioSource.cpp; sourceTree = "<group>"; }; | |||
| 84052DE308D095D200BEC0F0 /* juce_ToneGeneratorAudioSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_ToneGeneratorAudioSource.h; sourceTree = "<group>"; }; | |||
| @@ -893,6 +892,7 @@ | |||
| 846927DD0A49ABE600314975 /* juce_RectanglePlacement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_RectanglePlacement.h; sourceTree = "<group>"; }; | |||
| 846927E00A49ABFD00314975 /* juce_SVGParser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_SVGParser.cpp; sourceTree = "<group>"; }; | |||
| 8478247F0D7816A00082A5C5 /* juce_AudioCDBurner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_AudioCDBurner.h; sourceTree = "<group>"; }; | |||
| 847D06460DD88D1100DF6A61 /* juce_mac_Network.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_Network.mm; sourceTree = "<group>"; }; | |||
| 847F72D70C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DirectoryContentsDisplayComponent.cpp; path = filebrowser/juce_DirectoryContentsDisplayComponent.cpp; sourceTree = "<group>"; }; | |||
| 847F72D80C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_DirectoryContentsDisplayComponent.h; path = filebrowser/juce_DirectoryContentsDisplayComponent.h; sourceTree = "<group>"; }; | |||
| 847F72D90C2702A000CBECEC /* juce_FileTreeComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileTreeComponent.cpp; path = filebrowser/juce_FileTreeComponent.cpp; sourceTree = "<group>"; }; | |||
| @@ -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 = "<group>"; }; | |||
| 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 = "<group>"; }; | |||
| 84D296BB09B763190026C535 /* juce_PropertiesFile.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_PropertiesFile.cpp; sourceTree = "<group>"; }; | |||
| 84D296BC09B763190026C535 /* juce_PropertiesFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_PropertiesFile.h; sourceTree = "<group>"; }; | |||
| 84E8209209729D2A0097675B /* juce_AudioFormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_AudioFormatManager.cpp; sourceTree = "<group>"; }; | |||
| @@ -1379,7 +1379,7 @@ | |||
| 84FED3C80CAA96DA00003997 /* juce_FileDragAndDropTarget.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_FileDragAndDropTarget.h; sourceTree = "<group>"; }; | |||
| 84FFAF290C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileSearchPathListComponent.cpp; path = filebrowser/juce_FileSearchPathListComponent.cpp; sourceTree = "<group>"; }; | |||
| 84FFAF2A0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_FileSearchPathListComponent.h; path = filebrowser/juce_FileSearchPathListComponent.h; sourceTree = "<group>"; }; | |||
| 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 = "<group>"; | |||
| @@ -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; | |||
| }; | |||
| @@ -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 | |||
| @@ -29,48 +29,82 @@ | |||
| ============================================================================== | |||
| */ | |||
| #include "../../../src/juce_core/basics/juce_StandardHeader.h" | |||
| /*#include "../../../src/juce_core/basics/juce_StandardHeader.h" | |||
| #include <Carbon/Carbon.h> | |||
| 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 | |||
| END_JUCE_NAMESPACE*/ | |||
| @@ -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 <Cocoa/Cocoa.h> | |||
| #import <DiscRecording/DiscRecording.h> | |||
| 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 | |||
| @@ -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__ | |||
| @@ -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 <Cocoa/Cocoa.h> | |||
| #import <CoreFoundation/CoreFoundation.h> | |||
| #import <IOKit/IOKitLib.h> | |||
| #import <IOKit/network/IOEthernetInterface.h> | |||
| #import <IOKit/network/IONetworkInterface.h> | |||
| #import <IOKit/network/IOEthernetController.h> | |||
| #include <netdb.h> | |||
| #include <arpa/inet.h> | |||
| #include <netinet/in.h> | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <sys/wait.h> | |||
| 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 | |||
| @@ -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 | |||
| { | |||
| @@ -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; | |||
| } | |||
| @@ -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() | |||
| { | |||
| @@ -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) | |||
| @@ -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; | |||
| @@ -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__ | |||
| @@ -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_) | |||
| @@ -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); | |||
| } | |||
| //============================================================================== | |||
| @@ -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. | |||
| @@ -627,8 +627,8 @@ bool TreeView::keyPressed (const KeyPress& key) | |||
| void TreeView::itemsChanged() throw() | |||
| { | |||
| needsRecalculating = true; | |||
| triggerAsyncUpdate(); | |||
| repaint(); | |||
| triggerAsyncUpdate(); | |||
| } | |||
| void TreeView::handleAsyncUpdate() | |||
| @@ -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. | |||
| @@ -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() | |||
| { | |||