21#include "JuceHeader.h"
28juce::uint32 CelloMagicIpcNumber { 0x000C3110 };
33template <>
struct VariantConverter<cello::IpcServerStatus>
35 static cello::IpcServerStatus fromVar (
const var& v) {
return static_cast<cello::IpcServerStatus
> (int (v)); }
37 static var toVar (
const cello::IpcServerStatus& t) {
return static_cast<int> (t); }
44IpcClient::IpcClient (Object& objectToWatch, UpdateType updateType,
const juce::String& hostName,
int portNum,
45 const juce::String& pipeName,
int msTimeout, Object* state)
46: juce::InterprocessConnection { true, CelloMagicIpcNumber }
47, juce::ValueTreeSynchroniser { objectToWatch }
48, UpdateQueue { objectToWatch, nullptr }
49, clientProperties { objectToWatch.getType ().toString (), state }
50, update { updateType }
54, timeout { msTimeout }
58 jassert ((update & UpdateType::send) || (update & UpdateType::receive));
60 jassert (!(update & UpdateType::fullUpdateOnConnect) ||
61 ((update & UpdateType::fullUpdateOnConnect) && (update & UpdateType::send)));
65 UpdateType updateType,
Object* state)
66:
IpcClient (objectToWatch, updateType, hostName, portNum,
"", msTimeout, state)
68 jassert (host.isNotEmpty ());
73:
IpcClient (objectToWatch, updateType,
"", 0, pipeName, msTimeout, state)
75 jassert (pipe.isNotEmpty ());
78IpcClient::~IpcClient ()
85 if (host.isNotEmpty ())
89 return connectToSocket (host, port, timeout);
92 if (pipe.isNotEmpty ())
98 return createPipe (pipe, timeout,
true);
100 return connectToPipe (pipe, timeout);
102 return createPipe (pipe, timeout,
false);
114void IpcClient::connectionMade ()
116 clientProperties.connected =
true;
117 if (update & UpdateType::fullUpdateOnConnect)
118 sendFullSyncCallback ();
121void IpcClient::connectionLost ()
123 clientProperties.connected =
false;
126void IpcClient::messageReceived (
const juce::MemoryBlock& message)
128 if (update & UpdateType::receive)
131 pushUpdate (juce::MemoryBlock { message });
132 clientProperties.rxCount++;
135void IpcClient::stateChanged (
const void* encodedChange,
size_t encodedSize)
137 if ((update & UpdateType::send) && (clientProperties.connected))
139 sendMessage ({ encodedChange, encodedSize });
140 clientProperties.txCount++;
146IpcServerProperties::IpcServerProperties (
const juce::String& path,
Object* state)
157 status = IpcServerStatus::alreadyRunning;
160 bindAddress = address;
163 portNumber = portNum;
170 status = IpcServerStatus::alreadyStopped;
178IpcServer::IpcServer (
Object& sync, IpcClient::UpdateType updateType,
const juce::String& statePath,
Object* state)
180, update { updateType }
181, serverProperties { statePath, state }
186 [
this] (juce::Identifier )
188 if (serverProperties.portNumber > 0)
189 startServer (serverProperties.portNumber, serverProperties.bindAddress);
195IpcServer::~IpcServer ()
200 connections.clear ();
205 if (serverProperties.running)
207 serverProperties.status = IpcServerStatus::alreadyRunning;
211 if (beginWaitingForSocket (portNumber, bindAddress))
213 serverProperties.running =
true;
214 serverProperties.status = IpcServerStatus::startedOkay;
218 serverProperties.running =
false;
219 serverProperties.status = IpcServerStatus::errorStarting;
225 if (!serverProperties.running)
227 serverProperties.status = IpcServerStatus::alreadyStopped;
235 serverProperties.running =
false;
236 serverProperties.status = IpcServerStatus::stoppedOkay;
245 auto client { std::make_unique<IpcClient> (syncObject,
"", 0, 0, update, &serverProperties) };
246 juce::InterprocessConnection* connection { client.get () };
247 connections.push_back (std::move (client));
254#include "test/test_cello_ipc.inl"
IpcClient(Object &objectToWatch, const juce::String &hostName, int portNum, int msTimeout, UpdateType updateType, Object *state=nullptr)
Construct a new Ipc Client object that connects using sockets.
Definition cello_ipc.cpp:64
bool connect(ConnectOptions option=ConnectOptions::noOptions)
Attempt to make a connection to another IpcClient running in another process.
Definition cello_ipc.cpp:83
ConnectOptions
Definition cello_ipc.h:62
@ mustExist
pipe must already exist, fail if it doesn't
Definition cello_ipc.h:65
@ noOptions
default, used for sockets, which have no options.
Definition cello_ipc.h:63
@ createIfNeeded
If pipe exists, use it, otherwise create.
Definition cello_ipc.h:66
@ createOrFail
create the pipe, fail if we couldn't
Definition cello_ipc.h:64
bool startServer(int portNumber, const juce::String &bindAddress=juce::String())
Launch the thread that starts listening for incoming socket connections.
Definition cello_ipc.cpp:203
bool stopServer()
Stop the server.
Definition cello_ipc.cpp:223
juce::InterprocessConnection * createConnectionObject() override
When we get a connection, the base server class will call this so that we can create and return an in...
Definition cello_ipc.cpp:240
Definition cello_object.h:34
void onPropertyChange(juce::Identifier id, PropertyUpdateFn callback)
Install (or clear) a function to be called when one of this Object's properties changes....
Definition cello_object.cpp:255
void forceUpdate(bool shouldForceUpdate)
If passed true, any call that sets any Value property on this Object will result in a property change...
Definition cello_update_source.h:39
void stopServer()
Tell the server object we're controlling to stop.
Definition cello_ipc.cpp:166
void startServer(int portNum, const juce::String &address=juce::String())
Tell the server object we're controlling to start on the specified port (and optionally which address...
Definition cello_ipc.cpp:153