diff options
Diffstat (limited to 'arts/runtime/structures_impl.cc')
-rw-r--r-- | arts/runtime/structures_impl.cc | 1421 |
1 files changed, 1421 insertions, 0 deletions
diff --git a/arts/runtime/structures_impl.cc b/arts/runtime/structures_impl.cc new file mode 100644 index 00000000..7c5a5e05 --- /dev/null +++ b/arts/runtime/structures_impl.cc @@ -0,0 +1,1421 @@ +#include "artsbuilder.h" +#include "weakreference.h" +#include "moduleinfo.h" +#include "compatibility.h" +#include "sequenceutils.h" +#include <stdio.h> +#include <iostream> + +using namespace std; +using namespace Arts; + +typedef WeakReference<PortDesc> PortDesc_wref; +typedef WeakReference<ModuleDesc> ModuleDesc_wref; +typedef WeakReference<StructureDesc> StructureDesc_wref; + +class PortDesc_impl :virtual public Arts::PortDesc_skel { +protected: + string _name; + PortType _type; + vector<PortDesc_wref> _connections; + ModuleDesc_wref _parent; + bool _isConnected; + bool _hasValue; + Any _value; + long _ID; + long _oldID; + list<long> oldConnections; + + void removeNullConnections(); + +public: + ~PortDesc_impl(); + + inline PortDesc self() { return PortDesc::_from_base(_copy()); } + void constructor(ModuleDesc parent, const string& name, const PortType& type); + + void disconnectAll(); + long ID(); + ModuleDesc parent(); + string name(); + PortType type(); + bool isConnected(); + bool hasValue(); + void hasValue(bool newvalue); + vector<PortDesc> *connections(); + float floatValue(); + void floatValue( float _new_value ); + + string stringValue(); + void stringValue( const string& _new_value ); + + Any value(); + void value( const Any& _new_value ); + + bool connectTo( PortDesc port ); + void internalConnectInput( PortDesc port ); + void disconnectFrom( PortDesc port ); + + void loadFromList(const vector<string>& list); + vector<string> *saveToList(); + + void internalReConnect( const vector<PortDesc>& allports ); + long internalOldID(); +}; + +class ModuleDesc_impl : virtual public ModuleDesc_skel { +private: + long _ID; + StructureDesc_wref _parent; + string _name; + long _x, _y; + vector<PortDesc> _ports; + long collectPorts( const Arts::ModuleInfo& info ); + + bool _isInterface, _isStructure; + + inline ModuleDesc self() { return ModuleDesc::_from_base(_copy()); } + +public: + long ID(); + StructureDesc parent(); + string name(); + vector<PortDesc> *ports(); + long height(); + long width(); + long x(); + long y(); + bool moveTo( long x, long y ); + void constructor( StructureDesc parent, const ModuleInfo& info ); + + void loadFromList(const vector<string>& list); + vector<string> *saveToList(); + + ~ModuleDesc_impl(); + + bool isInterface(); + bool isStructure(); + Arts::PortDesc findPort(const string& name); +}; + +class StructureDesc_impl : virtual public Arts::StructureDesc_skel { +protected: + bool _valid; + vector<ModuleDesc> _modules; + vector<StructurePortDesc> _ports; /* only structure ports which are part of the interface */ + vector<string> _inheritedInterfaces; + long nextID; + ModuleInfo _externalInterface; + + inline StructureDesc self() { return StructureDesc::_from_base(_copy()); } +public: + string name(); + void name(const string& newName); + + vector<string> *saveToList(); + void loadFromList(const vector<string>& list); + vector<ModuleDesc> *modules(); + vector<StructurePortDesc> *ports(); + vector<string> *inheritedInterfaces(); + + void clear(); + long obtainID(); + long width(); + long height(); + bool valid(); + + ModuleDesc createModuleDesc( const ModuleInfo& info ); + ModuleDesc createModuleDesc( const string& name ); + void freeModuleDesc(ModuleDesc moduledesc); + + // external interface + StructurePortDesc createStructurePortDesc(const PortType& type, const string& name); + void freeStructurePortDesc(StructurePortDesc portdesc); + void moveStructurePortDesc(StructurePortDesc portdesc, long newposition); + + ModuleInfo externalInterface(); + + void addInheritedInterface(const string& iface); + void removeInheritedInterface(const string& iface); + + StructureDesc_impl(); + ~StructureDesc_impl(); +}; + +class StructurePortDesc_impl : + virtual public PortDesc_impl, + virtual public StructurePortDesc_skel +{ +protected: + StructureDesc_wref _parentStructure; + long _x, _y, _position; + string _inheritedInterface; + + inline StructurePortDesc self() { + return StructurePortDesc::_from_base(_copy()); + } +public: + void constructor(StructureDesc parent, const string& name, + const PortType& type); + ~StructurePortDesc_impl(); + + long x(); + long y(); + long position(); + void lowerPosition(); + void raisePosition(); + void rename(const string& newname); + string inheritedInterface(); + void inheritedInterface(const string& iface); + + void internalSetPosition(long position); + StructureDesc parentStructure(); + bool moveTo( long X, long Y ); + + void loadFromList(const vector<string>& list); + vector<string> *saveToList(); +}; + +REGISTER_IMPLEMENTATION(PortDesc_impl); +REGISTER_IMPLEMENTATION(ModuleDesc_impl); +REGISTER_IMPLEMENTATION(StructureDesc_impl); +REGISTER_IMPLEMENTATION(StructurePortDesc_impl); + +/* +#include "structures.h" +*/ +#include "debug.h" +#include <vector> +#include <algorithm> + +#define dname(dir) ((dir)==Arts::input?"input":"output") +#define pstat \ + printf("port name %s, direction %s, id %d\n",_Name.c_str(),dname(_Type.direction),_ID); + +void PortDesc_impl::constructor(ModuleDesc parent, const string& name, + const PortType& type) +{ +#if 0 + if(parent) + { + char * pname = parent->Name(); + describe("PortDesc."+string(pname)+string(".")+name); + } + else + { + describe("PortDesc.Structure."+name); + } +#endif + _name = name; + _type = type; + _parent = parent; + _isConnected = false; + _hasValue = false; + _value.type = _type.dataType; + + if(!parent.isNull()) + { + StructureDesc sd = parent.parent(); + _ID = sd.obtainID(); + } + // else: assume that some smart object which derives from us will set the ID accordingly + // -> for instance StructurePortDesc_impl does so +} + +#if 0 /* PORT */ +void PortDesc_impl::cleanUp() +{ + disconnectAll(); + delete _Connections; +} +#endif + +/* + * This is new and related to weak references, it purges all null references from _connections + */ +void PortDesc_impl::removeNullConnections() +{ + vector<PortDesc_wref>::iterator i = _connections.begin(); + + while(i != _connections.end()) + { + PortDesc pd = *i; + if(pd.isNull()) + { + _connections.erase(i); + i = _connections.begin(); + printf("removeNullConnections() removed something (shouldn't happen)\n"); + } + else i++; + } + + _isConnected = !_connections.empty(); +} + +void PortDesc_impl::disconnectAll() +{ + // disconnect all connected ports + while(!_connections.empty()) + { + PortDesc pd = _connections.front(); + + if(pd.isNull()) // weak references can automatically disappear + _connections.erase(_connections.begin()); + else + pd.disconnectFrom(self()); + } +} + +PortDesc_impl::~PortDesc_impl() +{ +} + +// Implementation for interface PortDesc +long PortDesc_impl::ID() +{ + return _ID; +} + +ModuleDesc PortDesc_impl::parent() +{ + return _parent; +} + +string PortDesc_impl::name() +{ + return _name; +} + +PortType PortDesc_impl::type() +{ + return _type; +} + +bool PortDesc_impl::isConnected() +{ + if(_isConnected) removeNullConnections(); + return _isConnected; +} + +bool PortDesc_impl::hasValue() +{ + return _hasValue; +} + +void PortDesc_impl::hasValue(bool newvalue) +{ + if(_hasValue != newvalue) + { + assert(newvalue == false); + _hasValue = newvalue; + } +} + +vector<PortDesc> *PortDesc_impl::connections() +{ + vector<PortDesc_wref>::iterator i; + vector<PortDesc> *result = new vector<PortDesc>; + + for(i = _connections.begin(); i != _connections.end(); i++) + { + PortDesc pd = *i; + if(!pd.isNull()) result->push_back(pd); + } + return result; +} + +float PortDesc_impl::floatValue() +{ + assert(_hasValue); + assert(_type.dataType == "float"); + + Buffer b; + b.write(_value.value); + return b.readFloat(); +} + +void PortDesc_impl::floatValue( float _new_value ) +{ + assert(!_isConnected); + assert(_type.direction == Arts::input); + assert(_type.dataType == "float"); + assert(_value.type == "float"); + + Buffer b; + b.writeFloat(_new_value); + b.read(_value.value, b.size()); + _hasValue = true; +} + +string PortDesc_impl::stringValue() +{ + assert(_hasValue); + assert(_type.dataType == "string"); + assert(_value.type == "string"); + + string result; + Buffer b; + b.write(_value.value); + b.readString(result); + return result; +} + +void PortDesc_impl::stringValue( const string& _new_value ) +{ + assert(!_isConnected); // shouldn't happen, but check anyway + assert(_type.direction == Arts::input); + assert(_type.dataType == "string"); + + Buffer b; + b.writeString(_new_value); + b.read(_value.value, b.size()); + _hasValue = true; +} + +Any PortDesc_impl::value() +{ + assert(_hasValue); + return _value; +} + +void PortDesc_impl::value( const Any& _new_value ) +{ + _value = _new_value; + _hasValue = true; +} + +bool PortDesc_impl::connectTo( PortDesc port ) +{ + removeNullConnections(); + + // check if we are already connected to that port: + + unsigned long i; + for(i=0;i<_connections.size();i++) + { + PortDesc pd = _connections[i]; + if(pd.ID() == port.ID()) return true; + } + + const PortType& rType = port.type(); + + // only stream or event channels may be connected + if( _type.connType != rType.connType ) + return false; + + // TODO: eventually check conditions when it is legal to connect property + // ports, and when it is insane (_Type.connType == Arts::property) + // + // for incoming structure ports, for instance, it is perfectly allright + + // only same data type connections allowed + if( _type.dataType != rType.dataType ) + return false; + + // only opposite directions + if( _type.direction == rType.direction ) + return false; + + // always first connect the input port to the output port and + // then the other direction + + if( _type.direction == Arts::input ) + { + if(!_isConnected || _type.isMultiPort) + { + assert(_connections.empty() || _type.isMultiPort); + _connections.push_back(port); + + port.internalConnectInput(self()); + + _isConnected = true; + _hasValue = false; + return true; + } + } + if( _type.direction == Arts::output ) + return port.connectTo(self()); + + return false; +} + +void PortDesc_impl::internalConnectInput( PortDesc port ) +{ + _connections.push_back(port); + _isConnected = true; +} + +void PortDesc_impl::disconnectFrom( PortDesc port ) +{ + removeNullConnections(); + + unsigned long found = 0; + + artsdebug("port %ld disconnecting from port %ld\n",ID(),port.ID()); + + vector<PortDesc_wref>::iterator i = _connections.begin(); + while(!found && i != _connections.end()) + { + Arts::PortDesc other = *i; + if(!other.isNull() && other.ID() == port.ID()) + { + _connections.erase(i); + i = _connections.begin(); + found++; + } + else i++; + } + + _isConnected = !_connections.empty(); + + ModuleDesc parent = _parent; + if(parent.isNull()) + artsdebug("_Parent = <some structure>, isConnected = %d\n",_isConnected); + else + artsdebug("_Parent = %s, isConnected = %d\n",parent.name().c_str(),_isConnected); + + if(found) + port.disconnectFrom(self()); +} + +// Implementation for interface ModuleDesc +long ModuleDesc_impl::ID() +{ + return _ID; +} + +StructureDesc ModuleDesc_impl::parent() +{ + return _parent; +} + +string ModuleDesc_impl::name() +{ + return _name; +} + +vector<PortDesc> *ModuleDesc_impl::ports() +{ + return new vector<PortDesc>(_ports); +} + +long ModuleDesc_impl::x() +{ + return _x; +} + +long ModuleDesc_impl::y() +{ + return _y; +} + +long ModuleDesc_impl::width() +{ + assert(false); + return 0; +} + +long ModuleDesc_impl::height() +{ + assert(false); + return 0; +} + + +bool ModuleDesc_impl::moveTo( long x, long y ) +{ + // FIXME: collision checking! + _x = x; + _y = y; + + return(true); +} + + +// Implementation for interface StructureDesc +long StructureDesc_impl::width() +{ + assert(false); + return 0; +} + +long StructureDesc_impl::height() +{ + assert(false); + return 0; +} + +/* + * Query the module for it's paramenters + */ + +void ModuleDesc_impl::constructor( StructureDesc parent, + const Arts::ModuleInfo& info ) +{ + _name = info.name; + _x = -1; // no position assigned + _y = -1; + _ID = parent.obtainID(); + _parent = parent; + _isInterface = info.isInterface; + _isStructure = info.isStructure; + + collectPorts(info); +} + +ModuleDesc_impl::~ModuleDesc_impl() +{ +} + +bool ModuleDesc_impl::isInterface() +{ + return _isInterface; +} + +bool ModuleDesc_impl::isStructure() +{ + return _isStructure; +} + + +PortDesc ModuleDesc_impl::findPort(const string& name) +{ + vector<PortDesc>::iterator p; + + for(p = _ports.begin(); p != _ports.end(); p++) + { + if(name == p->name()) return *p; + } + + return PortDesc::null(); +} + +long ModuleDesc_impl::collectPorts( const Arts::ModuleInfo& info ) +{ + vector<PortType>::const_iterator i; + vector<string>::const_iterator ni = info.portnames.begin(); + long portcount = 0; + + for(i=info.ports.begin(); i != info.ports.end(); i++) + { + const PortType& porttype = *i; + const string& portname = *ni++; + + artsdebug("#%d: %s\n",portcount,portname.c_str()); + + PortDesc pd(self(),portname,porttype); + _ports.push_back(pd); + portcount++; + } + return(portcount); +} + +ModuleDesc StructureDesc_impl::createModuleDesc( const ModuleInfo& info ) +{ + Arts::ModuleDesc result = createModuleDesc(info.name); + + assert(!result.isNull()); + return result; +} + +ModuleDesc StructureDesc_impl::createModuleDesc( const string& name ) +{ + /* FIXME: need new comment + * to create a representation of a specified synth module, we + * + * - create an instance of this synth module by contacting the + * module server and telling him to do so (result is a C++ class) + * + * - create an instance of a ModuleDesc, and tell it to query the + * module for it's parameters (result is a CORBA object) + * + * - destroy the synth module (C++ class) again and return a reference + * to the CORBA object + */ +/* + ModuleServer<SynthModule> *MS_SynthModule; + MS_SynthModule = (ModuleServer<SynthModule> *)SynthModule::get_MS(); + + SynthModule *m = (SynthModule *)MS_SynthModule->getModule(name); +*/ +#if 0 + Arts::ModuleInfo_var info = ModuleBroker->lookupModule(name); + if(!info) return 0; +#endif + const Arts::ModuleInfo& info = makeModuleInfo(name); + Arts::ModuleDesc moduledesc = ModuleDesc(self(),info); + _modules.push_back(moduledesc); + return moduledesc; +} + +void StructureDesc_impl::freeModuleDesc(ModuleDesc moduledesc) +{ + vector<ModuleDesc>::iterator i; + + for(i=_modules.begin();i != _modules.end(); i++) + { + Arts::ModuleDesc current = *i; + + if(current.ID() == moduledesc.ID()) + { + _modules.erase(i); // will get freed automagically + return; + } + } +} + +vector<ModuleDesc> *StructureDesc_impl::modules() +{ + vector<ModuleDesc> *retval = new vector<ModuleDesc>(_modules); + return(retval); +} + +void StructureDesc_impl::addInheritedInterface(const string& iface) +{ + _inheritedInterfaces.push_back(iface); +} + +void StructureDesc_impl::removeInheritedInterface(const string& iface) +{ + vector<string> newII; + vector<string>::iterator ii; + + for(ii = _inheritedInterfaces.begin(); ii != _inheritedInterfaces.end(); ii++) + if(*ii != iface) + newII.push_back(*ii); + + _inheritedInterfaces = newII; +} + +vector<string> *StructureDesc_impl::inheritedInterfaces() +{ + return new vector<string>(_inheritedInterfaces); +} + +StructureDesc_impl::StructureDesc_impl() +{ + arts_debug("PORT: created structuredesc_impl"); + nextID = 0; + _valid = true; + _externalInterface.name = "unknown"; // FIXME + _externalInterface.isStructure = true; + _externalInterface.isInterface = false; +} + +StructureDesc_impl::~StructureDesc_impl() +{ + artsdebug("StructureDesc released...\n"); +} + +long StructureDesc_impl::obtainID() +{ + return(nextID++); +} + +bool StructureDesc_impl::valid() +{ + return(_valid); +} + +void StructureDesc_impl::clear() +{ + _modules.clear(); + _ports.clear(); + _inheritedInterfaces.clear(); + _valid = true; +} + +// "file" management + +vector<string> *PortDesc_impl::saveToList() +{ + vector<string> *list = new vector<string>; + + sqprintf(list,"id=%ld",_ID); + if(_hasValue) + { + if(_type.dataType == "string") + { + sqprintf(list,"string_data=%s",stringValue().c_str()); + } + else if(_type.dataType == "float") + { + sqprintf(list,"audio_data=%2.5f",floatValue()); + } + else + { + Buffer b; + _value.writeType(b); + sqprintf(list,"any_data=%s",b.toString("value").c_str()); + } + } + + if(_isConnected) + { + vector<PortDesc_wref>::iterator i; + + for(i=_connections.begin();i != _connections.end(); i++) + { + Arts::PortDesc port = *i; + if(!port.isNull()) sqprintf(list,"connect_to=%ld",port.ID()); + } + } + return list; +} + +vector<string> *ModuleDesc_impl::saveToList() +{ + vector<string> *list = new vector<string>; + vector<PortDesc>::iterator i; + + sqprintf(list,"id=%ld",_ID); + sqprintf(list,"x=%ld",_x); + sqprintf(list,"y=%ld",_y); + for(i=_ports.begin();i != _ports.end();i++) + { + PortDesc pd = *i; + sqprintf(list,"port=%s",pd.name().c_str()); + + vector<string> *portlist = pd.saveToList(); + addSubStringSeq(list,portlist); + delete portlist; + } + return list; +} + +vector<string> *StructureDesc_impl::saveToList() +{ + vector<string> *list = new vector<string>; + vector<ModuleDesc>::iterator mi; + vector<StructurePortDesc>::iterator pi; + vector<string>::iterator ii; + + sqprintf(list,"name=%s",_externalInterface.name.c_str()); + for(mi=_modules.begin();mi != _modules.end();mi++) + { + ModuleDesc md = *mi; + sqprintf(list,"module=%s",md.name().c_str()); + + vector<string> *modulelist = md.saveToList(); + addSubStringSeq(list,modulelist); + delete modulelist; + } + for(pi=_ports.begin(); pi!=_ports.end(); pi++) + { + Arts::StructurePortDesc spd = *pi; + sqprintf(list,"structureport"); + + vector<string> *portlist= spd.saveToList(); + addSubStringSeq(list,portlist); + delete portlist; + } + for(ii=_inheritedInterfaces.begin(); ii != _inheritedInterfaces.end(); ii++) + sqprintf(list,"interface=%s",ii->c_str()); + + return list; +} + +void PortDesc_impl::internalReConnect( const vector<PortDesc>& allports ) +{ + vector<PortDesc>::const_iterator i; + + for(i=allports.begin(); i != allports.end(); i++) + { + PortDesc pd = (*i); + long oid = pd.internalOldID(); + + if(find(oldConnections.begin(),oldConnections.end(),oid) + != oldConnections.end()) + { + connectTo(pd); + } + } +} + +long PortDesc_impl::internalOldID() +{ + return _oldID; +} + +void PortDesc_impl::loadFromList(const vector<string>& list) +{ + unsigned long i; + string cmd,param; + for(i=0;i<list.size();i++) + { + if(parse_line(list[i],cmd,param)) // otherwise: empty or comment + { + if(cmd == "audio_data") { + floatValue(atof(param.c_str())); + } else if(cmd == "string_data") { + stringValue(param); + } else if(cmd == "any_data") { + Buffer b; + if(b.fromString(param,"value")) + { + Any any; + any.readType(b); + if(!b.readError() && !b.remaining()) + value(any); + } + } else if(cmd == "id") { + _oldID = atol(param.c_str()); + } else if(cmd == "connect_to") { + oldConnections.push_back(atol(param.c_str())); + } + } + } +} + +void ModuleDesc_impl::loadFromList(const vector<string>& list) +{ + artsdebug("mlist-----------\n"); + unsigned long i; + string cmd, param; + for(i=0;i<list.size();i++) + { + if(parse_line(list[i],cmd,param)) // otherwise: empty or comment + { + artsdebug("MD: load-> cmd was %s\n",cmd.c_str()); + if(cmd == "port") + { + string portName = + OldFormatTranslator::newPortName(_name,param); + PortDesc pd = PortDesc::null(); + vector<PortDesc>::iterator pi; + + for(pi=_ports.begin(); pi != _ports.end(); pi++) + { + artsdebug("pdi = %s, portName = %s\n",pi->name().c_str(), + portName.c_str()); + if(pi->name() == portName) pd = *pi; + } + assert(!pd.isNull()); + + vector<string> *plist = getSubStringSeq(&list,i); + pd.loadFromList(*plist); + delete plist; + } else if(cmd == "x") { + _x = atol(param.c_str()); + artsdebug("X set to %ld (param was %s)\n",_x,param.c_str()); + } else if(cmd == "y") { + _y = atol(param.c_str()); + artsdebug("Y set to %ld (param was %s)\n",_y,param.c_str()); + } + } + } + artsdebug("-----------mlist\n"); +} + +void StructureDesc_impl::loadFromList(const vector<string>& list) +{ + string cmd,param; + unsigned long i; + vector<PortDesc> allports; + + clear(); + _externalInterface.name = (const char *)"unknown"; + + artsdebug("loadFromList; listlen = %ld\n",list.size()); + for(i=0;i<list.size();i++) + { + if(parse_line(list[i],cmd,param)) // otherwise: empty or comment + { + artsdebug("SD: load-> cmd was %s\n",cmd.c_str()); + if(cmd == "module") + { + string newName = OldFormatTranslator::newModuleName(param); + ModuleDesc md = createModuleDesc(newName); + + vector<string> *mlist = getSubStringSeq(&list,i); + + if(!md.isNull()) + { + md.loadFromList(*mlist); + + // PORT: order changed + vector<PortDesc> *pd = md.ports(); + vector<PortDesc>::iterator pi; + for(pi = pd->begin(); pi != pd->end();pi++) + allports.push_back(*pi); + + delete pd; + } + else + { + // module couldn't be found + _valid = false; + } + delete mlist; + } + else if(cmd == "name") + { + _externalInterface.name = param; + } + else if(cmd == "interface") + { + _inheritedInterfaces.push_back(param); + } + else if(cmd == "structureport") + { + // just to have valid values to pass to the new (to be loaded) + // port: + PortType type; + type.direction = Arts::input; + type.dataType = "float"; + type.connType = Arts::conn_stream; + type.isMultiPort = false; + + StructurePortDesc spd = + createStructurePortDesc(type,"unknown"); + + vector<string> *splist = getSubStringSeq(&list,i); + spd.loadFromList(*splist); + delete splist; + + // yes; this is a port as well + allports.push_back(spd); + } + } + } + + for(i=0;i<allports.size();i++) + allports[i].internalReConnect(allports); +} + +void StructureDesc_impl::name(const string& name) +{ + _externalInterface.name = name; +} + +string StructureDesc_impl::name() +{ + return _externalInterface.name; +} + +long extint_pscore(StructurePortDesc p) +{ + long result = p.position(); //p->X()*1000+p->Y(); + if(p.type().direction == Arts::input) result += 5000000; + + return result; +} + +bool extint_port_compare(StructurePortDesc p1, StructurePortDesc p2) +{ + long p1s = extint_pscore(p1); + long p2s = extint_pscore(p2); + + artsdebug("compare; [%s] = %d ; [%s] = %d\n", p1.name().c_str(),p1s, + p2.name().c_str(),p2s); + return (p1s < p2s); +// return -1; + //if(p1s == p2s) return 0; + //return 1; +} + +ModuleInfo StructureDesc_impl::externalInterface() +{ + ModuleInfo result = _externalInterface; + vector<StructurePortDesc> sorted_ports = _ports; + vector<StructurePortDesc>::iterator p; + unsigned long l; +/* PORT: + for(l=0;l<_Ports->length();l++) sorted_ports.push_back((*_Ports)[l]); +*/ + sort(sorted_ports.begin(),sorted_ports.end(),extint_port_compare); + + l = 0; + for(p=sorted_ports.begin();p != sorted_ports.end();p++) + { + string pname = p->name(); + PortType ptype = p->type(); + + if(ptype.direction == Arts::input) + ptype.direction = Arts::output; + else + ptype.direction = Arts::input; + + artsdebug("externalInterface; sorted ports: %d => %s\n",l,pname.c_str()); + result.ports.push_back(ptype); + result.portnames.push_back(pname); + l++; + } + return result; +} + +vector<StructurePortDesc> *StructureDesc_impl::ports() +{ + return new vector<StructurePortDesc>(_ports); +} + +StructurePortDesc StructureDesc_impl::createStructurePortDesc( + const Arts::PortType& type, const string& name) +{ + artsdebug("creating new port %s\n",name.c_str()); + StructurePortDesc port(self(), name, type); + _ports.push_back(port); + + // set the Position (put it at the end of the ports) + unsigned long i, count = 0; + for(i=0;i<_ports.size();i++) + { + if(_ports[i].type().direction == type.direction) count++; + } + assert(count > 0); // we just inserted one ;) + port.internalSetPosition(count-1); + return port; +} + +void StructureDesc_impl::freeStructurePortDesc(StructurePortDesc portdesc) +{ + vector<StructurePortDesc>::iterator i; + + for(i=_ports.begin(); i != _ports.end(); i++) + { + if(i->ID() == portdesc.ID()) + { + _ports.erase(i); + return; + } + } +} + +void StructureDesc_impl::moveStructurePortDesc(StructurePortDesc + portdesc, long newposition) +{ + const Arts::PortType& type = portdesc.type(); + + unsigned long i; + long count = 0; + for(i=0;i<_ports.size();i++) + { + if(_ports[i].type().direction == type.direction) count++; + } + + if(newposition < 0) newposition = 0; + if(newposition > count-1) newposition = count-1; + + if(newposition == portdesc.position()) return; + + int delta, lower, upper; + + if(newposition > portdesc.position()) + { + // if the port gets a higher position, move all ports that + // are between it's current position and its new position down one + lower = portdesc.position(); + upper = newposition; + delta = -1; + } + else + { + // if the port gets a lower position, move all ports that + // are between it's current position and its new position up one + lower = newposition; + upper = portdesc.position(); + delta = 1; + } + + for(i=0;i<_ports.size();i++) + { + StructurePortDesc pd = _ports[i]; + + if(pd.type().direction == type.direction) + { + if(pd.ID() != portdesc.ID() && + pd.position() >= lower && pd.position() <= upper) + { + pd.internalSetPosition(pd.position()+delta); + } + } + + } + portdesc.internalSetPosition(newposition); +} + +void StructurePortDesc_impl::constructor(StructureDesc parent, + const string& name, const PortType& type) +{ + PortDesc_impl::constructor(ModuleDesc::null(),name,type); + _parentStructure = parent; + _ID = parent.obtainID(); + _x = 0; + _y = 0; + _position = 0; +} + +StructurePortDesc_impl::~StructurePortDesc_impl() +{ + // this destructor is required to make some compilers (egcs-1.1.2) compile +} + +long StructurePortDesc_impl::x() +{ + return _x; +} + +long StructurePortDesc_impl::y() +{ + return _y; +} + +long StructurePortDesc_impl::position() +{ + return _position; +} + +void StructurePortDesc_impl::lowerPosition() +{ + StructureDesc parent = _parentStructure; // weak reference + + if(!parent.isNull()) + parent.moveStructurePortDesc(self(), _position-1); +} + +void StructurePortDesc_impl::raisePosition() +{ + StructureDesc parent = _parentStructure; // weak reference + + if(!parent.isNull()) + parent.moveStructurePortDesc(self(), _position+1); +} + +void StructurePortDesc_impl::rename(const string& newname) +{ + _name = newname; +} + +void StructurePortDesc_impl::inheritedInterface(const string& iface) +{ + _inheritedInterface = iface; +} + +string StructurePortDesc_impl::inheritedInterface() +{ + return _inheritedInterface; +} + +// only used by the structure to reorder the ports +void StructurePortDesc_impl::internalSetPosition(long position) +{ + _position = position; +} + +StructureDesc StructurePortDesc_impl::parentStructure() +{ + return _parentStructure; +} + +bool StructurePortDesc_impl::moveTo( long X, long Y ) +{ + // FIXME: check space + _x = X; + _y = Y; + + return true; +} + +/* + override load & save behaviour this kind of port requires that we save the type + of the port as well, that means all of the porttype: + + enum PortDirection {input, output}; + enum PortDataType {audio_data, string_data}; + enum PortConnType {stream, event, property}; + struct PortType { + PortDirection direction; + PortDataType dataType; + PortConnType connType; + }; + + so when saved, it will look like that: + + { + name=fasel + x=4 + y=2 + type + { + direction=input/output + datatype=audio/string + conntype=stream/event/property + } + data + { + [original port saves here] + } + } +*/ + +PortType loadTypeFromList(const vector<string>& list) +{ + unsigned long i,loadstate = 0; + string cmd,param; + Arts::PortType result; + + for(i=0;i<list.size();i++) + { + if(parse_line(list[i],cmd,param)) // otherwise: empty or comment + { + artsdebug("PortType: load-> cmd was %s\n",cmd.c_str()); + if(cmd == "direction") + { + if(param == "input") { + result.direction = Arts::input; + } + else if(param == "output") { + result.direction = Arts::output; + } + else assert(false); + + loadstate += 1; + } else if(cmd == "datatype") { + if(param == "audio") { + result.dataType = "float"; + } + else if(param == "string") { + result.dataType = "string"; + } + else assert(false); + + loadstate += 100; + } else if(cmd == "conntype") { + if(param == "stream") { + result.connType = Arts::conn_stream; + } + else if(param == "event") { + result.connType = Arts::conn_event; + } + else if(param == "property") { + result.connType = Arts::conn_property; + artsdebug("got property stuff\n"); + } + else assert(false); + + loadstate += 10000; + } + } + } + assert(loadstate == 10101); // should see every member exactly once + result.isMultiPort = false; + return result; +} + +void StructurePortDesc_impl::loadFromList(const vector<string>& list) +{ + artsdebug("structureportlist-----------\n"); + unsigned long i; + string cmd,param; + vector<string> *typelist = 0, *datalist = 0; + bool haveType = false, haveData = false; + // need both to do restore, type first + + for(i=0;i<list.size();i++) + { + if(parse_line(list[i],cmd,param)) // otherwise: empty or comment + { + artsdebug("StructurePortDesc: load-> cmd was %s\n",cmd.c_str()); + if(cmd == "type") + { + assert(!haveType); // only allowed once + haveType = true; + typelist = getSubStringSeq(&list,i); + } else if(cmd == "data") { + assert(!haveData); // only allowed once + haveData = true; + datalist = getSubStringSeq(&list,i); + } else if(cmd == "x") { + _x = atol(param.c_str()); + artsdebug("X set to %ld (param was %s)\n",_x,param.c_str()); + } else if(cmd == "y") { + _y = atol(param.c_str()); + artsdebug("Y set to %ld (param was %s)\n",_y,param.c_str()); + } else if(cmd == "position") { + _position = atol(param.c_str()); + artsdebug("Position set to %ld (param was %s)\n",_position, + param.c_str()); + } else if(cmd == "name") { + _name = param; + artsdebug("Name set to %s\n",_name.c_str()); + } else if(cmd == "interface") { + _inheritedInterface = param; + artsdebug("Interface set to %s\n",_inheritedInterface.c_str()); + } + } + } + assert(haveType && haveData); + + _type = loadTypeFromList(*typelist); + + if(_type.connType == Arts::conn_property) artsdebug("have property here\n"); + PortDesc_impl::loadFromList(*datalist); + + delete typelist; + delete datalist; + artsdebug("-----------structureportlist\n"); +} + +vector<string> *saveTypeToList(const PortType& type) +{ + vector<string> *list = new vector<string>; + + switch(type.direction) + { + case Arts::input: sqprintf(list,"direction=input"); + break; + case Arts::output: sqprintf(list,"direction=output"); + break; + default: assert(false); // should never happen! + } + if(type.dataType == "float") + { + sqprintf(list,"datatype=audio"); + } + else if(type.dataType == "string") + { + sqprintf(list,"datatype=string"); + } + else + { + assert(false); // should never happen! + } + switch(type.connType) + { + case Arts::conn_stream: sqprintf(list,"conntype=stream"); + break; + case Arts::conn_event: sqprintf(list,"conntype=event"); + break; + case Arts::conn_property: sqprintf(list,"conntype=property"); + break; + default: assert(false); // should never happen! + } + + return list; +} + +vector<string> *StructurePortDesc_impl::saveToList() +{ + vector<string> *list = new vector<string>; + sqprintf(list,"name=%s",_name.c_str()); + sqprintf(list,"x=%ld",_x); + sqprintf(list,"y=%ld",_y); + sqprintf(list,"position=%ld",_position); + + if(!_inheritedInterface.empty()) + sqprintf(list, "interface=%s",_inheritedInterface.c_str()); + + sqprintf(list,"type"); + + vector<string> *typelist = saveTypeToList(_type); + addSubStringSeq(list,typelist); + delete typelist; + + sqprintf(list,"data"); + + vector<string> *portlist = PortDesc_impl::saveToList(); + addSubStringSeq(list,portlist); + delete portlist; + + return list; +} |