in pedalboard/_pedalboard.py [0:0]
def __init__(self, plugin: "ExternalPlugin", parameter_name: str, search_steps: int = 1000):
self.__plugin = plugin
self.__parameter_name = parameter_name
self.ranges: Dict[Tuple[float, float], Union[str, float, bool]] = {}
with self.__get_cpp_parameter() as cpp_parameter:
for fetch_slow in (False, True):
start_of_range: float = 0
text_value: Optional[str] = None
self.ranges = {}
for x in range(0, search_steps + 1):
raw_value = x / search_steps
x_text_value = get_text_for_raw_value(cpp_parameter, raw_value, fetch_slow)
if text_value is None:
text_value = x_text_value
elif x_text_value != text_value:
# End current range and start a new one
self.ranges[(start_of_range, raw_value)] = text_value
text_value = x_text_value
start_of_range = raw_value
results_look_incorrect = not self.ranges or (
len(self.ranges) == 1 and all(looks_like_float(v) for v in self.ranges.values())
)
if not results_look_incorrect:
break
if text_value is None:
raise NotImplementedError(
f"Plugin parameter '{parameter_name}' failed to return a valid string for its"
" value."
)
self.ranges[(start_of_range, 1)] = text_value
self.python_name = to_python_parameter_name(cpp_parameter)
self.min_value = None
self.max_value = None
self.step_size = None
self.approximate_step_size = None
self.type: Type = str
if all(looks_like_float(v) for v in self.ranges.values()):
self.type = float
float_ranges = {
k: float(strip_common_float_suffixes(v)) for k, v in self.ranges.items()
}
self.min_value = min(float_ranges.values())
self.max_value = max(float_ranges.values())
if not self.label:
# Try to infer the label from the string values:
a_value = next(iter(self.ranges.values()))
if isinstance(a_value, str):
stripped_value = strip_common_float_suffixes(a_value, strip_si_prefixes=False)
if (
stripped_value != a_value
and isinstance(stripped_value, str)
and stripped_value in a_value
):
# We probably have a label! Iterate through all values just to make sure:
all_possible_labels = set()
for value in self.ranges.values():
if not isinstance(value, str):
continue
stripped_value = strip_common_float_suffixes(
value, strip_si_prefixes=False
)
if not isinstance(stripped_value, str):
continue
all_possible_labels.add(value.replace(stripped_value, "").strip())
if len(all_possible_labels) == 1:
self._label = next(iter(all_possible_labels))
sorted_values = sorted(float_ranges.values())
first_derivative_steps = set(
[round(abs(b - a), 8) for a, b in zip(sorted_values, sorted_values[1:])]
)
if len(first_derivative_steps) == 1:
self.step_size = next(iter(first_derivative_steps))
elif first_derivative_steps:
self.approximate_step_size = sum(first_derivative_steps) / len(
first_derivative_steps
)
self.ranges = dict(float_ranges)
elif len(self.ranges) == 2 and (
TRUE_BOOLEANS & {(v.lower() if isinstance(v, str) else v) for v in self.ranges.values()}
):
self.type = bool
self.ranges = {
k: (v.lower() if isinstance(v, str) else v) in TRUE_BOOLEANS
for k, v in self.ranges.items()
}
self.min_value = False
self.max_value = True
self.step_size = 1
self.valid_values = list(self.ranges.values())
self.range = self.min_value, self.max_value, self.step_size
self._value_to_raw_value_ranges = {value: _range for _range, value in self.ranges.items()}