mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Fix for linux build, lookandfeel typo, VS2005 sockets. Added a class ZipFile::Builder for creating zip files.
This commit is contained in:
parent
883ff38bf5
commit
c15d414895
15 changed files with 505 additions and 48 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue