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.

141 lines
5.1KB

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