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.

370 lines
10KB

  1. /*
  2. * Carla Pipe utils
  3. * Copyright (C) 2013-2023 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_PIPE_UTILS_HPP_INCLUDED
  18. #define CARLA_PIPE_UTILS_HPP_INCLUDED
  19. #include "CarlaJuceUtils.hpp"
  20. #include "CarlaMutex.hpp"
  21. #ifdef BUILDING_CARLA
  22. # include "lv2/atom.h"
  23. #else
  24. # include "lv2/atom/atom.h"
  25. #endif
  26. // -----------------------------------------------------------------------
  27. // CarlaPipeCommon class
  28. class CarlaPipeCommon
  29. {
  30. protected:
  31. /*!
  32. * Constructor.
  33. */
  34. CarlaPipeCommon() noexcept;
  35. /*!
  36. * Destructor.
  37. */
  38. virtual ~CarlaPipeCommon() /*noexcept*/;
  39. /*!
  40. * A message has been received (in the context of idlePipe()).
  41. * If extra data is required, use any of the readNextLineAs* functions.
  42. * Returning true means the message has been handled and should not propagate to subclasses.
  43. */
  44. virtual bool msgReceived(const char* msg) noexcept = 0;
  45. /*!
  46. * An error has occurred during the current requested operation.
  47. * Reimplementing this method allows to catch these errors as strings.
  48. * By default the error is simply printed to stderr.
  49. */
  50. virtual void fail(const char* error) noexcept
  51. {
  52. carla_stderr2(error);
  53. }
  54. public:
  55. /*!
  56. * Check if the pipe is running.
  57. */
  58. bool isPipeRunning() const noexcept;
  59. /*!
  60. * Check the pipe for new messages and send them to msgReceived().
  61. */
  62. void idlePipe(bool onlyOnce = false) noexcept;
  63. // -------------------------------------------------------------------
  64. // write lock
  65. /*!
  66. * Lock the pipe write mutex.
  67. */
  68. void lockPipe() const noexcept;
  69. /*!
  70. * Try locking the pipe write mutex.
  71. * Returns true if successful.
  72. */
  73. bool tryLockPipe() const noexcept;
  74. /*!
  75. * Unlock the pipe write mutex.
  76. */
  77. void unlockPipe() const noexcept;
  78. /*!
  79. * Get the pipe write lock.
  80. */
  81. CarlaMutex& getPipeLock() const noexcept;
  82. // -------------------------------------------------------------------
  83. // read lines, must only be called in the context of msgReceived()
  84. /*!
  85. * Read the next line as a boolean.
  86. */
  87. bool readNextLineAsBool(bool& value) const noexcept;
  88. /*!
  89. * Read the next line as a byte.
  90. */
  91. bool readNextLineAsByte(uint8_t& value) const noexcept;
  92. /*!
  93. * Read the next line as an integer.
  94. */
  95. bool readNextLineAsInt(int32_t& value) const noexcept;
  96. /*!
  97. * Read the next line as an unsigned integer.
  98. */
  99. bool readNextLineAsUInt(uint32_t& value) const noexcept;
  100. /*!
  101. * Read the next line as a long integer.
  102. */
  103. bool readNextLineAsLong(int64_t& value) const noexcept;
  104. /*!
  105. * Read the next line as a long unsigned integer.
  106. */
  107. bool readNextLineAsULong(uint64_t& value) const noexcept;
  108. /*!
  109. * Read the next line as a floating point number (single precision).
  110. */
  111. bool readNextLineAsFloat(float& value) const noexcept;
  112. /*!
  113. * Read the next line as a floating point number (double precision).
  114. */
  115. bool readNextLineAsDouble(double& value) const noexcept;
  116. /*!
  117. * Read the next line as a string.
  118. * @note: @a value must be freed if valid and allocateString is true.
  119. */
  120. bool readNextLineAsString(const char*& value, bool allocateString, uint32_t size = 0) const noexcept;
  121. /*!
  122. * Read the next line as a string, returning an allocated copy that needs to be freed.
  123. */
  124. char* readNextLineAsString() const noexcept;
  125. // -------------------------------------------------------------------
  126. // write messages, must be locked before calling
  127. /*!
  128. * Write a valid message with unknown size.
  129. * A valid message has only one '\n' character and it's at the end.
  130. */
  131. bool writeMessage(const char* msg) const noexcept;
  132. /*!
  133. * Write a valid message with known size.
  134. * A valid message has only one '\n' character and it's at the end.
  135. */
  136. bool writeMessage(const char* msg, std::size_t size) const noexcept;
  137. /*!
  138. * Write and fix a message.
  139. */
  140. bool writeAndFixMessage(const char* msg) const noexcept;
  141. /*!
  142. * Write an empty message, which means a single '\n'.
  143. */
  144. bool writeEmptyMessage() const noexcept;
  145. /*!
  146. * Sync all messages currently in cache.
  147. * This call will forcely write any messages in cache to any relevant IO.
  148. */
  149. bool syncMessages() const noexcept;
  150. // -------------------------------------------------------------------
  151. // write prepared messages, no lock or flush needed (done internally)
  152. /*!
  153. * Write an "error" message.
  154. */
  155. bool writeErrorMessage(const char* error) const noexcept;
  156. /*!
  157. * Write a "control" message used for parameter/control changes.
  158. */
  159. bool writeControlMessage(uint32_t index, float value, bool withWriteLock = true) const noexcept;
  160. /*!
  161. * Write a "configure" message used for state changes.
  162. */
  163. bool writeConfigureMessage(const char* key, const char* value) const noexcept;
  164. /*!
  165. * Write a "program" message (using index).
  166. */
  167. bool writeProgramMessage(uint32_t index) const noexcept;
  168. /*!
  169. * Write a "program" message (using channel, bank and program).
  170. */
  171. bool writeProgramMessage(uint8_t channel, uint32_t bank, uint32_t program) const noexcept;
  172. /*!
  173. * Write a "midiprogram" message (using bank and program).
  174. */
  175. bool writeMidiProgramMessage(uint32_t bank, uint32_t program) const noexcept;
  176. /*!
  177. * Write a "reloadprograms" message.
  178. */
  179. bool writeReloadProgramsMessage(int32_t index) const noexcept;
  180. /*!
  181. * Write a MIDI "note" message.
  182. */
  183. bool writeMidiNoteMessage(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) const noexcept;
  184. /*!
  185. * Write an lv2 "atom" message.
  186. */
  187. bool writeLv2AtomMessage(uint32_t index, const LV2_Atom* atom) const noexcept;
  188. /*!
  189. * Write an lv2 "parameter" message.
  190. */
  191. bool writeLv2ParameterMessage(const char* uri, float value, bool withWriteLock = true) const noexcept;
  192. /*!
  193. * Write an lv2 "urid" message.
  194. */
  195. bool writeLv2UridMessage(uint32_t urid, const char* uri) const noexcept;
  196. // -------------------------------------------------------------------
  197. protected:
  198. struct PrivateData;
  199. PrivateData* const pData;
  200. // -------------------------------------------------------------------
  201. /*! @internal */
  202. const char* _readline(bool allocReturn, uint16_t size, bool& readSucess) const noexcept;
  203. /*! @internal */
  204. const char* _readlineblock(bool allocReturn, uint16_t size = 0, uint32_t timeOutMilliseconds = 50) const noexcept;
  205. /*! @internal */
  206. bool _writeMsgBuffer(const char* msg, std::size_t size) const noexcept;
  207. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPipeCommon)
  208. };
  209. // -----------------------------------------------------------------------
  210. // CarlaPipeServer class
  211. class CarlaPipeServer : public CarlaPipeCommon
  212. {
  213. public:
  214. /*!
  215. * Constructor.
  216. */
  217. CarlaPipeServer() noexcept;
  218. /*!
  219. * Destructor.
  220. */
  221. ~CarlaPipeServer() /*noexcept*/ override;
  222. /*!
  223. * Get the process ID of this pipe's matching client.
  224. * Will return 0 if client is not running.
  225. * @note: Unsupported on Windows
  226. */
  227. uintptr_t getPID() const noexcept;
  228. /*!
  229. * Start the pipe server using @a filename with 2 arguments.
  230. * @see fail()
  231. */
  232. bool startPipeServer(const char* helperTool,
  233. const char* filename, const char* arg1, const char* arg2, int size = -1) noexcept;
  234. /*!
  235. * Start the pipe server using @a filename with 2 arguments.
  236. * @see fail()
  237. */
  238. bool startPipeServer(const char* filename, const char* arg1, const char* arg2, int size = -1) noexcept;
  239. /*!
  240. * Stop the pipe server.
  241. * This will send a quit message to the client, wait for it to close for @a timeOutMilliseconds, and close the pipes.
  242. */
  243. void stopPipeServer(uint32_t timeOutMilliseconds) noexcept;
  244. /*!
  245. * Close the pipes without waiting for the child process to terminate.
  246. */
  247. void closePipeServer() noexcept;
  248. // -------------------------------------------------------------------
  249. // write prepared messages, no lock or flush needed (done internally)
  250. /*!
  251. * Write a single "show" message.
  252. */
  253. void writeShowMessage() const noexcept;
  254. /*!
  255. * Write a single "focus" message.
  256. */
  257. void writeFocusMessage() const noexcept;
  258. /*!
  259. * Write a single "hide" message.
  260. */
  261. void writeHideMessage() const noexcept;
  262. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPipeServer)
  263. };
  264. // -----------------------------------------------------------------------
  265. // CarlaPipeClient class
  266. class CarlaPipeClient : public CarlaPipeCommon
  267. {
  268. public:
  269. /*!
  270. * Constructor.
  271. */
  272. CarlaPipeClient() noexcept;
  273. /*!
  274. * Destructor.
  275. */
  276. ~CarlaPipeClient() /*noexcept*/ override;
  277. /*!
  278. * Initialize the pipes used by a server.
  279. * @a argv must match the arguments set the by server.
  280. */
  281. bool initPipeClient(const char* argv[]) noexcept;
  282. /*!
  283. * Close the pipes.
  284. */
  285. void closePipeClient() noexcept;
  286. // -------------------------------------------------------------------
  287. // write prepared messages, no lock or flush needed (done internally)
  288. /*!
  289. * Write a single "exiting" message and wait for server to respond.
  290. */
  291. void writeExitingMessageAndWait() noexcept;
  292. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPipeClient)
  293. };
  294. // -----------------------------------------------------------------------
  295. #endif // CARLA_PIPE_UTILS_HPP_INCLUDED