DISTRHO Plugin Framework
ExternalWindow.hpp
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 
17 #ifndef DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED
18 #define DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED
19 
20 #include "String.hpp"
21 
22 #ifdef DISTRHO_OS_WINDOWS
23 # error Unsupported platform!
24 #else
25 # include <cerrno>
26 # include <signal.h>
27 # include <sys/wait.h>
28 # include <unistd.h>
29 #endif
30 
31 START_NAMESPACE_DISTRHO
32 
33 // -----------------------------------------------------------------------
34 // ExternalWindow class
35 
37 {
38 public:
39  ExternalWindow(const uint w = 1, const uint h = 1, const char* const t = "")
40  : width(w),
41  height(h),
42  title(t),
43  pid(0) {}
44 
45  virtual ~ExternalWindow()
46  {
47  terminateAndWaitForProcess();
48  }
49 
50  uint getWidth() const noexcept
51  {
52  return width;
53  }
54 
55  uint getHeight() const noexcept
56  {
57  return height;
58  }
59 
60  const char* getTitle() const noexcept
61  {
62  return title;
63  }
64 
65  void setTitle(const char* const t) noexcept
66  {
67  title = t;
68  }
69 
70  bool isRunning() noexcept
71  {
72  if (pid <= 0)
73  return false;
74 
75  const pid_t p = ::waitpid(pid, nullptr, WNOHANG);
76 
77  if (p == pid || (p == -1 && errno == ECHILD))
78  {
79  printf("NOTICE: Child process exited while idle\n");
80  pid = 0;
81  return false;
82  }
83 
84  return true;
85  }
86 
87 protected:
88  bool startExternalProcess(const char* args[])
89  {
90  terminateAndWaitForProcess();
91 
92  pid = vfork();
93 
94  switch (pid)
95  {
96  case 0:
97  execvp(args[0], (char**)args);
98  _exit(1);
99  return false;
100 
101  case -1:
102  printf("Could not start external ui\n");
103  return false;
104 
105  default:
106  return true;
107  }
108  }
109 
110 private:
111  uint width;
112  uint height;
113  String title;
114  pid_t pid;
115 
116  friend class UIExporter;
117 
118  void terminateAndWaitForProcess()
119  {
120  if (pid <= 0)
121  return;
122 
123  printf("Waiting for previous process to stop,,,\n");
124 
125  bool sendTerm = true;
126 
127  for (pid_t p;;)
128  {
129  p = ::waitpid(pid, nullptr, WNOHANG);
130 
131  switch (p)
132  {
133  case 0:
134  if (sendTerm)
135  {
136  sendTerm = false;
137  ::kill(pid, SIGTERM);
138  }
139  break;
140 
141  case -1:
142  if (errno == ECHILD)
143  {
144  printf("Done! (no such process)\n");
145  pid = 0;
146  return;
147  }
148  break;
149 
150  default:
151  if (p == pid)
152  {
153  printf("Done! (clean wait)\n");
154  pid = 0;
155  return;
156  }
157  break;
158  }
159 
160  // 5 msec
161  usleep(5*1000);
162  }
163  }
164 
165  DISTRHO_DECLARE_NON_COPY_CLASS(ExternalWindow)
166 };
167 
168 // -----------------------------------------------------------------------
169 
170 END_NAMESPACE_DISTRHO
171 
172 #endif // DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED
Definition: ExternalWindow.hpp:36
Definition: String.hpp:29