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