Marsyas  0.5.0-beta1
/Users/jleben/code/marsyas/src/marsyas/system/MarControl.cpp
Go to the documentation of this file.
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 /************************************************************************/
00020 /* MarControlPtr implementation                                         */
00021 /************************************************************************/
00022 
00023 #include <marsyas/system/MarControl.h>
00024 #include <marsyas/system/MarControlValue.h>
00025 #include <marsyas/system/MarSystem.h>
00026 
00027 #include <cstddef>
00028 
00029 using std::ostringstream;
00030 using std::vector;
00031 using std::pair;
00032 using std::size_t;
00033 using std::string;
00034 
00035 namespace Marsyas {
00036 
00037 
00038 #ifdef TRACECONTROLS
00039 std::set<MarControl*> MarControlPtr::controlTracer;
00040 
00041 void
00042 MarControlPtr::printControlTracer()
00043 {
00044   std::set<MarControl*>::iterator it;
00045   if (MarControlPtr::controlTracer.size() > 0)
00046   {
00047     cout << "#############################################################" << endl;
00048     cout << "++ Existing MarControls: " << MarControlPtr::controlTracer.size() << endl;
00049     for (it=MarControlPtr::controlTracer.begin(); it!=MarControlPtr::controlTracer.end(); it++)
00050     {
00051       cout << (*it)->getMarSystem()->getPrefix() << (*it)->getName()
00052            << " | ref.count: " << (*it)->getRefCount() << endl;
00053     }
00054     cout << "#############################################################" << endl;
00055   }
00056 }
00057 #endif
00058 
00059 MarControlPtr::MarControlPtr()
00060 {
00061   control_ = NULL;
00062 }
00063 
00064 MarControlPtr::~MarControlPtr()
00065 {
00066   if (control_)
00067   {
00068     TRACE_REMCONTROL;
00069     control_->unref();
00070     control_ = NULL;
00071   }
00072 }
00073 
00074 /************************************************************************/
00075 /* MarControl implementation                                            */
00076 /************************************************************************/
00077 
00078 
00079 WAS_INLINE void MarControl::ref()
00080 {
00081   refCount_++;
00082 }
00083 WAS_INLINE void MarControl::unref()
00084 {
00085   if (--refCount_ <= 0)
00086     delete this;
00087 }
00088 int MarControl::getRefCount() const
00089 {
00090   return refCount_;
00091 }
00092 
00093 
00094 MarControl*
00095 MarControl::clone()
00096 {
00097   return new MarControl(*this);
00098 }
00099 
00100 void
00101 MarControl::setMarSystem(MarSystem* msys)
00102 {
00103   msys_ = msys;
00104 }
00105 
00106 MarSystem*
00107 MarControl::getMarSystem() const
00108 {
00109   return msys_;
00110 }
00111 
00112 void
00113 MarControl::setName(const std::string & cname)
00114 {
00115   cname_ = cname;
00116   string::size_type separator = cname.find('/');
00117   if (separator != string::npos)
00118     id_ = cname.substr( separator + 1 );
00119   else
00120     id_.clear();
00121 }
00122 
00123 void
00124 MarControl::setState(bool state)
00125 {
00126   state_ = state;
00127 }
00128 
00129 bool
00130 MarControl::hasState() const
00131 {
00132   return state_;
00133 }
00134 
00135 mrs_string
00136 MarControl::getType() const
00137 {
00138   return value_->getType();
00139 }
00140 
00141 std::string MarControl::path() const
00142 {
00143   string path;
00144   const MarSystem *system = getMarSystem();
00145   if (system)
00146   {
00147     path += system->path();
00148   }
00149   path += id_;
00150   return path;
00151 }
00152 
00153 void
00154 MarControl::callMarSystemUpdate()
00155 {
00156   if (state_ && msys_)
00157   {
00158     MarSystem* msys = msys_;
00159     msys->update(this);
00160     return;
00161   }
00162 }
00163 
00164 bool
00165 MarControl::linkTo(MarControlPtr ctrl, bool update)
00166 {
00167   if (ctrl.isInvalid())
00168   {
00169     ostringstream oss;
00170     oss << "MarControl::linkTo() - Linking to an invalid control ";
00171     oss << "(" << ctrl->cname_ << " with " << cname_ << ").";
00172     MRSWARN(oss.str());
00173     return false;
00174   }
00175 
00176   //check if these controls are already linked
00177   //(i.e. they own the same MarControlValue)
00178   if(value_ == ctrl->value_)
00179   {
00180     return true;//already linked! :-)
00181   }
00182 
00183   if (ctrl->value_->type_ != value_->type_)
00184   {
00185     ostringstream oss;
00186     oss << "MarControl::linkTo() - Linking controls of different types ";
00187     oss << "(" << ctrl->cname_ << " with " << cname_ << ").";
00188     MRSWARN(oss.str());
00189     return false;
00190   }
00191 
00192   //unlink this control (but keeping all links to it)
00193   //before linking it again to the passed control
00194   this->unlinkFromTarget();
00195 
00196   //store a pointer to the (soon to be old) MarControlValue object,
00197   //so we can later delete it from memory
00198   MarControlValue* oldvalue = value_;
00199   //and get a pointer to the new value
00200   MarControlValue* newvalue = ctrl->value_;
00201 
00202   //get all the links of our current MarControlValue so we can also
00203   //re-link them to the passed ctrl
00204   vector<pair<MarControl*, MarControl*> >::iterator lit;
00205   for(lit=oldvalue->links_.begin(); lit!=oldvalue->links_.end(); ++lit)
00206   {
00207     //make each linked control now point to the "passed" MarControlValue
00208     lit->first->value_ = newvalue;
00209 
00210     // check if this is the root link
00211     if(lit->first == lit->second)
00212     {
00213       //make it "link to" the passed control
00214       newvalue->links_.push_back(pair<MarControl*, MarControl*>(lit->first, ctrl()));
00215     }
00216     else //if not a root link, just copy the table entry unchanged into the new MarControlValue
00217       newvalue->links_.push_back(*lit);
00218   }
00219 
00220   //old MarControlValue can and should now be safely deleted from memory
00221   delete oldvalue;
00222 
00223   //check if it's needed to call update()
00224   if(update)
00225     value_->callMarSystemsUpdate();//newvalue->callMarSystemsUpdate();
00226 
00227   return true;
00228 }
00229 
00230 
00231 mrs_string
00232 MarControl::to_string() const
00233 {
00234   if(!this)
00235   {
00236     MRSERR("MarControl::to() - trying to get a value from a NULL MarControl! Returning invalid value...");
00237     return "";
00238   }
00239   const MarControlValueT<mrs_string> *ptr = dynamic_cast<const MarControlValueT<mrs_string>*>(value_);
00240   if(ptr)
00241   {
00242     return ptr->get();
00243   }
00244   else
00245   {
00246     MRSERR("MarControl::to() -  Incompatible type requested - " << "expected " << value_->getType() << " for control  " << this->getName()) ;
00247     return "";
00248   }
00249 }
00250 
00251 mrs_natural
00252 MarControl::to_natural() const
00253 {
00254   if(!this)
00255   {
00256     MRSERR("MarControl::to() - trying to get a value from a NULL MarControl! Returning invalid value...");
00257     return 0;
00258   }
00259   const MarControlValueT<mrs_natural> *ptr = dynamic_cast<const MarControlValueT<mrs_natural>*>(value_);
00260   if(ptr)
00261   {
00262     return ptr->get();
00263   }
00264   else
00265   {
00266     MRSERR("MarControl::to() -  Incompatible type requested - " << "expected " << value_->getType() << " for control  " << this->getName()) ;
00267     return 0;
00268   }
00269 }
00270 
00271 
00272 mrs_bool
00273 MarControl::to_bool() const
00274 {
00275   if(!this)
00276   {
00277     MRSERR("MarControl::to() - trying to get a value from a NULL MarControl! Returning invalid value...");
00278     return 0;
00279   }
00280   const MarControlValueT<mrs_bool> *ptr = dynamic_cast<const MarControlValueT<mrs_bool>*>(value_);
00281   if(ptr)
00282   {
00283     return ptr->get();
00284   }
00285   else
00286   {
00287     MRSERR("MarControl::to() -  Incompatible type requested - " << "expected " << value_->getType() << " for control  " << this->getName()) ;
00288     return 0;
00289   }
00290 }
00291 
00292 mrs_real
00293 MarControl::to_real() const
00294 {
00295   if(!this)
00296   {
00297     MRSERR("MarControl::to() - trying to get a value from a NULL MarControl! Returning invalid value...");
00298     return 0.0;
00299   }
00300   const MarControlValueT<mrs_real> *ptr = dynamic_cast<const MarControlValueT<mrs_real>*>(value_);
00301   if(ptr)
00302   {
00303     return ptr->get();
00304   }
00305   else
00306   {
00307     MRSERR("MarControl::to() -  Incompatible type requested - " << "expected " << value_->getType() << " for control  " << this->getName()) ;
00308     return 0.0;
00309   }
00310 }
00311 
00312 mrs_realvec
00313 MarControl::to_realvec() const
00314 {
00315   if(!this)
00316   {
00317     MRSERR("MarControl::to() - trying to get a value from a NULL MarControl! Returning invalid value...");
00318     realvec s;
00319     return s;
00320   }
00321   const MarControlValueT<mrs_realvec> *ptr = dynamic_cast<const MarControlValueT<mrs_realvec>*>(value_);
00322   if(ptr)
00323   {
00324     return ptr->get();
00325   }
00326   else
00327   {
00328     MRSERR("MarControl::to() -  Incompatible type requested - " << "expected " << value_->getType() << " for control  " << this->getName()) ;
00329     realvec s;
00330     return s;
00331   }
00332 }
00333 
00334 
00335 
00336 void
00337 MarControl::unlinkFromAll()
00338 {
00339   //first unlink this control from all the controls to which
00340   //it links to
00341   this->unlinkFromTarget();
00342 
00343   //get a list of all the controls that target this controls...
00344   vector<pair<MarControl*, MarControl*> >::iterator lit;
00345   vector<MarControl*> linkedControls;
00346   for(lit=value_->links_.begin(); lit!=value_->links_.end(); ++lit)
00347   {
00348     if(lit->second == this && lit->first != lit->second)
00349       linkedControls.push_back(lit->first);
00350   }
00351   //... and now unlink them all from this
00352   for(mrs_natural i=0; i < (mrs_natural)linkedControls.size(); ++i)
00353     linkedControls[i]->unlinkFromTarget();
00354 }
00355 
00356 void
00357 MarControl::unlinkFromTarget()
00358 {
00359   vector<pair<MarControl*, MarControl*> >::iterator lit;
00360 
00361   //check if this MarControl is linked
00362   //(i.e. more than one MarControl linking
00363   //to the MarControlValue).
00364   //if not, no point doing unlink - just return.
00365   if(value_->links_.size() <= 1)
00366     return;
00367 
00368   MarControlValue* oldvalue = value_;
00369   MarControlValue* newvalue = oldvalue->clone();
00370 
00371   vector<pair<MarControl*, MarControl*> >* inSet = new vector<pair<MarControl*, MarControl*> >;
00372   vector<pair<MarControl*, MarControl*> >* outSet = new vector<pair<MarControl*, MarControl*> >;
00373 
00374   size_t toProcess = oldvalue->links_.size();
00375   bool* processed = new bool[toProcess];
00376   for(size_t i=0; i < toProcess; ++i)
00377     processed[i] = false;
00378 
00379   //iterate over all the links
00380   MarControl* oldRootLink = NULL;
00381   //vector<pair<MarControl*, MarControl*> >::iterator lit;
00382   lit = oldvalue->links_.begin();
00383   mrs_natural idx = 0;
00384   while(toProcess > 0)
00385   {
00386     //avoid processing processed links
00387     if(!processed[idx])
00388     {
00389       //check if this is the old root link and send it to the outSet (also as a root link)
00390       if(lit->first == lit->second)
00391       {
00392         oldRootLink = lit->first;
00393         outSet->push_back(*lit);
00394         toProcess --;
00395         processed[idx]=true;
00396       }
00397       //check if this is this same control (i.e. the control to unlink at)
00398       //and set it as the root link of the inSet
00399       else if(lit->first == this)
00400       {
00401         lit->first->value_ = newvalue; //"this" is already locked for writing
00402         inSet->push_back(pair<MarControl*, MarControl*>(lit->first, lit->first));
00403         toProcess--;
00404         processed[idx]=true;
00405       }
00406       //check if this is directly linked to the old root link and if so,
00407       //send it to the outSet
00408       else if(lit->second == oldRootLink)
00409       {
00410         outSet->push_back(*lit);
00411         toProcess --;
00412         processed[idx]=true;
00413       }
00414       //if this control links directly to the control we want to unlink, send it to the inSet
00415       else if(lit->second == this)
00416       {
00417         lit->first->value_ = newvalue;
00418         inSet->push_back(*lit);
00419         toProcess--;
00420         processed[idx]=true;
00421       }
00422       //This control is not directly connected to any root link, so we have
00423       //to check to which set belongs the control it links to and assign it to
00424       //the same set
00425       else
00426       {
00427         bool found = false;
00428         vector<pair<MarControl*, MarControl*> >::iterator sit;
00429         //do a copy of the inSet because we are using iterators
00430         //and they become invalid if we change the size of the inSet object
00431         //inside the for loop below
00432         vector<pair<MarControl*, MarControl*> > inSet2 = *inSet;
00433         //start by searching in the inSet...
00434         for(sit = inSet2.begin(); sit != inSet2.end(); ++sit)
00435         {
00436           if(lit->second == sit->first)
00437           {
00438             lit->first->value_ = newvalue;
00439             inSet->push_back(*lit);
00440             toProcess--;
00441             processed[idx]=true;
00442             found = true;
00443           }
00444         }
00445         //if not found there, look for it in the outSet...
00446         if(!found)
00447         {
00448           vector<pair<MarControl*, MarControl*> > outSet2 = *outSet;
00449           for(sit = outSet2.begin(); sit != outSet2.end(); ++sit)
00450           {
00451             if(lit->second == sit->first)
00452             {
00453               outSet->push_back(*lit);
00454               toProcess--;
00455               processed[idx]=true;
00456             }
00457           }
00458         }
00459       }
00460     }
00461 
00462     //iterate until all links were processed!
00463     if(lit!=oldvalue->links_.end())
00464     {
00465       lit++;
00466       idx++;
00467     }
00468     else
00469     {
00470       lit=oldvalue->links_.begin();
00471       idx = 0;
00472     }
00473   }
00474 
00475   delete [] processed;
00476 
00477   //set the two unlinked tables
00478   oldvalue->links_ = *outSet;
00479   newvalue->links_ = *inSet;
00480 
00481   delete inSet;
00482   delete outSet;
00483 
00484   //check if newValue has in fact any control
00485   //linking to it
00486   if(newvalue->links_.size() == 0)
00487     delete newvalue;
00488 }
00489 
00490 bool
00491 MarControl::isLinked() const
00492 {
00493   //if there is only one link (i.e. this control itself),
00494   //it means that there are no other linked controls
00495   // => return false (i.e. 0)
00496   if(value_->links_.size()-1 == 0)
00497     return false;
00498   else
00499     return true;
00500 }
00501 
00502 vector<pair<MarControlPtr, MarControlPtr> >
00503 MarControl::getLinks()
00504 {
00505   vector<pair<MarControlPtr, MarControlPtr> > res;
00506   vector<pair<MarControl*, MarControl*> >::const_iterator lit;
00507   for(lit=value_->links_.begin(); lit != value_->links_.end(); ++lit)
00508   {
00509     res.push_back(pair<MarControlPtr, MarControlPtr>(MarControlPtr(lit->first),MarControlPtr(lit->second)));
00510   }
00511   return res;
00512 }
00513 
00514 
00515 
00516 WAS_INLINE MarControlPtr::MarControlPtr(MarControl control)
00517 {
00518   control_ = new MarControl(control);
00519   control_->ref();
00520   TRACE_ADDCONTROL;
00521 }
00522 
00523 WAS_INLINE MarControlPtr::MarControlPtr(MarControlValue *value)
00524 {
00525   control_ = new MarControl(value);
00526   control_->ref();
00527   TRACE_ADDCONTROL;
00528 }
00529 
00530 WAS_INLINE MarControlPtr::MarControlPtr(int ne)
00531 {
00532   control_ = new MarControl((mrs_natural)ne);
00533   control_->ref();
00534   TRACE_ADDCONTROL;
00535 }
00536 
00537 WAS_INLINE MarControlPtr::MarControlPtr(unsigned int ne)
00538 {
00539   control_ = new MarControl((mrs_natural)ne);
00540   control_->ref();
00541   TRACE_ADDCONTROL;
00542 }
00543 
00544 WAS_INLINE MarControlPtr::MarControlPtr(float ne)
00545 {
00546   control_ = new MarControl(ne);
00547   control_->ref();
00548   TRACE_ADDCONTROL;
00549 }
00550 
00551 
00552 WAS_INLINE MarControlPtr::MarControlPtr(mrs_natural ne)
00553 {
00554   control_ = new MarControl(ne);
00555   control_->ref();
00556   TRACE_ADDCONTROL;
00557 }
00558 
00559 WAS_INLINE MarControlPtr::MarControlPtr(double re)
00560 {
00561   control_ = new MarControl(re);
00562   control_->ref();
00563   TRACE_ADDCONTROL;
00564 }
00565 
00566 WAS_INLINE MarControlPtr::MarControlPtr(const char *c)
00567 {
00568   control_ = new MarControl(std::string(c));
00569   control_->ref();
00570   TRACE_ADDCONTROL;
00571 }
00572 
00573 WAS_INLINE MarControlPtr::MarControlPtr(std::string st)
00574 {
00575   control_ = new MarControl(st);
00576   control_->ref();
00577   TRACE_ADDCONTROL;
00578 }
00579 
00580 WAS_INLINE MarControlPtr::MarControlPtr(mrs_bool be)
00581 {
00582   control_ = new MarControl(be);
00583   control_->ref();
00584   TRACE_ADDCONTROL;
00585 }
00586 
00587 WAS_INLINE MarControlPtr::MarControlPtr(realvec ve)
00588 {
00589   control_ = new MarControl(ve);
00590   control_->ref();
00591   TRACE_ADDCONTROL;
00592 }
00593 
00594 WAS_INLINE std::ostream& operator<<(std::ostream& os, const MarControlPtr& ctrl)
00595 {
00596   return (os << (*ctrl.control_));
00597 }
00598 
00599 WAS_INLINE bool operator==(const MarControlPtr& v1, const MarControlPtr& v2)
00600 {
00601   return (*v1.control_) == (*v2.control_);
00602 }
00603 
00604 WAS_INLINE bool operator!=(const MarControlPtr& v1, const MarControlPtr& v2)
00605 {
00606   return (*v1.control_) != (*v2.control_);
00607 }
00608 
00609 WAS_INLINE mrs_real operator+(const MarControlPtr& v1, const mrs_real& v2)
00610 {
00611   return (*v1.control_)+v2;
00612 }
00613 
00614 WAS_INLINE mrs_real operator+(const mrs_real& v1, const MarControlPtr& v2)
00615 {
00616   return v1+(*v2.control_);
00617 }
00618 
00619 WAS_INLINE mrs_real operator-(const MarControlPtr& v1, const mrs_real& v2)
00620 {
00621   return (*v1.control_)-v2;
00622 }
00623 
00624 WAS_INLINE mrs_real operator-(const mrs_real& v1, const MarControlPtr& v2)
00625 {
00626   return v1-(*v2.control_);
00627 }
00628 
00629 WAS_INLINE mrs_real operator*(const MarControlPtr& v1, const mrs_real& v2)
00630 {
00631   return (*v1.control_)*v2;
00632 }
00633 WAS_INLINE mrs_real operator*(const mrs_real& v1, const MarControlPtr& v2)
00634 {
00635   return v1*(*v2.control_);
00636 }
00637 
00638 WAS_INLINE mrs_real operator/(const MarControlPtr& v1, const mrs_real& v2)
00639 {
00640   return (*v1.control_)/v2;
00641 }
00642 
00643 WAS_INLINE mrs_real operator/(const mrs_real& v1, const MarControlPtr& v2)
00644 {
00645   return v1/(*v2.control_);
00646 }
00647 
00648 WAS_INLINE MarControlPtr operator+(const MarControlPtr& v1, const MarControlPtr& v2)
00649 {
00650   return (*v1.control_)+(*v2.control_);
00651 }
00652 
00653 WAS_INLINE MarControlPtr operator-(const MarControlPtr& v1, const MarControlPtr& v2)
00654 {
00655   return (*v1.control_)-(*v2.control_);
00656 }
00657 
00658 WAS_INLINE MarControlPtr operator*(const MarControlPtr& v1, const MarControlPtr& v2)
00659 {
00660   return (*v1.control_)*(*v2.control_);
00661 }
00662 
00663 WAS_INLINE MarControlPtr operator/(const MarControlPtr& v1, const MarControlPtr& v2)
00664 {
00665   return (*v1.control_)/(*v2.control_);
00666 }
00667 
00668 bool operator<(const MarControlPtr& v1, const MarControlPtr& v2)
00669 {
00670   return v1.control_ < v2.control_;
00671 }
00672 
00673 //WAS_INLINE
00674 MarControlPtr::MarControlPtr(const MarControlPtr& a) //mutexes? [?]
00675 {
00676   control_ = a.control_;
00677   if (control_)
00678   {
00679     control_->ref();
00680     TRACE_ADDCONTROL;
00681   }
00682 }
00683 
00684 WAS_INLINE
00685 MarControlPtr::MarControlPtr(MarControl *control)//mutexes? [?]
00686 {
00687   control_ = control;
00688   if (control_)
00689   {
00690     control_->ref();
00691     TRACE_ADDCONTROL;
00692   }
00693 }
00694 
00695 WAS_INLINE
00696 MarControlPtr&
00697 MarControlPtr::operator=(const MarControlPtr& a)//mutexes? [?]
00698 {
00699   if (control_)
00700   {
00701     TRACE_REMCONTROL;
00702     control_->unref();
00703   }
00704   control_ = a.control_;
00705   if (control_)
00706   {
00707     control_->ref();
00708     TRACE_ADDCONTROL;
00709   }
00710   return *this;
00711 }
00712 
00713 WAS_INLINE
00714 bool
00715 MarControlPtr::isInvalid() const
00716 {
00717   return (control_== NULL);
00718 }
00719 
00720 WAS_INLINE
00721 bool
00722 MarControlPtr::isEqual(const MarControlPtr& p)
00723 {
00724   return (control_ == p.control_);
00725 }
00726 
00727 
00728 
00729 // default constructor
00730 MarControl::MarControl() :
00731   refCount_(0),
00732   value_(NULL),
00733   msys_(NULL),
00734   state_(false),
00735   is_public_(false)
00736 {
00737 
00738 
00739 }
00740 
00741 
00742 WAS_INLINE
00743 MarControl::MarControl(const MarControl& a):
00744   refCount_(0),
00745   value_(a.value_->clone()),
00746   msys_(a.msys_),
00747   cname_(a.cname_),
00748   id_(a.id_),
00749   desc_(a.desc_),
00750   state_(a.state_),
00751   is_public_(a.is_public_)
00752 {
00753   value_->links_.push_back(std::pair<MarControl*, MarControl*>(this, this));
00754 }
00755 
00756 WAS_INLINE
00757 MarControl::MarControl(MarControlValue *value, std::string cname, MarSystem* msys, bool state):
00758   refCount_(0),
00759   value_(value->clone()),
00760   msys_(msys),
00761   state_(state),
00762   is_public_(false)
00763 {
00764   setName(cname);
00765   value_->links_.push_back(std::pair<MarControl*, MarControl*>(this, this));
00766 }
00767 
00768 WAS_INLINE
00769 MarControl::MarControl(double re, std::string cname, MarSystem* msys, bool state):
00770   refCount_(0),
00771   value_(new MarControlValueT<mrs_real>(re)),
00772   msys_(msys),
00773   state_(state),
00774   is_public_(false)
00775 {
00776   setName(cname);
00777   value_->links_.push_back(std::pair<MarControl*, MarControl*>(this, this));
00778 }
00779 
00780 WAS_INLINE
00781 MarControl::MarControl(float re, std::string cname, MarSystem* msys, bool state):
00782   refCount_(0),
00783   value_(new MarControlValueT<mrs_real>(re)),
00784   msys_(msys),
00785   state_(state),
00786   is_public_(false)
00787 {
00788   setName(cname);
00789   value_->links_.push_back(std::pair<MarControl*, MarControl*>(this, this));
00790 }
00791 
00792 
00793 WAS_INLINE
00794 MarControl::MarControl(mrs_natural ne, std::string cname, MarSystem* msys, bool state):
00795   refCount_(0),
00796   value_(new MarControlValueT<mrs_natural>(ne)),
00797   msys_(msys),
00798   state_(state),
00799   is_public_(false)
00800 {
00801   setName(cname);
00802   value_->links_.push_back(std::pair<MarControl*, MarControl*>(this, this));
00803 }
00804 
00805 WAS_INLINE
00806 MarControl::MarControl(std::string st, std::string cname, MarSystem* msys, bool state):
00807   refCount_(0),
00808   value_(new MarControlValueT<std::string>(st)),
00809   msys_(msys),
00810   state_(state),
00811   is_public_(false)
00812 {
00813   setName(cname);
00814   value_->links_.push_back(std::pair<MarControl*, MarControl*>(this, this));
00815 }
00816 
00817 WAS_INLINE
00818 MarControl::MarControl(mrs_bool be, std::string cname, MarSystem* msys, bool state):
00819   refCount_(0),
00820   value_(new MarControlValueT<bool>(be)),
00821   msys_(msys),
00822   state_(state),
00823   is_public_(false)
00824 {
00825   setName(cname);
00826   value_->links_.push_back(std::pair<MarControl*, MarControl*>(this, this));
00827 }
00828 
00829 WAS_INLINE
00830 MarControl::MarControl(realvec& ve, std::string cname, MarSystem* msys, bool state):
00831   refCount_(0),
00832   value_(new MarControlValueT<realvec>(ve)),
00833   msys_(msys),
00834   state_(state),
00835   is_public_(false)
00836 {
00837   setName(cname);
00838   value_->links_.push_back(std::pair<MarControl*, MarControl*>(this, this));
00839 }
00840 
00841 WAS_INLINE
00842 MarControl::~MarControl()
00843 {
00844   //first unlink this control from everything
00845   this->unlinkFromAll();
00846   //now we can safely delete its uniquely owned MarControlValue
00847   delete value_;
00848   value_ = NULL;
00849 }
00850 
00851 WAS_INLINE
00852 MarControl&
00853 MarControl::operator=(const MarControl& a)
00854 {
00855   if (this != &a)
00856     this->setValue(a.value_);
00857 
00858   return *this;
00859 }
00860 
00861 
00862 
00863 WAS_INLINE
00864 bool
00865 MarControl::setValue(MarControlPtr mc, bool update)
00866 {
00867   if (value_->type_ != mc->value_->type_)
00868   {
00869     std::ostringstream sstr;
00870     sstr << "MarControl::setValue() - Trying to set value of incompatible type "
00871          << "(expected " << value_->type_ << ", given " << mc->value_->type_ << ")";
00872     MRSWARN(sstr.str());
00873     return false;
00874   }
00875 
00876   if (MarControlPtr(this) == mc)
00877   {
00878     return true;
00879   }
00880 
00881   value_->copyValue(*(mc->value_));
00882 
00883 #ifdef MARSYAS_TRACECONTROLS
00884   value_->setDebugValue();
00885 #endif
00886 
00887   //check if it's needed to call update()
00888   if(update)
00889     value_->callMarSystemsUpdate();
00890 
00891   return true;
00892 }
00893 
00894 WAS_INLINE
00895 bool
00896 MarControl::setValue(MarControlValue *mcv, bool update)
00897 {
00898   if (value_->type_ != mcv->type_)
00899   {
00900     std::ostringstream sstr;
00901     sstr << "MarControl::setValue() - Trying to set value of incompatible type "
00902          << "(expected " << value_->type_ << ", given " << mcv->type_ << ")";
00903     MRSWARN(sstr.str());
00904     return false;
00905   }
00906 
00907   if (mcv->isEqual(value_))
00908   {
00909     return true;
00910   }
00911 
00912   value_->copyValue(*(mcv));
00913 
00914 #ifdef MARSYAS_TRACECONTROLS
00915   value_->setDebugValue();
00916 #endif
00917 
00918   //check if it's needed to call update()
00919   if(update)
00920     value_->callMarSystemsUpdate();
00921 
00922   return true;
00923 }
00924 
00925 WAS_INLINE
00926 bool
00927 MarControl::setValue(const char *t, bool update)
00928 {
00929   return this->setValue(std::string(t), update);
00930 }
00931 
00932 WAS_INLINE
00933 bool
00934 MarControl::setValue(const int t, bool update)
00935 {
00936   return this->setValue((mrs_natural)t, update);
00937 }
00938 
00939 
00940 
00941 WAS_INLINE
00942 std::ostream&
00943 operator<<(std::ostream& os, const MarControl& ctrl)
00944 {
00945   return ctrl.value_->serialize(os);
00946 }
00947 
00948 WAS_INLINE
00949 mrs_real
00950 operator+(const MarControl& v1, const mrs_real& v2)
00951 {
00952   mrs_real r1;
00953   MarControlValueT<mrs_real> *ptr = dynamic_cast<MarControlValueT<mrs_real>*>(v1.value_);
00954   if(ptr)
00955   {
00956     r1 = ptr->get();
00957   }
00958   else
00959   {
00960     std::ostringstream sstr;
00961     sstr << "MarControl::operator + : Trying to get value of incompatible type "
00962          << "(expected " << v1.getType() << ", given " << typeid(mrs_real).name() << ")";
00963     MRSWARN(sstr.str());
00964     return false;
00965   }
00966   return r1 + v2;
00967 }
00968 
00969 WAS_INLINE
00970 mrs_real
00971 operator+(const mrs_real& v1, const MarControl& v2)
00972 {
00973   mrs_real r2;
00974   MarControlValueT<mrs_real> *ptr = dynamic_cast<MarControlValueT<mrs_real>*>(v2.value_);
00975   if(ptr)
00976   {
00977     r2 = ptr->get();
00978   }
00979   else
00980   {
00981     std::ostringstream sstr;
00982     sstr << "MarControl::operator + : Trying to get value of incompatible type "
00983          << "(expected " << v2.getType() << ", given " << typeid(mrs_real).name() << ")";
00984     MRSWARN(sstr.str());
00985     return false;
00986   }
00987   return v1 + r2;
00988 }
00989 
00990 WAS_INLINE
00991 mrs_real
00992 operator-(const MarControl& v1, const mrs_real& v2)
00993 {
00994   mrs_real r1;
00995   MarControlValueT<mrs_real> *ptr = dynamic_cast<MarControlValueT<mrs_real>*>(v1.value_);
00996   if(ptr)
00997   {
00998     r1 = ptr->get();
00999   }
01000   else
01001   {
01002     std::ostringstream sstr;
01003     sstr << "[MarControl::setValue] Trying to get value of incompatible type "
01004          << "(expected " << v1.getType() << ", given " << typeid(mrs_real).name() << ")";
01005     MRSWARN(sstr.str());
01006     return false;
01007   }
01008   return r1 - v2;
01009 }
01010 
01011 WAS_INLINE
01012 mrs_real
01013 operator-(const mrs_real& v1, const MarControl& v2)
01014 {
01015   mrs_real r2;
01016   MarControlValueT<mrs_real> *ptr = dynamic_cast<MarControlValueT<mrs_real>*>(v2.value_);
01017   if(ptr)
01018   {
01019     r2 = ptr->get();
01020   }
01021   else
01022   {
01023     std::ostringstream sstr;
01024     sstr << "[MarControl::setValue] Trying to get value of incompatible type "
01025          << "(expected " << v2.getType() << ", given " << typeid(mrs_real).name() << ")";
01026     MRSWARN(sstr.str());
01027     return false;
01028   }
01029   return v1 - r2;
01030 }
01031 
01032 WAS_INLINE
01033 mrs_real
01034 operator*(const MarControl& v1, const mrs_real& v2)
01035 {
01036   mrs_real r1;
01037   MarControlValueT<mrs_real> *ptr = dynamic_cast<MarControlValueT<mrs_real>*>(v1.value_);
01038   if(ptr)
01039   {
01040     r1 = ptr->get();
01041   }
01042   else
01043   {
01044     std::ostringstream sstr;
01045     sstr << "[MarControl::setValue] Trying to get value of incompatible type "
01046          << "(expected " << v1.getType() << ", given " << typeid(mrs_real).name() << ")";
01047     MRSWARN(sstr.str());
01048     return false;
01049   }
01050   return r1 * v2;
01051 }
01052 
01053 WAS_INLINE
01054 mrs_real
01055 operator*(const mrs_real& v1, const MarControl& v2)
01056 {
01057   mrs_real r2;
01058   MarControlValueT<mrs_real> *ptr = dynamic_cast<MarControlValueT<mrs_real>*>(v2.value_);
01059   if(ptr)
01060   {
01061     r2 = ptr->get();
01062   }
01063   else
01064   {
01065     std::ostringstream sstr;
01066     sstr << "[MarControl::setValue] Trying to get value of incompatible type "
01067          << "(expected " << v2.getType() << ", given " << typeid(mrs_real).name() << ")";
01068     MRSWARN(sstr.str());
01069     return false;
01070   }
01071   return v1 * r2;
01072 }
01073 
01074 WAS_INLINE
01075 mrs_real
01076 operator/(const MarControl& v1, const mrs_real& v2)
01077 {
01078   mrs_real r1;
01079   MarControlValueT<mrs_real> *ptr = dynamic_cast<MarControlValueT<mrs_real>*>(v1.value_);
01080   if(ptr)
01081   {
01082     r1 = ptr->get();
01083   }
01084   else
01085   {
01086     std::ostringstream sstr;
01087     sstr << "[MarControl::setValue] Trying to get value of incompatible type "
01088          << "(expected " << v1.getType() << ", given " << typeid(mrs_real).name() << ")";
01089     MRSWARN(sstr.str());
01090     return false;
01091   }
01092   return r1 / v2;
01093 }
01094 
01095 WAS_INLINE
01096 mrs_real
01097 operator/(const mrs_real& v1, const MarControl& v2)
01098 {
01099   mrs_real r2;
01100   MarControlValueT<mrs_real> *ptr = dynamic_cast<MarControlValueT<mrs_real>*>(v2.value_);
01101   if(ptr)
01102   {
01103     r2 = ptr->get();
01104   }
01105   else
01106   {
01107     std::ostringstream sstr;
01108     sstr << "[MarControl::setValue] Trying to get value of incompatible type "
01109          << "(expected " << v2.getType() << ", given " << typeid(mrs_real).name() << ")";
01110     MRSWARN(sstr.str());
01111     return false;
01112   }
01113   return v1 / r2;
01114 }
01115 
01116 WAS_INLINE
01117 MarControl
01118 operator+(const MarControl& v1, const MarControl& v2)
01119 {
01120   MarControlValue *val = v1.value_->sum(v2.value_);
01121   MarControl ret(val);
01122   delete val;
01123   return ret;
01124 }
01125 
01126 WAS_INLINE
01127 MarControl
01128 operator-(const MarControl& v1, const MarControl& v2)
01129 {
01130   MarControlValue *val = v1.value_->subtract(v2.value_);
01131   MarControl ret(val);
01132   delete val;
01133   return ret;
01134 }
01135 
01136 WAS_INLINE
01137 MarControl
01138 operator*(const MarControl& v1, const MarControl& v2)
01139 {
01140   MarControlValue *val = v1.value_->multiply(v2.value_);
01141   MarControl ret(val);
01142   delete val;
01143   return ret;
01144 }
01145 
01146 WAS_INLINE
01147 MarControl
01148 operator/(const MarControl& v1, const MarControl& v2)
01149 {
01150   MarControlValue *val = v1.value_->divide(v2.value_);
01151   MarControl ret(val);
01152   delete val;
01153   return ret;
01154 }
01155 
01156 
01157 WAS_INLINE
01158 bool
01159 MarControl::isTrue()
01160 {
01161   MarControlValueT<bool> *ptr = dynamic_cast<MarControlValueT<bool>*>(value_);
01162   if(ptr)
01163   {
01164     return ptr->get();
01165   }
01166   else
01167   {
01168     std::ostringstream sstr;
01169     sstr << "MarControl::isTrue() - Trying to get use bool-specific method with " << value_->getType();
01170     MRSWARN(sstr.str());
01171     return false;
01172   }
01173 }
01174 
01175 
01176 } // namespace Marsyas