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.

198 lines
5.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. class AudioThumbnailCache::ThumbnailCacheEntry
  21. {
  22. public:
  23. ThumbnailCacheEntry (const int64 hashCode)
  24. : hash (hashCode),
  25. lastUsed (Time::getMillisecondCounter())
  26. {
  27. }
  28. ThumbnailCacheEntry (InputStream& in)
  29. : hash (in.readInt64()),
  30. lastUsed (0)
  31. {
  32. const int64 len = in.readInt64();
  33. in.readIntoMemoryBlock (data, (ssize_t) len);
  34. }
  35. void write (OutputStream& out)
  36. {
  37. out.writeInt64 (hash);
  38. out.writeInt64 ((int64) data.getSize());
  39. out << data;
  40. }
  41. int64 hash;
  42. uint32 lastUsed;
  43. MemoryBlock data;
  44. private:
  45. JUCE_LEAK_DETECTOR (ThumbnailCacheEntry)
  46. };
  47. //==============================================================================
  48. AudioThumbnailCache::AudioThumbnailCache (const int maxNumThumbs)
  49. : thread ("thumb cache"),
  50. maxNumThumbsToStore (maxNumThumbs)
  51. {
  52. jassert (maxNumThumbsToStore > 0);
  53. thread.startThread (2);
  54. }
  55. AudioThumbnailCache::~AudioThumbnailCache()
  56. {
  57. }
  58. AudioThumbnailCache::ThumbnailCacheEntry* AudioThumbnailCache::findThumbFor (const int64 hash) const
  59. {
  60. for (int i = thumbs.size(); --i >= 0;)
  61. if (thumbs.getUnchecked(i)->hash == hash)
  62. return thumbs.getUnchecked(i);
  63. return nullptr;
  64. }
  65. int AudioThumbnailCache::findOldestThumb() const
  66. {
  67. int oldest = 0;
  68. uint32 oldestTime = Time::getMillisecondCounter() + 1;
  69. for (int i = thumbs.size(); --i >= 0;)
  70. {
  71. const ThumbnailCacheEntry* const te = thumbs.getUnchecked(i);
  72. if (te->lastUsed < oldestTime)
  73. {
  74. oldest = i;
  75. oldestTime = te->lastUsed;
  76. }
  77. }
  78. return oldest;
  79. }
  80. bool AudioThumbnailCache::loadThumb (AudioThumbnailBase& thumb, const int64 hashCode)
  81. {
  82. const ScopedLock sl (lock);
  83. if (ThumbnailCacheEntry* te = findThumbFor (hashCode))
  84. {
  85. te->lastUsed = Time::getMillisecondCounter();
  86. MemoryInputStream in (te->data, false);
  87. thumb.loadFrom (in);
  88. return true;
  89. }
  90. return loadNewThumb (thumb, hashCode);
  91. }
  92. void AudioThumbnailCache::storeThumb (const AudioThumbnailBase& thumb,
  93. const int64 hashCode)
  94. {
  95. const ScopedLock sl (lock);
  96. ThumbnailCacheEntry* te = findThumbFor (hashCode);
  97. if (te == nullptr)
  98. {
  99. te = new ThumbnailCacheEntry (hashCode);
  100. if (thumbs.size() < maxNumThumbsToStore)
  101. thumbs.add (te);
  102. else
  103. thumbs.set (findOldestThumb(), te);
  104. }
  105. {
  106. MemoryOutputStream out (te->data, false);
  107. thumb.saveTo (out);
  108. }
  109. saveNewlyFinishedThumbnail (thumb, hashCode);
  110. }
  111. void AudioThumbnailCache::clear()
  112. {
  113. const ScopedLock sl (lock);
  114. thumbs.clear();
  115. }
  116. void AudioThumbnailCache::removeThumb (const int64 hashCode)
  117. {
  118. const ScopedLock sl (lock);
  119. for (int i = thumbs.size(); --i >= 0;)
  120. if (thumbs.getUnchecked(i)->hash == hashCode)
  121. thumbs.remove (i);
  122. }
  123. static int getThumbnailCacheFileMagicHeader() noexcept
  124. {
  125. return (int) ByteOrder::littleEndianInt ("ThmC");
  126. }
  127. bool AudioThumbnailCache::readFromStream (InputStream& source)
  128. {
  129. if (source.readInt() != getThumbnailCacheFileMagicHeader())
  130. return false;
  131. const ScopedLock sl (lock);
  132. clear();
  133. int numThumbnails = jmin (maxNumThumbsToStore, source.readInt());
  134. while (--numThumbnails >= 0 && ! source.isExhausted())
  135. thumbs.add (new ThumbnailCacheEntry (source));
  136. return true;
  137. }
  138. void AudioThumbnailCache::writeToStream (OutputStream& out)
  139. {
  140. const ScopedLock sl (lock);
  141. out.writeInt (getThumbnailCacheFileMagicHeader());
  142. out.writeInt (thumbs.size());
  143. for (int i = 0; i < thumbs.size(); ++i)
  144. thumbs.getUnchecked(i)->write (out);
  145. }
  146. void AudioThumbnailCache::saveNewlyFinishedThumbnail (const AudioThumbnailBase&, int64)
  147. {
  148. }
  149. bool AudioThumbnailCache::loadNewThumb (AudioThumbnailBase&, int64)
  150. {
  151. return false;
  152. }
  153. } // namespace juce