diff options
Diffstat (limited to 'arts/runtime')
-rw-r--r-- | arts/runtime/ArtsBuilderLoader.mcopclass | 4 | ||||
-rw-r--r-- | arts/runtime/LocalFactory.mcopclass | 3 | ||||
-rw-r--r-- | arts/runtime/Makefile.am | 38 | ||||
-rw-r--r-- | arts/runtime/StructureBuilder.mcopclass | 3 | ||||
-rw-r--r-- | arts/runtime/StructureDesc.mcopclass | 3 | ||||
-rw-r--r-- | arts/runtime/artsbuilder.idl | 228 | ||||
-rw-r--r-- | arts/runtime/artsbuilderloader_impl.cc | 285 | ||||
-rw-r--r-- | arts/runtime/compatibility.cc | 56 | ||||
-rw-r--r-- | arts/runtime/compatibility.h | 36 | ||||
-rw-r--r-- | arts/runtime/localfactory_impl.cc | 15 | ||||
-rw-r--r-- | arts/runtime/moduleinfo.cc | 106 | ||||
-rw-r--r-- | arts/runtime/moduleinfo.h | 33 | ||||
-rw-r--r-- | arts/runtime/sequenceutils.cc | 188 | ||||
-rw-r--r-- | arts/runtime/sequenceutils.h | 41 | ||||
-rw-r--r-- | arts/runtime/structurebuilder_impl.cc | 347 | ||||
-rw-r--r-- | arts/runtime/structures_impl.cc | 1421 |
16 files changed, 2807 insertions, 0 deletions
diff --git a/arts/runtime/ArtsBuilderLoader.mcopclass b/arts/runtime/ArtsBuilderLoader.mcopclass new file mode 100644 index 00000000..cceb4765 --- /dev/null +++ b/arts/runtime/ArtsBuilderLoader.mcopclass @@ -0,0 +1,4 @@ +Interface=Arts::ArtsBuilderLoader,Arts::Loader,Arts::Object +LoadLanguage=aRts +Language=C++ +Library=libartsbuilder.la diff --git a/arts/runtime/LocalFactory.mcopclass b/arts/runtime/LocalFactory.mcopclass new file mode 100644 index 00000000..e35f778b --- /dev/null +++ b/arts/runtime/LocalFactory.mcopclass @@ -0,0 +1,3 @@ +Interface=Arts::LocalFactory,Arts::ObjectFactory,Arts::Object +Language=C++ +Library=libartsbuilder.la diff --git a/arts/runtime/Makefile.am b/arts/runtime/Makefile.am new file mode 100644 index 00000000..b10abe7a --- /dev/null +++ b/arts/runtime/Makefile.am @@ -0,0 +1,38 @@ +####### Runtime part of artsbuilder: this part will get dynamically loaded +# into the aRts server (or other apps) to create structures which are designed +# in artsbuilder. So to speak it's the "loader for the .arts language". + +AM_CXXFLAGS = -DEXAMPLES_DIR='"$(arts_datadir)/artsbuilder/examples"' +INCLUDES= -I$(arts_includes) $(all_includes) + +lib_LTLIBRARIES = libartsbuilder.la + +libartsbuilder_la_SOURCES = artsbuilder.cc sequenceutils.cc \ + structurebuilder_impl.cc structures_impl.cc moduleinfo.cc \ + compatibility.cc localfactory_impl.cc artsbuilderloader_impl.cc + +libartsbuilder_la_LIBADD = -lmcop -lartsflow $(LIBDL) +libartsbuilder_la_COMPILE_FIRST = artsbuilder.h +libartsbuilder_la_LDFLAGS = $(all_libraries) -L$(arts_libraries) \ + -no-undefined + +artsbuilder.lo: artsbuilder.h +artsbuilder.mcopclass: artsbuilder.h +artsbuilder.mcoptype: artsbuilder.h +artsbuilder.h artsbuilder.cc: $(srcdir)/artsbuilder.idl $(MCOPIDL) + $(MCOPIDL) -t -I$(arts_includes) $(srcdir)/artsbuilder.idl + +DISTCLEANFILES = artsbuilder.cc artsbuilder.h \ + artsbuilder.mcoptype artsbuilder.mcopclass + +####### install idl files + +artsincludedir = $(includedir)/arts +artsinclude_HEADERS = artsbuilder.h artsbuilder.idl + +mcopclassdir = $(libdir)/mcop/Arts +mcopclass_DATA = StructureBuilder.mcopclass StructureDesc.mcopclass \ + LocalFactory.mcopclass ArtsBuilderLoader.mcopclass + +mcoptypedir = $(libdir)/mcop +mcoptype_DATA = artsbuilder.mcoptype artsbuilder.mcopclass diff --git a/arts/runtime/StructureBuilder.mcopclass b/arts/runtime/StructureBuilder.mcopclass new file mode 100644 index 00000000..5ea71358 --- /dev/null +++ b/arts/runtime/StructureBuilder.mcopclass @@ -0,0 +1,3 @@ +Interface=Arts::StructureBuilder,Arts::Object +Language=C++ +Library=libartsbuilder.la diff --git a/arts/runtime/StructureDesc.mcopclass b/arts/runtime/StructureDesc.mcopclass new file mode 100644 index 00000000..3a7039e0 --- /dev/null +++ b/arts/runtime/StructureDesc.mcopclass @@ -0,0 +1,3 @@ +Interface=Arts::StructureDesc,Arts::Object +Language=C++ +Library=libartsbuilder.la diff --git a/arts/runtime/artsbuilder.idl b/arts/runtime/artsbuilder.idl new file mode 100644 index 00000000..42ff393a --- /dev/null +++ b/arts/runtime/artsbuilder.idl @@ -0,0 +1,228 @@ +/* + * DISCLAIMER: The interfaces in artsbuilder.idl (and the derived .cc/.h files) + * DO NOT GUARANTEE BINARY COMPATIBILITY YET. + * + * They are intended for developers. You shouldn't expect that applications in + * binary form will be fully compatibile with further releases of these + * interfaces. + */ + +#include <core.idl> +#include <artsflow.idl> +module Arts { + /* + * incoming or outgoing port? + */ + enum PortDirection {input, output}; + + /** + * ConnType (maybe obsolete) + * + * ConnType: (connection type) this is wether this value is used + * + * - once (such as a filename of a waveplugin) -> property + * this implies that the allowed connection is only value + * + * - event based (such as midi events) -> event + * when events arrive, they are processed, when no events arrive, + * don't care + * + * - stream based (such as audio streams) -> stream + * every calculation of the module consumes/creates a sample + * that means: no data = no calculation possible + * + * WARNING: This is part of the artsbuilder dynamic programming interface + * as the MCOP port isn't there yet, this stuff may change + */ + enum PortConnType { conn_stream, conn_event, conn_property}; + + /** + * PortType (maybe obsolete) + * + * isMultiPort specifies if the port can take multiple incoming + * connections or not. This is only relevant/allowed for input ports, + * the output of all output ports may be connected to any amount of + * receivers. + * + * Ports which can take multiple connections are handled differently + * internally. (Also, artsbuilder needs to know whether to allow multi- + * connections or not). + * + * WARNING: This is part of the artsbuilder dynamic programming interface + * as the MCOP port isn't there yet, this stuff may change + */ + struct PortType { + PortDirection direction; + string dataType; + PortConnType connType; + boolean isMultiPort; + }; + + struct ModuleInfo { + string name; + + //--- internal information: + // ports, first the input ports, then the output ports + sequence<PortType> ports; + sequence<string> portnames; + boolean isInterface; + boolean isStructure; + }; + + interface PortDesc; + interface ModuleDesc; + interface StructureDesc; + interface StructurePortDesc; + + interface PortDesc { + // internal: + void constructor(ModuleDesc parent, string name, PortType type); + + // ID is guaranteed to be unique in the structure the port belongs to + readonly attribute long ID; + readonly attribute ModuleDesc parent; + + // Name is guaranteed to be unique for each module (no two in/out- + // ports with the same name allowed) + readonly attribute string name; + readonly attribute PortType type; + + /* + * - for input channels, one of those must be true (only event + * channels may remain unconnected), + * - for output channels, only isConnected may be set + * + * only one of them may be set, not both + */ + readonly attribute boolean isConnected; + attribute boolean hasValue; // set to false is only allowed writing + + // connections, used when isConnected is true + readonly attribute sequence<PortDesc> connections; + + // to be used as const value when hasValue is true + attribute float floatValue; + attribute string stringValue; + + // the value as "any" + attribute Any value; + + boolean connectTo(PortDesc port); + void disconnectFrom(PortDesc port); + void disconnectAll(); + + sequence<string> saveToList(); + void loadFromList(sequence<string> list); + + // never call this by hand, it will only be used by the module: + void internalConnectInput(PortDesc port); + void internalReConnect(sequence<PortDesc> allports); + + readonly attribute long internalOldID; + }; + + interface ModuleDesc { + // internal + void constructor(StructureDesc parent, ModuleInfo info); + + // ID is guaranteed to be unique in the structure the module belongs to + readonly attribute long ID; + readonly attribute StructureDesc parent; + + readonly attribute string name; + readonly attribute sequence<PortDesc> ports; + readonly attribute long x, y, width, height; + readonly attribute boolean isInterface, isStructure; + + boolean moveTo(long x, long y); // returns true when successful + + PortDesc findPort(string name); + sequence<string> saveToList(); + void loadFromList(sequence<string> list); + }; + + interface StructureDesc { + // internal: + long obtainID(); // only to be used as module or port + + // public: + readonly attribute boolean valid; + attribute string name; + readonly attribute sequence<ModuleDesc> modules; + readonly attribute sequence<StructurePortDesc> ports; + readonly attribute sequence<string> inheritedInterfaces; + + sequence<string> saveToList(); + void loadFromList(sequence<string> list); + + /** + * deletes all components in the structure + */ + void clear(); + + ModuleDesc createModuleDesc(ModuleInfo info); + void freeModuleDesc(ModuleDesc moduledesc); + + /** + * publishing (HMM) + */ + readonly attribute ModuleInfo externalInterface; + + // External Interface Ports: + StructurePortDesc createStructurePortDesc(PortType type, + string name); + void freeStructurePortDesc(StructurePortDesc portdesc); + void moveStructurePortDesc(StructurePortDesc portdesc, + long newposition); + + // you will need to add the structure ports yourself + void addInheritedInterface(string iface); + + // this will remove the associated structure ports + void removeInheritedInterface(string iface); + }; + + interface StructurePortDesc : PortDesc { + // internal + void constructor(StructureDesc parent, string name, PortType type); + + // Position: how the port is positioned when the structure is used + // as module - 0 is leftmost, higher numbers are more right + readonly attribute long x, y, position; + readonly attribute StructureDesc parentStructure; + + // if the port is associated with an inherited interface of the + // parent structure, then it should be setup here + attribute string inheritedInterface; + + boolean moveTo(long x, long y); // returns true when successful + + void lowerPosition(); // will move the port more left + void raisePosition(); // will move the port more right + void rename(string newname); + + // only used by the structure to reorder the ports + void internalSetPosition(long position); + }; + + interface ObjectFactory { + object createObject(string name); + }; + + interface LocalFactory : ObjectFactory { + }; + + interface StructureBuilder { + void addFactory(ObjectFactory factory); + object createObject(StructureDesc structure); + ModuleDef createTypeInfo(StructureDesc structure); + }; + + interface ArtsBuilderLoader : Loader { + }; + + interface Structure : SynthModule { + void run(); + void halt(); + }; +}; diff --git a/arts/runtime/artsbuilderloader_impl.cc b/arts/runtime/artsbuilderloader_impl.cc new file mode 100644 index 00000000..415106ef --- /dev/null +++ b/arts/runtime/artsbuilderloader_impl.cc @@ -0,0 +1,285 @@ + /* + + Copyright (C) 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "artsbuilder.h" +#include "debug.h" +#include <stdlib.h> +#include <fstream> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <unistd.h> +#include <dirent.h> +#include <set> +#include <cstring> + + +using namespace Arts; +using namespace std; + +namespace Arts { + +class ArtsBuilderLoader_impl : virtual public ArtsBuilderLoader_skel { +protected: + set<string> sourceDirs; + + string lastDataVersion; + vector<TraderEntry> _traderEntries; + vector<ModuleDef> _modules; + +public: + Object loadObject(Arts::TraderOffer offer) + { + StructureDesc structureDesc; + + vector<string> strseq; + + // load file + vector<string> *filenames = offer.getProperty("File"); + if(filenames->size() == 1) + { + string& filename = filenames->front(); + arts_info("ArtsBuilderLoader: filename = %s", filename.c_str()); + + ifstream infile(filename.c_str()); + string line; + while(getline(infile,line)) strseq.push_back(line); + } + delete filenames; + + structureDesc.loadFromList(strseq); + if(structureDesc.name() != offer.interfaceName()) + { + arts_warning("failed (name = %s).",structureDesc.name().c_str()); + return Object::null(); + } + + StructureBuilder builder; + builder.addFactory(LocalFactory()); + + return builder.createObject(structureDesc); + } + + vector<string> *listFiles(const string& pathname, const char *extension) + { + vector<string> *result = new vector<string>(); + + unsigned long extlen = strlen(extension); + DIR *dir = opendir(pathname.c_str()); + if(dir != 0) + { + struct dirent *de; + while((de = readdir(dir)) != 0) + { + if(strlen(de->d_name) > extlen && + strncmp(&de->d_name[strlen(de->d_name)-extlen], + extension,extlen) == 0) + result->push_back(de->d_name); + } + closedir(dir); + } + return result; + } + + void collectInterfaces(const InterfaceDef& interface, + map<string, bool>& implemented) + { + if(!implemented[interface.name]) + { + implemented[interface.name] = true; + + vector<string>::const_iterator ii; + for(ii = interface.inheritedInterfaces.begin(); + ii != interface.inheritedInterfaces.end(); ii++) + { + InterfaceDef id; + id = Dispatcher::the()->interfaceRepo().queryInterface(*ii); + collectInterfaces(id, implemented); + } + } + } + + string getInterfacesList(const InterfaceDef& interface) + { + map<string, bool> implemented; + map<string, bool>::iterator ii; + string result; + + collectInterfaces(interface, implemented); + + for(ii = implemented.begin(); ii != implemented.end(); ii++) + result += ii->first + ","; + result += "Arts::Object"; + return result; + } + + void scanArtsFile(const string& filename) + { + StructureDesc structureDesc; + vector<string> strseq; + + // load file + { + ifstream infile(filename.c_str()); + string line; + int inmodule = 0; + + while(getline(infile,line)) + { + /* + * TODO - maybe there is a cleaner way? + * + * the following six lines are a bit hackish code to skip + * the module sections of the structures + * + * the problem with the module sections is this: + * we can't be sure that every module is known to the type + * system before we registered them with the type system, + * but as this code should be able to initially register .arts + * files with the type system, we can't rely that it has been + * done already (if we could, what would be the point of + * running this?) + */ + if(strncmp(line.c_str(), "module=", 7) == 0) + inmodule = 1; + + if(strncmp(line.c_str(), "{", 1) == 0 && inmodule == 1) + inmodule = 2; + + if(strncmp(line.c_str(), "}", 1) == 0 && inmodule == 2) + inmodule = 0; + + if(inmodule == 0) + strseq.push_back(line); + } + } + + structureDesc.loadFromList(strseq); + string name = structureDesc.name(); + + + arts_debug("%s [%s]\n",filename.c_str(),name.c_str()); + + /* add to _modules */ + StructureBuilder builder; + ModuleDef md = builder.createTypeInfo(structureDesc); + _modules.push_back(md); + + arts_assert(md.moduleName == name); + arts_assert(!md.interfaces.empty()); + + const InterfaceDef& id = md.interfaces.front(); + + /* add to _traderEntries */ + + TraderEntry entry; + entry.interfaceName = name; + entry.lines.push_back("Buildable=true"); + entry.lines.push_back("Interface="+getInterfacesList(id)); + entry.lines.push_back("Language=aRts"); + entry.lines.push_back("File="+filename); + + _traderEntries.push_back(entry); + /* + * TODO: more entries like + * Author="Stefan Westerfeld <stefan@space.twc.de>" + * URL="http://www.arts-project.org" + * License=... + */ + } + + void rescan() + { + lastDataVersion = dataVersion(); + + _traderEntries.clear(); + _modules.clear(); + + set<string>::iterator si; + for(si = sourceDirs.begin(); si != sourceDirs.end(); si++) + { + vector<string> *files = listFiles(*si, ".arts"); + vector<string>::iterator i; + for(i = files->begin(); i != files->end(); i++) + scanArtsFile(*si + "/" +*i); + delete files; + } + } + + string dataVersion() + { + /* + * change this string if you change the loading algorithm to force + * rescanning even with the same data + */ + string result = "ArtsBuilderLoader:1.1:"; + + bool first = true; + + set<string>::iterator i; + for(i = sourceDirs.begin(); i != sourceDirs.end(); i++) + { + const string& filename = *i; + + if(!first) result += ","; + first = false; + + struct stat st; + if( stat(filename.c_str(), &st) == 0 ) + { + char mtime[32]; + sprintf(mtime,"[%ld]",st.st_mtime); + result += filename + mtime; + } + else + result += filename + "[-1]"; + } + return result; + } + + vector<TraderEntry> *traderEntries() + { + if(dataVersion() != lastDataVersion) + rescan(); + + return new vector<TraderEntry>(_traderEntries); + } + + vector<ModuleDef> *modules() + { + if(dataVersion() != lastDataVersion) + rescan(); + + return new vector<ModuleDef>(_modules); + } + + ArtsBuilderLoader_impl() + { + sourceDirs.insert(EXAMPLES_DIR); + + const char *home = getenv("HOME"); + if(home) sourceDirs.insert(home+string("/arts/structures")); + } +}; + +REGISTER_IMPLEMENTATION(ArtsBuilderLoader_impl); +} diff --git a/arts/runtime/compatibility.cc b/arts/runtime/compatibility.cc new file mode 100644 index 00000000..190d471b --- /dev/null +++ b/arts/runtime/compatibility.cc @@ -0,0 +1,56 @@ + /* + + Copyright (C) 1999 Stefan Westerfeld + stefan@space.twc.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#include "compatibility.h" +#include "debug.h" +#include <iostream> + +#undef DEBUG_COMPATIBILITY + +using namespace std; + +string Arts::OldFormatTranslator::newModuleName(const string& module) +{ +#ifdef DEBUG_COMPATIBILITY + arts_debug("COMPAT: %s", module.c_str()); +#endif + + if(module.substr(0,10) == "Interface_") return "Arts::"+module; + if(module.substr(0,6) == "Synth_") return "Arts::"+module; + return module; +} + +string Arts::OldFormatTranslator::newPortName(const string& module, const string& port) +{ +#ifdef DEBUG_COMPATIBILITY + arts_debug("COMPAT: %s.%s", module.c_str(), port.c_str()); +#endif + + if(module == "Arts::Synth_MUL") { + if(port == "invalue") return "invalue1"; + if(port == "faktor") return "invalue2"; + } + if(module == "Arts::Synth_ADD") { + if(port == "invalue") return "invalue1"; + if(port == "addit") return "invalue2"; + } + return port; +} diff --git a/arts/runtime/compatibility.h b/arts/runtime/compatibility.h new file mode 100644 index 00000000..b95b0266 --- /dev/null +++ b/arts/runtime/compatibility.h @@ -0,0 +1,36 @@ + /* + + Copyright (C) 1999 Stefan Westerfeld + stefan@space.twc.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#ifndef ARTS_COMPATIBILITY_H +#define ARTS_COMPATIBILITY_H + +#include <string> + +namespace Arts { + class OldFormatTranslator { + public: + static std::string newModuleName(const std::string& module); + static std::string newPortName(const std::string& module, + const std::string& port); + }; +} + +#endif /* ARTS_COMPATIBILITY_H */ diff --git a/arts/runtime/localfactory_impl.cc b/arts/runtime/localfactory_impl.cc new file mode 100644 index 00000000..bf55271c --- /dev/null +++ b/arts/runtime/localfactory_impl.cc @@ -0,0 +1,15 @@ +#include "artsbuilder.h" + +using namespace Arts; +using namespace std; + +class LocalFactory_impl : virtual public LocalFactory_skel { +public: + Object createObject(const string& name) + { + return SubClass(name); + } +}; + +REGISTER_IMPLEMENTATION(LocalFactory_impl); + diff --git a/arts/runtime/moduleinfo.cc b/arts/runtime/moduleinfo.cc new file mode 100644 index 00000000..28a44310 --- /dev/null +++ b/arts/runtime/moduleinfo.cc @@ -0,0 +1,106 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Permission is also granted to link this program with the Qt + library, treating Qt like a library that normally accompanies the + operating system kernel, whether or not that is in fact the case. + + */ + +#include "moduleinfo.h" + +using namespace std; + +static void gatherPorts(Arts::InterfaceDef& idef, Arts::ModuleInfo& minfo, + map<string, bool>& done) +{ + Arts::InterfaceRepo interfaceRepo=Arts::Dispatcher::the()->interfaceRepo(); + + vector<string>::iterator ii = idef.inheritedInterfaces.begin(); + while(ii != idef.inheritedInterfaces.end()) + { + Arts::InterfaceDef inherited = interfaceRepo.queryInterface(*ii++); + gatherPorts(inherited,minfo,done); + } + + if(idef.name == "Arts::Object" || idef.name == "Arts::SynthModule") + { + // don't gather members of these basic interfaces as ports + return; + } + vector<Arts::AttributeDef>::iterator i; + for(i=idef.attributes.begin(); i != idef.attributes.end(); i++) + { + // 1 = direction, 10000 = connectiontype + long complete = 0; + Arts::PortType ptype; + + if(i->flags & Arts::streamIn) + { + ptype.direction = Arts::input; + complete += 1; + } + else if(i->flags & Arts::streamOut) + { + ptype.direction = Arts::output; + complete += 1; + } + + ptype.dataType = i->type; + + if(i->flags & Arts::attributeStream) + { + ptype.connType = Arts::conn_stream; + complete += 10000; + } + else if(i->flags & Arts::attributeAttribute) + { + ptype.connType = Arts::conn_property; + complete += 10000; + } + + ptype.isMultiPort = (i->flags & Arts::streamMulti); + + if(complete == 10001 && !done[i->name]) + { + minfo.portnames.push_back(i->name); + minfo.ports.push_back(ptype); + done[i->name] = true; + } + } +} + +Arts::ModuleInfo makeModuleInfo(const string& name) +{ + Arts::InterfaceRepo interfaceRepo=Arts::Dispatcher::the()->interfaceRepo(); + Arts::InterfaceDef idef = interfaceRepo.queryInterface(name); + Arts::ModuleInfo minfo; + + if(!idef.name.empty()) + { + map<string,bool> done; + minfo.name = name; + minfo.isStructure = false; + minfo.isInterface = false; + + gatherPorts(idef,minfo,done); + } + return minfo; +} + diff --git a/arts/runtime/moduleinfo.h b/arts/runtime/moduleinfo.h new file mode 100644 index 00000000..1067f342 --- /dev/null +++ b/arts/runtime/moduleinfo.h @@ -0,0 +1,33 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Permission is also granted to link this program with the Qt + library, treating Qt like a library that normally accompanies the + operating system kernel, whether or not that is in fact the case. + + */ + +#ifndef MODULEINFO_H +#define MODULEINFO_H + +#include "artsbuilder.h" +#include <kdelibs_export.h> +KDE_EXPORT Arts::ModuleInfo makeModuleInfo(const std::string& name); + +#endif /* MODULEINFO_H */ diff --git a/arts/runtime/sequenceutils.cc b/arts/runtime/sequenceutils.cc new file mode 100644 index 00000000..9634f40b --- /dev/null +++ b/arts/runtime/sequenceutils.cc @@ -0,0 +1,188 @@ + /* + + Copyright (C) 1999 Stefan Westerfeld + stefan@space.twc.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#include "sequenceutils.h" +#include <stdarg.h> +#include <stdio.h> +#include <config.h> + +using namespace std; + +#if 0 +void sqprintf(ArtsCorba::StringSeq *list, const char *fmt, ...) +{ + char p[1024]; + va_list ap; + va_start(ap, fmt); + (void) vsnprintf(p, 1024, fmt, ap); + va_end(ap); + + unsigned long len = list->length(); + list->length(len+1); + (*list)[len] = CORBA::string_dup(p); +} +#endif + +void sqprintf(vector<string> *list, const char *fmt, ...) +{ + char p[1024]; + va_list ap; + va_start(ap, fmt); + (void) vsnprintf(p, 1024, fmt, ap); + va_end(ap); + + list->push_back(p); +} + +int parse_line(const char *in, char *& cmd, char *& param) +{ + int i,cmdlen=0,paramlen=0; + static char static_cmd[1000], static_param[1000]; + + cmd = static_cmd; + param = static_param; + i = 0; + + while(in[i] == ' ' || in[i] == '\t') i++; + + if(in[i] == 0) return(0); + + while(in[i] != '=' && in[i] != 0) cmd[cmdlen++] = in[i++]; + if(in[i] != 0) i++; + while(in[i] != 0) param[paramlen++] = in[i++]; + + cmd[cmdlen] = 0; + param[paramlen] = 0; + + if(paramlen) return(2); + if(cmdlen) return(1); + return(0); +} + +int parse_line(const string& in, string& cmd, string& param) +{ + char *ccmd, *cparam; + int result = parse_line(in.c_str(),ccmd,cparam); + param = cparam; + cmd = ccmd; + return result; +} + +#if 0 +void addSubStringSeq(ArtsCorba::StringSeq *target, ArtsCorba::StringSeq *source) +{ + unsigned long i; + + sqprintf(target,"{"); + for(i=0;i<source->length();i++) + { + unsigned long len = target->length(); + target->length(len+1); + string srcstring = string(" ") + string((*source)[i]); + (*target)[len] = CORBA::string_dup(srcstring.c_str()); + } + sqprintf(target,"}"); +} +#endif + +void addSubStringSeq(vector<string> *target, const vector<string> *source) +{ + sqprintf(target,"{"); + + vector<string>::const_iterator i; + for(i=source->begin();i != source->end();i++) + target->push_back(" " + *i); + + sqprintf(target,"}"); +} + +#if 0 +void appendStringSeq(ArtsCorba::StringSeq *target, ArtsCorba::StringSeq *source) +{ + unsigned long i; + + for(i=0;i<source->length();i++) + { + unsigned long len = target->length(); + target->length(len+1); + (*target)[len] = CORBA::string_dup((*source)[i]); + } +} +#endif + +void appendStringSeq(vector<string> *target, const vector<string> *source) +{ + vector<string>::const_iterator i; + for(i=source->begin();i != source->end();i++) + target->push_back(*i); +} + +#if 0 +ArtsCorba::StringSeq *getSubStringSeq(const ArtsCorba::StringSeq *seq,unsigned long& i) +{ + ArtsCorba::StringSeq *result = new ArtsCorba::StringSeq; + char empty[1] = {0}; + char *cmd = empty,*param; + + + while(strcmp(cmd,"{") && i<seq->length()) + parse_line((*seq)[i++],cmd,param); + + int brackets = 1; + + while(i<seq->length()) + { + parse_line((*seq)[i],cmd,param); + if(strcmp(cmd,"{") == 0) brackets++; + if(strcmp(cmd,"}") == 0) brackets--; + if(brackets == 0) return(result); + + unsigned long len = result->length(); + result->length(len+1); + (*result)[len] = CORBA::string_dup((*seq)[i]); + i++; + } + return(result); +} +#endif + +vector<string> *getSubStringSeq(const vector<string> *seq,unsigned long& i) +{ + vector<string> *result = new vector<string>; + string cmd = "",param; + + while(cmd != "{" && i<seq->size()) + parse_line((*seq)[i++],cmd,param); + + int brackets = 1; + + while(i<seq->size()) + { + parse_line((*seq)[i],cmd,param); + if(cmd == "{") brackets++; + if(cmd == "}") brackets--; + if(brackets == 0) return(result); + + result->push_back((*seq)[i]); + i++; + } + return result; +} diff --git a/arts/runtime/sequenceutils.h b/arts/runtime/sequenceutils.h new file mode 100644 index 00000000..5925bff3 --- /dev/null +++ b/arts/runtime/sequenceutils.h @@ -0,0 +1,41 @@ + /* + + Copyright (C) 1999 Stefan Westerfeld + stefan@space.twc.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#ifndef ARTS_SEQUENCEUTILS_H +#define ARTS_SEQUENCEUTILS_H + +#include <vector> +#include <string> +#include <kdelibs_export.h> + +KDE_EXPORT int parse_line(const char *in, char *& cmd, char *& param); + +KDE_EXPORT void sqprintf(std::vector<std::string> *list, const char *fmt, ...) +#ifdef __GNUC__ + __attribute__ (( format (printf, 2, 3))) +#endif +; +KDE_EXPORT void addSubStringSeq(std::vector<std::string> *target, const std::vector<std::string> *source); +KDE_EXPORT void appendStringSeq(std::vector<std::string> *target, const std::vector<std::string> *source); +KDE_EXPORT int parse_line(const std::string& in, std::string& cmd, std::string& param); +KDE_EXPORT std::vector<std::string> *getSubStringSeq(const std::vector<std::string> *seq,unsigned long& i); + +#endif /* ARTS_SEQUENCEUTILS_H */ diff --git a/arts/runtime/structurebuilder_impl.cc b/arts/runtime/structurebuilder_impl.cc new file mode 100644 index 00000000..63dd6927 --- /dev/null +++ b/arts/runtime/structurebuilder_impl.cc @@ -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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, 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(); + } + } +} 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; +} |