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

ossia / score / 40815790952

29 Oct 2026 04:05AM UTC coverage: 50.888% (+1.7%) from 49.183%
40815790952

Pull #2361

github

web-flow
Merge 996cd0c5d into b3ba4155e
Pull Request #2361: MIDI effects, audio and MIDI loopers, MIDI sync

176299 of 346447 relevant lines covered (50.89%)

166790.68 hits per line

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

65.04
/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/algorithms.hpp>
11
#include <ossia/detail/parse_strict.hpp>
12
#include <ossia/detail/ssize.hpp>
13
#include <ossia/network/value/value_conversion.hpp>
14

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

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

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

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

26
#include <wobjectimpl.h>
27

28
W_OBJECT_IMPL(Process::ComboBox)
257,894 ✔
29
W_OBJECT_IMPL(Process::FileChooserBase)
2 ✔
30
W_OBJECT_IMPL(Process::FileChooser)
7,170 ✔
31
W_OBJECT_IMPL(Process::FolderChooser)
27 ✔
32
W_OBJECT_IMPL(Process::AudioFileChooser)
3 ✔
33
W_OBJECT_IMPL(Process::VideoFileChooser)
×
34
W_OBJECT_IMPL(Process::ImpulseButton)
130,584 ✔
35
W_OBJECT_IMPL(Process::FloatSlider)
236,252 ✔
36
W_OBJECT_IMPL(Process::FloatKnob)
192,265 ✔
37
W_OBJECT_IMPL(Process::LogFloatSlider)
12,957 ✔
38
W_OBJECT_IMPL(Process::IntSlider)
89,485 ✔
39
W_OBJECT_IMPL(Process::IntRangeSlider)
×
40
W_OBJECT_IMPL(Process::FloatRangeSlider)
37,949 ✔
41
W_OBJECT_IMPL(Process::IntRangeSpinBox)
6,762 ✔
42
W_OBJECT_IMPL(Process::FloatRangeSpinBox)
×
43
W_OBJECT_IMPL(Process::IntSpinBox)
283,275 ✔
44
W_OBJECT_IMPL(Process::FloatSpinBox)
20,584 ✔
45
W_OBJECT_IMPL(Process::TimeChooser)
80,848 ✔
46
W_OBJECT_IMPL(Process::GridChooser)
8,968 ✔
47
W_OBJECT_IMPL(Process::Toggle)
163,878 ✔
48
W_OBJECT_IMPL(Process::ChooserToggle)
×
49
W_OBJECT_IMPL(Process::LineEdit)
73,000 ✔
50
W_OBJECT_IMPL(Process::ProgramEdit)
110 ✔
51
W_OBJECT_IMPL(Process::Enum)
120,913 ✔
52
W_OBJECT_IMPL(Process::Button)
4,175 ✔
53
W_OBJECT_IMPL(Process::HSVSlider)
6,301 ✔
54
W_OBJECT_IMPL(Process::XYSlider)
265 ✔
55
W_OBJECT_IMPL(Process::XYZSlider)
×
56
W_OBJECT_IMPL(Process::XYSpinboxes)
1,172 ✔
57
W_OBJECT_IMPL(Process::XYZSpinboxes)
10,103 ✔
58
W_OBJECT_IMPL(Process::MultiSlider)
66,580 ✔
59
W_OBJECT_IMPL(Process::MultiSliderXY)
9 ✔
60
W_OBJECT_IMPL(Process::PathGeneratorXY)
9 ✔
61
W_OBJECT_IMPL(Process::Bargraph)
×
62
namespace Process
63
{
64
namespace
65
{
66
struct entry_index_visitor
67
{
68
  int n;
69

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

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

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

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

120
  const int n = std::ssize(alternatives);
12,422 ✔
121
  for(int i = 0; i < n; i++)
33,828 ✔
122
    if(alternatives[i].second == v)
33,061 ✔
123
      return i;
11,655 ✔
124

125
  if(auto str = v.target<std::string>())
767 ✔
126
  {
127
    const auto label = QString::fromStdString(*str);
760 ✔
128
    for(int i = 0; i < n; i++)
2,029 ✔
129
      if(alternatives[i].first == label)
2,024 ✔
130
        return i;
755 ✔
131
  }
760 ✔
132

133
  if(!entriesAreNames(alternatives))
12 ✔
134
    return -1;
5 ✔
135

136
  return readEntryIndex(v, n).value_or(-1);
7 ✔
137
}
12,423 ✔
138

139
void ComboBox::setValue(const ossia::value& value)
6,108 ✔
140
{
141
  if(value.target<std::string>())
6,108 ✔
142
  {
143
    const bool is_a_value = ossia::any_of(
982 ✔
144
        alternatives, [&](const auto& alt) { return alt.second == value; });
6,738 ✔
145
    if(!is_a_value)
982 ✔
146
    {
147
      if(const int i = indexOfValue(value); i >= 0)
757 ✔
148
        return ControlInlet::setValue(alternatives[i].second);
754 ✔
149
    }
3 ✔
150
  }
228 ✔
151
  ControlInlet::setValue(value);
5,354 ✔
152
}
6,108 ✔
153

154
ossia::value ComboBox::valueAtIndex(int i) const noexcept
4 ✔
155
{
156
  if(i < 0 || i >= std::ssize(alternatives))
4 ✔
157
    return {};
2 ✔
158
  return alternatives[i].second;
2 ✔
159
}
4 ✔
160

161
int Enum::indexOfValue(const ossia::value& v) const noexcept
8,605 ✔
162
{
163
  if(!v.valid())
8,605 ✔
164
    return -1;
1 ✔
165

166
  const int n = std::ssize(values);
8,604 ✔
167
  const auto name = QString::fromStdString(ossia::convert<std::string>(v));
8,604 ✔
168
  for(int i = 0; i < n; i++)
32,899 ✔
169
    if(values[i] == name)
32,845 ✔
170
      return i;
8,550 ✔
171

172
  return readEntryIndex(v, n).value_or(-1);
54 ✔
173
}
8,605 ✔
174

175
ossia::value Enum::valueAtIndex(int i) const noexcept
4 ✔
176
{
177
  if(i < 0 || i >= std::ssize(values))
4 ✔
178
    return {};
1 ✔
179
  return values[i].toStdString();
3 ✔
180
}
4 ✔
181

182
Enum::Enum(
2,291 ✔
183
    const std::vector<std::string>& dom, std::vector<QString> pixmaps, std::string init,
184
    const QString& name, Id<Port> id, QObject* parent)
185
    : ControlInlet{name, id, parent}
2,291 ✔
186
    , pixmaps{std::move(pixmaps)}
2,291 ✔
187
{
2,291 ✔
188
  for(auto& val : dom)
19,255 ✔
189
    values.push_back(QString::fromStdString(val));
16,964 ✔
190

191
  displayHandledExplicitly = true;
2,291 ✔
192
  setInit(init);
2,291 ✔
193
  setValue(init);
2,291 ✔
194
  setDomain(State::Domain{ossia::domain_base<std::string>{dom}});
2,291 ✔
195
}
2,291 ✔
196

197
Enum::Enum(
×
198
    const QStringList& values, std::vector<QString> pixmaps, std::string init,
199
    const QString& name, Id<Port> id, QObject* parent)
200
    : ControlInlet{name, id, parent}
×
201
    , values{values.begin(), values.end()}
×
202
    , pixmaps{std::move(pixmaps)}
×
203
{
×
204
  displayHandledExplicitly = true;
×
205
  setInit(init);
×
206
  setValue(init);
×
207
  ossia::domain_base<std::string> dom;
×
208
  for(auto& val : values)
×
209
    dom.values.push_back(val.toStdString());
×
210
  setDomain(State::Domain{dom});
×
211
}
×
212

213
Enum::~Enum() { }
6,739 ✔
214

215
Enum::Enum(DataStream::Deserializer& vis, QObject* parent)
1,566 ✔
216
    : ControlInlet{vis, parent}
783 ✔
217
{
783 ✔
218
  vis.writeTo(*this);
783 ✔
219
}
783 ✔
220
Enum::Enum(JSONObject::Deserializer& vis, QObject* parent)
596 ✔
221
    : ControlInlet{vis, parent}
298 ✔
222
{
298 ✔
223
  vis.writeTo(*this);
298 ✔
224
}
298 ✔
225
Enum::Enum(DataStream::Deserializer&& vis, QObject* parent)
×
226
    : ControlInlet{vis, parent}
×
227
{
×
228
  vis.writeTo(*this);
×
229
}
×
230
Enum::Enum(JSONObject::Deserializer&& vis, QObject* parent)
×
231
    : ControlInlet{vis, parent}
×
232
{
×
233
  vis.writeTo(*this);
×
234
}
×
235

236
void Enum::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
3 ✔
237
{
238
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
3 ✔
239
  port.type = ossia::val_type::STRING;
3 ✔
240
  port.domain = domain().get();
3 ✔
241
}
3 ✔
242

243
ComboBox::ComboBox(DataStream::Deserializer& vis, QObject* parent)
2,262 ✔
244
    : ControlInlet{vis, parent}
1,131 ✔
245
{
1,131 ✔
246
  vis.writeTo(*this);
1,131 ✔
247
}
×
248
ComboBox::ComboBox(
3,893 ✔
249
    std::vector<std::pair<QString, ossia::value>> values, ossia::value init,
250
    const QString& name, Id<Port> id, QObject* parent)
251
    : ControlInlet{name, id, parent}
3,893 ✔
252
    , alternatives{std::move(values)}
3,893 ✔
253
{
3,893 ✔
254
  displayHandledExplicitly = true;
3,893 ✔
255
  setInit(init);
3,893 ✔
256
  setValue(init);
3,893 ✔
257
  std::vector<ossia::value> vals;
3,893 ✔
258
  for(auto& v : alternatives)
26,534 ✔
259
    vals.push_back(v.second);
22,641 ✔
260
  setDomain(State::Domain{ossia::make_domain(vals)});
3,893 ✔
261
}
×
262

263
void ComboBox::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
611 ✔
264
{
265
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
611 ✔
266
  port.domain = domain().get();
611 ✔
267
}
611 ✔
268

269
void ComboBox::repopulateFromFolder(const QString& folderPath)
6 ✔
270
{
271
  std::vector<std::pair<QString, ossia::value>> alts;
6 ✔
272
  if(!folderPath.isEmpty())
6 ✔
273
  {
274
    QDir dir(folderPath);
5 ✔
275
    const auto files = fileExtensions.isEmpty()
10 ✔
276
                           ? dir.entryList(QDir::Files, QDir::Name)
4 ✔
277
                           : dir.entryList(fileExtensions, QDir::Files, QDir::Name);
1 ✔
278
    for(const auto& f : files)
13 ✔
279
      alts.emplace_back(f, f.toStdString()); // value = the file name itself
8 ✔
280
  }
5 ✔
281
  if(alts.empty())
6 ✔
282
    alts.emplace_back(QStringLiteral("-"), std::string("-"));
3 ✔
283
  setAlternatives(std::move(alts));
6 ✔
284

285
  // Watch the folder so files created while the document is open (e.g. by an
286
  // upstream process writing its analysis) appear in the list right away.
287
  if(folderPath != m_watchedFolder)
6 ✔
288
  {
289
    if(m_folderWatcher)
6 ✔
290
    {
291
      delete m_folderWatcher;
1 ✔
292
      m_folderWatcher = nullptr;
1 ✔
293
    }
1 ✔
294
    m_watchedFolder = folderPath;
6 ✔
295
    if(!folderPath.isEmpty() && QDir{folderPath}.exists())
11 ✔
296
    {
297
      m_folderWatcher = new QFileSystemWatcher{{folderPath}, this};
4 ✔
298
      connect(
4 ✔
299
          m_folderWatcher, &QFileSystemWatcher::directoryChanged, this,
4 ✔
300
          [this](const QString& path) { repopulateFromFolder(path); });
4 ✔
301
    }
4 ✔
302
  }
6 ✔
303
}
6 ✔
304

305
void ComboBox::setAlternatives(std::vector<std::pair<QString, ossia::value>> values)
11 ✔
306
{
307
  if(values == alternatives)
11 ✔
308
    return;
5 ✔
309
  alternatives = std::move(values);
6 ✔
310

311
  std::vector<ossia::value> vals;
6 ✔
312
  for(auto& v : alternatives)
22 ✔
313
    vals.push_back(v.second);
16 ✔
314
  // Not setDomain(): what changed is the item list, and alternativesChanged
315
  // below says exactly that. Announcing a domain change instead makes the
316
  // effect item rebuild every control of the process, which kills whatever
317
  // edit is in flight -- and for a combo box refilled from the running score,
318
  // that includes the control the user is dragging to refill it.
319
  setDomainWithoutNotifying(State::Domain{ossia::make_domain(vals)});
6 ✔
320

321
  // Keep the current value if it is still in the list; otherwise fall back to
322
  // the init value when available. A value absent from the list is left
323
  // untouched: for folder-backed comboboxes it may name a file that simply
324
  // does not exist *yet* — it becomes selectable (and shows up as selected)
325
  // once the file appears.
326
  if(!alternatives.empty())
6 ✔
327
  {
328
    auto in_list = [this](const ossia::value& v) {
16 ✔
329
      return ossia::find_if(
20 ✔
330
                 alternatives, [&](const auto& pair) { return pair.second == v; })
31 ✔
331
             != alternatives.end();
10 ✔
332
    };
333
    if(!in_list(value()) && in_list(init()))
6 ✔
334
      setValue(init());
1 ✔
335
  }
6 ✔
336

337
  alternativesChanged();
6 ✔
338
}
11 ✔
339

340
ComboBox::~ComboBox() { }
11,089 ✔
341

342
ComboBox::ComboBox(JSONObject::Deserializer& vis, QObject* parent)
1,064 ✔
343
    : ControlInlet{vis, parent}
532 ✔
344
{
532 ✔
345
  vis.writeTo(*this);
532 ✔
346
}
×
347
ComboBox::ComboBox(DataStream::Deserializer&& vis, QObject* parent)
×
348
    : ControlInlet{vis, parent}
×
349
{
×
350
  vis.writeTo(*this);
×
351
}
×
352
ComboBox::ComboBox(JSONObject::Deserializer&& vis, QObject* parent)
×
353
    : ControlInlet{vis, parent}
×
354
{
×
355
  vis.writeTo(*this);
×
356
}
×
357

358
HSVSlider::HSVSlider(
71 ✔
359
    ossia::vec4f init, const QString& name, Id<Port> id, QObject* parent)
360
    : ControlInlet{name, id, parent}
71 ✔
361
{
71 ✔
362
  displayHandledExplicitly = true;
71 ✔
363
  setInit(init);
71 ✔
364
  setValue(init);
71 ✔
365
}
71 ✔
366

367
HSVSlider::~HSVSlider() { }
182 ✔
368

369
const State::Unit& HSVSlider::unit() const noexcept
41 ✔
370
{
371
  static const State::Unit u{ossia::unit_t{ossia::rgba_u{}}};
41 ✔
372
  return u;
41 ✔
373
}
374

375
void HSVSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
21 ✔
376
{
377
  // The unit, not just the value type: it is what makes an address declared
378
  // color.rgb (or hsv, or any other colour unit) arrive here as the rgba this
379
  // control reads. Without it value_port::effective_type() is empty and
380
  // adapt_value() has nothing to convert towards.
381
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
21 ✔
382
  port.type = unit().get();
21 ✔
383
}
21 ✔
384

385
FloatSlider::FloatSlider(
3,018 ✔
386
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
387
    : ControlInlet{name, id, parent}
3,018 ✔
388
{
3,018 ✔
389
  displayHandledExplicitly = true;
3,018 ✔
390
  setInit(init);
3,018 ✔
391
  setValue(init);
3,018 ✔
392
  setDomain(ossia::make_domain(min, max));
3,018 ✔
393
}
3,018 ✔
394

395
FloatSlider::~FloatSlider() { }
13,210 ✔
396

397
void FloatSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
1,616 ✔
398
{
399
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
1,616 ✔
400
  port.type = ossia::val_type::FLOAT;
1,616 ✔
401
  port.domain = domain().get();
1,616 ✔
402
}
1,616 ✔
403

404
FloatKnob::FloatKnob(
3,918 ✔
405
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
406
    : ControlInlet{name, id, parent}
3,918 ✔
407
{
3,918 ✔
408
  displayHandledExplicitly = true;
3,918 ✔
409
  setInit(init);
3,918 ✔
410
  setValue(init);
3,918 ✔
411
  setDomain(ossia::make_domain(min, max));
3,918 ✔
412
}
3,918 ✔
413

414
FloatKnob::~FloatKnob() { }
12,006 ✔
415

416
void FloatKnob::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
417
{
418
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
419
  port.type = ossia::val_type::FLOAT;
×
420
  port.domain = domain().get();
×
421
}
×
422

423
LogFloatSlider::LogFloatSlider(
339 ✔
424
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
425
    : ControlInlet{name, id, parent}
339 ✔
426
{
339 ✔
427
  displayHandledExplicitly = true;
339 ✔
428
  setInit(init);
339 ✔
429
  setValue(init);
339 ✔
430
  setDomain(ossia::make_domain(min, max));
339 ✔
431
}
339 ✔
432

433
LogFloatSlider::~LogFloatSlider() { }
870 ✔
434

435
void LogFloatSlider::setupExecution(
4 ✔
436
    ossia::inlet& inl, QObject* exec_context) const noexcept
437
{
438
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
4 ✔
439
  port.type = ossia::val_type::FLOAT;
4 ✔
440
  port.domain = domain().get();
4 ✔
441
}
4 ✔
442

443
IntSlider::IntSlider(
867 ✔
444
    int min, int max, int init, const QString& name, Id<Port> id, QObject* parent)
445
    : ControlInlet{name, id, parent}
867 ✔
446
{
867 ✔
447
  displayHandledExplicitly = true;
867 ✔
448
  setInit(init);
867 ✔
449
  setValue(init);
867 ✔
450
  setDomain(ossia::make_domain(min, max));
867 ✔
451
}
867 ✔
452

453
IntSlider::~IntSlider() { }
2,564 ✔
454

455
void IntSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
71 ✔
456
{
457
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
71 ✔
458
  port.type = ossia::val_type::INT;
71 ✔
459
  port.domain = domain().get();
71 ✔
460
}
71 ✔
461

462
IntRangeSlider::IntRangeSlider(
×
463
    int min, int max, ossia::vec2f init, const QString& name, Id<Port> id,
464
    QObject* parent)
465
    : ControlInlet{name, id, parent}
×
466
{
×
467
  displayHandledExplicitly = true;
×
468
  setInit(init);
×
469
  setValue(init);
×
470
  setDomain(ossia::make_domain(min, max));
×
471
}
×
472

473
IntRangeSlider::~IntRangeSlider() { }
×
474

475
void IntRangeSlider::setupExecution(
×
476
    ossia::inlet& inl, QObject* exec_context) const noexcept
477
{
478
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
479
  port.type = ossia::val_type::VEC2F;
×
480
  port.domain = domain().get();
×
481
}
×
482

483
FloatRangeSlider::FloatRangeSlider(
337 ✔
484
    float min, float max, ossia::vec2f init, const QString& name, Id<Port> id,
485
    QObject* parent)
486
    : ControlInlet{name, id, parent}
337 ✔
487
{
337 ✔
488
  displayHandledExplicitly = true;
337 ✔
489
  setInit(init);
337 ✔
490
  setValue(init);
337 ✔
491
  setDomain(ossia::make_domain(min, max));
337 ✔
492
}
337 ✔
493

494
FloatRangeSlider::~FloatRangeSlider() { }
1,024 ✔
495

496
void FloatRangeSlider::setupExecution(
×
497
    ossia::inlet& inl, QObject* exec_context) const noexcept
498
{
499
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
500
  port.type = ossia::val_type::VEC2F;
×
501
  port.domain = domain().get();
×
502
}
×
503

504
IntRangeSpinBox::IntRangeSpinBox(
62 ✔
505
    int min, int max, ossia::vec2f init, const QString& name, Id<Port> id,
506
    QObject* parent)
507
    : ControlInlet{name, id, parent}
62 ✔
508
{
62 ✔
509
  displayHandledExplicitly = true;
62 ✔
510
  setInit(init);
62 ✔
511
  setValue(init);
62 ✔
512
  setDomain(ossia::make_domain(min, max));
62 ✔
513
}
62 ✔
514
IntRangeSpinBox::~IntRangeSpinBox() { }
188 ✔
515

516
void IntRangeSpinBox::setupExecution(
×
517
    ossia::inlet& inl, QObject* exec_context) const noexcept
518
{
519
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
520
  port.type = ossia::val_type::VEC2F;
×
521
  port.domain = domain().get();
×
522
}
×
523

524
FloatRangeSpinBox::FloatRangeSpinBox(
×
525
    float min, float max, ossia::vec2f init, const QString& name, Id<Port> id,
526
    QObject* parent)
527
    : ControlInlet{name, id, parent}
×
528
{
×
529
  displayHandledExplicitly = true;
×
530
  setInit(init);
×
531
  setValue(init);
×
532
  setDomain(ossia::make_domain(min, max));
×
533
}
×
534

535
FloatRangeSpinBox::~FloatRangeSpinBox() { }
×
536

537
void FloatRangeSpinBox::setupExecution(
×
538
    ossia::inlet& inl, QObject* exec_context) const noexcept
539
{
540
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
541
  port.type = ossia::val_type::VEC2F;
×
542
  port.domain = domain().get();
×
543
}
×
544

545
IntSpinBox::IntSpinBox(
4,760 ✔
546
    int min, int max, int init, const QString& name, Id<Port> id, QObject* parent)
547
    : ControlInlet{name, id, parent}
4,760 ✔
548
{
4,760 ✔
549
  displayHandledExplicitly = true;
4,760 ✔
550
  setInit(init);
4,760 ✔
551
  setValue(init);
4,760 ✔
552
  setDomain(ossia::make_domain(min, max));
4,760 ✔
553
}
4,760 ✔
554

555
void IntSpinBox::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
306 ✔
556
{
557
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
306 ✔
558
  port.type = ossia::val_type::INT;
306 ✔
559
  port.domain = domain().get();
306 ✔
560
}
306 ✔
561

562
IntSpinBox::~IntSpinBox() { }
13,605 ✔
563

564
FloatSpinBox::FloatSpinBox(
364 ✔
565
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
566
    : ControlInlet{name, id, parent}
364 ✔
567
{
364 ✔
568
  displayHandledExplicitly = true;
364 ✔
569
  setInit(init);
364 ✔
570
  setValue(init);
364 ✔
571
  setDomain(ossia::make_domain(min, max));
364 ✔
572
}
364 ✔
573

574
void FloatSpinBox::setupExecution(
12 ✔
575
    ossia::inlet& inl, QObject* exec_context) const noexcept
576
{
577
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
12 ✔
578
  port.type = ossia::val_type::FLOAT;
12 ✔
579
  port.domain = domain().get();
12 ✔
580
}
12 ✔
581

582
FloatSpinBox::~FloatSpinBox() { }
1,136 ✔
583

584
TimeChooser::TimeChooser(
1,575 ✔
585
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
586
    : ControlInlet{name, id, parent}
1,575 ✔
587
{
1,575 ✔
588
  displayHandledExplicitly = true;
1,575 ✔
589
  // The second component is the mode: 0 is a time in seconds, anything else is
590
  // a musical denomination. It starts at 0, which is what the object declaring
591
  // the control says too -- halp::time_chooser_t has `bool sync{false}`.
592
  //
593
  // It used to start synced, and that made every such control's default wrong:
594
  // the value the process declared as its init was read as a number of quarter
595
  // notes and converted to seconds against the tempo, so a control asking for
596
  // two seconds got two quarters instead. Deuterium's sampler carries a
597
  // work-around for exactly this.
598
  setValue(ossia::vec2f{init, 0.f});
1,575 ✔
599
  setInit(value());
1,575 ✔
600
  setDomain(ossia::make_domain(ossia::vec2f{min, 0.f}, ossia::vec2f{max, 1.f}));
1,575 ✔
601
}
1,575 ✔
602

603
TimeChooser::~TimeChooser() { }
4,737 ✔
604

605
bool TimeChooser::preferSynced(double tempo)
402 ✔
606
{
607
  const auto v = ossia::convert<ossia::vec2f>(value());
402 ✔
608
  if(v[1] != 0.f || !(v[0] > 0.f) || !(tempo > 0.))
402 ✔
609
    return false;
95 ✔
610
  // Seconds -> a fraction of a whole note, then the closest straight note
611
  // from 1/64 to 4 wholes
612
  const double whole = v[0] * tempo / 240.;
307 ✔
613
  double best = 1.;
307 ✔
614
  double best_ratio = 1e9;
307 ✔
615
  for(double note = 1. / 64.; note <= 4.; note *= 2.)
3,070 ✔
616
  {
617
    const double r = std::max(note / whole, whole / note);
2,763 ✔
618
    if(r < best_ratio)
2,763 ✔
619
    {
620
      best_ratio = r;
1,026 ✔
621
      best = note;
1,026 ✔
622
    }
1,026 ✔
623
  }
2,763 ✔
624
  if(best_ratio > 1.5)
307 ✔
625
    return false;
67 ✔
626
  const ossia::vec2f synced{float(best), 1.f};
240 ✔
627
  setValue(synced);
240 ✔
628
  setInit(synced);
240 ✔
629
  return true;
240 ✔
630
}
402 ✔
631

632
void TimeChooser::setValue(const ossia::value& value)
2,415 ✔
633
{
634
  switch(value.get_type())
2,415 ✔
635
  {
636
    case ossia::val_type::FLOAT:
637
    case ossia::val_type::INT:
638
    case ossia::val_type::BOOL:
639
      ControlInlet::setValue(ossia::vec2f{ossia::convert<float>(value), 0.f});
142 ✔
640
      break;
142 ✔
641
    default:
642
      ControlInlet::setValue(value);
2,273 ✔
643
      break;
2,273 ✔
644
  }
645
}
2,415 ✔
646

647
void TimeChooser::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
313 ✔
648
{
649
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
313 ✔
650
  port.type = ossia::val_type::VEC2F;
313 ✔
651
  // port.type = ossia::second_u{};
652
  // port.domain = domain().get();
653
}
313 ✔
654

655
GridChooser::GridChooser(
257 ✔
656
    ossia::vec2f init, uint32_t units, int maxBars, double maxSeconds,
657
    QString periodName, const QString& name, Id<Port> id, QObject* parent)
658
    : ControlInlet{name, id, parent}
257 ✔
659
    , units{units}
257 ✔
660
    , maxBars{maxBars}
257 ✔
661
    , maxSeconds{maxSeconds}
257 ✔
662
    , periodName{std::move(periodName)}
257 ✔
663
{
257 ✔
664
  displayHandledExplicitly = true;
257 ✔
665
  setValue(init);
257 ✔
666
  setInit(value());
257 ✔
667
  // No domain: a range would clamp the value of one unit with another's bounds
668
}
257 ✔
669

670
GridChooser::~GridChooser() { }
670 ✔
671

672
GridChooser::GridChooser(DataStream::Deserializer& vis, QObject* parent)
64 ✔
673
    : ControlInlet{vis, parent}
64 ✔
674
{
64 ✔
675
  vis.writeTo(*this);
64 ✔
676
}
×
677
GridChooser::GridChooser(JSONObject::Deserializer& vis, QObject* parent)
14 ✔
678
    : ControlInlet{vis, parent}
14 ✔
679
{
14 ✔
680
  vis.writeTo(*this);
14 ✔
681
}
×
682
GridChooser::GridChooser(DataStream::Deserializer&& vis, QObject* parent)
×
683
    : ControlInlet{vis, parent}
×
684
{
×
685
  vis.writeTo(*this);
×
686
}
×
687
GridChooser::GridChooser(JSONObject::Deserializer&& vis, QObject* parent)
×
688
    : ControlInlet{vis, parent}
×
689
{
×
690
  vis.writeTo(*this);
×
691
}
×
692

693
void GridChooser::setValue(const ossia::value& value)
534 ✔
694
{
695
  switch(value.get_type())
534 ✔
696
  {
697
    case ossia::val_type::FLOAT:
698
    case ossia::val_type::INT:
699
    case ossia::val_type::BOOL:
700
      ControlInlet::setValue(ossia::vec2f{ossia::convert<float>(value), 0.f});
18 ✔
701
      break;
18 ✔
702
    default:
703
      ControlInlet::setValue(value);
516 ✔
704
      break;
516 ✔
705
  }
706
}
534 ✔
707

708
void GridChooser::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
709
{
710
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
711
  port.type = ossia::val_type::VEC2F;
×
712
}
×
713

714
Toggle::Toggle(bool init, const QString& name, Id<Port> id, QObject* parent)
2,690 ✔
715
    : ControlInlet{name, id, parent}
2,690 ✔
716
{
2,690 ✔
717
  displayHandledExplicitly = true;
2,690 ✔
718
  setInit(init);
2,690 ✔
719
  setValue(init);
2,690 ✔
720
  setDomain(State::Domain{ossia::domain_base<bool>{}});
2,690 ✔
721
}
2,690 ✔
722

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

730
Toggle::~Toggle() { }
7,758 ✔
731

732
ChooserToggle::ChooserToggle(
×
733
    QStringList alternatives, bool init, const QString& name, Id<Port> id,
734
    QObject* parent)
735
    : ControlInlet{name, id, parent}
×
736
{
×
737
  displayHandledExplicitly = true;
×
738
  setValue(init ? alternatives[1].toStdString() : alternatives[0].toStdString());
×
739
  setInit(value());
×
740
  setDomain(
×
741
      State::Domain{ossia::domain_base<std::string>{
×
742
          {alternatives[0].toStdString(), alternatives[1].toStdString()}}});
×
743
}
×
744

745
void ChooserToggle::setupExecution(
×
746
    ossia::inlet& inl, QObject* exec_context) const noexcept
747
{
748
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
749
  port.type = ossia::val_type::STRING;
×
750
  port.domain = domain().get();
×
751
}
×
752

753
ChooserToggle::~ChooserToggle() { }
×
754

755
QStringList ChooserToggle::alternatives() const noexcept
×
756
{
757
  const auto& dom = *this->domain().get().v.target<ossia::domain_base<std::string>>();
×
758
  auto it = dom.values.begin();
×
759
  auto& s1 = *it;
×
760
  auto& s2 = *(++it);
×
761
  return {QString::fromStdString(s1), QString::fromStdString(s2)};
×
762
}
763

764
LineEdit::LineEdit(QString init, const QString& name, Id<Port> id, QObject* parent)
627 ✔
765
    : ControlInlet{name, id, parent}
627 ✔
766
{
627 ✔
767
  displayHandledExplicitly = true;
627 ✔
768
  setValue(init.toStdString());
627 ✔
769
  setInit(value());
627 ✔
770
}
627 ✔
771

772
void LineEdit::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
92 ✔
773
{
774
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
92 ✔
775
  port.type = ossia::val_type::STRING;
92 ✔
776
  port.domain = domain().get();
92 ✔
777
}
92 ✔
778

779
LineEdit::~LineEdit() { }
1,745 ✔
780

781
ProgramEdit::ProgramEdit(QString init, const QString& name, Id<Port> id, QObject* parent)
25 ✔
782
    : ControlInlet{name, id, parent}
25 ✔
783
{
25 ✔
784
  displayHandledExplicitly = true;
25 ✔
785
  setValue(init.toStdString());
25 ✔
786
  setInit(value());
25 ✔
787
}
25 ✔
788

789
void ProgramEdit::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
790
{
791
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
792
  port.type = ossia::val_type::STRING;
×
793
  port.domain = domain().get();
×
794
}
×
795

796
ProgramEdit::~ProgramEdit() { }
68 ✔
797

798
FileChooserBase::FileChooserBase(
199 ✔
799
    QString init, QString filters, const QString& name, Id<Port> id, QObject* parent)
800
    : ControlInlet{name, id, parent}
199 ✔
801
{
199 ✔
802
  displayHandledExplicitly = true;
199 ✔
803
  setValue(init.toStdString());
199 ✔
804
  setInit(value());
199 ✔
805
  m_filters = filters;
199 ✔
806
}
199 ✔
807

808
void FileChooserBase::setupExecution(
28 ✔
809
    ossia::inlet& inl, QObject* exec_context) const noexcept
810
{
811
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
28 ✔
812
  port.type = ossia::val_type::STRING;
28 ✔
813
  port.domain = domain().get();
28 ✔
814
}
28 ✔
815

816
void FileChooserBase::enableFileWatch()
2 ✔
817
{
818
  auto fun = std::make_shared<std::function<void()>>([ptr = QPointer{this}]() mutable {
2 ✔
819
    ossia::qt::run_async(qApp, [ptr] {
×
820
      if(ptr)
×
821
      {
822
        // This will trigger a reload
823
        // FIXME make it work with execution value changes
824
        ptr->valueChanged(ptr->value());
×
825
      }
×
826
    });
×
827
  });
×
828

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

832
  connect(
2 ✔
833
      this, &Process::FileChooser::valueChanged, this,
834
      [cur_s = ossia::convert<std::string>(this->value()),
2 ✔
835
       fun](const ossia::value& v) mutable {
2 ✔
836
    auto new_s = ossia::convert<std::string>(v);
×
837
    if(new_s != cur_s)
×
838
    {
839
      auto& f = score::FileWatch::instance();
×
840
      f.remove(QString::fromStdString(cur_s), fun);
×
841
      f.add(QString::fromStdString(new_s), fun);
×
842
      cur_s = new_s;
×
843
    }
×
844
      });
×
845

846
  connect(this, &Process::FileChooser::destroying, this, [this, fun] {
4 ✔
847
    auto& f = score::FileWatch::instance();
2 ✔
848
    f.remove(QString::fromStdString(ossia::convert<std::string>(this->value())), fun);
2 ✔
849
  });
2 ✔
850
}
2 ✔
851

852
FileChooserBase::~FileChooserBase()
391 ✔
853
{
391 ✔
854
  destroying();
391 ✔
855
}
391 ✔
856

857
FileChooser::FileChooser(
197 ✔
858
    QString init, QString filters, const QString& name, Id<Port> id, QObject* parent)
859
    : FileChooserBase{init, filters, name, id, parent}
197 ✔
860
{
197 ✔
861
}
197 ✔
862

863
FileChooser::~FileChooser() { }
769 ✔
864

865
FileChooser::FileChooser(DataStream::Deserializer& vis, QObject* parent)
105 ✔
866
    : FileChooserBase{vis, parent}
105 ✔
867
{
105 ✔
868
  vis.writeTo(*this);
105 ✔
869
}
105 ✔
870
FileChooser::FileChooser(JSONObject::Deserializer& vis, QObject* parent)
83 ✔
871
    : FileChooserBase{vis, parent}
83 ✔
872
{
83 ✔
873
  vis.writeTo(*this);
83 ✔
874
}
83 ✔
875
FileChooser::FileChooser(DataStream::Deserializer&& vis, QObject* parent)
×
876
    : FileChooserBase{vis, parent}
×
877
{
×
878
  vis.writeTo(*this);
×
879
}
×
880
FileChooser::FileChooser(JSONObject::Deserializer&& vis, QObject* parent)
×
881
    : FileChooserBase{vis, parent}
×
882
{
×
883
  vis.writeTo(*this);
×
884
}
×
885

886
FolderChooser::FolderChooser(
9 ✔
887
    QString init, const QString& name, Id<Port> id, QObject* parent)
888
    : Process::ControlInlet{name, id, parent}
9 ✔
889
{
9 ✔
890
  displayHandledExplicitly = true;
9 ✔
891
  setValue(init.toStdString());
9 ✔
892
  setInit(value());
9 ✔
893
}
9 ✔
894

895
void FolderChooser::setupExecution(
×
896
    ossia::inlet& inl, QObject* exec_context) const noexcept
897
{
898
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
899
  port.type = ossia::val_type::STRING;
×
900
  port.domain = domain().get();
×
901
}
×
902

903
FolderChooser::~FolderChooser() { }
30 ✔
904

905
AudioFileChooser::AudioFileChooser(
2 ✔
906
    QString init, QString filters, const QString& name, Id<Port> id, QObject* parent)
907
    : FileChooserBase{init, filters, name, id, parent}
2 ✔
908
{
2 ✔
909
}
2 ✔
910

911
AudioFileChooser::~AudioFileChooser() { }
11 ✔
912

913
AudioFileChooser::AudioFileChooser(DataStream::Deserializer& vis, QObject* parent)
2 ✔
914
    : FileChooserBase{vis, parent}
2 ✔
915
{
2 ✔
916
  vis.writeTo(*this);
2 ✔
917
}
2 ✔
918
AudioFileChooser::AudioFileChooser(JSONObject::Deserializer& vis, QObject* parent)
2 ✔
919
    : FileChooserBase{vis, parent}
2 ✔
920
{
2 ✔
921
  vis.writeTo(*this);
2 ✔
922
}
2 ✔
923
AudioFileChooser::AudioFileChooser(DataStream::Deserializer&& vis, QObject* parent)
×
924
    : FileChooserBase{vis, parent}
×
925
{
×
926
  vis.writeTo(*this);
×
927
}
×
928
AudioFileChooser::AudioFileChooser(JSONObject::Deserializer&& vis, QObject* parent)
×
929
    : FileChooserBase{vis, parent}
×
930
{
×
931
  vis.writeTo(*this);
×
932
}
×
933

934
static QString toFilters(const QSet<QString>& exts)
×
935
{
936
  QString res;
×
937
  for(const auto& s : exts)
×
938
  {
939
    res += "*.";
×
940
    res += s;
×
941
    res += " ";
×
942
  }
943
  if(!res.isEmpty())
×
944
    res.resize(res.size() - 1);
×
945
  return res;
×
946
}
×
947

948
static QString videoFilesTypes()
×
949
{
950
  // FIXME refactor supported formats with Video process
951
  QSet<QString> files = {"mkv", "mov", "mp4", "h264", "avi", "hap",  "mpg", "mpeg",
×
952
                          "imf", "mxf", "mts", "m2ts", "mj2", "webm", "y4m", "nut", "ts"};
×
953
  return QString{"Videos (%1)"}.arg(toFilters(files));
×
954
}
×
955

956
VideoFileChooser::VideoFileChooser(
×
957
    QString init, QString filters, const QString& name, Id<Port> id, QObject* parent)
958
    : FileChooserBase{init, videoFilesTypes(), name, id, parent}
×
959
{
×
960
}
×
961

962
VideoFileChooser::~VideoFileChooser() { }
×
963

964
VideoFileChooser::VideoFileChooser(DataStream::Deserializer& vis, QObject* parent)
×
965
    : FileChooserBase{vis, parent}
×
966
{
×
967
  vis.writeTo(*this);
×
968
}
×
969
VideoFileChooser::VideoFileChooser(JSONObject::Deserializer& vis, QObject* parent)
×
970
    : FileChooserBase{vis, parent}
×
971
{
×
972
  vis.writeTo(*this);
×
973
}
×
974
VideoFileChooser::VideoFileChooser(DataStream::Deserializer&& vis, QObject* parent)
×
975
    : FileChooserBase{vis, parent}
×
976
{
×
977
  vis.writeTo(*this);
×
978
}
×
979
VideoFileChooser::VideoFileChooser(JSONObject::Deserializer&& vis, QObject* parent)
×
980
    : FileChooserBase{vis, parent}
×
981
{
×
982
  vis.writeTo(*this);
×
983
}
×
984

985
Button::Button(const QString& name, Id<Port> id, QObject* parent)
135 ✔
986
    : ControlInlet{name, id, parent}
135 ✔
987
{
135 ✔
988
  displayHandledExplicitly = true;
135 ✔
989
  setValue(false);
135 ✔
990
  setInit(false);
135 ✔
991
  setDomain(State::Domain{ossia::domain_base<bool>{}});
135 ✔
992
}
135 ✔
993

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

1001
Button::~Button() { }
392 ✔
1002

1003
ImpulseButton::ImpulseButton(const QString& name, Id<Port> id, QObject* parent)
4,068 ✔
1004
    : ControlInlet{name, id, parent}
4,068 ✔
1005
{
4,068 ✔
1006
  displayHandledExplicitly = true;
4,068 ✔
1007
  setValue(ossia::impulse{});
4,068 ✔
1008
  setInit(ossia::impulse{});
4,068 ✔
1009
  setDomain(State::Domain{ossia::domain_base<ossia::impulse>{}});
4,068 ✔
1010
}
4,068 ✔
1011

1012
void ImpulseButton::setupExecution(
×
1013
    ossia::inlet& inl, QObject* exec_context) const noexcept
1014
{
1015
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
1016
  port.type = ossia::val_type::IMPULSE;
×
1017
  port.domain = domain().get();
×
1018
  // A bang happens, it is not a state: an address mapped here delivers what it
1019
  // received, instead of having its current value copied in on every tick.
1020
  port.is_event = true;
×
1021
}
×
1022

1023
ImpulseButton::~ImpulseButton() { }
11,746 ✔
1024

1025
XYSlider::XYSlider(ossia::vec2f init, const QString& name, Id<Port> id, QObject* parent)
×
1026
    : ControlInlet{name, id, parent}
×
1027
{
×
1028
  displayHandledExplicitly = true;
×
1029
  setValue(init);
×
1030
  setInit(init);
×
1031
  setDomain(ossia::make_domain(ossia::vec2f{0., 0.}, ossia::vec2f{1., 1.}));
×
1032
}
×
1033

1034
XYSlider::XYSlider(
15 ✔
1035
    ossia::vec2f min, ossia::vec2f max, ossia::vec2f init, const QString& name,
1036
    Id<Port> id, QObject* parent)
1037
    : ControlInlet{name, id, parent}
15 ✔
1038
{
15 ✔
1039
  displayHandledExplicitly = true;
15 ✔
1040
  setValue(init);
15 ✔
1041
  setInit(init);
15 ✔
1042
  setDomain(ossia::make_domain(min, max));
15 ✔
1043
}
15 ✔
1044

1045
void XYSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
1046
{
1047
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
1048
  port.type = ossia::val_type::VEC2F;
×
1049
  port.domain = domain().get();
×
1050
}
×
1051

1052
XYSlider::~XYSlider() { }
58 ✔
1053

1054
XYZSlider::XYZSlider(
×
1055
    ossia::vec3f init, const QString& name, Id<Port> id, QObject* parent)
1056
    : ControlInlet{name, id, parent}
×
1057
{
×
1058
  displayHandledExplicitly = true;
×
1059
  setValue(init);
×
1060
  setInit(init);
×
1061
  setDomain(ossia::make_domain(ossia::vec3f{0., 0., 0.}, ossia::vec3f{1., 1., 1.}));
×
1062
}
×
1063

1064
XYZSlider::XYZSlider(
×
1065
    ossia::vec3f min, ossia::vec3f max, ossia::vec3f init, const QString& name,
1066
    Id<Port> id, QObject* parent)
1067
    : ControlInlet{name, id, parent}
×
1068
{
×
1069
  displayHandledExplicitly = true;
×
1070
  setValue(init);
×
1071
  setInit(init);
×
1072
  setDomain(ossia::make_domain(min, max));
×
1073
}
×
1074

1075
XYZSlider::~XYZSlider() { }
2 ✔
1076

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

1084
XYZSpinboxes::XYZSpinboxes(
×
1085
    ossia::vec3f init, const QString& name, Id<Port> id, QObject* parent)
1086
    : ControlInlet{name, id, parent}
×
1087
{
×
1088
  displayHandledExplicitly = true;
×
1089
  setValue(init);
×
1090
  setInit(init);
×
1091
  setDomain(ossia::make_domain(ossia::vec3f{0., 0., 0.}, ossia::vec3f{1., 1., 1.}));
×
1092
}
×
1093

1094
XYSpinboxes::XYSpinboxes(
×
1095
    ossia::vec2f init, const QString& name, Id<Port> id, QObject* parent)
1096
    : ControlInlet{name, id, parent}
×
1097
    , integral{false}
×
1098
{
×
1099
  displayHandledExplicitly = true;
×
1100
  setValue(init);
×
1101
  setInit(init);
×
1102
}
×
1103
XYSpinboxes::XYSpinboxes(
162 ✔
1104
    ossia::vec2f min, ossia::vec2f max, ossia::vec2f init, bool integral,
1105
    const QString& name, Id<Port> id, QObject* parent)
1106
    : ControlInlet{name, id, parent}
162 ✔
1107
    , integral{integral}
162 ✔
1108
{
162 ✔
1109
  displayHandledExplicitly = true;
162 ✔
1110
  setValue(init);
162 ✔
1111
  setInit(init);
162 ✔
1112
  setDomain(ossia::make_domain(min, max));
162 ✔
1113
}
162 ✔
1114

1115
XYSpinboxes::XYSpinboxes(DataStream::Deserializer& vis, QObject* parent)
48 ✔
1116
    : ControlInlet{vis, parent}
48 ✔
1117
{
48 ✔
1118
  vis.writeTo(*this);
48 ✔
1119
}
×
1120
XYSpinboxes::XYSpinboxes(JSONObject::Deserializer& vis, QObject* parent)
49 ✔
1121
    : ControlInlet{vis, parent}
49 ✔
1122
{
49 ✔
1123
  vis.writeTo(*this);
49 ✔
1124
}
×
1125
XYSpinboxes::XYSpinboxes(DataStream::Deserializer&& vis, QObject* parent)
×
1126
    : ControlInlet{vis, parent}
×
1127
{
×
1128
  vis.writeTo(*this);
×
1129
}
×
1130
XYSpinboxes::XYSpinboxes(JSONObject::Deserializer&& vis, QObject* parent)
×
1131
    : ControlInlet{vis, parent}
×
1132
{
×
1133
  vis.writeTo(*this);
×
1134
}
×
1135

1136
XYSpinboxes::~XYSpinboxes() { }
518 ✔
1137

1138
void XYSpinboxes::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
3 ✔
1139
{
1140
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
3 ✔
1141
  port.type = ossia::val_type::VEC2F;
3 ✔
1142
  port.domain = domain().get();
3 ✔
1143
}
3 ✔
1144

1145
XYZSpinboxes::XYZSpinboxes(
1,161 ✔
1146
    ossia::vec3f min, ossia::vec3f max, ossia::vec3f init, bool integral,
1147
    const QString& name, Id<Port> id, QObject* parent)
1148
    : ControlInlet{name, id, parent}
1,161 ✔
1149
    , integral{integral}
1,161 ✔
1150
{
1,161 ✔
1151
  displayHandledExplicitly = true;
1,161 ✔
1152
  setValue(init);
1,161 ✔
1153
  setInit(init);
1,161 ✔
1154
  setDomain(ossia::make_domain(min, max));
1,161 ✔
1155
}
1,161 ✔
1156

1157
XYZSpinboxes::~XYZSpinboxes() { }
2,678 ✔
1158

1159
void XYZSpinboxes::setupExecution(
136 ✔
1160
    ossia::inlet& inl, QObject* exec_context) const noexcept
1161
{
1162
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
136 ✔
1163
  port.type = ossia::val_type::VEC3F;
136 ✔
1164
  port.domain = domain().get();
136 ✔
1165
}
136 ✔
1166

1167
MultiSlider::MultiSlider(
811 ✔
1168
    ossia::value init, const QString& name, Id<Port> id, QObject* parent)
1169
    : ControlInlet{name, id, parent}
811 ✔
1170
{
811 ✔
1171
  displayHandledExplicitly = true;
811 ✔
1172
  setValue(std::move(init));
811 ✔
1173
  setInit(value());
811 ✔
1174
  setDomain(ossia::make_domain(0., 1.));
811 ✔
1175
}
811 ✔
1176

1177
MultiSlider::~MultiSlider() { }
1,178 ✔
1178

1179
ossia::value MultiSlider::getMin() const noexcept
×
1180
{
1181
  return domain().get().get_min();
×
1182
}
1183

1184
ossia::value MultiSlider::getMax() const noexcept
×
1185
{
1186
  return domain().get().get_max();
×
1187
}
1188

1189
void MultiSlider::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
1190
{
1191
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
1192
  port.type = ossia::val_type::LIST;
×
1193
  port.domain = domain().get();
×
1194
}
×
1195

1196
MultiSliderXY::MultiSliderXY(
3 ✔
1197
    ossia::value init, const QString& name, Id<Port> id, QObject* parent)
1198
    : ControlInlet{name, id, parent}
3 ✔
1199
{
3 ✔
1200
  displayHandledExplicitly = true;
3 ✔
1201
  setValue(std::move(init));
3 ✔
1202
  setInit(value());
3 ✔
1203
  setDomain(ossia::make_domain(0., 1.));
3 ✔
1204
}
3 ✔
1205

1206
MultiSliderXY::~MultiSliderXY() { }
10 ✔
1207

1208
ossia::value MultiSliderXY::getMin() const noexcept
×
1209
{
1210
  return domain().get().get_min();
×
1211
}
1212

1213
ossia::value MultiSliderXY::getMax() const noexcept
×
1214
{
1215
  return domain().get().get_max();
×
1216
}
1217

1218
void MultiSliderXY::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
1219
{
1220
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
1221
  port.type = ossia::val_type::LIST;
×
1222
  port.domain = domain().get();
×
1223
}
×
1224

1225
PathGeneratorXY::PathGeneratorXY(
3 ✔
1226
    ossia::value init, const QString& name, Id<Port> id, QObject* parent)
1227
    : ControlInlet{name, id, parent}
3 ✔
1228
{
3 ✔
1229
  displayHandledExplicitly = true;
3 ✔
1230
  setValue(std::move(init));
3 ✔
1231
  setInit(value());
3 ✔
1232
  setDomain(ossia::make_domain(0., 1.));
3 ✔
1233
}
3 ✔
1234

1235
PathGeneratorXY::~PathGeneratorXY() { }
10 ✔
1236

1237
ossia::value PathGeneratorXY::getMin() const noexcept
×
1238
{
1239
  return domain().get().get_min();
×
1240
}
1241

1242
ossia::value PathGeneratorXY::getMax() const noexcept
×
1243
{
1244
  return domain().get().get_max();
×
1245
}
1246

1247
void PathGeneratorXY::setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept
×
1248
{
1249
  auto& port = **safe_cast<ossia::value_inlet*>(&inl);
×
1250
  port.type = ossia::val_type::LIST;
×
1251
  port.domain = domain().get();
×
1252
}
×
1253

1254
Bargraph::Bargraph(
2 ✔
1255
    float min, float max, float init, const QString& name, Id<Port> id, QObject* parent)
1256
    : ControlOutlet{name, id, parent}
2 ✔
1257
{
2 ✔
1258
  displayHandledExplicitly = true;
2 ✔
1259
  setValue(init);
2 ✔
1260
  setDomain(ossia::make_domain(min, max));
2 ✔
1261
}
2 ✔
1262

1263
Bargraph::~Bargraph() { }
12 ✔
1264

1265
}
1266
template <>
1267
SCORE_LIB_PROCESS_EXPORT void
1268
DataStreamReader::read(const Process::FloatSlider& p)
1,043 ✔
1269
{
1270
  read((const Process::ControlInlet&)p);
1,043 ✔
1271
}
1,043 ✔
1272
template <>
1273
SCORE_LIB_PROCESS_EXPORT void
1274
DataStreamWriter::write(Process::FloatSlider& p)
×
1275
{
1276
}
×
1277
template <>
1278
SCORE_LIB_PROCESS_EXPORT void
1279
JSONReader::read(const Process::FloatSlider& p)
1,030 ✔
1280
{
1281
  read((const Process::ControlInlet&)p);
1,030 ✔
1282
}
1,030 ✔
1283
template <>
1284
SCORE_LIB_PROCESS_EXPORT void
1285
JSONWriter::write(Process::FloatSlider& p)
×
1286
{
1287
}
×
1288

1289
template <>
1290
SCORE_LIB_PROCESS_EXPORT void
1291
DataStreamReader::read(const Process::FloatKnob& p)
1,856 ✔
1292
{
1293
  read((const Process::ControlInlet&)p);
1,856 ✔
1294
}
1,856 ✔
1295
template <>
1296
SCORE_LIB_PROCESS_EXPORT void
1297
DataStreamWriter::write(Process::FloatKnob& p)
×
1298
{
1299
}
×
1300
template <>
1301
SCORE_LIB_PROCESS_EXPORT void
1302
JSONReader::read(const Process::FloatKnob& p)
1,205 ✔
1303
{
1304
  read((const Process::ControlInlet&)p);
1,205 ✔
1305
}
1,205 ✔
1306
template <>
1307
SCORE_LIB_PROCESS_EXPORT void
1308
JSONWriter::write(Process::FloatKnob& p)
×
1309
{
1310
}
×
1311

1312
template <>
1313
SCORE_LIB_PROCESS_EXPORT void
1314
DataStreamReader::read(const Process::LogFloatSlider& p)
95 ✔
1315
{
1316
  read((const Process::ControlInlet&)p);
95 ✔
1317
}
95 ✔
1318
template <>
1319
SCORE_LIB_PROCESS_EXPORT void
1320
DataStreamWriter::write(Process::LogFloatSlider& p)
×
1321
{
1322
}
×
1323
template <>
1324
SCORE_LIB_PROCESS_EXPORT void
1325
JSONReader::read(const Process::LogFloatSlider& p)
85 ✔
1326
{
1327
  read((const Process::ControlInlet&)p);
85 ✔
1328
}
85 ✔
1329
template <>
1330
SCORE_LIB_PROCESS_EXPORT void
1331
JSONWriter::write(Process::LogFloatSlider& p)
×
1332
{
1333
}
×
1334

1335
template <>
1336
SCORE_LIB_PROCESS_EXPORT void
1337
DataStreamReader::read(const Process::IntSlider& p)
395 ✔
1338
{
1339
  read((const Process::ControlInlet&)p);
395 ✔
1340
}
395 ✔
1341
template <>
1342
SCORE_LIB_PROCESS_EXPORT void
1343
DataStreamWriter::write(Process::IntSlider& p)
×
1344
{
1345
}
×
1346
template <>
1347
SCORE_LIB_PROCESS_EXPORT void
1348
JSONReader::read(const Process::IntSlider& p)
228 ✔
1349
{
1350
  read((const Process::ControlInlet&)p);
228 ✔
1351
}
228 ✔
1352
template <>
1353
SCORE_LIB_PROCESS_EXPORT void
1354
JSONWriter::write(Process::IntSlider& p)
×
1355
{
1356
}
×
1357

1358
template <>
1359
SCORE_LIB_PROCESS_EXPORT void
1360
DataStreamReader::read(const Process::IntRangeSlider& p)
×
1361
{
1362
  read((const Process::ControlInlet&)p);
×
1363
}
×
1364
template <>
1365
SCORE_LIB_PROCESS_EXPORT void
1366
DataStreamWriter::write(Process::IntRangeSlider& p)
×
1367
{
1368
}
×
1369
template <>
1370
SCORE_LIB_PROCESS_EXPORT void
1371
JSONReader::read(const Process::IntRangeSlider& p)
×
1372
{
1373
  read((const Process::ControlInlet&)p);
×
1374
}
×
1375
template <>
1376
SCORE_LIB_PROCESS_EXPORT void
1377
JSONWriter::write(Process::IntRangeSlider& p)
×
1378
{
1379
}
×
1380
template <>
1381
SCORE_LIB_PROCESS_EXPORT void
1382
DataStreamReader::read(const Process::FloatRangeSlider& p)
175 ✔
1383
{
1384
  read((const Process::ControlInlet&)p);
175 ✔
1385
}
175 ✔
1386
template <>
1387
SCORE_LIB_PROCESS_EXPORT void
1388
DataStreamWriter::write(Process::FloatRangeSlider& p)
×
1389
{
1390
}
×
1391
template <>
1392
SCORE_LIB_PROCESS_EXPORT void
1393
JSONReader::read(const Process::FloatRangeSlider& p)
26 ✔
1394
{
1395
  read((const Process::ControlInlet&)p);
26 ✔
1396
}
26 ✔
1397
template <>
1398
SCORE_LIB_PROCESS_EXPORT void
1399
JSONWriter::write(Process::FloatRangeSlider& p)
×
1400
{
1401
}
×
1402

1403
template <>
1404
SCORE_LIB_PROCESS_EXPORT void
1405
DataStreamReader::read(const Process::IntRangeSpinBox& p)
32 ✔
1406
{
1407
  read((const Process::ControlInlet&)p);
32 ✔
1408
}
32 ✔
1409
template <>
1410
SCORE_LIB_PROCESS_EXPORT void
1411
DataStreamWriter::write(Process::IntRangeSpinBox& p)
×
1412
{
1413
}
×
1414
template <>
1415
SCORE_LIB_PROCESS_EXPORT void
1416
JSONReader::read(const Process::IntRangeSpinBox& p)
4 ✔
1417
{
1418
  read((const Process::ControlInlet&)p);
4 ✔
1419
}
4 ✔
1420
template <>
1421
SCORE_LIB_PROCESS_EXPORT void
1422
JSONWriter::write(Process::IntRangeSpinBox& p)
×
1423
{
1424
}
×
1425
template <>
1426
SCORE_LIB_PROCESS_EXPORT void
1427
DataStreamReader::read(const Process::FloatRangeSpinBox& p)
×
1428
{
1429
  read((const Process::ControlInlet&)p);
×
1430
}
×
1431
template <>
1432
SCORE_LIB_PROCESS_EXPORT void
1433
DataStreamWriter::write(Process::FloatRangeSpinBox& p)
×
1434
{
1435
}
×
1436
template <>
1437
SCORE_LIB_PROCESS_EXPORT void
1438
JSONReader::read(const Process::FloatRangeSpinBox& p)
×
1439
{
1440
  read((const Process::ControlInlet&)p);
×
1441
}
×
1442
template <>
1443
SCORE_LIB_PROCESS_EXPORT void
1444
JSONWriter::write(Process::FloatRangeSpinBox& p)
×
1445
{
1446
}
×
1447

1448
template <>
1449
SCORE_LIB_PROCESS_EXPORT void
1450
DataStreamReader::read(const Process::IntSpinBox& p)
1,988 ✔
1451
{
1452
  read((const Process::ControlInlet&)p);
1,988 ✔
1453
}
1,988 ✔
1454
template <>
1455
SCORE_LIB_PROCESS_EXPORT void
1456
DataStreamWriter::write(Process::IntSpinBox& p)
×
1457
{
1458
}
×
1459
template <>
1460
SCORE_LIB_PROCESS_EXPORT void
1461
JSONReader::read(const Process::IntSpinBox& p)
920 ✔
1462
{
1463
  read((const Process::ControlInlet&)p);
920 ✔
1464
}
920 ✔
1465
template <>
1466
SCORE_LIB_PROCESS_EXPORT void
1467
JSONWriter::write(Process::IntSpinBox& p)
×
1468
{
1469
}
×
1470

1471
template <>
1472
SCORE_LIB_PROCESS_EXPORT void
1473
DataStreamReader::read(const Process::FloatSpinBox& p)
206 ✔
1474
{
1475
  read((const Process::ControlInlet&)p);
206 ✔
1476
}
206 ✔
1477
template <>
1478
SCORE_LIB_PROCESS_EXPORT void
1479
DataStreamWriter::write(Process::FloatSpinBox& p)
×
1480
{
1481
}
×
1482
template <>
1483
SCORE_LIB_PROCESS_EXPORT void
1484
JSONReader::read(const Process::FloatSpinBox& p)
166 ✔
1485
{
1486
  read((const Process::ControlInlet&)p);
166 ✔
1487
}
166 ✔
1488
template <>
1489
SCORE_LIB_PROCESS_EXPORT void
1490
JSONWriter::write(Process::FloatSpinBox& p)
×
1491
{
1492
}
×
1493

1494
template <>
1495
SCORE_LIB_PROCESS_EXPORT void
1496
DataStreamReader::read(const Process::TimeChooser& p)
725 ✔
1497
{
1498
  read((const Process::ControlInlet&)p);
725 ✔
1499
}
725 ✔
1500
template <>
1501
SCORE_LIB_PROCESS_EXPORT void
1502
DataStreamWriter::write(Process::TimeChooser& p)
×
1503
{
1504
}
×
1505
template <>
1506
SCORE_LIB_PROCESS_EXPORT void
1507
JSONReader::read(const Process::TimeChooser& p)
582 ✔
1508
{
1509
  read((const Process::ControlInlet&)p);
582 ✔
1510
}
582 ✔
1511
template <>
1512
SCORE_LIB_PROCESS_EXPORT void
1513
JSONWriter::write(Process::TimeChooser& p)
×
1514
{
1515
}
×
1516

1517
template <>
1518
SCORE_LIB_PROCESS_EXPORT void
1519
DataStreamReader::read(const Process::GridChooser& p)
74 ✔
1520
{
1521
  read((const Process::ControlInlet&)p);
74 ✔
1522
  m_stream << p.units << p.maxBars << p.maxSeconds << p.periodName;
74 ✔
1523
}
74 ✔
1524
template <>
1525
SCORE_LIB_PROCESS_EXPORT void
1526
DataStreamWriter::write(Process::GridChooser& p)
64 ✔
1527
{
1528
  m_stream >> p.units >> p.maxBars >> p.maxSeconds >> p.periodName;
64 ✔
1529
}
64 ✔
1530
template <>
1531
SCORE_LIB_PROCESS_EXPORT void
1532
JSONReader::read(const Process::GridChooser& p)
18 ✔
1533
{
1534
  read((const Process::ControlInlet&)p);
18 ✔
1535
  obj["Units"] = p.units;
18 ✔
1536
  obj["MaxBars"] = p.maxBars;
18 ✔
1537
  obj["MaxSeconds"] = p.maxSeconds;
18 ✔
1538
  obj["Period"] = p.periodName;
18 ✔
1539
}
18 ✔
1540
template <>
1541
SCORE_LIB_PROCESS_EXPORT void
1542
JSONWriter::write(Process::GridChooser& p)
14 ✔
1543
{
1544
  p.units = uint32_t(obj["Units"].toUInt64());
14 ✔
1545
  p.maxBars = obj["MaxBars"].toInt();
14 ✔
1546
  p.maxSeconds = obj["MaxSeconds"].toDouble();
14 ✔
1547
  p.periodName <<= obj["Period"];
14 ✔
1548
}
14 ✔
1549

1550
template <>
1551
SCORE_LIB_PROCESS_EXPORT void
1552
DataStreamReader::read(const Process::Toggle& p)
1,116 ✔
1553
{
1554
  read((const Process::ControlInlet&)p);
1,116 ✔
1555
}
1,116 ✔
1556
template <>
1557
SCORE_LIB_PROCESS_EXPORT void
1558
DataStreamWriter::write(Process::Toggle& p)
×
1559
{
1560
}
×
1561
template <>
1562
SCORE_LIB_PROCESS_EXPORT void JSONReader::read(const Process::Toggle& p)
650 ✔
1563
{
1564
  read((const Process::ControlInlet&)p);
650 ✔
1565
}
650 ✔
1566
template <>
1567
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::Toggle& p)
×
1568
{
1569
}
×
1570

1571
template <>
1572
SCORE_LIB_PROCESS_EXPORT void
1573
DataStreamReader::read(const Process::ChooserToggle& p)
×
1574
{
1575
  read((const Process::ControlInlet&)p);
×
1576
}
×
1577
template <>
1578
SCORE_LIB_PROCESS_EXPORT void
1579
DataStreamWriter::write(Process::ChooserToggle& p)
×
1580
{
1581
}
×
1582
template <>
1583
SCORE_LIB_PROCESS_EXPORT void
1584
JSONReader::read(const Process::ChooserToggle& p)
×
1585
{
1586
  read((const Process::ControlInlet&)p);
×
1587
}
×
1588
template <>
1589
SCORE_LIB_PROCESS_EXPORT void
1590
JSONWriter::write(Process::ChooserToggle& p)
×
1591
{
1592
}
×
1593

1594
template <>
1595
SCORE_LIB_PROCESS_EXPORT void
1596
DataStreamReader::read(const Process::LineEdit& p)
246 ✔
1597
{
1598
  read((const Process::ControlInlet&)p);
246 ✔
1599
}
246 ✔
1600
template <>
1601
SCORE_LIB_PROCESS_EXPORT void
1602
DataStreamWriter::write(Process::LineEdit& p)
×
1603
{
1604
}
×
1605
template <>
1606
SCORE_LIB_PROCESS_EXPORT void
1607
JSONReader::read(const Process::LineEdit& p)
187 ✔
1608
{
1609
  read((const Process::ControlInlet&)p);
187 ✔
1610
}
187 ✔
1611
template <>
1612
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::LineEdit& p)
×
1613
{
1614
}
×
1615

1616
template <>
1617
SCORE_LIB_PROCESS_EXPORT void
1618
DataStreamReader::read(const Process::ProgramEdit& p)
9 ✔
1619
{
1620
  read((const Process::ControlInlet&)p);
9 ✔
1621
}
9 ✔
1622
template <>
1623
SCORE_LIB_PROCESS_EXPORT void
1624
DataStreamWriter::write(Process::ProgramEdit& p)
×
1625
{
1626
}
×
1627
template <>
1628
SCORE_LIB_PROCESS_EXPORT void
1629
JSONReader::read(const Process::ProgramEdit& p)
10 ✔
1630
{
1631
  read((const Process::ControlInlet&)p);
10 ✔
1632
}
10 ✔
1633
template <>
1634
SCORE_LIB_PROCESS_EXPORT void
1635
JSONWriter::write(Process::ProgramEdit& p)
×
1636
{
1637
}
×
1638

1639

1640
namespace
1641
{
1642
// Paths under the document's folder or the user library are saved as
1643
// <PROJECT>: / <LIBRARY>: paths, so that they survive the document moving.
1644
ossia::value storedPathValue(const Process::ControlInlet& p)
347 ✔
1645
{
1646
  const auto* str = p.value().target<std::string>();
347 ✔
1647
  if(!str || str->empty())
347 ✔
1648
    return p.value();
335 ✔
1649

1650
  const auto path = QString::fromStdString(*str);
12 ✔
1651
  const auto stored = [&] {
24 ✔
1652
    if(auto* doc = score::IDocument::try_documentFromObject(p))
12 ✔
1653
      return score::relativizeFilePath(path, doc->context());
6 ✔
1654
    return score::relativizeFilePath(path);
6 ✔
1655
  }();
12 ✔
1656
  return stored.toStdString();
12 ✔
1657
}
347 ✔
1658

1659
void readPathControl(DataStreamReader& s, const Process::ControlInlet& p)
185 ✔
1660
{
1661
  s.readFrom(storedPathValue(p));
185 ✔
1662
  s.readFrom(p.init());
185 ✔
1663
  s.readFrom(p.domain());
185 ✔
1664
}
185 ✔
1665

1666
void readPathControl(JSONReader& s, const Process::ControlInlet& p)
162 ✔
1667
{
1668
  s.obj[s.strings.Value] = storedPathValue(p);
162 ✔
1669
  s.obj[s.strings.Init] = p.init();
162 ✔
1670
  s.obj[s.strings.Domain] = p.domain();
162 ✔
1671
}
162 ✔
1672
}
1673

1674
template <>
1675
SCORE_LIB_PROCESS_EXPORT void
1676
DataStreamReader::read(const Process::FileChooser& p)
176 ✔
1677
{
1678
  readPathControl(*this, p);
176 ✔
1679
  m_stream << p.filters();
176 ✔
1680
}
176 ✔
1681
template <>
1682
SCORE_LIB_PROCESS_EXPORT void
1683
DataStreamWriter::write(Process::FileChooser& p)
105 ✔
1684
{
1685
  QString f;
105 ✔
1686
  m_stream >> f;
105 ✔
1687
  p.setFilters(f);
105 ✔
1688
}
105 ✔
1689
template <>
1690
SCORE_LIB_PROCESS_EXPORT void
1691
JSONReader::read(const Process::FileChooser& p)
153 ✔
1692
{
1693
  readPathControl(*this, p);
153 ✔
1694
  obj["Filters"] = p.filters();
153 ✔
1695
}
153 ✔
1696
template <>
1697
SCORE_LIB_PROCESS_EXPORT void
1698
JSONWriter::write(Process::FileChooser& p)
83 ✔
1699
{
1700
  // tryGet: these three writers are reachable through the deserializing
1701
  // constructors, and documents older than the "Filters" key exist.
1702
  if(auto it = obj.tryGet("Filters"))
83 ✔
1703
  {
1704
    QString f;
83 ✔
1705
    f <<= *it;
83 ✔
1706
    p.setFilters(f);
83 ✔
1707
  }
83 ✔
1708
}
83 ✔
1709

1710
template <>
1711
SCORE_LIB_PROCESS_EXPORT void
1712
DataStreamReader::read(const Process::FolderChooser& p)
6 ✔
1713
{
1714
  readPathControl(*this, p);
6 ✔
1715
}
6 ✔
1716
template <>
1717
SCORE_LIB_PROCESS_EXPORT void
1718
DataStreamWriter::write(Process::FolderChooser& p)
×
1719
{
1720
}
×
1721
template <>
1722
SCORE_LIB_PROCESS_EXPORT void
1723
JSONReader::read(const Process::FolderChooser& p)
6 ✔
1724
{
1725
  readPathControl(*this, p);
6 ✔
1726
}
6 ✔
1727
template <>
1728
SCORE_LIB_PROCESS_EXPORT void
1729
JSONWriter::write(Process::FolderChooser& p)
×
1730
{
1731
}
×
1732

1733
template <>
1734
SCORE_LIB_PROCESS_EXPORT void
1735
DataStreamReader::read(const Process::AudioFileChooser& p)
3 ✔
1736
{
1737
  readPathControl(*this, p);
3 ✔
1738
  m_stream << p.filters();
3 ✔
1739
}
3 ✔
1740
template <>
1741
SCORE_LIB_PROCESS_EXPORT void
1742
DataStreamWriter::write(Process::AudioFileChooser& p)
2 ✔
1743
{
1744
  QString f;
2 ✔
1745
  m_stream >> f;
2 ✔
1746
  p.setFilters(f);
2 ✔
1747
}
2 ✔
1748
template <>
1749
SCORE_LIB_PROCESS_EXPORT void
1750
JSONReader::read(const Process::AudioFileChooser& p)
3 ✔
1751
{
1752
  readPathControl(*this, p);
3 ✔
1753
  obj["Filters"] = p.filters();
3 ✔
1754
}
3 ✔
1755
template <>
1756
SCORE_LIB_PROCESS_EXPORT void
1757
JSONWriter::write(Process::AudioFileChooser& p)
2 ✔
1758
{
1759
  if(auto it = obj.tryGet("Filters"))
2 ✔
1760
  {
1761
    QString f;
2 ✔
1762
    f <<= *it;
2 ✔
1763
    p.setFilters(f);
2 ✔
1764
  }
2 ✔
1765
}
2 ✔
1766

1767
template <>
1768
SCORE_LIB_PROCESS_EXPORT void DataStreamReader::read(const Process::VideoFileChooser& p)
×
1769
{
1770
  readPathControl(*this, p);
×
1771
  m_stream << p.filters();
×
1772
}
×
1773
template <>
1774
SCORE_LIB_PROCESS_EXPORT void DataStreamWriter::write(Process::VideoFileChooser& p)
×
1775
{
1776
  QString f;
×
1777
  m_stream >> f;
×
1778
  p.setFilters(f);
×
1779
}
×
1780
template <>
1781
SCORE_LIB_PROCESS_EXPORT void JSONReader::read(const Process::VideoFileChooser& p)
×
1782
{
1783
  readPathControl(*this, p);
×
1784
  obj["Filters"] = p.filters();
×
1785
}
×
1786
template <>
1787
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::VideoFileChooser& p)
×
1788
{
1789
  if(auto it = obj.tryGet("Filters"))
×
1790
  {
1791
    QString f;
×
1792
    f <<= *it;
×
1793
    p.setFilters(f);
×
1794
  }
×
1795
}
×
1796

1797
template <>
1798
SCORE_LIB_PROCESS_EXPORT void
1799
DataStreamReader::read(const Process::Enum& p)
1,006 ✔
1800
{
1801
  read((const Process::ControlInlet&)p);
1,006 ✔
1802
  m_stream << p.values << p.pixmaps;
1,006 ✔
1803
}
1,006 ✔
1804
template <>
1805
SCORE_LIB_PROCESS_EXPORT void DataStreamWriter::write(Process::Enum& p)
783 ✔
1806
{
1807
  m_stream >> p.values >> p.pixmaps;
783 ✔
1808
}
783 ✔
1809
template <>
1810
SCORE_LIB_PROCESS_EXPORT void JSONReader::read(const Process::Enum& p)
474 ✔
1811
{
1812
  read((const Process::ControlInlet&)p);
474 ✔
1813
  obj["Values"] = p.values;
474 ✔
1814
  obj["Pixmaps"] = p.pixmaps;
474 ✔
1815
}
474 ✔
1816
template <>
1817
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::Enum& p)
298 ✔
1818
{
1819
  p.values <<= obj["Values"];
298 ✔
1820
  p.pixmaps <<= obj["Pixmaps"];
298 ✔
1821
}
298 ✔
1822

1823
template <>
1824
SCORE_LIB_PROCESS_EXPORT void
1825
DataStreamReader::read(const Process::ComboBox& p)
1,445 ✔
1826
{
1827
  read((const Process::ControlInlet&)p);
1,445 ✔
1828
  m_stream << p.alternatives << p.folderPortName << p.fileExtensions;
1,445 ✔
1829
}
1,445 ✔
1830
template <>
1831
SCORE_LIB_PROCESS_EXPORT void
1832
DataStreamWriter::write(Process::ComboBox& p)
1,131 ✔
1833
{
1834
  m_stream >> p.alternatives >> p.folderPortName >> p.fileExtensions;
1,131 ✔
1835
}
1,131 ✔
1836
template <>
1837
SCORE_LIB_PROCESS_EXPORT void
1838
JSONReader::read(const Process::ComboBox& p)
804 ✔
1839
{
1840
  read((const Process::ControlInlet&)p);
804 ✔
1841
  obj["Values"] = p.alternatives;
804 ✔
1842
  // Folder-backed combobox metadata (empty for a plain combobox). Persisted so
1843
  // a loaded document can re-scan the folder and re-establish live refresh;
1844
  // see ProcessModel::init_folder_comboboxes. Extensions are stored as one
1845
  // space-joined string ("*.json *.wav"), like FileChooser's filters.
1846
  obj["FolderPort"] = p.folderPortName;
804 ✔
1847
  obj["FileExtensions"] = p.fileExtensions.join(QChar(' '));
804 ✔
1848
}
804 ✔
1849
template <>
1850
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::ComboBox& p)
532 ✔
1851
{
1852
  p.alternatives <<= obj["Values"];
532 ✔
1853
  // Guarded for documents saved before these fields existed.
1854
  if(obj.tryGet("FolderPort"))
532 ✔
1855
    p.folderPortName <<= obj["FolderPort"];
531 ✔
1856
  if(obj.tryGet("FileExtensions"))
532 ✔
1857
  {
1858
    QString exts;
531 ✔
1859
    exts <<= obj["FileExtensions"];
531 ✔
1860
    p.fileExtensions
1,062 ✔
1861
        = exts.isEmpty() ? QStringList{} : exts.split(QChar(' '), Qt::SkipEmptyParts);
531 ✔
1862
  }
531 ✔
1863
}
532 ✔
1864
template <>
1865
SCORE_LIB_PROCESS_EXPORT void
1866
DataStreamReader::read(const Process::Button& p)
62 ✔
1867
{
1868
  read((const Process::ControlInlet&)p);
62 ✔
1869
}
62 ✔
1870
template <>
1871
SCORE_LIB_PROCESS_EXPORT void
1872
DataStreamWriter::write(Process::Button& p)
×
1873
{
1874
}
×
1875
template <>
1876
SCORE_LIB_PROCESS_EXPORT void JSONReader::read(const Process::Button& p)
37 ✔
1877
{
1878
  read((const Process::ControlInlet&)p);
37 ✔
1879
}
37 ✔
1880
template <>
1881
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::Button& p)
×
1882
{
1883
}
×
1884
template <>
1885
SCORE_LIB_PROCESS_EXPORT void
1886
DataStreamReader::read(const Process::ImpulseButton& p)
1,538 ✔
1887
{
1888
  read((const Process::ControlInlet&)p);
1,538 ✔
1889
}
1,538 ✔
1890
template <>
1891
SCORE_LIB_PROCESS_EXPORT void
1892
DataStreamWriter::write(Process::ImpulseButton& p)
×
1893
{
1894
}
×
1895
template <>
1896
SCORE_LIB_PROCESS_EXPORT void
1897
JSONReader::read(const Process::ImpulseButton& p)
687 ✔
1898
{
1899
  read((const Process::ControlInlet&)p);
687 ✔
1900
}
687 ✔
1901
template <>
1902
SCORE_LIB_PROCESS_EXPORT void
1903
JSONWriter::write(Process::ImpulseButton& p)
×
1904
{
1905
}
×
1906

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

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

1952
template <>
1953
SCORE_LIB_PROCESS_EXPORT void
1954
DataStreamReader::read(const Process::XYZSlider& p)
×
1955
{
1956
  read((const Process::ControlInlet&)p);
×
1957
}
×
1958
template <>
1959
SCORE_LIB_PROCESS_EXPORT void
1960
DataStreamWriter::write(Process::XYZSlider& p)
×
1961
{
1962
}
×
1963
template <>
1964
SCORE_LIB_PROCESS_EXPORT void
1965
JSONReader::read(const Process::XYZSlider& p)
×
1966
{
1967
  read((const Process::ControlInlet&)p);
×
1968
}
×
1969
template <>
1970
SCORE_LIB_PROCESS_EXPORT void
1971
JSONWriter::write(Process::XYZSlider& p)
×
1972
{
1973
}
×
1974

1975
template <>
1976
SCORE_LIB_PROCESS_EXPORT void
1977
DataStreamReader::read(const Process::XYSpinboxes& p)
97 ✔
1978
{
1979
  read((const Process::ControlInlet&)p);
97 ✔
1980
  m_stream << p.integral;
97 ✔
1981
}
97 ✔
1982
template <>
1983
SCORE_LIB_PROCESS_EXPORT void
1984
DataStreamWriter::write(Process::XYSpinboxes& p)
48 ✔
1985
{
1986
  m_stream >> p.integral;
48 ✔
1987
}
48 ✔
1988
template <>
1989
SCORE_LIB_PROCESS_EXPORT void
1990
JSONReader::read(const Process::XYSpinboxes& p)
97 ✔
1991
{
1992
  read((const Process::ControlInlet&)p);
97 ✔
1993
  obj["Integral"] = p.integral;
97 ✔
1994
}
97 ✔
1995
template <>
1996
SCORE_LIB_PROCESS_EXPORT void
1997
JSONWriter::write(Process::XYSpinboxes& p)
49 ✔
1998
{
1999
  if(auto val = obj.tryGet("Integral"))
49 ✔
2000
    p.integral = val->toBool();
49 ✔
2001
}
49 ✔
2002

2003
template <>
2004
SCORE_LIB_PROCESS_EXPORT void
2005
DataStreamReader::read(const Process::XYZSpinboxes& p)
190 ✔
2006
{
2007
  read((const Process::ControlInlet&)p);
190 ✔
2008
}
190 ✔
2009
template <>
2010
SCORE_LIB_PROCESS_EXPORT void
2011
DataStreamWriter::write(Process::XYZSpinboxes& p)
×
2012
{
2013
}
×
2014
template <>
2015
SCORE_LIB_PROCESS_EXPORT void
2016
JSONReader::read(const Process::XYZSpinboxes& p)
168 ✔
2017
{
2018
  read((const Process::ControlInlet&)p);
168 ✔
2019
}
168 ✔
2020
template <>
2021
SCORE_LIB_PROCESS_EXPORT void
2022
JSONWriter::write(Process::XYZSpinboxes& p)
×
2023
{
2024
}
×
2025

2026
template <>
2027
SCORE_LIB_PROCESS_EXPORT void
2028
DataStreamReader::read(const Process::MultiSlider& p)
351 ✔
2029
{
2030
  read((const Process::ControlInlet&)p);
351 ✔
2031
}
351 ✔
2032
template <>
2033
SCORE_LIB_PROCESS_EXPORT void
2034
DataStreamWriter::write(Process::MultiSlider& p)
×
2035
{
2036
}
×
2037
template <>
2038
SCORE_LIB_PROCESS_EXPORT void
2039
JSONReader::read(const Process::MultiSlider& p)
67 ✔
2040
{
2041
  read((const Process::ControlInlet&)p);
67 ✔
2042
}
67 ✔
2043
template <>
2044
SCORE_LIB_PROCESS_EXPORT void
2045
JSONWriter::write(Process::MultiSlider& p)
×
2046
{
2047
}
×
2048

2049
template <>
2050
SCORE_LIB_PROCESS_EXPORT void
2051
DataStreamReader::read(const Process::MultiSliderXY& p)
2 ✔
2052
{
2053
  read((const Process::ControlInlet&)p);
2 ✔
2054
}
2 ✔
2055
template <>
2056
SCORE_LIB_PROCESS_EXPORT void
2057
DataStreamWriter::write(Process::MultiSliderXY& p)
×
2058
{
2059
}
×
2060
template <>
2061
SCORE_LIB_PROCESS_EXPORT void
2062
JSONReader::read(const Process::MultiSliderXY& p)
2 ✔
2063
{
2064
  read((const Process::ControlInlet&)p);
2 ✔
2065
}
2 ✔
2066
template <>
2067
SCORE_LIB_PROCESS_EXPORT void
2068
JSONWriter::write(Process::MultiSliderXY& p)
×
2069
{
2070
}
×
2071

2072

2073
template <>
2074
SCORE_LIB_PROCESS_EXPORT void
2075
DataStreamReader::read(const Process::PathGeneratorXY& p)
2 ✔
2076
{
2077
  read((const Process::ControlInlet&)p);
2 ✔
2078
}
2 ✔
2079
template <>
2080
SCORE_LIB_PROCESS_EXPORT void
2081
DataStreamWriter::write(Process::PathGeneratorXY& p)
×
2082
{
2083
}
×
2084
template <>
2085
SCORE_LIB_PROCESS_EXPORT void
2086
JSONReader::read(const Process::PathGeneratorXY& p)
2 ✔
2087
{
2088
  read((const Process::ControlInlet&)p);
2 ✔
2089
}
2 ✔
2090
template <>
2091
SCORE_LIB_PROCESS_EXPORT void
2092
JSONWriter::write(Process::PathGeneratorXY& p)
×
2093
{
2094
}
×
2095

2096
template <>
2097
SCORE_LIB_PROCESS_EXPORT void
2098
DataStreamReader::read(const Process::Bargraph& p)
4 ✔
2099
{
2100
  read((const Process::ControlOutlet&)p);
4 ✔
2101
}
4 ✔
2102
template <>
2103
SCORE_LIB_PROCESS_EXPORT void
2104
DataStreamWriter::write(Process::Bargraph& p)
×
2105
{
2106
}
×
2107
template <>
2108
SCORE_LIB_PROCESS_EXPORT void
2109
JSONReader::read(const Process::Bargraph& p)
4 ✔
2110
{
2111
  read((const Process::ControlOutlet&)p);
4 ✔
2112
}
4 ✔
2113
template <>
2114
SCORE_LIB_PROCESS_EXPORT void JSONWriter::write(Process::Bargraph& p)
×
2115
{
2116
}
×
2117

2118
template <>
2119
SCORE_LIB_PROCESS_EXPORT void DataStreamReader::read(const QString& p)
8,222 ✔
2120
{
2121
  m_stream << p;
8,222 ✔
2122
}
8,222 ✔
2123
template <>
2124
SCORE_LIB_PROCESS_EXPORT void DataStreamWriter::write(QString& p)
6,997 ✔
2125
{
2126
  m_stream >> p;
6,997 ✔
2127
}
6,997 ✔
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