Network exposure and access

Jamoma 0.6 would provide a way to explore/listen any application's namespace
in order to make transparent for user the fact that an application is local
or over a network.

In the same time the access and the control of the TTObject registers into an
application's namespace would also be possible whatever the application is
local or over a network.

The communication protocole with a distant application would be choosen
among a set of plugins (like OSC, CopperLan or Minuit). Of course, depending
on the choosen protocole, all the features would not be possible.

This topic is separated in two parts : it explains the current implementation
for a local application and then it tries to define some specifications to
make it possible.

Current implementation

for local namespace exploration/listening

For now a C++ Modular developper can only explore/listen the namespace of a local application :


// Look for nodes into the directory giving an address (which can contain wilcard(s))
getDirectoryFrom(this)->Lookup(TT("anAddress"), aNodeList, &aNode);

// Observe any creation or destruction below the attr_name address
getDirectoryFrom(this)->addObserverForNotifications(TT("anAddress"), *newObserver);

// Stop life cycle observation
getDirectoryFrom(this)->removeObserverForNotifications(TT("anAddress"), *oldObserver);

// Look for all nodes under a list of nodes matching a test method
getDirectoryFrom(this)->LookFor(&aNodeList, testNodeObjectType, &arg, returnedNodes, &firstNode);

// Is There
getDirectoryFrom(this)->IsThere(&aNodeList, testNodeMethod, &arg, &isThere, &firstNode);

In those samples of code, getDirectoryFrom(this) is a macro defined in
TTApplication.h file which returns the TTNodeDirectory of the local application :

// Macro to have a direct access to the Directory 
// This macro have to be used on a TTObject with a mApplication member.
#define    getDirectoryFrom(aTTObject) TTApplicationGetDirectory((TTObjectPtr)aTTObject->mApplication)

In order to understand completly how it is implemented for now,
here is the exported TTApplicationGetDirectory method :

TTNodeDirectoryPtr TTApplicationGetDirectory(TTObjectPtr anApplication)
{
    TTValue v;
    TTNodeDirectoryPtr d;

    if (anApplication) {

        d = TTApplicationPtr(anApplication)->mDirectory;

        if (d) return d;
    }

    return NULL;
}

for local TTObject access

For now a C++ Modular developper can only get/set/listen attributes and
send messages to a local TTobject registered into the local namespace :

// get the object from a TTNode
anObject = aNode->getObject();

// Send a message
anObject->sendMessage(TT("messageName"), value);

// Get an attribute value
anObject->getAttributeValue(TT("attributeName"), value);

// Set an attribute value
anObject->setAttributeValue(TT("attributeName"), value);

// Observe an attribute value
anObject->findAttribute(TT("attributeName"), &anAttribute);
anAttribute->registerObserverForNotifications(*newObserver);

Specifications

Considering C++ point of view, we want that all actions described before
are the same for a local and distant application in order to do not deal
with this distinction in TTModular Object developement.

For now all specifications described below are only a sketch.

for local/distant namespace exploration/listening

The problem is that LookUp, LookFor and IsThere returned TTNodePtr or list of TTnodePtr.
For the a local exploration it make sense because the pointer is accessible but it's not true
for a distant exploration. So the idea is to create a mirror namespace for distant application

The TTApplication class :

    TTSymbolPtr        mName
    TTSymbolPtr        mVersion

    TTNodeDirectory     mDirectory

    TTHashPtr         mPluginParameters ///< Hash table <TTSymbolPtr PluginName, HashPtr<TTSymbolPtr parameterName, TTValue parameterValue>>

    TTApplicationManager     mManager

The local TTApplication will have all Plugin parameters for each plugin reception thread configuration.
All distant TTApplications will have one plugin parameter set to configure the sending of messages.
At the end of their creation, distant TTApplications will explore the distant namespace using Discover request
(or load a xml description of it) and will start a continuous listening for any address creation/destruction
using Listen request of the plugin.

The aim of this exploration/listening is to build a mirror of the distant namespace.
Each time an address is created or destroyed, the distant TTapplication calls TTNodeCreate
or TTNodeRemove methods of his internal TTNodeDirectory.

(See next step about the TTObject we have to pass to the TTNodeCreate method)

The TTApplicationManager class :

    TTHashPtr        mApplications
    PluginFactoriesPtr    mFactories
    TTHashPtr        mPlugins;

First of all the TTApplicationManager will load and manage all communication plugins,
scan the network to find distant applications and provide some messages to add/remove/get applications.

The local application is registered into the TTApplicationManager using kTTSym_local symbol
while all other distant applications will be registered using their name.
(the local one is added by TTModular during the initialisation time)

Each TTObject class of TTModular will have a TTApplicationManagerPtr and
the getDirectoryFrom macro will be handled by the TTApplicationManagerPtr to
route to the correct directory :

// Macro to have a direct acces to a local or a distant Directory 
// This macro have to be used on a TTObject with a mApplicationManager member.
#define    getDirectoryFrom(aTTObject, anAddress) TTApplicationManagerGetDirectory((TTObjectPtr)aTTObject->mApplicationManager, anAddress)

TTNodeDirectoryPtr TTApplicationManagerGetDirectory(TTObjectPtr anApplicationManager, TTSymbolPtr anAddress)
{
    TTValue v;
    TTApplicationPtr anApplication;
    TTNodeDirectoryPtr d;
    TTErr err;

    if (anApplicationManager) {

        // TODO : split the address to get the first level
        // Then look into mApplications table to find the right application
        // and return his directory
        // or if it fails returns the directory of local application by default

        err = TTApplicationManagerPtr(anApplicationManager)->mApplications->lookup( firstLevel, &anApplication);

        if (err)
            TTApplicationManagerPtr(anApplicationManager)->mApplications->lookup( kTTSym_local, &anApplication);

        return anApplication->mDirectory
    }

    return NULL;
}

By this way all TTModular object will be able to make the same things on a local or a distant application namespace.

Maybe this would certainly need to change a bit the Plugin interface (Discover and Listen request are they really
adapted for the requests we want to do now ? and why not change while we are breaking everythings ?)

Here are several schemas for each namespace communication between a local and a distant application :

DISCOVER LOCAL NAMESPACE

DISCOVER DISTANT NAMESPACE
This would be automatically done after the creation of the distant application.
The Modular programmer will never call this mecanism himself because it would only
deal with the mirror namespace).

LISTEN LOCAL NAMESPACE

LISTEN DISTANT NAMESPACE
This would be automatically done after the creation of the distant application.
The Modular programmer will never call this mecanism himself because it would only
deal with the mirror namespace).

for local/distant TTObject access

The problem is that a TTNode refers a TTObjectPtr.
For the a local access it make sense because the pointer is accessible but it's not true for a distant exploration.
So the idea is to create and refer into the mirror namespace a TTObject which would be the mirror of the distant TTObject.