15Param::fetch (
const String &key)
 const 
   17  return kvpairs_fetch (
metadata, key);
 
   23  kvpairs_assign (
metadata, key + 
'=' + v);
 
   27ParamExtraVals::ParamExtraVals (
double vmin, 
double vmax, 
double step)
 
   30  Base::operator= (
MinMaxStep { vmin, vmax, step });
 
   33ParamExtraVals::ParamExtraVals (
const MinMaxStep &range)
 
   36  Base::operator= (range);
 
   40  *
this = ChoiceS (choices);
 
   43ParamExtraVals::ParamExtraVals (
const ChoiceS &choices)
 
   46  Base::operator= (choices);
 
   49ParamExtraVals::ParamExtraVals (
const ChoicesFunc &choicesfunc)
 
   52  Base::operator= (choicesfunc);
 
   57Parameter::construct_hints (
const String &hints, 
const String &more, 
double pmin, 
double pmax)
 
   79Parameter::nick ()
 const 
   81  String nick = fetch (
"nick");
 
   88Parameter::has (
const String &key)
 const 
   90  return key == 
"ident" || kvpairs_search (metadata_, key) >= 0;
 
   94Parameter::fetch (
const String &key)
 const 
   97  return kvpairs_fetch (metadata_, key);
 
  101Parameter::store (
const String &key, 
const String &value)
 
  108    kvpairs_assign (metadata_, kv);
 
  117  const ChoiceS cs = choices();
 
  119    return { 0, cs.size() -1, 1 };
 
  120  return { NAN, NAN, NAN };
 
 
  124Parameter::choices ()
 const 
  129    return (*cf) (cident);
 
  134Parameter::is_numeric ()
 const 
  138  auto [i, a, s] = 
range();
 
  143Parameter::initialsync (
const Value &v)
 
  149Parameter::has_hint (
const String &hint)
 const 
  151  const String hints_ = hints();
 
  153  while ((pos = hints_.find (hint, pos)) != std::string::npos) {
 
  154    if ((pos == 0 || hints_[pos-1] == 
':') && (pos + hint.size() == hints_.size() || hints_[pos + hint.size()] == 
':'))
 
  162Parameter::normalize (
double val)
 const 
  165  if (std::abs (fmax - fmin) < F32EPS)
 
  167  const double normalized = (val - 
fmin) / (fmax - fmin);
 
  168  assert_return (normalized >= 0.0 && normalized <= 1.0, normalized);
 
  173Parameter::rescale (
double t)
 const 
  182Parameter::match_choice (
const ChoiceS &choices, 
const String &text)
 
  184  for (
size_t i = 0; i < choices.size(); i++)
 
  185    if (text == choices[i].ident)
 
  190  for (
size_t i = 0; i < choices.size(); i++) {
 
  191    const size_t maxdist = 
std::max (choices[i].ident.size(), ltext.size());
 
  202Parameter::constrain (
const Value &value)
 const 
  206    const ChoiceS choices = this->choices();
 
  207    if (value.is_numeric()) {
 
  209      if (i >= 0 && i < choices.size())
 
  210        return choices[i].ident;
 
  212    const size_t selected = value.is_string() ? match_choice (choices, value.as_string()) : 0;
 
  213    return choices.size() ? choices[selected].ident : initial_;
 
  219  return dconstrain (value);
 
  223Parameter::dconstrain (
const Value &value)
 const 
  227    const ChoiceS choices = this->choices();
 
  228    if (value.is_numeric()) {
 
  230      if (i >= 0 && i < choices.size())
 
  233    const size_t selected = value.is_string() ? match_choice (choices, value.as_string()) : 0;
 
  238    return value.as_double();
 
  240  double val = value.as_double();
 
  242  if (std::abs (fmax - fmin) < F32EPS)
 
  246  if (step > F32EPS && has_hint (
"stepped")) {
 
  251    const double t = 
std::floor ((val - fmin) / step + nearintoffset);
 
  252    val = 
fmin + t * step;
 
  259minmaxstep_from_initialval (
const Param::InitialVal &iv, 
bool *isbool)
 
  268      range = { -128, 127, 1 };
 
  270      range = { 0, 255, 1 };
 
  272      range = { -32768, 32767, 1 };
 
  274      range = { 0, 65536, 1 };
 
  276      range = { -2147483648, 2147483647, 1 };
 
  278      range = { 0, 4294967295, 1 };
 
  280      range = { -9223372036854775807-1, 9223372036854775807, 1 };
 
  282      range = { 0, 18446744073709551615ull, 1 };
 
  284      range = { -F32MAX, F32MAX, 0 };
 
  286      range = { -D64MAX, D64MAX, 0 };
 
  289      range = { 0, I31MAX, 1 }; 
 
  291      static_assert (
sizeof (T) < 0, 
"unimplemented InitialVal type");
 
  299value_from_initialval (
const Param::InitialVal &iv)
 
  312      value = int32_t (arg);
 
  317      value = int64_t (arg);
 
  326      static_assert (
sizeof (T) < 0, 
"unimplemented InitialVal type");
 
  331Parameter::Parameter (
const Param &initparam)
 
  333  const Param &p = initparam;
 
  334  cident = kvpairs_fetch (p.metadata, 
"ident");
 
  335  if (!p.ident.empty()) {
 
  337    kvpairs_assign (metadata_, 
"ident=" + cident);
 
  338  } 
else if (cident.empty()) {
 
  340    kvpairs_assign (metadata_, 
"ident=" + cident);
 
  342  metadata_ = p.metadata; 
 
  348  if (!p.label.empty())
 
  349    store (
"label", p.label);
 
  351    store (
"nick", p.nick);
 
  353    store (
"unit", p.unit);
 
  357    extras_ = *choicesfuncp;
 
  360  else if (fmin != fmax)
 
  363    extras_ = minmaxstep_from_initialval (p.initial, &isbool);
 
  364  initial_ = value_from_initialval (p.initial);
 
  366  String choice = choicesp || choicesfuncp ? 
"choice" : 
"";
 
  367  String text = choicesfuncp || initial_.is_string() ? 
"text" : 
"";
 
  368  String dynamic = choicesfuncp ? 
"dynamic" : 
"";
 
  369  String stepped = isbool ? 
"stepped" : 
"";
 
  370  store (
"hints", construct_hints (p.hints, fetch (
"hints") + 
":" + text + 
":" + choice + 
":" + dynamic + 
":" + stepped, fmin, fmax));
 
  375Parameter::value_to_text (
const Value &value)
 const 
  379  const Value::Type type = value.index();
 
  380  if (type != Value::BOOL && type != Value::INT64 && type != Value::DOUBLE)
 
  381    return value.as_string();
 
  382  double val = value.as_double();
 
  383  String unit = this->unit();
 
  384  if (unit == 
"Hz" && fabs (val) >= 1000)
 
  392  else if (fabs (val) < 100)
 
  394  else if (fabs (val) < 1000)
 
  399  const bool need_sign = 
fmin < 0;
 
  401  if (fdigits == 0 && fabs (val) == 100 && unit == 
"%")
 
  409Parameter::value_from_text (
const String &text)
 const 
  412    const ChoiceS choices = this->choices();
 
  413    return int64_t (match_choice (choices, text));
 
  424  return { *
this, 
id };
 
 
  428ParameterMap::Entry::operator= (
const Param ¶m)
 
  430  const char *
const FUNC = 
"ParameterMap::Entry::operator=";
 
  434    warning (
"%s: reassign parameter '%s' with: %s\n", FUNC, old->ident(), param.
ident);
 
  436    auto it = pmap.find (
id - 1);
 
  437    if (it != pmap.end() && it->second) {
 
  439      if (it->second->ident() == param.
ident)
 
  440        warning (
"%s: duplicate %s: '%s' (param_id=%u)", FUNC, 
"ident", param.
ident, 
id);
 
  441      else if (it->second->label() == param.
label)
 
  442        warning (
"%s: duplicate %s: '%s' (param_id=%u)", FUNC, 
"label", param.
label, 
id);
 
  446    Param mparam = param;
 
  447    mparam.store (
"group", map.
group);
 
  457  return kvpairs_fetch (metadata, 
"hints");
 
 
  463  return kvpairs_fetch (metadata, 
"blurb");
 
 
  469  return kvpairs_fetch (metadata, 
"descr");
 
 
  475  return kvpairs_fetch (metadata, 
"group");
 
 
  483search_first_digit (
const String &s)
 
  485  for (
size_t i = 0; i < s.
size(); ++i)
 
  493search_last_digits (
const String &s)
 
  495  for (
size_t i = 0; i < s.size(); ++i)
 
  496    if (isdigit (s[i])) {
 
  497      if (isdigit (s[i+1]) && !isalnum (s[i+2]))
 
  499      else if (!isalnum (s[i+1]))
 
  507make_nick3 (
const String &label)
 
  513  if (words.size() == 1) {
 
  514    const ssize_t d = search_first_digit (words[0]);
 
  515    if (d > 0 && isdigit (words[0][d + 1]))                     
 
  516      return { words[0].substr (0, 1), words[0].substr (d, 2), 
"" };
 
  518      return { words[0].substr (0, 2), words[0].substr (d, 1), 
"" };
 
  520      return { words[0].substr (0, 3), 
"", 
"" };
 
  524  if (words.size() == 2) {
 
  525    const ssize_t e = search_last_digits (words[1]);
 
  526    if (e >= 0 && isdigit (words[1][e+1]))                      
 
  527      return { words[0].substr (0, 1), words[1].substr (e, 2), 
"" };
 
  529      return { words[0].substr (0, 1), words[1].substr (0, 1), words[1].substr (e, 1) };
 
  531      return { words[0].substr (0, 2), words[1].substr (e, 1), 
"" };
 
  532    const ssize_t d = search_first_digit (words[0]);
 
  534      return { words[0].substr (0, 1), words[0].substr (d, 1), words[1].substr (0, 1) };
 
  535    if (words[1].
size() > 1)                                    
 
  536      return { words[0].substr (0, 1), words[1].substr (0, 2), 
"" };
 
  538      return { words[0].substr (0, 2), words[1].substr (0, 1), 
"" };
 
  542  if (words.size() >= 3) {
 
  544    for (i = words.size() - 1; i > 1; i--) {
 
  545      e = search_last_digits (words[i]);
 
  549    if (e >= 0 && isdigit (words[i][e + 1]))                    
 
  550      return { words[0].substr (0, 1), words[i].substr (e, 2), 
"" };
 
  551    if (e >= 0 && i + 1 < words.size())                         
 
  552      return { words[0].substr (0, 1), words[i].substr (e, 1), words[i+1].substr (0, 1) };
 
  554      return { words[0].substr (0, 1), words[i].substr (0, 1), words[i].substr (e, 1) };
 
  555    if (e == 0 && i >= 3)                                       
 
  556      return { words[0].substr (0, 1), words[i-1].substr (0, 1), words[i].substr (e, 1) };
 
  557    if (e == 0 && i >= 2)                                       
 
  558      return { words[0].substr (0, 1), words[1].substr (0, 1), words[i].substr (e, 1) };
 
  560      return { words[0].substr (0, 2), words[i].substr (e, 1), 
"" };
 
  561    if (words.back().size() >= 2)                               
 
  562      return { words[0].substr (0, 1), words.back().substr (0, 2), 
"" };
 
  564      return { words[0].substr (0, 1), words[words.size()-1].substr (0, 1), words.back().substr (0, 1) };
 
  568  return { words[0].substr (0, 3), 
"", 
"" };
 
  575  for (ssize_t i = s.size() - 1; i > 0; i--)
 
  577      s.
insert (s.begin() + i, 
' ');
 
  586  String string = spaced_nums (parameter_label);
 
  589  const auto& [a, b, c] = make_nick3 (
string);
 
  594    nick = a.
substr (0, 1) + b.substr (0, 1) + c.substr (0, 1);
 
  595  else if (b.size() > 0)
 
  596    nick = a.
substr (0, 1) + b.substr (0, 2);
 
 
String descr() const
Elaborate description, e.g. for help dialogs (metadata).
 
String blurb() const
Short description for user interface tooltips (metadata).
 
String hints() const
Hints for parameter handling (metadata).
 
String group() const
Group name for parameters of similar function (metadata).
 
static StringS findall(const String ®ex, const String &input, Flags=DEFAULT)
Find regex in input and return non-overlapping matches.
 
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
 
#define return_unless(cond,...)
Return silently if cond does not evaluate to true with return value ...
 
The Anklang C++ API namespace.
 
std::string string_format(const char *format, const Args &...args) __attribute__((__format__(__printf__
Format a string similar to sprintf(3) with support for std::string and std::ostringstream convertible...
 
StringS string_split(const String &string, const String &splitter, size_t maxn)
 
String parameter_guess_nick(const String ¶meter_label)
Create a few letter nick name from a multi word parameter label.
 
String string_tolower(const String &str)
Convert all string characters into Unicode lower case characters.
 
std::tuple< double, double, double > MinMaxStep
Min, max, stepping for double ranges.
 
std::vector< String > StringS
Convenience alias for a std::vector<std::string>.
 
std::function< ChoiceS(const CString &)> ChoicesFunc
Handler to generate all possible parameter choices dynamically.
 
String string_option_find(const String &optionlist, const String &feature, const String &fallback)
Retrieve the option value from an options list separated by ':' or ';' or fallback.
 
double string_to_double(const String &string)
Parse a double from a string, trying locale specific characters and POSIX/C formatting.
 
std::string String
Convenience alias for std::string.
 
constexpr const char STANDARD[]
STORAGE GUI READABLE WRITABLE.
 
float damerau_levenshtein_restricted(const std::string &source, const std::string &target, const float ci, const float cd, const float cs, const float ct)
 
String string_to_ncname(const String &input, uint32_t substitute)
 
constexpr const double DOUBLE_EPSILON
Double round-off error at 1.0, equals 2^-53.
 
Structured initializer for Parameter.
 
StringS metadata
Array of "key=value" pairs.
 
String label
Preferred user interface name.
 
String ident
Identifier used for serialization (can be derived from untranslated label).
 
Entry operator[](uint32_t id)
Slot subscription for new Parameter creation.
 
String group
Group to be applied to all newly inserted Parameter objects.
 
MinMaxStep range() const
Min, max, stepping for double ranges.
 
double as_double() const
Convert Value to double or return 0.
 
bool is_numeric(bool boolisnumeric=true) const
Checks if Value is a DOUBLE, INT64, or BOOL.
 
String as_string() const
Convert Value to a string, not very useful for RECORD or ARRAY.