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.

137 lines
4.9KB

  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. static StringArray readDeadMansPedalFile (const File& file)
  22. {
  23. StringArray lines;
  24. file.readLines (lines);
  25. lines.removeEmptyStrings();
  26. return lines;
  27. }
  28. PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo,
  29. AudioPluginFormat& formatToLookFor,
  30. FileSearchPath directoriesToSearch,
  31. const bool recursive,
  32. const File& deadMansPedal,
  33. bool allowPluginsWhichRequireAsynchronousInstantiation)
  34. : list (listToAddTo),
  35. format (formatToLookFor),
  36. deadMansPedalFile (deadMansPedal),
  37. allowAsync (allowPluginsWhichRequireAsynchronousInstantiation)
  38. {
  39. directoriesToSearch.removeRedundantPaths();
  40. filesOrIdentifiersToScan = format.searchPathsForPlugins (directoriesToSearch, recursive, allowAsync);
  41. // If any plugins have crashed recently when being loaded, move them to the
  42. // end of the list to give the others a chance to load correctly..
  43. for (auto& crashed : readDeadMansPedalFile (deadMansPedalFile))
  44. for (int j = filesOrIdentifiersToScan.size(); --j >= 0;)
  45. if (crashed == filesOrIdentifiersToScan[j])
  46. filesOrIdentifiersToScan.move (j, -1);
  47. applyBlacklistingsFromDeadMansPedal (listToAddTo, deadMansPedalFile);
  48. nextIndex.set (filesOrIdentifiersToScan.size());
  49. }
  50. PluginDirectoryScanner::~PluginDirectoryScanner()
  51. {
  52. list.scanFinished();
  53. }
  54. //==============================================================================
  55. String PluginDirectoryScanner::getNextPluginFileThatWillBeScanned() const
  56. {
  57. return format.getNameOfPluginFromIdentifier (filesOrIdentifiersToScan [nextIndex.get() - 1]);
  58. }
  59. void PluginDirectoryScanner::updateProgress()
  60. {
  61. progress = (1.0f - nextIndex.get() / (float) filesOrIdentifiersToScan.size());
  62. }
  63. bool PluginDirectoryScanner::scanNextFile (bool dontRescanIfAlreadyInList,
  64. String& nameOfPluginBeingScanned)
  65. {
  66. const int index = --nextIndex;
  67. if (index >= 0)
  68. {
  69. auto file = filesOrIdentifiersToScan [index];
  70. if (file.isNotEmpty() && ! (dontRescanIfAlreadyInList && list.isListingUpToDate (file, format)))
  71. {
  72. nameOfPluginBeingScanned = format.getNameOfPluginFromIdentifier (file);
  73. OwnedArray<PluginDescription> typesFound;
  74. // Add this plugin to the end of the dead-man's pedal list in case it crashes...
  75. auto crashedPlugins = readDeadMansPedalFile (deadMansPedalFile);
  76. crashedPlugins.removeString (file);
  77. crashedPlugins.add (file);
  78. setDeadMansPedalFile (crashedPlugins);
  79. list.scanAndAddFile (file, dontRescanIfAlreadyInList, typesFound, format);
  80. // Managed to load without crashing, so remove it from the dead-man's-pedal..
  81. crashedPlugins.removeString (file);
  82. setDeadMansPedalFile (crashedPlugins);
  83. if (typesFound.size() == 0 && ! list.getBlacklistedFiles().contains (file))
  84. failedFiles.add (file);
  85. }
  86. }
  87. updateProgress();
  88. return index > 0;
  89. }
  90. bool PluginDirectoryScanner::skipNextFile()
  91. {
  92. updateProgress();
  93. return --nextIndex > 0;
  94. }
  95. void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents)
  96. {
  97. if (deadMansPedalFile.getFullPathName().isNotEmpty())
  98. deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true);
  99. }
  100. void PluginDirectoryScanner::applyBlacklistingsFromDeadMansPedal (KnownPluginList& list, const File& file)
  101. {
  102. // If any plugins have crashed recently when being loaded, move them to the
  103. // end of the list to give the others a chance to load correctly..
  104. for (auto& crashedPlugin : readDeadMansPedalFile (file))
  105. list.addToBlacklist (crashedPlugin);
  106. }
  107. } // namespace juce