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 36 class ExternalWindow 37 { 38 public: ExternalWindow(const uint w=1,const uint h=1,const char * const t="")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 ~ExternalWindow()47 virtual ~ExternalWindow() 48 { 49 terminateAndWaitForProcess(); 50 } 51 getWidth() const52 uint getWidth() const noexcept 53 { 54 return width; 55 } 56 getHeight() const57 uint getHeight() const noexcept 58 { 59 return height; 60 } 61 getTitle() const62 const char* getTitle() const noexcept 63 { 64 return title; 65 } 66 getTransientWinId() const67 uintptr_t getTransientWinId() const noexcept 68 { 69 return transientWinId; 70 } 71 isVisible() const72 bool isVisible() const noexcept 73 { 74 return visible; 75 } 76 isRunning()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 setSize(uint w,uint h)94 virtual void setSize(uint w, uint h) 95 { 96 width = w; 97 height = h; 98 } 99 setTitle(const char * const t)100 virtual void setTitle(const char* const t) 101 { 102 title = t; 103 } 104 setTransientWinId(const uintptr_t winId)105 virtual void setTransientWinId(const uintptr_t winId) 106 { 107 transientWinId = winId; 108 } 109 setVisible(const bool yesNo)110 virtual void setVisible(const bool yesNo) 111 { 112 visible = yesNo; 113 } 114 115 protected: startExternalProcess(const char * args[])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 terminateAndWaitForProcess()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_COPY_CLASS(ExternalWindow) 196 }; 197 198 // ----------------------------------------------------------------------- 199 200 END_NAMESPACE_DISTRHO 201 202 #endif // DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED 203