The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
5.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. class AudioThumbnailCache::ThumbnailCacheEntry
  19. {
  20. public:
  21. ThumbnailCacheEntry (const int64 hashCode)
  22. : hash (hashCode),
  23. lastUsed (Time::getMillisecondCounter())
  24. {
  25. }
  26. ThumbnailCacheEntry (InputStream& in)
  27. : hash (in.readInt64()),
  28. lastUsed (0)
  29. {
  30. const int64 len = in.readInt64();
  31. in.readIntoMemoryBlock (data, (ssize_t) len);
  32. }
  33. void write (OutputStream& out)
  34. {
  35. out.writeInt64 (hash);
  36. out.writeInt64 ((int64) data.getSize());
  37. out << data;
  38. }
  39. int64 hash;
  40. uint32 lastUsed;
  41. MemoryBlock data;
  42. private:
  43. JUCE_LEAK_DETECTOR (ThumbnailCacheEntry)
  44. };
  45. //==============================================================================
  46. AudioThumbnailCache::AudioThumbnailCache (const int maxNumThumbs)
  47. : thread ("thumb cache"),
  48. maxNumThumbsToStore (maxNumThumbs)
  49. {
  50. jassert (maxNumThumbsToStore > 0);
  51. thread.startThread (2);
  52. }
  53. AudioThumbnailCache::~AudioThumbnailCache()
  54. {
  55. }
  56. AudioThumbnailCache::ThumbnailCacheEntry* AudioThumbnailCache::findThumbFor (const int64 hash) const
  57. {
  58. for (int i = thumbs.size(); --i >= 0;)
  59. if (thumbs.getUnchecked(i)->hash == hash)
  60. return thumbs.getUnchecked(i);
  61. return nullptr;
  62. }
  63. int AudioThumbnailCache::findOldestThumb() const
  64. {
  65. int oldest = 0;
  66. uint32 oldestTime = Time::getMillisecondCounter() + 1;
  67. for (int i = thumbs.size(); --i >= 0;)
  68. {
  69. const ThumbnailCacheEntry* const te = thumbs.getUnchecked(i);
  70. if (te->lastUsed < oldestTime)
  71. {
  72. oldest = i;
  73. oldestTime = te->lastUsed;
  74. }
  75. }
  76. return oldest;
  77. }
  78. bool AudioThumbnailCache::loadThumb (AudioThumbnailBase& thumb, const int64 hashCode)
  79. {
  80. const ScopedLock sl (lock);
  81. if (ThumbnailCacheEntry* te = findThumbFor (hashCode))
  82. {
  83. te->lastUsed = Time::getMillisecondCounter();
  84. MemoryInputStream in (te->data, false);
  85. thumb.loadFrom (in);
  86. return true;
  87. }
  88. return loadNewThumb (thumb, hashCode);
  89. }
  90. void AudioThumbnailCache::storeThumb (const AudioThumbnailBase& thumb,
  91. const int64 hashCode)
  92. {
  93. const ScopedLock sl (lock);
  94. ThumbnailCacheEntry* te = findThumbFor (hashCode);
  95. if (te == nullptr)
  96. {
  97. te = new ThumbnailCacheEntry (hashCode);
  98. if (thumbs.size() < maxNumThumbsToStore)
  99. thumbs.add (te);
  100. else
  101. thumbs.set (findOldestThumb(), te);
  102. }
  103. {
  104. MemoryOutputStream out (te->data, false);
  105. thumb.saveTo (out);
  106. }
  107. saveNewlyFinishedThumbnail (thumb, hashCode);
  108. }
  109. void AudioThumbnailCache::clear()
  110. {
  111. const ScopedLock sl (lock);
  112. thumbs.clear();
  113. }
  114. void AudioThumbnailCache::removeThumb (const int64 hashCode)
  115. {
  116. const ScopedLock sl (lock);
  117. for (int i = thumbs.size(); --i >= 0;)
  118. if (thumbs.getUnchecked(i)->hash == hashCode)
  119. thumbs.remove (i);
  120. }
  121. static inline int getThumbnailCacheFileMagicHeader() noexcept
  122. {
  123. return (int) ByteOrder::littleEndianInt ("ThmC");
  124. }
  125. bool AudioThumbnailCache::readFromStream (InputStream& source)
  126. {
  127. if (source.readInt() != getThumbnailCacheFileMagicHeader())
  128. return false;
  129. const ScopedLock sl (lock);
  130. clear();
  131. int numThumbnails = jmin (maxNumThumbsToStore, source.readInt());
  132. while (--numThumbnails >= 0 && ! source.isExhausted())
  133. thumbs.add (new ThumbnailCacheEntry (source));
  134. return true;
  135. }
  136. void AudioThumbnailCache::writeToStream (OutputStream& out)
  137. {
  138. const ScopedLock sl (lock);
  139. out.writeInt (getThumbnailCacheFileMagicHeader());
  140. out.writeInt (thumbs.size());
  141. for (int i = 0; i < thumbs.size(); ++i)
  142. thumbs.getUnchecked(i)->write (out);
  143. }
  144. void AudioThumbnailCache::saveNewlyFinishedThumbnail (const AudioThumbnailBase&, int64)
  145. {
  146. }
  147. bool AudioThumbnailCache::loadNewThumb (AudioThumbnailBase&, int64)
  148. {
  149. return false;
  150. }