@@ -97,7 +97,7 @@ public: | |||||
testResultsBox.setMultiLine (true); | testResultsBox.setMultiLine (true); | ||||
testResultsBox.setFont ({ Font::getDefaultMonospacedFontName(), 12.0f, Font::plain }); | testResultsBox.setFont ({ Font::getDefaultMonospacedFontName(), 12.0f, Font::plain }); | ||||
logMessage (String ("This demo uses the ChildProcessMaster and ChildProcessSlave classes to launch and communicate " | |||||
logMessage (String ("This demo uses the ChildProcessCoordinator and ChildProcessWorker classes to launch and communicate " | |||||
"with a child process, sending messages in the form of serialised ValueTree objects.") + newLine); | "with a child process, sending messages in the form of serialised ValueTree objects.") + newLine); | ||||
setSize (500, 500); | setSize (500, 500); | ||||
@@ -105,7 +105,7 @@ public: | |||||
~ChildProcessDemo() override | ~ChildProcessDemo() override | ||||
{ | { | ||||
masterProcess.reset(); | |||||
coordinatorProcess.reset(); | |||||
} | } | ||||
void paint (Graphics& g) override | void paint (Graphics& g) override | ||||
@@ -134,11 +134,11 @@ public: | |||||
// invoked by the 'launch' button. | // invoked by the 'launch' button. | ||||
void launchChildProcess() | void launchChildProcess() | ||||
{ | { | ||||
if (masterProcess.get() == nullptr) | |||||
if (coordinatorProcess.get() == nullptr) | |||||
{ | { | ||||
masterProcess.reset (new DemoMasterProcess (*this)); | |||||
coordinatorProcess.reset (new DemoCoordinatorProcess (*this)); | |||||
if (masterProcess->launchSlaveProcess (File::getSpecialLocation (File::currentExecutableFile), demoCommandLineUID)) | |||||
if (coordinatorProcess->launchWorkerProcess (File::getSpecialLocation (File::currentExecutableFile), demoCommandLineUID)) | |||||
logMessage ("Child process started"); | logMessage ("Child process started"); | ||||
} | } | ||||
} | } | ||||
@@ -146,8 +146,8 @@ public: | |||||
// invoked by the 'ping' button. | // invoked by the 'ping' button. | ||||
void pingChildProcess() | void pingChildProcess() | ||||
{ | { | ||||
if (masterProcess.get() != nullptr) | |||||
masterProcess->sendPingMessageToSlave(); | |||||
if (coordinatorProcess.get() != nullptr) | |||||
coordinatorProcess->sendPingMessageToWorker(); | |||||
else | else | ||||
logMessage ("Child process is not running!"); | logMessage ("Child process is not running!"); | ||||
} | } | ||||
@@ -155,45 +155,45 @@ public: | |||||
// invoked by the 'kill' button. | // invoked by the 'kill' button. | ||||
void killChildProcess() | void killChildProcess() | ||||
{ | { | ||||
if (masterProcess.get() != nullptr) | |||||
if (coordinatorProcess.get() != nullptr) | |||||
{ | { | ||||
masterProcess.reset(); | |||||
coordinatorProcess.reset(); | |||||
logMessage ("Child process killed"); | logMessage ("Child process killed"); | ||||
} | } | ||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
// This class is used by the main process, acting as the master and receiving messages | |||||
// from the slave process. | |||||
class DemoMasterProcess : public ChildProcessMaster, | |||||
private DeletedAtShutdown | |||||
// This class is used by the main process, acting as the coordinator and receiving messages | |||||
// from the worker process. | |||||
class DemoCoordinatorProcess : public ChildProcessCoordinator, | |||||
private DeletedAtShutdown | |||||
{ | { | ||||
public: | public: | ||||
DemoMasterProcess (ChildProcessDemo& d) : demo (d) {} | |||||
DemoCoordinatorProcess (ChildProcessDemo& d) : demo (d) {} | |||||
// This gets called when a message arrives from the slave process.. | |||||
void handleMessageFromSlave (const MemoryBlock& mb) override | |||||
// This gets called when a message arrives from the worker process.. | |||||
void handleMessageFromWorker (const MemoryBlock& mb) override | |||||
{ | { | ||||
auto incomingMessage = memoryBlockToValueTree (mb); | auto incomingMessage = memoryBlockToValueTree (mb); | ||||
demo.logMessage ("Received: " + valueTreeToString (incomingMessage)); | demo.logMessage ("Received: " + valueTreeToString (incomingMessage)); | ||||
} | } | ||||
// This gets called if the slave process dies. | |||||
// This gets called if the worker process dies. | |||||
void handleConnectionLost() override | void handleConnectionLost() override | ||||
{ | { | ||||
demo.logMessage ("Connection lost to child process!"); | demo.logMessage ("Connection lost to child process!"); | ||||
demo.killChildProcess(); | demo.killChildProcess(); | ||||
} | } | ||||
void sendPingMessageToSlave() | |||||
void sendPingMessageToWorker() | |||||
{ | { | ||||
ValueTree message ("MESSAGE"); | ValueTree message ("MESSAGE"); | ||||
message.setProperty ("count", count++, nullptr); | message.setProperty ("count", count++, nullptr); | ||||
demo.logMessage ("Sending: " + valueTreeToString (message)); | demo.logMessage ("Sending: " + valueTreeToString (message)); | ||||
sendMessageToSlave (valueTreeToMemoryBlock (message)); | |||||
sendMessageToWorker (valueTreeToMemoryBlock (message)); | |||||
} | } | ||||
ChildProcessDemo& demo; | ChildProcessDemo& demo; | ||||
@@ -201,7 +201,7 @@ public: | |||||
}; | }; | ||||
//============================================================================== | //============================================================================== | ||||
std::unique_ptr<DemoMasterProcess> masterProcess; | |||||
std::unique_ptr<DemoCoordinatorProcess> coordinatorProcess; | |||||
private: | private: | ||||
TextButton launchButton { "Launch Child Process" }; | TextButton launchButton { "Launch Child Process" }; | ||||
@@ -234,15 +234,15 @@ private: | |||||
//============================================================================== | //============================================================================== | ||||
/* This class gets instantiated in the child process, and receives messages from | /* This class gets instantiated in the child process, and receives messages from | ||||
the master process. | |||||
the coordinator process. | |||||
*/ | */ | ||||
class DemoSlaveProcess : public ChildProcessSlave, | |||||
private DeletedAtShutdown | |||||
class DemoWorkerProcess : public ChildProcessWorker, | |||||
private DeletedAtShutdown | |||||
{ | { | ||||
public: | public: | ||||
DemoSlaveProcess() {} | |||||
DemoWorkerProcess() = default; | |||||
void handleMessageFromMaster (const MemoryBlock& mb) override | |||||
void handleMessageFromCoordinator (const MemoryBlock& mb) override | |||||
{ | { | ||||
ValueTree incomingMessage (memoryBlockToValueTree (mb)); | ValueTree incomingMessage (memoryBlockToValueTree (mb)); | ||||
@@ -256,7 +256,7 @@ public: | |||||
ValueTree reply ("REPLY"); | ValueTree reply ("REPLY"); | ||||
reply.setProperty ("countPlusOne", static_cast<int> (incomingMessage["count"]) + 1, nullptr); | reply.setProperty ("countPlusOne", static_cast<int> (incomingMessage["count"]) + 1, nullptr); | ||||
sendMessageToMaster (valueTreeToMemoryBlock (reply)); | |||||
sendMessageToCoordinator (valueTreeToMemoryBlock (reply)); | |||||
} | } | ||||
void handleConnectionMade() override | void handleConnectionMade() override | ||||
@@ -264,10 +264,10 @@ public: | |||||
// This method is called when the connection is established, and in response, we'll just | // This method is called when the connection is established, and in response, we'll just | ||||
// send off a message to say hello. | // send off a message to say hello. | ||||
ValueTree reply ("HelloWorld"); | ValueTree reply ("HelloWorld"); | ||||
sendMessageToMaster (valueTreeToMemoryBlock (reply)); | |||||
sendMessageToCoordinator (valueTreeToMemoryBlock (reply)); | |||||
} | } | ||||
/* If no pings are received from the master process for a number of seconds, then this will get invoked. | |||||
/* If no pings are received from the coordinator process for a number of seconds, then this will get invoked. | |||||
Typically you'll want to use this as a signal to kill the process as quickly as possible, as you | Typically you'll want to use this as a signal to kill the process as quickly as possible, as you | ||||
don't want to leave it hanging around as a zombie.. | don't want to leave it hanging around as a zombie.. | ||||
*/ | */ | ||||
@@ -284,11 +284,11 @@ public: | |||||
*/ | */ | ||||
bool invokeChildProcessDemo (const String& commandLine) | bool invokeChildProcessDemo (const String& commandLine) | ||||
{ | { | ||||
std::unique_ptr<DemoSlaveProcess> slave (new DemoSlaveProcess()); | |||||
std::unique_ptr<DemoWorkerProcess> worker (new DemoWorkerProcess()); | |||||
if (slave->initialiseFromCommandLine (commandLine, demoCommandLineUID)) | |||||
if (worker->initialiseFromCommandLine (commandLine, demoCommandLineUID)) | |||||
{ | { | ||||
slave.release(); // allow the slave object to stay alive - it'll handle its own deletion. | |||||
worker.release(); // allow the worker object to stay alive - it'll handle its own deletion. | |||||
return true; | return true; | ||||
} | } | ||||
@@ -31,7 +31,7 @@ | |||||
#error "If you're building the audio plugin host, you probably want to enable VST and/or AU support" | #error "If you're building the audio plugin host, you probably want to enable VST and/or AU support" | ||||
#endif | #endif | ||||
class PluginScannerSubprocess : private ChildProcessSlave, | |||||
class PluginScannerSubprocess : private ChildProcessWorker, | |||||
private AsyncUpdater | private AsyncUpdater | ||||
{ | { | ||||
public: | public: | ||||
@@ -40,10 +40,10 @@ public: | |||||
formatManager.addDefaultFormats(); | formatManager.addDefaultFormats(); | ||||
} | } | ||||
using ChildProcessSlave::initialiseFromCommandLine; | |||||
using ChildProcessWorker::initialiseFromCommandLine; | |||||
private: | private: | ||||
void handleMessageFromMaster (const MemoryBlock& mb) override | |||||
void handleMessageFromCoordinator (const MemoryBlock& mb) override | |||||
{ | { | ||||
{ | { | ||||
const std::lock_guard<std::mutex> lock (mutex); | const std::lock_guard<std::mutex> lock (mutex); | ||||
@@ -94,7 +94,7 @@ private: | |||||
xml.addChildElement (desc->createXml().release()); | xml.addChildElement (desc->createXml().release()); | ||||
const auto str = xml.toString(); | const auto str = xml.toString(); | ||||
sendMessageToMaster ({ str.toRawUTF8(), str.getNumBytesAsUTF8() }); | |||||
sendMessageToCoordinator ({ str.toRawUTF8(), str.getNumBytesAsUTF8() }); | |||||
} | } | ||||
} | } | ||||
@@ -71,7 +71,7 @@ public: | |||||
stream.writeString (format.getName()); | stream.writeString (format.getName()); | ||||
stream.writeString (fileOrIdentifier); | stream.writeString (fileOrIdentifier); | ||||
if (superprocess->sendMessageToSlave (block)) | |||||
if (superprocess->sendMessageToWorker (block)) | |||||
{ | { | ||||
std::unique_lock<std::mutex> lock (mutex); | std::unique_lock<std::mutex> lock (mutex); | ||||
gotResponse = false; | gotResponse = false; | ||||
@@ -123,17 +123,19 @@ public: | |||||
} | } | ||||
private: | private: | ||||
class Superprocess : public ChildProcessMaster | |||||
class Superprocess : private ChildProcessCoordinator | |||||
{ | { | ||||
public: | public: | ||||
explicit Superprocess (CustomPluginScanner& o) | explicit Superprocess (CustomPluginScanner& o) | ||||
: owner (o) | : owner (o) | ||||
{ | { | ||||
launchSlaveProcess (File::getSpecialLocation (File::currentExecutableFile), processUID, 0, 0); | |||||
launchWorkerProcess (File::getSpecialLocation (File::currentExecutableFile), processUID, 0, 0); | |||||
} | } | ||||
using ChildProcessCoordinator::sendMessageToWorker; | |||||
private: | private: | ||||
void handleMessageFromSlave (const MemoryBlock& mb) override | |||||
void handleMessageFromWorker (const MemoryBlock& mb) override | |||||
{ | { | ||||
auto xml = parseXML (mb.toString()); | auto xml = parseXML (mb.toString()); | ||||
@@ -37,7 +37,7 @@ add_library( ${BINARY_NAME} | |||||
"../../../Source/Demos.h" | "../../../Source/Demos.h" | ||||
"../../../Source/Main.cpp" | "../../../Source/Main.cpp" | ||||
"../../../Source/MasterComponent.h" | "../../../Source/MasterComponent.h" | ||||
"../../../Source/SlaveComponent.h" | |||||
"../../../Source/ClientComponent.h" | |||||
"../../../Source/SharedCanvas.h" | "../../../Source/SharedCanvas.h" | ||||
"../../../Source/juce_icon.png" | "../../../Source/juce_icon.png" | ||||
"../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h" | "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h" | ||||
@@ -1623,7 +1623,7 @@ add_library( ${BINARY_NAME} | |||||
set_source_files_properties("../../../Source/Demos.h" PROPERTIES HEADER_FILE_ONLY TRUE) | set_source_files_properties("../../../Source/Demos.h" PROPERTIES HEADER_FILE_ONLY TRUE) | ||||
set_source_files_properties("../../../Source/MasterComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE) | set_source_files_properties("../../../Source/MasterComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE) | ||||
set_source_files_properties("../../../Source/SlaveComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE) | |||||
set_source_files_properties("../../../Source/ClientComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE) | |||||
set_source_files_properties("../../../Source/SharedCanvas.h" PROPERTIES HEADER_FILE_ONLY TRUE) | set_source_files_properties("../../../Source/SharedCanvas.h" PROPERTIES HEADER_FILE_ONLY TRUE) | ||||
set_source_files_properties("../../../Source/juce_icon.png" PROPERTIES HEADER_FILE_ONLY TRUE) | set_source_files_properties("../../../Source/juce_icon.png" PROPERTIES HEADER_FILE_ONLY TRUE) | ||||
set_source_files_properties("../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h" PROPERTIES HEADER_FILE_ONLY TRUE) | set_source_files_properties("../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h" PROPERTIES HEADER_FILE_ONLY TRUE) | ||||
@@ -67,7 +67,6 @@ | |||||
7BE6330821794919A88ED8ED /* include_juce_gui_extra.mm */ /* include_juce_gui_extra.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_gui_extra.mm; path = ../../JuceLibraryCode/include_juce_gui_extra.mm; sourceTree = SOURCE_ROOT; }; | 7BE6330821794919A88ED8ED /* include_juce_gui_extra.mm */ /* include_juce_gui_extra.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_gui_extra.mm; path = ../../JuceLibraryCode/include_juce_gui_extra.mm; sourceTree = SOURCE_ROOT; }; | ||||
84B287BB2AD252B7D69AC47E /* include_juce_gui_basics.mm */ /* include_juce_gui_basics.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_gui_basics.mm; path = ../../JuceLibraryCode/include_juce_gui_basics.mm; sourceTree = SOURCE_ROOT; }; | 84B287BB2AD252B7D69AC47E /* include_juce_gui_basics.mm */ /* include_juce_gui_basics.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_gui_basics.mm; path = ../../JuceLibraryCode/include_juce_gui_basics.mm; sourceTree = SOURCE_ROOT; }; | ||||
89583CD42AD218E9753DF11C /* juce_audio_devices */ /* juce_audio_devices */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_audio_devices; path = ../../../../modules/juce_audio_devices; sourceTree = SOURCE_ROOT; }; | 89583CD42AD218E9753DF11C /* juce_audio_devices */ /* juce_audio_devices */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_audio_devices; path = ../../../../modules/juce_audio_devices; sourceTree = SOURCE_ROOT; }; | ||||
8E2F72AFA0CDA64F0C07F105 /* SlaveComponent.h */ /* SlaveComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SlaveComponent.h; path = ../../Source/SlaveComponent.h; sourceTree = SOURCE_ROOT; }; | |||||
8EACAADD3A23DED3E252C92F /* juce_core */ /* juce_core */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_core; path = ../../../../modules/juce_core; sourceTree = SOURCE_ROOT; }; | 8EACAADD3A23DED3E252C92F /* juce_core */ /* juce_core */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_core; path = ../../../../modules/juce_core; sourceTree = SOURCE_ROOT; }; | ||||
92800676AF753D1A60108F11 /* BinaryData.h */ /* BinaryData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BinaryData.h; path = ../../JuceLibraryCode/BinaryData.h; sourceTree = SOURCE_ROOT; }; | 92800676AF753D1A60108F11 /* BinaryData.h */ /* BinaryData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BinaryData.h; path = ../../JuceLibraryCode/BinaryData.h; sourceTree = SOURCE_ROOT; }; | ||||
935CA85EF98714D3A17AE737 /* QuartzCore.framework */ /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; | 935CA85EF98714D3A17AE737 /* QuartzCore.framework */ /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; | ||||
@@ -83,6 +82,7 @@ | |||||
AFF729977947528F3E4AAA96 /* include_juce_cryptography.mm */ /* include_juce_cryptography.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_cryptography.mm; path = ../../JuceLibraryCode/include_juce_cryptography.mm; sourceTree = SOURCE_ROOT; }; | AFF729977947528F3E4AAA96 /* include_juce_cryptography.mm */ /* include_juce_cryptography.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_cryptography.mm; path = ../../JuceLibraryCode/include_juce_cryptography.mm; sourceTree = SOURCE_ROOT; }; | ||||
B5433B00F012AD87AADBFCD6 /* juce_cryptography */ /* juce_cryptography */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_cryptography; path = ../../../../modules/juce_cryptography; sourceTree = SOURCE_ROOT; }; | B5433B00F012AD87AADBFCD6 /* juce_cryptography */ /* juce_cryptography */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_cryptography; path = ../../../../modules/juce_cryptography; sourceTree = SOURCE_ROOT; }; | ||||
B76F10A7778664E164A01934 /* juce_audio_basics */ /* juce_audio_basics */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_audio_basics; path = ../../../../modules/juce_audio_basics; sourceTree = SOURCE_ROOT; }; | B76F10A7778664E164A01934 /* juce_audio_basics */ /* juce_audio_basics */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_audio_basics; path = ../../../../modules/juce_audio_basics; sourceTree = SOURCE_ROOT; }; | ||||
B9B80E3572715F63FFC3678B /* ClientComponent.h */ /* ClientComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ClientComponent.h; path = ../../Source/ClientComponent.h; sourceTree = SOURCE_ROOT; }; | |||||
BA2E40409255F1B078406221 /* juce_data_structures */ /* juce_data_structures */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_data_structures; path = ../../../../modules/juce_data_structures; sourceTree = SOURCE_ROOT; }; | BA2E40409255F1B078406221 /* juce_data_structures */ /* juce_data_structures */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_data_structures; path = ../../../../modules/juce_data_structures; sourceTree = SOURCE_ROOT; }; | ||||
C6E2284D86D93F1D9D5C7666 /* include_juce_audio_formats.mm */ /* include_juce_audio_formats.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_audio_formats.mm; path = ../../JuceLibraryCode/include_juce_audio_formats.mm; sourceTree = SOURCE_ROOT; }; | C6E2284D86D93F1D9D5C7666 /* include_juce_audio_formats.mm */ /* include_juce_audio_formats.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_audio_formats.mm; path = ../../JuceLibraryCode/include_juce_audio_formats.mm; sourceTree = SOURCE_ROOT; }; | ||||
C78806A6727F44EACFDED4A5 /* Cocoa.framework */ /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; | C78806A6727F44EACFDED4A5 /* Cocoa.framework */ /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; | ||||
@@ -138,7 +138,7 @@ | |||||
4FF648D72D6F1A78956CDA1B, | 4FF648D72D6F1A78956CDA1B, | ||||
77C0AC21C1028911123844FC, | 77C0AC21C1028911123844FC, | ||||
9982F39121710EFFD5FEEAEF, | 9982F39121710EFFD5FEEAEF, | ||||
8E2F72AFA0CDA64F0C07F105, | |||||
B9B80E3572715F63FFC3678B, | |||||
25DEDA8C9F94A6C8DFC8E53E, | 25DEDA8C9F94A6C8DFC8E53E, | ||||
); | ); | ||||
name = Source; | name = Source; | ||||
@@ -2174,7 +2174,7 @@ | |||||
<ItemGroup> | <ItemGroup> | ||||
<ClInclude Include="..\..\Source\Demos.h"/> | <ClInclude Include="..\..\Source\Demos.h"/> | ||||
<ClInclude Include="..\..\Source\MasterComponent.h"/> | <ClInclude Include="..\..\Source\MasterComponent.h"/> | ||||
<ClInclude Include="..\..\Source\SlaveComponent.h"/> | |||||
<ClInclude Include="..\..\Source\ClientComponent.h"/> | |||||
<ClInclude Include="..\..\Source\SharedCanvas.h"/> | <ClInclude Include="..\..\Source\SharedCanvas.h"/> | ||||
<ClInclude Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.h"/> | <ClInclude Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.h"/> | ||||
<ClInclude Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.h"/> | <ClInclude Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.h"/> | ||||
@@ -2667,7 +2667,7 @@ | |||||
<ClInclude Include="..\..\Source\MasterComponent.h"> | <ClInclude Include="..\..\Source\MasterComponent.h"> | ||||
<Filter>NetworkGraphicsDemo\Source</Filter> | <Filter>NetworkGraphicsDemo\Source</Filter> | ||||
</ClInclude> | </ClInclude> | ||||
<ClInclude Include="..\..\Source\SlaveComponent.h"> | |||||
<ClInclude Include="..\..\Source\ClientComponent.h"> | |||||
<Filter>NetworkGraphicsDemo\Source</Filter> | <Filter>NetworkGraphicsDemo\Source</Filter> | ||||
</ClInclude> | </ClInclude> | ||||
<ClInclude Include="..\..\Source\SharedCanvas.h"> | <ClInclude Include="..\..\Source\SharedCanvas.h"> | ||||
@@ -71,7 +71,6 @@ | |||||
7BE6330821794919A88ED8ED /* include_juce_gui_extra.mm */ /* include_juce_gui_extra.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_gui_extra.mm; path = ../../JuceLibraryCode/include_juce_gui_extra.mm; sourceTree = SOURCE_ROOT; }; | 7BE6330821794919A88ED8ED /* include_juce_gui_extra.mm */ /* include_juce_gui_extra.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_gui_extra.mm; path = ../../JuceLibraryCode/include_juce_gui_extra.mm; sourceTree = SOURCE_ROOT; }; | ||||
84B287BB2AD252B7D69AC47E /* include_juce_gui_basics.mm */ /* include_juce_gui_basics.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_gui_basics.mm; path = ../../JuceLibraryCode/include_juce_gui_basics.mm; sourceTree = SOURCE_ROOT; }; | 84B287BB2AD252B7D69AC47E /* include_juce_gui_basics.mm */ /* include_juce_gui_basics.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_gui_basics.mm; path = ../../JuceLibraryCode/include_juce_gui_basics.mm; sourceTree = SOURCE_ROOT; }; | ||||
89583CD42AD218E9753DF11C /* juce_audio_devices */ /* juce_audio_devices */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_audio_devices; path = ../../../../modules/juce_audio_devices; sourceTree = SOURCE_ROOT; }; | 89583CD42AD218E9753DF11C /* juce_audio_devices */ /* juce_audio_devices */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_audio_devices; path = ../../../../modules/juce_audio_devices; sourceTree = SOURCE_ROOT; }; | ||||
8E2F72AFA0CDA64F0C07F105 /* SlaveComponent.h */ /* SlaveComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SlaveComponent.h; path = ../../Source/SlaveComponent.h; sourceTree = SOURCE_ROOT; }; | |||||
8EACAADD3A23DED3E252C92F /* juce_core */ /* juce_core */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_core; path = ../../../../modules/juce_core; sourceTree = SOURCE_ROOT; }; | 8EACAADD3A23DED3E252C92F /* juce_core */ /* juce_core */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_core; path = ../../../../modules/juce_core; sourceTree = SOURCE_ROOT; }; | ||||
9193D2A3C463BEAA07FD424D /* CoreText.framework */ /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; | 9193D2A3C463BEAA07FD424D /* CoreText.framework */ /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; | ||||
92800676AF753D1A60108F11 /* BinaryData.h */ /* BinaryData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BinaryData.h; path = ../../JuceLibraryCode/BinaryData.h; sourceTree = SOURCE_ROOT; }; | 92800676AF753D1A60108F11 /* BinaryData.h */ /* BinaryData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BinaryData.h; path = ../../JuceLibraryCode/BinaryData.h; sourceTree = SOURCE_ROOT; }; | ||||
@@ -88,6 +87,7 @@ | |||||
AFF729977947528F3E4AAA96 /* include_juce_cryptography.mm */ /* include_juce_cryptography.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_cryptography.mm; path = ../../JuceLibraryCode/include_juce_cryptography.mm; sourceTree = SOURCE_ROOT; }; | AFF729977947528F3E4AAA96 /* include_juce_cryptography.mm */ /* include_juce_cryptography.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_cryptography.mm; path = ../../JuceLibraryCode/include_juce_cryptography.mm; sourceTree = SOURCE_ROOT; }; | ||||
B5433B00F012AD87AADBFCD6 /* juce_cryptography */ /* juce_cryptography */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_cryptography; path = ../../../../modules/juce_cryptography; sourceTree = SOURCE_ROOT; }; | B5433B00F012AD87AADBFCD6 /* juce_cryptography */ /* juce_cryptography */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_cryptography; path = ../../../../modules/juce_cryptography; sourceTree = SOURCE_ROOT; }; | ||||
B76F10A7778664E164A01934 /* juce_audio_basics */ /* juce_audio_basics */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_audio_basics; path = ../../../../modules/juce_audio_basics; sourceTree = SOURCE_ROOT; }; | B76F10A7778664E164A01934 /* juce_audio_basics */ /* juce_audio_basics */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_audio_basics; path = ../../../../modules/juce_audio_basics; sourceTree = SOURCE_ROOT; }; | ||||
B9B80E3572715F63FFC3678B /* ClientComponent.h */ /* ClientComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ClientComponent.h; path = ../../Source/ClientComponent.h; sourceTree = SOURCE_ROOT; }; | |||||
BA2E40409255F1B078406221 /* juce_data_structures */ /* juce_data_structures */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_data_structures; path = ../../../../modules/juce_data_structures; sourceTree = SOURCE_ROOT; }; | BA2E40409255F1B078406221 /* juce_data_structures */ /* juce_data_structures */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_data_structures; path = ../../../../modules/juce_data_structures; sourceTree = SOURCE_ROOT; }; | ||||
C6E2284D86D93F1D9D5C7666 /* include_juce_audio_formats.mm */ /* include_juce_audio_formats.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_audio_formats.mm; path = ../../JuceLibraryCode/include_juce_audio_formats.mm; sourceTree = SOURCE_ROOT; }; | C6E2284D86D93F1D9D5C7666 /* include_juce_audio_formats.mm */ /* include_juce_audio_formats.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_audio_formats.mm; path = ../../JuceLibraryCode/include_juce_audio_formats.mm; sourceTree = SOURCE_ROOT; }; | ||||
C821C5805007FFDC2636BBE6 /* OpenGLES.framework */ /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; | C821C5805007FFDC2636BBE6 /* OpenGLES.framework */ /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; | ||||
@@ -147,7 +147,7 @@ | |||||
4FF648D72D6F1A78956CDA1B, | 4FF648D72D6F1A78956CDA1B, | ||||
77C0AC21C1028911123844FC, | 77C0AC21C1028911123844FC, | ||||
9982F39121710EFFD5FEEAEF, | 9982F39121710EFFD5FEEAEF, | ||||
8E2F72AFA0CDA64F0C07F105, | |||||
B9B80E3572715F63FFC3678B, | |||||
25DEDA8C9F94A6C8DFC8E53E, | 25DEDA8C9F94A6C8DFC8E53E, | ||||
); | ); | ||||
name = Source; | name = Source; | ||||
@@ -10,8 +10,8 @@ | |||||
<FILE id="xdUc9q" name="Main.cpp" compile="1" resource="0" file="Source/Main.cpp"/> | <FILE id="xdUc9q" name="Main.cpp" compile="1" resource="0" file="Source/Main.cpp"/> | ||||
<FILE id="Vjuvqu" name="MasterComponent.h" compile="0" resource="0" | <FILE id="Vjuvqu" name="MasterComponent.h" compile="0" resource="0" | ||||
file="Source/MasterComponent.h"/> | file="Source/MasterComponent.h"/> | ||||
<FILE id="KbZNxO" name="SlaveComponent.h" compile="0" resource="0" | |||||
file="Source/SlaveComponent.h"/> | |||||
<FILE id="KbZNxO" name="ClientComponent.h" compile="0" resource="0" | |||||
file="Source/ClientComponent.h"/> | |||||
<FILE id="F7A4kl" name="SharedCanvas.h" compile="0" resource="0" file="Source/SharedCanvas.h"/> | <FILE id="F7A4kl" name="SharedCanvas.h" compile="0" resource="0" file="Source/SharedCanvas.h"/> | ||||
</GROUP> | </GROUP> | ||||
<FILE id="Ww6bQw" name="juce_icon.png" compile="0" resource="1" file="Source/juce_icon.png"/> | <FILE id="Ww6bQw" name="juce_icon.png" compile="0" resource="1" file="Source/juce_icon.png"/> | ||||
@@ -25,19 +25,19 @@ | |||||
/** | /** | ||||
This component runs in a slave process, draws the part of the canvas that this | |||||
This component runs in a client process, draws the part of the canvas that this | |||||
particular client covers, and updates itself when messages arrive from the master | particular client covers, and updates itself when messages arrive from the master | ||||
containing new canvas states. | containing new canvas states. | ||||
*/ | */ | ||||
class SlaveCanvasComponent : public Component, | |||||
private OSCSender, | |||||
private OSCReceiver, | |||||
private OSCReceiver::Listener<OSCReceiver::RealtimeCallback>, | |||||
private AsyncUpdater, | |||||
private Timer | |||||
class ClientCanvasComponent : public Component, | |||||
private OSCSender, | |||||
private OSCReceiver, | |||||
private OSCReceiver::Listener<OSCReceiver::RealtimeCallback>, | |||||
private AsyncUpdater, | |||||
private Timer | |||||
{ | { | ||||
public: | public: | ||||
SlaveCanvasComponent (PropertiesFile& p, int windowIndex) : properties (p) | |||||
ClientCanvasComponent (PropertiesFile& p, int windowIndex) : properties (p) | |||||
{ | { | ||||
{ | { | ||||
String uuidPropName ("UUID" + String (windowIndex)); | String uuidPropName ("UUID" + String (windowIndex)); | ||||
@@ -65,7 +65,7 @@ public: | |||||
startTimer (2000); | startTimer (2000); | ||||
} | } | ||||
~SlaveCanvasComponent() override | |||||
~ClientCanvasComponent() override | |||||
{ | { | ||||
OSCReceiver::removeListener (this); | OSCReceiver::removeListener (this); | ||||
} | } | ||||
@@ -220,5 +220,5 @@ private: | |||||
CriticalSection canvasLock; | CriticalSection canvasLock; | ||||
BlockPacketiser packetiser; | BlockPacketiser packetiser; | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SlaveCanvasComponent) | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ClientCanvasComponent) | |||||
}; | }; |
@@ -41,7 +41,7 @@ namespace | |||||
} | } | ||||
#include "SharedCanvas.h" | #include "SharedCanvas.h" | ||||
#include "SlaveComponent.h" | |||||
#include "ClientComponent.h" | |||||
#include "Demos.h" | #include "Demos.h" | ||||
#include "MasterComponent.h" | #include "MasterComponent.h" | ||||
@@ -107,7 +107,7 @@ public: | |||||
: DocumentWindow ("JUCE Networked Graphics Demo", Colours::black, DocumentWindow::allButtons) | : DocumentWindow ("JUCE Networked Graphics Demo", Colours::black, DocumentWindow::allButtons) | ||||
{ | { | ||||
setUsingNativeTitleBar (true); | setUsingNativeTitleBar (true); | ||||
setContentOwned (new SlaveCanvasComponent (props, windowIndex), true); | |||||
setContentOwned (new ClientCanvasComponent (props, windowIndex), true); | |||||
setBounds (500, 100, getWidth(), getHeight()); | setBounds (500, 100, getWidth(), getHeight()); | ||||
setResizable (true, false); | setResizable (true, false); | ||||
setVisible (true); | setVisible (true); | ||||
@@ -23,7 +23,7 @@ | |||||
namespace juce | namespace juce | ||||
{ | { | ||||
enum { magicMastSlaveConnectionHeader = 0x712baf04 }; | |||||
enum { magicCoordWorkerConnectionHeader = 0x712baf04 }; | |||||
static const char* startMessage = "__ipc_st"; | static const char* startMessage = "__ipc_st"; | ||||
static const char* killMessage = "__ipc_k_"; | static const char* killMessage = "__ipc_k_"; | ||||
@@ -82,11 +82,11 @@ private: | |||||
}; | }; | ||||
//============================================================================== | //============================================================================== | ||||
struct ChildProcessMaster::Connection : public InterprocessConnection, | |||||
private ChildProcessPingThread | |||||
struct ChildProcessCoordinator::Connection : public InterprocessConnection, | |||||
private ChildProcessPingThread | |||||
{ | { | ||||
Connection (ChildProcessMaster& m, const String& pipeName, int timeout) | |||||
: InterprocessConnection (false, magicMastSlaveConnectionHeader), | |||||
Connection (ChildProcessCoordinator& m, const String& pipeName, int timeout) | |||||
: InterprocessConnection (false, magicCoordWorkerConnectionHeader), | |||||
ChildProcessPingThread (timeout), | ChildProcessPingThread (timeout), | ||||
owner (m) | owner (m) | ||||
{ | { | ||||
@@ -103,7 +103,7 @@ private: | |||||
void connectionMade() override {} | void connectionMade() override {} | ||||
void connectionLost() override { owner.handleConnectionLost(); } | void connectionLost() override { owner.handleConnectionLost(); } | ||||
bool sendPingMessage (const MemoryBlock& m) override { return owner.sendMessageToSlave (m); } | |||||
bool sendPingMessage (const MemoryBlock& m) override { return owner.sendMessageToWorker (m); } | |||||
void pingFailed() override { connectionLost(); } | void pingFailed() override { connectionLost(); } | ||||
void messageReceived (const MemoryBlock& m) override | void messageReceived (const MemoryBlock& m) override | ||||
@@ -111,25 +111,34 @@ private: | |||||
pingReceived(); | pingReceived(); | ||||
if (m.getSize() != specialMessageSize || ! isMessageType (m, pingMessage)) | if (m.getSize() != specialMessageSize || ! isMessageType (m, pingMessage)) | ||||
owner.handleMessageFromSlave (m); | |||||
owner.handleMessageFromWorker (m); | |||||
} | } | ||||
ChildProcessMaster& owner; | |||||
ChildProcessCoordinator& owner; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Connection) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Connection) | ||||
}; | }; | ||||
//============================================================================== | //============================================================================== | ||||
ChildProcessMaster::ChildProcessMaster() {} | |||||
ChildProcessCoordinator::ChildProcessCoordinator() = default; | |||||
ChildProcessMaster::~ChildProcessMaster() | |||||
ChildProcessCoordinator::~ChildProcessCoordinator() | |||||
{ | { | ||||
killSlaveProcess(); | |||||
killWorkerProcess(); | |||||
} | } | ||||
void ChildProcessMaster::handleConnectionLost() {} | |||||
void ChildProcessCoordinator::handleConnectionLost() {} | |||||
void ChildProcessCoordinator::handleMessageFromWorker (const MemoryBlock& mb) | |||||
{ | |||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations") | |||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996) | |||||
handleMessageFromSlave (mb); | |||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE | |||||
JUCE_END_IGNORE_WARNINGS_MSVC | |||||
} | |||||
bool ChildProcessMaster::sendMessageToSlave (const MemoryBlock& mb) | |||||
bool ChildProcessCoordinator::sendMessageToWorker (const MemoryBlock& mb) | |||||
{ | { | ||||
if (connection != nullptr) | if (connection != nullptr) | ||||
return connection->sendMessage (mb); | return connection->sendMessage (mb); | ||||
@@ -138,10 +147,10 @@ bool ChildProcessMaster::sendMessageToSlave (const MemoryBlock& mb) | |||||
return false; | return false; | ||||
} | } | ||||
bool ChildProcessMaster::launchSlaveProcess (const File& executable, const String& commandLineUniqueID, | |||||
int timeoutMs, int streamFlags) | |||||
bool ChildProcessCoordinator::launchWorkerProcess (const File& executable, const String& commandLineUniqueID, | |||||
int timeoutMs, int streamFlags) | |||||
{ | { | ||||
killSlaveProcess(); | |||||
killWorkerProcess(); | |||||
auto pipeName = "p" + String::toHexString (Random().nextInt64()); | auto pipeName = "p" + String::toHexString (Random().nextInt64()); | ||||
@@ -157,7 +166,7 @@ bool ChildProcessMaster::launchSlaveProcess (const File& executable, const Strin | |||||
if (connection->isConnected()) | if (connection->isConnected()) | ||||
{ | { | ||||
sendMessageToSlave ({ startMessage, specialMessageSize }); | |||||
sendMessageToWorker ({ startMessage, specialMessageSize }); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -167,11 +176,11 @@ bool ChildProcessMaster::launchSlaveProcess (const File& executable, const Strin | |||||
return false; | return false; | ||||
} | } | ||||
void ChildProcessMaster::killSlaveProcess() | |||||
void ChildProcessCoordinator::killWorkerProcess() | |||||
{ | { | ||||
if (connection != nullptr) | if (connection != nullptr) | ||||
{ | { | ||||
sendMessageToSlave ({ killMessage, specialMessageSize }); | |||||
sendMessageToWorker ({ killMessage, specialMessageSize }); | |||||
connection->disconnect(); | connection->disconnect(); | ||||
connection.reset(); | connection.reset(); | ||||
} | } | ||||
@@ -180,11 +189,11 @@ void ChildProcessMaster::killSlaveProcess() | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
struct ChildProcessSlave::Connection : public InterprocessConnection, | |||||
private ChildProcessPingThread | |||||
struct ChildProcessWorker::Connection : public InterprocessConnection, | |||||
private ChildProcessPingThread | |||||
{ | { | ||||
Connection (ChildProcessSlave& p, const String& pipeName, int timeout) | |||||
: InterprocessConnection (false, magicMastSlaveConnectionHeader), | |||||
Connection (ChildProcessWorker& p, const String& pipeName, int timeout) | |||||
: InterprocessConnection (false, magicCoordWorkerConnectionHeader), | |||||
ChildProcessPingThread (timeout), | ChildProcessPingThread (timeout), | ||||
owner (p) | owner (p) | ||||
{ | { | ||||
@@ -198,12 +207,12 @@ struct ChildProcessSlave::Connection : public InterprocessConnection, | |||||
} | } | ||||
private: | private: | ||||
ChildProcessSlave& owner; | |||||
ChildProcessWorker& owner; | |||||
void connectionMade() override {} | void connectionMade() override {} | ||||
void connectionLost() override { owner.handleConnectionLost(); } | void connectionLost() override { owner.handleConnectionLost(); } | ||||
bool sendPingMessage (const MemoryBlock& m) override { return owner.sendMessageToMaster (m); } | |||||
bool sendPingMessage (const MemoryBlock& m) override { return owner.sendMessageToCoordinator (m); } | |||||
void pingFailed() override { connectionLost(); } | void pingFailed() override { connectionLost(); } | ||||
void messageReceived (const MemoryBlock& m) override | void messageReceived (const MemoryBlock& m) override | ||||
@@ -219,20 +228,29 @@ private: | |||||
if (isMessageType (m, startMessage)) | if (isMessageType (m, startMessage)) | ||||
return owner.handleConnectionMade(); | return owner.handleConnectionMade(); | ||||
owner.handleMessageFromMaster (m); | |||||
owner.handleMessageFromCoordinator (m); | |||||
} | } | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Connection) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Connection) | ||||
}; | }; | ||||
//============================================================================== | //============================================================================== | ||||
ChildProcessSlave::ChildProcessSlave() {} | |||||
ChildProcessSlave::~ChildProcessSlave() {} | |||||
ChildProcessWorker::ChildProcessWorker() = default; | |||||
ChildProcessWorker::~ChildProcessWorker() = default; | |||||
void ChildProcessWorker::handleConnectionMade() {} | |||||
void ChildProcessWorker::handleConnectionLost() {} | |||||
void ChildProcessSlave::handleConnectionMade() {} | |||||
void ChildProcessSlave::handleConnectionLost() {} | |||||
void ChildProcessWorker::handleMessageFromCoordinator (const MemoryBlock& mb) | |||||
{ | |||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations") | |||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996) | |||||
handleMessageFromMaster (mb); | |||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE | |||||
JUCE_END_IGNORE_WARNINGS_MSVC | |||||
} | |||||
bool ChildProcessSlave::sendMessageToMaster (const MemoryBlock& mb) | |||||
bool ChildProcessWorker::sendMessageToCoordinator (const MemoryBlock& mb) | |||||
{ | { | ||||
if (connection != nullptr) | if (connection != nullptr) | ||||
return connection->sendMessage (mb); | return connection->sendMessage (mb); | ||||
@@ -241,9 +259,9 @@ bool ChildProcessSlave::sendMessageToMaster (const MemoryBlock& mb) | |||||
return false; | return false; | ||||
} | } | ||||
bool ChildProcessSlave::initialiseFromCommandLine (const String& commandLine, | |||||
const String& commandLineUniqueID, | |||||
int timeoutMs) | |||||
bool ChildProcessWorker::initialiseFromCommandLine (const String& commandLine, | |||||
const String& commandLineUniqueID, | |||||
int timeoutMs) | |||||
{ | { | ||||
auto prefix = getCommandLinePrefix (commandLineUniqueID); | auto prefix = getCommandLinePrefix (commandLineUniqueID); | ||||
@@ -25,47 +25,47 @@ namespace juce | |||||
//============================================================================== | //============================================================================== | ||||
/** | /** | ||||
Acts as the slave end of a master/slave pair of connected processes. | |||||
Acts as the worker end of a coordinator/worker pair of connected processes. | |||||
The ChildProcessSlave and ChildProcessMaster classes make it easy for an app | |||||
The ChildProcessWorker and ChildProcessCoordinator classes make it easy for an app | |||||
to spawn a child process, and to manage a 2-way messaging connection to control it. | to spawn a child process, and to manage a 2-way messaging connection to control it. | ||||
To use the system, you need to create subclasses of both ChildProcessSlave and | |||||
ChildProcessMaster. To instantiate the ChildProcessSlave object, you must | |||||
To use the system, you need to create subclasses of both ChildProcessWorker and | |||||
ChildProcessCoordinator. To instantiate the ChildProcessWorker object, you must | |||||
add some code to your main() or JUCEApplication::initialise() function that | add some code to your main() or JUCEApplication::initialise() function that | ||||
calls the initialiseFromCommandLine() method to check the app's command-line | calls the initialiseFromCommandLine() method to check the app's command-line | ||||
parameters to see whether it's being launched as a child process. If this returns | parameters to see whether it's being launched as a child process. If this returns | ||||
true then the slave process can be allowed to run, and its handleMessageFromMaster() | |||||
true then the worker process can be allowed to run, and its handleMessageFromCoordinator() | |||||
method will be called whenever a message arrives. | method will be called whenever a message arrives. | ||||
The juce demo app has a good example of this class in action. | The juce demo app has a good example of this class in action. | ||||
@see ChildProcessMaster, InterprocessConnection, ChildProcess | |||||
@see ChildProcessCoordinator, InterprocessConnection, ChildProcess | |||||
@tags{Events} | @tags{Events} | ||||
*/ | */ | ||||
class JUCE_API ChildProcessSlave | |||||
class JUCE_API ChildProcessWorker | |||||
{ | { | ||||
public: | public: | ||||
/** Creates a non-connected slave process. | |||||
Use initialiseFromCommandLine to connect to a master process. | |||||
/** Creates a non-connected worker process. | |||||
Use initialiseFromCommandLine to connect to a coordinator process. | |||||
*/ | */ | ||||
ChildProcessSlave(); | |||||
ChildProcessWorker(); | |||||
/** Destructor. */ | /** Destructor. */ | ||||
virtual ~ChildProcessSlave(); | |||||
virtual ~ChildProcessWorker(); | |||||
/** This checks some command-line parameters to see whether they were generated by | /** This checks some command-line parameters to see whether they were generated by | ||||
ChildProcessMaster::launchSlaveProcess(), and if so, connects to that master process. | |||||
ChildProcessCoordinator::launchWorkerProcess(), and if so, connects to that coordinator process. | |||||
In an exe that can be used as a child process, you should add some code to your | In an exe that can be used as a child process, you should add some code to your | ||||
main() or JUCEApplication::initialise() that calls this method. | main() or JUCEApplication::initialise() that calls this method. | ||||
The commandLineUniqueID should be a short alphanumeric identifier (no spaces!) | The commandLineUniqueID should be a short alphanumeric identifier (no spaces!) | ||||
that matches the string passed to ChildProcessMaster::launchSlaveProcess(). | |||||
that matches the string passed to ChildProcessCoordinator::launchWorkerProcess(). | |||||
The timeoutMs parameter lets you specify how long the child process is allowed | The timeoutMs parameter lets you specify how long the child process is allowed | ||||
to run without receiving a ping from the master before the master is considered to | |||||
to run without receiving a ping from the coordinator before the coordinator is considered to | |||||
have died, and handleConnectionLost() will be called. Passing <= 0 for this timeout | have died, and handleConnectionLost() will be called. Passing <= 0 for this timeout | ||||
makes it use a default value. | makes it use a default value. | ||||
@@ -76,78 +76,86 @@ public: | |||||
int timeoutMs = 0); | int timeoutMs = 0); | ||||
//============================================================================== | //============================================================================== | ||||
/** This will be called to deliver messages from the master process. | |||||
/** This will be called to deliver messages from the coordinator process. | |||||
The call will probably be made on a background thread, so be careful with your | The call will probably be made on a background thread, so be careful with your | ||||
thread-safety! You may want to respond by sending back a message with | thread-safety! You may want to respond by sending back a message with | ||||
sendMessageToMaster() | |||||
sendMessageToCoordinator() | |||||
*/ | */ | ||||
virtual void handleMessageFromMaster (const MemoryBlock&) = 0; | |||||
virtual void handleMessageFromCoordinator (const MemoryBlock& mb); | |||||
/** This will be called when the master process finishes connecting to this slave. | |||||
[[deprecated ("Replaced by handleMessageFromCoordinator.")]] | |||||
virtual void handleMessageFromMaster (const MemoryBlock&) {} | |||||
/** This will be called when the coordinator process finishes connecting to this worker. | |||||
The call will probably be made on a background thread, so be careful with your thread-safety! | The call will probably be made on a background thread, so be careful with your thread-safety! | ||||
*/ | */ | ||||
virtual void handleConnectionMade(); | virtual void handleConnectionMade(); | ||||
/** This will be called when the connection to the master process is lost. | |||||
/** This will be called when the connection to the coordinator process is lost. | |||||
The call may be made from any thread (including the message thread). | The call may be made from any thread (including the message thread). | ||||
Typically, if your process only exists to act as a slave, you should probably exit | |||||
Typically, if your process only exists to act as a worker, you should probably exit | |||||
when this happens. | when this happens. | ||||
*/ | */ | ||||
virtual void handleConnectionLost(); | virtual void handleConnectionLost(); | ||||
/** Tries to send a message to the master process. | |||||
/** Tries to send a message to the coordinator process. | |||||
This returns true if the message was sent, but doesn't check that it actually gets | This returns true if the message was sent, but doesn't check that it actually gets | ||||
delivered at the other end. If successful, the data will emerge in a call to your | delivered at the other end. If successful, the data will emerge in a call to your | ||||
ChildProcessMaster::handleMessageFromSlave(). | |||||
ChildProcessCoordinator::handleMessageFromWorker(). | |||||
*/ | */ | ||||
bool sendMessageToMaster (const MemoryBlock&); | |||||
bool sendMessageToCoordinator (const MemoryBlock&); | |||||
[[deprecated ("Replaced by sendMessageToCoordinator.")]] | |||||
bool sendMessageToMaster (const MemoryBlock& mb) { return sendMessageToCoordinator (mb); } | |||||
private: | private: | ||||
struct Connection; | struct Connection; | ||||
std::unique_ptr<Connection> connection; | std::unique_ptr<Connection> connection; | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcessSlave) | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcessWorker) | |||||
}; | }; | ||||
using ChildProcessSlave [[deprecated ("Replaced by ChildProcessWorker.")]] = ChildProcessWorker; | |||||
//============================================================================== | //============================================================================== | ||||
/** | /** | ||||
Acts as the master in a master/slave pair of connected processes. | |||||
Acts as the coordinator in a coordinator/worker pair of connected processes. | |||||
The ChildProcessSlave and ChildProcessMaster classes make it easy for an app | |||||
The ChildProcessWorker and ChildProcessCoordinator classes make it easy for an app | |||||
to spawn a child process, and to manage a 2-way messaging connection to control it. | to spawn a child process, and to manage a 2-way messaging connection to control it. | ||||
To use the system, you need to create subclasses of both ChildProcessSlave and | |||||
ChildProcessMaster. When you want your master process to launch the slave, you | |||||
just call launchSlaveProcess(), and it'll attempt to launch the executable that | |||||
To use the system, you need to create subclasses of both ChildProcessWorker and | |||||
ChildProcessCoordinator. When you want your coordinator process to launch the worker, you | |||||
just call launchWorkerProcess(), and it'll attempt to launch the executable that | |||||
you specify (which may be the same exe), and assuming it has been set-up to | you specify (which may be the same exe), and assuming it has been set-up to | ||||
correctly parse the command-line parameters (see ChildProcessSlave) then a | |||||
correctly parse the command-line parameters (see ChildProcessWorker) then a | |||||
two-way connection will be created. | two-way connection will be created. | ||||
The juce demo app has a good example of this class in action. | The juce demo app has a good example of this class in action. | ||||
@see ChildProcessSlave, InterprocessConnection, ChildProcess | |||||
@see ChildProcessWorker, InterprocessConnection, ChildProcess | |||||
@tags{Events} | @tags{Events} | ||||
*/ | */ | ||||
class JUCE_API ChildProcessMaster | |||||
class JUCE_API ChildProcessCoordinator | |||||
{ | { | ||||
public: | public: | ||||
/** Creates an uninitialised master process object. | |||||
Use launchSlaveProcess to launch and connect to a child process. | |||||
/** Creates an uninitialised coordinator process object. | |||||
Use launchWorkerProcess to launch and connect to a child process. | |||||
*/ | */ | ||||
ChildProcessMaster(); | |||||
ChildProcessCoordinator(); | |||||
/** Destructor. | /** Destructor. | ||||
Note that the destructor calls killSlaveProcess(), but doesn't wait for | |||||
Note that the destructor calls killWorkerProcess(), but doesn't wait for | |||||
the child process to finish terminating. | the child process to finish terminating. | ||||
*/ | */ | ||||
virtual ~ChildProcessMaster(); | |||||
virtual ~ChildProcessCoordinator(); | |||||
/** Attempts to launch and connect to a slave process. | |||||
/** Attempts to launch and connect to a worker process. | |||||
This will start the given executable, passing it a special command-line | This will start the given executable, passing it a special command-line | ||||
parameter based around the commandLineUniqueID string, which must be a | parameter based around the commandLineUniqueID string, which must be a | ||||
short alphanumeric string (no spaces!) that identifies your app. The exe | short alphanumeric string (no spaces!) that identifies your app. The exe | ||||
that gets launched must respond by calling ChildProcessSlave::initialiseFromCommandLine() | |||||
that gets launched must respond by calling ChildProcessWorker::initialiseFromCommandLine() | |||||
in its startup code, and must use a matching ID to commandLineUniqueID. | in its startup code, and must use a matching ID to commandLineUniqueID. | ||||
The timeoutMs parameter lets you specify how long the child process is allowed | The timeoutMs parameter lets you specify how long the child process is allowed | ||||
@@ -156,37 +164,55 @@ public: | |||||
it use a default value. | it use a default value. | ||||
If this all works, the method returns true, and you can begin sending and | If this all works, the method returns true, and you can begin sending and | ||||
receiving messages with the slave process. | |||||
receiving messages with the worker process. | |||||
If a child process is already running, this will call killSlaveProcess() and | |||||
If a child process is already running, this will call killWorkerProcess() and | |||||
start a new one. | start a new one. | ||||
*/ | */ | ||||
bool launchWorkerProcess (const File& executableToLaunch, | |||||
const String& commandLineUniqueID, | |||||
int timeoutMs = 0, | |||||
int streamFlags = ChildProcess::wantStdOut | ChildProcess::wantStdErr); | |||||
[[deprecated ("Replaced by launchWorkerProcess.")]] | |||||
bool launchSlaveProcess (const File& executableToLaunch, | bool launchSlaveProcess (const File& executableToLaunch, | ||||
const String& commandLineUniqueID, | const String& commandLineUniqueID, | ||||
int timeoutMs = 0, | int timeoutMs = 0, | ||||
int streamFlags = ChildProcess::wantStdOut | ChildProcess::wantStdErr); | |||||
int streamFlags = ChildProcess::wantStdOut | ChildProcess::wantStdErr) | |||||
{ | |||||
return launchWorkerProcess (executableToLaunch, commandLineUniqueID, timeoutMs, streamFlags); | |||||
} | |||||
/** Sends a kill message to the slave, and disconnects from it. | |||||
/** Sends a kill message to the worker, and disconnects from it. | |||||
Note that this won't wait for it to terminate. | Note that this won't wait for it to terminate. | ||||
*/ | */ | ||||
void killSlaveProcess(); | |||||
void killWorkerProcess(); | |||||
/** This will be called to deliver a message from the slave process. | |||||
[[deprecated ("Replaced by killWorkerProcess.")]] | |||||
void killSlaveProcess() { killWorkerProcess(); } | |||||
/** This will be called to deliver a message from the worker process. | |||||
The call will probably be made on a background thread, so be careful with your thread-safety! | The call will probably be made on a background thread, so be careful with your thread-safety! | ||||
*/ | */ | ||||
virtual void handleMessageFromSlave (const MemoryBlock&) = 0; | |||||
virtual void handleMessageFromWorker (const MemoryBlock&); | |||||
[[deprecated ("Replaced by handleMessageFromWorker")]] | |||||
virtual void handleMessageFromSlave (const MemoryBlock&) {} | |||||
/** This will be called when the slave process dies or is somehow disconnected. | |||||
/** This will be called when the worker process dies or is somehow disconnected. | |||||
The call will probably be made on a background thread, so be careful with your thread-safety! | The call will probably be made on a background thread, so be careful with your thread-safety! | ||||
*/ | */ | ||||
virtual void handleConnectionLost(); | virtual void handleConnectionLost(); | ||||
/** Attempts to send a message to the slave process. | |||||
/** Attempts to send a message to the worker process. | |||||
This returns true if the message was dispatched, but doesn't check that it actually | This returns true if the message was dispatched, but doesn't check that it actually | ||||
gets delivered at the other end. If successful, the data will emerge in a call to | gets delivered at the other end. If successful, the data will emerge in a call to | ||||
your ChildProcessSlave::handleMessageFromMaster(). | |||||
your ChildProcessWorker::handleMessageFromCoordinator(). | |||||
*/ | */ | ||||
bool sendMessageToSlave (const MemoryBlock&); | |||||
bool sendMessageToWorker (const MemoryBlock&); | |||||
[[deprecated ("Replaced by sendMessageToWorker.")]] | |||||
bool sendMessageToSlave (const MemoryBlock& mb) { return sendMessageToWorker (mb); } | |||||
private: | private: | ||||
std::unique_ptr<ChildProcess> childProcess; | std::unique_ptr<ChildProcess> childProcess; | ||||
@@ -194,7 +220,9 @@ private: | |||||
struct Connection; | struct Connection; | ||||
std::unique_ptr<Connection> connection; | std::unique_ptr<Connection> connection; | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcessMaster) | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcessCoordinator) | |||||
}; | }; | ||||
using ChildProcessMaster [[deprecated ("Replaced by ChildProcessCoordinator.")]] = ChildProcessCoordinator; | |||||
} // namespace juce | } // namespace juce |