• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ossia / score / 37492781442

06 Oct 2026 04:04PM UTC coverage: 48.588% (+1.1%) from 47.45%
37492781442

push

github

jcelerier
execution: a port's address is rebound on the ossia port it has now

The rebinds on a port's exposed name and scriptable flag are queued, and a
queued call still runs after the port is bound again: one posted while a
shader's undo restored its ports ran after the second program change had
replaced the ossia inlets, and the audio thread unregistered a freed inlet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcLJ4VuB2nzXbazQb9nyC1

14 of 14 new or added lines in 1 file covered. (100.0%)

4596 existing lines in 94 files now uncovered.

157183 of 323499 relevant lines covered (48.59%)

149381.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

62.73
/src/plugins/score-lib-process/Process/Dataflow/WidgetInlets.cpp
1
#include <Process/Dataflow/WidgetInlets.hpp>
2

3
#include <score/document/DocumentContext.hpp>
4
#include <score/document/DocumentInterface.hpp>
5
#include <score/plugins/SerializableHelpers.hpp>
6
#include <score/tools/FilePath.hpp>
7
#include <score/tools/FileWatch.hpp>
8

9
#include <ossia/dataflow/port.hpp>
10
#include <ossia/detail/parse_strict.hpp>
11
#include <ossia/detail/ssize.hpp>
12
#include <ossia/network/value/value_conversion.hpp>
13

14
#include <ossia-qt/invoke.hpp>
15

16
#include <QCoreApplication>
17
#include <QDir>
18
#include <QFileSystemWatcher>
19

20
#include <cmath>
21
#include <optional>
22

23
#include <core/document/Document.hpp>
24

25
#include <wobjectimpl.h>
26

27
W_OBJECT_IMPL(Process::ComboBox)
62,999 ✔
28
W_OBJECT_IMPL(Process::FileChooserBase)
2 ✔
29
W_OBJECT_IMPL(Process::FileChooser)
783 ✔
30
W_OBJECT_IMPL(Process::FolderChooser)
9 ✔
31
W_OBJECT_IMPL(Process::AudioFileChooser)
3 ✔
UNCOV
32
W_OBJECT_IMPL(Process::VideoFileChooser)
×
33
W_OBJECT_IMPL(Process::ImpulseButton)
11,651 ✔
34
W_OBJECT_IMPL(Process::FloatSlider)
153,416 ✔
35
W_OBJECT_IMPL(Process::FloatKnob)
36,909 ✔
36
W_OBJECT_IMPL(Process::LogFloatSlider)
12,957 ✔
37
W_OBJECT_IMPL(Process::IntSlider)
36,428 ✔
UNCOV
38
W_OBJECT_IMPL(Process::IntRangeSlider)
×
39
W_OBJECT_IMPL(Process::FloatRangeSlider)
54 ✔
UNCOV
40
W_OBJECT_IMPL(Process::IntRangeSpinBox)
×
41
W_OBJECT_IMPL(Process::FloatRangeSpinBox)
×
42
W_OBJECT_IMPL(Process::IntSpinBox)
27,904 ✔
43
W_OBJECT_IMPL(Process::FloatSpinBox)
13,729 ✔
44
W_OBJECT_IMPL(Process::TimeChooser)
7,337 ✔
45
W_OBJECT_IMPL(Process::Toggle)
42,369 ✔
UNCOV
46
W_OBJECT_IMPL(Process::ChooserToggle)
×
47
W_OBJECT_IMPL(Process::LineEdit)
59,990 ✔
48
W_OBJECT_IMPL(Process::ProgramEdit)
108 ✔
49
W_OBJECT_IMPL(Process::Enum)
14,901 ✔
50
W_OBJECT_IMPL(Process::Button)
753 ✔
51
W_OBJECT_IMPL(Process::HSVSlider)
6,211 ✔
52
W_OBJECT_IMPL(Process::XYSlider)
265 ✔
UNCOV
53
W_OBJECT_IMPL(Process::XYZSlider)
×
54
W_OBJECT_IMPL(Process::XYSpinboxes)
1,140 ✔
55
W_OBJECT_IMPL(Process::XYZSpinboxes)
3,197 ✔
56
W_OBJECT_IMPL(Process::MultiSlider)
3,706 ✔
57
W_OBJECT_IMPL(Process::MultiSliderXY)
9 ✔
58
W_OBJECT_IMPL(Process::PathGeneratorXY)
9 ✔
UNCOV
59
W_OBJECT_IMPL(Process::Bargraph)
×
60
namespace Process
61
{
62
namespace
63
{
64
struct entry_index_visitor
65
{
66
  int n;
67

68
  std::optional<int> operator()(int32_t i) const noexcept
6 ✔
69
  {
70
    return i >= 0 && i < n ? std::optional<int>(i) : std::nullopt;
6 ✔
71
  }
72
  std::optional<int> operator()(float f) const noexcept
9 ✔
73
  {
74
    // Bounded before narrowing: int32_t(1e30f) and int32_t(NaN) are undefined.
75
    // Whole numbers only, so a float and the same number spelled as a string
76
    // agree, and nothing in (-1, 1) truncates onto the first entry.
77
    const double d = f;
9 ✔
78
    if(!(d >= 0. && d < double(n)) || d != std::floor(d))
9 ✔
79
      return std::nullopt;
7 ✔
80
    return std::optional<int>(int(d));
2 ✔
81
  }
9 ✔
82
  std::optional<int> operator()(const std::string& s) const noexcept
6 ✔
83
  {
84
    // Exactly the digits a coerced integer becomes, not even surrounding
85
    // blanks: anything looser eats names that merely begin with a number.
86
    const auto parsed = ossia::parse_strict<int64_t>(s);
6 ✔
87
    if(!parsed)
6 ✔
88
      return std::nullopt;
4 ✔
89
    // Bounded here: narrowing first could fold a huge number back into range.
90
    return *parsed >= 0 && *parsed < n ? std::optional<int>(int(*parsed))
2 ✔
91
                                       : std::nullopt;
1 ✔
92
  }
6 ✔
UNCOV
93
  std::optional<int> operator()(const auto&) const noexcept { return std::nullopt; }
×
UNCOV
94
  std::optional<int> operator()() const noexcept { return std::nullopt; }
×
95
};
96

97
bool entriesAreNames(
8 ✔
98
    const std::vector<std::pair<QString, ossia::value>>& alternatives) noexcept
99
{
100
  for(const auto& [name, value] : alternatives)
8 ✔
101
    if(value.valid())
8 ✔
102
      return value.get_type() == ossia::val_type::STRING;
8 ✔
UNCOV
103
  return false;
×
104
}
8 ✔
105
}
106

107
std::optional<int> readEntryIndex(const ossia::value& v, int n) noexcept
21 ✔
108
{
109
  return v.apply(entry_index_visitor{n});
21 ✔
110
}
111

112
int ComboBox::indexOfValue(const ossia::value& v) const noexcept
193 ✔
113
{
114
  // Two invalid values compare equal, so one would select a valueless entry.
115
  if(!v.valid())
193 ✔
116
    return -1;
1 ✔
117

118
  const int n = std::ssize(alternatives);
192 ✔
119
  for(int i = 0; i < n; i++)
482 ✔
120
    if(alternatives[i].second == v)
474 ✔
121
      return i;
184 ✔
122

123
  if(!entriesAreNames(alternatives))
8 ✔
124
    return -1;
3 ✔
125

126
  return readEntryIndex(v, n).value_or(-1);
5 ✔
127
}
193 ✔
128

129
ossia::value ComboBox::valueAtIndex(int i) const noexcept
4 ✔
130
{
131
  if(i < 0 || i >= std::ssize(alternatives))
4 ✔
132
    return {};
2 ✔
133
  return alternatives[i].second;
2 ✔
134
}
4 ✔
135

136
int Enum::indexOfValue(const ossia::value& v) const noexcept
259 ✔
137
{
138
  if(!v.valid())
259 ✔
139
    return -1;
1 ✔
140

141
  const int n = std::ssize(values);
258 ✔
142
  const auto name = QString::fromStdString(ossia::convert<std::string>(v));
258 ✔
143
  for(int i = 0; i < n; i++)
347 ✔
144
    if(values[i] == name)
331 ✔
145
      return i;
242 ✔
146

147
  return readEntryIndex(v, n).value_or(-1);
16 ✔
148
}
259 ✔
149

150
ossia::value Enum::valueAtIndex(int i) const noexcept
4 ✔
151
{
152
  if(i < 0 || i >= std::ssize(values))
4 ✔
153
    return {};
1 ✔
154
  return values[i].toStdString();
3 ✔
155
}
4 ✔
156

157
Enum::Enum(
718 ✔
158
    const std::vector<std::string>& dom, std::vector<QString> pixmaps, std::string init,
159
    const QString& name, Id<Port> id, QObject* parent)
160
    : ControlInlet{name, id, parent}
718 ✔
161
    , pixmaps{std::move(pixmaps)}
718 ✔
162
{
718 ✔
163
  for(auto& val : dom)
3,933 ✔
164
    values.push_back(QString::fromStdString(val));
3,215 ✔
165

166
  displayHandledExplicitly = true;
718 ✔
167
  setInit(init);
718 ✔
168
  setValue(init);
718 ✔
169
  setDomain(State::Domain{ossia::domain_base<std::string>{dom}});
718 ✔
170
}
718 ✔
171

172
Enum::Enum(
×
173
    const QStringList& values, std::vector<QString> pixmaps, std::string init,
174
    const QString& name, Id<Port> id, QObject* parent)
175
    : ControlInlet{name, id, parent}
×
176
    , values{values.begin(), values.end()}
×
177
    , pixmaps{std::move(pixmaps)}
×
178
{
×
179
  displayHandledExplicitly = true;
×
180
  setInit(init);
×
181
  setValue(init);
×
UNCOV
182
  ossia::domain_base<std::string> dom;
×
UNCOV
183
  for(auto& val : values)
×
UNCOV
184
    dom.values.push_back(val.toStdString());
×
UNCOV
185
  setDomain(State::Domain{dom});
×
UNCOV
186
}
×
187

188
Enum::~Enum() { }
2,105 ✔
189

190
Enum::Enum(DataStream::Deserializer& vis, QObject* parent)
322 ✔
191
    : ControlInlet{vis, parent}
161 ✔
192
{
161 ✔
193
  vis.writeTo(*this);
161 ✔
194
}
161 ✔
195
Enum::Enum(JSONObject::Deserializer& vis, QObject* parent)
352 ✔
196
    : ControlInlet{vis, parent}
176 ✔
197
{
176 ✔
198
  vis.writeTo(*this);
176 ✔
199
}
176 ✔
200
Enum::Enum(DataStream::Deserializer&& vis, QObject* parent)
×
201
    : ControlInlet{vis, parent}
×
202
{
×
203
  vis.writeTo(*this);
×
204
}
×
UNCOV
205
Enum::Enum(JSONObject::Deserializer&& vis, QObject* parent)
×
UNCOV
206
    : ControlInlet{vis, parent}
×
UNCOV
207
{
×
UNCOV
208
  vis.writeTo(*this);
×
UNCOV
209
}
×
210

211
void Enum::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
3 ✔
212
{
213
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
3 ✔
214
  port.type = ossia::val_type::STRING;
3 ✔
215
  port.domain = domain().get();
3 ✔
216
}
3 ✔
217

218
ComboBox::ComboBox(DataStream::Deserializer& vis, QObject* parent)
410 ✔
219
    : ControlInlet{vis, parent}
205 ✔
220
{
205 ✔
221
  vis.writeTo(*this);
205 ✔
UNCOV
222
}
×
223
ComboBox::ComboBox(
1,159 ✔
224
    std::vector<std::pair<QString, ossia::value>> values, ossia::value init,
225
    const QString& name, Id<Port> id, QObject* parent)
226
    : ControlInlet{name, id, parent}
1,159 ✔
227
    , alternatives{std::move(values)}
1,159 ✔
228
{
1,159 ✔
229
  displayHandledExplicitly = true;
1,159 ✔
230
  setInit(init);
1,159 ✔
231
  setValue(init);
1,159 ✔
232
  std::vector<ossia::value> vals;
1,159 ✔
233
  for(auto& v : alternatives)
10,279 ✔
234
    vals.push_back(v.second);
9,120 ✔
235
  setDomain(State::Domain{ossia::make_domain(vals)});
1,159 ✔
UNCOV
236
}
×
237

238
void ComboBox::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
119 ✔
239
{
240
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
119 ✔
241
  port.domain = domain().get();
119 ✔
242
}
119 ✔
243

244
void ComboBox::repopulateFromFolder(const QString& folderPath)
6 ✔
245
{
246
  std::vector<std::pair<QString, ossia::value>> alts;
6 ✔
247
  if(!folderPath.isEmpty())
6 ✔
248
  {
249
    QDir dir(folderPath);
5 ✔
250
    const auto files = fileExtensions.isEmpty()
10 ✔
251
                           ? dir.entryList(QDir::Files, QDir::Name)
4 ✔
252
                           : dir.entryList(fileExtensions, QDir::Files, QDir::Name);
1 ✔
253
    for(const auto& f : files)
13 ✔
254
      alts.emplace_back(f, f.toStdString()); // value = the file name itself
8 ✔
255
  }
5 ✔
256
  if(alts.empty())
6 ✔
257
    alts.emplace_back(QStringLiteral("-"), std::string("-"));
3 ✔
258
  setAlternatives(std::move(alts));
6 ✔
259

260
  // Watch the folder so files created while the document is open (e.g. by an
261
  // upstream process writing its analysis) appear in the list right away.
262
  if(folderPath != m_watchedFolder)
6 ✔
263
  {
264
    if(m_folderWatcher)
6 ✔
265
    {
266
      delete m_folderWatcher;
1 ✔
267
      m_folderWatcher = nullptr;
1 ✔
268
    }
1 ✔
269
    m_watchedFolder = folderPath;
6 ✔
270
    if(!folderPath.isEmpty() && QDir{folderPath}.exists())
11 ✔
271
    {
272
      m_folderWatcher = new QFileSystemWatcher{{folderPath}, this};
4 ✔
273
      connect(
4 ✔
274
          m_folderWatcher, &QFileSystemWatcher::directoryChanged, this,
4 ✔
275
          [this](const QString& path) { repopulateFromFolder(path); });
4 ✔
276
    }
4 ✔
277
  }
6 ✔
278
}
6 ✔
279

280
void ComboBox::setAlternatives(std::vector<std::pair<QString, ossia::value>> values)
11 ✔
281
{
282
  if(values == alternatives)
11 ✔
283
    return;
5 ✔
284
  alternatives = std::move(values);
6 ✔
285

286
  std::vector<ossia::value> vals;
6 ✔
287
  for(auto& v : alternatives)
22 ✔
288
    vals.push_back(v.second);
16 ✔
289
  // Not setDomain(): what changed is the item list, and alternativesChanged
290
  // below says exactly that. Announcing a domain change instead makes the
291
  // effect item rebuild every control of the process, which kills whatever
292
  // edit is in flight -- and for a combo box refilled from the running score,
293
  // that includes the control the user is dragging to refill it.
294
  setDomainWithoutNotifying(State::Domain{ossia::make_domain(vals)});
6 ✔
295

296
  // Keep the current value if it is still in the list; otherwise fall back to
297
  // the init value when available. A value absent from the list is left
298
  // untouched: for folder-backed comboboxes it may name a file that simply
299
  // does not exist *yet* — it becomes selectable (and shows up as selected)
300
  // once the file appears.
301
  if(!alternatives.empty())
6 ✔
302
  {
303
    auto in_list = [this](const ossia::value& v) {
16 ✔
304
      return ossia::find_if(
20 ✔
305
                 alternatives, [&](const auto& pair) { return pair.second == v; })
31 ✔
306
             != alternatives.end();
10 ✔
307
    };
308
    if(!in_list(value()) && in_list(init()))
6 ✔
309
      setValue(init());
1 ✔
310
  }
6 ✔
311

312
  alternativesChanged();
6 ✔
313
}
11 ✔
314

315
ComboBox::~ComboBox() { }
3,300 ✔
316

317
ComboBox::ComboBox(JSONObject::Deserializer& vis, QObject* parent)
592 ✔
318
    : ControlInlet{vis, parent}
296 ✔
319
{
296 ✔
320
  vis.writeTo(*this);
296 ✔
321
}
×
322
ComboBox::ComboBox(DataStream::Deserializer&& vis, QObject* parent)
×
323
    : ControlInlet{vis, parent}
×
324
{
×
325
  vis.writeTo(*this);
×
326
}
×
UNCOV
327
ComboBox::ComboBox(JSONObject::Deserializer&& vis, QObject* parent)
×
UNCOV
328
    : ControlInlet{vis, parent}
×
UNCOV
329
{
×
UNCOV
330
  vis.writeTo(*this);
×
UNCOV
331
}
×
332

333
HSVSlider::HSVSlider(
36 ✔
334
    ossia::vec4f init, const QString& name, Id<Port> id, QObject* parent)
335
    : ControlInlet{name, id, parent}
36 ✔
336
{
36 ✔
337
  displayHandledExplicitly = true;
36 ✔
338
  setInit(init);
36 ✔
339
  setValue(init);
36 ✔
340
}
36 ✔
341

342
HSVSlider::~HSVSlider() { }
96 ✔
343

344
const State::Unit& HSVSlider::unit() const noexcept
41 ✔
345
{
346
  static const State::Unit u{ossia::unit_t{ossia::rgba_u{}}};
41 ✔
347
  return u;
41 ✔
348
}
349

350
void HSVSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
21 ✔
351
{
352
  // The unit, not just the value type: it is what makes an address declared
353
  // color.rgb (or hsv, or any other colour unit) arrive here as the rgba this
354
  // control reads. Without it value_port::effective_type() is empty and
355
  // adapt_value() has nothing to convert towards.
356
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
21 ✔
357
  port.type = unit().get();
21 ✔
358
}
21 ✔
359

360
FloatSlider::FloatSlider(
2,511 ✔
361
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
362
    : ControlInlet{name, id, parent}
2,511 ✔
363
{
2,511 ✔
364
  displayHandledExplicitly = true;
2,511 ✔
365
  setInit(init);
2,511 ✔
366
  setValue(init);
2,511 ✔
367
  setDomain(ossia::make_domain(min, max));
2,511 ✔
368
}
2,511 ✔
369

370
FloatSlider::~FloatSlider() { }
12,004 ✔
371

372
void FloatSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
179 ✔
373
{
374
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
179 ✔
375
  port.type = ossia::val_type::FLOAT;
179 ✔
376
  port.domain = domain().get();
179 ✔
377
}
179 ✔
378

379
FloatKnob::FloatKnob(
2,408 ✔
380
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
381
    : ControlInlet{name, id, parent}
2,408 ✔
382
{
2,408 ✔
383
  displayHandledExplicitly = true;
2,408 ✔
384
  setInit(init);
2,408 ✔
385
  setValue(init);
2,408 ✔
386
  setDomain(ossia::make_domain(min, max));
2,408 ✔
387
}
2,408 ✔
388

389
FloatKnob::~FloatKnob() { }
7,498 ✔
390

391
void FloatKnob::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
392
{
UNCOV
393
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
394
  port.type = ossia::val_type::FLOAT;
×
UNCOV
395
  port.domain = domain().get();
×
UNCOV
396
}
×
397

398
LogFloatSlider::LogFloatSlider(
339 ✔
399
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
400
    : ControlInlet{name, id, parent}
339 ✔
401
{
339 ✔
402
  displayHandledExplicitly = true;
339 ✔
403
  setInit(init);
339 ✔
404
  setValue(init);
339 ✔
405
  setDomain(ossia::make_domain(min, max));
339 ✔
406
}
339 ✔
407

408
LogFloatSlider::~LogFloatSlider() { }
870 ✔
409

410
void LogFloatSlider::setupExecution(
4 ✔
411
    ossia::inlet& inl, QObject* exec_context) const noexcept
412
{
413
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
4 ✔
414
  port.type = ossia::val_type::FLOAT;
4 ✔
415
  port.domain = domain().get();
4 ✔
416
}
4 ✔
417

418
IntSlider::IntSlider(
429 ✔
419
    int min, int max, int init, const QString& name, Id<Port> id, QObject* parent)
420
    : ControlInlet{name, id, parent}
429 ✔
421
{
429 ✔
422
  displayHandledExplicitly = true;
429 ✔
423
  setInit(init);
429 ✔
424
  setValue(init);
429 ✔
425
  setDomain(ossia::make_domain(min, max));
429 ✔
426
}
429 ✔
427

428
IntSlider::~IntSlider() { }
1,276 ✔
429

430
void IntSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
71 ✔
431
{
432
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
71 ✔
433
  port.type = ossia::val_type::INT;
71 ✔
434
  port.domain = domain().get();
71 ✔
435
}
71 ✔
436

437
IntRangeSlider::IntRangeSlider(
×
438
    int min, int max, ossia::vec2f init, const QString& name, Id<Port> id,
439
    QObject* parent)
440
    : ControlInlet{name, id, parent}
×
441
{
×
UNCOV
442
  displayHandledExplicitly = true;
×
443
  setInit(init);
×
UNCOV
444
  setValue(init);
×
445
  setDomain(ossia::make_domain(min, max));
×
UNCOV
446
}
×
447

448
IntRangeSlider::~IntRangeSlider() { }
×
449

450
void IntRangeSlider::setupExecution(
×
451
    ossia::inlet& inl, QObject* exec_context) const noexcept
452
{
UNCOV
453
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
454
  port.type = ossia::val_type::VEC2F;
×
UNCOV
455
  port.domain = domain().get();
×
UNCOV
456
}
×
457

458
FloatRangeSlider::FloatRangeSlider(
18 ✔
459
    float min, float max, ossia::vec2f init, const QString& name, Id<Port> id,
460
    QObject* parent)
461
    : ControlInlet{name, id, parent}
18 ✔
462
{
18 ✔
463
  displayHandledExplicitly = true;
18 ✔
464
  setInit(init);
18 ✔
465
  setValue(init);
18 ✔
466
  setDomain(ossia::make_domain(min, max));
18 ✔
467
}
18 ✔
468

469
FloatRangeSlider::~FloatRangeSlider() { }
60 ✔
470

471
void FloatRangeSlider::setupExecution(
×
472
    ossia::inlet& inl, QObject* exec_context) const noexcept
473
{
474
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
475
  port.type = ossia::val_type::VEC2F;
×
UNCOV
476
  port.domain = domain().get();
×
477
}
×
478

479
IntRangeSpinBox::IntRangeSpinBox(
×
480
    int min, int max, ossia::vec2f init, const QString& name, Id<Port> id,
481
    QObject* parent)
482
    : ControlInlet{name, id, parent}
×
483
{
×
484
  displayHandledExplicitly = true;
×
UNCOV
485
  setInit(init);
×
486
  setValue(init);
×
UNCOV
487
  setDomain(ossia::make_domain(min, max));
×
UNCOV
488
}
×
489
IntRangeSpinBox::~IntRangeSpinBox() { }
×
490

491
void IntRangeSpinBox::setupExecution(
×
492
    ossia::inlet& inl, QObject* exec_context) const noexcept
493
{
494
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
495
  port.type = ossia::val_type::VEC2F;
×
UNCOV
496
  port.domain = domain().get();
×
497
}
×
498

499
FloatRangeSpinBox::FloatRangeSpinBox(
×
500
    float min, float max, ossia::vec2f init, const QString& name, Id<Port> id,
501
    QObject* parent)
502
    : ControlInlet{name, id, parent}
×
503
{
×
UNCOV
504
  displayHandledExplicitly = true;
×
505
  setInit(init);
×
UNCOV
506
  setValue(init);
×
507
  setDomain(ossia::make_domain(min, max));
×
UNCOV
508
}
×
509

510
FloatRangeSpinBox::~FloatRangeSpinBox() { }
×
511

512
void FloatRangeSpinBox::setupExecution(
×
513
    ossia::inlet& inl, QObject* exec_context) const noexcept
514
{
UNCOV
515
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
516
  port.type = ossia::val_type::VEC2F;
×
UNCOV
517
  port.domain = domain().get();
×
UNCOV
518
}
×
519

520
IntSpinBox::IntSpinBox(
1,503 ✔
521
    int min, int max, int init, const QString& name, Id<Port> id, QObject* parent)
522
    : ControlInlet{name, id, parent}
1,503 ✔
523
{
1,503 ✔
524
  displayHandledExplicitly = true;
1,503 ✔
525
  setInit(init);
1,503 ✔
526
  setValue(init);
1,503 ✔
527
  setDomain(ossia::make_domain(min, max));
1,503 ✔
528
}
1,503 ✔
529

530
void IntSpinBox::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
33 ✔
531
{
532
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
33 ✔
533
  port.type = ossia::val_type::INT;
33 ✔
534
  port.domain = domain().get();
33 ✔
535
}
33 ✔
536

537
IntSpinBox::~IntSpinBox() { }
4,059 ✔
538

539
FloatSpinBox::FloatSpinBox(
277 ✔
540
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
541
    : ControlInlet{name, id, parent}
277 ✔
542
{
277 ✔
543
  displayHandledExplicitly = true;
277 ✔
544
  setInit(init);
277 ✔
545
  setValue(init);
277 ✔
546
  setDomain(ossia::make_domain(min, max));
277 ✔
547
}
277 ✔
548

549
void FloatSpinBox::setupExecution(
12 ✔
550
    ossia::inlet& inl, QObject* exec_context) const noexcept
551
{
552
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
12 ✔
553
  port.type = ossia::val_type::FLOAT;
12 ✔
554
  port.domain = domain().get();
12 ✔
555
}
12 ✔
556

557
FloatSpinBox::~FloatSpinBox() { }
874 ✔
558

559
TimeChooser::TimeChooser(
1,025 ✔
560
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
561
    : ControlInlet{name, id, parent}
1,025 ✔
562
{
1,025 ✔
563
  displayHandledExplicitly = true;
1,025 ✔
564
  // The second component is the mode: 0 is a time in seconds, anything else is
565
  // a musical denomination. It starts at 0, which is what the object declaring
566
  // the control says too -- halp::time_chooser_t has `bool sync{false}`.
567
  //
568
  // It used to start synced, and that made every such control's default wrong:
569
  // the value the process declared as its init was read as a number of quarter
570
  // notes and converted to seconds against the tempo, so a control asking for
571
  // two seconds got two quarters instead. Deuterium's sampler carries a
572
  // work-around for exactly this.
573
  setValue(ossia::vec2f{init, 0.f});
1,025 ✔
574
  setInit(value());
1,025 ✔
575
  setDomain(ossia::make_domain(ossia::vec2f{min, 0.f}, ossia::vec2f{max, 1.f}));
1,025 ✔
576
}
1,025 ✔
577

578
TimeChooser::~TimeChooser() { }
3,123 ✔
579

580
bool TimeChooser::preferSynced(double tempo)
127 ✔
581
{
582
  const auto v = ossia::convert<ossia::vec2f>(value());
127 ✔
583
  if(v[1] != 0.f || !(v[0] > 0.f) || !(tempo > 0.))
127 ✔
584
    return false;
17 ✔
585
  // Seconds -> a fraction of a whole note, then the closest straight note
586
  // from 1/64 to 4 wholes
587
  const double whole = v[0] * tempo / 240.;
110 ✔
588
  double best = 1.;
110 ✔
589
  double best_ratio = 1e9;
110 ✔
590
  for(double note = 1. / 64.; note <= 4.; note *= 2.)
1,100 ✔
591
  {
592
    const double r = std::max(note / whole, whole / note);
990 ✔
593
    if(r < best_ratio)
990 ✔
594
    {
595
      best_ratio = r;
388 ✔
596
      best = note;
388 ✔
597
    }
388 ✔
598
  }
990 ✔
599
  if(best_ratio > 1.5)
110 ✔
600
    return false;
20 ✔
601
  const ossia::vec2f synced{float(best), 1.f};
90 ✔
602
  setValue(synced);
90 ✔
603
  setInit(synced);
90 ✔
604
  return true;
90 ✔
605
}
127 ✔
606

607
void TimeChooser::setValue(const ossia::value& value)
1,264 ✔
608
{
609
  switch(value.get_type())
1,264 ✔
610
  {
611
    case ossia::val_type::FLOAT:
612
    case ossia::val_type::INT:
613
    case ossia::val_type::BOOL:
614
      ControlInlet::setValue(ossia::vec2f{ossia::convert<float>(value), 0.f});
4 ✔
615
      break;
4 ✔
616
    default:
617
      ControlInlet::setValue(value);
1,260 ✔
618
      break;
1,260 ✔
619
  }
620
}
1,264 ✔
621

622
void TimeChooser::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
40 ✔
623
{
624
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
40 ✔
625
  port.type = ossia::val_type::VEC2F;
40 ✔
626
  // port.type = ossia::second_u{};
627
  // port.domain = domain().get();
628
}
40 ✔
629

630
Toggle::Toggle(bool init, const QString& name, Id<Port> id, QObject* parent)
1,213 ✔
631
    : ControlInlet{name, id, parent}
1,213 ✔
632
{
1,213 ✔
633
  displayHandledExplicitly = true;
1,213 ✔
634
  setInit(init);
1,213 ✔
635
  setValue(init);
1,213 ✔
636
  setDomain(State::Domain{ossia::domain_base<bool>{}});
1,213 ✔
637
}
1,213 ✔
638

639
void Toggle::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
32 ✔
640
{
641
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
32 ✔
642
  port.type = ossia::val_type::BOOL;
32 ✔
643
  port.domain = domain().get();
32 ✔
644
}
32 ✔
645

646
Toggle::~Toggle() { }
3,474 ✔
647

648
ChooserToggle::ChooserToggle(
×
649
    QStringList alternatives, bool init, const QString& name, Id<Port> id,
650
    QObject* parent)
651
    : ControlInlet{name, id, parent}
×
652
{
×
653
  displayHandledExplicitly = true;
×
654
  setValue(init ? alternatives[1].toStdString() : alternatives[0].toStdString());
×
UNCOV
655
  setInit(value());
×
656
  setDomain(
×
UNCOV
657
      State::Domain{ossia::domain_base<std::string>{
×
UNCOV
658
          {alternatives[0].toStdString(), alternatives[1].toStdString()}}});
×
659
}
×
660

661
void ChooserToggle::setupExecution(
×
662
    ossia::inlet& inl, QObject* exec_context) const noexcept
663
{
664
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
665
  port.type = ossia::val_type::STRING;
×
666
  port.domain = domain().get();
×
UNCOV
667
}
×
668

669
ChooserToggle::~ChooserToggle() { }
×
670

671
QStringList ChooserToggle::alternatives() const noexcept
×
672
{
UNCOV
673
  const auto& dom = *this->domain().get().v.target<ossia::domain_base<std::string>>();
×
UNCOV
674
  auto it = dom.values.begin();
×
UNCOV
675
  auto& s1 = *it;
×
UNCOV
676
  auto& s2 = *(++it);
×
UNCOV
677
  return {QString::fromStdString(s1), QString::fromStdString(s2)};
×
678
}
679

680
LineEdit::LineEdit(QString init, const QString& name, Id<Port> id, QObject* parent)
487 ✔
681
    : ControlInlet{name, id, parent}
487 ✔
682
{
487 ✔
683
  displayHandledExplicitly = true;
487 ✔
684
  setValue(init.toStdString());
487 ✔
685
  setInit(value());
487 ✔
686
}
487 ✔
687

688
void LineEdit::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
92 ✔
689
{
690
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
92 ✔
691
  port.type = ossia::val_type::STRING;
92 ✔
692
  port.domain = domain().get();
92 ✔
693
}
92 ✔
694

695
LineEdit::~LineEdit() { }
1,311 ✔
696

697
ProgramEdit::ProgramEdit(QString init, const QString& name, Id<Port> id, QObject* parent)
25 ✔
698
    : ControlInlet{name, id, parent}
25 ✔
699
{
25 ✔
700
  displayHandledExplicitly = true;
25 ✔
701
  setValue(init.toStdString());
25 ✔
702
  setInit(value());
25 ✔
703
}
25 ✔
704

705
void ProgramEdit::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
706
{
UNCOV
707
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
708
  port.type = ossia::val_type::STRING;
×
UNCOV
709
  port.domain = domain().get();
×
UNCOV
710
}
×
711

712
ProgramEdit::~ProgramEdit() { }
68 ✔
713

714
FileChooserBase::FileChooserBase(
116 ✔
715
    QString init, QString filters, const QString& name, Id<Port> id, QObject* parent)
716
    : ControlInlet{name, id, parent}
116 ✔
717
{
116 ✔
718
  displayHandledExplicitly = true;
116 ✔
719
  setValue(init.toStdString());
116 ✔
720
  setInit(value());
116 ✔
721
  m_filters = filters;
116 ✔
722
}
116 ✔
723

724
void FileChooserBase::setupExecution(
4 ✔
725
    ossia::inlet& inl, QObject* exec_context) const noexcept
726
{
727
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
4 ✔
728
  port.type = ossia::val_type::STRING;
4 ✔
729
  port.domain = domain().get();
4 ✔
730
}
4 ✔
731

732
void FileChooserBase::enableFileWatch()
2 ✔
733
{
734
  auto fun = std::make_shared<std::function<void()>>([ptr = QPointer{this}]() mutable {
2 ✔
735
    ossia::qt::run_async(qApp, [ptr] {
×
736
      if(ptr)
×
737
      {
738
        // This will trigger a reload
739
        // FIXME make it work with execution value changes
UNCOV
740
        ptr->valueChanged(ptr->value());
×
UNCOV
741
      }
×
UNCOV
742
    });
×
UNCOV
743
  });
×
744

745
  auto& f = score::FileWatch::instance();
2 ✔
746
  f.add(QString::fromStdString(ossia::convert<std::string>(this->value())), fun);
2 ✔
747

748
  connect(
2 ✔
749
      this, &Process::FileChooser::valueChanged, this,
750
      [cur_s = ossia::convert<std::string>(this->value()),
2 ✔
751
       fun](const ossia::value& v) mutable {
2 ✔
752
    auto new_s = ossia::convert<std::string>(v);
×
753
    if(new_s != cur_s)
×
754
    {
755
      auto& f = score::FileWatch::instance();
×
UNCOV
756
      f.remove(QString::fromStdString(cur_s), fun);
×
UNCOV
757
      f.add(QString::fromStdString(new_s), fun);
×
UNCOV
758
      cur_s = new_s;
×
UNCOV
759
    }
×
UNCOV
760
      });
×
761

762
  connect(this, &Process::FileChooser::destroying, this, [this, fun] {
4 ✔
763
    auto& f = score::FileWatch::instance();
2 ✔
764
    f.remove(QString::fromStdString(ossia::convert<std::string>(this->value())), fun);
2 ✔
765
  });
2 ✔
766
}
2 ✔
767

768
FileChooserBase::~FileChooserBase()
258 ✔
769
{
258 ✔
770
  destroying();
258 ✔
771
}
258 ✔
772

773
FileChooser::FileChooser(
114 ✔
774
    QString init, QString filters, const QString& name, Id<Port> id, QObject* parent)
775
    : FileChooserBase{init, filters, name, id, parent}
114 ✔
776
{
114 ✔
777
}
114 ✔
778

779
FileChooser::~FileChooser() { }
503 ✔
780

781
FileChooser::FileChooser(DataStream::Deserializer& vis, QObject* parent)
65 ✔
782
    : FileChooserBase{vis, parent}
65 ✔
783
{
65 ✔
784
  vis.writeTo(*this);
65 ✔
785
}
65 ✔
786
FileChooser::FileChooser(JSONObject::Deserializer& vis, QObject* parent)
73 ✔
787
    : FileChooserBase{vis, parent}
73 ✔
788
{
73 ✔
789
  vis.writeTo(*this);
73 ✔
790
}
73 ✔
791
FileChooser::FileChooser(DataStream::Deserializer&& vis, QObject* parent)
×
792
    : FileChooserBase{vis, parent}
×
793
{
×
794
  vis.writeTo(*this);
×
795
}
×
UNCOV
796
FileChooser::FileChooser(JSONObject::Deserializer&& vis, QObject* parent)
×
UNCOV
797
    : FileChooserBase{vis, parent}
×
UNCOV
798
{
×
UNCOV
799
  vis.writeTo(*this);
×
UNCOV
800
}
×
801

802
FolderChooser::FolderChooser(
3 ✔
803
    QString init, const QString& name, Id<Port> id, QObject* parent)
804
    : Process::ControlInlet{name, id, parent}
3 ✔
805
{
3 ✔
806
  displayHandledExplicitly = true;
3 ✔
807
  setValue(init.toStdString());
3 ✔
808
  setInit(value());
3 ✔
809
}
3 ✔
810

811
void FolderChooser::setupExecution(
×
812
    ossia::inlet& inl, QObject* exec_context) const noexcept
813
{
UNCOV
814
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
815
  port.type = ossia::val_type::STRING;
×
UNCOV
816
  port.domain = domain().get();
×
UNCOV
817
}
×
818

819
FolderChooser::~FolderChooser() { }
10 ✔
820

821
AudioFileChooser::AudioFileChooser(
2 ✔
822
    QString init, QString filters, const QString& name, Id<Port> id, QObject* parent)
823
    : FileChooserBase{init, filters, name, id, parent}
2 ✔
824
{
2 ✔
825
}
2 ✔
826

827
AudioFileChooser::~AudioFileChooser() { }
11 ✔
828

829
AudioFileChooser::AudioFileChooser(DataStream::Deserializer& vis, QObject* parent)
2 ✔
830
    : FileChooserBase{vis, parent}
2 ✔
831
{
2 ✔
832
  vis.writeTo(*this);
2 ✔
833
}
2 ✔
834
AudioFileChooser::AudioFileChooser(JSONObject::Deserializer& vis, QObject* parent)
2 ✔
835
    : FileChooserBase{vis, parent}
2 ✔
836
{
2 ✔
837
  vis.writeTo(*this);
2 ✔
838
}
2 ✔
839
AudioFileChooser::AudioFileChooser(DataStream::Deserializer&& vis, QObject* parent)
×
840
    : FileChooserBase{vis, parent}
×
841
{
×
842
  vis.writeTo(*this);
×
843
}
×
UNCOV
844
AudioFileChooser::AudioFileChooser(JSONObject::Deserializer&& vis, QObject* parent)
×
845
    : FileChooserBase{vis, parent}
×
UNCOV
846
{
×
847
  vis.writeTo(*this);
×
848
}
×
849

850
static QString toFilters(const QSet<QString>& exts)
×
851
{
852
  QString res;
×
UNCOV
853
  for(const auto& s : exts)
×
854
  {
855
    res += "*.";
×
856
    res += s;
×
857
    res += " ";
×
858
  }
859
  if(!res.isEmpty())
×
UNCOV
860
    res.resize(res.size() - 1);
×
UNCOV
861
  return res;
×
862
}
×
863

864
static QString videoFilesTypes()
×
865
{
866
  // FIXME refactor supported formats with Video process
867
  QSet<QString> files = {"mkv", "mov", "mp4", "h264", "avi", "hap",  "mpg", "mpeg",
×
UNCOV
868
                          "imf", "mxf", "mts", "m2ts", "mj2", "webm", "y4m", "nut", "ts"};
×
869
  return QString{"Videos (%1)"}.arg(toFilters(files));
×
870
}
×
871

UNCOV
872
VideoFileChooser::VideoFileChooser(
×
873
    QString init, QString filters, const QString& name, Id<Port> id, QObject* parent)
UNCOV
874
    : FileChooserBase{init, videoFilesTypes(), name, id, parent}
×
875
{
×
876
}
×
877

878
VideoFileChooser::~VideoFileChooser() { }
×
879

880
VideoFileChooser::VideoFileChooser(DataStream::Deserializer& vis, QObject* parent)
×
881
    : FileChooserBase{vis, parent}
×
882
{
×
883
  vis.writeTo(*this);
×
884
}
×
885
VideoFileChooser::VideoFileChooser(JSONObject::Deserializer& vis, QObject* parent)
×
886
    : FileChooserBase{vis, parent}
×
887
{
×
888
  vis.writeTo(*this);
×
889
}
×
890
VideoFileChooser::VideoFileChooser(DataStream::Deserializer&& vis, QObject* parent)
×
891
    : FileChooserBase{vis, parent}
×
892
{
×
893
  vis.writeTo(*this);
×
894
}
×
UNCOV
895
VideoFileChooser::VideoFileChooser(JSONObject::Deserializer&& vis, QObject* parent)
×
UNCOV
896
    : FileChooserBase{vis, parent}
×
UNCOV
897
{
×
UNCOV
898
  vis.writeTo(*this);
×
UNCOV
899
}
×
900

901
Button::Button(const QString& name, Id<Port> id, QObject* parent)
57 ✔
902
    : ControlInlet{name, id, parent}
57 ✔
903
{
57 ✔
904
  displayHandledExplicitly = true;
57 ✔
905
  setValue(false);
57 ✔
906
  setInit(false);
57 ✔
907
  setDomain(State::Domain{ossia::domain_base<bool>{}});
57 ✔
908
}
57 ✔
909

910
void Button::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
911
{
UNCOV
912
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
913
  port.type = ossia::val_type::BOOL;
×
UNCOV
914
  port.domain = domain().get();
×
UNCOV
915
}
×
916

917
Button::~Button() { }
164 ✔
918

919
ImpulseButton::ImpulseButton(const QString& name, Id<Port> id, QObject* parent)
350 ✔
920
    : ControlInlet{name, id, parent}
350 ✔
921
{
350 ✔
922
  displayHandledExplicitly = true;
350 ✔
923
  setValue(ossia::impulse{});
350 ✔
924
  setInit(ossia::impulse{});
350 ✔
925
  setDomain(State::Domain{ossia::domain_base<ossia::impulse>{}});
350 ✔
926
}
350 ✔
927

928
void ImpulseButton::setupExecution(
×
929
    ossia::inlet& inl, QObject* exec_context) const noexcept
930
{
931
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
932
  port.type = ossia::val_type::IMPULSE;
×
UNCOV
933
  port.domain = domain().get();
×
934
  // A bang happens, it is not a state: an address mapped here delivers what it
935
  // received, instead of having its current value copied in on every tick.
936
  port.is_event = true;
×
937
}
×
938

939
ImpulseButton::~ImpulseButton() { }
1,014 ✔
940

941
XYSlider::XYSlider(ossia::vec2f init, const QString& name, Id<Port> id, QObject* parent)
×
942
    : ControlInlet{name, id, parent}
×
943
{
×
UNCOV
944
  displayHandledExplicitly = true;
×
UNCOV
945
  setValue(init);
×
UNCOV
946
  setInit(init);
×
UNCOV
947
  setDomain(ossia::make_domain(ossia::vec2f{0., 0.}, ossia::vec2f{1., 1.}));
×
UNCOV
948
}
×
949

950
XYSlider::XYSlider(
15 ✔
951
    ossia::vec2f min, ossia::vec2f max, ossia::vec2f init, const QString& name,
952
    Id<Port> id, QObject* parent)
953
    : ControlInlet{name, id, parent}
15 ✔
954
{
15 ✔
955
  displayHandledExplicitly = true;
15 ✔
956
  setValue(init);
15 ✔
957
  setInit(init);
15 ✔
958
  setDomain(ossia::make_domain(min, max));
15 ✔
959
}
15 ✔
960

961
void XYSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
962
{
UNCOV
963
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
964
  port.type = ossia::val_type::VEC2F;
×
965
  port.domain = domain().get();
×
UNCOV
966
}
×
967

968
XYSlider::~XYSlider() { }
58 ✔
969

970
XYZSlider::XYZSlider(
×
971
    ossia::vec3f init, const QString& name, Id<Port> id, QObject* parent)
972
    : ControlInlet{name, id, parent}
×
973
{
×
UNCOV
974
  displayHandledExplicitly = true;
×
975
  setValue(init);
×
UNCOV
976
  setInit(init);
×
UNCOV
977
  setDomain(ossia::make_domain(ossia::vec3f{0., 0., 0.}, ossia::vec3f{1., 1., 1.}));
×
978
}
×
979

980
XYZSlider::XYZSlider(
×
981
    ossia::vec3f min, ossia::vec3f max, ossia::vec3f init, const QString& name,
982
    Id<Port> id, QObject* parent)
983
    : ControlInlet{name, id, parent}
×
984
{
×
UNCOV
985
  displayHandledExplicitly = true;
×
UNCOV
986
  setValue(init);
×
UNCOV
987
  setInit(init);
×
988
  setDomain(ossia::make_domain(min, max));
×
UNCOV
989
}
×
990

991
XYZSlider::~XYZSlider() { }
2 ✔
992

993
void XYZSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
994
{
995
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
996
  port.type = ossia::val_type::VEC3F;
×
997
  port.domain = domain().get();
×
998
}
×
999

1000
XYZSpinboxes::XYZSpinboxes(
×
1001
    ossia::vec3f init, const QString& name, Id<Port> id, QObject* parent)
1002
    : ControlInlet{name, id, parent}
×
1003
{
×
UNCOV
1004
  displayHandledExplicitly = true;
×
1005
  setValue(init);
×
UNCOV
1006
  setInit(init);
×
1007
  setDomain(ossia::make_domain(ossia::vec3f{0., 0., 0.}, ossia::vec3f{1., 1., 1.}));
×
1008
}
×
1009

1010
XYSpinboxes::XYSpinboxes(
×
1011
    ossia::vec2f init, const QString& name, Id<Port> id, QObject* parent)
1012
    : ControlInlet{name, id, parent}
×
1013
    , integral{false}
×
UNCOV
1014
{
×
UNCOV
1015
  displayHandledExplicitly = true;
×
UNCOV
1016
  setValue(init);
×
UNCOV
1017
  setInit(init);
×
UNCOV
1018
}
×
1019
XYSpinboxes::XYSpinboxes(
161 ✔
1020
    ossia::vec2f min, ossia::vec2f max, ossia::vec2f init, bool integral,
1021
    const QString& name, Id<Port> id, QObject* parent)
1022
    : ControlInlet{name, id, parent}
161 ✔
1023
    , integral{integral}
161 ✔
1024
{
161 ✔
1025
  displayHandledExplicitly = true;
161 ✔
1026
  setValue(init);
161 ✔
1027
  setInit(init);
161 ✔
1028
  setDomain(ossia::make_domain(min, max));
161 ✔
1029
}
161 ✔
1030

1031
XYSpinboxes::XYSpinboxes(DataStream::Deserializer& vis, QObject* parent)
48 ✔
1032
    : ControlInlet{vis, parent}
48 ✔
1033
{
48 ✔
1034
  vis.writeTo(*this);
48 ✔
1035
}
×
1036
XYSpinboxes::XYSpinboxes(JSONObject::Deserializer& vis, QObject* parent)
49 ✔
1037
    : ControlInlet{vis, parent}
49 ✔
1038
{
49 ✔
1039
  vis.writeTo(*this);
49 ✔
1040
}
×
1041
XYSpinboxes::XYSpinboxes(DataStream::Deserializer&& vis, QObject* parent)
×
1042
    : ControlInlet{vis, parent}
×
1043
{
×
1044
  vis.writeTo(*this);
×
1045
}
×
UNCOV
1046
XYSpinboxes::XYSpinboxes(JSONObject::Deserializer&& vis, QObject* parent)
×
UNCOV
1047
    : ControlInlet{vis, parent}
×
UNCOV
1048
{
×
UNCOV
1049
  vis.writeTo(*this);
×
UNCOV
1050
}
×
1051

1052
XYSpinboxes::~XYSpinboxes() { }
516 ✔
1053

1054
void XYSpinboxes::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
3 ✔
1055
{
1056
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
3 ✔
1057
  port.type = ossia::val_type::VEC2F;
3 ✔
1058
  port.domain = domain().get();
3 ✔
1059
}
3 ✔
1060

1061
XYZSpinboxes::XYZSpinboxes(
951 ✔
1062
    ossia::vec3f min, ossia::vec3f max, ossia::vec3f init, bool integral,
1063
    const QString& name, Id<Port> id, QObject* parent)
1064
    : ControlInlet{name, id, parent}
951 ✔
1065
    , integral{integral}
951 ✔
1066
{
951 ✔
1067
  displayHandledExplicitly = true;
951 ✔
1068
  setValue(init);
951 ✔
1069
  setInit(init);
951 ✔
1070
  setDomain(ossia::make_domain(min, max));
951 ✔
1071
}
951 ✔
1072

1073
XYZSpinboxes::~XYZSpinboxes() { }
2,258 ✔
1074

1075
void XYZSpinboxes::setupExecution(
16 ✔
1076
    ossia::inlet& inl, QObject* exec_context) const noexcept
1077
{
1078
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
16 ✔
1079
  port.type = ossia::val_type::VEC3F;
16 ✔
1080
  port.domain = domain().get();
16 ✔
1081
}
16 ✔
1082

1083
MultiSlider::MultiSlider(
118 ✔
1084
    ossia::value init, const QString& name, Id<Port> id, QObject* parent)
1085
    : ControlInlet{name, id, parent}
118 ✔
1086
{
118 ✔
1087
  displayHandledExplicitly = true;
118 ✔
1088
  setValue(std::move(init));
118 ✔
1089
  setInit(value());
118 ✔
1090
  setDomain(ossia::make_domain(0., 1.));
118 ✔
1091
}
118 ✔
1092

1093
MultiSlider::~MultiSlider() { }
161 ✔
1094

1095
ossia::value MultiSlider::getMin() const noexcept
×
1096
{
1097
  return domain().get().get_min();
×
1098
}
1099

1100
ossia::value MultiSlider::getMax() const noexcept
×
1101
{
1102
  return domain().get().get_max();
×
1103
}
1104

1105
void MultiSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
1106
{
UNCOV
1107
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
1108
  port.type = ossia::val_type::LIST;
×
UNCOV
1109
  port.domain = domain().get();
×
UNCOV
1110
}
×
1111

1112
MultiSliderXY::MultiSliderXY(
3 ✔
1113
    ossia::value init, const QString& name, Id<Port> id, QObject* parent)
1114
    : ControlInlet{name, id, parent}
3 ✔
1115
{
3 ✔
1116
  displayHandledExplicitly = true;
3 ✔
1117
  setValue(std::move(init));
3 ✔
1118
  setInit(value());
3 ✔
1119
  setDomain(ossia::make_domain(0., 1.));
3 ✔
1120
}
3 ✔
1121

1122
MultiSliderXY::~MultiSliderXY() { }
10 ✔
1123

1124
ossia::value MultiSliderXY::getMin() const noexcept
×
1125
{
1126
  return domain().get().get_min();
×
1127
}
1128

1129
ossia::value MultiSliderXY::getMax() const noexcept
×
1130
{
1131
  return domain().get().get_max();
×
1132
}
1133

1134
void MultiSliderXY::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
1135
{
UNCOV
1136
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
1137
  port.type = ossia::val_type::LIST;
×
UNCOV
1138
  port.domain = domain().get();
×
UNCOV
1139
}
×
1140

1141
PathGeneratorXY::PathGeneratorXY(
3 ✔
1142
    ossia::value init, const QString& name, Id<Port> id, QObject* parent)
1143
    : ControlInlet{name, id, parent}
3 ✔
1144
{
3 ✔
1145
  displayHandledExplicitly = true;
3 ✔
1146
  setValue(std::move(init));
3 ✔
1147
  setInit(value());
3 ✔
1148
  setDomain(ossia::make_domain(0., 1.));
3 ✔
1149
}
3 ✔
1150

1151
PathGeneratorXY::~PathGeneratorXY() { }
10 ✔
1152

1153
ossia::value PathGeneratorXY::getMin() const noexcept
×
1154
{
1155
  return domain().get().get_min();
×
1156
}
1157

1158
ossia::value PathGeneratorXY::getMax() const noexcept
×
1159
{
1160
  return domain().get().get_max();
×
1161
}
1162

1163
void PathGeneratorXY::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
1164
{
UNCOV
1165
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
UNCOV
1166
  port.type = ossia::val_type::LIST;
×
UNCOV
1167
  port.domain = domain().get();
×
UNCOV
1168
}
×
1169

1170
Bargraph::Bargraph(
2 ✔
1171
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
1172
    : ControlOutlet{name, id, parent}
2 ✔
1173
{
2 ✔
1174
  displayHandledExplicitly = true;
2 ✔
1175
  setValue(init);
2 ✔
1176
  setDomain(ossia::make_domain(min, max));
2 ✔
1177
}
2 ✔
1178

1179
Bargraph::~Bargraph() { }
12 ✔
1180

1181
}
1182
template <>
1183
SCORE_LIB_PROCESS_EXPORT void
1184
DataStreamReader::read(const Process::FloatSlider& p)
967 ✔
1185
{
1186
  read((const Process::ControlInlet&)p);
967 ✔
1187
}
967 ✔
1188
template <>
1189
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1190
DataStreamWriter::write(Process::FloatSlider& p)
×
1191
{
UNCOV
1192
}
×
1193
template <>
1194
SCORE_LIB_PROCESS_EXPORT void
1195
JSONReader::read(const Process::FloatSlider& p)
1,022 ✔
1196
{
1197
  read((const Process::ControlInlet&)p);
1,022 ✔
1198
}
1,022 ✔
1199
template <>
1200
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1201
JSONWriter::write(Process::FloatSlider& p)
×
1202
{
UNCOV
1203
}
×
1204

1205
template <>
1206
SCORE_LIB_PROCESS_EXPORT void
1207
DataStreamReader::read(const Process::FloatKnob& p)
1,127 ✔
1208
{
1209
  read((const Process::ControlInlet&)p);
1,127 ✔
1210
}
1,127 ✔
1211
template <>
1212
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1213
DataStreamWriter::write(Process::FloatKnob& p)
×
1214
{
UNCOV
1215
}
×
1216
template <>
1217
SCORE_LIB_PROCESS_EXPORT void
1218
JSONReader::read(const Process::FloatKnob& p)
1,100 ✔
1219
{
1220
  read((const Process::ControlInlet&)p);
1,100 ✔
1221
}
1,100 ✔
1222
template <>
1223
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1224
JSONWriter::write(Process::FloatKnob& p)
×
1225
{
UNCOV
1226
}
×
1227

1228
template <>
1229
SCORE_LIB_PROCESS_EXPORT void
1230
DataStreamReader::read(const Process::LogFloatSlider& p)
95 ✔
1231
{
1232
  read((const Process::ControlInlet&)p);
95 ✔
1233
}
95 ✔
1234
template <>
1235
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1236
DataStreamWriter::write(Process::LogFloatSlider& p)
×
1237
{
UNCOV
1238
}
×
1239
template <>
1240
SCORE_LIB_PROCESS_EXPORT void
1241
JSONReader::read(const Process::LogFloatSlider& p)
85 ✔
1242
{
1243
  read((const Process::ControlInlet&)p);
85 ✔
1244
}
85 ✔
1245
template <>
1246
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1247
JSONWriter::write(Process::LogFloatSlider& p)
×
1248
{
UNCOV
1249
}
×
1250

1251
template <>
1252
SCORE_LIB_PROCESS_EXPORT void
1253
DataStreamReader::read(const Process::IntSlider& p)
190 ✔
1254
{
1255
  read((const Process::ControlInlet&)p);
190 ✔
1256
}
190 ✔
1257
template <>
1258
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1259
DataStreamWriter::write(Process::IntSlider& p)
×
1260
{
UNCOV
1261
}
×
1262
template <>
1263
SCORE_LIB_PROCESS_EXPORT void
1264
JSONReader::read(const Process::IntSlider& p)
217 ✔
1265
{
1266
  read((const Process::ControlInlet&)p);
217 ✔
1267
}
217 ✔
1268
template <>
1269
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1270
JSONWriter::write(Process::IntSlider& p)
×
1271
{
UNCOV
1272
}
×
1273

1274
template <>
1275
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1276
DataStreamReader::read(const Process::IntRangeSlider& p)
×
1277
{
UNCOV
1278
  read((const Process::ControlInlet&)p);
×
1279
}
×
1280
template <>
1281
SCORE_LIB_PROCESS_EXPORT void
1282
DataStreamWriter::write(Process::IntRangeSlider& p)
×
1283
{
1284
}
×
1285
template <>
1286
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1287
JSONReader::read(const Process::IntRangeSlider& p)
×
1288
{
UNCOV
1289
  read((const Process::ControlInlet&)p);
×
1290
}
×
1291
template <>
1292
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1293
JSONWriter::write(Process::IntRangeSlider& p)
×
1294
{
UNCOV
1295
}
×
1296
template <>
1297
SCORE_LIB_PROCESS_EXPORT void
1298
DataStreamReader::read(const Process::FloatRangeSlider& p)
12 ✔
1299
{
1300
  read((const Process::ControlInlet&)p);
12 ✔
1301
}
12 ✔
1302
template <>
1303
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1304
DataStreamWriter::write(Process::FloatRangeSlider& p)
×
1305
{
UNCOV
1306
}
×
1307
template <>
1308
SCORE_LIB_PROCESS_EXPORT void
1309
JSONReader::read(const Process::FloatRangeSlider& p)
12 ✔
1310
{
1311
  read((const Process::ControlInlet&)p);
12 ✔
1312
}
12 ✔
1313
template <>
1314
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1315
JSONWriter::write(Process::FloatRangeSlider& p)
×
1316
{
UNCOV
1317
}
×
1318

1319
template <>
1320
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1321
DataStreamReader::read(const Process::IntRangeSpinBox& p)
×
1322
{
UNCOV
1323
  read((const Process::ControlInlet&)p);
×
1324
}
×
1325
template <>
1326
SCORE_LIB_PROCESS_EXPORT void
1327
DataStreamWriter::write(Process::IntRangeSpinBox& p)
×
1328
{
1329
}
×
1330
template <>
1331
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1332
JSONReader::read(const Process::IntRangeSpinBox& p)
×
1333
{
UNCOV
1334
  read((const Process::ControlInlet&)p);
×
1335
}
×
1336
template <>
1337
SCORE_LIB_PROCESS_EXPORT void
1338
JSONWriter::write(Process::IntRangeSpinBox& p)
×
1339
{
1340
}
×
1341
template <>
1342
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1343
DataStreamReader::read(const Process::FloatRangeSpinBox& p)
×
1344
{
UNCOV
1345
  read((const Process::ControlInlet&)p);
×
1346
}
×
1347
template <>
1348
SCORE_LIB_PROCESS_EXPORT void
1349
DataStreamWriter::write(Process::FloatRangeSpinBox& p)
×
1350
{
1351
}
×
1352
template <>
1353
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1354
JSONReader::read(const Process::FloatRangeSpinBox& p)
×
1355
{
UNCOV
1356
  read((const Process::ControlInlet&)p);
×
1357
}
×
1358
template <>
1359
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1360
JSONWriter::write(Process::FloatRangeSpinBox& p)
×
1361
{
UNCOV
1362
}
×
1363

1364
template <>
1365
SCORE_LIB_PROCESS_EXPORT void
1366
DataStreamReader::read(const Process::IntSpinBox& p)
598 ✔
1367
{
1368
  read((const Process::ControlInlet&)p);
598 ✔
1369
}
598 ✔
1370
template <>
1371
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1372
DataStreamWriter::write(Process::IntSpinBox& p)
×
1373
{
UNCOV
1374
}
×
1375
template <>
1376
SCORE_LIB_PROCESS_EXPORT void
1377
JSONReader::read(const Process::IntSpinBox& p)
582 ✔
1378
{
1379
  read((const Process::ControlInlet&)p);
582 ✔
1380
}
582 ✔
1381
template <>
1382
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1383
JSONWriter::write(Process::IntSpinBox& p)
×
1384
{
UNCOV
1385
}
×
1386

1387
template <>
1388
SCORE_LIB_PROCESS_EXPORT void
1389
DataStreamReader::read(const Process::FloatSpinBox& p)
162 ✔
1390
{
1391
  read((const Process::ControlInlet&)p);
162 ✔
1392
}
162 ✔
1393
template <>
1394
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1395
DataStreamWriter::write(Process::FloatSpinBox& p)
×
1396
{
UNCOV
1397
}
×
1398
template <>
1399
SCORE_LIB_PROCESS_EXPORT void
1400
JSONReader::read(const Process::FloatSpinBox& p)
160 ✔
1401
{
1402
  read((const Process::ControlInlet&)p);
160 ✔
1403
}
160 ✔
1404
template <>
1405
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1406
JSONWriter::write(Process::FloatSpinBox& p)
×
1407
{
UNCOV
1408
}
×
1409

1410
template <>
1411
SCORE_LIB_PROCESS_EXPORT void
1412
DataStreamReader::read(const Process::TimeChooser& p)
475 ✔
1413
{
1414
  read((const Process::ControlInlet&)p);
475 ✔
1415
}
475 ✔
1416
template <>
1417
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1418
DataStreamWriter::write(Process::TimeChooser& p)
×
1419
{
UNCOV
1420
}
×
1421
template <>
1422
SCORE_LIB_PROCESS_EXPORT void
1423
JSONReader::read(const Process::TimeChooser& p)
557 ✔
1424
{
1425
  read((const Process::ControlInlet&)p);
557 ✔
1426
}
557 ✔
1427
template <>
1428
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1429
JSONWriter::write(Process::TimeChooser& p)
×
1430
{
UNCOV
1431
}
×
1432

1433
template <>
1434
SCORE_LIB_PROCESS_EXPORT void
1435
DataStreamReader::read(const Process::Toggle& p)
501 ✔
1436
{
1437
  read((const Process::ControlInlet&)p);
501 ✔
1438
}
501 ✔
1439
template <>
1440
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1441
DataStreamWriter::write(Process::Toggle& p)
×
1442
{
UNCOV
1443
}
×
1444
template <>
1445
SCORE_LIB_PROCESS_EXPORT void JSONReader::read(const Process::Toggle& p)
512 ✔
1446
{
1447
  read((const Process::ControlInlet&)p);
512 ✔
1448
}
512 ✔
1449
template <>
UNCOV
1450
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::Toggle& p)
×
1451
{
UNCOV
1452
}
×
1453

1454
template <>
1455
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1456
DataStreamReader::read(const Process::ChooserToggle& p)
×
1457
{
UNCOV
1458
  read((const Process::ControlInlet&)p);
×
1459
}
×
1460
template <>
1461
SCORE_LIB_PROCESS_EXPORT void
1462
DataStreamWriter::write(Process::ChooserToggle& p)
×
1463
{
1464
}
×
1465
template <>
1466
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1467
JSONReader::read(const Process::ChooserToggle& p)
×
1468
{
UNCOV
1469
  read((const Process::ControlInlet&)p);
×
1470
}
×
1471
template <>
1472
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1473
JSONWriter::write(Process::ChooserToggle& p)
×
1474
{
UNCOV
1475
}
×
1476

1477
template <>
1478
SCORE_LIB_PROCESS_EXPORT void
1479
DataStreamReader::read(const Process::LineEdit& p)
174 ✔
1480
{
1481
  read((const Process::ControlInlet&)p);
174 ✔
1482
}
174 ✔
1483
template <>
1484
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1485
DataStreamWriter::write(Process::LineEdit& p)
×
1486
{
UNCOV
1487
}
×
1488
template <>
1489
SCORE_LIB_PROCESS_EXPORT void
1490
JSONReader::read(const Process::LineEdit& p)
170 ✔
1491
{
1492
  read((const Process::ControlInlet&)p);
170 ✔
1493
}
170 ✔
1494
template <>
UNCOV
1495
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::LineEdit& p)
×
1496
{
UNCOV
1497
}
×
1498

1499
template <>
1500
SCORE_LIB_PROCESS_EXPORT void
1501
DataStreamReader::read(const Process::ProgramEdit& p)
9 ✔
1502
{
1503
  read((const Process::ControlInlet&)p);
9 ✔
1504
}
9 ✔
1505
template <>
1506
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1507
DataStreamWriter::write(Process::ProgramEdit& p)
×
1508
{
UNCOV
1509
}
×
1510
template <>
1511
SCORE_LIB_PROCESS_EXPORT void
1512
JSONReader::read(const Process::ProgramEdit& p)
10 ✔
1513
{
1514
  read((const Process::ControlInlet&)p);
10 ✔
1515
}
10 ✔
1516
template <>
1517
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1518
JSONWriter::write(Process::ProgramEdit& p)
×
1519
{
UNCOV
1520
}
×
1521

1522

1523
namespace
1524
{
1525
// Paths under the document's folder or the user library are saved as
1526
// <PROJECT>: / <LIBRARY>: paths, so that they survive the document moving.
1527
ossia::value storedPathValue(const Process::ControlInlet& p)
280 ✔
1528
{
1529
  const auto* str = p.value().target<std::string>();
280 ✔
1530
  if(!str || str->empty())
280 ✔
1531
    return p.value();
268 ✔
1532

1533
  const auto path = QString::fromStdString(*str);
12 ✔
1534
  const auto stored = [&] {
24 ✔
1535
    if(auto* doc = score::IDocument::try_documentFromObject(p))
12 ✔
1536
      return score::relativizeFilePath(path, doc->context());
6 ✔
1537
    return score::relativizeFilePath(path);
6 ✔
1538
  }();
12 ✔
1539
  return stored.toStdString();
12 ✔
1540
}
280 ✔
1541

1542
void readPathControl(DataStreamReader& s, const Process::ControlInlet& p)
136 ✔
1543
{
1544
  s.readFrom(storedPathValue(p));
136 ✔
1545
  s.readFrom(p.init());
136 ✔
1546
  s.readFrom(p.domain());
136 ✔
1547
}
136 ✔
1548

1549
void readPathControl(JSONReader& s, const Process::ControlInlet& p)
144 ✔
1550
{
1551
  s.obj[s.strings.Value] = storedPathValue(p);
144 ✔
1552
  s.obj[s.strings.Init] = p.init();
144 ✔
1553
  s.obj[s.strings.Domain] = p.domain();
144 ✔
1554
}
144 ✔
1555
}
1556

1557
template <>
1558
SCORE_LIB_PROCESS_EXPORT void
1559
DataStreamReader::read(const Process::FileChooser& p)
131 ✔
1560
{
1561
  readPathControl(*this, p);
131 ✔
1562
  m_stream << p.filters();
131 ✔
1563
}
131 ✔
1564
template <>
1565
SCORE_LIB_PROCESS_EXPORT void
1566
DataStreamWriter::write(Process::FileChooser& p)
65 ✔
1567
{
1568
  QString f;
65 ✔
1569
  m_stream >> f;
65 ✔
1570
  p.setFilters(f);
65 ✔
1571
}
65 ✔
1572
template <>
1573
SCORE_LIB_PROCESS_EXPORT void
1574
JSONReader::read(const Process::FileChooser& p)
139 ✔
1575
{
1576
  readPathControl(*this, p);
139 ✔
1577
  obj["Filters"] = p.filters();
139 ✔
1578
}
139 ✔
1579
template <>
1580
SCORE_LIB_PROCESS_EXPORT void
1581
JSONWriter::write(Process::FileChooser& p)
73 ✔
1582
{
1583
  // tryGet: these three writers are reachable through the deserializing
1584
  // constructors, and documents older than the "Filters" key exist.
1585
  if(auto it = obj.tryGet("Filters"))
73 ✔
1586
  {
1587
    QString f;
73 ✔
1588
    f <<= *it;
73 ✔
1589
    p.setFilters(f);
73 ✔
1590
  }
73 ✔
1591
}
73 ✔
1592

1593
template <>
1594
SCORE_LIB_PROCESS_EXPORT void
1595
DataStreamReader::read(const Process::FolderChooser& p)
2 ✔
1596
{
1597
  readPathControl(*this, p);
2 ✔
1598
}
2 ✔
1599
template <>
1600
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1601
DataStreamWriter::write(Process::FolderChooser& p)
×
1602
{
UNCOV
1603
}
×
1604
template <>
1605
SCORE_LIB_PROCESS_EXPORT void
1606
JSONReader::read(const Process::FolderChooser& p)
2 ✔
1607
{
1608
  readPathControl(*this, p);
2 ✔
1609
}
2 ✔
1610
template <>
1611
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1612
JSONWriter::write(Process::FolderChooser& p)
×
1613
{
1614
}
×
1615

1616
template <>
1617
SCORE_LIB_PROCESS_EXPORT void
1618
DataStreamReader::read(const Process::AudioFileChooser& p)
3 ✔
1619
{
1620
  readPathControl(*this, p);
3 ✔
1621
  m_stream << p.filters();
3 ✔
1622
}
3 ✔
1623
template <>
1624
SCORE_LIB_PROCESS_EXPORT void
1625
DataStreamWriter::write(Process::AudioFileChooser& p)
2 ✔
1626
{
1627
  QString f;
2 ✔
1628
  m_stream >> f;
2 ✔
1629
  p.setFilters(f);
2 ✔
1630
}
2 ✔
1631
template <>
1632
SCORE_LIB_PROCESS_EXPORT void
1633
JSONReader::read(const Process::AudioFileChooser& p)
3 ✔
1634
{
1635
  readPathControl(*this, p);
3 ✔
1636
  obj["Filters"] = p.filters();
3 ✔
1637
}
3 ✔
1638
template <>
1639
SCORE_LIB_PROCESS_EXPORT void
1640
JSONWriter::write(Process::AudioFileChooser& p)
2 ✔
1641
{
1642
  if(auto it = obj.tryGet("Filters"))
2 ✔
1643
  {
1644
    QString f;
2 ✔
1645
    f <<= *it;
2 ✔
1646
    p.setFilters(f);
2 ✔
1647
  }
2 ✔
1648
}
2 ✔
1649

1650
template <>
UNCOV
1651
SCORE_LIB_PROCESS_EXPORT void DataStreamReader::read(const Process::VideoFileChooser& p)
×
1652
{
UNCOV
1653
  readPathControl(*this, p);
×
UNCOV
1654
  m_stream << p.filters();
×
UNCOV
1655
}
×
1656
template <>
UNCOV
1657
SCORE_LIB_PROCESS_EXPORT void DataStreamWriter::write(Process::VideoFileChooser& p)
×
1658
{
UNCOV
1659
  QString f;
×
UNCOV
1660
  m_stream >> f;
×
UNCOV
1661
  p.setFilters(f);
×
UNCOV
1662
}
×
1663
template <>
UNCOV
1664
SCORE_LIB_PROCESS_EXPORT void JSONReader::read(const Process::VideoFileChooser& p)
×
1665
{
UNCOV
1666
  readPathControl(*this, p);
×
UNCOV
1667
  obj["Filters"] = p.filters();
×
UNCOV
1668
}
×
1669
template <>
UNCOV
1670
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::VideoFileChooser& p)
×
1671
{
UNCOV
1672
  if(auto it = obj.tryGet("Filters"))
×
1673
  {
UNCOV
1674
    QString f;
×
UNCOV
1675
    f <<= *it;
×
UNCOV
1676
    p.setFilters(f);
×
UNCOV
1677
  }
×
UNCOV
1678
}
×
1679

1680
template <>
1681
SCORE_LIB_PROCESS_EXPORT void
1682
DataStreamReader::read(const Process::Enum& p)
335 ✔
1683
{
1684
  read((const Process::ControlInlet&)p);
335 ✔
1685
  m_stream << p.values << p.pixmaps;
335 ✔
1686
}
335 ✔
1687
template <>
1688
SCORE_LIB_PROCESS_EXPORT void DataStreamWriter::write(Process::Enum& p)
161 ✔
1689
{
1690
  m_stream >> p.values >> p.pixmaps;
161 ✔
1691
}
161 ✔
1692
template <>
1693
SCORE_LIB_PROCESS_EXPORT void JSONReader::read(const Process::Enum& p)
319 ✔
1694
{
1695
  read((const Process::ControlInlet&)p);
319 ✔
1696
  obj["Values"] = p.values;
319 ✔
1697
  obj["Pixmaps"] = p.pixmaps;
319 ✔
1698
}
319 ✔
1699
template <>
1700
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::Enum& p)
176 ✔
1701
{
1702
  p.values <<= obj["Values"];
176 ✔
1703
  p.pixmaps <<= obj["Pixmaps"];
176 ✔
1704
}
176 ✔
1705

1706
template <>
1707
SCORE_LIB_PROCESS_EXPORT void
1708
DataStreamReader::read(const Process::ComboBox& p)
421 ✔
1709
{
1710
  read((const Process::ControlInlet&)p);
421 ✔
1711
  m_stream << p.alternatives << p.folderPortName << p.fileExtensions;
421 ✔
1712
}
421 ✔
1713
template <>
1714
SCORE_LIB_PROCESS_EXPORT void
1715
DataStreamWriter::write(Process::ComboBox& p)
205 ✔
1716
{
1717
  m_stream >> p.alternatives >> p.folderPortName >> p.fileExtensions;
205 ✔
1718
}
205 ✔
1719
template <>
1720
SCORE_LIB_PROCESS_EXPORT void
1721
JSONReader::read(const Process::ComboBox& p)
490 ✔
1722
{
1723
  read((const Process::ControlInlet&)p);
490 ✔
1724
  obj["Values"] = p.alternatives;
490 ✔
1725
  // Folder-backed combobox metadata (empty for a plain combobox). Persisted so
1726
  // a loaded document can re-scan the folder and re-establish live refresh;
1727
  // see ProcessModel::init_folder_comboboxes. Extensions are stored as one
1728
  // space-joined string ("*.json *.wav"), like FileChooser's filters.
1729
  obj["FolderPort"] = p.folderPortName;
490 ✔
1730
  obj["FileExtensions"] = p.fileExtensions.join(QChar(' '));
490 ✔
1731
}
490 ✔
1732
template <>
1733
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::ComboBox& p)
296 ✔
1734
{
1735
  p.alternatives <<= obj["Values"];
296 ✔
1736
  // Guarded for documents saved before these fields existed.
1737
  if(obj.tryGet("FolderPort"))
296 ✔
1738
    p.folderPortName <<= obj["FolderPort"];
295 ✔
1739
  if(obj.tryGet("FileExtensions"))
296 ✔
1740
  {
1741
    QString exts;
295 ✔
1742
    exts <<= obj["FileExtensions"];
295 ✔
1743
    p.fileExtensions
590 ✔
1744
        = exts.isEmpty() ? QStringList{} : exts.split(QChar(' '), Qt::SkipEmptyParts);
295 ✔
1745
  }
295 ✔
1746
}
296 ✔
1747
template <>
1748
SCORE_LIB_PROCESS_EXPORT void
1749
DataStreamReader::read(const Process::Button& p)
26 ✔
1750
{
1751
  read((const Process::ControlInlet&)p);
26 ✔
1752
}
26 ✔
1753
template <>
1754
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1755
DataStreamWriter::write(Process::Button& p)
×
1756
{
UNCOV
1757
}
×
1758
template <>
1759
SCORE_LIB_PROCESS_EXPORT void JSONReader::read(const Process::Button& p)
26 ✔
1760
{
1761
  read((const Process::ControlInlet&)p);
26 ✔
1762
}
26 ✔
1763
template <>
UNCOV
1764
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::Button& p)
×
1765
{
UNCOV
1766
}
×
1767
template <>
1768
SCORE_LIB_PROCESS_EXPORT void
1769
DataStreamReader::read(const Process::ImpulseButton& p)
150 ✔
1770
{
1771
  read((const Process::ControlInlet&)p);
150 ✔
1772
}
150 ✔
1773
template <>
1774
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1775
DataStreamWriter::write(Process::ImpulseButton& p)
×
1776
{
UNCOV
1777
}
×
1778
template <>
1779
SCORE_LIB_PROCESS_EXPORT void
1780
JSONReader::read(const Process::ImpulseButton& p)
129 ✔
1781
{
1782
  read((const Process::ControlInlet&)p);
129 ✔
1783
}
129 ✔
1784
template <>
1785
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1786
JSONWriter::write(Process::ImpulseButton& p)
×
1787
{
UNCOV
1788
}
×
1789

1790
template <>
1791
SCORE_LIB_PROCESS_EXPORT void
1792
DataStreamReader::read(const Process::HSVSlider& p)
14 ✔
1793
{
1794
  read((const Process::ControlInlet&)p);
14 ✔
1795
}
14 ✔
1796
template <>
1797
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1798
DataStreamWriter::write(Process::HSVSlider& p)
×
1799
{
1800
}
×
1801
template <>
1802
SCORE_LIB_PROCESS_EXPORT void
1803
JSONReader::read(const Process::HSVSlider& p)
10 ✔
1804
{
1805
  read((const Process::ControlInlet&)p);
10 ✔
1806
}
10 ✔
1807
template <>
1808
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1809
JSONWriter::write(Process::HSVSlider& p)
×
1810
{
1811
}
×
1812

1813
template <>
1814
SCORE_LIB_PROCESS_EXPORT void
1815
DataStreamReader::read(const Process::XYSlider& p)
12 ✔
1816
{
1817
  read((const Process::ControlInlet&)p);
12 ✔
1818
}
12 ✔
1819
template <>
1820
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1821
DataStreamWriter::write(Process::XYSlider& p)
×
1822
{
UNCOV
1823
}
×
1824
template <>
1825
SCORE_LIB_PROCESS_EXPORT void
1826
JSONReader::read(const Process::XYSlider& p)
10 ✔
1827
{
1828
  read((const Process::ControlInlet&)p);
10 ✔
1829
}
10 ✔
1830
template <>
UNCOV
1831
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::XYSlider& p)
×
1832
{
UNCOV
1833
}
×
1834

1835
template <>
1836
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1837
DataStreamReader::read(const Process::XYZSlider& p)
×
1838
{
UNCOV
1839
  read((const Process::ControlInlet&)p);
×
UNCOV
1840
}
×
1841
template <>
1842
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1843
DataStreamWriter::write(Process::XYZSlider& p)
×
1844
{
UNCOV
1845
}
×
1846
template <>
1847
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1848
JSONReader::read(const Process::XYZSlider& p)
×
1849
{
UNCOV
1850
  read((const Process::ControlInlet&)p);
×
UNCOV
1851
}
×
1852
template <>
1853
SCORE_LIB_PROCESS_EXPORT void
1854
JSONWriter::write(Process::XYZSlider& p)
×
1855
{
1856
}
×
1857

1858
template <>
1859
SCORE_LIB_PROCESS_EXPORT void
1860
DataStreamReader::read(const Process::XYSpinboxes& p)
97 ✔
1861
{
1862
  read((const Process::ControlInlet&)p);
97 ✔
1863
  m_stream << p.integral;
97 ✔
1864
}
97 ✔
1865
template <>
1866
SCORE_LIB_PROCESS_EXPORT void
1867
DataStreamWriter::write(Process::XYSpinboxes& p)
48 ✔
1868
{
1869
  m_stream >> p.integral;
48 ✔
1870
}
48 ✔
1871
template <>
1872
SCORE_LIB_PROCESS_EXPORT void
1873
JSONReader::read(const Process::XYSpinboxes& p)
97 ✔
1874
{
1875
  read((const Process::ControlInlet&)p);
97 ✔
1876
  obj["Integral"] = p.integral;
97 ✔
1877
}
97 ✔
1878
template <>
1879
SCORE_LIB_PROCESS_EXPORT void
1880
JSONWriter::write(Process::XYSpinboxes& p)
49 ✔
1881
{
1882
  if(auto val = obj.tryGet("Integral"))
49 ✔
1883
    p.integral = val->toBool();
49 ✔
1884
}
49 ✔
1885

1886
template <>
1887
SCORE_LIB_PROCESS_EXPORT void
1888
DataStreamReader::read(const Process::XYZSpinboxes& p)
190 ✔
1889
{
1890
  read((const Process::ControlInlet&)p);
190 ✔
1891
}
190 ✔
1892
template <>
1893
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1894
DataStreamWriter::write(Process::XYZSpinboxes& p)
×
1895
{
UNCOV
1896
}
×
1897
template <>
1898
SCORE_LIB_PROCESS_EXPORT void
1899
JSONReader::read(const Process::XYZSpinboxes& p)
168 ✔
1900
{
1901
  read((const Process::ControlInlet&)p);
168 ✔
1902
}
168 ✔
1903
template <>
1904
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1905
JSONWriter::write(Process::XYZSpinboxes& p)
×
1906
{
UNCOV
1907
}
×
1908

1909
template <>
1910
SCORE_LIB_PROCESS_EXPORT void
1911
DataStreamReader::read(const Process::MultiSlider& p)
35 ✔
1912
{
1913
  read((const Process::ControlInlet&)p);
35 ✔
1914
}
35 ✔
1915
template <>
1916
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1917
DataStreamWriter::write(Process::MultiSlider& p)
×
1918
{
UNCOV
1919
}
×
1920
template <>
1921
SCORE_LIB_PROCESS_EXPORT void
1922
JSONReader::read(const Process::MultiSlider& p)
27 ✔
1923
{
1924
  read((const Process::ControlInlet&)p);
27 ✔
1925
}
27 ✔
1926
template <>
1927
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1928
JSONWriter::write(Process::MultiSlider& p)
×
1929
{
UNCOV
1930
}
×
1931

1932
template <>
1933
SCORE_LIB_PROCESS_EXPORT void
1934
DataStreamReader::read(const Process::MultiSliderXY& p)
2 ✔
1935
{
1936
  read((const Process::ControlInlet&)p);
2 ✔
1937
}
2 ✔
1938
template <>
1939
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1940
DataStreamWriter::write(Process::MultiSliderXY& p)
×
1941
{
UNCOV
1942
}
×
1943
template <>
1944
SCORE_LIB_PROCESS_EXPORT void
1945
JSONReader::read(const Process::MultiSliderXY& p)
2 ✔
1946
{
1947
  read((const Process::ControlInlet&)p);
2 ✔
1948
}
2 ✔
1949
template <>
1950
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1951
JSONWriter::write(Process::MultiSliderXY& p)
×
1952
{
UNCOV
1953
}
×
1954

1955

1956
template <>
1957
SCORE_LIB_PROCESS_EXPORT void
1958
DataStreamReader::read(const Process::PathGeneratorXY& p)
2 ✔
1959
{
1960
  read((const Process::ControlInlet&)p);
2 ✔
1961
}
2 ✔
1962
template <>
1963
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1964
DataStreamWriter::write(Process::PathGeneratorXY& p)
×
1965
{
UNCOV
1966
}
×
1967
template <>
1968
SCORE_LIB_PROCESS_EXPORT void
1969
JSONReader::read(const Process::PathGeneratorXY& p)
2 ✔
1970
{
1971
  read((const Process::ControlInlet&)p);
2 ✔
1972
}
2 ✔
1973
template <>
1974
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1975
JSONWriter::write(Process::PathGeneratorXY& p)
×
1976
{
UNCOV
1977
}
×
1978

1979
template <>
1980
SCORE_LIB_PROCESS_EXPORT void
1981
DataStreamReader::read(const Process::Bargraph& p)
4 ✔
1982
{
1983
  read((const Process::ControlOutlet&)p);
4 ✔
1984
}
4 ✔
1985
template <>
1986
SCORE_LIB_PROCESS_EXPORT void
UNCOV
1987
DataStreamWriter::write(Process::Bargraph& p)
×
1988
{
UNCOV
1989
}
×
1990
template <>
1991
SCORE_LIB_PROCESS_EXPORT void
1992
JSONReader::read(const Process::Bargraph& p)
4 ✔
1993
{
1994
  read((const Process::ControlOutlet&)p);
4 ✔
1995
}
4 ✔
1996
template <>
UNCOV
1997
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::Bargraph& p)
×
1998
{
UNCOV
1999
}
×
2000

2001
template <>
2002
SCORE_LIB_PROCESS_EXPORT void DataStreamReader::read(const QString& p)
1,575 ✔
2003
{
2004
  m_stream << p;
1,575 ✔
2005
}
1,575 ✔
2006
template <>
2007
SCORE_LIB_PROCESS_EXPORT void DataStreamWriter::write(QString& p)
738 ✔
2008
{
2009
  m_stream >> p;
738 ✔
2010
}
738 ✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc