diff options
Diffstat (limited to 'arts/runtime/structurebuilder_impl.cpp')
-rw-r--r-- | arts/runtime/structurebuilder_impl.cpp | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/arts/runtime/structurebuilder_impl.cpp b/arts/runtime/structurebuilder_impl.cpp new file mode 100644 index 00000000..43e5485c --- /dev/null +++ b/arts/runtime/structurebuilder_impl.cpp @@ -0,0 +1,347 @@ + /* + + 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 + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#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(); + + // if we inherited the port from a parent interface, we don't need to + // 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++) + { + if(!ci->parent().isNull()) // structureport otherwise + { + Object& dest = moduleMap[ci->parent().ID()]; +#ifdef STRUCTBUILDER_DEBUG + cout << "connect " << mi->name() << "." << pi->name() + << " to " << ci->parent().name() + << "." << 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++) + { + Object& dest = moduleMap[ci->parent().ID()]; +#ifdef STRUCTBUILDER_DEBUG + cout << "virtualize " << pi->name() + << " to " << ci->parent().name() << "." << ci->name() + << 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(); + } + } +} |