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.

300 lines
11KB

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