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.
tdemultimedia/arts/runtime/structurebuilder_impl.cc

348 lines
9.0 KiB

/*
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();
}
}
}