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.

199 lines
5.0KB

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