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.

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