|
Urbi SDK Remote for C++
2.7.3
|
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");