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.

172 lines
4.7KB

  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 hash_)
  22. : hash (hash_),
  23. lastUsed (Time::getMillisecondCounter())
  24. {
  25. }
  26. ThumbnailCacheEntry (InputStream& in)
  27. : lastUsed (0)
  28. {
  29. hash = in.readInt64();
  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 maxNumThumbsToStore_)
  47. : thread ("thumb cache"),
  48. maxNumThumbsToStore (maxNumThumbsToStore_)
  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. ThumbnailCacheEntry* te = findThumbFor (hashCode);
  82. if (te != nullptr)
  83. {
  84. te->lastUsed = Time::getMillisecondCounter();
  85. MemoryInputStream in (te->data, false);
  86. thumb.loadFrom (in);
  87. return true;
  88. }
  89. return false;
  90. }
  91. void AudioThumbnailCache::storeThumb (const AudioThumbnailBase& thumb,
  92. const int64 hashCode)
  93. {
  94. const ScopedLock sl (lock);
  95. ThumbnailCacheEntry* te = findThumbFor (hashCode);
  96. if (te == nullptr)
  97. {
  98. te = new ThumbnailCacheEntry (hashCode);
  99. if (thumbs.size() < maxNumThumbsToStore)
  100. thumbs.add (te);
  101. else
  102. thumbs.set (findOldestThumb(), te);
  103. }
  104. MemoryOutputStream out (te->data, false);
  105. thumb.saveTo (out);
  106. }
  107. void AudioThumbnailCache::clear()
  108. {
  109. const ScopedLock sl (lock);
  110. thumbs.clear();
  111. }
  112. static inline int getThumbnailCacheFileMagicHeader() noexcept
  113. {
  114. return (int) ByteOrder::littleEndianInt ("ThmC");
  115. }
  116. bool AudioThumbnailCache::readFromStream (InputStream& source)
  117. {
  118. if (source.readInt() != getThumbnailCacheFileMagicHeader())
  119. return false;
  120. const ScopedLock sl (lock);
  121. clear();
  122. int numThumbnails = jmin (maxNumThumbsToStore, source.readInt());
  123. while (--numThumbnails >= 0 && ! source.isExhausted())
  124. thumbs.add (new ThumbnailCacheEntry (source));
  125. return true;
  126. }
  127. void AudioThumbnailCache::writeToStream (OutputStream& out)
  128. {
  129. const ScopedLock sl (lock);
  130. out.writeInt (getThumbnailCacheFileMagicHeader());
  131. out.writeInt (thumbs.size());
  132. for (int i = 0; i < thumbs.size(); ++i)
  133. thumbs.getUnchecked(i)->write (out);
  134. }