mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Added storage methods to AudioThumbnailCache.
This commit is contained in:
parent
fd00effb69
commit
8ef30afad2
4 changed files with 113 additions and 46 deletions
|
|
@ -453,7 +453,6 @@ namespace WavFileHelpers
|
|||
class WavAudioFormatReader : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
WavAudioFormatReader (InputStream* const in)
|
||||
: AudioFormatReader (in, TRANS (wavFormatName)),
|
||||
bwavChunkStart (0),
|
||||
|
|
@ -650,14 +649,14 @@ public:
|
|||
MemoryBlock textBlock;
|
||||
input->readIntoMemoryBlock (textBlock, (int) stringLength);
|
||||
|
||||
metadataValues.set (prefix + "Identifier", String (identifier));
|
||||
metadataValues.set (prefix + "SampleLength", String (sampleLength));
|
||||
metadataValues.set (prefix + "Purpose", String (purpose));
|
||||
metadataValues.set (prefix + "Country", String (country));
|
||||
metadataValues.set (prefix + "Language", String (language));
|
||||
metadataValues.set (prefix + "Dialect", String (dialect));
|
||||
metadataValues.set (prefix + "CodePage", String (codePage));
|
||||
metadataValues.set (prefix + "Text", textBlock.toString());
|
||||
metadataValues.set (prefix + "Identifier", String (identifier));
|
||||
metadataValues.set (prefix + "SampleLength", String (sampleLength));
|
||||
metadataValues.set (prefix + "Purpose", String (purpose));
|
||||
metadataValues.set (prefix + "Country", String (country));
|
||||
metadataValues.set (prefix + "Language", String (language));
|
||||
metadataValues.set (prefix + "Dialect", String (dialect));
|
||||
metadataValues.set (prefix + "CodePage", String (codePage));
|
||||
metadataValues.set (prefix + "Text", textBlock.toString());
|
||||
}
|
||||
|
||||
input->setPosition (adtlChunkEnd);
|
||||
|
|
@ -746,7 +745,6 @@ private:
|
|||
class WavAudioFormatWriter : public AudioFormatWriter
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
WavAudioFormatWriter (OutputStream* const out, const double sampleRate_,
|
||||
const unsigned int numChannels_, const unsigned int bits,
|
||||
const StringPairArray& metadataValues)
|
||||
|
|
|
|||
|
|
@ -26,12 +26,35 @@
|
|||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
//==============================================================================
|
||||
struct ThumbnailCacheEntry
|
||||
class AudioThumbnailCache::ThumbnailCacheEntry
|
||||
{
|
||||
public:
|
||||
ThumbnailCacheEntry (const int64 hash_)
|
||||
: hash (hash_),
|
||||
lastUsed (Time::getMillisecondCounter())
|
||||
{
|
||||
}
|
||||
|
||||
ThumbnailCacheEntry (InputStream& in)
|
||||
: lastUsed (0)
|
||||
{
|
||||
hash = in.readInt64();
|
||||
const int64 len = in.readInt64();
|
||||
in.readIntoMemoryBlock (data, len);
|
||||
}
|
||||
|
||||
void write (OutputStream& out)
|
||||
{
|
||||
out.writeInt64 (hash);
|
||||
out.writeInt64 ((int64) data.getSize());
|
||||
out << data;
|
||||
}
|
||||
|
||||
int64 hash;
|
||||
uint32 lastUsed;
|
||||
MemoryBlock data;
|
||||
|
||||
private:
|
||||
JUCE_LEAK_DETECTOR (ThumbnailCacheEntry);
|
||||
};
|
||||
|
||||
|
|
@ -40,6 +63,7 @@ AudioThumbnailCache::AudioThumbnailCache (const int maxNumThumbsToStore_)
|
|||
: TimeSliceThread ("thumb cache"),
|
||||
maxNumThumbsToStore (maxNumThumbsToStore_)
|
||||
{
|
||||
jassert (maxNumThumbsToStore > 0);
|
||||
startThread (2);
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +71,7 @@ AudioThumbnailCache::~AudioThumbnailCache()
|
|||
{
|
||||
}
|
||||
|
||||
ThumbnailCacheEntry* AudioThumbnailCache::findThumbFor (const int64 hash) const
|
||||
AudioThumbnailCache::ThumbnailCacheEntry* AudioThumbnailCache::findThumbFor (const int64 hash) const
|
||||
{
|
||||
for (int i = thumbs.size(); --i >= 0;)
|
||||
if (thumbs.getUnchecked(i)->hash == hash)
|
||||
|
|
@ -56,8 +80,28 @@ ThumbnailCacheEntry* AudioThumbnailCache::findThumbFor (const int64 hash) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
int AudioThumbnailCache::findOldestThumb() const
|
||||
{
|
||||
int oldest = 0;
|
||||
uint32 oldestTime = Time::getMillisecondCounter() + 1;
|
||||
|
||||
for (int i = thumbs.size(); --i >= 0;)
|
||||
{
|
||||
const ThumbnailCacheEntry* const te = thumbs.getUnchecked(i);
|
||||
|
||||
if (te->lastUsed < oldestTime)
|
||||
{
|
||||
oldest = i;
|
||||
oldestTime = te->lastUsed;
|
||||
}
|
||||
}
|
||||
|
||||
return oldest;
|
||||
}
|
||||
|
||||
bool AudioThumbnailCache::loadThumb (AudioThumbnail& thumb, const int64 hashCode)
|
||||
{
|
||||
const ScopedLock sl (lock);
|
||||
ThumbnailCacheEntry* te = findThumbFor (hashCode);
|
||||
|
||||
if (te != nullptr)
|
||||
|
|
@ -75,45 +119,58 @@ bool AudioThumbnailCache::loadThumb (AudioThumbnail& thumb, const int64 hashCode
|
|||
void AudioThumbnailCache::storeThumb (const AudioThumbnail& thumb,
|
||||
const int64 hashCode)
|
||||
{
|
||||
const ScopedLock sl (lock);
|
||||
ThumbnailCacheEntry* te = findThumbFor (hashCode);
|
||||
|
||||
if (te == nullptr)
|
||||
{
|
||||
te = new ThumbnailCacheEntry();
|
||||
te->hash = hashCode;
|
||||
te = new ThumbnailCacheEntry (hashCode);
|
||||
|
||||
if (thumbs.size() < maxNumThumbsToStore)
|
||||
{
|
||||
thumbs.add (te);
|
||||
}
|
||||
else
|
||||
{
|
||||
int oldest = 0;
|
||||
uint32 oldestTime = Time::getMillisecondCounter() + 1;
|
||||
|
||||
for (int i = thumbs.size(); --i >= 0;)
|
||||
{
|
||||
if (thumbs.getUnchecked(i)->lastUsed < oldestTime)
|
||||
{
|
||||
oldest = i;
|
||||
oldestTime = thumbs.getUnchecked(i)->lastUsed;
|
||||
}
|
||||
}
|
||||
|
||||
thumbs.set (oldest, te);
|
||||
}
|
||||
thumbs.set (findOldestThumb(), te);
|
||||
}
|
||||
|
||||
te->lastUsed = Time::getMillisecondCounter();
|
||||
|
||||
MemoryOutputStream out (te->data, false);
|
||||
thumb.saveTo (out);
|
||||
}
|
||||
|
||||
void AudioThumbnailCache::clear()
|
||||
{
|
||||
const ScopedLock sl (lock);
|
||||
thumbs.clear();
|
||||
}
|
||||
|
||||
static inline int getThumbnailCacheFileMagicHeader() noexcept
|
||||
{
|
||||
return (int) ByteOrder::littleEndianInt ("ThmC");
|
||||
}
|
||||
|
||||
bool AudioThumbnailCache::readFromStream (InputStream& source)
|
||||
{
|
||||
if (source.readInt() != getThumbnailCacheFileMagicHeader())
|
||||
return false;
|
||||
|
||||
const ScopedLock sl (lock);
|
||||
clear();
|
||||
int numThumbnails = jmin (maxNumThumbsToStore, source.readInt());
|
||||
|
||||
while (--numThumbnails >= 0 && ! source.isExhausted())
|
||||
thumbs.add (new ThumbnailCacheEntry (source));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioThumbnailCache::writeToStream (OutputStream& out)
|
||||
{
|
||||
const ScopedLock sl (lock);
|
||||
|
||||
out.writeInt (getThumbnailCacheFileMagicHeader());
|
||||
out.writeInt (thumbs.size());
|
||||
|
||||
for (int i = 0; i < thumbs.size(); ++i)
|
||||
thumbs.getUnchecked(i)->write (out);
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#define __JUCE_AUDIOTHUMBNAILCACHE_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioThumbnail.h"
|
||||
struct ThumbnailCacheEntry;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -74,13 +73,28 @@ public:
|
|||
*/
|
||||
void storeThumb (const AudioThumbnail& thumb, int64 hashCode);
|
||||
|
||||
//==============================================================================
|
||||
/** Attempts to re-load a saved cache of thumbnails from a stream.
|
||||
The cache data must have been written by the writeToStream() method.
|
||||
This will replace all currently-loaded thumbnails with the new data.
|
||||
*/
|
||||
bool readFromStream (InputStream& source);
|
||||
|
||||
/** Writes all currently-loaded cache data to a stream.
|
||||
The resulting data can be re-loaded with readFromStream().
|
||||
*/
|
||||
void writeToStream (OutputStream& stream);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
OwnedArray <ThumbnailCacheEntry> thumbs;
|
||||
class ThumbnailCacheEntry;
|
||||
friend class OwnedArray<ThumbnailCacheEntry>;
|
||||
OwnedArray<ThumbnailCacheEntry> thumbs;
|
||||
CriticalSection lock;
|
||||
int maxNumThumbsToStore;
|
||||
|
||||
ThumbnailCacheEntry* findThumbFor (int64 hash) const;
|
||||
int findOldestThumb() const;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioThumbnailCache);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1929,21 +1929,20 @@ public:
|
|||
if (clip != nullptr)
|
||||
{
|
||||
SoftwareRendererClasses::ClipRegion_EdgeTable* edgeTableClip = new SoftwareRendererClasses::ClipRegion_EdgeTable (edgeTable);
|
||||
SoftwareRendererClasses::ClipRegionBase::Ptr shapeToFill (edgeTableClip);
|
||||
edgeTableClip->edgeTable.translate (x + transform.xOffset, y + transform.yOffset);
|
||||
fillShape (shapeToFill, false);
|
||||
edgeTableClip->edgeTable.translate (x + transform.xOffset,
|
||||
y + transform.yOffset);
|
||||
fillShape (edgeTableClip, false);
|
||||
}
|
||||
}
|
||||
|
||||
void drawGlyph (const Font& f, int glyphNumber, const AffineTransform& t)
|
||||
{
|
||||
const ScopedPointer<EdgeTable> et (f.getTypeface()->getEdgeTableForGlyph (glyphNumber, transform.getTransformWith (t)));
|
||||
|
||||
if (et != nullptr && clip != nullptr)
|
||||
if (clip != nullptr)
|
||||
{
|
||||
SoftwareRendererClasses::ClipRegion_EdgeTable* edgeTableClip = new SoftwareRendererClasses::ClipRegion_EdgeTable (*et);
|
||||
SoftwareRendererClasses::ClipRegionBase::Ptr shapeToFill (edgeTableClip);
|
||||
fillShape (shapeToFill, false);
|
||||
const ScopedPointer<EdgeTable> et (f.getTypeface()->getEdgeTableForGlyph (glyphNumber, transform.getTransformWith (t)));
|
||||
|
||||
if (et != nullptr)
|
||||
fillShape (new SoftwareRendererClasses::ClipRegion_EdgeTable (*et), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2021,8 +2020,7 @@ public:
|
|||
|
||||
if (! area.isEmpty())
|
||||
{
|
||||
SoftwareRendererClasses::ClipRegionBase::Ptr c (new SoftwareRendererClasses::ClipRegion_EdgeTable (area));
|
||||
c = clip->applyClipTo (c);
|
||||
SoftwareRendererClasses::ClipRegionBase::Ptr c (clip->applyClipTo (new SoftwareRendererClasses::ClipRegion_EdgeTable (area)));
|
||||
|
||||
if (c != nullptr)
|
||||
c->renderImageUntransformed (destData, srcData, alpha, tx, ty, false);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue