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
4.2KB

  1. #pragma once
  2. #include <JuceHeader.h>
  3. #include "AllUtils.h"
  4. class Superprocess : private juce::ChildProcessCoordinator {
  5. public:
  6. Superprocess(juce::AudioProcessor::WrapperType wrapperType) {
  7. juce::Logger::writeToLog("Launching scan");
  8. launchWorkerProcess(Utils::getPluginScanServerBinary(wrapperType), Utils::PLUGIN_SCAN_SERVER_UID, 0, 0);
  9. }
  10. enum class State {
  11. timeout,
  12. gotResult,
  13. connectionLost,
  14. };
  15. struct Response {
  16. State state;
  17. std::unique_ptr<juce::XmlElement> xml;
  18. };
  19. Response getResponse() {
  20. std::unique_lock<std::mutex> lock { mutex };
  21. if (! condvar.wait_for (lock, std::chrono::milliseconds { 50 }, [&] { return gotResult || connectionLost; })) {
  22. return { State::timeout, nullptr };
  23. }
  24. const auto state = connectionLost ? State::connectionLost : State::gotResult;
  25. connectionLost = false;
  26. gotResult = false;
  27. return {state, std::move (pluginDescription)};
  28. }
  29. using ChildProcessCoordinator::sendMessageToWorker;
  30. private:
  31. void handleMessageFromWorker(const juce::MemoryBlock& mb) override {
  32. const std::lock_guard<std::mutex> lock { mutex };
  33. pluginDescription = parseXML (mb.toString());
  34. gotResult = true;
  35. condvar.notify_one();
  36. }
  37. void handleConnectionLost() override {
  38. juce::Logger::writeToLog("Connection lost");
  39. const std::lock_guard<std::mutex> lock { mutex };
  40. connectionLost = true;
  41. condvar.notify_one();
  42. }
  43. std::mutex mutex;
  44. std::condition_variable condvar;
  45. std::unique_ptr<juce::XmlElement> pluginDescription;
  46. bool connectionLost = false;
  47. bool gotResult = false;
  48. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Superprocess)
  49. };
  50. class CustomPluginScanner : public juce::KnownPluginList::CustomScanner {
  51. public:
  52. CustomPluginScanner(juce::AudioProcessor::WrapperType wrapperType)
  53. : _wrapperType(wrapperType) { }
  54. ~CustomPluginScanner() override { }
  55. bool findPluginTypesFor(juce::AudioPluginFormat& format,
  56. juce::OwnedArray<juce::PluginDescription>& result,
  57. const juce::String& fileOrIdentifier) override {
  58. if (addPluginDescriptions(format.getName(), fileOrIdentifier, result)) {
  59. return true;
  60. }
  61. superprocess = nullptr;
  62. return false;
  63. }
  64. void scanFinished() override {
  65. superprocess = nullptr;
  66. }
  67. private:
  68. /* Scans for a plugin with format 'formatName' and ID 'fileOrIdentifier' using a subprocess,
  69. and adds discovered plugin descriptions to 'result'.
  70. Returns true on success.
  71. Failure indicates that the subprocess is unrecoverable and should be terminated.
  72. */
  73. bool addPluginDescriptions(const juce::String& formatName,
  74. const juce::String& fileOrIdentifier,
  75. juce::OwnedArray<juce::PluginDescription>& result) {
  76. if (superprocess == nullptr) {
  77. superprocess = std::make_unique<Superprocess>(_wrapperType);
  78. }
  79. juce::MemoryBlock block;
  80. juce::MemoryOutputStream stream { block, true };
  81. stream.writeString(formatName);
  82. stream.writeString(fileOrIdentifier);
  83. if (!superprocess->sendMessageToWorker(block)) {
  84. return false;
  85. }
  86. for (;;) {
  87. if (shouldExit()) {
  88. return true;
  89. }
  90. const auto response = superprocess->getResponse();
  91. if (response.state == Superprocess::State::timeout) {
  92. continue;
  93. }
  94. if (response.xml != nullptr) {
  95. for (const auto* item : response.xml->getChildIterator()) {
  96. auto desc = std::make_unique<juce::PluginDescription>();
  97. if (desc->loadFromXml (*item)) {
  98. result.add (std::move (desc));
  99. }
  100. }
  101. }
  102. return (response.state == Superprocess::State::gotResult);
  103. }
  104. }
  105. const juce::AudioProcessor::WrapperType _wrapperType;
  106. std::unique_ptr<Superprocess> superprocess;
  107. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomPluginScanner)
  108. };