DISTRHO Plugin Framework
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.

203 lines
4.4KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED
  17. #define DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED
  18. #include "String.hpp"
  19. #ifdef DISTRHO_OS_WINDOWS
  20. # error Unsupported platform!
  21. #else
  22. # include <cerrno>
  23. # include <signal.h>
  24. # include <sys/wait.h>
  25. # include <unistd.h>
  26. #endif
  27. START_NAMESPACE_DISTRHO
  28. // -----------------------------------------------------------------------
  29. // ExternalWindow class
  30. class ExternalWindow
  31. {
  32. public:
  33. ExternalWindow(const uint w = 1, const uint h = 1, const char* const t = "")
  34. : width(w),
  35. height(h),
  36. title(t),
  37. transientWinId(0),
  38. visible(false),
  39. pid(0) {}
  40. virtual ~ExternalWindow()
  41. {
  42. terminateAndWaitForProcess();
  43. }
  44. uint getWidth() const noexcept
  45. {
  46. return width;
  47. }
  48. uint getHeight() const noexcept
  49. {
  50. return height;
  51. }
  52. const char* getTitle() const noexcept
  53. {
  54. return title;
  55. }
  56. uintptr_t getTransientWinId() const noexcept
  57. {
  58. return transientWinId;
  59. }
  60. bool isVisible() const noexcept
  61. {
  62. return visible;
  63. }
  64. bool isRunning() noexcept
  65. {
  66. if (pid <= 0)
  67. return false;
  68. const pid_t p = ::waitpid(pid, nullptr, WNOHANG);
  69. if (p == pid || (p == -1 && errno == ECHILD))
  70. {
  71. printf("NOTICE: Child process exited while idle\n");
  72. pid = 0;
  73. return false;
  74. }
  75. return true;
  76. }
  77. virtual void setSize(uint w, uint h)
  78. {
  79. width = w;
  80. height = h;
  81. }
  82. virtual void setTitle(const char* const t)
  83. {
  84. title = t;
  85. }
  86. virtual void setTransientWinId(const uintptr_t winId)
  87. {
  88. transientWinId = winId;
  89. }
  90. virtual void setVisible(const bool yesNo)
  91. {
  92. visible = yesNo;
  93. }
  94. protected:
  95. bool startExternalProcess(const char* args[])
  96. {
  97. terminateAndWaitForProcess();
  98. pid = vfork();
  99. switch (pid)
  100. {
  101. case 0:
  102. execvp(args[0], (char**)args);
  103. _exit(1);
  104. return false;
  105. case -1:
  106. printf("Could not start external ui\n");
  107. return false;
  108. default:
  109. return true;
  110. }
  111. }
  112. void terminateAndWaitForProcess()
  113. {
  114. if (pid <= 0)
  115. return;
  116. printf("Waiting for previous process to stop,,,\n");
  117. bool sendTerm = true;
  118. for (pid_t p;;)
  119. {
  120. p = ::waitpid(pid, nullptr, WNOHANG);
  121. switch (p)
  122. {
  123. case 0:
  124. if (sendTerm)
  125. {
  126. sendTerm = false;
  127. ::kill(pid, SIGTERM);
  128. }
  129. break;
  130. case -1:
  131. if (errno == ECHILD)
  132. {
  133. printf("Done! (no such process)\n");
  134. pid = 0;
  135. return;
  136. }
  137. break;
  138. default:
  139. if (p == pid)
  140. {
  141. printf("Done! (clean wait)\n");
  142. pid = 0;
  143. return;
  144. }
  145. break;
  146. }
  147. // 5 msec
  148. usleep(5*1000);
  149. }
  150. }
  151. private:
  152. uint width;
  153. uint height;
  154. String title;
  155. uintptr_t transientWinId;
  156. bool visible;
  157. pid_t pid;
  158. friend class UIExporter;
  159. DISTRHO_DECLARE_NON_COPY_CLASS(ExternalWindow)
  160. };
  161. // -----------------------------------------------------------------------
  162. END_NAMESPACE_DISTRHO
  163. #endif // DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED