commit c96969c56ef19b3efe7d8b12d3707294e36e4d39
parent d87042df0d7ad86eb726cc7b9b418af44acc1e40
Author: falkTX <falktx@gmail.com>
Date: Sun, 14 Feb 2016 21:00:36 +0100
ExternalWindow: Add code for managing external process
Diffstat:
1 file changed, 101 insertions(+), 5 deletions(-)
diff --git a/distrho/extra/ExternalWindow.hpp b/distrho/extra/ExternalWindow.hpp
@@ -19,6 +19,14 @@
#include "../DistrhoUtils.hpp"
+#ifdef DISTRHO_OS_UNIX
+# include <cerrno>
+# include <sys/wait.h>
+# include <unistd.h>
+#else
+# error Unsupported platform!
+#endif
+
START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------
@@ -29,7 +37,13 @@ class ExternalWindow
public:
ExternalWindow(const uint w = 1, const uint h = 1)
: width(w),
- height(h) {}
+ height(h),
+ pid(0) {}
+
+ ~ExternalWindow()
+ {
+ terminateAndWaitForProcess();
+ }
uint getWidth() const noexcept
{
@@ -41,17 +55,99 @@ public:
return height;
}
- void setSize(const uint w, const uint h) noexcept
+ bool isRunning() noexcept
+ {
+ if (pid <= 0)
+ return false;
+
+ const pid_t p = ::waitpid(pid, nullptr, WNOHANG);
+
+ if (p == pid || (p == -1 && errno == ECHILD))
+ {
+ printf("NOTICE: Child process exited while idle\n");
+ pid = 0;
+ return false;
+ }
+
+ return true;
+ }
+
+protected:
+ bool startExternalProcess(const char* args[])
{
- DISTRHO_SAFE_ASSERT_RETURN(w > 0 && h > 0,)
+ terminateAndWaitForProcess();
+
+ pid = vfork();
+
+ switch (pid)
+ {
+ case 0:
+ execvp(args[0], (char**)args);
+ _exit(1);
+ return false;
- width = w;
- height = h;
+ case -1:
+ printf("Could not start external ui\n");
+ return false;
+
+ default:
+ return true;
+ }
}
private:
uint width;
uint height;
+ pid_t pid;
+
+ friend class UIExporter;
+
+ void terminateAndWaitForProcess()
+ {
+ if (pid <= 0)
+ return;
+
+ printf("Waiting for previous process to stop,,,\n");
+
+ bool sendTerm = true;
+
+ for (pid_t p;;)
+ {
+ p = ::waitpid(pid, nullptr, WNOHANG);
+
+ switch (p)
+ {
+ case 0:
+ if (sendTerm)
+ {
+ sendTerm = false;
+ ::kill(pid, SIGTERM);
+ }
+ break;
+
+ case -1:
+ if (errno == ECHILD)
+ {
+ printf("Done! (no such process)\n");
+ pid = 0;
+ return;
+ }
+ break;
+
+ default:
+ if (p == pid)
+ {
+ printf("Done! (clean wait)\n");
+ pid = 0;
+ return;
+ }
+ break;
+ }
+
+ // 5 msec
+ usleep(5*1000);
+ }
+ }
DISTRHO_DECLARE_NON_COPY_CLASS(ExternalWindow)
};