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.

292 lines
11KB

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