Skip to content

Commit

Permalink
Introduce IPC connection as generic wrapper around potentially multip…
Browse files Browse the repository at this point in the history
…le message channels
  • Loading branch information
sgretscher committed Feb 11, 2024
1 parent d9f7efa commit 33eef73
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 78 deletions.
4 changes: 2 additions & 2 deletions ExamplesCommon/PlugInHosting/AudioUnitLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ typedef struct _AudioUnitInstance * AudioUnitInstance;
AudioUnitComponent AudioUnitPrepareComponentWithIDs(OSType type, OSType subtype, OSType manufacturer);
bool AudioUnitIsV2(AudioUnitComponent audioUnitComponent);
AudioUnitInstance AudioUnitOpenInstance(AudioUnitComponent audioUnitComponent, bool useIPC);
// On return, *messageChannel will be NULL if Audio Unit does not use IPC, otherwise it will point to
// On return, *connection will be NULL if Audio Unit does not use IPC, otherwise it will point to
// a valid message channel for all factory-related calls until AudioUnitCleanupComponent() is called.
const ARA_NAMESPACE ARAFactory * AudioUnitGetARAFactory(AudioUnitInstance audioUnit, ARA_IPC_NAMESPACE ARAIPCMessageChannelRef * messageChannelRef);
const ARA_NAMESPACE ARAFactory * AudioUnitGetARAFactory(AudioUnitInstance audioUnit, ARA_IPC_NAMESPACE ARAIPCConnectionRef * connectionRef);
const ARA_NAMESPACE ARAPlugInExtensionInstance * AudioUnitBindToARADocumentController(AudioUnitInstance audioUnit, ARA_NAMESPACE ARADocumentControllerRef controllerRef, ARA_NAMESPACE ARAPlugInInstanceRoleFlags assignedRoles);
void AudioUnitStartRendering(AudioUnitInstance audioUnit, UInt32 maxBlockSize, double sampleRate);
void AudioUnitRenderBuffer(AudioUnitInstance audioUnit, UInt32 blockSize, SInt64 samplePosition, float * buffer);
Expand Down
10 changes: 5 additions & 5 deletions ExamplesCommon/PlugInHosting/AudioUnitLoader.m
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,10 @@ AudioUnitInstance AudioUnitOpenInstance(AudioUnitComponent audioUnitComponent, b
return result;
}

const ARAFactory * AudioUnitGetARAFactory(AudioUnitInstance audioUnitInstance, ARAIPCMessageChannelRef * messageChannelRef)
const ARAFactory * AudioUnitGetARAFactory(AudioUnitInstance audioUnitInstance, ARAIPCConnectionRef * connectionRef)
{
const ARAFactory * result = NULL; // initially assume this plug-in doesn't support ARA
*messageChannelRef = NULL;
*connectionRef = NULL;

// check whether the AU supports ARA by trying to get the factory
if (audioUnitInstance->isAUv2)
Expand Down Expand Up @@ -242,10 +242,10 @@ AudioUnitInstance AudioUnitOpenInstance(AudioUnitComponent audioUnitComponent, b
audioUnitInstance->audioUnitComponent->araProxy = ARAIPCAUProxyPlugInInitialize(audioUnitInstance->v3AudioUnit);
if (audioUnitInstance->audioUnitComponent->araProxy)
{
*messageChannelRef = ARAIPCAUProxyPlugInGetMainMessageChannel(audioUnitInstance->audioUnitComponent->araProxy);
*connectionRef = audioUnitInstance->audioUnitComponent->araProxy;

ARA_VALIDATE_API_CONDITION(ARAIPCProxyPlugInGetFactoriesCount(*messageChannelRef) == 1);
result = ARAIPCProxyPlugInGetFactoryAtIndex (*messageChannelRef, 0);
ARA_VALIDATE_API_CONDITION(ARAIPCProxyPlugInGetFactoriesCount(*connectionRef) == 1);
result = ARAIPCProxyPlugInGetFactoryAtIndex (*connectionRef, 0);
ARA_VALIDATE_API_CONDITION(result != NULL);
}
}
Expand Down
110 changes: 60 additions & 50 deletions TestHost/CompanionAPIs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ constexpr auto kIPCTerminateMethodID { ARA::IPC::MethodID::createWithNonARAMetho
_Pragma ("GCC diagnostic ignored \"-Wunused-template\"")
#endif

ARA_MAP_IPC_REF (ARA::IPC::MessageChannel, ARA::IPC::ARAIPCMessageChannelRef)
ARA_MAP_IPC_REF (ARA::IPC::Connection, ARA::IPC::ARAIPCConnectionRef)

#if defined (__GNUC__)
_Pragma ("GCC diagnostic pop")
Expand Down Expand Up @@ -324,7 +324,7 @@ class AUPlugInEntry : public PlugInEntry
_audioUnitComponent { AudioUnitPrepareComponentWithIDs (parseOSType (type), parseOSType (subType), parseOSType (manufacturer)) }
{
AudioUnitInstance audioUnitInstance = AudioUnitOpenInstance (_audioUnitComponent, useIPCIfPossible);
validateAndSetFactory (AudioUnitGetARAFactory (audioUnitInstance, &_messageChannelRef));
validateAndSetFactory (AudioUnitGetARAFactory (audioUnitInstance, &_connectionRef));
AudioUnitCloseInstance (audioUnitInstance);
}

Expand All @@ -335,13 +335,13 @@ class AUPlugInEntry : public PlugInEntry

bool usesIPC () const override
{
return _messageChannelRef != nullptr;
return _connectionRef != nullptr;
}

void initializeARA (ARA::ARAAssertFunction* assertFunctionAddress) override
{
if (usesIPC ())
ARA::IPC::ARAIPCProxyPlugInInitializeARA (_messageChannelRef, getARAFactory ()->factoryID, getDesiredAPIGeneration (getARAFactory ()));
ARA::IPC::ARAIPCProxyPlugInInitializeARA (_connectionRef, getARAFactory ()->factoryID, getDesiredAPIGeneration (getARAFactory ()));
else
PlugInEntry::initializeARA (assertFunctionAddress);
}
Expand All @@ -350,15 +350,15 @@ class AUPlugInEntry : public PlugInEntry
const ARA::ARADocumentProperties* properties) override
{
if (usesIPC ())
return ARA::IPC::ARAIPCProxyPlugInCreateDocumentControllerWithDocument (_messageChannelRef, getARAFactory ()->factoryID, hostInstance, properties);
return ARA::IPC::ARAIPCProxyPlugInCreateDocumentControllerWithDocument (_connectionRef, getARAFactory ()->factoryID, hostInstance, properties);
else
return PlugInEntry::createDocumentControllerWithDocument (hostInstance, properties);
}

void uninitializeARA () override
{
if (usesIPC ())
ARA::IPC::ARAIPCProxyPlugInUninitializeARA (_messageChannelRef, getARAFactory ()->factoryID);
ARA::IPC::ARAIPCProxyPlugInUninitializeARA (_connectionRef, getARAFactory ()->factoryID);
else
PlugInEntry::uninitializeARA ();
}
Expand All @@ -371,7 +371,7 @@ class AUPlugInEntry : public PlugInEntry

private:
AudioUnitComponent const _audioUnitComponent;
ARA::IPC::ARAIPCMessageChannelRef _messageChannelRef {};
ARA::IPC::ARAIPCConnectionRef _connectionRef {};
};

#endif // defined (__APPLE__)
Expand Down Expand Up @@ -451,11 +451,33 @@ class CLAPPlugInEntry : public PlugInEntry

#if ARA_ENABLE_IPC

class Connection : public ARA::IPC::Connection
{
public:
using ARA::IPC::Connection::Connection;

ARA::IPC::MessageEncoder* createEncoder () override
{
#if USE_ARA_CF_ENCODING
return new ARA::IPC::CFMessageEncoder {};
#else
return new IPCXMLMessageEncoder {};
#endif
}

// \todo currently not implemented, we rely on running on the same machine for now
// C++20 offers std::endian which allows for a simple implementation upon connecting...
bool receiverEndianessMatches () override
{
return true;
}
};

class IPCPlugInInstance : public PlugInInstance, protected ARA::IPC::RemoteCaller
{
public:
IPCPlugInInstance (ARA::IPC::ARAIPCPlugInInstanceRef remoteRef, ARA::IPC::MessageChannel* messageChannel)
: RemoteCaller { messageChannel },
IPCPlugInInstance (ARA::IPC::ARAIPCPlugInInstanceRef remoteRef, ARA::IPC::Connection* connection)
: RemoteCaller { connection },
_remoteRef { remoteRef }
{}

Expand Down Expand Up @@ -498,9 +520,6 @@ class IPCPlugInInstance : public PlugInInstance, protected ARA::IPC::RemoteCalle
ARA::IPC::ARAIPCPlugInInstanceRef const _remoteRef;
};


/*******************************************************************************/

// helper class to launch remote before initializing related IPC channel members
struct RemoteLauncher
{
Expand All @@ -517,40 +536,37 @@ struct RemoteLauncher
}
};

/*******************************************************************************/

class IPCPlugInEntry : public PlugInEntry, private RemoteLauncher, protected ARA::IPC::RemoteCaller, public ARA::IPC::ProxyPlugInMessageHandler
class IPCPlugInEntry : public PlugInEntry, private RemoteLauncher, public ARA::IPC::ProxyPlugIn, public Connection
{
private:
static const ARA::ARAFactory* defaultGetFactory (ARA::IPC::ARAIPCMessageChannelRef messageChannel)
static const ARA::ARAFactory* defaultGetFactory (ARA::IPC::ARAIPCConnectionRef connection)
{
const auto count { ARA::IPC::ARAIPCProxyPlugInGetFactoriesCount (messageChannel) };
const auto count { ARA::IPC::ARAIPCProxyPlugInGetFactoriesCount (connection) };
ARA_INTERNAL_ASSERT (count > 0);
return ARA::IPC::ARAIPCProxyPlugInGetFactoryAtIndex (messageChannel, 0U);
return ARA::IPC::ARAIPCProxyPlugInGetFactoryAtIndex (connection, 0U);
}

IPCPlugInEntry (std::string&& description, const std::string& launchArgs,
const std::string channelID,
const std::function<const ARA::ARAFactory* (ARA::IPC::ARAIPCMessageChannelRef)>& getFactoryFunction)
const std::function<const ARA::ARAFactory* (ARA::IPC::ARAIPCConnectionRef)>& getFactoryFunction)
: PlugInEntry { std::move (description) },
RemoteLauncher { launchArgs, channelID },
ARA::IPC::RemoteCaller { IPCMessageChannel::createConnectedToID (channelID, this) }
ARA::IPC::ProxyPlugIn { this },
Connection { this, IPCMessageChannel::createConnectedToID (channelID, this) }
{
validateAndSetFactory (getFactoryFunction (toIPCRef (getMessageChannel ())));
validateAndSetFactory (getFactoryFunction (toIPCRef (getConnection ())));
}

public:
// \todo the current ARA IPC implementation does not support sending ARA asserts to the host...
IPCPlugInEntry (std::string&& description, const std::string& launchArgs,
const std::function<const ARA::ARAFactory* (ARA::IPC::ARAIPCMessageChannelRef)>& getFactoryFunction = defaultGetFactory)
const std::function<const ARA::ARAFactory* (ARA::IPC::ARAIPCConnectionRef)>& getFactoryFunction = defaultGetFactory)
: IPCPlugInEntry { std::move (description), launchArgs, _createChannelID (), getFactoryFunction }
{}

~IPCPlugInEntry () override
{
remoteCall (kIPCTerminateMethodID);

delete getMessageChannel ();
}

bool usesIPC () const override
Expand All @@ -567,25 +583,25 @@ class IPCPlugInEntry : public PlugInEntry, private RemoteLauncher, protected ARA

void initializeARA (ARA::ARAAssertFunction* /*assertFunctionAddress*/) override
{
ARA::IPC::ARAIPCProxyPlugInInitializeARA (toIPCRef (getMessageChannel ()), getARAFactory ()->factoryID, getDesiredAPIGeneration (getARAFactory ()));
ARA::IPC::ARAIPCProxyPlugInInitializeARA (toIPCRef (getConnection ()), getARAFactory ()->factoryID, getDesiredAPIGeneration (getARAFactory ()));
}

const ARA::ARADocumentControllerInstance* createDocumentControllerWithDocument (const ARA::ARADocumentControllerHostInstance* hostInstance,
const ARA::ARADocumentProperties* properties) override
{
return ARA::IPC::ARAIPCProxyPlugInCreateDocumentControllerWithDocument (toIPCRef (getMessageChannel ()), getARAFactory ()->factoryID, hostInstance, properties);
return ARA::IPC::ARAIPCProxyPlugInCreateDocumentControllerWithDocument (toIPCRef (getConnection ()), getARAFactory ()->factoryID, hostInstance, properties);
}

void uninitializeARA () override
{
ARA::IPC::ARAIPCProxyPlugInUninitializeARA (toIPCRef (getMessageChannel ()), getARAFactory ()->factoryID);
ARA::IPC::ARAIPCProxyPlugInUninitializeARA (toIPCRef (getConnection ()), getARAFactory ()->factoryID);
}

std::unique_ptr<PlugInInstance> createPlugInInstance () override
{
ARA::IPC::ARAIPCPlugInInstanceRef remoteInstanceRef {};
remoteCall (remoteInstanceRef, kIPCCreateEffectMethodID);
return std::make_unique<IPCPlugInInstance> (remoteInstanceRef, getMessageChannel ());
return std::make_unique<IPCPlugInInstance> (remoteInstanceRef, getConnection ());
}
};

Expand All @@ -597,22 +613,22 @@ class IPCGenericPlugInEntry : public IPCPlugInEntry
IPCGenericPlugInEntry (const std::string& commandLineArg, const std::string& apiName, const std::string& binaryName, const std::string& optionalPlugInName)
: IPCPlugInEntry { createEntryDescription (apiName, binaryName, optionalPlugInName),
commandLineArg + " " + binaryName + " " + optionalPlugInName,
[&optionalPlugInName] (ARA::IPC::ARAIPCMessageChannelRef messageChannel) -> const ARA::ARAFactory*
[&optionalPlugInName] (ARA::IPC::ARAIPCConnectionRef connection) -> const ARA::ARAFactory*
{
const auto count { ARA::IPC::ARAIPCProxyPlugInGetFactoriesCount (messageChannel) };
const auto count { ARA::IPC::ARAIPCProxyPlugInGetFactoriesCount (connection) };
ARA_INTERNAL_ASSERT (count > 0);

if (optionalPlugInName.empty ())
return ARA::IPC::ARAIPCProxyPlugInGetFactoryAtIndex (messageChannel, 0U);
return ARA::IPC::ARAIPCProxyPlugInGetFactoryAtIndex (connection, 0U);

for (auto i { 0U }; i < count; ++i)
{
auto factory { ARA::IPC::ARAIPCProxyPlugInGetFactoryAtIndex (messageChannel, i) };
auto factory { ARA::IPC::ARAIPCProxyPlugInGetFactoryAtIndex (connection, i) };
if (0 == std::strcmp (factory->plugInName, optionalPlugInName.c_str ()))
return factory;
}
ARA_INTERNAL_ASSERT (false);
return ARA::IPC::ARAIPCProxyPlugInGetFactoryAtIndex (messageChannel, 0U);
return ARA::IPC::ARAIPCProxyPlugInGetFactoryAtIndex (connection, 0U);
} }
{}
};
Expand Down Expand Up @@ -657,9 +673,14 @@ class IPCAUPlugInEntry : public IPCPlugInEntry
std::unique_ptr<PlugInEntry> _plugInEntry {};
bool _shutDown { false };

class ProxyMessageHandler : public ARA::IPC::ProxyHostMessageHandler
class ProxyHost : public ARA::IPC::ProxyHost, public Connection
{
public:
ProxyHost (const std::string& channelID)
: ARA::IPC::ProxyHost { this },
Connection { this, IPCMessageChannel::createPublishingID (channelID, this) }
{}

void handleReceivedMessage (const ARA::IPC::MessageID messageID,
const ARA::IPC::MessageDecoder* decoder,
ARA::IPC::MessageEncoder* const replyEncoder) override
Expand Down Expand Up @@ -715,23 +736,14 @@ class ProxyMessageHandler : public ARA::IPC::ProxyHostMessageHandler
}
else
{
ARA::IPC::ProxyHostMessageHandler::handleReceivedMessage (messageID, decoder, replyEncoder);
ARA::IPC::ProxyHost::handleReceivedMessage (messageID, decoder, replyEncoder);
}
}

void setMessageChannel (ARA::IPC::MessageChannel* channel)
{
_messageChannel = channel;
}

protected:
ARA::IPC::MessageChannel* getMessageChannel () override
bool runReceiveLoop (int32_t milliseconds)
{
return _messageChannel;
return static_cast<IPCMessageChannel *> (getMainChannel ())->runReceiveLoop (milliseconds);
}

private:
ARA::IPC::MessageChannel * _messageChannel;
};

namespace RemoteHost
Expand All @@ -740,9 +752,7 @@ int main (std::unique_ptr<PlugInEntry> plugInEntry, const std::string& channelID
{
_plugInEntry = std::move (plugInEntry);

ProxyMessageHandler handler;
auto plugInCallbacksChannel { IPCMessageChannel::createPublishingID (channelID, &handler) };
handler.setMessageChannel (plugInCallbacksChannel);
ProxyHost proxy { channelID };

ARA::IPC::ARAIPCProxyHostAddFactory (_plugInEntry->getARAFactory ());
ARA::IPC::ARAIPCProxyHostSetBindingHandler ([] (ARA::IPC::ARAIPCPlugInInstanceRef plugInInstanceRef,
Expand All @@ -757,7 +767,7 @@ int main (std::unique_ptr<PlugInEntry> plugInEntry, const std::string& channelID
});

while (!_shutDown)
plugInCallbacksChannel->runReceiveLoop (100 /*ms*/);
proxy.runReceiveLoop (100 /*ms*/);

_plugInEntry.reset ();

Expand Down
16 changes: 4 additions & 12 deletions TestHost/IPC/IPCMessageChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,17 +306,17 @@ class IPCSendPort
//------------------------------------------------------------------------------


IPCMessageChannel* IPCMessageChannel::createPublishingID (const std::string& channelID, ARA::IPC::MessageHandler* handler)
IPCMessageChannel* IPCMessageChannel::createPublishingID (const std::string& channelID, ARA::IPC::Connection* connection)
{
auto channel { new IPCMessageChannel { handler } };
auto channel { new IPCMessageChannel { connection } };
channel->_sendPort = new IPCSendPort { channelID + ".from_server" };
channel->_receivePort = new IPCReceivePort { channelID + ".to_server", channel };
return channel;
}

IPCMessageChannel* IPCMessageChannel::createConnectedToID (const std::string& channelID, ARA::IPC::MessageHandler* handler)
IPCMessageChannel* IPCMessageChannel::createConnectedToID (const std::string& channelID, ARA::IPC::Connection* connection)
{
auto channel { new IPCMessageChannel { handler } };
auto channel { new IPCMessageChannel { connection } };
channel->_receivePort = new IPCReceivePort { channelID + ".from_server", channel };
channel->_sendPort = new IPCSendPort { channelID + ".to_server" };
return channel;
Expand Down Expand Up @@ -366,11 +366,3 @@ void IPCMessageChannel::loopUntilMessageReceived ()
}
#endif

ARA::IPC::MessageEncoder* IPCMessageChannel::createEncoder ()
{
#if USE_ARA_CF_ENCODING
return new ARA::IPC::CFMessageEncoder {};
#else
return new IPCXMLMessageEncoder {};
#endif
}
10 changes: 2 additions & 8 deletions TestHost/IPC/IPCMessageChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,8 @@ class IPCMessageChannel : public ARA::IPC::MessageChannel
~IPCMessageChannel () override;

// factory functions for send and receive channels
static IPCMessageChannel* createPublishingID (const std::string& channelID, ARA::IPC::MessageHandler* handler);
static IPCMessageChannel* createConnectedToID (const std::string& channelID, ARA::IPC::MessageHandler* handler);

ARA::IPC::MessageEncoder* createEncoder () override;

// \todo currently not implemented, we rely on running on the same machine for now
// C++20 offers std::endian which allows for a simple implementation upon connecting...
bool receiverEndianessMatches () override { return true; }
static IPCMessageChannel* createPublishingID (const std::string& channelID, ARA::IPC::Connection* connection);
static IPCMessageChannel* createConnectedToID (const std::string& channelID, ARA::IPC::Connection* connection);

// message receiving
// waits up to the specified amount of milliseconds for an incoming event and processes it
Expand Down
1 change: 0 additions & 1 deletion TestPlugIn/AudioUnit_v3/Framework/TestAUv3AudioUnit.mm
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ void destroy_sharedFactoryMessageChannel() {
{
ARA::IPC::ARAIPCProxyHostAddFactory(ARATestDocumentController::getARAFactory());
_sharedFactoryMessageChannel = [TestAUv3ARAIPCMessageChannel new];
ARA::IPC::ARAIPCAUProxyHostInitialize(_sharedFactoryMessageChannel);
}

return _sharedFactoryMessageChannel;
Expand Down

0 comments on commit 33eef73

Please sign in to comment.