summaryrefslogtreecommitdiffstats
path: root/arts/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'arts/runtime')
-rw-r--r--arts/runtime/ArtsBuilderLoader.mcopclass4
-rw-r--r--arts/runtime/LocalFactory.mcopclass3
-rw-r--r--arts/runtime/Makefile.am38
-rw-r--r--arts/runtime/StructureBuilder.mcopclass3
-rw-r--r--arts/runtime/StructureDesc.mcopclass3
-rw-r--r--arts/runtime/artsbuilder.idl228
-rw-r--r--arts/runtime/artsbuilderloader_impl.cc285
-rw-r--r--arts/runtime/compatibility.cc56
-rw-r--r--arts/runtime/compatibility.h36
-rw-r--r--arts/runtime/localfactory_impl.cc15
-rw-r--r--arts/runtime/moduleinfo.cc106
-rw-r--r--arts/runtime/moduleinfo.h33
-rw-r--r--arts/runtime/sequenceutils.cc188
-rw-r--r--arts/runtime/sequenceutils.h41
-rw-r--r--arts/runtime/structurebuilder_impl.cc347
-rw-r--r--arts/runtime/structures_impl.cc1421
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;
+}