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.

340 lines
9.0KB

  1. /*
  2. * Carla Pipe utils
  3. * Copyright (C) 2013-2014 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. #include "lv2/atom.h"
  22. // -----------------------------------------------------------------------
  23. // CarlaPipeCommon class
  24. class CarlaPipeCommon
  25. {
  26. protected:
  27. /*!
  28. * Constructor.
  29. */
  30. CarlaPipeCommon() noexcept;
  31. /*!
  32. * Destructor.
  33. */
  34. virtual ~CarlaPipeCommon() /*noexcept*/;
  35. /*!
  36. * A message has been received (in the context of idlePipe()).
  37. * If extra data is required, use any of the readNextLineAs* functions.
  38. * Returning true means the message has been handled and should not propagate to subclasses.
  39. */
  40. virtual bool msgReceived(const char* const msg) noexcept = 0;
  41. /*!
  42. * An error has occurred during the current requested operation.
  43. * Reimplementing this method allows to catch these errors as strings.
  44. * By default the error is simply printed to stderr.
  45. */
  46. virtual void fail(const char* const error) noexcept
  47. {
  48. carla_stderr2(error);
  49. }
  50. public:
  51. /*!
  52. * Check if the pipe is running.
  53. */
  54. bool isPipeRunning() const noexcept;
  55. /*!
  56. * Check the pipe for new messages and send them to msgReceived().
  57. */
  58. void idlePipe(const bool onlyOnce = false) noexcept;
  59. // -------------------------------------------------------------------
  60. // write lock
  61. /*!
  62. * Lock the pipe write mutex.
  63. */
  64. void lockPipe() const noexcept;
  65. /*!
  66. * Try locking the pipe write mutex.
  67. * Returns true if successful.
  68. */
  69. bool tryLockPipe() const noexcept;
  70. /*!
  71. * Unlock the pipe write mutex.
  72. */
  73. void unlockPipe() const noexcept;
  74. /*!
  75. * Get the pipe write lock.
  76. */
  77. CarlaMutex& getPipeLock() const noexcept;
  78. // -------------------------------------------------------------------
  79. // read lines, must only be called in the context of msgReceived()
  80. /*!
  81. * Read the next line as a boolean.
  82. */
  83. bool readNextLineAsBool(bool& value) const noexcept;
  84. /*!
  85. * Read the next line as a byte.
  86. */
  87. bool readNextLineAsByte(uint8_t& value) const noexcept;
  88. /*!
  89. * Read the next line as an integer.
  90. */
  91. bool readNextLineAsInt(int32_t& value) const noexcept;
  92. /*!
  93. * Read the next line as an unsigned integer.
  94. */
  95. bool readNextLineAsUInt(uint32_t& value) const noexcept;
  96. /*!
  97. * Read the next line as a long integer.
  98. */
  99. bool readNextLineAsLong(int64_t& value) const noexcept;
  100. /*!
  101. * Read the next line as a long unsigned integer.
  102. */
  103. bool readNextLineAsULong(uint64_t& value) const noexcept;
  104. /*!
  105. * Read the next line as a floating point number (single precision).
  106. */
  107. bool readNextLineAsFloat(float& value) const noexcept;
  108. /*!
  109. * Read the next line as a floating point number (double precision).
  110. */
  111. bool readNextLineAsDouble(double& value) const noexcept;
  112. /*!
  113. * Read the next line as a string.
  114. * @note: @a value must be deleted if valid.
  115. */
  116. bool readNextLineAsString(const char*& value) const noexcept;
  117. // -------------------------------------------------------------------
  118. // write messages, must be locked before calling
  119. /*!
  120. * Write a valid message with unknown size.
  121. * A valid message has only one '\n' character and it's at the end.
  122. */
  123. bool writeMessage(const char* const msg) const noexcept;
  124. /*!
  125. * Write a valid message with known size.
  126. * A valid message has only one '\n' character and it's at the end.
  127. */
  128. bool writeMessage(const char* const msg, std::size_t size) const noexcept;
  129. /*!
  130. * Write and fix a message.
  131. */
  132. bool writeAndFixMessage(const char* const msg) const noexcept;
  133. /*!
  134. * Flush all messages currently in cache.
  135. */
  136. bool flushMessages() const noexcept;
  137. // -------------------------------------------------------------------
  138. // write prepared messages, no lock or flush needed (done internally)
  139. /*!
  140. * Write an "error" message.
  141. */
  142. void writeErrorMessage(const char* const error) const noexcept;
  143. /*!
  144. * Write a "control" message used for parameter changes.
  145. */
  146. void writeControlMessage(const uint32_t index, const float value) const noexcept;
  147. /*!
  148. * Write a "configure" message used for state changes.
  149. */
  150. void writeConfigureMessage(const char* const key, const char* const value) const noexcept;
  151. /*!
  152. * Write a "program" message (using index).
  153. */
  154. void writeProgramMessage(const uint32_t index) const noexcept;
  155. /*!
  156. * Write a "midiprogram" message (using bank and program).
  157. */
  158. void writeMidiProgramMessage(const uint32_t bank, const uint32_t program) const noexcept;
  159. /*!
  160. * Write a MIDI "note" message.
  161. */
  162. void writeMidiNoteMessage(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) const noexcept;
  163. /*!
  164. * Write an lv2 "atom" message.
  165. */
  166. void writeLv2AtomMessage(const uint32_t index, const LV2_Atom* const atom) const noexcept;
  167. /*!
  168. * Write an lv2 "urid" message.
  169. */
  170. void writeLv2UridMessage(const uint32_t urid, const char* const uri) const noexcept;
  171. // -------------------------------------------------------------------
  172. protected:
  173. struct PrivateData;
  174. PrivateData* const pData;
  175. // -------------------------------------------------------------------
  176. /*! @internal */
  177. const char* _readline() const noexcept;
  178. /*! @internal */
  179. const char* _readlineblock(const uint32_t timeOutMilliseconds = 50) const noexcept;
  180. /*! @internal */
  181. bool _writeMsgBuffer(const char* const msg, const std::size_t size) const noexcept;
  182. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPipeCommon)
  183. };
  184. // -----------------------------------------------------------------------
  185. // CarlaPipeServer class
  186. class CarlaPipeServer : public CarlaPipeCommon
  187. {
  188. public:
  189. /*!
  190. * Constructor.
  191. */
  192. CarlaPipeServer() noexcept;
  193. /*!
  194. * Destructor.
  195. */
  196. ~CarlaPipeServer() /*noexcept*/ override;
  197. /*!
  198. * Get the process ID of this pipe's matching client.
  199. * Will return 0 if client is not running.
  200. * @note: Unsupported on Windows
  201. */
  202. uintptr_t getPID() const noexcept;
  203. /*!
  204. * Start the pipe server using @a filename with 2 arguments.
  205. * @see fail()
  206. */
  207. bool startPipeServer(const char* const filename, const char* const arg1, const char* const arg2) noexcept;
  208. /*!
  209. * Stop the pipe server.
  210. * This will send a quit message to the client, wait for it to close for @a timeOutMilliseconds, and close the pipes.
  211. */
  212. void stopPipeServer(const uint32_t timeOutMilliseconds) noexcept;
  213. /*!
  214. * Close the pipes without waiting for the child process to terminate.
  215. */
  216. void closePipeServer() noexcept;
  217. // -------------------------------------------------------------------
  218. // write prepared messages, no lock or flush needed (done internally)
  219. /*!
  220. * Write a single "show" message.
  221. */
  222. void writeShowMessage() const noexcept;
  223. /*!
  224. * Write a single "focus" message.
  225. */
  226. void writeFocusMessage() const noexcept;
  227. /*!
  228. * Write a single "hide" message.
  229. */
  230. void writeHideMessage() const noexcept;
  231. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPipeServer)
  232. };
  233. // -----------------------------------------------------------------------
  234. // CarlaPipeClient class
  235. class CarlaPipeClient : public CarlaPipeCommon
  236. {
  237. public:
  238. /*!
  239. * Constructor.
  240. */
  241. CarlaPipeClient() noexcept;
  242. /*!
  243. * Destructor.
  244. */
  245. ~CarlaPipeClient() /*noexcept*/ override;
  246. /*!
  247. * Initialize the pipes used by a server.
  248. * @a argv must match the arguments set the by server.
  249. */
  250. bool initPipeClient(const char* argv[]) noexcept;
  251. /*!
  252. * Close the pipes.
  253. */
  254. void closePipeClient() noexcept;
  255. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPipeClient)
  256. };
  257. // -----------------------------------------------------------------------
  258. // ScopedLocale class
  259. class ScopedLocale {
  260. public:
  261. ScopedLocale() noexcept;
  262. ~ScopedLocale() noexcept;
  263. private:
  264. const char* const fLocale;
  265. CARLA_DECLARE_NON_COPY_CLASS(ScopedLocale)
  266. CARLA_PREVENT_HEAP_ALLOCATION
  267. };
  268. // -----------------------------------------------------------------------
  269. #endif // CARLA_PIPE_UTILS_HPP_INCLUDED