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/structures_impl.cpp

1422 lines
30 KiB

#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;
}