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 findParamAndActOnIt(paramdescriptor,
442 { param->
hide(doit); ++n; },
444 [&n]() {
return (n == 0); }
451 boost::shared_lock<boost::shared_mutex> lck(itsParamMtx);
453 for (
auto const & p : itsParameterList) p.second->hide(doit);
460 std::ifstream ifs(absfile);
461 if (!ifs)
LFATAL(
"Could not open file " << absfile);
462 setParamsFromStream(ifs, absfile);
469 for (std::string line; std::getline(is, line); )
472 if (line.length() && line[0] ==
'#') { ++linenum;
continue; }
475 if (std::all_of(line.begin(), line.end(), [](
unsigned char c) { return std::isspace(c); })) { ++linenum;
continue; }
478 size_t idx = line.find(
'=');
479 if (idx == line.npos)
LFATAL(
"No '=' symbol found at line " << linenum <<
" in " << absfile);
480 if (idx == 0)
LFATAL(
"No parameter descriptor found at line " << linenum <<
" in " << absfile);
481 if (idx == line.length() - 1)
LFATAL(
"No parameter value found at line " << linenum <<
" in " << absfile);
483 std::string desc = line.substr(0, idx);
484 std::string val = line.substr(idx + 1);
487 while (desc.length() > 0 && std::isspace(desc[0])) desc.erase(0, 1);
488 while (desc.length() > 0 && std::isspace(desc[desc.length()-1])) desc.erase(desc.length()-1, 1);
489 if (desc.empty())
LFATAL(
"Invalid blank parameter descriptor at line " << linenum <<
" in " << absfile);
491 while (val.length() > 0 && std::isspace(val[0])) val.erase(0, 1);
492 while (val.length() > 0 && std::isspace(val[val.length()-1])) val.erase(val.length()-1, 1);
493 if (val.empty())
LFATAL(
"Invalid blank parameter value at line " << linenum <<
" in " << absfile);
496 setParamString(desc, val);
510 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
511 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->setPath(path);
520 std::lock_guard<std::mutex> _(itsDynParMtx);
522 auto itr = itsDynParams.find(name);
523 if (itr == itsDynParams.end())
525 if (throw_if_not_found)
LFATAL(
"No dynamic parameter with name [" << name <<
']');
530 itsDynParams.erase(itr);
542 bool skipFrozen, std::string
const & cname, std::string
const & pfx)
546 std::string
const compname = cname.empty() ? itsInstanceName : cname +
':' + itsInstanceName;
550 boost::shared_lock<boost::shared_mutex> lck(itsParamMtx);
551 for (
auto const & p : itsParameterList)
556 if (skipFrozen && ps.
frozen)
continue;
560 if (ps.
frozen) s->writeString(pfx,
"F");
else s->writeString(pfx,
"N");
561 s->writeString(pfx, compname);
563 s->writeString(pfx, ps.
name);
565 s->writeString(pfx, ps.
value);
573 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
574 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->paramInfo(s, categs, skipFrozen, compname, pfx);
579 s->writeString(pfx,
"C");
580 for (
auto const & c : categs)
582 s->writeString(pfx, c.first);
583 s->writeString(pfx, c.second);
590 std::string
const & cname)
594 std::string
const compname = cname.empty() ? itsInstanceName : cname +
':' + itsInstanceName;
598 boost::shared_lock<boost::shared_mutex> lck(itsParamMtx);
599 for (
auto const & p : itsParameterList) func(compname, p.second);
603 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
604 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->foreachParam(func, compname);
608void jevois::Component::populateHelpMessage(std::string
const & cname,
609 std::unordered_map<std::string,
610 std::unordered_map<std::string,
611 std::vector<std::pair<std::string, std::string> > > > & helplist,
616 std::string
const compname = cname.empty() ? itsInstanceName : cname +
':' + itsInstanceName;
620 boost::shared_lock<boost::shared_mutex> lck(itsParamMtx);
621 for (
auto const & p : itsParameterList)
630 std::string val =
"";
632 helplist[key1][key2].push_back(std::make_pair(compname, val));
639 boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
640 for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->populateHelpMessage(compname, helplist);
645std::string jevois::Component::computeInstanceName(std::string
const & instance, std::string
const & classname)
const
649 std::string inst = instance;
655 inst = classname +
'#';
658 size_t const idxx = inst.rfind(
':');
if (idxx != inst.npos) inst = inst.substr(idxx + 1);
667 for (std::shared_ptr<Component>
const & c : itsSubComponents)
668 if (c->instanceName() == inst) { found =
true;
break; }
674 for (std::string
const & v : vec)
676 if (v.empty())
continue;
679 size_t largestId = 1;
683 std::string stem = inst + std::to_string(largestId);
686 for (std::shared_ptr<Component>
const & c : itsSubComponents)
687 if (c->instanceName() == stem) { gotit =
true;
break; }
689 if (gotit ==
false) { inst = stem;
break; }
696 LDEBUG(
"Using automatic instance name [" << inst <<
']');
701 for (std::shared_ptr<Component>
const & c : itsSubComponents)
702 if (c->instanceName() == inst)
703 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.
void hideAllParams(bool doit)
Hide all parameters.
virtual ~Component()
Virtual destructor for safe inheritance.
void hideParam(std::string const ¶mdescriptor, bool doit)
Hide/unhide a parameter, by name, see ParameterBase::hide()
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.
void hide(bool doit)
Hide or un-hide a parameter; hidden params will not show up in GUI or help message,...
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.
bool hidden
Flag that indicates whether parameter is hidden.
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...