Audio plugin host https://kx.studio/carla
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.6KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI 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 ImageCache::Pimpl : private Timer,
  18. private DeletedAtShutdown
  19. {
  20. public:
  21. Pimpl() : cacheTimeout (5000)
  22. {
  23. }
  24. ~Pimpl()
  25. {
  26. clearSingletonInstance();
  27. }
  28. Image getFromHashCode (const int64 hashCode)
  29. {
  30. const ScopedLock sl (lock);
  31. for (int i = images.size(); --i >= 0;)
  32. {
  33. const Item* const item = images.getUnchecked(i);
  34. if (item->hashCode == hashCode)
  35. return item->image;
  36. }
  37. return Image();
  38. }
  39. void addImageToCache (const Image& image, const int64 hashCode)
  40. {
  41. if (image.isValid())
  42. {
  43. if (! isTimerRunning())
  44. startTimer (2000);
  45. Item* const item = new Item();
  46. item->hashCode = hashCode;
  47. item->image = image;
  48. item->lastUseTime = Time::getApproximateMillisecondCounter();
  49. const ScopedLock sl (lock);
  50. images.add (item);
  51. }
  52. }
  53. void timerCallback() override
  54. {
  55. const uint32 now = Time::getApproximateMillisecondCounter();
  56. const ScopedLock sl (lock);
  57. for (int i = images.size(); --i >= 0;)
  58. {
  59. Item* const item = images.getUnchecked(i);
  60. if (item->image.getReferenceCount() <= 1)
  61. {
  62. if (now > item->lastUseTime + cacheTimeout || now < item->lastUseTime - 1000)
  63. images.remove (i);
  64. }
  65. else
  66. {
  67. item->lastUseTime = now; // multiply-referenced, so this image is still in use.
  68. }
  69. }
  70. if (images.size() == 0)
  71. stopTimer();
  72. }
  73. void releaseUnusedImages()
  74. {
  75. const ScopedLock sl (lock);
  76. for (int i = images.size(); --i >= 0;)
  77. if (images.getUnchecked(i)->image.getReferenceCount() <= 1)
  78. images.remove (i);
  79. }
  80. struct Item
  81. {
  82. Image image;
  83. int64 hashCode;
  84. uint32 lastUseTime;
  85. };
  86. unsigned int cacheTimeout;
  87. juce_DeclareSingleton_SingleThreaded_Minimal (ImageCache::Pimpl)
  88. private:
  89. OwnedArray<Item> images;
  90. CriticalSection lock;
  91. JUCE_DECLARE_NON_COPYABLE (Pimpl)
  92. };
  93. juce_ImplementSingleton_SingleThreaded (ImageCache::Pimpl)
  94. //==============================================================================
  95. Image ImageCache::getFromHashCode (const int64 hashCode)
  96. {
  97. if (Pimpl::getInstanceWithoutCreating() != nullptr)
  98. return Pimpl::getInstanceWithoutCreating()->getFromHashCode (hashCode);
  99. return Image();
  100. }
  101. void ImageCache::addImageToCache (const Image& image, const int64 hashCode)
  102. {
  103. Pimpl::getInstance()->addImageToCache (image, hashCode);
  104. }
  105. Image ImageCache::getFromFile (const File& file)
  106. {
  107. const int64 hashCode = file.hashCode64();
  108. Image image (getFromHashCode (hashCode));
  109. if (image.isNull())
  110. {
  111. image = ImageFileFormat::loadFrom (file);
  112. addImageToCache (image, hashCode);
  113. }
  114. return image;
  115. }
  116. Image ImageCache::getFromMemory (const void* imageData, const int dataSize)
  117. {
  118. const int64 hashCode = (int64) (pointer_sized_int) imageData;
  119. Image image (getFromHashCode (hashCode));
  120. if (image.isNull())
  121. {
  122. image = ImageFileFormat::loadFrom (imageData, (size_t) dataSize);
  123. addImageToCache (image, hashCode);
  124. }
  125. return image;
  126. }
  127. void ImageCache::setCacheTimeout (const int millisecs)
  128. {
  129. jassert (millisecs >= 0);
  130. Pimpl::getInstance()->cacheTimeout = (unsigned int) millisecs;
  131. }
  132. void ImageCache::releaseUnusedImages()
  133. {
  134. Pimpl::getInstance()->releaseUnusedImages();
  135. }