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.

177 lines
4.8KB

  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. BEGIN_JUCE_NAMESPACE
  19. //==============================================================================
  20. class AudioThumbnailCache::ThumbnailCacheEntry
  21. {
  22. public:
  23. ThumbnailCacheEntry (const int64 hash_)
  24. : hash (hash_),
  25. lastUsed (Time::getMillisecondCounter())
  26. {
  27. }
  28. ThumbnailCacheEntry (InputStream& in)
  29. : lastUsed (0)
  30. {
  31. hash = in.readInt64();
  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 maxNumThumbsToStore_)
  49. : TimeSliceThread ("thumb cache"),
  50. maxNumThumbsToStore (maxNumThumbsToStore_)
  51. {
  52. jassert (maxNumThumbsToStore > 0);
  53. 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 (AudioThumbnail& thumb, const int64 hashCode)
  81. {
  82. const ScopedLock sl (lock);
  83. ThumbnailCacheEntry* te = findThumbFor (hashCode);
  84. if (te != nullptr)
  85. {
  86. te->lastUsed = Time::getMillisecondCounter();
  87. MemoryInputStream in (te->data, false);
  88. thumb.loadFrom (in);
  89. return true;
  90. }
  91. return false;
  92. }
  93. void AudioThumbnailCache::storeThumb (const AudioThumbnail& 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. MemoryOutputStream out (te->data, false);
  107. thumb.saveTo (out);
  108. }
  109. void AudioThumbnailCache::clear()
  110. {
  111. const ScopedLock sl (lock);
  112. thumbs.clear();
  113. }
  114. static inline int getThumbnailCacheFileMagicHeader() noexcept
  115. {
  116. return (int) ByteOrder::littleEndianInt ("ThmC");
  117. }
  118. bool AudioThumbnailCache::readFromStream (InputStream& source)
  119. {
  120. if (source.readInt() != getThumbnailCacheFileMagicHeader())
  121. return false;
  122. const ScopedLock sl (lock);
  123. clear();
  124. int numThumbnails = jmin (maxNumThumbsToStore, source.readInt());
  125. while (--numThumbnails >= 0 && ! source.isExhausted())
  126. thumbs.add (new ThumbnailCacheEntry (source));
  127. return true;
  128. }
  129. void AudioThumbnailCache::writeToStream (OutputStream& out)
  130. {
  131. const ScopedLock sl (lock);
  132. out.writeInt (getThumbnailCacheFileMagicHeader());
  133. out.writeInt (thumbs.size());
  134. for (int i = 0; i < thumbs.size(); ++i)
  135. thumbs.getUnchecked(i)->write (out);
  136. }
  137. END_JUCE_NAMESPACE