| @@ -287,7 +287,7 @@ private: | |||
| { | |||
| XmlElement* proj = new XmlElement ("project"); | |||
| proj->setAttribute ("name", project.getProjectName().toString()); | |||
| proj->setAttribute ("default", "help"); | |||
| proj->setAttribute ("default", "debug"); | |||
| proj->createNewChildElement ("property")->setAttribute ("file", "local.properties"); | |||
| proj->createNewChildElement ("property")->setAttribute ("file", "build.properties"); | |||
| @@ -8984,10 +8984,10 @@ END_JUCE_NAMESPACE | |||
| #include <netdb.h> | |||
| #include <arpa/inet.h> | |||
| #include <netinet/tcp.h> | |||
| #endif | |||
| #ifndef AI_NUMERICSERV // (missing in older Mac SDKs) | |||
| #define AI_NUMERICSERV 0x1000 | |||
| #endif | |||
| #ifndef AI_NUMERICSERV // (missing in older Mac SDKs) | |||
| #define AI_NUMERICSERV 0x1000 | |||
| #endif | |||
| BEGIN_JUCE_NAMESPACE | |||
| @@ -10759,9 +10759,9 @@ public: | |||
| } | |||
| else | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| file_.numOpenStreams++; | |||
| #endif | |||
| #endif | |||
| } | |||
| char buffer [30]; | |||
| @@ -10778,10 +10778,10 @@ public: | |||
| ~ZipInputStream() | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| if (inputStream != 0 && inputStream == file.inputStream) | |||
| file.numOpenStreams--; | |||
| #endif | |||
| #endif | |||
| } | |||
| int64 getTotalLength() | |||
| @@ -10847,9 +10847,9 @@ private: | |||
| ZipFile::ZipFile (InputStream* const source_, const bool deleteStreamWhenDestroyed) | |||
| : inputStream (source_) | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| , numOpenStreams (0) | |||
| #endif | |||
| #endif | |||
| { | |||
| if (deleteStreamWhenDestroyed) | |||
| streamToDelete = inputStream; | |||
| @@ -10859,9 +10859,9 @@ ZipFile::ZipFile (InputStream* const source_, const bool deleteStreamWhenDestroy | |||
| ZipFile::ZipFile (const File& file) | |||
| : inputStream (0) | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| , numOpenStreams (0) | |||
| #endif | |||
| #endif | |||
| { | |||
| inputSource = new FileInputSource (file); | |||
| init(); | |||
| @@ -10870,16 +10870,16 @@ ZipFile::ZipFile (const File& file) | |||
| ZipFile::ZipFile (InputSource* const inputSource_) | |||
| : inputStream (0), | |||
| inputSource (inputSource_) | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| , numOpenStreams (0) | |||
| #endif | |||
| #endif | |||
| { | |||
| init(); | |||
| } | |||
| ZipFile::~ZipFile() | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| entries.clear(); | |||
| /* If you hit this assertion, it means you've created a stream to read one of the items in the | |||
| @@ -10888,7 +10888,7 @@ ZipFile::~ZipFile() | |||
| stream that the file uses to read itself. | |||
| */ | |||
| jassert (numOpenStreams == 0); | |||
| #endif | |||
| #endif | |||
| } | |||
| int ZipFile::getNumEntries() const throw() | |||
| @@ -11114,6 +11114,155 @@ bool ZipFile::uncompressEntry (const int index, | |||
| return false; | |||
| } | |||
| extern unsigned long juce_crc32 (unsigned long crc, const unsigned char* buf, unsigned len); | |||
| class ZipFile::Builder::Item | |||
| { | |||
| public: | |||
| Item (const File& file_, const int compressionLevel_, const String& storedPathName_) | |||
| : file (file_), | |||
| storedPathname (storedPathName_.isEmpty() ? file_.getFileName() : storedPathName_), | |||
| compressionLevel (compressionLevel_), | |||
| compressedSize (0), | |||
| headerStart (0) | |||
| { | |||
| } | |||
| bool writeData (OutputStream& target, const int64 overallStartPosition) | |||
| { | |||
| MemoryOutputStream compressedData; | |||
| if (compressionLevel > 0) | |||
| { | |||
| GZIPCompressorOutputStream compressor (&compressedData, compressionLevel, false, | |||
| GZIPCompressorOutputStream::windowBitsRaw); | |||
| if (! writeSource (compressor)) | |||
| return false; | |||
| } | |||
| else | |||
| { | |||
| if (! writeSource (compressedData)) | |||
| return false; | |||
| } | |||
| compressedSize = compressedData.getDataSize(); | |||
| headerStart = (int) (target.getPosition() - overallStartPosition); | |||
| target.writeInt (0x04034b50); | |||
| writeFlagsAndSizes (target); | |||
| target << storedPathname | |||
| << compressedData; | |||
| return true; | |||
| } | |||
| bool writeDirectoryEntry (OutputStream& target) | |||
| { | |||
| target.writeInt (0x02014b50); | |||
| target.writeShort (20); // version written | |||
| writeFlagsAndSizes (target); | |||
| target.writeShort (0); // comment length | |||
| target.writeShort (0); // start disk num | |||
| target.writeShort (0); // internal attributes | |||
| target.writeInt (0); // external attributes | |||
| target.writeInt (headerStart); | |||
| target << storedPathname; | |||
| return true; | |||
| } | |||
| private: | |||
| const File file; | |||
| String storedPathname; | |||
| int compressionLevel, compressedSize, headerStart; | |||
| uint32 checksum; | |||
| void writeTimeAndDate (OutputStream& target) const | |||
| { | |||
| const Time t (file.getLastModificationTime()); | |||
| target.writeShort ((short) (t.getSeconds() + (t.getMinutes() << 5) + (t.getHours() << 11))); | |||
| target.writeShort ((short) (t.getDayOfMonth() + ((t.getMonth() + 1) << 5) + ((t.getYear() - 1980) << 9))); | |||
| } | |||
| bool writeSource (OutputStream& target) | |||
| { | |||
| checksum = 0; | |||
| ScopedPointer<FileInputStream> input (file.createInputStream()); | |||
| if (input == 0) | |||
| return false; | |||
| const int bufferSize = 2048; | |||
| HeapBlock<unsigned char> buffer (bufferSize); | |||
| while (! input->isExhausted()) | |||
| { | |||
| const int bytesRead = input->read (buffer, bufferSize); | |||
| if (bytesRead < 0) | |||
| return false; | |||
| checksum = juce_crc32 (checksum, buffer, bytesRead); | |||
| target.write (buffer, bytesRead); | |||
| } | |||
| return true; | |||
| } | |||
| void writeFlagsAndSizes (OutputStream& target) const | |||
| { | |||
| target.writeShort (10); // version needed | |||
| target.writeShort (0); // flags | |||
| target.writeShort (compressionLevel > 0 ? (short) 8 : (short) 0); | |||
| writeTimeAndDate (target); | |||
| target.writeInt (checksum); | |||
| target.writeInt (compressedSize); | |||
| target.writeInt ((int) file.getSize()); | |||
| target.writeShort ((short) storedPathname.toUTF8().sizeInBytes() - 1); | |||
| target.writeShort (0); // extra field length | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Item); | |||
| }; | |||
| ZipFile::Builder::Builder() {} | |||
| ZipFile::Builder::~Builder() {} | |||
| void ZipFile::Builder::addFile (const File& fileToAdd, const int compressionLevel, const String& storedPathName) | |||
| { | |||
| items.add (new Item (fileToAdd, compressionLevel, storedPathName)); | |||
| } | |||
| bool ZipFile::Builder::writeToStream (OutputStream& target) const | |||
| { | |||
| const int64 fileStart = target.getPosition(); | |||
| int i; | |||
| for (i = 0; i < items.size(); ++i) | |||
| if (! items.getUnchecked (i)->writeData (target, fileStart)) | |||
| return false; | |||
| const int64 directoryStart = target.getPosition(); | |||
| for (i = 0; i < items.size(); ++i) | |||
| if (! items.getUnchecked (i)->writeDirectoryEntry (target)) | |||
| return false; | |||
| const int64 directoryEnd = target.getPosition(); | |||
| target.writeInt (0x06054b50); | |||
| target.writeShort (0); | |||
| target.writeShort (0); | |||
| target.writeShort ((short) items.size()); | |||
| target.writeShort ((short) items.size()); | |||
| target.writeInt ((int) (directoryEnd - directoryStart)); | |||
| target.writeInt ((int) (directoryStart - fileStart)); | |||
| target.writeShort (0); | |||
| target.flush(); | |||
| return true; | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| /*** End of inlined file: juce_ZipFile.cpp ***/ | |||
| @@ -61264,6 +61413,9 @@ public: | |||
| { | |||
| component->setAlpha ((float) destAlpha); | |||
| component->setBounds (destination); | |||
| if (proxy != 0) | |||
| component->setVisible (destAlpha > 0); | |||
| } | |||
| } | |||
| @@ -106086,6 +106238,12 @@ bool GZIPDecompressorInputStream::setPosition (int64 newPos) | |||
| return true; | |||
| } | |||
| // (This is used as a way for the zip file code to use the crc32 function without including zlib) | |||
| unsigned long juce_crc32 (unsigned long crc, const unsigned char* buf, unsigned len) | |||
| { | |||
| return zlibNamespace::crc32 (crc, buf, len); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| /*** End of inlined file: juce_GZIPDecompressorInputStream.cpp ***/ | |||
| @@ -256374,11 +256532,15 @@ private: | |||
| { | |||
| sessionEventCallback = new SessionEventCallback (*this); | |||
| audioSessionControl->RegisterAudioSessionNotification (sessionEventCallback); | |||
| sessionEventCallback->Release(); // (required because ComBaseClassHelper objects are constructed with a ref count of 1) | |||
| } | |||
| } | |||
| void deleteSessionEventCallback() | |||
| { | |||
| if (audioSessionControl != 0 && sessionEventCallback != 0) | |||
| audioSessionControl->UnregisterAudioSessionNotification (sessionEventCallback); | |||
| audioSessionControl = 0; | |||
| sessionEventCallback = 0; | |||
| } | |||
| @@ -262011,7 +262173,7 @@ class LinuxComponentPeer : public ComponentPeer | |||
| { | |||
| public: | |||
| LinuxComponentPeer (Component* const component, const int windowStyleFlags, Window parentToAddTo)) | |||
| LinuxComponentPeer (Component* const component, const int windowStyleFlags, Window parentToAddTo) | |||
| : ComponentPeer (component, windowStyleFlags), | |||
| windowH (0), parentWindow (0), | |||
| wx (0), wy (0), ww (0), wh (0), | |||
| @@ -280566,6 +280728,11 @@ public: | |||
| messageQueue.post (m); | |||
| } | |||
| static NSString* getBroacastEventName() | |||
| { | |||
| return juceStringToNS ("juce_" + String::toHexString (File::getSpecialLocation (File::currentExecutableFile).hashCode64())); | |||
| } | |||
| private: | |||
| CFRunLoopRef runLoop; | |||
| CFRunLoopSourceRef runLoopSource; | |||
| @@ -280605,6 +280772,7 @@ using namespace JUCE_NAMESPACE; | |||
| - (void) applicationDidResignActive: (NSNotification*) aNotification; | |||
| - (void) applicationWillUnhide: (NSNotification*) aNotification; | |||
| - (void) performCallback: (id) info; | |||
| - (void) broadcastMessageCallback: (NSNotification*) info; | |||
| - (void) dummyMethod; | |||
| @end | |||
| @@ -280622,6 +280790,11 @@ using namespace JUCE_NAMESPACE; | |||
| { | |||
| oldDelegate = [NSApp delegate]; | |||
| [NSApp setDelegate: self]; | |||
| [[NSDistributedNotificationCenter defaultCenter] addObserver: self | |||
| selector: @selector (broadcastMessageCallback:) | |||
| name: AppDelegateRedirector::getBroacastEventName() | |||
| object: nil]; | |||
| } | |||
| else | |||
| { | |||
| @@ -280644,6 +280817,10 @@ using namespace JUCE_NAMESPACE; | |||
| if (oldDelegate != 0) | |||
| [NSApp setDelegate: oldDelegate]; | |||
| [[NSDistributedNotificationCenter defaultCenter] removeObserver: self | |||
| name: AppDelegateRedirector::getBroacastEventName() | |||
| object: nil]; | |||
| redirector->deleteSelf(); | |||
| [super dealloc]; | |||
| } | |||
| @@ -280706,6 +280883,13 @@ using namespace JUCE_NAMESPACE; | |||
| } | |||
| } | |||
| - (void) broadcastMessageCallback: (NSNotification*) n | |||
| { | |||
| NSDictionary* dict = (NSDictionary*) [n userInfo]; | |||
| const String messageString (nsStringToJuce ((NSString*) [dict valueForKey: @"message"])); | |||
| MessageManager::getInstance()->deliverBroadcastMessage (messageString); | |||
| } | |||
| - (void) dummyMethod {} // (used as a way of running a dummy thread) | |||
| @end | |||
| @@ -280723,7 +280907,7 @@ void MessageManager::runDispatchLoop() | |||
| // must only be called by the message thread! | |||
| jassert (isThisTheMessageThread()); | |||
| #if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||
| #if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||
| @try | |||
| { | |||
| [NSApp run]; | |||
| @@ -280737,9 +280921,9 @@ void MessageManager::runDispatchLoop() | |||
| @finally | |||
| { | |||
| } | |||
| #else | |||
| #else | |||
| [NSApp run]; | |||
| #endif | |||
| #endif | |||
| } | |||
| } | |||
| @@ -280897,8 +281081,14 @@ bool juce_postMessageToSystemQueue (Message* message) | |||
| return true; | |||
| } | |||
| void MessageManager::broadcastMessage (const String&) | |||
| void MessageManager::broadcastMessage (const String& message) | |||
| { | |||
| NSDictionary* info = [NSDictionary dictionaryWithObject: juceStringToNS (message) | |||
| forKey: @"message"]; | |||
| [[NSDistributedNotificationCenter defaultCenter] postNotificationName: AppDelegateRedirector::getBroacastEventName() | |||
| object: nil | |||
| userInfo: info]; | |||
| } | |||
| void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, void* data) | |||
| @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 49 | |||
| #define JUCE_BUILDNUMBER 50 | |||
| /** Current Juce version number. | |||
| @@ -19001,6 +19001,42 @@ public: | |||
| const File& targetDirectory, | |||
| bool shouldOverwriteFiles = true); | |||
| /** Used to create a new zip file. | |||
| Create a ZipFile::Builder object, and call its addFile() method to add some files, | |||
| then you can write it to a stream with write(). | |||
| Currently this just stores the files with no compression.. That will be added | |||
| soon! | |||
| */ | |||
| class Builder | |||
| { | |||
| public: | |||
| Builder(); | |||
| ~Builder(); | |||
| /** Adds a file while should be added to the archive. | |||
| The file isn't read immediately, all the files will be read later when the writeToStream() | |||
| method is called. | |||
| The compressionLevel can be between 0 (no compression), and 9 (maximum compression). | |||
| If the storedPathName parameter is specified, you can customise the partial pathname that | |||
| will be stored for this file. | |||
| */ | |||
| void addFile (const File& fileToAdd, int compressionLevel, | |||
| const String& storedPathName = String::empty); | |||
| /** Generates the zip file, writing it to the specified stream. */ | |||
| bool writeToStream (OutputStream& target) const; | |||
| private: | |||
| class Item; | |||
| friend class OwnedArray<Item>; | |||
| OwnedArray<Item> items; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Builder); | |||
| }; | |||
| private: | |||
| class ZipInputStream; | |||
| @@ -59899,7 +59935,7 @@ public: | |||
| virtual const Rectangle<int> getPropertyComponentContentPosition (PropertyComponent& component); | |||
| void drawCallOutBoxBackground (CallOutBox& box, Graphics& g, const Path& path); | |||
| virtual void drawCallOutBoxBackground (CallOutBox& box, Graphics& g, const Path& path); | |||
| virtual void drawLevelMeter (Graphics& g, int width, int height, float level); | |||
| @@ -63522,7 +63558,6 @@ private: | |||
| Image background; | |||
| void refreshPath(); | |||
| void drawCallOutBoxBackground (Graphics& g, const Path& outline, int width, int height); | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallOutBox); | |||
| }; | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 49 | |||
| #define JUCE_BUILDNUMBER 50 | |||
| /** Current Juce version number. | |||
| @@ -138,6 +138,9 @@ public: | |||
| { | |||
| component->setAlpha ((float) destAlpha); | |||
| component->setBounds (destination); | |||
| if (proxy != 0) | |||
| component->setVisible (destAlpha > 0); | |||
| } | |||
| } | |||
| @@ -602,7 +602,7 @@ public: | |||
| virtual const Rectangle<int> getPropertyComponentContentPosition (PropertyComponent& component); | |||
| //============================================================================== | |||
| void drawCallOutBoxBackground (CallOutBox& box, Graphics& g, const Path& path); | |||
| virtual void drawCallOutBoxBackground (CallOutBox& box, Graphics& g, const Path& path); | |||
| //============================================================================== | |||
| virtual void drawLevelMeter (Graphics& g, int width, int height, float level); | |||
| @@ -119,7 +119,6 @@ private: | |||
| Image background; | |||
| void refreshPath(); | |||
| void drawCallOutBoxBackground (Graphics& g, const Path& outline, int width, int height); | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallOutBox); | |||
| }; | |||
| @@ -31,6 +31,8 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../streams/juce_GZIPDecompressorInputStream.h" | |||
| #include "../streams/juce_BufferedInputStream.h" | |||
| #include "../streams/juce_FileInputSource.h" | |||
| #include "../streams/juce_MemoryOutputStream.h" | |||
| #include "../streams/juce_GZIPCompressorOutputStream.h" | |||
| #include "juce_FileInputStream.h" | |||
| #include "juce_FileOutputStream.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| @@ -66,9 +68,9 @@ public: | |||
| } | |||
| else | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| file_.numOpenStreams++; | |||
| #endif | |||
| #endif | |||
| } | |||
| char buffer [30]; | |||
| @@ -85,10 +87,10 @@ public: | |||
| ~ZipInputStream() | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| if (inputStream != 0 && inputStream == file.inputStream) | |||
| file.numOpenStreams--; | |||
| #endif | |||
| #endif | |||
| } | |||
| int64 getTotalLength() | |||
| @@ -157,9 +159,9 @@ private: | |||
| //============================================================================== | |||
| ZipFile::ZipFile (InputStream* const source_, const bool deleteStreamWhenDestroyed) | |||
| : inputStream (source_) | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| , numOpenStreams (0) | |||
| #endif | |||
| #endif | |||
| { | |||
| if (deleteStreamWhenDestroyed) | |||
| streamToDelete = inputStream; | |||
| @@ -169,9 +171,9 @@ ZipFile::ZipFile (InputStream* const source_, const bool deleteStreamWhenDestroy | |||
| ZipFile::ZipFile (const File& file) | |||
| : inputStream (0) | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| , numOpenStreams (0) | |||
| #endif | |||
| #endif | |||
| { | |||
| inputSource = new FileInputSource (file); | |||
| init(); | |||
| @@ -180,16 +182,16 @@ ZipFile::ZipFile (const File& file) | |||
| ZipFile::ZipFile (InputSource* const inputSource_) | |||
| : inputStream (0), | |||
| inputSource (inputSource_) | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| , numOpenStreams (0) | |||
| #endif | |||
| #endif | |||
| { | |||
| init(); | |||
| } | |||
| ZipFile::~ZipFile() | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| entries.clear(); | |||
| /* If you hit this assertion, it means you've created a stream to read one of the items in the | |||
| @@ -198,7 +200,7 @@ ZipFile::~ZipFile() | |||
| stream that the file uses to read itself. | |||
| */ | |||
| jassert (numOpenStreams == 0); | |||
| #endif | |||
| #endif | |||
| } | |||
| //============================================================================== | |||
| @@ -427,4 +429,156 @@ bool ZipFile::uncompressEntry (const int index, | |||
| } | |||
| //============================================================================= | |||
| extern unsigned long juce_crc32 (unsigned long crc, const unsigned char* buf, unsigned len); | |||
| class ZipFile::Builder::Item | |||
| { | |||
| public: | |||
| Item (const File& file_, const int compressionLevel_, const String& storedPathName_) | |||
| : file (file_), | |||
| storedPathname (storedPathName_.isEmpty() ? file_.getFileName() : storedPathName_), | |||
| compressionLevel (compressionLevel_), | |||
| compressedSize (0), | |||
| headerStart (0) | |||
| { | |||
| } | |||
| bool writeData (OutputStream& target, const int64 overallStartPosition) | |||
| { | |||
| MemoryOutputStream compressedData; | |||
| if (compressionLevel > 0) | |||
| { | |||
| GZIPCompressorOutputStream compressor (&compressedData, compressionLevel, false, | |||
| GZIPCompressorOutputStream::windowBitsRaw); | |||
| if (! writeSource (compressor)) | |||
| return false; | |||
| } | |||
| else | |||
| { | |||
| if (! writeSource (compressedData)) | |||
| return false; | |||
| } | |||
| compressedSize = compressedData.getDataSize(); | |||
| headerStart = (int) (target.getPosition() - overallStartPosition); | |||
| target.writeInt (0x04034b50); | |||
| writeFlagsAndSizes (target); | |||
| target << storedPathname | |||
| << compressedData; | |||
| return true; | |||
| } | |||
| bool writeDirectoryEntry (OutputStream& target) | |||
| { | |||
| target.writeInt (0x02014b50); | |||
| target.writeShort (20); // version written | |||
| writeFlagsAndSizes (target); | |||
| target.writeShort (0); // comment length | |||
| target.writeShort (0); // start disk num | |||
| target.writeShort (0); // internal attributes | |||
| target.writeInt (0); // external attributes | |||
| target.writeInt (headerStart); | |||
| target << storedPathname; | |||
| return true; | |||
| } | |||
| private: | |||
| const File file; | |||
| String storedPathname; | |||
| int compressionLevel, compressedSize, headerStart; | |||
| uint32 checksum; | |||
| void writeTimeAndDate (OutputStream& target) const | |||
| { | |||
| const Time t (file.getLastModificationTime()); | |||
| target.writeShort ((short) (t.getSeconds() + (t.getMinutes() << 5) + (t.getHours() << 11))); | |||
| target.writeShort ((short) (t.getDayOfMonth() + ((t.getMonth() + 1) << 5) + ((t.getYear() - 1980) << 9))); | |||
| } | |||
| bool writeSource (OutputStream& target) | |||
| { | |||
| checksum = 0; | |||
| ScopedPointer<FileInputStream> input (file.createInputStream()); | |||
| if (input == 0) | |||
| return false; | |||
| const int bufferSize = 2048; | |||
| HeapBlock<unsigned char> buffer (bufferSize); | |||
| while (! input->isExhausted()) | |||
| { | |||
| const int bytesRead = input->read (buffer, bufferSize); | |||
| if (bytesRead < 0) | |||
| return false; | |||
| checksum = juce_crc32 (checksum, buffer, bytesRead); | |||
| target.write (buffer, bytesRead); | |||
| } | |||
| return true; | |||
| } | |||
| void writeFlagsAndSizes (OutputStream& target) const | |||
| { | |||
| target.writeShort (10); // version needed | |||
| target.writeShort (0); // flags | |||
| target.writeShort (compressionLevel > 0 ? (short) 8 : (short) 0); | |||
| writeTimeAndDate (target); | |||
| target.writeInt (checksum); | |||
| target.writeInt (compressedSize); | |||
| target.writeInt ((int) file.getSize()); | |||
| target.writeShort ((short) storedPathname.toUTF8().sizeInBytes() - 1); | |||
| target.writeShort (0); // extra field length | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Item); | |||
| }; | |||
| //============================================================================= | |||
| ZipFile::Builder::Builder() {} | |||
| ZipFile::Builder::~Builder() {} | |||
| void ZipFile::Builder::addFile (const File& fileToAdd, const int compressionLevel, const String& storedPathName) | |||
| { | |||
| items.add (new Item (fileToAdd, compressionLevel, storedPathName)); | |||
| } | |||
| bool ZipFile::Builder::writeToStream (OutputStream& target) const | |||
| { | |||
| const int64 fileStart = target.getPosition(); | |||
| int i; | |||
| for (i = 0; i < items.size(); ++i) | |||
| if (! items.getUnchecked (i)->writeData (target, fileStart)) | |||
| return false; | |||
| const int64 directoryStart = target.getPosition(); | |||
| for (i = 0; i < items.size(); ++i) | |||
| if (! items.getUnchecked (i)->writeDirectoryEntry (target)) | |||
| return false; | |||
| const int64 directoryEnd = target.getPosition(); | |||
| target.writeInt (0x06054b50); | |||
| target.writeShort (0); | |||
| target.writeShort (0); | |||
| target.writeShort ((short) items.size()); | |||
| target.writeShort ((short) items.size()); | |||
| target.writeInt ((int) (directoryEnd - directoryStart)); | |||
| target.writeInt ((int) (directoryStart - fileStart)); | |||
| target.writeShort (0); | |||
| target.flush(); | |||
| return true; | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -165,6 +165,45 @@ public: | |||
| const File& targetDirectory, | |||
| bool shouldOverwriteFiles = true); | |||
| //============================================================================== | |||
| /** Used to create a new zip file. | |||
| Create a ZipFile::Builder object, and call its addFile() method to add some files, | |||
| then you can write it to a stream with write(). | |||
| Currently this just stores the files with no compression.. That will be added | |||
| soon! | |||
| */ | |||
| class Builder | |||
| { | |||
| public: | |||
| Builder(); | |||
| ~Builder(); | |||
| /** Adds a file while should be added to the archive. | |||
| The file isn't read immediately, all the files will be read later when the writeToStream() | |||
| method is called. | |||
| The compressionLevel can be between 0 (no compression), and 9 (maximum compression). | |||
| If the storedPathName parameter is specified, you can customise the partial pathname that | |||
| will be stored for this file. | |||
| */ | |||
| void addFile (const File& fileToAdd, int compressionLevel, | |||
| const String& storedPathName = String::empty); | |||
| /** Generates the zip file, writing it to the specified stream. */ | |||
| bool writeToStream (OutputStream& target) const; | |||
| //============================================================================== | |||
| private: | |||
| class Item; | |||
| friend class OwnedArray<Item>; | |||
| OwnedArray<Item> items; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Builder); | |||
| }; | |||
| private: | |||
| //============================================================================== | |||
| class ZipInputStream; | |||
| @@ -47,10 +47,10 @@ | |||
| #include <netdb.h> | |||
| #include <arpa/inet.h> | |||
| #include <netinet/tcp.h> | |||
| #endif | |||
| #ifndef AI_NUMERICSERV // (missing in older Mac SDKs) | |||
| #define AI_NUMERICSERV 0x1000 | |||
| #endif | |||
| #ifndef AI_NUMERICSERV // (missing in older Mac SDKs) | |||
| #define AI_NUMERICSERV 0x1000 | |||
| #endif | |||
| #include "../../core/juce_StandardHeader.h" | |||
| @@ -41,7 +41,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_GZIPCompressorOutputStream.h" | |||
| //============================================================================== | |||
| class GZIPCompressorOutputStream::GZIPCompressorHelper | |||
| { | |||
| @@ -277,4 +277,10 @@ bool GZIPDecompressorInputStream::setPosition (int64 newPos) | |||
| return true; | |||
| } | |||
| // (This is used as a way for the zip file code to use the crc32 function without including zlib) | |||
| unsigned long juce_crc32 (unsigned long crc, const unsigned char* buf, unsigned len) | |||
| { | |||
| return zlibNamespace::crc32 (crc, buf, len); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -747,7 +747,7 @@ class LinuxComponentPeer : public ComponentPeer | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| LinuxComponentPeer (Component* const component, const int windowStyleFlags, Window parentToAddTo)) | |||
| LinuxComponentPeer (Component* const component, const int windowStyleFlags, Window parentToAddTo) | |||
| : ComponentPeer (component, windowStyleFlags), | |||
| windowH (0), parentWindow (0), | |||
| wx (0), wy (0), ww (0), wh (0), | |||
| @@ -118,6 +118,11 @@ public: | |||
| messageQueue.post (m); | |||
| } | |||
| static NSString* getBroacastEventName() | |||
| { | |||
| return juceStringToNS ("juce_" + String::toHexString (File::getSpecialLocation (File::currentExecutableFile).hashCode64())); | |||
| } | |||
| private: | |||
| CFRunLoopRef runLoop; | |||
| CFRunLoopSourceRef runLoopSource; | |||
| @@ -159,6 +164,7 @@ using namespace JUCE_NAMESPACE; | |||
| - (void) applicationDidResignActive: (NSNotification*) aNotification; | |||
| - (void) applicationWillUnhide: (NSNotification*) aNotification; | |||
| - (void) performCallback: (id) info; | |||
| - (void) broadcastMessageCallback: (NSNotification*) info; | |||
| - (void) dummyMethod; | |||
| @end | |||
| @@ -176,6 +182,11 @@ using namespace JUCE_NAMESPACE; | |||
| { | |||
| oldDelegate = [NSApp delegate]; | |||
| [NSApp setDelegate: self]; | |||
| [[NSDistributedNotificationCenter defaultCenter] addObserver: self | |||
| selector: @selector (broadcastMessageCallback:) | |||
| name: AppDelegateRedirector::getBroacastEventName() | |||
| object: nil]; | |||
| } | |||
| else | |||
| { | |||
| @@ -198,6 +209,10 @@ using namespace JUCE_NAMESPACE; | |||
| if (oldDelegate != 0) | |||
| [NSApp setDelegate: oldDelegate]; | |||
| [[NSDistributedNotificationCenter defaultCenter] removeObserver: self | |||
| name: AppDelegateRedirector::getBroacastEventName() | |||
| object: nil]; | |||
| redirector->deleteSelf(); | |||
| [super dealloc]; | |||
| } | |||
| @@ -260,6 +275,13 @@ using namespace JUCE_NAMESPACE; | |||
| } | |||
| } | |||
| - (void) broadcastMessageCallback: (NSNotification*) n | |||
| { | |||
| NSDictionary* dict = (NSDictionary*) [n userInfo]; | |||
| const String messageString (nsStringToJuce ((NSString*) [dict valueForKey: @"message"])); | |||
| MessageManager::getInstance()->deliverBroadcastMessage (messageString); | |||
| } | |||
| - (void) dummyMethod {} // (used as a way of running a dummy thread) | |||
| @end | |||
| @@ -278,7 +300,7 @@ void MessageManager::runDispatchLoop() | |||
| // must only be called by the message thread! | |||
| jassert (isThisTheMessageThread()); | |||
| #if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||
| #if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||
| @try | |||
| { | |||
| [NSApp run]; | |||
| @@ -292,9 +314,9 @@ void MessageManager::runDispatchLoop() | |||
| @finally | |||
| { | |||
| } | |||
| #else | |||
| #else | |||
| [NSApp run]; | |||
| #endif | |||
| #endif | |||
| } | |||
| } | |||
| @@ -453,8 +475,14 @@ bool juce_postMessageToSystemQueue (Message* message) | |||
| return true; | |||
| } | |||
| void MessageManager::broadcastMessage (const String&) | |||
| void MessageManager::broadcastMessage (const String& message) | |||
| { | |||
| NSDictionary* info = [NSDictionary dictionaryWithObject: juceStringToNS (message) | |||
| forKey: @"message"]; | |||
| [[NSDistributedNotificationCenter defaultCenter] postNotificationName: AppDelegateRedirector::getBroacastEventName() | |||
| object: nil | |||
| userInfo: info]; | |||
| } | |||
| void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, void* data) | |||
| @@ -301,11 +301,15 @@ private: | |||
| { | |||
| sessionEventCallback = new SessionEventCallback (*this); | |||
| audioSessionControl->RegisterAudioSessionNotification (sessionEventCallback); | |||
| sessionEventCallback->Release(); // (required because ComBaseClassHelper objects are constructed with a ref count of 1) | |||
| } | |||
| } | |||
| void deleteSessionEventCallback() | |||
| { | |||
| if (audioSessionControl != 0 && sessionEventCallback != 0) | |||
| audioSessionControl->UnregisterAudioSessionNotification (sessionEventCallback); | |||
| audioSessionControl = 0; | |||
| sessionEventCallback = 0; | |||
| } | |||