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.

503 lines
12KB

  1. /*
  2. * Carla Pipe utils based on lv2fil UI code
  3. * Copyright (C) 2009 Nedko Arnaudov <nedko@arnaudov.name>
  4. * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of
  9. * the License, or any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  17. */
  18. #ifndef CARLA_PIPE_UTILS_HPP_INCLUDED
  19. #define CARLA_PIPE_UTILS_HPP_INCLUDED
  20. #define WAIT_START_TIMEOUT 3000 /* ms */
  21. #define WAIT_ZOMBIE_TIMEOUT 3000 /* ms */
  22. #define WAIT_STEP 100 /* ms */
  23. #include "CarlaUtils.hpp"
  24. #include "CarlaString.hpp"
  25. #include <cerrno>
  26. #include <clocale>
  27. #include <fcntl.h>
  28. #include <sys/wait.h>
  29. // -----------------------------------------------------------------------
  30. class CarlaPipeServer
  31. {
  32. protected:
  33. CarlaPipeServer()
  34. : fPipeRecv(-1),
  35. fPipeSend(-1),
  36. fPid(-1),
  37. fReading(false)
  38. {
  39. carla_debug("CarlaPipeServer::CarlaPipeServer()");
  40. }
  41. // -------------------------------------------------------------------
  42. public:
  43. virtual ~CarlaPipeServer()
  44. {
  45. carla_debug("CarlaPipeServer::~CarlaPipeServer()");
  46. stop();
  47. }
  48. void start(const char* const filename, const char* const arg1, const char* const arg2)
  49. {
  50. CARLA_SAFE_ASSERT_RETURN(filename != nullptr,);
  51. CARLA_SAFE_ASSERT_RETURN(arg1 != nullptr,);
  52. CARLA_SAFE_ASSERT_RETURN(arg2 != nullptr,);
  53. carla_debug("CarlaPipeServer::start(\"%s\", \"%s\", \"%s\"", filename, arg1, arg2);
  54. //----------------------------------------------------------------
  55. const char* argv[6];
  56. //----------------------------------------------------------------
  57. // argv[0] => filename
  58. argv[0] = filename;
  59. //----------------------------------------------------------------
  60. // argv[1-2] => args
  61. argv[1] = arg1;
  62. argv[2] = arg2;
  63. //----------------------------------------------------------------
  64. // argv[3-4] => pipes
  65. int pipe1[2]; // written by host process, read by plugin UI process
  66. int pipe2[2]; // written by plugin UI process, read by host process
  67. if (pipe(pipe1) != 0)
  68. {
  69. fail("pipe1 creation failed");
  70. return;
  71. }
  72. if (pipe(pipe2) != 0)
  73. {
  74. fail("pipe2 creation failed");
  75. return;
  76. }
  77. char uiPipeRecv[100+1];
  78. char uiPipeSend[100+1];
  79. std::snprintf(uiPipeRecv, 100, "%d", pipe1[0]); /* [0] means reading end */
  80. std::snprintf(uiPipeSend, 100, "%d", pipe2[1]); /* [1] means writting end */
  81. uiPipeRecv[100] = '\0';
  82. uiPipeSend[100] = '\0';
  83. argv[3] = uiPipeRecv; // reading end
  84. argv[4] = uiPipeSend; // writting end
  85. //----------------------------------------------------------------
  86. // argv[5] => NULL
  87. argv[5] = nullptr;
  88. //----------------------------------------------------------------
  89. // fork
  90. int ret = -1;
  91. if ((! fork_exec(argv, &ret)) || ret == -1)
  92. {
  93. close(pipe1[0]);
  94. close(pipe1[1]);
  95. close(pipe2[0]);
  96. close(pipe2[1]);
  97. fail("fork_exec() failed");
  98. return;
  99. }
  100. fPid = ret;
  101. /* fork duplicated the handles, close pipe ends that are used by the child process */
  102. close(pipe1[0]);
  103. close(pipe2[1]);
  104. fPipeSend = pipe1[1]; /* [1] means writting end */
  105. fPipeRecv = pipe2[0]; /* [0] means reading end */
  106. fcntl(fPipeRecv, F_SETFL, fcntl(fPipeRecv, F_GETFL) | O_NONBLOCK);
  107. //----------------------------------------------------------------
  108. // wait a while for child process to confirm it is alive
  109. char ch;
  110. for (int i=0; ;)
  111. {
  112. ret = read(fPipeRecv, &ch, 1);
  113. switch (ret)
  114. {
  115. case -1:
  116. if (errno == EAGAIN)
  117. {
  118. if (i < WAIT_START_TIMEOUT / WAIT_STEP)
  119. {
  120. carla_msleep(WAIT_STEP);
  121. i++;
  122. continue;
  123. }
  124. carla_stderr("we have waited for child with pid %d to appear for %.1f seconds and we are giving up", (int)fPid, (float)WAIT_START_TIMEOUT / 1000.0f);
  125. }
  126. else
  127. carla_stderr("read() failed: %s", strerror(errno));
  128. break;
  129. case 1:
  130. if (ch == '\n')
  131. // success
  132. return;
  133. carla_stderr("read() wrong first char '%c'", ch);
  134. break;
  135. default:
  136. carla_stderr("read() returned %d", ret);
  137. break;
  138. }
  139. break;
  140. }
  141. carla_stderr("force killing misbehaved child %d (start)", (int)fPid);
  142. if (kill(fPid, SIGKILL) == -1)
  143. {
  144. carla_stderr("kill() failed: %s (start)\n", strerror(errno));
  145. }
  146. /* wait a while child to exit, we dont like zombie processes */
  147. wait_child(fPid);
  148. }
  149. void stop()
  150. {
  151. carla_debug("CarlaPipeServer::stop()");
  152. if (fPipeSend == -1 || fPipeRecv == -1 || fPid == -1)
  153. return;
  154. write(fPipeSend, "quit\n", 5);
  155. waitChildClose();
  156. close(fPipeRecv);
  157. close(fPipeSend);
  158. fPipeRecv = -1;
  159. fPipeSend = -1;
  160. fPid = -1;
  161. }
  162. void idle()
  163. {
  164. char* locale = nullptr;
  165. for (;;)
  166. {
  167. char* const msg = readline();
  168. if (msg == nullptr)
  169. break;
  170. if (locale == nullptr)
  171. {
  172. locale = strdup(setlocale(LC_NUMERIC, nullptr));
  173. setlocale(LC_NUMERIC, "POSIX");
  174. }
  175. fReading = true;
  176. msgReceived(msg);
  177. fReading = false;
  178. std::free(msg);
  179. }
  180. if (locale != nullptr)
  181. {
  182. setlocale(LC_NUMERIC, locale);
  183. std::free(locale);
  184. }
  185. }
  186. // -------------------------------------------------------------------
  187. bool readNextLineAsBool(bool& value)
  188. {
  189. if (! fReading)
  190. return false;
  191. if (char* const msg = readline())
  192. {
  193. value = (std::strcmp(msg, "true") == 0);
  194. std::free(msg);
  195. return true;
  196. }
  197. return false;
  198. }
  199. bool readNextLineAsInt(int& value)
  200. {
  201. if (! fReading)
  202. return false;
  203. if (char* const msg = readline())
  204. {
  205. value = atoi(msg);
  206. std::free(msg);
  207. return true;
  208. }
  209. return false;
  210. }
  211. bool readNextLineAsFloat(float& value)
  212. {
  213. if (! fReading)
  214. return false;
  215. if (char* const msg = readline())
  216. {
  217. bool ret = (sscanf(msg, "%f", &value) == 1);
  218. std::free(msg);
  219. return ret;
  220. }
  221. return false;
  222. }
  223. bool readNextLineAsString(char*& value)
  224. {
  225. if (! fReading)
  226. return false;
  227. if (char* const msg = readline())
  228. {
  229. value = msg;
  230. return true;
  231. }
  232. return false;
  233. }
  234. void writeMsg(const char* const msg)
  235. {
  236. ::write(fPipeSend, msg, std::strlen(msg));
  237. }
  238. void writeMsg(const char* const msg, size_t size)
  239. {
  240. ::write(fPipeSend, msg, size);
  241. }
  242. void writeAndFixMsg(const char* const msg)
  243. {
  244. const size_t size = std::strlen(msg);
  245. char smsg[size+1];
  246. std::strcpy(smsg, msg);
  247. smsg[size-1] = '\n';
  248. smsg[size] = '\0';
  249. for (size_t i=0; i<size; ++i)
  250. {
  251. if (smsg[i] == '\n')
  252. smsg[i] = '\r';
  253. }
  254. ::write(fPipeSend, smsg, size+1);
  255. }
  256. void waitChildClose()
  257. {
  258. if (! wait_child(fPid))
  259. {
  260. carla_stderr2("force killing misbehaved child %d (exit)", (int)fPid);
  261. if (kill(fPid, SIGKILL) == -1)
  262. carla_stderr2("kill() failed: %s (exit)", strerror(errno));
  263. else
  264. wait_child(fPid);
  265. }
  266. }
  267. // -------------------------------------------------------------------
  268. protected:
  269. virtual void fail(const char* const error)
  270. {
  271. carla_stderr2(error);
  272. }
  273. virtual void msgReceived(const char* const msg) = 0;
  274. // -------------------------------------------------------------------
  275. private:
  276. int fPipeRecv; // the pipe end that is used for receiving messages from UI
  277. int fPipeSend; // the pipe end that is used for sending messages to UI
  278. pid_t fPid;
  279. bool fReading;
  280. CarlaString fTempBuf;
  281. // -------------------------------------------------------------------
  282. char* readline()
  283. {
  284. char ch;
  285. ssize_t ret;
  286. char buf[0xff+1];
  287. char* ptr = buf;
  288. fTempBuf.clear();
  289. buf[0xff] = '\0';
  290. for (int i=0;; ++i)
  291. {
  292. ret = read(fPipeRecv, &ch, 1);
  293. if (ret == 1 && ch != '\n')
  294. {
  295. if (ch == '\r')
  296. ch = '\n';
  297. *ptr++ = ch;
  298. if (i+1 == 0xff)
  299. {
  300. i = 0;
  301. ptr = buf;
  302. fTempBuf += buf;
  303. }
  304. continue;
  305. }
  306. if (fTempBuf.isNotEmpty() || ptr != buf)
  307. {
  308. if (ptr != buf)
  309. {
  310. *ptr = '\0';
  311. fTempBuf += buf;
  312. }
  313. return strdup((const char*)fTempBuf);
  314. }
  315. break;
  316. }
  317. return nullptr;
  318. }
  319. static bool fork_exec(const char* const argv[6], int* const retp)
  320. {
  321. pid_t ret = *retp = vfork();
  322. switch (ret)
  323. {
  324. case 0: /* child process */
  325. execvp(argv[0], (char* const*)argv);
  326. carla_stderr2("exec of UI failed: %s", strerror(errno));
  327. return false;
  328. case -1:
  329. carla_stderr2("fork() failed to create new process for plugin UI");
  330. return false;
  331. }
  332. return true;
  333. }
  334. static bool wait_child(const pid_t pid)
  335. {
  336. pid_t ret;
  337. int i;
  338. if (pid == -1)
  339. {
  340. carla_stderr2("Can't wait for pid -1");
  341. return false;
  342. }
  343. for (i = 0; i < WAIT_ZOMBIE_TIMEOUT / WAIT_STEP; ++i)
  344. {
  345. ret = waitpid(pid, NULL, WNOHANG);
  346. if (ret != 0)
  347. {
  348. if (ret == pid)
  349. return true;
  350. if (ret == -1)
  351. {
  352. carla_stderr2("waitpid(%d) failed: %s", (int)pid, strerror(errno));
  353. return false;
  354. }
  355. carla_stderr2("we have waited for child pid %d to exit but we got pid %d instead", (int)pid, (int)ret);
  356. return false;
  357. }
  358. carla_msleep(WAIT_STEP); /* wait 100 ms */
  359. }
  360. carla_stderr2("we have waited for child with pid %d to exit for %.1f seconds and we are giving up", (int)pid, (float)WAIT_START_TIMEOUT / 1000.0f);
  361. return false;
  362. }
  363. };
  364. // -----------------------------------------------------------------------
  365. class CarlaPipeClient
  366. {
  367. protected:
  368. CarlaPipeClient()
  369. {
  370. carla_debug("CarlaPipeClient::CarlaPipeClient()");
  371. }
  372. // -------------------------------------------------------------------
  373. public:
  374. virtual ~CarlaPipeClient()
  375. {
  376. carla_debug("CarlaPipeClient::~CarlaPipeClient()");
  377. stop();
  378. }
  379. void stop()
  380. {
  381. }
  382. };
  383. // -----------------------------------------------------------------------
  384. #endif // CARLA_PIPE_UTILS_HPP_INCLUDED