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.

294 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. struct MessageHandler
  18. {
  19. virtual ~MessageHandler() {}
  20. virtual bool sendMessage (const ValueTree&) = 0;
  21. static MemoryBlock convertMessage (const ValueTree& tree)
  22. {
  23. MemoryOutputStream out;
  24. tree.writeToStream (out);
  25. return out.getMemoryBlock();
  26. }
  27. static ValueTree convertMessage (const MemoryBlock& rawData)
  28. {
  29. return ValueTree::readFromData (rawData.getData(), rawData.getSize());
  30. }
  31. };
  32. //==============================================================================
  33. static inline Rectangle<int> varToRect (const var& v)
  34. {
  35. if (const Array<var>* obj = v.getArray())
  36. {
  37. if (obj->size() == 4)
  38. {
  39. int intArray[4];
  40. for (int i = 0; i < 4; ++i)
  41. {
  42. const var& p = obj->getReference (i);
  43. if (p.isInt() || p.isDouble() || p.isInt64())
  44. intArray[i] = static_cast<int> (p);
  45. else
  46. return Rectangle<int>();
  47. }
  48. return Rectangle<int> (intArray[0], intArray[1], intArray[2], intArray[3]);
  49. }
  50. }
  51. return Rectangle<int>();
  52. }
  53. static inline var rectToVar (const Rectangle<int>& rect)
  54. {
  55. Array<var> retval;
  56. retval.add (var (rect.getX()));
  57. retval.add (var (rect.getY()));
  58. retval.add (var (rect.getWidth()));
  59. retval.add (var (rect.getHeight()));
  60. return var (retval);
  61. }
  62. //==============================================================================
  63. namespace MessageTypes
  64. {
  65. inline bool send (MessageHandler& target, const ValueTree& v)
  66. {
  67. //DBG ("Send: " << v.getType().toString());
  68. bool result = target.sendMessage (v);
  69. if (! result)
  70. {
  71. DBG ("*** Message failed: " << v.getType().toString());
  72. }
  73. return result;
  74. }
  75. inline bool sendPing (MessageHandler& target)
  76. {
  77. return send (target, ValueTree (PING));
  78. }
  79. //==============================================================================
  80. // client -> server
  81. inline void sendOpenPreview (MessageHandler& target, const ClassDatabase::Class& comp, Rectangle<int> mainWindowRect)
  82. {
  83. ValueTree v (OPEN_PREVIEW);
  84. v.setProperty (Ids::name, comp.getName(), nullptr);
  85. v.setProperty (Ids::bounds, rectToVar (mainWindowRect), nullptr);
  86. send (target, v);
  87. }
  88. inline void sendReinstantiate (MessageHandler& target)
  89. {
  90. send (target, ValueTree (RELOAD));
  91. }
  92. inline void sendFileChanges (MessageHandler& target, const Array<CodeChange>& changes, const File& file)
  93. {
  94. ValueTree changesMessage (MessageTypes::LIVE_FILE_CHANGES);
  95. changesMessage.setProperty (Ids::file, file.getFullPathName(), nullptr);
  96. for (const CodeChange& change : changes)
  97. {
  98. ValueTree v (CHANGE);
  99. v.setProperty (Ids::start, change.range.getStart(), nullptr);
  100. v.setProperty (Ids::end, change.range.getEnd(), nullptr);
  101. v.setProperty (Ids::text, change.text, nullptr);
  102. changesMessage.addChild (v, -1, nullptr);
  103. }
  104. send (target, changesMessage);
  105. }
  106. inline Array<CodeChange> getChangeArray (const ValueTree& changes)
  107. {
  108. Array<CodeChange> result;
  109. for (int i = 0; i < changes.getNumChildren(); ++i)
  110. {
  111. const ValueTree& v = changes.getChild (i);
  112. result.add (CodeChange (Range<int> (v[Ids::start], v[Ids::end]), v[Ids::text]));
  113. }
  114. return result;
  115. }
  116. inline void sendFileContentFullUpdate (MessageHandler& target, const File& file, const String& text)
  117. {
  118. ValueTree v (LIVE_FILE_UPDATE);
  119. v.setProperty (Ids::file, file.getFullPathName(), nullptr);
  120. v.setProperty (Ids::text, text, nullptr);
  121. send (target, v);
  122. }
  123. inline void sendHandleFileReset (MessageHandler& target, const File& file)
  124. {
  125. ValueTree v (LIVE_FILE_RESET);
  126. v.setProperty (Ids::file, file.getFullPathName(), nullptr);
  127. send (target, v);
  128. }
  129. inline void sendNewBuild (MessageHandler& target, const ProjectBuildInfo& build)
  130. {
  131. send (target, build.tree);
  132. }
  133. inline void sendCleanAll (MessageHandler& target)
  134. {
  135. send (target, ValueTree (CLEAN_ALL));
  136. }
  137. inline void sendNewDiagnosticList (MessageHandler& target, const ValueTree& list)
  138. {
  139. send (target, list);
  140. }
  141. inline void sendEmptyDiagnosticList (MessageHandler& target)
  142. {
  143. send (target, ValueTree (MessageTypes::DIAGNOSTIC_LIST));
  144. }
  145. inline void sendProcessActivationState (MessageHandler& target, bool isNowActive)
  146. {
  147. ValueTree v (FOREGROUND);
  148. v.setProperty (Ids::parentActive, isNowActive, nullptr);
  149. send (target, v);
  150. }
  151. inline void sendLaunchApp (MessageHandler& target) { send (target, ValueTree (LAUNCH_APP)); }
  152. inline void sendQuit (MessageHandler& target) { send (target, ValueTree (QUIT_SERVER)); }
  153. inline void sendShouldCloseIDE (MessageHandler& target) { send (target, ValueTree (QUIT_IDE)); }
  154. //==============================================================================
  155. // server -> client
  156. inline void sendNewClassList (MessageHandler& target, const ClassDatabase::ClassList& classes)
  157. {
  158. send (target, classes.toValueTree());
  159. }
  160. inline void sendCrash (MessageHandler& target, const String& message)
  161. {
  162. ValueTree v (CRASH);
  163. v.setProperty (Ids::message, message, nullptr);
  164. send (target, v);
  165. }
  166. inline void sendSystemHeadersMissing (MessageHandler& target)
  167. {
  168. send (target, ValueTree (MISSING_SYSTEM_HEADERS));
  169. }
  170. inline void sendBuildFailed (MessageHandler& target)
  171. {
  172. send (target, ValueTree (BUILD_FAILED));
  173. }
  174. inline void sendNewActivityList (MessageHandler& target, const StringArray& list)
  175. {
  176. ValueTree v (ACTIVITY_LIST);
  177. v.setProperty (Ids::list, concatenateListOfStrings (list), nullptr);
  178. send (target, v);
  179. }
  180. inline void sendChangeCode (MessageHandler& target, const String& location, const String& newText)
  181. {
  182. if (location.isNotEmpty())
  183. {
  184. ValueTree v (CHANGE_CODE);
  185. v.setProperty (Ids::position, location, nullptr);
  186. v.setProperty (Ids::text, newText, nullptr);
  187. send (target, v);
  188. }
  189. }
  190. inline void sendHighlightCode (MessageHandler& target, const String& location)
  191. {
  192. if (location.isNotEmpty())
  193. {
  194. ValueTree v (HIGHLIGHT_CODE);
  195. v.setProperty (Ids::position, location, nullptr);
  196. send (target, v);
  197. }
  198. }
  199. inline void sendAppLaunched (MessageHandler& target) { send (target, ValueTree (LAUNCHED)); }
  200. inline void sendAppQuit (MessageHandler& target) { send (target, ValueTree (APPQUIT)); }
  201. inline void sendKeyPress (MessageHandler& target, const String& className, const String& keyDesc)
  202. {
  203. ValueTree v (KEY);
  204. v.setProperty (Ids::class_, className, nullptr);
  205. v.setProperty (Ids::key, keyDesc, nullptr);
  206. send (target, v);
  207. }
  208. //==============================================================================
  209. template <class MessageHandlerType>
  210. static void dispatchToClient (MessageHandlerType& target, const ValueTree& v)
  211. {
  212. if (v.hasType (DIAGNOSTIC_LIST)) target.handleNewDiagnosticList (v);
  213. else if (v.hasType (ACTIVITY_LIST)) target.handleActivityListChanged (separateJoinedStrings (v [Ids::list]));
  214. else if (v.hasType (Ids::CLASSLIST)) target.handleClassListChanged (v);
  215. else if (v.hasType (BUILD_FAILED)) target.handleBuildFailed();
  216. else if (v.hasType (CHANGE_CODE)) target.handleChangeCode (v [Ids::position].toString(), v [Ids::text]);
  217. else if (v.hasType (HIGHLIGHT_CODE)) target.handleHighlightCode (v [Ids::position].toString());
  218. else if (v.hasType (LAUNCHED)) target.handleAppLaunched();
  219. else if (v.hasType (APPQUIT)) target.handleAppQuit();
  220. else if (v.hasType (PING)) target.handlePing();
  221. else if (v.hasType (CRASH)) target.handleCrash (v [Ids::message]);
  222. else if (v.hasType (KEY)) target.handleKeyPress (v[Ids::class_], KeyPress::createFromDescription (v[Ids::key]));
  223. else if (v.hasType (QUIT_IDE)) target.handleCloseIDE();
  224. else if (v.hasType (MISSING_SYSTEM_HEADERS)) target.handleMissingSystemHeaders();
  225. else jassertfalse;
  226. }
  227. template <class MessageHandlerType>
  228. static void dispatchToServer (MessageHandlerType& target, const ValueTree& v)
  229. {
  230. if (v.hasType (CLEAN_ALL)) target.handleCleanAll();
  231. else if (v.hasType (BUILDINFO)) target.handleNewBuildSettings (ProjectBuildInfo (v));
  232. else if (v.hasType (OPEN_PREVIEW)) target.handleOpenPreview (v[Ids::name], varToRect (v[Ids::bounds]));
  233. else if (v.hasType (RELOAD)) target.handleReinstantiatePreviews();
  234. else if (v.hasType (LAUNCH_APP)) target.handleLaunchApp();
  235. else if (v.hasType (LIVE_FILE_CHANGES)) target.handleLiveFileChanges (v[Ids::file].toString(), getChangeArray (v));
  236. else if (v.hasType (LIVE_FILE_UPDATE)) target.handleLiveFileFullUpdate (v[Ids::file].toString(), v[Ids::text]);
  237. else if (v.hasType (LIVE_FILE_RESET)) target.handleResetLiveFileContent (v[Ids::file].toString());
  238. else if (v.hasType (FOREGROUND)) target.handleProcessActivationState (v[Ids::parentActive]);
  239. else if (v.hasType (PING)) target.handlePing();
  240. else jassertfalse;
  241. }
  242. }