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  transientWinId(0),
44  visible(false),
45  pid(0) {}
46 
47  virtual ~ExternalWindow()
48  {
49  terminateAndWaitForProcess();
50  }
51 
52  uint getWidth() const noexcept
53  {
54  return width;
55  }
56 
57  uint getHeight() const noexcept
58  {
59  return height;
60  }
61 
62  const char* getTitle() const noexcept
63  {
64  return title;
65  }
66 
67  uintptr_t getTransientWinId() const noexcept
68  {
69  return transientWinId;
70  }
71 
72  bool isVisible() const noexcept
73  {
74  return visible;
75  }
76 
77  bool isRunning() noexcept
78  {
79  if (pid <= 0)
80  return false;
81 
82  const pid_t p = ::waitpid(pid, nullptr, WNOHANG);
83 
84  if (p == pid || (p == -1 && errno == ECHILD))
85  {
86  printf("NOTICE: Child process exited while idle\n");
87  pid = 0;
88  return false;
89  }
90 
91  return true;
92  }
93 
94  virtual void setSize(uint w, uint h)
95  {
96  width = w;
97  height = h;
98  }
99 
100  virtual void setTitle(const char* const t)
101  {
102  title = t;
103  }
104 
105  virtual void setTransientWinId(const uintptr_t winId)
106  {
107  transientWinId = winId;
108  }
109 
110  virtual void setVisible(const bool yesNo)
111  {
112  visible = yesNo;
113  }
114 
115 protected:
116  bool startExternalProcess(const char* args[])
117  {
118  terminateAndWaitForProcess();
119 
120  pid = vfork();
121 
122  switch (pid)
123  {
124  case 0:
125  execvp(args[0], (char**)args);
126  _exit(1);
127  return false;
128 
129  case -1:
130  printf("Could not start external ui\n");
131  return false;
132 
133  default:
134  return true;
135  }
136  }
137 
138  void terminateAndWaitForProcess()
139  {
140  if (pid <= 0)
141  return;
142 
143  printf("Waiting for previous process to stop,,,\n");
144 
145  bool sendTerm = true;
146 
147  for (pid_t p;;)
148  {
149  p = ::waitpid(pid, nullptr, WNOHANG);
150 
151  switch (p)
152  {
153  case 0:
154  if (sendTerm)
155  {
156  sendTerm = false;
157  ::kill(pid, SIGTERM);
158  }
159  break;
160 
161  case -1:
162  if (errno == ECHILD)
163  {
164  printf("Done! (no such process)\n");
165  pid = 0;
166  return;
167  }
168  break;
169 
170  default:
171  if (p == pid)
172  {
173  printf("Done! (clean wait)\n");
174  pid = 0;
175  return;
176  }
177  break;
178  }
179 
180  // 5 msec
181  usleep(5*1000);
182  }
183  }
184 
185 private:
186  uint width;
187  uint height;
188  String title;
189  uintptr_t transientWinId;
190  bool visible;
191  pid_t pid;
192 
193  friend class UIExporter;
194 
195  DISTRHO_DECLARE_NON_COPYABLE(ExternalWindow)
196 };
197 
198 // -----------------------------------------------------------------------
199 
200 END_NAMESPACE_DISTRHO
201 
202 #endif // DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED
String
Definition: String.hpp:30
ExternalWindow
Definition: ExternalWindow.hpp:36