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.

192 lines
5.0KB

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