Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2010 George Tzanetakis <gtzan@cs.uvic.ca> 00003 ** 00004 ** This program is free software; you can redistribute it and/or modify 00005 ** it under the terms of the GNU General Public License as published by 00006 ** the Free Software Foundation; either version 2 of the License, or 00007 ** (at your option) any later version. 00008 ** 00009 ** This program is distributed in the hope that it will be useful, 00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 ** GNU General Public License for more details. 00013 ** 00014 ** You should have received a copy of the GNU General Public License 00015 ** along with this program; if not, write to the Free Software 00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #include <marsyas/system/MarSystem.h> 00020 #include <marsyas/system/MarControlManager.h> 00021 #include <marsyas/sched/EvValUpd.h> 00022 #include <marsyas/sched/TmVirtualTime.h> 00023 #include "../common_source.h" 00024 00025 #include <algorithm> 00026 #include <stack> 00027 00028 using std::ostringstream; 00029 using std::cout; 00030 using std::endl; 00031 using std::vector; 00032 using std::pair; 00033 using std::map; 00034 using std::istream; 00035 using std::ostream; 00036 using std::string; 00037 00038 00039 using namespace Marsyas; 00040 00041 MarSystem::MarSystem(mrs_string type, mrs_string name): 00042 parent_scope_(0) 00043 { 00044 parent_ = NULL; 00045 name_ = name; 00046 type_ = type; 00047 active_ = true; 00048 prefix_ = "/" + type_ + "/" + name_ + "/"; 00049 absPath_ = prefix_; 00050 00051 inObservations_ = 0; 00052 inSamples_ = 0; 00053 onObservations_ = 0; 00054 onSamples_ = 0; 00055 osrate_ = 0.0; 00056 israte_ = 0.0; 00057 00058 inStabilizingDelay_ = 0; 00059 onStabilizingDelay_ = 0; 00060 00061 tonSamples_ = 0; 00062 tonObservations_ = 0; 00063 tinSamples_ = 0; 00064 tinObservations_ = 0; 00065 tosrate_ = 0.0; 00066 tisrate_ = 0.0; 00067 tinStabilizingDelay_ = 0; 00068 tonStabilizingDelay_ = 0; 00069 tonObsNames_ = ""; 00070 onObsNames_ = ""; 00071 00072 addToStabilizingDelay_ = 0; 00073 00074 00075 isComposite_ = false; 00076 00077 MATLABscript_ = ""; 00078 00079 isUpdating_ = false; 00080 00081 //add default controls that 00082 //all MarSystems should have 00083 addControls(); 00084 00085 scheduler_.removeAll(); 00086 TmTimer* t = new TmVirtualTime("Virtual",this); 00087 scheduler_.addTimer(t); 00088 } 00089 00090 // copy constructor 00091 MarSystem::MarSystem(const MarSystem& a): 00092 parent_scope_(0) 00093 { 00094 parent_ = NULL; 00095 type_ = a.type_; 00096 name_ = a.name_; 00097 prefix_ = a.prefix_; 00098 absPath_ = a.absPath_; 00099 active_ = true; 00100 00101 osrate_ = 0.0; 00102 inObservations_ = 0; 00103 onObservations_ = 0; 00104 inSamples_ = 0; 00105 israte_ = 0.0; 00106 inStabilizingDelay_ = 0; 00107 onStabilizingDelay_ = 0; 00108 00109 onSamples_ = 0; 00110 tonObsNames_ = ""; 00111 onObsNames_ = ""; 00112 00113 tonSamples_ = 0; 00114 tonObservations_ = 0; 00115 tinSamples_ = 0; 00116 tinObservations_ = 0; 00117 tosrate_ = 0.0; 00118 tisrate_ = 0.0; 00119 tinStabilizingDelay_ = 0; 00120 tonStabilizingDelay_ = 0; 00121 00122 addToStabilizingDelay_ = 0; 00123 00124 00125 MATLABscript_ = a.MATLABscript_; 00126 00127 isUpdating_ = false; 00128 00129 //clone controls (cloned controls will have no links! - they have to be relinked as done below) 00130 { 00131 controls_.clear(); 00132 for (ControlItr ctrlIter_ = a.controls_.begin(); ctrlIter_ != a.controls_.end(); ++ctrlIter_) 00133 { 00134 //clone all controls 00135 controls_[ctrlIter_->first] = ctrlIter_->second->clone(); 00136 //set new MarSystem parent 00137 controls_[ctrlIter_->first]->setMarSystem(this); 00138 } 00139 } 00140 00141 //update the "references" to the controls 00142 ctrl_inSamples_ = getctrl("mrs_natural/inSamples"); 00143 ctrl_inObservations_ = getctrl("mrs_natural/inObservations"); 00144 ctrl_israte_ = getctrl("mrs_real/israte"); 00145 ctrl_inObsNames_ = getctrl("mrs_string/inObsNames"); 00146 ctrl_onSamples_ = getctrl("mrs_natural/onSamples"); 00147 ctrl_onObservations_ = getctrl("mrs_natural/onObservations"); 00148 ctrl_osrate_ = getctrl("mrs_real/osrate"); 00149 ctrl_onObsNames_ = getctrl("mrs_string/onObsNames"); 00150 ctrl_debug_ = getctrl("mrs_bool/debug"); 00151 ctrl_verbose_ = getctrl("mrs_bool/verbose"); 00152 ctrl_mute_ = getctrl("mrs_bool/mute"); 00153 ctrl_active_ = getctrl("mrs_bool/active"); 00154 ctrl_processedData_ = getctrl("mrs_realvec/processedData"); 00155 ctrl_inStabilizingDelay_ = getctrl("mrs_natural/inStabilizingDelay"); 00156 ctrl_onStabilizingDelay_ = getctrl("mrs_natural/onStabilizingDelay"); 00157 00158 //clone children (if any) => mutexes [?] 00159 isComposite_ = a.isComposite_; 00160 if (isComposite_) 00161 { 00162 child_count_t child_count = a.marsystems_.size(); 00163 for (child_count_t i=0; i< child_count; ++i) 00164 { 00165 MarSystem* clonedChild = (*a.marsystems_[i]).clone(); 00166 addMarSystem(clonedChild); 00167 clonedChild->relinkControls((*a.marsystems_[i])); 00168 } 00169 } 00170 00171 this->relinkControls(a); 00172 00173 // // "re-link" controls => mutexes [?] 00174 // for(ControlItr ctrlIter_ = a.controls_.begin(); ctrlIter_ != a.controls_.end(); ++ctrlIter_) 00175 // { 00176 // // get original links... 00177 // vector<pair<MarControlPtr, MarControlPtr> > originalLinks = ctrlIter_->second->getLinks(); 00178 // 00179 // // ...clear clone's links... 00180 // //controls_[ctrlIter_->first]->unlinkFromAll(); //[?] is this really necessary? 00181 // 00182 // //... and re-establish links between the new cloned controls 00183 // vector<pair<MarControlPtr, MarControlPtr> >::const_iterator linksIter; 00184 // for (linksIter = originalLinks.begin(); linksIter != originalLinks.end(); ++linksIter) 00185 // { 00186 // //ignore the root link (not important for relinking) 00187 // if(linksIter->first() == linksIter->second()) 00188 // continue; 00189 // 00190 // //check if this control links to someone, and link them accordingly... 00191 // if(linksIter->first() == ctrlIter_->second()) 00192 // { 00193 // MarControlPtr ctrl2Link2 = this->getControl(linksIter->second->getMarSystem()->getAbsPath() + linksIter->second->getName(), true); 00194 // //controls from siblings may not exist yet at this time, so we must not try to link 00195 // //to their yet invalid controls. Just link with controls from 00196 // //the parent or already existing siblings and children. The remaining ones will be linked 00197 // //by the siblings when they get created. 00198 // if (!ctrl2Link2.isInvalid()) 00199 // { 00200 // controls_[ctrlIter_->first]->linkTo(ctrl2Link2); 00201 // } 00202 // } 00203 // //...or check if someone links to this control, and link them accordingly 00204 // else if(linksIter->second() == ctrlIter_->second()) 00205 // { 00206 // MarControlPtr linkedCtrl = this->getControl(linksIter->first->getMarSystem()->getAbsPath() + linksIter->first->getName(), true); 00207 // //controls from siblings may not exist yet at this time, so we must not try to link 00208 // //to their yet invalid controls. Just link with controls from 00209 // //the parent or already existing siblings and children. The remaining ones will be linked 00210 // //by the siblings when they get created. 00211 // if (!linkedCtrl.isInvalid()) 00212 // { 00213 // linkedCtrl->linkTo(controls_[ctrlIter_->first]); 00214 // } 00215 // } 00216 // } 00217 // } 00218 00219 //recreate schedule objects => mutexes [?] 00220 00221 scheduler_.removeAll(); 00222 TmTimer* t = new TmVirtualTime("Virtual",this); 00223 scheduler_.addTimer(t); 00224 } 00225 00226 void 00227 MarSystem::relinkControls(const MarSystem& a) 00228 { 00229 // "re-link" controls => mutexes [?] 00230 for (ControlItr ctrlIter_ = a.controls_.begin(); ctrlIter_ != a.controls_.end(); ++ctrlIter_) 00231 { 00232 // get original links... 00233 vector<pair<MarControlPtr, MarControlPtr> > originalLinks = ctrlIter_->second->getLinks(); 00234 00235 // ...clear clone's links... 00236 //controls_[ctrlIter_->first]->unlinkFromAll(); //[?] is this really necessary? 00237 00238 //... and re-establish links between the new cloned controls 00239 vector<pair<MarControlPtr, MarControlPtr> >::const_iterator linksIter; 00240 for (linksIter = originalLinks.begin(); linksIter != originalLinks.end(); ++linksIter) 00241 { 00242 //ignore the root link (not important for relinking) 00243 if (linksIter->first() == linksIter->second()) 00244 continue; 00245 00246 //check if this control links to someone, and link them accordingly... 00247 if (linksIter->first() == ctrlIter_->second()) 00248 { 00249 MarControlPtr ctrl2Link2 = this->getControl(linksIter->second->getMarSystem()->getAbsPath() + linksIter->second->getName(), true); 00250 //controls from siblings may not exist yet at this time, so we must not try to link 00251 //to their yet invalid controls. Just link with controls from 00252 //the parent or already existing siblings and children. The remaining ones will be linked 00253 //by the siblings when they get created. 00254 if (!ctrl2Link2.isInvalid()) 00255 { 00256 controls_[ctrlIter_->first]->linkTo(ctrl2Link2); 00257 } 00258 } 00259 //...or check if someone links to this control, and link them accordingly 00260 else if (linksIter->second() == ctrlIter_->second()) 00261 { 00262 MarControlPtr linkedCtrl = this->getControl(linksIter->first->getMarSystem()->getAbsPath() + linksIter->first->getName(), true); 00263 //controls from siblings may not exist yet at this time, so we must not try to link 00264 //to their yet invalid controls. Just link with controls from 00265 //the parent or already existing siblings and children. The remaining ones will be linked 00266 //by the siblings when they get created. 00267 if (!linkedCtrl.isInvalid()) 00268 { 00269 linkedCtrl->linkTo(controls_[ctrlIter_->first]); 00270 } 00271 } 00272 } 00273 } 00274 } 00275 00276 MarSystem::~MarSystem() 00277 { 00278 //delete children (if any) 00279 child_count_t child_count = marsystems_.size(); 00280 for (child_count_t i=0; i< child_count; ++i) 00281 { 00282 delete marsystems_[i]; 00283 } 00284 00285 child_count_t attached_count = attached_marsystems_.size(); 00286 for (child_count_t i=0; i < attached_count; ++i) 00287 { 00288 delete attached_marsystems_[i]; 00289 } 00290 00291 removeFromScope(); 00292 } 00293 00294 void 00295 MarSystem::addControls() 00296 { 00297 //input pin controls (with state) 00298 addctrl("mrs_natural/inSamples", MRS_DEFAULT_SLICE_NSAMPLES, ctrl_inSamples_); 00299 setctrlState(ctrl_inSamples_, true); 00300 addctrl("mrs_natural/inObservations", MRS_DEFAULT_SLICE_NOBSERVATIONS, ctrl_inObservations_); 00301 setctrlState(ctrl_inObservations_, true); 00302 addctrl("mrs_real/israte", MRS_DEFAULT_SLICE_SRATE, ctrl_israte_); 00303 setctrlState(ctrl_israte_, true); 00304 addctrl("mrs_string/inObsNames", ",", ctrl_inObsNames_); 00305 setctrlState(ctrl_inObsNames_, true); 00306 addctrl("mrs_natural/inStabilizingDelay", 0, ctrl_inStabilizingDelay_); 00307 setctrlState(ctrl_inStabilizingDelay_, true); 00308 00309 //output pin controls (stateless) 00310 addctrl("mrs_natural/onSamples", MRS_DEFAULT_SLICE_NSAMPLES, ctrl_onSamples_); 00311 addctrl("mrs_natural/onObservations", MRS_DEFAULT_SLICE_NOBSERVATIONS, ctrl_onObservations_); 00312 addctrl("mrs_real/osrate", MRS_DEFAULT_SLICE_SRATE, ctrl_osrate_); 00313 addctrl("mrs_string/onObsNames", ",", ctrl_onObsNames_); 00314 addctrl("mrs_natural/onStabilizingDelay", 0, ctrl_onStabilizingDelay_); 00315 setctrlState(ctrl_onStabilizingDelay_, true); 00316 00317 inObservations_ = ctrl_inObservations_->to<mrs_natural>(); 00318 inSamples_ = ctrl_inSamples_->to<mrs_natural>(); 00319 inStabilizingDelay_ = ctrl_inStabilizingDelay_->to<mrs_natural>(); 00320 onObservations_ = ctrl_onObservations_->to<mrs_natural>(); 00321 onSamples_ = ctrl_onSamples_->to<mrs_natural>(); 00322 onStabilizingDelay_ = ctrl_onStabilizingDelay_->to<mrs_natural>(); 00323 00324 //other controls: 00325 addctrl("mrs_bool/debug", false, ctrl_debug_); //no debug by default 00326 addctrl("mrs_bool/verbose", false, ctrl_verbose_); 00327 addctrl("mrs_bool/mute", false, ctrl_mute_); //unmuted by default 00328 addctrl("mrs_bool/active",true, ctrl_active_); //active by default 00329 00330 inTick_.create(inObservations_, inSamples_); 00331 outTick_.create(onObservations_, onSamples_); 00332 00333 addctrl("mrs_realvec/processedData", outTick_, ctrl_processedData_); 00334 00335 ctrl_active_->setState(true); 00336 00337 active_ = ctrl_active_->to<bool>(); 00338 } 00339 00340 bool 00341 MarSystem::addMarSystem(MarSystem *marsystem) 00342 { 00343 //idiot proof 1 00344 if (this == marsystem) 00345 { 00346 MRSWARN("MarSystem::addMarSystem - Trying to add MarSystem to itself - failing..."); 00347 return false; 00348 } 00349 00350 if (marsystem == NULL) 00351 { 00352 MRSWARN("MarSystem::addMarSystem - Adding a NULL MarSystem - failing..."); 00353 return false; 00354 } 00355 00356 //idiot proof 2 00357 MarSystem* msys = parent_; 00358 while (msys) 00359 { 00360 if (msys == marsystem) 00361 { 00362 MRSWARN("MarSystem::addMarSystem - Trying to add an ancestor MarSystem as a child - failing..."); 00363 return false; 00364 } 00365 msys = msys->parent_; 00366 } 00367 00368 //it's only possible to add MarSystems to Composites 00369 if (isComposite_) 00370 { 00371 vector<MarSystem*>::iterator it; 00372 bool replaced = false; 00373 //check if a child MarSystem with the same type/name 00374 //exists. If it does, replace it with the new one. 00375 for (it = marsystems_.begin(); it != marsystems_.end(); ++it) 00376 { 00377 if ((*it)->getName() == marsystem->getName() && 00378 (*it)->getType() == marsystem->getType()) 00379 { 00380 //delete current child MarSystem 00381 delete (*it); 00382 //and replace it with the new one 00383 (*it) = marsystem; 00384 replaced = true; 00385 break; 00386 } 00387 } 00388 //if no replacement took place, then add the 00389 //new MarSystem as a new child 00390 if (!replaced) 00391 { 00392 marsystems_.push_back(marsystem); 00393 } 00394 //set parent for the new child MarSystem 00395 marsystem->setParent(this); 00396 00397 //update child MarSystem 00398 //marsystem->update(); //superfluous update call! It will be called by this->update() [!] 00399 //update parent MarSystem 00400 update(); 00401 return true; 00402 } 00403 else 00404 { 00405 MRSWARN("MarSystem::addMarSystem - Trying to add MarSystem to a non-Composite - failing..."); 00406 return false; 00407 } 00408 } 00409 00410 bool MarSystem::isDescendentOf(MarSystem *ancestor) 00411 { 00412 MarSystem *system = parent_; 00413 while(system) 00414 { 00415 if (system == ancestor) 00416 return true; 00417 system = system->parent_; 00418 } 00419 return false; 00420 } 00421 00422 void MarSystem::addToScope( MarSystem * ancestor ) 00423 { 00424 //MRSMSG("MarSystem::addToScope: " << getPrefix() << " >> " << ancestor->getAbsPath()); 00425 00426 if (ancestor == this) 00427 throw std::runtime_error("MarSystem can not have itself in scope."); 00428 00429 if (parent_scope_) 00430 throw std::runtime_error("MarSystem already in another scope."); 00431 00432 //if (!isDescendentOf(ancestor)) 00433 //throw std::runtime_error("MarSystem must be descendent to be in scope."); 00434 00435 const string & name = getName(); 00436 if (name.empty()) 00437 throw std::runtime_error("MarSystem has no name."); 00438 00439 std::map<string, MarSystem*>::iterator it; 00440 it = ancestor->scope_.find(name); 00441 if (it != ancestor->scope_.end()) 00442 { 00443 std::ostringstream msg; 00444 msg << "MarSystem with same name already in this scope."; 00445 throw std::runtime_error(msg.str()); 00446 } 00447 00448 ancestor->scope_[name] = this; 00449 00450 parent_scope_ = ancestor; 00451 } 00452 00453 void MarSystem::removeFromScope() 00454 { 00455 MarSystem *ancestor = parent_scope_; 00456 if (!ancestor) 00457 return; 00458 00459 parent_scope_ = 0; 00460 00461 std::map<string, MarSystem*>::iterator it; 00462 it = ancestor->scope_.find(getName()); 00463 if (it == ancestor->scope_.end()) 00464 return; 00465 00466 ancestor->scope_.erase(it); 00467 } 00468 00469 MarSystem* 00470 MarSystem::getChildMarSystem(std::string childPath) 00471 { 00472 //check for an absolute path, and if necessary convert it 00473 //to a relative path 00474 if (childPath[0] == '/') 00475 { 00476 //is this absolute path pointing to this MarSystem? => mutexes [?] 00477 if (childPath.substr(0, absPath_.length()) == absPath_) 00478 { 00479 //return control path without the absolute path 00480 //(i.e. return the relative path) 00481 childPath = childPath.substr(absPath_.length(), childPath.length()); 00482 } 00483 else 00484 { 00485 //this absolute path does not point to this MarSystem or any of its 00486 //children... 00487 MRSWARN("MarSystem::getChildMarSystem: " + childPath + " is an invalid path @ " + absPath_); 00488 return NULL; 00489 } 00490 } 00491 //from this point, childPath is for sure a relative path. 00492 00493 //start by checking if childPath is not empty (or resulted from an absolute 00494 //path pointing to this MarSystem itself and not to any of its children) 00495 if (childPath == "") 00496 { 00497 MRSWARN("MarSystem::getChildMarSystem: path does not point to a child MarSystem"); 00498 return NULL; 00499 } 00500 //...otherwise, search among its children... => mutexes [?] 00501 else if (isComposite_) 00502 { 00503 vector<MarSystem*>::const_iterator msysIter; 00504 for (msysIter = marsystems_.begin(); msysIter != marsystems_.end(); ++msysIter) 00505 { 00506 mrs_string prefix = (*msysIter)->getPrefix(); 00507 prefix = prefix.substr(1, prefix.length()-2); //ignore leading and trailing "/" 00508 if (childPath.substr(0, prefix.length()) == prefix) 00509 { 00510 //a matching child was found! 00511 if (childPath.length() == prefix.length()) 00512 return (*msysIter); 00513 //The prefix may be the same, but we still need to check that the next char is a / 00514 // Otherwise in the case of system Sys1, and Sys10, it will appear that Sys10 is the child Sys1 00515 else if (childPath.length() > prefix.length() && childPath.substr(prefix.length() , 1) == "/") 00516 { 00517 //remove parent prefix from childPath, and continue searching recursively in children 00518 childPath = childPath.substr(prefix.length()+1,childPath.length()); 00519 return (*msysIter)->getChildMarSystem(childPath); 00520 } 00521 } 00522 } 00523 MRSWARN("MarSystem::getChildMarsystem(): " + childPath + " not found!"); 00524 return NULL; 00525 } 00526 else 00527 { 00528 MRSWARN("MarSystem::getChildMarsystem(): " + childPath + " not found!"); 00529 return NULL; 00530 } 00531 } 00532 00533 void 00534 MarSystem::setParent(const MarSystem* parent) // => mutexes [?] 00535 { 00536 parent_ = const_cast<MarSystem*>(parent); 00537 00538 // Update our path, and propogate changes to children (if applicable) 00539 updatePath(); 00540 } 00541 00542 void 00543 MarSystem::setName(mrs_string name) // => mutexes [?] 00544 { 00545 if (name == name_) 00546 return; 00547 00548 mrs_string oldPrefix = prefix_; 00549 prefix_ = "/" + type_ + "/" + name + "/"; 00550 name_ = name; 00551 00552 //update path accordingly 00553 mrs_string::size_type pos = absPath_.find(oldPrefix, 0); 00554 mrs_string uppath = absPath_.substr(0, pos); 00555 mrs_string downpath = absPath_.substr(oldPrefix.length()+pos, absPath_.length()-(oldPrefix.length()+pos)); 00556 absPath_ = uppath + prefix_ + downpath; 00557 00558 if (isComposite_) 00559 { 00560 child_count_t child_count = marsystems_.size(); 00561 for (child_count_t i=0; i<child_count; ++i) 00562 { 00563 marsystems_[i]->updatePath(); 00564 } 00565 } 00566 } 00567 00568 void 00569 MarSystem::setType(mrs_string type) // => mutexes [?] 00570 { 00571 if (type == type_) 00572 return; 00573 00574 mrs_string oldPrefix = prefix_; 00575 prefix_ = "/" + type + "/" + name_ + "/"; 00576 type_ = type; 00577 00578 //update path accordingly 00579 mrs_string::size_type pos = absPath_.find_last_of(oldPrefix, 0); 00580 mrs_string uppath = absPath_.substr(0, pos); 00581 mrs_string downpath = absPath_.substr(oldPrefix.length()+pos, absPath_.length()-(oldPrefix.length()+pos)); 00582 absPath_ = uppath + prefix_ + downpath; 00583 00584 if (isComposite_) 00585 { 00586 child_count_t child_count = marsystems_.size(); 00587 for (child_count_t i=0; i<child_count; ++i) 00588 { 00589 marsystems_[i]->updatePath(); 00590 } 00591 } 00592 } 00593 00594 const std::string & 00595 MarSystem::getType() const // => mutexes [?] 00596 { 00597 return type_; 00598 } 00599 00600 const std::string & 00601 MarSystem::getName() const // => mutexes [?] 00602 { 00603 return name_; 00604 } 00605 00606 const std::string & 00607 MarSystem::getPrefix() const // => mutexes [?] 00608 { 00609 return prefix_; 00610 } 00611 00612 const std::string & 00613 MarSystem::getAbsPath() const // => mutexes [?] 00614 { 00615 return absPath_; 00616 } 00617 00618 void 00619 MarSystem::updatePath() // => mutexes [?] 00620 { 00621 if (parent_) 00622 { 00623 absPath_ = parent_->getAbsPath() + type_ + '/' + name_ + '/'; 00624 } 00625 else 00626 { 00627 absPath_ = prefix_; 00628 } 00629 00630 //propagate new path to all children (if any) 00631 if (isComposite_) { 00632 child_count_t child_count = marsystems_.size(); 00633 for (child_count_t i=0; i< child_count; ++i) 00634 marsystems_[i]->updatePath(); 00635 } 00636 } 00637 00638 void 00639 MarSystem::checkFlow(realvec& in, realvec& out) 00640 { 00641 irows_ = in.getRows(); 00642 icols_ = in.getCols(); 00643 orows_ = out.getRows(); 00644 ocols_ = out.getCols(); 00645 00646 if (ctrl_debug_->isTrue()) 00647 { 00648 MRSWARN("Debug CheckFlow Information"); 00649 MRSWARN("MarSystem Type = " << type_); 00650 MRSWARN("MarSystem Name = " << name_); 00651 MRSWARN("inObservAtions_ = " << inObservations_); 00652 MRSWARN("inSamples_ = " << inSamples_); 00653 MRSWARN("onObservations_ = " << onObservations_); 00654 MRSWARN("onSamples_ = " << onSamples_); 00655 MRSWARN("inStabilizingDelay_ = " << inStabilizingDelay_); 00656 MRSWARN("onStabilizingDelay_ = " << onStabilizingDelay_); 00657 MRSWARN("Input Slice Rows = " << irows_ ); 00658 MRSWARN("Input Slice Cols = " << icols_ ); 00659 MRSWARN("Output Slice Rows = " << orows_ ); 00660 MRSWARN("Output Slice Cols = " << ocols_ ); 00661 } 00662 00663 00664 MRSASSERT(irows_ == inObservations_); 00665 MRSASSERT(icols_ == inSamples_); 00666 MRSASSERT(orows_ == onObservations_); 00667 MRSASSERT(ocols_ == onSamples_); 00668 } 00669 00670 void 00671 MarSystem::process(realvec& in, realvec& out) 00672 { 00673 MRSDIAG(type_ << "/" << name_ << "::process"); 00674 #ifdef MARSYAS_FLOWCHECK 00675 checkFlow(in, out); 00676 #endif 00677 00678 #ifndef MARSYAS_NO_MARSYSTEM_OBSERVERS 00679 observer_count_t observer_count = observers_.size(); 00680 if (observer_count) 00681 { 00682 for (observer_count_t idx = 0; idx < observer_count; ++idx) 00683 { 00684 observers_[idx]->preProcess(in); 00685 } 00686 00687 myProcess(in, out); 00688 00689 for (observer_count_t idx = 0; idx < observer_count; ++idx) 00690 { 00691 observers_[idx]->postProcess(out); 00692 } 00693 } 00694 else 00695 #endif 00696 { 00697 myProcess(in, out); 00698 } 00699 00700 #ifdef MARSYAS_MATLAB 00701 if (!MATLABscript_.empty()) 00702 { 00703 MATLAB_PUT(in, name_ + "_in"); 00704 MATLAB_PUT(out, name_ + "_out"); 00705 MATLAB_EVAL(MATLABscript_); 00706 MATLAB_GET(name_+"_out", out); 00707 00708 //check if out realvec was shortened by MATLAB script... //[!] 00709 if ((out.getRows() < onObservations_)||(out.getCols() < onSamples_)) 00710 out.stretch(onObservations_, onSamples_); 00711 } 00712 #endif 00713 } 00714 00715 void 00716 MarSystem::tick() 00717 { 00718 //if MarSystem is not active, ignore ticks 00719 if (ctrl_active_->isTrue()) 00720 { 00721 scheduler_.tick(); 00722 { 00723 MarControlAccessor acc(ctrl_processedData_); 00724 realvec& processedData = acc.to<mrs_realvec>(); 00725 process(inTick_, processedData); 00726 } 00727 } 00728 else 00729 { 00730 MRSDIAG("MarSystem::tick() : MarSystem is not active! Ignoring tick command."); 00731 (void)42; 00732 } 00733 } 00734 00735 void 00736 MarSystem::myUpdate(MarControlPtr sender) 00737 { 00738 (void) sender; //suppress warning of unused parameter(s) 00739 MRSDIAG("MarSystem.cpp - MarSystem:myUpdate"); 00740 00741 //lmartins: 00742 //By default, a MarSystem does not modify the input data stream format. 00743 //Override this method on a derived MarSystem if data format changes 00744 //should take place... 00745 00746 //forward flow propagation 00747 ctrl_onSamples_->setValue(ctrl_inSamples_, NOUPDATE); 00748 ctrl_onObservations_->setValue(ctrl_inObservations_, NOUPDATE); 00749 ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE); 00750 ctrl_onObsNames_->setValue(ctrl_inObsNames_, NOUPDATE); 00751 } 00752 00753 bool 00754 MarSystem::isUpdating() 00755 { 00756 return isUpdating_; 00757 } 00758 00759 void 00760 MarSystem::update(MarControlPtr sender) 00761 { 00762 MRSDIAG(type_ << "/" << name_ << "::update"); 00763 00764 isUpdating_ = true; 00765 00766 //store current flow variables 00767 tinObservations_ = inObservations_; 00768 tinSamples_ = inSamples_; 00769 tisrate_ = israte_; 00770 tinObsNames_ = inObsNames_; 00771 tonObservations_ = onObservations_; 00772 tonSamples_ = onSamples_; 00773 tosrate_ = osrate_; 00774 tonObsNames_ = onObsNames_; 00775 tinStabilizingDelay_ = inStabilizingDelay_; 00776 tonStabilizingDelay_ = onStabilizingDelay_; 00777 00778 //sync input member variables 00779 inObservations_ = ctrl_inObservations_->to<mrs_natural>(); 00780 inSamples_ = ctrl_inSamples_->to<mrs_natural>(); 00781 israte_ = ctrl_israte_->to<mrs_real>(); 00782 inObsNames_ = ctrl_inObsNames_->to<mrs_string>(); 00783 inStabilizingDelay_ = ctrl_inStabilizingDelay_->to<mrs_natural>(); 00784 //sync output member variables 00785 onObservations_ = ctrl_onObservations_->to<mrs_natural>(); 00786 onSamples_ = ctrl_onSamples_->to<mrs_natural>(); 00787 osrate_ = ctrl_osrate_->to<mrs_real>(); 00788 onObsNames_ = ctrl_onObsNames_->to<mrs_string>(); 00789 onStabilizingDelay_ = ctrl_onStabilizingDelay_->to<mrs_natural>(); 00790 00791 // do this before myUpdate() in case it needs to be 00792 // overridden, i.e. for a Composite 00793 ctrl_onStabilizingDelay_->setValue( 00794 ctrl_inStabilizingDelay_->to<mrs_natural>() 00795 + addToStabilizingDelay_, NOUPDATE); 00796 00797 //call derived class specific update 00798 myUpdate(sender); 00799 00800 //sync input member variables 00801 inObservations_ = ctrl_inObservations_->to<mrs_natural>(); 00802 inSamples_ = ctrl_inSamples_->to<mrs_natural>(); 00803 israte_ = ctrl_israte_->to<mrs_real>(); 00804 inObsNames_ = ctrl_inObsNames_->to<mrs_string>(); 00805 inStabilizingDelay_ = ctrl_inStabilizingDelay_->to<mrs_natural>(); 00806 //sync output member variables 00807 onObservations_ = ctrl_onObservations_->to<mrs_natural>(); 00808 onSamples_ = ctrl_onSamples_->to<mrs_natural>(); 00809 osrate_ = ctrl_osrate_->to<mrs_real>(); 00810 onObsNames_ = ctrl_onObsNames_->to<mrs_string>(); 00811 onStabilizingDelay_ = ctrl_onStabilizingDelay_->to<mrs_natural>(); 00812 00813 //check active status 00814 bool active = ctrl_active_->isTrue(); 00815 //if active status changed... 00816 if (active_ != active) 00817 { 00818 active_ = active; 00819 activate(active); 00820 } 00821 00822 //resize input and output realvec if necessary 00823 if ((inObservations_ != inTick_.getRows()) || 00824 (inSamples_ != inTick_.getCols()) || 00825 (onObservations_ != outTick_.getRows()) || 00826 (onSamples_ != outTick_.getCols())) 00827 { 00828 00829 00830 inTick_.create(inObservations_, inSamples_); 00831 { 00832 MarControlAccessor acc(ctrl_processedData_); 00833 realvec& processedData = acc.to<mrs_realvec>(); 00834 processedData.create(onObservations_, onSamples_); 00835 00836 } 00837 00838 00839 } 00840 00841 //check for OUT-FLOW modifications without parent knowledge!! 00842 if (parent_) 00843 { 00844 if (tonObservations_ != onObservations_ || 00845 tonSamples_ != onSamples_ || 00846 tosrate_ != osrate_ || 00847 tonObsNames_ != onObsNames_) 00848 if (!parent_->isUpdating()) 00849 parent_->update(sender); 00850 } 00851 00852 isUpdating_ = false; 00853 } 00854 00855 void 00856 MarSystem::activate(bool state) //non-thread-safe, but this method is only supposed to be called from update(), which is thread-safe 00857 { 00858 //since this method must be public (so it can be called in Composite::activate()) 00859 //we must guarantee that the "mrs_bool/active" control is in sync with any eventual 00860 //direct calls to MarSystem::activate() from client code 00861 if (ctrl_active_->to<bool>() != state) 00862 { 00863 ctrl_active_->setValue(state, NOUPDATE); 00864 active_ = state; 00865 } 00866 00867 //execute any code needed to run when activating/deactivating 00868 //the derived MarSystem 00869 localActivate(state); 00870 } 00871 00872 void 00873 MarSystem::localActivate(bool state) 00874 { 00875 //call activate for all Composite's components 00876 if (isComposite_) 00877 { 00878 child_count_t child_count = marsystems_.size(); 00879 for (child_count_t i=0; i<child_count; ++i) 00880 { 00881 //marsystems_[i]->activate(state); 00882 marsystems_[i]->updControl("mrs_bool/active", state); //thread-safe 00883 } 00884 } 00885 } 00886 00887 mrs_string 00888 MarSystem::getControlRelativePath(mrs_string cname) const 00889 { 00890 // If the cname starts with an '/', it is an absolute path 00891 // that has to be made relative. 00892 if (cname[0] == '/') 00893 { 00894 //is this absolute path pointing to this MarSystem? // => mutexes [?] 00895 if (cname.substr(0, absPath_.length()) == absPath_) 00896 { 00897 //return control path without the absolute path 00898 //(i.e. return the relative path) 00899 return cname.substr(absPath_.length(), cname.length()); 00900 } 00901 else 00902 { 00903 return ""; 00904 } 00905 } 00906 else 00907 { 00908 // cname is already a relative path, so we can return that. 00909 return cname; 00910 } 00911 } 00912 00913 mrs_string 00914 MarSystem::getControlLocalPath(mrs_string cname) const 00915 { 00916 // Convert cname to the canonical relative format. 00917 cname = getControlRelativePath(cname); 00918 if (cname == "") 00919 { 00920 // Not a control from this MarSystem or its children. 00921 return ""; 00922 } 00923 00924 // A local path should have only one '/' (e.g. "mrs_xxx/nnnn"), 00925 // otherwise it's probably a control from a child MarSystem. 00926 if (cname.find_first_of('/') == cname.find_last_of('/') && 00927 cname.find_first_of('/') != mrs_string::npos) 00928 { 00929 // This is a relative and local path, so just return it 00930 return cname; 00931 } 00932 else 00933 { 00934 // This is not a local control => return invalid name 00935 return ""; 00936 } 00937 } 00938 00939 bool 00940 MarSystem::linkControl(mrs_string cname1, mrs_string cname2, bool update) 00941 { 00942 //Links the control cname1 with the control cname 2. 00943 // 00944 //Link fails case both cname1 and cname2 point to non-existing controls. 00945 // 00946 //cname1 should point to a local or child control (using an absolute control pathname, 00947 //a local control pathname or a relative pathname). 00948 //If control corresponding to cname1 does not exist locally or in any child, 00949 //a proxy control is created and added to the corresponding MarSystem. 00950 //In all these cases, cname1 control will assume the current value of the cname2 control. 00951 // 00952 //cname2 should point to an existing control, anywhere in the network (i.e. not necessarily a 00953 //local or a child's control). 00954 //cname 2 can be a absolute, local or relative pathname. 00955 //In case cname2 points to a non-existing control, if its pathname corresponds to a local or 00956 //a child's control, a proxy control will be created in the corresponding MarSystem. 00957 //In this case, the value of the cname2 control will be set to the current value of the cname1 control. 00958 00959 //try to get the controls 00960 MarControlPtr ctrl1 = getControl(cname1, false, true);//search local and child controls 00961 MarControlPtr ctrl2 = getControl(cname2, true, true);//search everywhere in the network (including locally, at parent and among children) 00962 00963 //a control is inherently connected to itself! 00964 if (ctrl1() == ctrl2()) 00965 { 00966 if (ctrl1() == NULL) 00967 { 00968 MRSWARN("MarSystem::linkControl - Impossible to link two non-existing controls: " + cname1+" --> "+cname2); 00969 return false; 00970 } 00971 else 00972 return true; 00973 } 00974 00975 //if 2nd control does not exist somewhere in the network, 00976 //try to create one locally or in children (and assign it the value of the 1st control) 00977 if (ctrl2.isInvalid()) 00978 { 00979 //MRSWARN("MarSystem::linkControl - 2nd control does not exist anywhere: " + cname2 + " -> THIS MAY BE NORMAL WHEN LOADING A MARSYSTEM NETWORK FROM A .mpl FILE!"); 00980 //return false; 00981 00982 mrs_string relativecname = getControlRelativePath(cname2); 00983 mrs_string localcname = getControlLocalPath(cname2); 00984 00985 //if cname2 is a local control path, add it to this MarSystem 00986 if (localcname != "") 00987 { 00988 if (!addControl(cname2, ctrl1->clone(), ctrl2)) 00989 { 00990 MRSWARN("MarSystem::linkControl - Error creating new proxy control " + cname2 + " @ " + getAbsPath()); 00991 return false; 00992 } 00993 MRSDIAG("MarSystem::linkControl - Added new proxy control " + cname2 + " @ " + getAbsPath()); 00994 ctrl2->setState(false); //proxy controls never need to have state! 00995 } 00996 //if cname2 is a relative path, check among children for a matching MarSystem 00997 //where to add the new link control 00998 else if (relativecname != "") 00999 { 01000 //get the MarSystem path from relativecname 01001 mrs_string::size_type pos = relativecname.find("/mrs_", 0); 01002 mrs_string relativepath = relativecname.substr(0, pos); 01003 01004 MarSystem* msys = getChildMarSystem(relativepath); 01005 if (msys) 01006 { 01007 mrs_string cname = relativecname.substr(pos+1, relativecname.length()); 01008 if (!msys->addControl(cname, ctrl1->clone(), ctrl2)) 01009 { 01010 MRSWARN("MarSystem::linkControl - Error creating new link control " + cname2 + " @ " + msys->getAbsPath()); 01011 return false; 01012 } 01013 MRSDIAG("MarSystem::linkControl - Added new proxy control " + cname2 + " @ " + msys->getAbsPath()); 01014 ctrl2->setState(false); //proxy controls never need to have state! 01015 } 01016 else 01017 { 01018 MRSWARN("MarSystem::linkControl - Error creating new link control: " + cname2 + " is an invalid path"); 01019 return false; 01020 } 01021 } 01022 //if cname1 path is not a valid path, nor a path pointing to any of the children 01023 //it is not possible to add the new link control... 01024 else 01025 { 01026 MRSWARN("MarSystem::linkControl - Error creating new link control: " + cname2 + " is an invalid path"); 01027 return false; 01028 } 01029 } 01030 01031 //check if the first control already exists or if we have 01032 // to create and add it to the corresponding MarSystem 01033 if (ctrl1.isInvalid()) 01034 { 01035 mrs_string relativecname = getControlRelativePath(cname1); 01036 mrs_string localcname = getControlLocalPath(cname1); 01037 01038 //if cname1 is a local control path, add it to this MarSystem 01039 if (localcname != "") 01040 { 01041 if (!addControl(cname1, ctrl2->clone(), ctrl1)) 01042 { 01043 MRSWARN("MarSystem::linkControl - Error creating new link control " + cname1 + " @ " + getAbsPath()); 01044 return false; 01045 } 01046 MRSDIAG("MarSystem::linkControl - Added new proxy control " + cname1 + " @ " + getAbsPath()); 01047 ctrl1->setState(false); //proxy controls never need to have state! 01048 } 01049 //if cname1 is a relative path, check among children for a matching MarSystem 01050 //where to add the new link control 01051 else if (relativecname != "") 01052 { 01053 //get the MarSystem path from relativecname 01054 mrs_string::size_type pos = relativecname.find("/mrs_", 0); 01055 mrs_string relativepath = relativecname.substr(0, pos); 01056 01057 MarSystem* msys = getChildMarSystem(relativepath); 01058 if (msys) 01059 { 01060 mrs_string cname = relativecname.substr(pos+1, relativecname.length()); 01061 if (!msys->addControl(cname, ctrl2->clone(), ctrl1)) 01062 { 01063 MRSWARN("MarSystem::linkControl - Error creating new link control " + cname1 + " @ " + msys->getAbsPath()); 01064 return false; 01065 } 01066 MRSDIAG("MarSystem::linkControl - Added new proxy control " + cname1 + " @ " + msys->getAbsPath()); 01067 ctrl1->setState(false); //proxy controls never need to have state! 01068 } 01069 else 01070 { 01071 MRSWARN("MarSystem::linkControl - Error creating new link control: " + cname1 + "is an invalid path"); 01072 return false; 01073 } 01074 } 01075 //if cname1 path is not a valid path, nor a path pointing to any of the children 01076 //it is not possible to add the new link control... 01077 else 01078 { 01079 MRSWARN("MarSystem::linkControl - Error creating new link control: " + cname1 + "is an invalid path"); 01080 return false; 01081 } 01082 } 01083 01084 //now both controls exist 01085 //just link them 01086 return ctrl1->linkTo(ctrl2, update); 01087 } 01088 01089 MarControlPtr 01090 MarSystem::getControl(mrs_string cname, bool searchParent, bool searchChildren) 01091 { 01092 //USE A CACHE FOR MORE EFFICIENT LOOK-UP?? [!] 01093 01094 //convert cname to the canonical relative format 01095 mrs_string relativecname = getControlRelativePath(cname); 01096 01097 //if this is not a control from this MarSystem or its children 01098 //ask parent (if allowed) to search for it on the remaining of the network 01099 if (relativecname == "") 01100 { 01101 if (searchParent && parent_) 01102 { 01103 return parent_->getControl(cname, true, true);//parent will also ask its parent if necessary // => mutexes [?] 01104 } 01105 else //parent search not allowed, so the control was not found => return invalid control 01106 { 01107 //MRSWARN("MarSystem::getControl - Unsupported control name: " + cname + " @ " + absPath_ + " -> THIS MAY BE NORMAL DURING CLONING!"); 01108 return MarControlPtr(); 01109 } 01110 } 01111 //check if this relative control path points to a possible local control 01112 mrs_string localcname = getControlLocalPath(relativecname); 01113 if (localcname != "") 01114 { 01115 //This may be a local control, so look for it 01116 if (controls_.find(localcname) != controls_.end()) 01117 { 01118 return controls_[localcname]; //control found 01119 } 01120 else 01121 { 01122 return MarControlPtr(); //no control found with this name => return invalid control 01123 } 01124 } 01125 //definitely not a local control pathname. It can only be a relative control path. 01126 //So search in children (if allowed). 01127 else 01128 { 01129 if (searchChildren) 01130 { 01131 //search for a child that has a corresponding prefix 01132 vector<MarSystem*>::const_iterator msysIter; 01133 for (msysIter = marsystems_.begin(); msysIter != marsystems_.end(); ++msysIter) // => mutexes [?] 01134 { 01135 mrs_string prefix = (*msysIter)->getPrefix(); 01136 prefix = prefix.substr(1, prefix.length()); //ignore leading "/" 01137 if (relativecname.substr(0, prefix.length()) == prefix) 01138 { 01139 //a matching child was found! 01140 //check if the control exists in the child 01141 mrs_string childcname = relativecname.substr(prefix.length(),relativecname.length()); 01142 return (*msysIter)->getControl(childcname); 01143 } 01144 } 01145 return MarControlPtr();//no child found with corresponding prefix... 01146 } 01147 else 01148 { 01149 return MarControlPtr(); 01150 } 01151 } 01152 } 01153 01154 bool 01155 MarSystem::hasControlState(mrs_string cname) 01156 { 01157 MarControlPtr control = getControl(cname); 01158 if (control.isInvalid()) 01159 { 01160 MRSWARN("MarSystem::hasControlState Unsupported control name = " + cname); 01161 return false; 01162 } 01163 else 01164 return control->hasState(); 01165 } 01166 01167 void 01168 MarSystem::setControlState(mrs_string cname, bool state) 01169 { 01170 MarControlPtr control = getControl(cname); 01171 if (control.isInvalid()) 01172 { 01173 MRSWARN("MarControls::setState Unsupported control name = " + cname); 01174 } 01175 else 01176 control->setState(state); 01177 } 01178 01179 bool 01180 MarSystem::hasControl(mrs_string cname, bool searchChildren) 01181 { 01182 //look for local and (optionally) children controls 01183 MarControlPtr control = this->getControl(cname, false, searchChildren); 01184 return !control.isInvalid(); 01185 } 01186 01187 bool 01188 MarSystem::hasControl(MarControlPtr control, bool searchChildren) 01189 { 01190 //search local controls 01191 for (ControlItr ctrlIter_=controls_.begin(); ctrlIter_!=controls_.end(); ++ctrlIter_) 01192 { 01193 if ((ctrlIter_->second)() == control()) 01194 return true; 01195 } 01196 //search control among children (if allowed) 01197 if (searchChildren) 01198 { 01199 vector<MarSystem*>::const_iterator msysIter; 01200 for (msysIter=marsystems_.begin(); msysIter!=marsystems_.end(); ++msysIter) 01201 { 01202 if ((*msysIter)->hasControl(control, true)) 01203 return true; 01204 } 01205 } 01206 return false; 01207 } 01208 01209 01210 01211 bool MarSystem::updControl(const char* cname, MarControlPtr newcontrol, bool upd) 01212 { 01213 MarControlPtr control = getControl(cname); 01214 if (control.isInvalid()) 01215 { 01216 MRSWARN("MarSystem::updControl - " + std::string(cname) + " is an invalid control @ " + getAbsPath()); 01217 return false; 01218 } 01219 return updControl(control, newcontrol, upd); 01220 } 01221 01222 bool MarSystem::updControl(std::string cname, MarControlPtr newcontrol, bool upd) 01223 { 01224 MarControlPtr control = getControl(cname); 01225 if (control.isInvalid()) 01226 { 01227 MRSWARN("MarSystem::updControl - " + cname + " is an invalid control @ " + getAbsPath()); 01228 return false; 01229 } 01230 return updControl(control, newcontrol, upd); 01231 } 01232 01233 01234 bool 01235 MarSystem::updControl(MarControlPtr control, MarControlPtr newcontrol, bool upd) 01236 { 01237 // check if the control is valid 01238 if (control.isInvalid()) 01239 { 01240 MRSWARN("MarSystem::updControl - Invalid control ptr @ " + getAbsPath()); 01241 return false; 01242 } 01243 01244 if (newcontrol.isInvalid()) 01245 { 01246 MRSWARN("MarSystem::updControl - Invalid control ptr given for assignment"); 01247 return false; 01248 } 01249 // //check if control exists locally or among children 01250 // if(!hasControl(control)) 01251 // { 01252 // MRSWARN("MarSystem::updControl - " + control->getName() +" @ "+getAbsPath()+ " does not exist locally or in children!"); 01253 // return false; 01254 // } 01255 01256 return control->setValue(newcontrol, upd); 01257 } 01258 01259 01260 void 01261 MarSystem::updControl(EvEvent* me) 01262 { 01263 if (me != NULL) 01264 { 01265 me->dispatch(); 01266 delete(me); 01267 } 01268 } 01269 01270 void 01271 MarSystem::updControl(TmTime t, EvEvent* ev) 01272 { 01273 scheduler_.post(t,Repeat(),ev); 01274 } 01275 01276 void 01277 MarSystem::updControl(TmTime t, Repeat r, EvEvent* ev) 01278 { 01279 scheduler_.post(t,r,ev); 01280 } 01281 01282 void 01283 MarSystem::updControl(TmTime t, mrs_string cname, MarControlPtr control) 01284 { 01285 scheduler_.post(t,Repeat(),new EvValUpd(this,cname,control)); 01286 } 01287 01288 void 01289 MarSystem::updControl(TmTime t, Repeat r, mrs_string cname, MarControlPtr control) 01290 { 01291 scheduler_.post(t,r,new EvValUpd(this,cname,control)); 01292 } 01293 01294 01295 01296 //get local controls only (i.e. no child controls included) 01297 const map<mrs_string, MarControlPtr>& 01298 MarSystem::getLocalControls() 01299 { 01300 return controls_; 01301 } 01302 01303 // get all the controls (including controls of children) 01304 // for a particular MarSystem 01305 map<mrs_string, MarControlPtr> 01306 MarSystem::getControls(map<mrs_string, MarControlPtr>* cmap) 01307 { 01308 if (!cmap) 01309 { 01310 map<mrs_string, MarControlPtr> controlsmap; 01311 01312 cmap = &controlsmap; 01313 01314 //fill list with local controls 01315 for (ControlItr ctrlIter_=controls_.begin(); ctrlIter_ != controls_.end(); ++ctrlIter_) 01316 { 01317 (*cmap)[absPath_+ctrlIter_->first] = ctrlIter_->second; 01318 } 01319 01320 //iterate over children, recursively, 01321 //and fill the list with their controls 01322 vector<MarSystem*>::const_iterator msysIter; 01323 for (msysIter = marsystems_.begin(); msysIter != marsystems_.end(); ++msysIter) 01324 { 01325 (*msysIter)->getControls(cmap); 01326 } 01327 01328 return (*cmap); 01329 } 01330 else 01331 { 01332 //fill list with local controls 01333 for (ControlItr ctrlIter_=controls_.begin(); ctrlIter_ != controls_.end(); ++ctrlIter_) 01334 { 01335 (*cmap)[absPath_+ctrlIter_->first] = ctrlIter_->second; 01336 } 01337 01338 //iterate over children, recursively, 01339 //and fill the list with their controls 01340 vector<MarSystem*>::const_iterator msysIter; 01341 for (msysIter = marsystems_.begin(); msysIter != marsystems_.end(); ++msysIter) 01342 { 01343 (*msysIter)->getControls(cmap); 01344 } 01345 01346 return (*cmap); 01347 } 01348 } 01349 01350 vector<MarSystem*> 01351 MarSystem::getChildren() 01352 { 01353 return marsystems_; 01354 } 01355 01356 std::string MarSystem::splitPathEnd( const std::string & path, std::string & remaining ) 01357 { 01358 string::size_type last_separator = path.rfind('/'); 01359 if (last_separator != string::npos) 01360 { 01361 string ending = path.substr(last_separator + 1); 01362 if (last_separator > 0) 01363 remaining = path.substr(0, last_separator); 01364 else 01365 remaining = '/'; 01366 return ending; 01367 } 01368 else 01369 { 01370 return path; 01371 } 01372 } 01373 01374 std::string MarSystem::path() const 01375 { 01376 std::stack<const MarSystem*> hierarchy; 01377 const MarSystem *system = this; 01378 while(system->getParent()) 01379 { 01380 hierarchy.push(system); 01381 system = system->getParent(); 01382 } 01383 string path("/"); 01384 while(!hierarchy.empty()) 01385 { 01386 path += hierarchy.top()->getName(); 01387 path += '/'; 01388 hierarchy.pop(); 01389 } 01390 return path; 01391 } 01392 01393 // Name without type: 01394 MarSystem * MarSystem::child( const string & name ) 01395 { 01396 std::vector<MarSystem*>::iterator it; 01397 for (it = marsystems_.begin(); it != marsystems_.end(); ++it) 01398 { 01399 if ((*it)->getName() == name) 01400 return *it; 01401 } 01402 01403 return 0; 01404 } 01405 01406 // Name without type: 01407 MarControlPtr MarSystem::control( const string & name ) 01408 { 01409 //MRSMSG("MarSystem::control: " << getAbsPath() << " -> " << name); 01410 01411 ControlItr it; 01412 for (it = controls_.begin(); it != controls_.end(); ++it) 01413 { 01414 if (it->second->id() == name) 01415 return it->second; 01416 } 01417 01418 return MarControlPtr(); 01419 } 01420 01421 MarSystem *MarSystem::subSystem( const std::string & name ) 01422 { 01423 //MRSMSG("MarSystem::subSystem: " << getAbsPath() << " -> " << name); 01424 01425 std::map<std::string, MarSystem*>::iterator it; 01426 it = scope_.find(name); 01427 if (it != scope_.end()) 01428 return it->second; 01429 else 01430 return 0; 01431 } 01432 01433 class path_stream 01434 { 01435 public: 01436 path_stream( const string & path ): 01437 m_path(path), 01438 m_pos(0) 01439 {} 01440 01441 path_stream & operator>>(string & element) 01442 { 01443 if (at_end()) { 01444 element = string(); 01445 return *this; 01446 } 01447 01448 string::size_type separator = m_path.find('/', m_pos); 01449 if (separator != string::npos) 01450 { 01451 element = m_path.substr(m_pos, separator - m_pos); 01452 m_pos = separator + 1; 01453 } 01454 else 01455 { 01456 element = m_path.substr(m_pos); 01457 m_pos = string::npos; 01458 } 01459 01460 return *this; 01461 } 01462 01463 void skip() 01464 { 01465 string::size_type separator = m_path.find('/', m_pos); 01466 if (separator != string::npos) 01467 m_pos = separator + 1; 01468 else 01469 m_pos = string::npos; 01470 } 01471 01472 bool at_end() 01473 { 01474 return m_pos >= m_path.length(); 01475 } 01476 01477 private: 01478 string m_path; 01479 string::size_type m_pos; 01480 }; 01481 01482 // Path in form of "system-name/system-name/..." without types: 01483 MarSystem *MarSystem::remoteSystem( const string & path ) 01484 { 01485 //MRSMSG("MarSystem::remoteSystem: " << this << " " << path); 01486 01487 if (path.empty()) 01488 return 0; 01489 01490 path_stream elements(path); 01491 MarSystem * system = this; 01492 01493 if (path[0] == '/') 01494 { 01495 // Absolute path. Go find root system: 01496 01497 elements.skip(); 01498 01499 while(system->getParent()) 01500 system = system->getParent(); 01501 } 01502 else 01503 { 01504 // Relative path. 01505 // Go find first ancestor which has the first element in scope. 01506 // TODO: Could speed up if all systems had parent_scope_, 01507 // even if not named in any scope 01508 // - then we could jump up scope instead of system hierarchy. 01509 01510 string elem; 01511 elements >> elem; 01512 assert(!elem.empty()); 01513 01514 while (system) 01515 { 01516 MarSystem *subsystem = system->subSystem(elem); 01517 if (subsystem) 01518 { 01519 system = subsystem; 01520 break; 01521 } 01522 system = system->getParent(); 01523 } 01524 } 01525 01526 while(system && !elements.at_end()) 01527 { 01528 string elem; 01529 elements >> elem; 01530 system = system->subSystem(elem); 01531 } 01532 01533 return system; 01534 } 01535 01536 // Path in form of "system-name/system-name/.../control-name" without types: 01537 MarControlPtr MarSystem::remoteControl( const string & path ) 01538 { 01539 //MRSMSG("MarSystem::remoteControl: " << getAbsPath() << " -> " << path); 01540 if (path.empty()) 01541 return MarControlPtr(); 01542 01543 MarSystem * system = this; 01544 string system_path; 01545 string control_name = splitPathEnd(path, system_path); 01546 if (!system_path.empty()) 01547 { 01548 system = remoteSystem(system_path); 01549 } 01550 if (system) 01551 return system->control( control_name ); 01552 else 01553 return MarControlPtr(); 01554 } 01555 01556 bool 01557 MarSystem::addControl(mrs_string cname, MarControlPtr v, MarControlPtr& ptr) 01558 { 01559 if (addControl(cname, v)) 01560 { 01561 ptr = controls_[cname]; // => mutexes [?] 01562 return true; 01563 } 01564 else 01565 { 01566 ptr = MarControlPtr();//return invalid control 01567 return false; 01568 } 01569 } 01570 01571 bool 01572 MarSystem::addControl(mrs_string cname, MarControlPtr v) 01573 { 01574 //convert cname to the canonical local control pathname format 01575 mrs_string pcname = cname; 01576 cname = getControlLocalPath(cname); 01577 if (cname == "") 01578 { 01579 //cname is an invalid control pathname! 01580 MRSWARN("MarSystem::addControl - invalid control pathname: " + pcname); 01581 MRSWARN("MarSystem::addControl - absolute path: " + absPath_); // => mutexes [?] 01582 return false; 01583 } 01584 01585 //check for type mismatch between cname string (which include type information) 01586 //and the actual control type passed as an argument 01587 mrs_string::size_type pos = cname.find("/", 0); 01588 mrs_string ctype = cname.substr(0,pos); 01589 if (ctype!= v->getType()) 01590 { 01591 MRSWARN("MarSystem::addControl control type mismatch (" + ctype + "!=" + v->getType() + ", in " + type_ + ")"); 01592 return false; 01593 } 01594 controls_[cname] = v; 01595 controls_[cname]->setMarSystem(this); 01596 controls_[cname]->setName(cname); 01597 01598 //success! 01599 MRSDIAG("MarSystem::addControl - control added successfully: " + cname + " @ " + absPath_); 01600 return true; 01601 } 01602 01603 void 01604 MarSystem::updctrl(EvEvent* me) 01605 { 01606 if (me != NULL) 01607 { 01608 me->dispatch(); 01609 delete(me); 01610 } 01611 } 01612 01613 void 01614 MarSystem::updctrl(TmTime t, EvEvent* ev) 01615 { 01616 scheduler_.post(t,Repeat(),ev); 01617 } 01618 01619 void 01620 MarSystem::updctrl(TmTime t, Repeat r, EvEvent* ev) 01621 { 01622 scheduler_.post(t,r,ev); 01623 } 01624 01625 void 01626 MarSystem::updctrl(TmTime t, mrs_string cname, MarControlPtr control) 01627 { 01628 scheduler_.post(t,Repeat(),new EvValUpd(this,cname,control)); 01629 } 01630 01631 void 01632 MarSystem::updctrl(TmTime t, Repeat r, mrs_string cname, MarControlPtr control) 01633 { 01634 scheduler_.post(t,r,new EvValUpd(this,cname,control)); 01635 } 01636 01637 void 01638 MarSystem::removeTimer(mrs_string name) 01639 { 01640 scheduler_.removeTimer(name); 01641 } 01642 01643 void 01644 MarSystem::addTimer(std::string tmr_class, std::string tmr_ident) 01645 { 01646 scheduler_.addTimer(tmr_class,tmr_ident); 01647 } 01648 void 01649 MarSystem::addTimer(std::string tmr_class, std::string tmr_ident, std::vector<TmParam> params) 01650 { 01651 scheduler_.addTimer(tmr_class,tmr_ident,params); 01652 } 01653 01654 void 01655 MarSystem::updtimer(std::string tmr_ctrl_path, TmControlValue value) 01656 { 01657 scheduler_.updtimer(tmr_ctrl_path,value); 01658 } 01659 void 01660 MarSystem::updtimer(std::string tmr_path, TmParam param) 01661 { 01662 scheduler_.updtimer(tmr_path,param); 01663 } 01664 void 01665 MarSystem::updtimer(std::string tmr_path, std::vector<TmParam> params) 01666 { 01667 scheduler_.updtimer(tmr_path,params); 01668 } 01669 01670 01671 01672 mrs_natural 01673 MarSystem::getTime(mrs_string timer_name) 01674 { 01675 return scheduler_.getTime(timer_name); 01676 } 01677 01678 void 01679 MarSystem::setMATLABscript(std::string script) 01680 { 01681 MATLABscript_ = script; 01682 } 01683 01684 mrs_string 01685 MarSystem::getMATLABscript() 01686 { 01687 return MATLABscript_; 01688 } 01689 01690 mrs_string 01691 MarSystem::toStringShort() 01692 { 01693 ostringstream oss; 01694 put(oss, false); 01695 return oss.str(); 01696 01697 } 01698 01699 01700 01701 mrs_string 01702 MarSystem::toString() 01703 { 01704 ostringstream oss; 01705 put(oss,true); 01706 return oss.str(); 01707 } 01708 01709 01710 mrs_string 01711 MarSystem::toStringGraphViz() 01712 { 01713 ostringstream oss; 01714 ostringstream oss_defs; 01715 ostringstream oss_links; 01716 toStringGraphViz(oss_defs, oss_links); 01717 01718 //oss << oss_defs.str() << endl; 01719 01720 oss << "digraph G {" << endl; 01721 oss << oss_links.str(); 01722 01723 oss << "}" << endl; 01724 return oss.str(); 01725 } 01726 01727 void 01728 MarSystem::toStringGraphViz(ostringstream& oss_defs, ostringstream& oss_links) 01729 { 01730 // Print the node def. 01731 //oss_defs << "Node=" << prefix_ << endl; 01732 static int a=0; 01733 01734 // Print the links 01735 child_count_t sz = marsystems_.size(); 01736 if (sz>0) 01737 { 01738 // Make a cluster. 01739 oss_links << "\tsubgraph cluster_" << a++ << " {" << endl; 01740 oss_links << "\t\tlabel = \"" << prefix_ << "\"" << endl; 01741 oss_links << "\t\t"; 01742 01743 for (child_count_t i=0; i<sz-1; ++i) 01744 { 01745 // TODO are there other composite types to handle? 01746 if (type_ == "Fanout" || type_ == "Parallel") { 01747 if ( marsystems_[i]->isComposite_) { 01748 // TODO: handle links to composites better. 01749 oss_links << "\"" << marsystems_[i]->prefix_ << "\";" << endl; 01750 } else { 01751 oss_links << "\"" << marsystems_[i]->prefix_ << "\";" << endl; 01752 } 01753 } else { 01754 if ( marsystems_[i]->isComposite_) { 01755 // TODO: handle links to composites better. 01756 oss_links << "\"" << marsystems_[i]->prefix_ << "\" -> "; 01757 } else { 01758 oss_links << "\"" << marsystems_[i]->prefix_ << "\" -> "; 01759 } 01760 } 01761 } 01762 oss_links << "\"" << marsystems_[sz-1]->prefix_ << "\";" << endl; 01763 oss_links << "\t}" << endl << endl; 01764 01765 // Link to start. 01766 // TODO are there other composite types to handle? 01767 if (type_ == "Fanout" || type_ == "Parallel") { 01768 // Link to all first items for parallel types of composites. 01769 for (child_count_t j=0; j<sz; ++j) 01770 oss_links << "\t\"" << prefix_ << "\" -> \"" << marsystems_[j]->prefix_ << "\";" << endl; 01771 } else { 01772 // Only link to first item in series. 01773 oss_links << "\t\"" << prefix_ << "\" -> \"" << marsystems_[0]->prefix_ << "\";" << endl; 01774 } 01775 01776 // Link the end of series back to parent's next item... tricky. 01777 // TODO 01778 } 01779 01780 01781 01782 // Children. 01783 if (sz>0) 01784 { 01785 for (child_count_t i=0; i<sz; ++i) 01786 marsystems_[i]->toStringGraphViz(oss_defs, oss_links); 01787 } 01788 } 01789 01790 01791 01792 01793 01794 marostring& 01795 MarSystem::toString(marostring& m) 01796 { 01797 m.begin_marsystem(isComposite_, getType(), getName()); 01798 01799 m.begin_controls((int)controls_.size()); 01800 for (ControlItr ctrlIter_ = controls_.begin(); ctrlIter_ != controls_.end(); ++ctrlIter_) 01801 { 01802 MarControlPtr c = ctrlIter_->second; 01803 std::ostringstream cv; 01804 cv << c; 01805 std::string ct = c->getType(); 01806 std::string cn = c->getName(); 01807 // get the trailing bit after / Don't know why name is now type/name 01808 int lp = (int)cn.find_last_of('/'); 01809 if (lp >= 0 && (lp+1) < (int)cn.size()) 01810 cn = cn.substr(lp+1); 01811 01812 bool cs = c->hasState(); 01813 m.begin_control(ct, cn, cv.str(), cs); 01814 01815 std::vector<std::pair<MarControlPtr, MarControlPtr> > links = c->getLinks(); 01816 int j=0; 01817 for (mrs_natural i=0; i< (mrs_natural)links.size(); ++i) 01818 { 01819 //check who is linking to this control, but avoid outputting root link info 01820 if (c == links[i].second() && links[i].first() != c) 01821 { 01822 j++; 01823 } 01824 } 01825 m.begin_control_links_in(j); 01826 for (mrs_natural i=0; i<(mrs_natural)links.size(); ++i) 01827 { 01828 // check who is linking to this control, but avoid outputting root link info 01829 if (c == links[i].second() && links[i].first() != c) 01830 { 01831 m.put_control_link_in(links[i].first->getMarSystem()->getAbsPath(),links[i].first->getType(),links[i].first->getName()); 01832 } 01833 } 01834 m.end_control_links_in(j); 01835 01836 for (mrs_natural i=0; i<(mrs_natural)links.size(); ++i) 01837 { 01838 //check where to this control is linking, but avoid outputting root link info 01839 if (c == links[i].first() && c != links[i].second()) 01840 { 01841 j++; 01842 } 01843 } 01844 m.begin_control_links_out(j); 01845 for (mrs_natural i=0; i<(mrs_natural)links.size(); ++i) 01846 { 01847 //check where to this control is linking, but avoid outputting root link info 01848 if (c == links[i].first() && c != links[i].second()) 01849 { 01850 m.put_control_link_out(links[i].second->getMarSystem()->getAbsPath(),links[i].second->getType(),links[i].second->getName()); 01851 } 01852 } 01853 m.end_control_links_out(j); 01854 m.end_control(ct, cn, cv.str(), cs); 01855 } 01856 m.end_controls((int)controls_.size()); 01857 01858 child_count_t sz = marsystems_.size(); 01859 if (sz>0) 01860 { 01861 m.begin_children((int)sz); 01862 for (child_count_t i=0; i<sz; ++i) 01863 { 01864 marsystems_[i]->toString(m); 01865 } 01866 m.end_children((int)sz); 01867 } 01868 m.end_marsystem(isComposite_, getType(), getName()); 01869 return m; 01870 } 01871 01872 // write *this to s 01873 ostream& 01874 MarSystem::put(ostream &o, bool verbose) 01875 { 01876 01877 if (isComposite_) 01878 { 01879 o << "# MarSystemComposite" << endl; 01880 } 01881 else 01882 { 01883 o << "# MarSystem" << endl; 01884 } 01885 o << "# Type = " << type_ << endl; 01886 o << "# Name = " << name_ << endl; 01887 01888 o << endl; 01889 01890 if (verbose) 01891 { 01892 o << "# MarControls = " << controls_.size() << endl; 01893 for (ControlItr ctrlIter_=controls_.begin(); ctrlIter_ != controls_.end(); ++ctrlIter_) 01894 { 01895 ostringstream toss; 01896 toss << ctrlIter_->second; 01897 if (toss.str() != "") 01898 o << "# " << ctrlIter_->first << " = " << ctrlIter_->second << endl; 01899 else 01900 o << "# " << ctrlIter_->first << " = " << "MARSYAS_EMPTYSTRING" << endl; 01901 //serialize links 01902 ostringstream oss; 01903 std::vector<std::pair<MarControlPtr, MarControlPtr> > links = ctrlIter_->second->getLinks(); 01904 mrs_natural numLinks = 0; 01905 //links to: 01906 for (mrs_natural i=0; i<(mrs_natural)links.size(); ++i) 01907 { 01908 //check where to this control is linking, but avoid outputting root link info 01909 if (ctrlIter_->second() == links[i].first() && links[i].first() != links[i].second()) 01910 { 01911 oss << "# " << links[i].second->getMarSystem()->getAbsPath() << links[i].second->getName() << endl; 01912 numLinks++; 01913 } 01914 } 01915 o << "# LinksTo = " << numLinks << endl << oss.str(); 01916 //linked from: 01917 numLinks = 0; 01918 oss.str(""); //clear the stringstream 01919 for (mrs_natural i=0; i<(mrs_natural)links.size(); ++i) 01920 { 01921 //check who is linking to this control, but avoid outputting root link info 01922 if (ctrlIter_->second() == links[i].second() && links[i].first() != links[i].second()) 01923 { 01924 oss << "# " << links[i].first->getMarSystem()->getAbsPath() << links[i].first->getName() << endl; 01925 numLinks++; 01926 } 01927 } 01928 o << "# LinkedFrom = " << numLinks << endl << oss.str(); 01929 } 01930 } 01931 01932 if (isComposite_) 01933 { 01934 child_count_t child_count = marsystems_.size(); 01935 01936 o << endl; 01937 o << "# nComponents = " << child_count << endl; 01938 o << endl; 01939 01940 for (child_count_t i=0; i < child_count; ++i) 01941 marsystems_[i]->put(o,verbose); 01942 } 01943 01944 return o; 01945 } 01946 01947 // 01948 // Output the MarSystem to stdout as a HTML document, with 01949 // collapsible elements provided by a Javascript function 01950 // 01951 ostream& 01952 MarSystem::put_html(ostream &o) 01953 { 01954 // 01955 // Output the HTML header 01956 // 01957 // sness - Add proper DOCTYPE later 01958 o << "<script type=\"text/javascript\" src=\"http://assets.sness.net/simpletreemenu.js\">" << endl; 01959 o << "</script>" << endl; 01960 o << "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://assets.sness.net/simpletree.css\" />" << endl; 01961 o << "<a href=\"javascript:ddtreemenu.flatten(\'treemenu1\', \'expand\')\">Expand All</a>" << endl; 01962 o << "<a href=\"javascript:ddtreemenu.flatten(\'treemenu1\', \'contact\')\">Contact All</a>" << endl; 01963 o << "<ul id=\"treemenu1\" class=\"treeview\">" << endl; 01964 01965 put_html_worker(o); 01966 01967 // 01968 // Output the HTML footer 01969 // 01970 o << "<script type=\"text/javascript\">" << endl; 01971 o << "ddtreemenu.createTree(\"treemenu1\", true)" << endl; 01972 o << "</script>" << endl; 01973 01974 return o; 01975 } 01976 01977 // 01978 // Output a single MarSystem to &o, without HTML headers and footers 01979 // 01980 ostream& 01981 MarSystem::put_html_worker(ostream &o) 01982 { 01983 01984 if (isComposite_) 01985 { 01986 o << "<li>MarSystemComposite" << endl; 01987 } 01988 else 01989 { 01990 o << "<li>MarSystem" << endl; 01991 } 01992 o << "Type = " << type_ << endl; 01993 o << "Name = " << name_ << endl; 01994 01995 o << endl; 01996 o << "<li>MarControls" << controls_.size() << endl; 01997 o << "<ul>" << endl; 01998 for (ControlItr ctrlIter_=controls_.begin(); ctrlIter_ != controls_.end(); ++ctrlIter_) 01999 { 02000 ostringstream toss; 02001 toss << ctrlIter_->second; 02002 if (toss.str() != "") 02003 o << "<li>" << ctrlIter_->first << " = " << ctrlIter_->second << "</li>" << endl; 02004 else 02005 o << "<li>" << ctrlIter_->first << " = " << "MARSYAS_EMPTYSTRING" << "</li>" << endl; 02006 02007 //serialize links 02008 ostringstream oss; 02009 std::vector<std::pair<MarControlPtr, MarControlPtr> > links = ctrlIter_->second->getLinks(); 02010 mrs_natural numLinks = 0; 02011 02012 // 02013 // Links To: 02014 // 02015 for (mrs_natural i=0; i<(mrs_natural)links.size(); ++i) 02016 { 02017 //check where to this control is linking, but avoid outputting root link info 02018 if (ctrlIter_->second() == links[i].first() && links[i].first() != links[i].second()) 02019 { 02020 oss << "<li>" << links[i].second->getMarSystem()->getAbsPath() << links[i].second->getName() << "</li>" << endl; 02021 numLinks++; 02022 } 02023 } 02024 if (numLinks > 0) 02025 o << "<li>LinksTo = " << numLinks << endl << "<ul>" << oss.str() << "</ul></li>"; 02026 02027 // 02028 // Linked From: 02029 // 02030 numLinks = 0; 02031 oss.str(""); //clear the stringstream 02032 for (mrs_natural i=0; i<(mrs_natural)links.size(); ++i) 02033 { 02034 //check who is linking to this control, but avoid outputting root link info 02035 if (ctrlIter_->second() == links[i].second() && links[i].first() != links[i].second()) 02036 { 02037 oss << "<li>" << links[i].first->getMarSystem()->getAbsPath() << links[i].first->getName() << "</li>" << endl; 02038 numLinks++; 02039 } 02040 } 02041 if (numLinks > 0) 02042 o << "<li>LinkedFrom = " << numLinks << endl << "<ul>" << oss.str() << "</ul></li>"; 02043 } 02044 o << "</ul>" << endl; 02045 o << "</li>" << endl; 02046 02047 if (isComposite_) 02048 { 02049 child_count_t child_count = marsystems_.size(); 02050 02051 o << endl; 02052 o << "<li>Components = " << child_count << endl; 02053 o << "<ul>" << endl; 02054 02055 for (child_count_t i=0; i < child_count; ++i) 02056 (marsystems_[i])->put_html_worker(o); 02057 02058 o << "</ul>" << endl; 02059 o << "</li>" << endl; 02060 } 02061 02062 o << "</li>" << endl; 02063 02064 02065 return o; 02066 } 02067 02068 istream& 02069 MarSystem::put(istream& is) 02070 { 02071 /* This method assumes that the input stream is in the format 02072 * generated by MarSystem::put(ostream& o). 02073 * This is also known as ".mpl file format". 02074 * 02075 * This method also assumes that it is being called by 02076 * MarSystemManager::getMarSystem(std::istream& is, MarSystem *parent) 02077 * and thus the input has its header data (first 4 lines) stripped off already 02078 */ 02079 02080 mrs_string skipstr; 02081 mrs_natural i; 02082 mrs_string type; 02083 mrs_string rstr = "mrs_real"; 02084 mrs_string nstr = "mrs_natural"; 02085 mrs_string bstr = "mrs_bool"; 02086 mrs_string sstr = "mrs_string"; 02087 mrs_string vstr = "mrs_realvec"; 02088 mrs_real rcvalue; 02089 mrs_string scvalue; 02090 mrs_natural ncvalue; 02091 bool bcvalue; 02092 mrs_string cname; 02093 map<mrs_string, MarControlPtr>::iterator iter; 02094 02095 // if composite, clear all children to avoid bad links to prototype children 02096 if (isComposite_) 02097 { 02098 child_count_t child_count = marsystems_.size(); 02099 for (child_count_t i=0; i< child_count; ++i) 02100 { 02101 delete marsystems_[i]; 02102 } 02103 marsystems_.clear(); 02104 } 02105 02106 // Start reading! 02107 02108 /* The first line should look something like: 02109 * # MarControls = 19 02110 * we want to skip everything up to the 19 (or whatever number it is) 02111 */ 02112 is >> skipstr >> skipstr >> skipstr; 02113 02114 mrs_natural nControls; 02115 is >> nControls; 02116 02117 for (i=0; i < nControls; ++i) 02118 { 02119 /* For each control there are at least three lines: 02120 * # ctrlname = ctrlvalue 02121 * # LinksTo = nLinks 02122 * # LinkedFrom = nLinks 02123 * First, we get the cname and, from it, extract the type: 02124 */ 02125 is >> skipstr; 02126 is >> cname; 02127 02128 mrs_string ctype; 02129 ctype = cname.substr(0, cname.rfind("/", cname.length())); 02130 02131 iter = controls_.find(cname); 02132 02133 is >> skipstr; 02134 // Now, based on the type, we extract the value 02135 if (ctype == rstr) 02136 { 02137 is >> rcvalue; 02138 if (iter == controls_.end()) 02139 addControl(cname, rcvalue); 02140 else 02141 updControl(cname, rcvalue); 02142 } 02143 else if (ctype == sstr) 02144 { 02145 getline(is, scvalue); // getline is used to include spaces in strings 02146 scvalue = scvalue.substr(1, scvalue.length()); // strip leading space 02147 02148 if (scvalue == "MARSYAS_EMPTYSTRING") 02149 scvalue = ""; 02150 if (iter == controls_.end()) 02151 addControl(cname, scvalue); 02152 else 02153 updControl(cname, scvalue); 02154 } 02155 else if (ctype == nstr) 02156 { 02157 is >> ncvalue; 02158 if (iter == controls_.end()) 02159 addControl(cname, ncvalue); 02160 else 02161 updControl(cname, ncvalue); 02162 } 02163 else if (ctype == bstr) 02164 { 02165 is >> bcvalue; 02166 if (iter == controls_.end()) 02167 addControl(cname, bcvalue); 02168 else 02169 updControl(cname, bcvalue); 02170 } 02171 else if (ctype == vstr) 02172 { 02173 realvec vcvalue; 02174 is >> vcvalue; 02175 if (iter == controls_.end()) 02176 addControl(cname, vcvalue); 02177 else 02178 updControl(cname, vcvalue); 02179 } 02180 else 02181 { 02182 // if the ctype wasn't recognized as a base type 02183 // it's a control type. add a new control pointer 02184 MarControlPtr ctrl = MarControlManager::getManager()->createFromStream(ctype, is); 02185 if (iter == controls_.end()) 02186 addControl(cname, ctrl); 02187 else 02188 updControl(cname, ctrl); 02189 } 02190 02191 /* 02192 * Now we read in the LinksTo and LinksFrom lines 02193 */ 02194 02195 //clean all links for current control (if any) 02196 MarControlPtr curCtrl = getControlLocal(cname); 02197 curCtrl->unlinkFromAll(); 02198 02199 // read links 02200 int nLinks; 02201 mrs_string linkto; 02202 mrs_string linkedfrom; 02203 02204 // Next line looks like: 02205 //# LinksTo = nlinks 02206 is >> skipstr >> skipstr >> skipstr; 02207 is >> nLinks; 02208 02209 //relink 02210 if (nLinks > 0) 02211 { 02212 //read link absolute path 02213 is >> skipstr >> linkto; 02214 linkControl(cname, linkto); 02215 } 02216 02217 // Next line looks like: 02218 //# LinksFrom = nlinks 02219 is >> skipstr >> skipstr >> skipstr; 02220 is >> nLinks; 02221 02222 //relink 02223 /* If there are any LinksFrom, there will be one line for each. 02224 * those lines look like: 02225 * # /Series/net/Classifier/cl/ZeroRClassifier/zerorcl/mrs_natural/nClasses 02226 * ie. hash sign, followed by a path 02227 */ 02228 for (mrs_natural link=0; link < nLinks; ++link) 02229 { 02230 //read link absolute path 02231 is >> skipstr; 02232 is >> linkedfrom; 02233 02234 //look for control in the entire network 02235 MarControlPtr ctrl = getControl(linkedfrom, true, true); 02236 //if found, just link it to this control. 02237 //if not, this link will be done when the sibling or child MarSystem 02238 //owning the missing control is created 02239 if (!ctrl.isInvalid()) 02240 { 02241 //ctrl->getMarSystem()->linkControl(linkedfrom, cname); 02242 ctrl->linkTo(curCtrl); 02243 } 02244 } 02245 } 02246 return is; 02247 } 02248 02249 bool MarSystem::hasObserver( MarSystemObserver * observer ) const 02250 { 02251 std::vector<MarSystemObserver*>::const_iterator it = 02252 std::find( observers_.begin(), observers_.end(), observer ); 02253 02254 return it != observers_.end(); 02255 } 02256 02257 void MarSystem::addObserver( MarSystemObserver * observer ) 02258 { 02259 if (hasObserver(observer)) 02260 return; 02261 02262 observers_.push_back(observer); 02263 } 02264 02265 void MarSystem::removeObserver( MarSystemObserver * observer ) 02266 { 02267 std::vector<MarSystemObserver*>::iterator it = 02268 std::find( observers_.begin(), observers_.end(), observer ); 02269 02270 if (it != observers_.end()) 02271 observers_.erase(it); 02272 } 02273 02274 void MarSystem::attachMarSystem( MarSystem * system ) 02275 { 02276 if (find(attached_marsystems_.begin(), attached_marsystems_.end(), system) 02277 != attached_marsystems_.end()) 02278 return; 02279 02280 if (system->getParent()) 02281 { 02282 MRSERR("MarSystem: can not attach a MarSystem with parent."); 02283 return; 02284 } 02285 02286 attached_marsystems_.push_back(system); 02287 } 02288 02289 void MarSystem::detachMarSystem( MarSystem * system ) 02290 { 02291 std::vector<MarSystem*>::iterator iter = std::find(attached_marsystems_.begin(), attached_marsystems_.end(), system); 02292 if (iter != attached_marsystems_.end()) 02293 attached_marsystems_.erase(iter); 02294 } 02295 02296 namespace Marsyas { 02297 02298 ostream& 02299 operator<< (ostream& o, MarSystem& sys) 02300 { 02301 sys.put(o, true); 02302 return o; 02303 } 02304 02305 istream& 02306 operator>> (istream& is, MarSystem& sys) 02307 { 02308 sys.put(is); 02309 return is; 02310 } 02311 02312 ostream& 02313 operator<< (ostream& o, const map<mrs_string,MarControlPtr>& c) 02314 { 02315 //lock map<mrs_string,MarControlPtr>& c for read? [?] 02316 o << "# MarControls = " << c.size() << endl; 02317 map<mrs_string, MarControlPtr>::const_iterator iter; 02318 for (iter=c.begin(); iter != c.end(); ++iter) 02319 { 02320 o << "# " << iter->first << " = " << iter->second << endl; 02321 } 02322 return o; 02323 } 02324 02325 } // namespace Marsyas 02326 02327 02343 mrs_string 02344 Marsyas::obsNamesAddPrefix(mrs_string observationNames, mrs_string prefix) 02345 { 02346 ostringstream oss; 02347 mrs_string::size_type startPos = 0, endPos=0; 02348 while ((endPos = observationNames.find(",", startPos)) != mrs_string::npos) 02349 { 02350 // Extract the observation name. 02351 mrs_string name = observationNames.substr(startPos, endPos-startPos); 02352 oss << prefix << name << ","; 02353 // Update the start position for the next name. 02354 startPos = endPos + 1; 02355 } 02356 return oss.str(); 02357 } 02358 02359 02377 vector<mrs_string> 02378 Marsyas::stringSplit(mrs_string input, mrs_string delimiter) 02379 { 02380 vector<mrs_string> itemList; 02381 mrs_string::size_type startPos = 0, endPos=0; 02382 // Keep searching for the delimiter. 02383 while ((endPos = input.find(delimiter, startPos)) != mrs_string::npos) 02384 { 02385 // Get the current item. 02386 mrs_string item = input.substr(startPos, endPos - startPos); 02387 // Store it 02388 itemList.push_back(item); 02389 // Update the start position for the next name. 02390 startPos = endPos + delimiter.size(); 02391 } 02392 // And the last item 02393 itemList.push_back(input.substr(startPos, input.size() - startPos)); 02394 return itemList; 02395 } 02396 02397 02413 vector<mrs_string> 02414 Marsyas::obsNamesSplit(mrs_string observationNames) 02415 { 02416 vector<mrs_string> obsNames = stringSplit(observationNames, ","); 02417 obsNames.pop_back(); 02418 return obsNames; 02419 }