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.

140 lines
5.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. static StringArray readDeadMansPedalFile (const File& file)
  21. {
  22. StringArray lines;
  23. file.readLines (lines);
  24. lines.removeEmptyStrings();
  25. return lines;
  26. }
  27. PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo,
  28. AudioPluginFormat& formatToLookFor,
  29. FileSearchPath directoriesToSearch,
  30. const bool recursive,
  31. const File& deadMansPedal,
  32. bool allowPluginsWhichRequireAsynchronousInstantiation)
  33. : list (listToAddTo),
  34. format (formatToLookFor),
  35. deadMansPedalFile (deadMansPedal),
  36. allowAsync (allowPluginsWhichRequireAsynchronousInstantiation)
  37. {
  38. directoriesToSearch.removeRedundantPaths();
  39. setFilesOrIdentifiersToScan (format.searchPathsForPlugins (directoriesToSearch, recursive, allowAsync));
  40. }
  41. PluginDirectoryScanner::~PluginDirectoryScanner()
  42. {
  43. list.scanFinished();
  44. }
  45. //==============================================================================
  46. void PluginDirectoryScanner::setFilesOrIdentifiersToScan (const StringArray& filesOrIdentifiers)
  47. {
  48. filesOrIdentifiersToScan = filesOrIdentifiers;
  49. // If any plugins have crashed recently when being loaded, move them to the
  50. // end of the list to give the others a chance to load correctly..
  51. for (auto& crashed : readDeadMansPedalFile (deadMansPedalFile))
  52. for (int j = filesOrIdentifiersToScan.size(); --j >= 0;)
  53. if (crashed == filesOrIdentifiersToScan[j])
  54. filesOrIdentifiersToScan.move (j, -1);
  55. applyBlacklistingsFromDeadMansPedal (list, deadMansPedalFile);
  56. nextIndex.set (filesOrIdentifiersToScan.size());
  57. }
  58. String PluginDirectoryScanner::getNextPluginFileThatWillBeScanned() const
  59. {
  60. return format.getNameOfPluginFromIdentifier (filesOrIdentifiersToScan [nextIndex.get() - 1]);
  61. }
  62. void PluginDirectoryScanner::updateProgress()
  63. {
  64. progress = (1.0f - (float) nextIndex.get() / (float) filesOrIdentifiersToScan.size());
  65. }
  66. bool PluginDirectoryScanner::scanNextFile (bool dontRescanIfAlreadyInList,
  67. String& nameOfPluginBeingScanned)
  68. {
  69. const int index = --nextIndex;
  70. if (index >= 0)
  71. {
  72. auto file = filesOrIdentifiersToScan [index];
  73. if (file.isNotEmpty() && ! (dontRescanIfAlreadyInList && list.isListingUpToDate (file, format)))
  74. {
  75. nameOfPluginBeingScanned = format.getNameOfPluginFromIdentifier (file);
  76. OwnedArray<PluginDescription> typesFound;
  77. // Add this plugin to the end of the dead-man's pedal list in case it crashes...
  78. auto crashedPlugins = readDeadMansPedalFile (deadMansPedalFile);
  79. crashedPlugins.removeString (file);
  80. crashedPlugins.add (file);
  81. setDeadMansPedalFile (crashedPlugins);
  82. list.scanAndAddFile (file, dontRescanIfAlreadyInList, typesFound, format);
  83. // Managed to load without crashing, so remove it from the dead-man's-pedal..
  84. crashedPlugins.removeString (file);
  85. setDeadMansPedalFile (crashedPlugins);
  86. if (typesFound.size() == 0 && ! list.getBlacklistedFiles().contains (file))
  87. failedFiles.add (file);
  88. }
  89. }
  90. updateProgress();
  91. return index > 0;
  92. }
  93. bool PluginDirectoryScanner::skipNextFile()
  94. {
  95. updateProgress();
  96. return --nextIndex > 0;
  97. }
  98. void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents)
  99. {
  100. if (deadMansPedalFile.getFullPathName().isNotEmpty())
  101. deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true);
  102. }
  103. void PluginDirectoryScanner::applyBlacklistingsFromDeadMansPedal (KnownPluginList& list, const File& file)
  104. {
  105. // If any plugins have crashed recently when being loaded, move them to the
  106. // end of the list to give the others a chance to load correctly..
  107. for (auto& crashedPlugin : readDeadMansPedalFile (file))
  108. list.addToBlacklist (crashedPlugin);
  109. }
  110. } // namespace juce