You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
348 lines
9.0 KiB
348 lines
9.0 KiB
15 years ago
|
/*
|
||
|
|
||
|
Copyright (C) 2000,2001 Stefan Westerfeld
|
||
|
stefan@space.twc.de
|
||
|
|
||
|
This library is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU Library General Public
|
||
|
License as published by the Free Software Foundation; either
|
||
|
version 2 of the License, or (at your option) any later version.
|
||
|
|
||
|
This library is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
Library General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU Library General Public License
|
||
|
along with this library; see the file COPYING.LIB. If not, write to
|
||
15 years ago
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||
|
Boston, MA 02110-1301, USA.
|
||
15 years ago
|
|
||
|
*/
|
||
|
|
||
|
#include "artsbuilder.h"
|
||
|
#include "artsflow.h"
|
||
|
#include "connect.h"
|
||
|
#include "debug.h"
|
||
|
#include "flowsystem.h"
|
||
|
#include "stdsynthmodule.h"
|
||
|
#include "dynamicrequest.h"
|
||
|
#include "dynamicskeleton.h"
|
||
|
#include "startupmanager.h"
|
||
|
#include <list>
|
||
|
|
||
|
//#define STRUCTBUILDER_DEBUG 1
|
||
|
|
||
|
using namespace Arts;
|
||
|
using namespace std;
|
||
|
|
||
|
class StructureBuilder_impl : virtual public StructureBuilder_skel {
|
||
|
protected:
|
||
|
list<ObjectFactory> factories;
|
||
|
public:
|
||
|
void addFactory(ObjectFactory factory);
|
||
|
Object createObject(StructureDesc structure);
|
||
|
ModuleDef createTypeInfo(StructureDesc structure);
|
||
|
};
|
||
|
|
||
|
REGISTER_IMPLEMENTATION(StructureBuilder_impl);
|
||
|
|
||
|
typedef DynamicSkeleton<SynthModule_skel> SynthModule_dskel;
|
||
|
|
||
|
class Structure_impl : virtual public SynthModule_dskel,
|
||
|
virtual public StdSynthModule {
|
||
|
protected:
|
||
|
list<Object> structureObjects;
|
||
|
|
||
|
struct ForwardMethod {
|
||
|
string method;
|
||
|
Object destObject;
|
||
|
string destMethod;
|
||
|
};
|
||
|
|
||
|
list<ForwardMethod> forwardMethods;
|
||
|
|
||
|
public:
|
||
|
Structure_impl(StructureDesc structure, list<ObjectFactory>& factories);
|
||
|
void streamInit();
|
||
|
void streamEnd();
|
||
|
|
||
|
void process(long methodID, Buffer *request, Buffer *result);
|
||
|
};
|
||
|
|
||
|
void StructureBuilder_impl::addFactory(ObjectFactory factory)
|
||
|
{
|
||
|
factories.push_back(factory);
|
||
|
}
|
||
|
|
||
|
ModuleDef StructureBuilder_impl::createTypeInfo(StructureDesc structure)
|
||
|
{
|
||
|
ModuleDef md;
|
||
|
InterfaceDef id;
|
||
|
|
||
|
/* convert structure to InterfaceDef id */
|
||
|
md.moduleName = id.name = structure.name();
|
||
|
id.inheritedInterfaces.push_back("Arts::SynthModule");
|
||
|
|
||
|
vector<string> *otherInterfaces = structure.inheritedInterfaces();
|
||
|
vector<string>::iterator ii;
|
||
|
for(ii = otherInterfaces->begin(); ii != otherInterfaces->end(); ii++)
|
||
|
id.inheritedInterfaces.push_back(*ii);
|
||
|
delete otherInterfaces;
|
||
|
|
||
|
vector<StructurePortDesc> *ports = structure.ports();
|
||
|
vector<StructurePortDesc>::iterator pi;
|
||
|
for(pi = ports->begin(); pi != ports->end(); pi++)
|
||
|
{
|
||
|
const Arts::PortType& type = pi->type();
|
||
|
|
||
13 years ago
|
// if we inherited the port from a parent interface, we don't need to
|
||
15 years ago
|
// list it in our interface description
|
||
|
if(pi->inheritedInterface().empty())
|
||
|
{
|
||
|
AttributeDef ad;
|
||
|
ad.name = pi->name();
|
||
|
|
||
|
// This is a little tricky, as input ports (which are bringing data
|
||
|
// from outside into the structure) are saved as output ports (and
|
||
|
// output ports as input ports).
|
||
|
ad.flags = AttributeType(
|
||
|
((type.direction == input)?streamOut:streamIn) |
|
||
|
((type.connType == conn_stream)?attributeStream:attributeAttribute)
|
||
|
);
|
||
|
ad.type = type.dataType;
|
||
|
|
||
|
id.attributes.push_back(ad);
|
||
|
}
|
||
|
}
|
||
|
delete ports;
|
||
|
|
||
|
md.interfaces.push_back(id);
|
||
|
|
||
|
return md;
|
||
|
}
|
||
|
|
||
|
namespace Arts {
|
||
|
static class StructureBuilderCleanUp : public StartupClass {
|
||
|
public:
|
||
|
vector<long> types;
|
||
|
void startup() { };
|
||
|
void shutdown() {
|
||
|
vector<long>::iterator i;
|
||
|
for(i = types.begin(); i != types.end(); i++)
|
||
|
Dispatcher::the()->interfaceRepo().removeModule(*i);
|
||
|
types.clear();
|
||
|
}
|
||
|
virtual ~StructureBuilderCleanUp() {}
|
||
|
} structureBuilderCleanUp;
|
||
|
}
|
||
|
|
||
|
Object StructureBuilder_impl::createObject(StructureDesc structure)
|
||
|
{
|
||
|
ModuleDef md = createTypeInfo(structure);
|
||
|
|
||
|
// FIXME: find some faster way of ensuring type consistency than creating
|
||
|
// the thing from scratch every time
|
||
|
structureBuilderCleanUp.types.push_back(Dispatcher::the()->interfaceRepo().insertModule(md));
|
||
|
Object obj = Object::_from_base(new Structure_impl(structure, factories));
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
Structure_impl::Structure_impl(StructureDesc structureDesc,
|
||
|
list<ObjectFactory>& factories)
|
||
|
: SynthModule_dskel(structureDesc.name())
|
||
|
{
|
||
|
map<long, Object> moduleMap;
|
||
|
vector<ModuleDesc> *modules = structureDesc.modules();
|
||
|
vector<ModuleDesc>::iterator mi;
|
||
|
|
||
|
// create each object
|
||
|
for(mi = modules->begin(); mi != modules->end(); mi++)
|
||
|
{
|
||
|
ModuleDesc& md = *mi;
|
||
|
|
||
|
#ifdef STRUCTBUILDER_DEBUG
|
||
|
cout << "create " << md.name() << endl;
|
||
|
#endif
|
||
|
Object o = Object::null(); //SubClass(md.name());
|
||
|
|
||
|
Object_skel *skel = 0;
|
||
|
skel = ObjectManager::the()->create(md.name());
|
||
|
if(skel) o = Object::_from_base(skel);
|
||
|
|
||
|
#ifdef STRUCTBUILDER_DEBUG
|
||
|
if(o.isNull()) cout << "no local creator for " << md.name() << endl;
|
||
|
#endif
|
||
|
list<ObjectFactory>::iterator fi = factories.begin();
|
||
|
while(o.isNull() && fi != factories.end())
|
||
|
{
|
||
|
o = fi->createObject(md.name());
|
||
|
fi++;
|
||
|
}
|
||
|
|
||
|
#ifdef STRUCTBUILDER_DEBUG
|
||
|
if(o.isNull()) cout << "no remote creator for " << md.name() << endl;
|
||
|
#endif
|
||
|
assert(!o.isNull());
|
||
|
moduleMap[md.ID()] = o;
|
||
|
structureObjects.push_back(o);
|
||
|
}
|
||
|
|
||
|
// connect objects and set values
|
||
|
for(mi = modules->begin(); mi != modules->end(); mi++)
|
||
|
{
|
||
|
Object& object = moduleMap[mi->ID()];
|
||
|
|
||
|
vector<PortDesc> *ports = mi->ports();
|
||
|
vector<PortDesc>::iterator pi;
|
||
|
|
||
|
for(pi = ports->begin(); pi != ports->end(); pi++)
|
||
|
{
|
||
|
PortDesc& pd = *pi;
|
||
|
const Arts::PortType& ptype = pd.type();
|
||
|
|
||
|
if(pd.hasValue())
|
||
|
{
|
||
|
// set values
|
||
|
#ifdef STRUCTBUILDER_DEBUG
|
||
|
cout << "value " << mi->name() << "." << pi->name() << endl;
|
||
|
#endif
|
||
|
|
||
|
if(ptype.connType == conn_property)
|
||
|
{
|
||
|
DynamicRequest req(object);
|
||
|
req.method("_set_"+pi->name());
|
||
|
req.param(pd.value());
|
||
|
|
||
|
bool requestOk = req.invoke();
|
||
|
arts_assert(requestOk);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(ptype.dataType == "float")
|
||
|
setValue(object,pi->name(),pd.floatValue());
|
||
|
else
|
||
|
arts_warning("unexpected property type %s",
|
||
|
ptype.dataType.c_str());
|
||
|
//setStringValue(object,pd.stringValue());
|
||
|
}
|
||
|
}
|
||
|
else if(pd.isConnected() && ptype.direction == output)
|
||
|
{
|
||
|
// create connections
|
||
|
|
||
|
vector<PortDesc> *connections = pd.connections();
|
||
|
vector<PortDesc>::iterator ci;
|
||
|
|
||
|
for(ci = connections->begin(); ci != connections->end(); ci++)
|
||
|
{
|
||
13 years ago
|
if(!ci->parent().isNull()) // structureport otherwise
|
||
15 years ago
|
{
|
||
13 years ago
|
Object& dest = moduleMap[ci->parent().ID()];
|
||
15 years ago
|
#ifdef STRUCTBUILDER_DEBUG
|
||
|
cout << "connect " << mi->name() << "." << pi->name()
|
||
13 years ago
|
<< " to " << ci->parent().name()
|
||
15 years ago
|
<< "." << ci->name() << endl;
|
||
|
#endif
|
||
|
connect(object,pd.name(),dest,ci->name());
|
||
|
}
|
||
|
}
|
||
|
delete connections;
|
||
|
}
|
||
|
}
|
||
|
delete ports;
|
||
|
}
|
||
|
delete modules;
|
||
|
|
||
|
// create ports (should be done via dynamic impl class...)
|
||
|
|
||
|
vector<StructurePortDesc> *ports = structureDesc.ports();
|
||
|
vector<StructurePortDesc>::iterator pi;
|
||
|
|
||
|
for(pi = ports->begin(); pi != ports->end(); pi++)
|
||
|
{
|
||
|
Arts::StructurePortDesc& pd = *pi;
|
||
|
if(pd.isConnected())
|
||
|
{
|
||
|
// create connections
|
||
|
|
||
|
vector<PortDesc> *connections = pd.connections();
|
||
|
vector<PortDesc>::iterator ci;
|
||
|
|
||
|
for(ci = connections->begin(); ci != connections->end(); ci++)
|
||
|
{
|
||
13 years ago
|
Object& dest = moduleMap[ci->parent().ID()];
|
||
15 years ago
|
#ifdef STRUCTBUILDER_DEBUG
|
||
|
cout << "virtualize " << pi->name()
|
||
13 years ago
|
<< " to " << ci->parent().name() << "." << ci->name()
|
||
15 years ago
|
<< endl;
|
||
|
#endif
|
||
|
|
||
|
_node()->virtualize(pd.name(),dest._node(),ci->name());
|
||
|
|
||
|
if(pd.type().connType == conn_property)
|
||
|
{
|
||
|
ForwardMethod fm;
|
||
|
fm.method = "_set_"+pd.name();
|
||
|
fm.destObject = dest;
|
||
|
fm.destMethod = "_set_"+ci->name();
|
||
|
forwardMethods.push_back(fm);
|
||
|
}
|
||
|
}
|
||
|
delete connections;
|
||
|
}
|
||
|
}
|
||
|
delete ports;
|
||
|
}
|
||
|
|
||
|
void Structure_impl::streamInit()
|
||
|
{
|
||
|
list<Object>::iterator i;
|
||
|
|
||
|
#ifdef STRUCTBUILDER_DEBUG
|
||
|
cout << "vstructure: got streamInit()" << endl;
|
||
|
#endif
|
||
|
|
||
|
for(i=structureObjects.begin(); i != structureObjects.end(); i++)
|
||
|
{
|
||
|
if(i->_base()->_isCompatibleWith("Arts::SynthModule"))
|
||
|
i->_node()->start();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Structure_impl::streamEnd()
|
||
|
{
|
||
|
list<Object>::iterator i;
|
||
|
|
||
|
#ifdef STRUCTBUILDER_DEBUG
|
||
|
cout << "vstructure: got streamEnd()" << endl;
|
||
|
#endif
|
||
|
|
||
|
for(i=structureObjects.begin(); i != structureObjects.end(); i++)
|
||
|
if(i->_base()->_isCompatibleWith("Arts::SynthModule"))
|
||
|
i->_node()->stop();
|
||
|
}
|
||
|
|
||
|
void Structure_impl::process(long methodID, Buffer *request, Buffer *result)
|
||
|
{
|
||
|
const MethodDef& methodDef = getMethodDef(methodID);
|
||
|
|
||
|
arts_debug("Structure_impl: got method, method ID=%ld name='%s'",
|
||
|
methodID, methodDef.name.c_str());
|
||
|
|
||
|
list<ForwardMethod>::iterator fi;
|
||
|
for(fi = forwardMethods.begin(); fi != forwardMethods.end(); fi++)
|
||
|
{
|
||
|
if(fi->method == methodDef.name)
|
||
|
{
|
||
|
Any a;
|
||
|
a.type = methodDef.signature[0].type;
|
||
|
|
||
|
while(request->remaining() > 0)
|
||
|
a.value.push_back(request->readByte());
|
||
|
|
||
|
DynamicRequest(fi->destObject).method(fi->destMethod).param(a).invoke();
|
||
|
}
|
||
|
}
|
||
|
}
|