Audio plugin host https://kx.studio/carla
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.

187 lines
5.4KB

  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. class ApplicationCommandTarget::CommandMessage : public MessageManager::MessageBase
  21. {
  22. public:
  23. CommandMessage (ApplicationCommandTarget* const target, const InvocationInfo& inf)
  24. : owner (target), info (inf)
  25. {
  26. }
  27. void messageCallback() override
  28. {
  29. if (ApplicationCommandTarget* const target = owner)
  30. target->tryToInvoke (info, false);
  31. }
  32. private:
  33. WeakReference<ApplicationCommandTarget> owner;
  34. const InvocationInfo info;
  35. JUCE_DECLARE_NON_COPYABLE (CommandMessage)
  36. };
  37. //==============================================================================
  38. ApplicationCommandTarget::ApplicationCommandTarget() {}
  39. ApplicationCommandTarget::~ApplicationCommandTarget() {}
  40. //==============================================================================
  41. bool ApplicationCommandTarget::tryToInvoke (const InvocationInfo& info, const bool async)
  42. {
  43. if (isCommandActive (info.commandID))
  44. {
  45. if (async)
  46. {
  47. (new CommandMessage (this, info))->post();
  48. return true;
  49. }
  50. if (perform (info))
  51. return true;
  52. // Hmm.. your target claimed that it could perform this command, but failed to do so.
  53. // If it can't do it at the moment for some reason, it should clear the 'isActive' flag
  54. // when it returns the command's info.
  55. jassertfalse;
  56. }
  57. return false;
  58. }
  59. ApplicationCommandTarget* ApplicationCommandTarget::findFirstTargetParentComponent()
  60. {
  61. if (Component* const c = dynamic_cast<Component*> (this))
  62. return c->findParentComponentOfClass<ApplicationCommandTarget>();
  63. return nullptr;
  64. }
  65. ApplicationCommandTarget* ApplicationCommandTarget::getTargetForCommand (const CommandID commandID)
  66. {
  67. ApplicationCommandTarget* target = this;
  68. int depth = 0;
  69. while (target != nullptr)
  70. {
  71. Array<CommandID> commandIDs;
  72. target->getAllCommands (commandIDs);
  73. if (commandIDs.contains (commandID))
  74. return target;
  75. target = target->getNextCommandTarget();
  76. ++depth;
  77. jassert (depth < 100); // could be a recursive command chain??
  78. jassert (target != this); // definitely a recursive command chain!
  79. if (depth > 100 || target == this)
  80. break;
  81. }
  82. if (target == nullptr)
  83. {
  84. target = JUCEApplication::getInstance();
  85. if (target != nullptr)
  86. {
  87. Array<CommandID> commandIDs;
  88. target->getAllCommands (commandIDs);
  89. if (commandIDs.contains (commandID))
  90. return target;
  91. }
  92. }
  93. return nullptr;
  94. }
  95. bool ApplicationCommandTarget::isCommandActive (const CommandID commandID)
  96. {
  97. ApplicationCommandInfo info (commandID);
  98. info.flags = ApplicationCommandInfo::isDisabled;
  99. getCommandInfo (commandID, info);
  100. return (info.flags & ApplicationCommandInfo::isDisabled) == 0;
  101. }
  102. //==============================================================================
  103. bool ApplicationCommandTarget::invoke (const InvocationInfo& info, const bool async)
  104. {
  105. ApplicationCommandTarget* target = this;
  106. int depth = 0;
  107. while (target != nullptr)
  108. {
  109. if (target->tryToInvoke (info, async))
  110. return true;
  111. target = target->getNextCommandTarget();
  112. ++depth;
  113. jassert (depth < 100); // could be a recursive command chain??
  114. jassert (target != this); // definitely a recursive command chain!
  115. if (depth > 100 || target == this)
  116. break;
  117. }
  118. if (target == nullptr)
  119. {
  120. target = JUCEApplication::getInstance();
  121. if (target != nullptr)
  122. return target->tryToInvoke (info, async);
  123. }
  124. return false;
  125. }
  126. bool ApplicationCommandTarget::invokeDirectly (const CommandID commandID, const bool asynchronously)
  127. {
  128. ApplicationCommandTarget::InvocationInfo info (commandID);
  129. info.invocationMethod = ApplicationCommandTarget::InvocationInfo::direct;
  130. return invoke (info, asynchronously);
  131. }
  132. //==============================================================================
  133. ApplicationCommandTarget::InvocationInfo::InvocationInfo (const CommandID command)
  134. : commandID (command),
  135. commandFlags (0),
  136. invocationMethod (direct),
  137. originatingComponent (nullptr),
  138. isKeyDown (false),
  139. millisecsSinceKeyPressed (0)
  140. {
  141. }
  142. } // namespace juce