• 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

77.82
/src/plugins/score-lib-process/Process/Process.cpp
1
// This is an open source non-commercial project. Dear PVS-Studio, please check
2
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3
#include "Process.hpp"
4

5
#include <Process/Dataflow/PortVisibility.hpp>
6

7
#include <Process/Dataflow/Port.hpp>
8
#include <Process/ExpandMode.hpp>
9
#include <Process/PresetHelpers.hpp>
10
#include <Process/TimeValue.hpp>
11

12
#include <LocalTree/ProcessComponent.hpp>
13

14
#include <score/model/ComponentUtils.hpp>
15
#include <score/model/EntitySerialization.hpp>
16
#include <score/model/IdentifiedObject.hpp>
17
#include <score/model/Identifier.hpp>
18
#include <score/model/ModelMetadata.hpp>
19
#include <score/tools/Bind.hpp>
20
#include <score/widgets/SetIcons.hpp>
21

22
#include <ossia/detail/algorithms.hpp>
23
#include <ossia/detail/disable_fpe.hpp>
24
#include <ossia/detail/hash_map.hpp>
25
#include <ossia/network/base/device.hpp>
26
#include <ossia/network/base/node.hpp>
27

28
#include <QObject>
29

30
#include <wobjectimpl.h>
31

32
W_OBJECT_IMPL(Process::ProcessModel)
375,519 ✔
33

34
#if !defined(SCORE_ALL_UNITY)
35
template class IdentifiedObject<Process::ProcessModel>;
36
template class score::SerializableInterface<Process::ProcessModelFactory>;
37
#endif
38
namespace Process
39
{
40

41
const QIcon& getCategoryIcon(const QString& category) noexcept
191,598 ✔
42
{
43
  static const ossia::flat_map<QString, QIcon> categoryIcon{
197,374 ✔
44
      {"AI", makeIcon(QStringLiteral(":/icons/ai.png"))},
361 ✔
45
      {"Analysis", makeIcon(QStringLiteral(":/icons/analysis.png"))},
361 ✔
46
      {"Audio", makeIcon(QStringLiteral(":/icons/audio.png"))},
361 ✔
47
      {"Plugins", makeIcon(QStringLiteral(":/icons/filter.png"))},
361 ✔
48
      {"Midi", makeIcon(QStringLiteral(":/icons/midi.png"))},
361 ✔
49
      {"Control", makeIcon(QStringLiteral(":/icons/controls.png"))},
361 ✔
50
      {"Visuals", makeIcon(QStringLiteral(":/icons/gfx.png"))},
361 ✔
51
      {"Automations", makeIcon(QStringLiteral(":/icons/automation.png"))},
361 ✔
52
      {"Impro", makeIcon(QStringLiteral(":/icons/controls.png"))},
361 ✔
53
      {"Script", makeIcon(QStringLiteral(":/icons/script.png"))},
361 ✔
54
      {"Structure", makeIcon(QStringLiteral(":/icons/structure.png"))},
361 ✔
55
      {"Network", makeIcon(QStringLiteral(":/icons/sync.png"))},
361 ✔
56
      {"Monitoring", makeIcon(QStringLiteral(":/icons/ui.png"))},
361 ✔
57
      {"Spatial", makeIcon(QStringLiteral(":/icons/spatial.png"))},
361 ✔
58
      {"Synths", makeIcon(QStringLiteral(":/icons/synths.png"))},
361 ✔
59
      {"Timing", makeIcon(QStringLiteral(":/icons/timing.png"))},
361 ✔
60
  };
61
  static const QIcon invalid;
191,598 ✔
62
  if(auto it = categoryIcon.find(category); it != categoryIcon.end())
191,598 ✔
63
  {
64
    return it->second;
191,598 ✔
65
  }
66
  if(auto slash_it = category.indexOf("/"); slash_it != -1)
×
67
  {
68
    if(auto it = categoryIcon.find(category.mid(0, slash_it)); it != categoryIcon.end())
×
69
    {
70
      return it->second;
×
71
    }
72
  }
×
73
  return invalid;
×
74
}
191,598 ✔
75
ProcessModel::ProcessModel(
9,560 ✔
76
    TimeVal duration, const Id<ProcessModel>& id, const QString& name, QObject* parent)
77
    : Entity{id, name, parent}
4,780 ✔
78
    , m_duration{std::move(duration)}
79
    , m_slotHeight{300}
80
    , m_loopDuration{m_duration}
81
    , m_size{200, 100}
82
    , m_loops{false}
83
{
9,560 ✔
84
  ossia::disable_fpe();
4,780 ✔
85
  con(metadata(), &score::ModelMetadata::NameChanged, this,
9,560 ✔
86
      [this] { prettyNameChanged(); });
9,853 ✔
87
  connect(this, &Process::ProcessModel::resetExecution, this, [this] {
8,347 ✔
88
    for(auto& p : this->m_inlets)
28,918 ✔
89
      p->executionReset();
25,351 ✔
90
    for(auto& p : this->m_outlets)
9,273 ✔
91
      p->executionReset();
5,706 ✔
92
  });
3,567 ✔
93
  // metadata().setInstanceName(*this);
94
}
×
95

96
ProcessModel::~ProcessModel()
6,245 ✔
97
{
6,245 ✔
98
  identified_object_destroying(this);
6,245 ✔
99
}
6,245 ✔
100

101
QString ProcessModel::effect() const noexcept
2,985 ✔
102
{
103
  return {};
2,985 ✔
104
}
105

106
void ProcessModel::setDurationAndScale(const TimeVal& newDuration) noexcept
2 ✔
107
{
108
  setDuration(newDuration);
2 ✔
109
}
2 ✔
110

111
void ProcessModel::setDurationAndGrow(const TimeVal& newDuration) noexcept
×
112
{
113
  setDuration(newDuration);
×
114
}
×
115

116
void ProcessModel::setDurationAndShrink(const TimeVal& newDuration) noexcept
×
117
{
118
  setDuration(newDuration);
×
119
}
×
120

121
ProcessModel::ProcessModel(DataStream::Deserializer& vis, QObject* parent)
1,634 ✔
122
    : Entity(vis, parent)
817 ✔
123
{
1,634 ✔
124
  ossia::disable_fpe();
817 ✔
125
  vis.writeTo(*this);
817 ✔
126
  con(metadata(), &score::ModelMetadata::NameChanged, this,
1,634 ✔
127
      [this] { prettyNameChanged(); });
843 ✔
128
}
×
129

130
ProcessModel::ProcessModel(JSONObject::Deserializer& vis, QObject* parent)
1,296 ✔
131
    : Entity(vis, parent)
648 ✔
132
{
1,296 ✔
133
  ossia::disable_fpe();
648 ✔
134
  vis.writeTo(*this);
648 ✔
135
  con(metadata(), &score::ModelMetadata::NameChanged, this,
1,296 ✔
136
      [this] { prettyNameChanged(); });
651 ✔
137
}
×
138

139
QString ProcessModel::prettyName() const noexcept
10,204 ✔
140
{
141
  return metadata().getName();
10,204 ✔
142
}
143

144
void ProcessModel::setParentDuration(ExpandMode mode, const TimeVal& t) noexcept
2,027 ✔
145
{
146
  switch(mode)
2,027 ✔
147
  {
148
    case ExpandMode::Scale:
149
      setDurationAndScale(t);
2,006 ✔
150
      break;
2,006 ✔
151
    case ExpandMode::GrowShrink: {
152
      if(duration() < t)
13 ✔
153
        setDurationAndGrow(t);
12 ✔
154
      else
155
        setDurationAndShrink(t);
1 ✔
156
      break;
13 ✔
157
    }
158
    case ExpandMode::ForceGrow: {
159
      if(duration() < t)
8 ✔
160
        setDurationAndGrow(t);
×
161
      break;
8 ✔
162
    }
163
    case ExpandMode::CannotExpand:
×
164
    default:
165
      break;
×
166
  }
167
}
2,027 ✔
168

169
TimeVal ProcessModel::contentDuration() const noexcept
×
170
{
171
  return TimeVal::zero();
×
172
}
173

174
void ProcessModel::setDuration(const TimeVal& other) noexcept
2,054 ✔
175
{
176
  m_duration = other;
2,054 ✔
177
  durationChanged(m_duration);
2,054 ✔
178
}
2,054 ✔
179

180
const TimeVal& ProcessModel::duration() const noexcept
9,829 ✔
181
{
182
  return m_duration;
9,829 ✔
183
}
184

185
ProcessStateDataInterface* ProcessModel::startStateData() const noexcept
4,851 ✔
186
{
187
  return nullptr;
4,851 ✔
188
}
189

190
ProcessStateDataInterface* ProcessModel::endStateData() const noexcept
3,594 ✔
191
{
192
  return nullptr;
3,594 ✔
193
}
194

195
Selection ProcessModel::selectableChildren() const noexcept
×
196
{
197
  return {};
×
198
}
199

200
Selection ProcessModel::selectedChildren() const noexcept
×
201
{
202
  return {};
×
203
}
204

205
void ProcessModel::setSelection(const Selection& s) const noexcept
31 ✔
206
{
207
  ossia::hash_set<const QObject*> selected;
31 ✔
208
  selected.reserve(s.size());
31 ✔
209
  for(const auto& obj : s)
1,230,032 ✔
210
    selected.insert(obj.data());
1,230,001 ✔
211

212
  for(Selectable* child : this->findChildren<Selectable*>())
1,380,101 ✔
213
    child->set(selected.contains(child->parent()));
1,380,070 ✔
214
}
31 ✔
215

216
Process::Inlet* ProcessModel::inlet(const Id<Process::Port>& p) const noexcept
6,304 ✔
217
{
218
  for(auto e : m_inlets)
113,662 ✔
219
    if(e->id() == p)
113,661 ✔
220
      return e;
6,303 ✔
221
  return nullptr;
1 ✔
222
}
6,304 ✔
223

224
Process::Outlet* ProcessModel::outlet(const Id<Process::Port>& p) const noexcept
1 ✔
225
{
226
  for(auto e : m_outlets)
1 ✔
227
    if(e->id() == p)
1 ✔
228
      return e;
1 ✔
229
  return nullptr;
×
230
}
1 ✔
231

232
void ProcessModel::loadPreset(const Preset& preset)
×
233
{
234
  const rapidjson::Document doc = readJson(preset.data);
×
235
  loadFixedControls(doc.GetArray(), *this);
×
236
}
×
237

238
Preset ProcessModel::savePreset() const noexcept
×
239
{
240
  Preset p;
×
241
  p.name = this->metadata().getName();
×
242
  p.key.key = this->concreteKey();
×
243

244
  JSONReader r;
×
245
  saveFixedControls(r, *this);
×
246
  p.data = r.toByteArray();
×
247
  return p;
×
248
}
×
249

250
std::vector<Preset> ProcessModel::builtinPresets() const noexcept
×
251
{
252
  return {};
×
253
}
254

255
bool ProcessModel::presetMatches(const Preset& preset) const noexcept
357 ✔
256
{
257
  return preset.key.key == concreteKey() && preset.key.effect == effect();
357 ✔
258
}
259

260
void ProcessModel::ancestorStartDateChanged() { }
5 ✔
261

262
void ProcessModel::ancestorTempoChanged() { }
×
263

264
void ProcessModel::forEachControl(
85 ✔
265
    smallfun::function<void(ControlInlet&, const ossia::value&)> f) const
266
{
267
  for(const auto& inlet : m_inlets)
771 ✔
268
  {
269
    if(auto ctrl = qobject_cast<Process::ControlInlet*>(inlet))
686 ✔
270
    {
271
      f(*ctrl, ctrl->value());
649 ✔
272
    }
649 ✔
273
  }
274
}
85 ✔
275

276
void ProcessModel::setCreatingControls(bool ok) { }
296 ✔
277

278
bool ProcessModel::creatingControls() const noexcept
×
279
{
280
  return this->flags() & ProcessFlags::CreateControls;
×
281
}
282

283
void ProcessModel::setScriptable(bool b)
128 ✔
284
{
285
  if(b != m_scriptable)
128 ✔
286
  {
287
    m_scriptable = b;
128 ✔
288
    scriptableChanged(b);
128 ✔
289
  }
128 ✔
290
}
128 ✔
291

292
void ProcessModel::setLoops(bool b)
29 ✔
293
{
294
  if(b != m_loops)
29 ✔
295
  {
296
    m_loops = b;
26 ✔
297
    loopsChanged(b);
26 ✔
298
  }
26 ✔
299
}
29 ✔
300

301
void ProcessModel::setStartOffset(TimeVal b)
11 ✔
302
{
303
  if(b != m_startOffset)
11 ✔
304
  {
305
    m_startOffset = b;
10 ✔
306
    startOffsetChanged(b);
10 ✔
307
  }
10 ✔
308
}
11 ✔
309

310
void ProcessModel::setLoopDuration(TimeVal b)
12 ✔
311
{
312
  if(b.msec() < 0.1)
12 ✔
313
    b = TimeVal::fromMsecs(0.1);
×
314

315
  if(b != m_loopDuration)
12 ✔
316
  {
317
    m_loopDuration = b;
12 ✔
318
    loopDurationChanged(b);
12 ✔
319
  }
12 ✔
320
}
12 ✔
321

322
QPointF ProcessModel::position() const noexcept
168,257,025 ✔
323
{
324
  return m_position;
168,257,025 ✔
325
}
326

327
QSizeF ProcessModel::size() const noexcept
167,759,265 ✔
328
{
329
  return m_size;
167,759,265 ✔
330
}
331

332
void ProcessModel::setPosition(const QPointF& v)
3,712 ✔
333
{
334
  if(v != m_position)
3,712 ✔
335
  {
336
    m_position = v;
3,709 ✔
337
    positionChanged(v);
3,709 ✔
338
  }
3,709 ✔
339
}
3,712 ✔
340

341
void ProcessModel::setSize(const QSizeF& v)
1,780 ✔
342
{
343
  if(v != m_size)
1,780 ✔
344
  {
345
    m_size = v;
1,780 ✔
346
    sizeChanged(v);
1,780 ✔
347
  }
1,780 ✔
348
}
1,780 ✔
349

350
FoldMode ProcessModel::foldMode() const noexcept
1,145 ✔
351
{
352
  return m_foldMode;
1,145 ✔
353
}
354

355
void ProcessModel::setFoldMode(FoldMode v)
8 ✔
356
{
357
  if(v != m_foldMode)
8 ✔
358
  {
359
    m_foldMode = v;
8 ✔
360
    foldModeChanged(v);
8 ✔
361
  }
8 ✔
362
}
8 ✔
363

364
bool ProcessModel::folded() const noexcept
1,658 ✔
365
{
366
  switch(m_foldMode)
1,658 ✔
367
  {
368
    case FoldMode::Folded:
369
      return true;
8 ✔
370
    case FoldMode::Unfolded:
371
      return false;
4 ✔
372
    case FoldMode::Auto:
1,646 ✔
373
    default:
374
      return std::ssize(m_inlets) > MaxUnpaginatedControls;
1,646 ✔
375
  }
376
}
1,658 ✔
377

378
double ProcessModel::getSlotHeight() const noexcept
27,650 ✔
379
{
380
  return m_slotHeight;
27,650 ✔
381
}
382

383
void ProcessModel::setSlotHeight(double v) noexcept
1,414 ✔
384
{
385
  m_slotHeight = v;
1,414 ✔
386
  slotHeightChanged(v);
1,414 ✔
387
}
1,414 ✔
388

389
void ProcessModel::setExecuting(bool e)
12,164 ✔
390
{
391
  m_executing = e;
12,164 ✔
392
}
12,164 ✔
393

394
std::optional<Process::MagneticInfo>
395
ProcessModel::magneticPosition(const QObject* o, const TimeVal t) const noexcept
×
396
{
397
  return {};
×
398
}
399

400
bool ProcessModel::externalSourceOutOfDate() const noexcept
×
401
{
402
  return false;
×
403
}
404

405
score::Command*
406
ProcessModel::refreshFromExternalSource(const score::DocumentContext& ctx) const
×
407
{
408
  return nullptr;
×
409
}
410

411
ProcessModel* parentProcess(QObject* obj) noexcept
18,940 ✔
412
{
413
  if(obj)
18,940 ✔
414
    obj = obj->parent();
18,940 ✔
415

416
  while(obj && !qobject_cast<ProcessModel*>(obj))
36,588 ✔
417
  {
418
    obj = obj->parent();
17,648 ✔
419
  }
420

421
  if(obj)
18,940 ✔
422
    return static_cast<ProcessModel*>(obj);
17,012 ✔
423
  return nullptr;
1,928 ✔
424
}
18,940 ✔
425

426
const ProcessModel* parentProcess(const QObject* obj) noexcept
93,046 ✔
427
{
428
  if(obj)
93,046 ✔
429
    obj = obj->parent();
93,046 ✔
430

431
  while(obj && !qobject_cast<const ProcessModel*>(obj))
106,836 ✔
432
  {
433
    obj = obj->parent();
13,790 ✔
434
  }
435

436
  if(obj)
93,046 ✔
437
    return static_cast<const ProcessModel*>(obj);
91,600 ✔
438
  return nullptr;
1,446 ✔
439
}
93,046 ✔
440

441
QString processLocalTreeAddress(const ProcessModel& proc)
×
442
{
443
  if(auto lt = findComponent<LocalTree::ProcessComponent>(proc.components()))
×
444
  {
445
    return QString::fromStdString(
×
446
        lt->node().get_device().get_name() + ":" + lt->node().osc_address());
×
447
  }
448
  return {};
×
449
}
×
450
}
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