|
|
@@ -43,26 +43,7 @@ START_NAMESPACE_DISTRHO |
|
|
|
*/ |
|
|
|
class ExternalWindow |
|
|
|
{ |
|
|
|
struct PrivateData { |
|
|
|
uintptr_t parentWindowHandle; |
|
|
|
uintptr_t transientWinId; |
|
|
|
uint width; |
|
|
|
uint height; |
|
|
|
double scaleFactor; |
|
|
|
String title; |
|
|
|
bool visible; |
|
|
|
pid_t pid; |
|
|
|
|
|
|
|
PrivateData() |
|
|
|
: parentWindowHandle(0), |
|
|
|
transientWinId(0), |
|
|
|
width(1), |
|
|
|
height(1), |
|
|
|
scaleFactor(1.0), |
|
|
|
title(), |
|
|
|
visible(false), |
|
|
|
pid(0) {} |
|
|
|
} pData; |
|
|
|
struct PrivateData; |
|
|
|
|
|
|
|
public: |
|
|
|
/** |
|
|
@@ -82,9 +63,7 @@ public: |
|
|
|
*/ |
|
|
|
virtual ~ExternalWindow() |
|
|
|
{ |
|
|
|
/* |
|
|
|
terminateAndWaitForProcess(); |
|
|
|
*/ |
|
|
|
DISTRHO_SAFE_ASSERT(!pData.visible); |
|
|
|
} |
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------------------------------------- |
|
|
@@ -92,11 +71,17 @@ public: |
|
|
|
|
|
|
|
virtual bool isRunning() const |
|
|
|
{ |
|
|
|
if (ext.inUse) |
|
|
|
return ext.isRunning(); |
|
|
|
|
|
|
|
return isVisible(); |
|
|
|
} |
|
|
|
|
|
|
|
virtual bool isQuiting() const |
|
|
|
{ |
|
|
|
if (ext.inUse) |
|
|
|
return ext.isQuiting; |
|
|
|
|
|
|
|
return !isVisible(); |
|
|
|
} |
|
|
|
|
|
|
@@ -113,6 +98,14 @@ public: |
|
|
|
transientWindowChanged(winId); |
|
|
|
} |
|
|
|
|
|
|
|
void close() |
|
|
|
{ |
|
|
|
hide(); |
|
|
|
|
|
|
|
if (ext.inUse) |
|
|
|
terminateAndWaitForExternalProcess(); |
|
|
|
} |
|
|
|
|
|
|
|
#if DISTRHO_PLUGIN_HAS_EMBED_UI |
|
|
|
/** |
|
|
|
Whether this Window is embed into another (usually not DGL-controlled) Window. |
|
|
@@ -280,6 +273,25 @@ public: |
|
|
|
virtual void focus() {} |
|
|
|
|
|
|
|
protected: |
|
|
|
/* -------------------------------------------------------------------------------------------------------- |
|
|
|
* ExternalWindow special calls for running externals tools */ |
|
|
|
|
|
|
|
bool startExternalProcess(const char* args[]) |
|
|
|
{ |
|
|
|
ext.inUse = true; |
|
|
|
|
|
|
|
return ext.start(args); |
|
|
|
} |
|
|
|
|
|
|
|
void terminateAndWaitForExternalProcess() |
|
|
|
{ |
|
|
|
ext.isQuiting = true; |
|
|
|
ext.terminateAndWait(); |
|
|
|
} |
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------------------------------------- |
|
|
|
* ExternalWindow specific callbacks */ |
|
|
|
|
|
|
|
/** |
|
|
|
A function called when the window is resized. |
|
|
|
*/ |
|
|
@@ -309,101 +321,125 @@ protected: |
|
|
|
return; (void)winId; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
bool isRunning() noexcept |
|
|
|
{ |
|
|
|
if (pid <= 0) |
|
|
|
return false; |
|
|
|
private: |
|
|
|
friend class PluginWindow; |
|
|
|
friend class UI; |
|
|
|
|
|
|
|
const pid_t p = ::waitpid(pid, nullptr, WNOHANG); |
|
|
|
struct ExternalProcess { |
|
|
|
bool inUse; |
|
|
|
bool isQuiting; |
|
|
|
mutable pid_t pid; |
|
|
|
|
|
|
|
if (p == pid || (p == -1 && errno == ECHILD)) |
|
|
|
{ |
|
|
|
printf("NOTICE: Child process exited while idle\n"); |
|
|
|
pid = 0; |
|
|
|
return false; |
|
|
|
} |
|
|
|
ExternalProcess() |
|
|
|
: inUse(false), |
|
|
|
isQuiting(false), |
|
|
|
pid(0) {} |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
bool isRunning() const noexcept |
|
|
|
{ |
|
|
|
if (pid <= 0) |
|
|
|
return false; |
|
|
|
|
|
|
|
*/ |
|
|
|
const pid_t p = ::waitpid(pid, nullptr, WNOHANG); |
|
|
|
|
|
|
|
protected: |
|
|
|
/* |
|
|
|
bool startExternalProcess(const char* args[]) |
|
|
|
{ |
|
|
|
terminateAndWaitForProcess(); |
|
|
|
if (p == pid || (p == -1 && errno == ECHILD)) |
|
|
|
{ |
|
|
|
d_stdout("NOTICE: Child process exited while idle"); |
|
|
|
pid = 0; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
pid = vfork(); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
switch (pid) |
|
|
|
bool start(const char* args[]) |
|
|
|
{ |
|
|
|
case 0: |
|
|
|
execvp(args[0], (char**)args); |
|
|
|
_exit(1); |
|
|
|
return false; |
|
|
|
|
|
|
|
case -1: |
|
|
|
printf("Could not start external ui\n"); |
|
|
|
return false; |
|
|
|
terminateAndWait(); |
|
|
|
|
|
|
|
default: |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
pid = vfork(); |
|
|
|
|
|
|
|
void terminateAndWaitForProcess() |
|
|
|
{ |
|
|
|
if (pid <= 0) |
|
|
|
return; |
|
|
|
switch (pid) |
|
|
|
{ |
|
|
|
case 0: |
|
|
|
execvp(args[0], (char**)args); |
|
|
|
_exit(1); |
|
|
|
return false; |
|
|
|
|
|
|
|
printf("Waiting for previous process to stop,,,\n"); |
|
|
|
case -1: |
|
|
|
d_stderr("Could not start external ui"); |
|
|
|
return false; |
|
|
|
|
|
|
|
bool sendTerm = true; |
|
|
|
default: |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for (pid_t p;;) |
|
|
|
void terminateAndWait() |
|
|
|
{ |
|
|
|
p = ::waitpid(pid, nullptr, WNOHANG); |
|
|
|
if (pid <= 0) |
|
|
|
return; |
|
|
|
|
|
|
|
d_stdout("Waiting for external process to stop,,,"); |
|
|
|
|
|
|
|
bool sendTerm = true; |
|
|
|
|
|
|
|
switch (p) |
|
|
|
for (pid_t p;;) |
|
|
|
{ |
|
|
|
case 0: |
|
|
|
if (sendTerm) |
|
|
|
{ |
|
|
|
sendTerm = false; |
|
|
|
::kill(pid, SIGTERM); |
|
|
|
} |
|
|
|
break; |
|
|
|
p = ::waitpid(pid, nullptr, WNOHANG); |
|
|
|
|
|
|
|
case -1: |
|
|
|
if (errno == ECHILD) |
|
|
|
switch (p) |
|
|
|
{ |
|
|
|
printf("Done! (no such process)\n"); |
|
|
|
pid = 0; |
|
|
|
return; |
|
|
|
case 0: |
|
|
|
if (sendTerm) |
|
|
|
{ |
|
|
|
sendTerm = false; |
|
|
|
::kill(pid, SIGTERM); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case -1: |
|
|
|
if (errno == ECHILD) |
|
|
|
{ |
|
|
|
d_stdout("Done! (no such process)"); |
|
|
|
pid = 0; |
|
|
|
return; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
if (p == pid) |
|
|
|
{ |
|
|
|
d_stdout("Done! (clean wait)"); |
|
|
|
pid = 0; |
|
|
|
return; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
if (p == pid) |
|
|
|
{ |
|
|
|
printf("Done! (clean wait)\n"); |
|
|
|
pid = 0; |
|
|
|
return; |
|
|
|
} |
|
|
|
break; |
|
|
|
// 5 msec |
|
|
|
usleep(5*1000); |
|
|
|
} |
|
|
|
|
|
|
|
// 5 msec |
|
|
|
usleep(5*1000); |
|
|
|
} |
|
|
|
} |
|
|
|
*/ |
|
|
|
} ext; |
|
|
|
|
|
|
|
private: |
|
|
|
friend class PluginWindow; |
|
|
|
friend class UI; |
|
|
|
struct PrivateData { |
|
|
|
uintptr_t parentWindowHandle; |
|
|
|
uintptr_t transientWinId; |
|
|
|
uint width; |
|
|
|
uint height; |
|
|
|
double scaleFactor; |
|
|
|
String title; |
|
|
|
bool visible; |
|
|
|
|
|
|
|
PrivateData() |
|
|
|
: parentWindowHandle(0), |
|
|
|
transientWinId(0), |
|
|
|
width(1), |
|
|
|
height(1), |
|
|
|
scaleFactor(1.0), |
|
|
|
title(), |
|
|
|
visible(false) {} |
|
|
|
} pData; |
|
|
|
|
|
|
|
DISTRHO_DECLARE_NON_COPYABLE(ExternalWindow) |
|
|
|
}; |
|
|
|