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.

159 lines
5.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #include "../../../../juce.h"
  24. #include "juce_PluginDirectoryScanner.h"
  25. #include "juce_AudioPluginFormat.h"
  26. //==============================================================================
  27. PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo,
  28. FileSearchPath directoriesToSearch,
  29. const bool recursive,
  30. const File& deadMansPedalFile_)
  31. : list (listToAddTo),
  32. deadMansPedalFile (deadMansPedalFile_),
  33. nextIndex (0),
  34. progress (0)
  35. {
  36. directoriesToSearch.removeRedundantPaths();
  37. for (int j = 0; j < directoriesToSearch.getNumPaths(); ++j)
  38. recursiveFileSearch (directoriesToSearch [j], recursive);
  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. const StringArray crashedPlugins (getDeadMansPedalFile());
  42. for (int i = 0; i < crashedPlugins.size(); ++i)
  43. {
  44. const File f (crashedPlugins[i]);
  45. for (int j = filesToScan.size(); --j >= 0;)
  46. if (f == *filesToScan.getUnchecked (j))
  47. filesToScan.move (j, -1);
  48. }
  49. }
  50. void PluginDirectoryScanner::recursiveFileSearch (const File& dir, const bool recursive)
  51. {
  52. // avoid allowing the dir iterator to be recursive, because we want to avoid letting it delve inside
  53. // .component or .vst directories.
  54. DirectoryIterator iter (dir, false, "*", File::findFilesAndDirectories);
  55. while (iter.next())
  56. {
  57. const File f (iter.getFile());
  58. bool isPlugin = false;
  59. for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i)
  60. {
  61. AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i);
  62. if (format->fileMightContainThisPluginType (f))
  63. {
  64. isPlugin = true;
  65. filesToScan.add (new File (f));
  66. break;
  67. }
  68. }
  69. if (recursive && (! isPlugin) && f.isDirectory())
  70. recursiveFileSearch (f, true);
  71. }
  72. }
  73. PluginDirectoryScanner::~PluginDirectoryScanner()
  74. {
  75. }
  76. //==============================================================================
  77. const File PluginDirectoryScanner::getNextPluginFileThatWillBeScanned() const throw()
  78. {
  79. File* const file = filesToScan [nextIndex];
  80. if (file != 0)
  81. return *file;
  82. return File::nonexistent;
  83. }
  84. bool PluginDirectoryScanner::scanNextFile (const bool dontRescanIfAlreadyInList)
  85. {
  86. File* const file = filesToScan [nextIndex];
  87. if (file != 0)
  88. {
  89. if (! list.isListingUpToDate (*file))
  90. {
  91. OwnedArray <PluginDescription> typesFound;
  92. // Add this plugin to the end of the dead-man's pedal list in case it crashes...
  93. StringArray crashedPlugins (getDeadMansPedalFile());
  94. crashedPlugins.removeString (file->getFullPathName());
  95. crashedPlugins.add (file->getFullPathName());
  96. setDeadMansPedalFile (crashedPlugins);
  97. list.scanAndAddFile (*file,
  98. dontRescanIfAlreadyInList,
  99. typesFound);
  100. // Managed to load without crashing, so remove it from the dead-man's-pedal..
  101. crashedPlugins.removeString (file->getFullPathName());
  102. setDeadMansPedalFile (crashedPlugins);
  103. }
  104. ++nextIndex;
  105. progress = nextIndex / (float) filesToScan.size();
  106. }
  107. return nextIndex < filesToScan.size();
  108. }
  109. const StringArray PluginDirectoryScanner::getDeadMansPedalFile() throw()
  110. {
  111. StringArray lines;
  112. if (deadMansPedalFile != File::nonexistent)
  113. {
  114. lines.addLines (deadMansPedalFile.loadFileAsString());
  115. lines.removeEmptyStrings();
  116. }
  117. return lines;
  118. }
  119. void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents) throw()
  120. {
  121. if (deadMansPedalFile != File::nonexistent)
  122. deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true);
  123. }