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.

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