+void slave_knob(QDial *master, QDial *slave)
+{
+ QWidget::connect(master, &QDial::valueChanged, [slave](int value){
+ slave->blockSignals(true);
+ slave->setValue(value);
+ slave->blockSignals(false);
+ });
+ QWidget::connect(slave, &QDial::valueChanged, [master](int value){
+ master->setValue(value);
+ });
+}
+
+void slave_checkbox(QCheckBox *master, QCheckBox *slave)
+{
+ QWidget::connect(master, &QCheckBox::stateChanged, [slave](int state){
+ slave->blockSignals(true);
+ slave->setCheckState(Qt::CheckState(state));
+ slave->blockSignals(false);
+ });
+ QWidget::connect(slave, &QCheckBox::stateChanged, [master](int state){
+ master->setCheckState(Qt::CheckState(state));
+ });
+}
+
+void slave_fader(NonLinearFader *master, NonLinearFader *slave)
+{
+ QWidget::connect(master, &NonLinearFader::dbValueChanged, [slave](double value) {
+ slave->blockSignals(true);
+ slave->setDbValue(value);
+ slave->blockSignals(false);
+ });
+ QWidget::connect(slave, &NonLinearFader::dbValueChanged, [master](double value){
+ master->setDbValue(value);
+ });
+}
+
+constexpr unsigned DB_NO_FLAGS = 0x0;
+constexpr unsigned DB_WITH_SIGN = 0x1;
+constexpr unsigned DB_BARE = 0x2;
+
+string format_db(double db, unsigned flags)
+{
+ string text;
+ if (flags & DB_WITH_SIGN) {
+ if (isfinite(db)) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "%+.1f", db);
+ text = buf;
+ } else if (db < 0.0) {
+ text = "-∞";
+ } else {
+ // Should never happen, really.
+ text = "+∞";
+ }
+ } else {
+ if (isfinite(db)) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "%.1f", db);
+ text = buf;
+ } else if (db < 0.0) {
+ text = "-∞";
+ } else {
+ // Should never happen, really.
+ text = "∞";
+ }
+ }
+ if (!(flags & DB_BARE)) {
+ text += " dB";
+ }
+ return text;
+}
+