mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-27 02:20:05 +00:00
This commit is contained in:
parent
336f5fa85c
commit
e9691fb437
13 changed files with 338 additions and 330 deletions
|
|
@ -96,14 +96,14 @@ const String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
|
|||
e->hasAttribute (T("audioDeviceOutChans")) ? &outs : 0,
|
||||
true));
|
||||
|
||||
StringArray enabledMidiIns;
|
||||
midiInsFromXml.clear();
|
||||
forEachXmlChildElementWithTagName (*e, c, T("MIDIINPUT"))
|
||||
enabledMidiIns.add (c->getStringAttribute (T("name")));
|
||||
midiInsFromXml.add (c->getStringAttribute (T("name")));
|
||||
|
||||
const StringArray allMidiIns (MidiInput::getDevices());
|
||||
|
||||
for (int i = allMidiIns.size(); --i >= 0;)
|
||||
setMidiInputEnabled (allMidiIns[i], enabledMidiIns.contains (allMidiIns[i]));
|
||||
setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i]));
|
||||
|
||||
if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
|
||||
error = initialise (numInputChannelsNeeded, numOutputChannelsNeeded, 0,
|
||||
|
|
@ -450,6 +450,24 @@ void AudioDeviceManager::updateXml()
|
|||
lastExplicitSettings->addChildElement (m);
|
||||
}
|
||||
|
||||
if (midiInsFromXml.size() > 0)
|
||||
{
|
||||
// Add any midi devices that have been enabled before, but which aren't currently
|
||||
// open because the device has been disconnected.
|
||||
const StringArray availableMidiDevices (MidiInput::getDevices());
|
||||
|
||||
for (int i = 0; i < midiInsFromXml.size(); ++i)
|
||||
{
|
||||
if (! availableMidiDevices.contains (midiInsFromXml[i], true))
|
||||
{
|
||||
XmlElement* const m = new XmlElement (T("MIDIINPUT"));
|
||||
m->setAttribute (T("name"), midiInsFromXml[i]);
|
||||
|
||||
lastExplicitSettings->addChildElement (m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultMidiOutputName.isNotEmpty())
|
||||
lastExplicitSettings->setAttribute (T("defaultMidiOutput"), defaultMidiOutputName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -371,6 +371,7 @@ private:
|
|||
mutable bool listNeedsScanning;
|
||||
bool useInputNames;
|
||||
|
||||
StringArray midiInsFromXml;
|
||||
OwnedArray <MidiInput> enabledMidiInputs;
|
||||
Array <MidiInputCallback*> midiCallbacks;
|
||||
Array <MidiInput*> midiCallbackDevices;
|
||||
|
|
|
|||
|
|
@ -419,16 +419,9 @@ public:
|
|||
|
||||
~AddChannelOp() throw() {}
|
||||
|
||||
void perform (AudioSampleBuffer& sharedBufferChans,
|
||||
const OwnedArray <MidiBuffer>& sharedMidiBuffers,
|
||||
const int numSamples) throw()
|
||||
void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray <MidiBuffer>&, const int numSamples) throw()
|
||||
{
|
||||
if (dstChannelNum != AudioProcessorGraph::midiChannelIndex)
|
||||
sharedBufferChans.addFrom (dstChannelNum, 0, sharedBufferChans, srcChannelNum, 0, numSamples);
|
||||
else
|
||||
sharedMidiBuffers.getUnchecked (dstChannelNum)
|
||||
->addEvents (*sharedMidiBuffers.getUnchecked (srcChannelNum),
|
||||
0, numSamples, 0);
|
||||
sharedBufferChans.addFrom (dstChannelNum, 0, sharedBufferChans, srcChannelNum, 0, numSamples);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -719,9 +712,8 @@ private:
|
|||
{
|
||||
const int srcIndex = getBufferContaining (sourceNodes.getUnchecked(j),
|
||||
sourceOutputChans.getUnchecked(j));
|
||||
jassert (srcIndex >= 0);
|
||||
|
||||
renderingOps.add (new AddChannelOp (srcIndex, bufIndex));
|
||||
if (srcIndex >= 0)
|
||||
renderingOps.add (new AddChannelOp (srcIndex, bufIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -429,13 +429,7 @@ void ComboBox::paint (Graphics& g)
|
|||
void ComboBox::resized()
|
||||
{
|
||||
if (getHeight() > 0 && getWidth() > 0)
|
||||
{
|
||||
label->setBounds (1, 1,
|
||||
getWidth() + 3 - getHeight(),
|
||||
getHeight() - 2);
|
||||
|
||||
label->setFont (getLookAndFeel().getComboBoxFont (*this));
|
||||
}
|
||||
getLookAndFeel().positionComboBoxText (*this, *label);
|
||||
}
|
||||
|
||||
void ComboBox::enablementChanged()
|
||||
|
|
|
|||
|
|
@ -1304,12 +1304,6 @@ void Slider::mouseDrag (const MouseEvent& e)
|
|||
|
||||
mouseXWhenLastDragged = e.x;
|
||||
mouseYWhenLastDragged = e.y;
|
||||
|
||||
// (repainting synchronously makes the sliders feel a bit snappier..)
|
||||
ComponentPeer* const peer = getPeer();
|
||||
|
||||
if (peer != 0)
|
||||
peer->performAnyPendingRepaintsNow();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,8 @@ public:
|
|||
file.getFileName(),
|
||||
icon,
|
||||
fileSize, modTime,
|
||||
isDirectory, highlighted);
|
||||
isDirectory, highlighted,
|
||||
index);
|
||||
}
|
||||
|
||||
void mouseDown (const MouseEvent& e)
|
||||
|
|
|
|||
|
|
@ -160,7 +160,8 @@ public:
|
|||
file.getFileName(),
|
||||
icon,
|
||||
fileSize, modTime,
|
||||
isDirectory, isSelected());
|
||||
isDirectory, isSelected(),
|
||||
indexInContentsList);
|
||||
}
|
||||
|
||||
void itemClicked (const MouseEvent& e)
|
||||
|
|
|
|||
|
|
@ -394,12 +394,6 @@ void ScrollBar::mouseDrag (const MouseEvent& e)
|
|||
setCurrentRangeStart (dragStartRange
|
||||
+ deltaPixels * ((maximum - minimum) - rangeSize)
|
||||
/ (thumbAreaSize - thumbSize));
|
||||
|
||||
// (repainting synchronously makes it feel a bit snappier..)
|
||||
ComponentPeer* const peer = getPeer();
|
||||
|
||||
if (peer != 0)
|
||||
peer->performAnyPendingRepaintsNow();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -537,7 +537,7 @@ void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar,
|
|||
|
||||
Path p;
|
||||
|
||||
for (float x = (float) (stripeWidth - position); x < width + stripeWidth; x += stripeWidth)
|
||||
for (float x = (float) (-stripeWidth - position); x < width + stripeWidth; x += stripeWidth)
|
||||
p.addQuadrilateral (x, 0.0f,
|
||||
x + stripeWidth * 0.5f, 0.0f,
|
||||
x, (float) height,
|
||||
|
|
@ -1178,6 +1178,15 @@ Label* LookAndFeel::createComboBoxTextBox (ComboBox&)
|
|||
return new Label (String::empty, String::empty);
|
||||
}
|
||||
|
||||
void LookAndFeel::positionComboBoxText (ComboBox& box, Label& label)
|
||||
{
|
||||
label.setBounds (1, 1,
|
||||
box.getWidth() + 3 - box.getHeight(),
|
||||
box.getHeight() - 2);
|
||||
|
||||
label.setFont (getComboBoxFont (box));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void LookAndFeel::drawLinearSliderBackground (Graphics& g,
|
||||
int x, int y,
|
||||
|
|
@ -2346,7 +2355,8 @@ void LookAndFeel::drawFileBrowserRow (Graphics& g, int width, int height,
|
|||
const String& fileSizeDescription,
|
||||
const String& fileTimeDescription,
|
||||
const bool isDirectory,
|
||||
const bool isItemSelected)
|
||||
const bool isItemSelected,
|
||||
const int /*itemIndex*/)
|
||||
{
|
||||
if (isItemSelected)
|
||||
g.fillAll (findColour (DirectoryContentsDisplayComponent::highlightColourId));
|
||||
|
|
|
|||
|
|
@ -266,7 +266,8 @@ public:
|
|||
const String& fileSizeDescription,
|
||||
const String& fileTimeDescription,
|
||||
const bool isDirectory,
|
||||
const bool isItemSelected);
|
||||
const bool isItemSelected,
|
||||
const int itemIndex);
|
||||
|
||||
virtual Button* createFileBrowserGoUpButton();
|
||||
|
||||
|
|
@ -343,6 +344,8 @@ public:
|
|||
|
||||
virtual Label* createComboBoxTextBox (ComboBox& box);
|
||||
|
||||
virtual void positionComboBoxText (ComboBox& box, Label& labelToPosition);
|
||||
|
||||
//==============================================================================
|
||||
virtual void drawLinearSlider (Graphics& g,
|
||||
int x, int y,
|
||||
|
|
|
|||
|
|
@ -93,8 +93,7 @@ void SplashScreen::show (const String& title,
|
|||
setVisible (true);
|
||||
centreWithSize (width, height);
|
||||
|
||||
addToDesktop (useDropShadow ? (ComponentPeer::windowAppearsOnTaskbar | ComponentPeer::windowHasDropShadow)
|
||||
: ComponentPeer::windowAppearsOnTaskbar);
|
||||
addToDesktop (useDropShadow ? ComponentPeer::windowHasDropShadow : 0);
|
||||
toFront (false);
|
||||
|
||||
MessageManager::getInstance()->dispatchPendingMessages();
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ public:
|
|||
{
|
||||
Oversampling_none = 0, /**< No vertical anti-aliasing at all. */
|
||||
Oversampling_4times = 2, /**< Anti-aliased with 4 levels of grey - good enough for normal use. */
|
||||
Oversampling_16times = 4, /**< Anti-aliased with 16 levels of grey - very good quality but slower. */
|
||||
Oversampling_16times = 4, /**< Anti-aliased with 16 levels of grey - very good quality. */
|
||||
Oversampling_32times = 5, /**< Anti-aliased with 32 levels of grey - very good quality but slower. */
|
||||
Oversampling_256times = 8 /**< Anti-aliased with 256 levels of grey - best quality, but too slow for
|
||||
normal user-interface use. */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,297 +1,297 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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 "../../basics/juce_StandardHeader.h"
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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 "../../basics/juce_StandardHeader.h"
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4309 4305)
|
||||
#endif
|
||||
|
||||
namespace zlibNamespace
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#undef OS_CODE
|
||||
#undef fdopen
|
||||
#define ZLIB_INTERNAL
|
||||
#define NO_DUMMY_DECL
|
||||
#include "zlib/zlib.h"
|
||||
|
||||
#include "zlib/adler32.c"
|
||||
#include "zlib/compress.c"
|
||||
#undef DO1
|
||||
#undef DO8
|
||||
#include "zlib/crc32.c"
|
||||
#include "zlib/deflate.c"
|
||||
#include "zlib/infback.c"
|
||||
#include "zlib/inffast.c"
|
||||
#undef PULLBYTE
|
||||
#undef LOAD
|
||||
#undef RESTORE
|
||||
#undef INITBITS
|
||||
#undef NEEDBITS
|
||||
#undef DROPBITS
|
||||
#undef BYTEBITS
|
||||
#include "zlib/inflate.c"
|
||||
#include "zlib/inftrees.c"
|
||||
#include "zlib/trees.c"
|
||||
#include "zlib/uncompr.c"
|
||||
#include "zlib/zutil.c"
|
||||
}
|
||||
}
|
||||
namespace zlibNamespace
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#undef OS_CODE
|
||||
#undef fdopen
|
||||
#define ZLIB_INTERNAL
|
||||
#define NO_DUMMY_DECL
|
||||
#include "zlib/zlib.h"
|
||||
|
||||
#include "zlib/adler32.c"
|
||||
#include "zlib/compress.c"
|
||||
#undef DO1
|
||||
#undef DO8
|
||||
#include "zlib/crc32.c"
|
||||
#include "zlib/deflate.c"
|
||||
#include "zlib/infback.c"
|
||||
#include "zlib/inffast.c"
|
||||
#undef PULLBYTE
|
||||
#undef LOAD
|
||||
#undef RESTORE
|
||||
#undef INITBITS
|
||||
#undef NEEDBITS
|
||||
#undef DROPBITS
|
||||
#undef BYTEBITS
|
||||
#include "zlib/inflate.c"
|
||||
#include "zlib/inftrees.c"
|
||||
#include "zlib/trees.c"
|
||||
#include "zlib/uncompr.c"
|
||||
#include "zlib/zutil.c"
|
||||
}
|
||||
}
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_GZIPDecompressorInputStream.h"
|
||||
|
||||
using namespace zlibNamespace;
|
||||
|
||||
//==============================================================================
|
||||
// internal helper object that holds the zlib structures so they don't have to be
|
||||
// included publicly.
|
||||
class GZIPDecompressHelper
|
||||
{
|
||||
private:
|
||||
z_stream* stream;
|
||||
uint8* data;
|
||||
int dataSize;
|
||||
|
||||
public:
|
||||
bool finished, needsDictionary, error;
|
||||
|
||||
GZIPDecompressHelper (const bool noWrap) throw()
|
||||
: data (0),
|
||||
dataSize (0),
|
||||
finished (false),
|
||||
needsDictionary (false),
|
||||
error (false)
|
||||
{
|
||||
stream = (z_stream*) juce_calloc (sizeof (z_stream));
|
||||
|
||||
if (inflateInit2 (stream, (noWrap) ? -MAX_WBITS
|
||||
: MAX_WBITS) != Z_OK)
|
||||
{
|
||||
juce_free (stream);
|
||||
stream = 0;
|
||||
error = true;
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
~GZIPDecompressHelper() throw()
|
||||
{
|
||||
if (stream != 0)
|
||||
{
|
||||
inflateEnd (stream);
|
||||
juce_free (stream);
|
||||
}
|
||||
}
|
||||
|
||||
bool needsInput() const throw() { return dataSize <= 0; }
|
||||
int getTotalOut() const throw() { return (stream != 0) ? stream->total_out : 0; }
|
||||
|
||||
void setInput (uint8* const data_, const int size) throw()
|
||||
{
|
||||
data = data_;
|
||||
dataSize = size;
|
||||
}
|
||||
|
||||
int doNextBlock (uint8* const dest, const int destSize) throw()
|
||||
{
|
||||
if (stream != 0 && data != 0 && ! finished)
|
||||
{
|
||||
stream->next_in = data;
|
||||
stream->next_out = dest;
|
||||
stream->avail_in = dataSize;
|
||||
stream->avail_out = destSize;
|
||||
|
||||
switch (inflate (stream, Z_PARTIAL_FLUSH))
|
||||
{
|
||||
case Z_STREAM_END:
|
||||
finished = true;
|
||||
// deliberate fall-through
|
||||
|
||||
case Z_OK:
|
||||
data += dataSize - stream->avail_in;
|
||||
dataSize = stream->avail_in;
|
||||
return destSize - stream->avail_out;
|
||||
|
||||
case Z_NEED_DICT:
|
||||
needsDictionary = true;
|
||||
data += dataSize - stream->avail_in;
|
||||
dataSize = stream->avail_in;
|
||||
break;
|
||||
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
error = true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
const int gzipDecompBufferSize = 32768;
|
||||
|
||||
GZIPDecompressorInputStream::GZIPDecompressorInputStream (InputStream* const sourceStream_,
|
||||
const bool deleteSourceWhenDestroyed_,
|
||||
const bool noWrap_,
|
||||
const int64 uncompressedStreamLength_)
|
||||
: sourceStream (sourceStream_),
|
||||
uncompressedStreamLength (uncompressedStreamLength_),
|
||||
deleteSourceWhenDestroyed (deleteSourceWhenDestroyed_),
|
||||
noWrap (noWrap_),
|
||||
isEof (false),
|
||||
activeBufferSize (0),
|
||||
originalSourcePos (sourceStream_->getPosition())
|
||||
{
|
||||
buffer = (uint8*) juce_malloc (gzipDecompBufferSize);
|
||||
helper = new GZIPDecompressHelper (noWrap_);
|
||||
}
|
||||
|
||||
GZIPDecompressorInputStream::~GZIPDecompressorInputStream()
|
||||
{
|
||||
juce_free (buffer);
|
||||
|
||||
if (deleteSourceWhenDestroyed)
|
||||
delete sourceStream;
|
||||
|
||||
GZIPDecompressHelper* const h = (GZIPDecompressHelper*) helper;
|
||||
delete h;
|
||||
}
|
||||
|
||||
int64 GZIPDecompressorInputStream::getTotalLength()
|
||||
{
|
||||
return uncompressedStreamLength;
|
||||
}
|
||||
|
||||
int GZIPDecompressorInputStream::read (void* destBuffer, int howMany)
|
||||
{
|
||||
GZIPDecompressHelper* const h = (GZIPDecompressHelper*) helper;
|
||||
|
||||
if ((howMany > 0) && ! isEof)
|
||||
{
|
||||
jassert (destBuffer != 0);
|
||||
|
||||
if (destBuffer != 0)
|
||||
{
|
||||
int numRead = 0;
|
||||
uint8* d = (uint8*) destBuffer;
|
||||
|
||||
while (! h->error)
|
||||
{
|
||||
const int n = h->doNextBlock (d, howMany);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
if (h->finished || h->needsDictionary)
|
||||
{
|
||||
isEof = true;
|
||||
return numRead;
|
||||
}
|
||||
|
||||
if (h->needsInput())
|
||||
{
|
||||
activeBufferSize = sourceStream->read (buffer, gzipDecompBufferSize);
|
||||
|
||||
if (activeBufferSize > 0)
|
||||
{
|
||||
h->setInput ((uint8*) buffer, activeBufferSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
isEof = true;
|
||||
return numRead;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
numRead += n;
|
||||
howMany -= n;
|
||||
d += n;
|
||||
|
||||
if (howMany <= 0)
|
||||
return numRead;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool GZIPDecompressorInputStream::isExhausted()
|
||||
{
|
||||
const GZIPDecompressHelper* const h = (GZIPDecompressHelper*) helper;
|
||||
|
||||
return h->error || isEof;
|
||||
}
|
||||
|
||||
int64 GZIPDecompressorInputStream::getPosition()
|
||||
{
|
||||
const GZIPDecompressHelper* const h = (GZIPDecompressHelper*) helper;
|
||||
|
||||
return h->getTotalOut() + activeBufferSize;
|
||||
}
|
||||
|
||||
bool GZIPDecompressorInputStream::setPosition (int64 newPos)
|
||||
{
|
||||
const int64 currentPos = getPosition();
|
||||
|
||||
if (newPos != currentPos)
|
||||
{
|
||||
// reset the stream and start again..
|
||||
GZIPDecompressHelper* const h = (GZIPDecompressHelper*) helper;
|
||||
delete h;
|
||||
|
||||
isEof = false;
|
||||
activeBufferSize = 0;
|
||||
helper = new GZIPDecompressHelper (noWrap);
|
||||
|
||||
sourceStream->setPosition (originalSourcePos);
|
||||
skipNextBytes (newPos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_GZIPDecompressorInputStream.h"
|
||||
|
||||
using namespace zlibNamespace;
|
||||
|
||||
//==============================================================================
|
||||
// internal helper object that holds the zlib structures so they don't have to be
|
||||
// included publicly.
|
||||
class GZIPDecompressHelper
|
||||
{
|
||||
private:
|
||||
z_stream* stream;
|
||||
uint8* data;
|
||||
int dataSize;
|
||||
|
||||
public:
|
||||
bool finished, needsDictionary, error;
|
||||
|
||||
GZIPDecompressHelper (const bool noWrap) throw()
|
||||
: data (0),
|
||||
dataSize (0),
|
||||
finished (false),
|
||||
needsDictionary (false),
|
||||
error (false)
|
||||
{
|
||||
stream = (z_stream*) juce_calloc (sizeof (z_stream));
|
||||
|
||||
if (inflateInit2 (stream, (noWrap) ? -MAX_WBITS
|
||||
: MAX_WBITS) != Z_OK)
|
||||
{
|
||||
juce_free (stream);
|
||||
stream = 0;
|
||||
error = true;
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
~GZIPDecompressHelper() throw()
|
||||
{
|
||||
if (stream != 0)
|
||||
{
|
||||
inflateEnd (stream);
|
||||
juce_free (stream);
|
||||
}
|
||||
}
|
||||
|
||||
bool needsInput() const throw() { return dataSize <= 0; }
|
||||
int getTotalOut() const throw() { return (stream != 0) ? stream->total_out : 0; }
|
||||
|
||||
void setInput (uint8* const data_, const int size) throw()
|
||||
{
|
||||
data = data_;
|
||||
dataSize = size;
|
||||
}
|
||||
|
||||
int doNextBlock (uint8* const dest, const int destSize) throw()
|
||||
{
|
||||
if (stream != 0 && data != 0 && ! finished)
|
||||
{
|
||||
stream->next_in = data;
|
||||
stream->next_out = dest;
|
||||
stream->avail_in = dataSize;
|
||||
stream->avail_out = destSize;
|
||||
|
||||
switch (inflate (stream, Z_PARTIAL_FLUSH))
|
||||
{
|
||||
case Z_STREAM_END:
|
||||
finished = true;
|
||||
// deliberate fall-through
|
||||
|
||||
case Z_OK:
|
||||
data += dataSize - stream->avail_in;
|
||||
dataSize = stream->avail_in;
|
||||
return destSize - stream->avail_out;
|
||||
|
||||
case Z_NEED_DICT:
|
||||
needsDictionary = true;
|
||||
data += dataSize - stream->avail_in;
|
||||
dataSize = stream->avail_in;
|
||||
break;
|
||||
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
error = true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
const int gzipDecompBufferSize = 32768;
|
||||
|
||||
GZIPDecompressorInputStream::GZIPDecompressorInputStream (InputStream* const sourceStream_,
|
||||
const bool deleteSourceWhenDestroyed_,
|
||||
const bool noWrap_,
|
||||
const int64 uncompressedStreamLength_)
|
||||
: sourceStream (sourceStream_),
|
||||
uncompressedStreamLength (uncompressedStreamLength_),
|
||||
deleteSourceWhenDestroyed (deleteSourceWhenDestroyed_),
|
||||
noWrap (noWrap_),
|
||||
isEof (false),
|
||||
activeBufferSize (0),
|
||||
originalSourcePos (sourceStream_->getPosition())
|
||||
{
|
||||
buffer = (uint8*) juce_malloc (gzipDecompBufferSize);
|
||||
helper = new GZIPDecompressHelper (noWrap_);
|
||||
}
|
||||
|
||||
GZIPDecompressorInputStream::~GZIPDecompressorInputStream()
|
||||
{
|
||||
juce_free (buffer);
|
||||
|
||||
if (deleteSourceWhenDestroyed)
|
||||
delete sourceStream;
|
||||
|
||||
GZIPDecompressHelper* const h = (GZIPDecompressHelper*) helper;
|
||||
delete h;
|
||||
}
|
||||
|
||||
int64 GZIPDecompressorInputStream::getTotalLength()
|
||||
{
|
||||
return uncompressedStreamLength;
|
||||
}
|
||||
|
||||
int GZIPDecompressorInputStream::read (void* destBuffer, int howMany)
|
||||
{
|
||||
GZIPDecompressHelper* const h = (GZIPDecompressHelper*) helper;
|
||||
|
||||
if ((howMany > 0) && ! isEof)
|
||||
{
|
||||
jassert (destBuffer != 0);
|
||||
|
||||
if (destBuffer != 0)
|
||||
{
|
||||
int numRead = 0;
|
||||
uint8* d = (uint8*) destBuffer;
|
||||
|
||||
while (! h->error)
|
||||
{
|
||||
const int n = h->doNextBlock (d, howMany);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
if (h->finished || h->needsDictionary)
|
||||
{
|
||||
isEof = true;
|
||||
return numRead;
|
||||
}
|
||||
|
||||
if (h->needsInput())
|
||||
{
|
||||
activeBufferSize = sourceStream->read (buffer, gzipDecompBufferSize);
|
||||
|
||||
if (activeBufferSize > 0)
|
||||
{
|
||||
h->setInput ((uint8*) buffer, activeBufferSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
isEof = true;
|
||||
return numRead;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
numRead += n;
|
||||
howMany -= n;
|
||||
d += n;
|
||||
|
||||
if (howMany <= 0)
|
||||
return numRead;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool GZIPDecompressorInputStream::isExhausted()
|
||||
{
|
||||
const GZIPDecompressHelper* const h = (GZIPDecompressHelper*) helper;
|
||||
|
||||
return h->error || isEof;
|
||||
}
|
||||
|
||||
int64 GZIPDecompressorInputStream::getPosition()
|
||||
{
|
||||
const GZIPDecompressHelper* const h = (GZIPDecompressHelper*) helper;
|
||||
|
||||
return h->getTotalOut() + activeBufferSize;
|
||||
}
|
||||
|
||||
bool GZIPDecompressorInputStream::setPosition (int64 newPos)
|
||||
{
|
||||
const int64 currentPos = getPosition();
|
||||
|
||||
if (newPos != currentPos)
|
||||
{
|
||||
// reset the stream and start again..
|
||||
GZIPDecompressHelper* const h = (GZIPDecompressHelper*) helper;
|
||||
delete h;
|
||||
|
||||
isEof = false;
|
||||
activeBufferSize = 0;
|
||||
helper = new GZIPDecompressHelper (noWrap);
|
||||
|
||||
sourceStream->setPosition (originalSourcePos);
|
||||
skipNextBytes (newPos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue