33 itsInstanceName(instanceName), itsInitialized(false), itsParent(nullptr), itsPath()
41 boost::shared_lock<boost::shared_mutex> lck(itsMetaMtx);
44 if (itsClassName.empty()) *(
const_cast<std::string *
>(&itsClassName)) =
jevois::demangle(
typeid(*this).name());
51{
return itsInstanceName; }
58 LDEBUG(
"Deleting Component");
61 if (itsInitialized) jevois::Component::uninit();
65 boost::upgrade_lock<boost::shared_mutex> uplck(itsSubMtx);
67 while (itsSubComponents.empty() ==
false)
69 auto itr = itsSubComponents.begin();
70 doRemoveSubComponent(itr, uplck,
"SubComponent");
79 boost::upgrade_lock<boost::shared_mutex> uplck(itsSubMtx);
81 for (
auto itr = itsSubComponents.begin(); itr != itsSubComponents.end(); ++itr)
82 if ((*itr)->instanceName() == instanceName)
85 doRemoveSubComponent(itr, uplck,
"SubComponent");
89 if (warnIfNotFound)
LERROR(
"SubComponent [" << instanceName <<
"] not found. Ignored.");
93void jevois::Component::doRemoveSubComponent(std::vector<std::shared_ptr<jevois::Component> >::iterator & itr,
94 boost::upgrade_lock<boost::shared_mutex> & uplck,
95 std::string
const & displayname)
100 std::shared_ptr<jevois::Component> component = *itr;
102 LDEBUG(
"Removing " << displayname <<
" [" << component->descriptor() <<
']');
105 if (component->initialized()) component->uninit();
108 boost::upgrade_to_unique_lock<boost::shared_mutex> ulck(uplck);
109 itsSubComponents.erase(itr);
111 if (component.use_count() > 1)
112 LERROR(component.use_count() - 1 <<
" additional external shared_ptr reference(s) exist to "
113 << displayname <<
" [" << component->descriptor() <<
"]. It was removed but NOT deleted.");
123 boost::shared_lock<boost::shared_mutex> lck(itsMtx);
124 if (
dynamic_cast<jevois::Manager *
>(itsParent) !=
nullptr)
return true;
133 boost::shared_lock<boost::shared_mutex> lck(itsMtx);
136 if (itsParent)
return itsParent->engine();
137 LFATAL(
"Reached root of hierarchy but could not find an Engine");
141void jevois::Component::init()
145 if (itsInitialized) {
LERROR(
"Already initialized. Ignored.");
return; }
147 LDEBUG(
"Initializing...");
157void jevois::Component::runPreInit()
163 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
164 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->runPreInit();
176void jevois::Component::setInitialized()
182 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
183 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->setInitialized();
187 itsInitialized =
true;
191void jevois::Component::runPostInit()
197 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
198 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->runPostInit();
210 return itsInitialized;
214void jevois::Component::uninit()
220 LDEBUG(
"Uninitializing...");
231void jevois::Component::runPreUninit()
237 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
238 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->runPreUninit();
246void jevois::Component::setUninitialized()
251 itsInitialized =
false;
255 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
256 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->setUninitialized();
261void jevois::Component::runPostUninit()
270 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
271 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->runPostUninit();
283 boost::shared_lock<boost::shared_mutex> lck(itsMtx);
285 if (itsParent &&
dynamic_cast<jevois::Manager *
>(itsParent) ==
nullptr)
286 return itsParent->descriptor() +
':' + itsInstanceName;
288 return itsInstanceName;
292void jevois::Component::findParamAndActOnIt(std::string
const & descrip,
294 std::function<
bool()> empty)
const
299 std::vector<std::string> desc =
jevois::split(descrip,
":" );
301 if (desc.empty())
throw std::range_error(descriptor() +
": Cannot parse empty parameter name");
304 findParamAndActOnIt(desc,
true, 0,
"", doit);
306 if (empty())
throw std::range_error(descriptor() +
": No Parameter named [" + descrip +
']');
310void jevois::Component::findParamAndActOnIt(std::vector<std::string>
const & descrip,
311 bool recur,
size_t idx, std::string
const & unrolled,
317 if (descrip.size() > idx + 1)
320 if (descrip[idx] ==
"*") { recur =
true; ++idx; }
325 if (itsInstanceName == descrip[idx]) { recur =
false; ++idx; }
330 if (descrip.size() == idx + 1)
333 boost::shared_lock<boost::shared_mutex> lck(itsParamMtx);
335 for (
auto const & p : itsParameterList)
336 if (p.second->name() == descrip[idx])
339 std::string ur = itsInstanceName +
':' + p.second->name();
340 if (unrolled.empty() ==
false) ur = unrolled +
':' + ur;
346 if (recur || descrip.size() > idx + 1)
348 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
351 if (unrolled.empty()) ur = itsInstanceName;
else ur = unrolled +
':' + itsInstanceName;
353 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->findParamAndActOnIt(descrip, recur, idx, ur, doit);
362 std::vector<std::string> ret;
363 findParamAndActOnIt(descriptor,
366 { param->
strset(val); ret.push_back(unrolled); },
368 [&ret]() {
return ret.empty(); }
379 std::vector<std::pair<std::string, std::string> > test = getParamString(descriptor);
380 if (test.size() > 1)
throw std::range_error(
"Ambiguous multiple matches for descriptor [" + descriptor +
']');
383 std::vector<std::string> ret = setParamString(descriptor, val);
384 if (ret.size() > 1)
throw std::range_error(
"Ambiguous multiple matches for descriptor [" + descriptor +
']');
388std::vector<std::pair<std::string, std::string> >
393 std::vector<std::pair<std::string, std::string> > ret;
394 findParamAndActOnIt(descriptor,
397 { ret.push_back(std::make_pair(unrolled, param->
strget())); },
399 [&ret]() {
return ret.empty(); }
409 std::vector<std::pair<std::string, std::string> > ret = getParamString(descriptor);
410 if (ret.size() > 1)
throw std::range_error(
"Ambiguous multiple matches for descriptor [" + descriptor +
']');
413 return ret[0].second;
420 findParamAndActOnIt(paramdescriptor,
422 { param->
freeze(doit); ++n; },
424 [&n]() {
return (n == 0); }
431 boost::shared_lock<boost::shared_mutex> lck(itsParamMtx);
433 for (
auto const & p : itsParameterList) p.second->freeze(doit);
440 std::ifstream ifs(absfile);
441 if (!ifs)
LFATAL(
"Could not open file " << absfile);
442 setParamsFromStream(ifs, absfile);
449 for (std::string line; std::getline(is, line); )
452 if (line.length() && line[0] ==
'#') { ++linenum;
continue; }
455 if (std::all_of(line.begin(), line.end(), [](
unsigned char c) { return std::isspace(c); })) { ++linenum;
continue; }
458 size_t idx = line.find(
'=');
459 if (idx == line.npos)
LFATAL(
"No '=' symbol found at line " << linenum <<
" in " << absfile);
460 if (idx == 0)
LFATAL(
"No parameter descriptor found at line " << linenum <<
" in " << absfile);
461 if (idx == line.length() - 1)
LFATAL(
"No parameter value found at line " << linenum <<
" in " << absfile);
463 std::string desc = line.substr(0, idx);
464 std::string val = line.substr(idx + 1);
467 while (desc.length() > 0 && std::isspace(desc[0])) desc.erase(0, 1);
468 while (desc.length() > 0 && std::isspace(desc[desc.length()-1])) desc.erase(desc.length()-1, 1);
469 if (desc.empty())
LFATAL(
"Invalid blank parameter descriptor at line " << linenum <<
" in " << absfile);
471 while (val.length() > 0 && std::isspace(val[0])) val.erase(0, 1);
472 while (val.length() > 0 && std::isspace(val[val.length()-1])) val.erase(val.length()-1, 1);
473 if (val.empty())
LFATAL(
"Invalid blank parameter value at line " << linenum <<
" in " << absfile);
476 setParamString(desc, val);
490 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
491 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->setPath(path);
500 std::lock_guard<std::mutex> _(itsDynParMtx);
502 auto itr = itsDynParams.find(name);
503 if (itr == itsDynParams.end())
505 if (throw_if_not_found)
LFATAL(
"No dynamic parameter with name [" << name <<
']');
510 itsDynParams.erase(itr);
522 bool skipFrozen, std::string
const & cname, std::string
const & pfx)
526 std::string
const compname = cname.empty() ? itsInstanceName : cname +
':' + itsInstanceName;
530 boost::shared_lock<boost::shared_mutex> lck(itsParamMtx);
531 for (
auto const & p : itsParameterList)
535 if (skipFrozen && ps.
frozen)
continue;
539 if (ps.
frozen) s->writeString(pfx,
"F");
else s->writeString(pfx,
"N");
540 s->writeString(pfx, compname);
542 s->writeString(pfx, ps.
name);
544 s->writeString(pfx, ps.
value);
552 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
553 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->paramInfo(s, categs, skipFrozen, compname, pfx);
558 s->writeString(pfx,
"C");
559 for (
auto const & c : categs)
561 s->writeString(pfx, c.first);
562 s->writeString(pfx, c.second);
569 std::string
const & cname)
573 std::string
const compname = cname.empty() ? itsInstanceName : cname +
':' + itsInstanceName;
577 boost::shared_lock<boost::shared_mutex> lck(itsParamMtx);
578 for (
auto const & p : itsParameterList) func(compname, p.second);
582 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
583 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->foreachParam(func, compname);
587void jevois::Component::populateHelpMessage(std::string
const & cname,
588 std::unordered_map<std::string,
589 std::unordered_map<std::string,
590 std::vector<std::pair<std::string, std::string> > > > & helplist,
595 std::string
const compname = cname.empty() ? itsInstanceName : cname +
':' + itsInstanceName;
599 boost::shared_lock<boost::shared_mutex> lck(itsParamMtx);
600 for (
auto const & p : itsParameterList)
609 std::string val =
"";
611 helplist[key1][key2].push_back(std::make_pair(compname, val));
618 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
619 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->populateHelpMessage(compname, helplist);
624std::string jevois::Component::computeInstanceName(std::string
const & instance, std::string
const & classname)
const
628 std::string inst = instance;
634 inst = classname +
'#';
637 size_t const idxx = inst.rfind(
':');
if (idxx != inst.npos) inst = inst.substr(idxx + 1);
646 for (std::shared_ptr<Component>
const & c : itsSubComponents)
647 if (c->instanceName() == inst) { found =
true;
break; }
653 for (std::string
const & v : vec)
655 if (v.empty())
continue;
658 size_t largestId = 1;
662 std::string stem = inst + std::to_string(largestId);
665 for (std::shared_ptr<Component>
const & c : itsSubComponents)
666 if (c->instanceName() == stem) { gotit =
true;
break; }
668 if (gotit ==
false) { inst = stem;
break; }
675 LDEBUG(
"Using automatic instance name [" << inst <<
']');
680 for (std::shared_ptr<Component>
const & c : itsSubComponents)
681 if (c->instanceName() == inst)
682 throw std::runtime_error(
"Provided instance name [" + instance +
"] clashes with existing sub-components.");
std::vector< std::string > setParamString(std::string const ¶mdescriptor, std::string const &val)
Set a parameter value, by string.
std::filesystem::path absolutePath(std::filesystem::path const &path="")
If given path is relative (not starting with /), prepend the Component path to it.
std::string descriptor() const
Get our full descriptor (including all parents) as [Instancename]:[...]:[...].
std::vector< std::pair< std::string, std::string > > getParamString(std::string const ¶mdescriptor) const
Get a parameter value, by string.
void freezeParam(std::string const ¶mdescriptor, bool doit)
Freeze/unfreeze a parameter, by name, see ParameterBase::freeze()
bool initialized() const
Has this component been initialized yet?
std::string const & instanceName() const
The instance name of this component.
void foreachParam(std::function< void(std::string const &compname, ParameterBase *p)> func, std::string const &cname="")
Run a function on every param we hold.
std::istream & setParamsFromStream(std::istream &is, std::string const &absfile)
Set some parameters from an open stream.
void freezeAllParams(bool doit)
Freeze all parameters.
void removeSubComponent(std::shared_ptr< Comp > &component)
Remove a sub-Component from this Component, by shared_ptr.
bool isTopLevel() const
Returns true if this component is top-level, i.e., its parent is jevois::Manager.
void setPath(std::string const &path)
Assign a filesystem path to this component.
virtual ~Component()
Virtual destructor for safe inheritance.
virtual void paramInfo(std::shared_ptr< UserInterface > s, std::map< std::string, std::string > &categs, bool skipFrozen, std::string const &cname="", std::string const &pfx="")
Get machine-oriented descriptions of all parameters.
std::string const & className() const
The class name of this component.
std::string getParamStringUnique(std::string const ¶mdescriptor) const
Get a parameter value by string, simple version assuming only one parameter match.
void setParamsFromFile(std::string const &filename)
Set some parameters from a file.
void removeDynamicParameter(std::string const &name, bool throw_if_not_found=true)
Remove a previously added dynamic parameter.
void setParamStringUnique(std::string const ¶mdescriptor, std::string const &val)
Set a parameter value by string, simple version assuming only one parameter match.
JeVois processing engine - gets images from camera sensor, processes them, and sends results over USB...
Manager of a hierarchy of Component objects.
Base class for Parameter.
virtual void strset(std::string const &valstring)=0
Set the value from a string representation of it.
virtual std::string const strget() const =0
Get the value as a string.
void freeze(bool doit)
Freeze or un-freeze a parameter; frozen parameters cannot be set(), but get() is still allowed.
void callbackInitCall()
For all parameters that have a callback which has never been called, call it with the default param v...
friend class Component
Allow Component and DynamicParameter to access our registry data, everyone else is locked out.
ParameterSummary provides a summary about a parameter.
std::string name
Plain name of the parameter.
std::string category
Category of the parameter, as a string.
std::string categorydescription
Category description.
std::string valuetype
Parameter value type, as a string.
std::string value
Current value of the parameter, as a string.
std::string validvalues
Description of the parameter's valid values specification, as a string.
std::string defaultvalue
Default value of the parameter, as a string.
bool frozen
Flag that indicates whether parameter is frozen.
std::string description
Description of the parameter.
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
#define LDEBUG(msg)
Convenience macro for users to print out console or syslog messages, DEBUG level.
#define JEVOIS_TRACE(level)
Trace object.
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
std::string demangle(std::string const &mangledName)
Demangle a mangled name.
std::string join(std::vector< T > const &tokens, std::string const &delimiter)
Concatenate a vector of tokens into a string.
std::filesystem::path absolutePath(std::filesystem::path const &root, std::filesystem::path const &path)
Compute an absolute path from two paths.
std::vector< std::string > split(std::string const &input, std::string const ®ex="\\s+")
Split string into vector of tokens using a regex to specify what to split on; default regex splits by...