Urbi SDK Remote for C++  2.7.3
all.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008-2011, Gostai S.A.S.
00003  *
00004  * This software is provided "as is" without warranty of any kind,
00005  * either expressed or implied, including but not limited to the
00006  * implied warranties of fitness for a particular purpose.
00007  *
00008  * See the LICENSE file for more information.
00009  */
00010 
00011 #include <iostream>
00012 #include <libport/cmath>
00013 #include <libport/compiler.hh>
00014 #include <libport/containers.hh>
00015 #include <libport/debug.hh>
00016 #include <libport/ufloat.hh>
00017 #include <libport/unistd.h>
00018 #include <sstream>
00019 #include <stdexcept>
00020 
00021 #include <urbi/uclient.hh>
00022 #undef URBI
00023 #include <urbi/uobject.hh>
00024 #include <urbi/input-port.hh>
00025 
00026 GD_CATEGORY(Test.All);
00027 
00029 static void*
00030 memdup(const void *data, size_t size)
00031 {
00032   return memcpy(malloc(size), data, size);
00033 }
00034 
00035 struct Point
00036 {
00037   Point()
00038     : x(0)
00039     , y(0)
00040   {}
00041   ufloat x,y;
00042 };
00043 
00044 struct Rect
00045 {
00046   Point a;
00047   Point b;
00048 };
00049 
00050 struct PointOfInterest
00051 {
00052   std::string sectorName;
00053   std::vector<Rect> subSectors;
00054   boost::unordered_map<std::string, Rect> byName;
00055 };
00056 
00057 URBI_REGISTER_STRUCT(Point, x, y);
00058 URBI_REGISTER_STRUCT(Rect, a, b);
00059 URBI_REGISTER_STRUCT(PointOfInterest, sectorName, subSectors, byName);
00060 
00061 
00062 class all: public urbi::UObject
00063 {
00064 public:
00065   typedef urbi::UObject super_type;
00066   pthread_t mainthread;
00067 
00068   inline void threadCheck() const
00069   {
00070     aver(mainthread == pthread_self());
00071   }
00072 
00073   all()
00074   {
00075     GD_INFO_TRACE("all default ctor");
00076     count = 0;
00077     mainthread = pthread_self();
00078     setup();
00079     init(1);
00080   }
00081 
00082   all(const std::string& name)
00083     : urbi::UObject(name)
00084   {
00085     GD_INFO_TRACE("all string ctor");
00086     count = 0;
00087     mainthread = pthread_self();
00088     if (getenv("CTOR_EXCEPTION") &&
00089         !strcmp(getenv("CTOR_EXCEPTION"), "true"))
00090       throw std::runtime_error("constructor failure");
00091     setup();
00092   }
00093 
00094   void setup()
00095   {
00096     UBindFunction(all, init);
00097     UBindFunction(all, setOwned);
00098     UBindFunction(all, setNotifyChange);
00099     UBindFunctions(all, multiRead, multiWrite);
00100 
00102     UBindFunction(all, setBypassNotifyChangeBinary);
00103     UBindFunction(all, setBypassNotifyChangeImage);
00104     UBindFunctions(all, markBypass, markRTP);
00105     UBindFunctions(all, selfWriteB, selfWriteI, selfWriteVD);
00106 
00107     UBindFunctions
00108       (all,
00109        setNotifyAccess, setNotifyChangeByName, setNotifyChangeByUVar,
00110        sendEvent8Args,
00111        unnotify,
00112        setThreadedNotifyChange, setThreadedNotifyChangeByUVar);
00113     UBindFunction(all, read);
00114     UBindFunction(all, write);
00115     UBindFunction(all, readByName);
00116     UBindFunction(all, writeByName);
00117     UBindFunction(all, writeByUVar);
00118     UBindFunction(all, writeOwnByName);
00119     UBindFunction(all, urbiWriteOwnByName);
00120     UBindFunction(all, sendString);
00121     UBindFunction(all, sendBuf);
00122     UBindFunction(all, sendPar);
00123     UBindFunction(all, typeOf);
00124     UBindFunction(all, uobjectName);
00125     UBindFunction(all, allUObjectName);
00126     UBindVar(all,a);
00127     UBindVars(all, b, c, d);
00128     UBindVar(all, initCalled);
00129     initCalled = 0;
00130     UBindVar(all, lastChange);
00131     UBindVar(all, lastAccess);
00132     UBindVar(all, lastChangeVal);
00133     lastChangeVal = -1;
00134     UBindVar(all, lastAccessVal);
00135     UBindVar(all, removeNotify);
00136     removeNotify = "";
00137     // Properties.
00138     UBindFunction(all, readProps);
00139     UBindFunction(all, writeProps);
00140 
00141     UBindFunction(all, writeD);
00142     UBindFunction(all, writeS);
00143     UBindFunction(all, writeL);
00144     UBindFunction(all, writeM); // M for Map
00145     UBindFunction(all, writeB);
00146     UBindFunction(all, makeCall);
00147     UBindFunction(all, writeBNone);
00148     UBindFunction(all, writeI);
00149     UBindFunction(all, writeSnd);
00150     UBindFunction(all, writeRI);
00151     UBindFunction(all, writeRSnd);
00152 
00153     UBindFunction(all, transmitD);
00154     UBindFunction(all, transmitS);
00155     UBindFunction(all, transmitL);
00156     UBindFunction(all, transmitM);
00157     UBindFunction(all, transmitB);
00158     UBindFunction(all, transmitI);
00159     UBindFunction(all, transmitSnd);
00160     UBindFunction(all, transmitO);
00161 
00162     UBindFunction(all, loop_yield);
00163     UBindFunction(urbi::UContext, side_effect_free_get);
00164     UBindFunction(urbi::UContext, side_effect_free_set);
00165     UBindFunction(urbi::UContext, yield);
00166     UBindFunction(urbi::UContext, yield_for);
00167     UBindFunction(urbi::UContext, yield_until_things_changed);
00168 
00169     UBindFunction(all, getDestructionCount);
00170 
00171     UBindFunction(all, invalidRead);
00172     UBindFunction(all, invalidWrite);
00173 
00174     UBindEvent(all, ev);
00175     UBindFunction(all, sendEvent);
00176     UBindFunction(all, sendEvent2Args);
00177     UBindFunction(all, sendNamedEvent);
00178 
00179     UBindFunction(all, throwException);
00180     UBindFunction(all, socketStats);
00181     UBindFunction(all, instanciate);
00182     UBindFunctions(all, area, translate, makeRect, multiTranslate,
00183                    transmitPointOfInterest, writePointOfInterest,
00184                    readPointOfInterest);
00185     UBindFunctionRename(all, area, "rectArea");
00186     UBindFunctions(all, pack, unpack);
00187     UBindVars(all, periodicWriteTarget, periodicWriteType, periodicWriteRate,
00188               periodicWriteCount, changeCount);
00189     periodicWriteCount = 1;
00190     UNotifyChange(periodicWriteRate, &all::onRateChange);
00191     vars[0] = &a;
00192     vars[1] = &b;
00193     vars[2] = &c;
00194     vars[3] = &d;
00195     vars[4] = &unbound;
00196     std::string name = "ia";
00197     for(int i=0; i<4; ++i)
00198     {
00199       name[1] = 'a' + i;
00200       ports[i] = new urbi::InputPort(this, name);
00201     }
00202     // 4 is unbound
00203     ports[4] = new urbi::InputPort();
00204     UBindFunctions(all, notifyWriteA, writeAD, writeAS, writeAB, manyWriteTest);
00205     UAt(all, boundev);
00206   }
00207 
00208   ~all()
00209   {
00210     ++destructionCount;
00211   }
00212 
00213   void multiWrite(int idx, int count, ufloat val)
00214   {
00215     for (int i=0; i<count; ++i)
00216       (*vars[idx]) = val+idx;
00217   }
00218 
00219   void multiRead(int idx, int count)
00220   {
00221     ufloat sum = 0;
00222     for (int i=0; i<count; ++i)
00223       sum += (ufloat)*vars[idx];
00224   }
00225 
00226   void boundev(ufloat v)
00227   {
00228     lastChange = "boundev";
00229     lastChangeVal = v;
00230   }
00231 
00232   void onRateChange(urbi::UVar&)
00233   {
00234     USetUpdate((ufloat)periodicWriteRate * 1000.0);
00235   }
00236 
00237   UObject* instanciate() const
00238   {
00239     return new all;
00240   }
00241 
00242   virtual int update()
00243   {
00244     int target = periodicWriteTarget;
00245     int type = periodicWriteType;
00246     GD_FINFO_DEBUG("update: type = %s, target = %s", type, target);
00247     for (int i=0; i<(int)periodicWriteCount; ++i)
00248     switch (type)
00249     {
00250     case urbi::DATA_STRING:
00251       *vars[target] = string_cast(libport::utime());
00252       break;
00253     case urbi::DATA_BINARY:
00254       selfWriteB(target, string_cast(libport::utime()));
00255       break;
00256     case urbi::DATA_DOUBLE:
00257     default:
00258       *vars[target] = libport::utime();
00259       break;
00260     }
00261     return 0;
00262   }
00263 
00264   int setBypassNotifyChangeBinary(const std::string& name)
00265   {
00266     threadCheck();
00267     UNotifyChange(name, &all::onBinaryBypass);
00268     return 0;
00269   }
00270 
00271   int setBypassNotifyChangeImage(const std::string& name)
00272   {
00273     threadCheck();
00274     UNotifyChange(name, &all::onImageBypass);
00275     return 0;
00276   }
00277 
00278   int markBypass(int id, bool state)
00279   {
00280     threadCheck();
00281     return vars[id]->setBypass(state);
00282   }
00283 
00284   int markRTP(int id, bool state)
00285   {
00286     vars[id]->useRTP(state);
00287     return 0;
00288   }
00289 
00290   void unnotify(int id)
00291   {
00292     if (id < 5)
00293       vars[id]->unnotify();
00294     else
00295       ports[id - 5]->unnotify();
00296   }
00297 
00298   int onBinaryBypass(urbi::UVar& var)
00299   {
00300     threadCheck();
00301     const urbi::UBinary& cb = var;
00302     GD_FINFO_DEBUG("onbin cptr %s", cb.common.data);
00303     urbi::UBinary& b = const_cast<urbi::UBinary&>(cb);
00304     for (unsigned int i=0; i<b.common.size; ++i)
00305       ((char*)b.common.data)[i]++;
00306     return 0;
00307   }
00308 
00309   void onImageBypass(urbi::UVar& var)
00310   {
00311     threadCheck();
00312     const urbi::UImage& cb = var;
00313     GD_FINFO_DEBUG("onimg cptr %s", (void*)cb.data);
00314     urbi::UImage& b = const_cast<urbi::UImage&>(cb);
00315     for (unsigned int i=0; i<b.size; ++i)
00316       b.data[i]++;
00317   }
00318 
00319   std::string selfWriteB(int idx, const std::string& content)
00320   {
00321     threadCheck();
00322     urbi::UBinary b;
00323     b.type = urbi::BINARY_UNKNOWN;
00324     // Dup since we want to test no-copy op: the other end will write.
00325     b.common.data = memdup(content.c_str(), content.size());
00326     b.common.size = content.size();
00327     GD_FINFO_DEBUG("writeB cptr %s", b.common.data);
00328     *vars[idx] = b;
00329     std::string res((char*)b.common.data, b.common.size);
00330     free(b.common.data);
00331     b.common.data = 0;
00332     return res;
00333   }
00334 
00335   std::string selfWriteI(int idx, const std::string& content)
00336   {
00337     threadCheck();
00338     urbi::UImage i;
00339     i.init();
00340     i.data = (unsigned char*)memdup(content.c_str(), content.size());
00341     i.size = content.length();
00342     GD_FINFO_DEBUG("writeI cptr %s", (void*)i.data);
00343     *vars[idx] = i;
00344     std::string res((char*)i.data, i.size);
00345     free(i.data);
00346     return res;
00347   }
00348 
00349   int writeOwnByName(const std::string& name, int val)
00350   {
00351     threadCheck();
00352     urbi::UVar v(__name + "." + name);
00353     v = val;
00354     return 0;
00355   }
00356 
00357   int urbiWriteOwnByName(const std::string& name, int val)
00358   {
00359     threadCheck();
00360     std::stringstream ss;
00361     ss << __name << "." << name << " = " << val << ";";
00362     send(ss.str());
00363     return 0;
00364   }
00365 
00366   void selfWriteVD(int i, std::vector<ufloat> v)
00367   {
00368     *vars[i] = v;
00369   }
00370 
00371   std::string typeOf(const std::string& name)
00372   {
00373     threadCheck();
00374     urbi::UVar v(name);
00375     v.syncValue();
00376     return v.val().format_string();
00377   }
00378 
00379   int init(int fail)
00380   {
00381     threadCheck();
00382     initCalled = 1;
00383     if (fail > 1)
00384       throw std::runtime_error("KABOOOM");
00385     return fail;
00386   }
00387 
00388   int setOwned(int id)
00389   {
00390     threadCheck();
00391     UOwned(*vars[id]);
00392     return 0;
00393   }
00394 
00395   int setNotifyChange(int id)
00396   {
00397     threadCheck();
00398     if (id < 5)
00399       UNotifyChange(*vars[id], &all::onChange);
00400     else
00401       UNotifyChange(*ports[id - 5], &all::onChange);
00402     return 0;
00403   }
00404 
00405   int setThreadedNotifyChange(int id)
00406   {
00407     threadCheck();
00408     if (id<5)
00409       UNotifyThreadedChange(*vars[id], &all::onChange, urbi::LOCK_FUNCTION);
00410     else
00411       UNotifyThreadedChange(*ports[id-5], &all::onChange, urbi::LOCK_FUNCTION);
00412     return 0;
00413   }
00414 
00415   int setThreadedNotifyChangeByUVar(urbi::UVar& v)
00416   {
00417     UNotifyThreadedChange(v, &all::onChange, urbi::LOCK_FUNCTION);
00418     return 0;
00419   }
00420 
00421   int setNotifyChangeByUVar(urbi::UVar& v)
00422   {
00423     threadCheck();
00424     UNotifyChange(v, &all::onChange);
00425     return 0;
00426   }
00427 
00428   int setNotifyAccess(int id)
00429   {
00430     threadCheck();
00431     UNotifyAccess(*vars[id], &all::onAccess);
00432     return 0;
00433   }
00434 
00435   int setNotifyChangeByName(const std::string& name)
00436   {
00437     threadCheck();
00438     UNotifyChange(name, &all::onChange);
00439     return 0;
00440   }
00441 
00442 
00443   int read(int id)
00444   {
00445     threadCheck();
00446     int v = *vars[id];
00447     return v;
00448   }
00449 
00450   int write(int id, int val)
00451   {
00452     threadCheck();
00453     *vars[id] = val;
00454     return val;
00455   }
00456 
00457   void invalidWrite()
00458   {
00459     threadCheck();
00460     urbi::UVar v;
00461     v = 12;
00462   }
00463 
00464   void invalidRead()
00465   {
00466     threadCheck();
00467     urbi::UVar v;
00468     int i = v;
00469     LIBPORT_USE(i);
00470   }
00471 
00472   int readByName(const std::string& name)
00473   {
00474     threadCheck();
00475     urbi::UVar v(name);
00476     return v;
00477   }
00478 
00479   int writeByName(const std::string& name, int val)
00480   {
00481     threadCheck();
00482     urbi::UVar v(name);
00483     v = val;
00484     return val;
00485   }
00486 
00487   int writeByUVar(urbi::UVar v, urbi::UValue val)
00488   {
00489     threadCheck();
00490     v = val;
00491     return 0;
00492   }
00493 
00494   int onChange(urbi::UVar& v)
00495   {
00496     lastChange = v.get_name();
00497     changeCount = ++count;
00498     if (v.type() == urbi::DATA_DOUBLE)
00499     {
00500       int val = v;
00501       lastChangeVal = val;
00502     }
00503     else if (v.type() == urbi::DATA_BINARY)
00504     {
00505       urbi::UBinary b = v;
00506       lastChangeVal = b;
00507     }
00508     if (removeNotify == v.get_name())
00509     {
00510       v.unnotify();
00511       removeNotify = "";
00512     }
00513     return 0;
00514   }
00515 
00516   int onAccess(urbi::UVar& v)
00517   {
00518     threadCheck();
00519     static int val = 0;
00520     lastAccess = v.get_name();
00521     val++;
00522     v = val;
00523     lastAccessVal = val;
00524     if ((std::string)removeNotify == v.get_name())
00525     {
00526       v.unnotify();
00527       removeNotify = "";
00528     }
00529     return 0;
00530   }
00531 
00532   void
00533   sendEvent()
00534   {
00535     threadCheck();
00536     ev.emit();
00537   }
00538 
00539   void
00540   sendEvent2Args(urbi::UValue v1, urbi::UValue v2)
00541   {
00542     ev.emit(v1, v2);
00543   }
00544 
00545   void sendEvent8Args()
00546   {
00547     ev.emit(0, "foo", 5.1, 4, 5, 6, 7);
00548   }
00549 
00550 
00551   void
00552   sendNamedEvent(const std::string& name)
00553   {
00554     urbi::UEvent tempEv(name);
00555     tempEv.emit();
00556   }
00557 
00559   urbi::UList
00560   readProps(const std::string& name)
00561   {
00562     threadCheck();
00563     urbi::UVar v(name);
00564     urbi::UList res;
00565 
00566 #define APPEND(Value)                                   \
00567     res.array.push_back(new urbi::UValue(Value))
00568 
00569 #define APPEND_UFLOAT(Prop)                     \
00570     APPEND(static_cast<ufloat>(v.Prop))
00571 
00572     APPEND_UFLOAT(rangemin);
00573     APPEND_UFLOAT(rangemax);
00574     APPEND_UFLOAT(speedmin);
00575     APPEND_UFLOAT(speedmax);
00576     APPEND_UFLOAT(delta);
00577     urbi::UValue bl = v.blend;
00578     APPEND(bl);
00579     APPEND_UFLOAT(constant);
00580 #undef APPEND_UFLOAT
00581 #undef APPEND
00582 
00583     GD_FINFO_DEBUG("all.readProps: %s", res);
00584     return res;
00585   }
00586 
00587   int writeProps(const std::string& name, ufloat val)
00588   {
00589     threadCheck();
00590     urbi::UVar v(name);
00591     v.rangemin = val;
00592     v.rangemax = val;
00593     v.speedmin = val;
00594     v.speedmax = val;
00595     v.delta = val;
00596     v.blend = val;
00597     v.constant = (val>0);
00598     return 0;
00599   }
00600 
00601 
00604   int writeD(const std::string& name, ufloat val)
00605   {
00606     threadCheck();
00607     GD_FINFO_DEBUG("writeD %s", name);
00608     urbi::UVar v(name);
00609     v = val;
00610     return 0;
00611   }
00612 
00613   int writeS(const std::string& name, const std::string& val)
00614   {
00615     GD_FINFO_DEBUG("writeS %s", name);
00616     urbi::UVar v(name);
00617     v = val;
00618     return 0;
00619   }
00620 
00621   int writeL(const std::string& name, const std::string& val)
00622   {
00623     GD_FINFO_DEBUG("writeL %s", name);
00624     urbi::UVar v(name);
00625     urbi::UList l;
00626     l.array.push_back(new urbi::UValue(val));
00627     l.array.push_back(new urbi::UValue(42));
00628     v = l;
00629     return 0;
00630   }
00631 
00632   int writeM(const std::string& name, const std::string& val)
00633   {
00634     GD_FINFO_DEBUG("writeM %s", name);
00635     urbi::UVar v(name);
00636     urbi::UDictionary d;
00637     d[val] = 42;
00638     d["foo"] = urbi::UList();
00639     v = d;
00640     return 0;
00641   }
00642 
00643   int writeB(const std::string& name, const std::string& content)
00644   {
00645     urbi::UVar v(name);
00646     urbi::UBinary val;
00647     val.type = urbi::BINARY_UNKNOWN;
00648     val.common.size = content.length();
00649     val.common.data = malloc(content.length());
00650     memcpy(val.common.data, content.c_str(), content.length());
00651     v = val;
00652     return 0;
00653   }
00654 
00655   int writeBNone(const std::string& name, const std::string& content)
00656   {
00657     urbi::UVar v(name);
00658     urbi::UBinary val;
00659     val.common.size = content.length();
00660     val.common.data = malloc(content.length());
00661     memcpy(val.common.data, content.c_str(), content.length());
00662     v = val;
00663     return 0;
00664   }
00665 
00666   int writeI(const std::string& name, const std::string& content)
00667   {
00668     urbi::UVar v(name);
00669     urbi::UImage i;
00670     i.init();
00671     i.imageFormat = urbi::IMAGE_JPEG;
00672     i.width = i.height = 42;
00673     i.size = content.length();
00674     i.data = (unsigned char*)malloc(content.length());
00675     memcpy(i.data, content.c_str(), content.length());
00676     v = i;
00677     free(i.data);
00678     return 0;
00679   }
00680 
00681   int writeSnd(const std::string& name, const std::string& content)
00682   {
00683     urbi::UVar v(name);
00684     urbi::USound s;
00685     s.init();
00686     s.soundFormat = urbi::SOUND_RAW;
00687     s.rate = 42;
00688     s.size = content.length();
00689     s.channels = 1;
00690     s.sampleSize= 8;
00691     s.sampleFormat = urbi::SAMPLE_UNSIGNED;
00692     s.data = (char*)malloc(content.length());
00693     memcpy(s.data, content.c_str(), content.length());
00694     v = s;
00695     free(s.data);
00696     return 0;
00697   }
00698 
00699 
00700   int writeRI(const std::string& name, const std::string& content)
00701   {
00702     urbi::UVar v(name);
00703     urbi::UImage i = v;
00704     memcpy(i.data, content.c_str(), content.length());
00705     return 0;
00706   }
00707 
00708   int writeRSnd(const std::string& name, const std::string& content)
00709   {
00710     urbi::UVar v(name);
00711     urbi::USound i = v;
00712     memcpy(i.data, content.c_str(), content.length());
00713     return 0;
00714   }
00715 
00716 
00718   ufloat transmitD(ufloat v) const
00719   {
00720     threadCheck();
00721     return -(ufloat)v;
00722   }
00723 
00724   urbi::UList transmitL(urbi::UList l) const
00725   {
00726     urbi::UList r;
00727     for (unsigned int i=0; i<l.array.size(); i++)
00728       r.array.push_back(new urbi::UValue(*l.array[l.array.size()-i-1]));
00729     return r;
00730   }
00731 
00732   urbi::UDictionary transmitM(urbi::UDictionary d) const
00733   {
00734     urbi::UDictionary r;
00735     foreach (const urbi::UDictionary::value_type& t, d)
00736       r[t.first] = t.second;
00737     return r;
00738   }
00739 
00740   std::string transmitS(const std::string& name) const
00741   {
00742     return name.substr(1, name.length()-2);
00743   }
00744 
00745   urbi::UBinary transmitB(urbi::UBinary b) const
00746   {
00747     urbi::UBinary res(b);
00748     unsigned char* data = static_cast<unsigned char*>(res.common.data);
00749     for (size_t i = 0; i < res.common.size; ++i)
00750       data[i] -= 1;
00751     data[res.common.size - 1] = '\n';
00752     return res;
00753   }
00754 
00755   urbi::UImage transmitI(urbi::UImage im) const
00756   {
00757     for (unsigned int i=0; i<im.size; i++)
00758       im.data[i] -= 1;
00759     return im;
00760   }
00761 
00762   urbi::USound transmitSnd(urbi::USound im) const
00763   {
00764     for (unsigned int i=0; i<im.size; i++)
00765       im.data[i] -= 1;
00766     return im;
00767   }
00768 
00769   urbi::UObject* transmitO(UObject* o) const
00770   {
00771     return o;
00772   }
00773 
00774   int sendString(const std::string& s)
00775   {
00776     threadCheck();
00777     send(s.c_str());
00778     return 0;
00779   }
00780 
00781   int sendBuf(const std::string& b, int l)
00782   {
00783     send(const_cast<void*>(static_cast<const void*>(b.c_str())), l);
00784     return 0;
00785   }
00786 
00787   int sendPar()
00788   {
00789     URBI((Object.a = 123,));
00790     return 0;
00791   }
00792 
00793   void loop_yield(long duration)
00794   {
00795     libport::utime_t end = libport::utime() + duration;
00796     while (libport::utime() < end)
00797     {
00798       yield();
00799       usleep(1000);
00800     }
00801   }
00802 
00803   int getDestructionCount() const
00804   {
00805     return destructionCount;
00806   }
00807 
00808   std::string uobjectName(UObject* n)
00809   {
00810     threadCheck();
00811     if (!n)
00812       return std::string();
00813     else
00814       return n->__name;
00815   }
00816 
00817   std::string allUObjectName(all* n)
00818   {
00819     return uobjectName(n);
00820   }
00821 
00822   void notifyWriteA(const std::string& target, int func)
00823   {
00824     switch(func)
00825     {
00826     case 0:
00827       UNotifyChange(target, &all::writeAD);
00828       break;
00829     case 1:
00830       UNotifyChange(target, &all::writeAS);
00831       break;
00832     case 2:
00833       UNotifyChange(target, &all::writeAB);
00834       break;
00835     case 3:
00836       UNotifyChange(target, &all::writeAV);
00837     }
00838   }
00839 
00840   void writeAD(ufloat d) { a = d; }
00841 
00842   void writeAS(const std::string& s) {a = s;}
00843 
00844   void writeAB(urbi::UBinary b) { a=b;}
00845 
00846   void writeAV(urbi::UValue v) { a=v;}
00847 
00848   void makeCall(const std::string& obj, const std::string& func,
00849                 urbi::UList args)
00850   {
00851     threadCheck();
00852     switch (args.size())
00853     {
00854 #define CASE(Num, ...)                                  \
00855       case Num: call(obj, func, ## __VA_ARGS__); break;
00856       CASE(0);
00857       CASE(1, args[0]);
00858       CASE(2, args[0], args[1]);
00859       CASE(3, args[0], args[1], args[2]);
00860       CASE(4, args[0], args[1], args[2], args[3]);
00861 #undef CASE
00862     default:
00863       throw std::runtime_error("Not implemented");
00864     }
00865   }
00866 
00867   void throwException(bool stdexcept)
00868   {
00869     if (stdexcept)
00870       throw std::runtime_error("KABOOM");
00871     else
00872       throw "KABOOM";
00873   }
00874 
00875   std::vector<unsigned long> socketStats()
00876   {
00877     std::vector<unsigned long> res;
00878     urbi::UClient* cl = urbi::getDefaultClient();
00879     if (!cl)
00880       return res;
00881    res.push_back(cl->bytesSent());
00882    res.push_back(cl->bytesReceived());
00883    return res;
00884   }
00885 
00886   // Test templates UVar.as, UVar.==, UVar.fill
00887   void manyWriteTest(int i)
00888   {
00889     #define CHECK                                     \
00890     if (d.size() !=2 || d[0] != 1 || d[1] != 2)       \
00891       throw std::runtime_error("vector is not what we expect")
00892     std::vector<ufloat> d;
00893     d.push_back(1);
00894     d.push_back(2);
00895     urbi::UVar& v =*vars[i];
00896     v = d;
00897     d = v.as(&d);
00898     CHECK;
00899     d = v.as<std::vector<ufloat> >();
00900     CHECK;
00901     v.fill(d);
00902     if (!(v == d))
00903       throw std::runtime_error("v != d");
00904     CHECK;
00905     boost::unordered_map<std::string, UObject*> vu;
00906     vu["coin"] = this;
00907     a = vu;
00908     a.fill(vu);
00909     if (!libport::mhas(vu, "coin") || vu["coin"] != this)
00910       throw std::runtime_error("hash is not what we expect");
00911   }
00912 
00913   ufloat area(Rect r)
00914   {
00915     return libport::round((r.a.x-r.b.x) * (r.a.y  - r.b.y));
00916   }
00917 
00918   PointOfInterest transmitPointOfInterest(PointOfInterest p)
00919   {
00920     return p;
00921   }
00922 
00923   void writePointOfInterest(urbi::UVar& target, PointOfInterest p)
00924   {
00925     target = p;
00926   }
00927 
00928   PointOfInterest readPointOfInterest(urbi::UVar& source)
00929   {
00930     source.syncValue();
00931     return source.as((PointOfInterest*)0);
00932   }
00933 
00934   Rect translate(Rect r, Point v)
00935   {
00936     r.a.x += v.x;
00937     r.a.y += v.y;
00938     r.b.x += v.x;
00939     r.b.y += v.y;
00940     return r;
00941   }
00942 
00943   Rect makeRect()
00944   {
00945     return Rect();
00946   }
00947 
00948   std::vector<Rect> multiTranslate(std::vector<Rect> src, Point v)
00949   {
00950     foreach(Rect& r, src)
00951       r = translate(r, v);
00952     return src;
00953   }
00954 
00955   std::vector<ufloat> unpack(UPackedData<ufloat> d)
00956   {
00957     return d;
00958   }
00959 
00960   UPackedData<ufloat> pack(std::vector<ufloat> d)
00961   {
00962     return d;
00963   }
00964   urbi::UVar a, b, c, d, unbound;
00965   urbi::UVar* vars[10];
00966   urbi::InputPort* ports[5];
00967   urbi::UEvent ev;
00968 
00969   //name of var that trigerred notifyChange
00970   urbi::UVar lastChange;
00971   //value read on said var
00972   urbi::UVar lastChangeVal;
00973   //name of var that triggered notifyAccess
00974   urbi::UVar lastAccess;
00975   //value written to said var
00976   urbi::UVar lastAccessVal;
00977   //Set to 0 in ctor, 1 in init
00978   urbi::UVar initCalled;
00979 
00980   // Periodic write target (0, 1 or 2 for a, b or c)
00981   urbi::UVar periodicWriteTarget;
00982   // Write rate (seconds)
00983   urbi::UVar periodicWriteRate;
00984   // Write data type
00985   urbi::UVar periodicWriteType;
00986   // Number of writes per call
00987   urbi::UVar periodicWriteCount;
00988 
00989   // If an UVar with the name in removeNotify reaches a callback,
00990   // unnotify will be called.
00991   urbi::UVar removeNotify;
00992   // Number of calls to onChange
00993   urbi::UVar changeCount;
00994   // Cached value to ensure consistency in remote mode.
00995   int count;
00996   static int destructionCount;
00997 };
00998 
00999 int all::destructionCount = 0;
01000 
01001 ::urbi::URBIStarter<all>
01002     starter1(urbi::isPluginMode() ? "all"  : "remall"),
01003     starter2(urbi::isPluginMode() ? "all2" : "remall2");