• 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

82.26
/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)
121,196 ✔
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
161,001 ✔
42
{
43
  static const ossia::flat_map<QString, QIcon> categoryIcon{
165,801 ✔
44
      {"AI", makeIcon(QStringLiteral(":/icons/ai.png"))},
300 ✔
45
      {"Analysis", makeIcon(QStringLiteral(":/icons/analysis.png"))},
300 ✔
46
      {"Audio", makeIcon(QStringLiteral(":/icons/audio.png"))},
300 ✔
47
      {"Plugins", makeIcon(QStringLiteral(":/icons/filter.png"))},
300 ✔
48
      {"Midi", makeIcon(QStringLiteral(":/icons/midi.png"))},
300 ✔
49
      {"Control", makeIcon(QStringLiteral(":/icons/controls.png"))},
300 ✔
50
      {"Visuals", makeIcon(QStringLiteral(":/icons/gfx.png"))},
300 ✔
51
      {"Automations", makeIcon(QStringLiteral(":/icons/automation.png"))},
300 ✔
52
      {"Impro", makeIcon(QStringLiteral(":/icons/controls.png"))},
300 ✔
53
      {"Script", makeIcon(QStringLiteral(":/icons/script.png"))},
300 ✔
54
      {"Structure", makeIcon(QStringLiteral(":/icons/structure.png"))},
300 ✔
55
      {"Network", makeIcon(QStringLiteral(":/icons/sync.png"))},
300 ✔
56
      {"Monitoring", makeIcon(QStringLiteral(":/icons/ui.png"))},
300 ✔
57
      {"Spatial", makeIcon(QStringLiteral(":/icons/spatial.png"))},
300 ✔
58
      // Kept until the remaining processes are renamed to "Spatial": the icon
59
      // is looked up on the first path segment only, so both spellings need a
60
      // row or one of them renders without an icon.
61
      {"Spatialization", makeIcon(QStringLiteral(":/icons/spatial.png"))},
300 ✔
62
      {"Timing", makeIcon(QStringLiteral(":/icons/timing.png"))},
300 ✔
63
  };
64
  static const QIcon invalid;
161,001 ✔
65
  if(auto it = categoryIcon.find(category); it != categoryIcon.end())
161,001 ✔
66
  {
67
    return it->second;
161,001 ✔
68
  }
69
  if(auto slash_it = category.indexOf("/"); slash_it != -1)
×
70
  {
71
    if(auto it = categoryIcon.find(category.mid(0, slash_it)); it != categoryIcon.end())
×
72
    {
73
      return it->second;
×
74
    }
75
  }
×
76
  return invalid;
×
77
}
161,001 ✔
78
ProcessModel::ProcessModel(
8,200 ✔
79
    TimeVal duration, const Id<ProcessModel>& id, const QString& name, QObject* parent)
80
    : Entity{id, name, parent}
4,100 ✔
81
    , m_duration{std::move(duration)}
82
    , m_slotHeight{300}
83
    , m_loopDuration{m_duration}
84
    , m_size{200, 100}
85
    , m_loops{false}
86
{
8,200 ✔
87
  ossia::disable_fpe();
4,100 ✔
88
  con(metadata(), &score::ModelMetadata::NameChanged, this,
8,200 ✔
89
      [this] { prettyNameChanged(); });
8,488 ✔
90
  connect(this, &Process::ProcessModel::resetExecution, this, [this] {
5,652 ✔
91
    for(auto& p : this->m_inlets)
5,480 ✔
92
      p->executionReset();
3,928 ✔
93
    for(auto& p : this->m_outlets)
3,245 ✔
94
      p->executionReset();
1,693 ✔
95
  });
1,552 ✔
96
  // metadata().setInstanceName(*this);
97
}
×
98

99
ProcessModel::~ProcessModel()
5,205 ✔
100
{
5,205 ✔
101
  identified_object_destroying(this);
5,205 ✔
102
}
5,205 ✔
103

104
QString ProcessModel::effect() const noexcept
908 ✔
105
{
106
  return {};
908 ✔
107
}
108

109
void ProcessModel::setDurationAndScale(const TimeVal& newDuration) noexcept
2 ✔
110
{
111
  setDuration(newDuration);
2 ✔
112
}
2 ✔
113

114
void ProcessModel::setDurationAndGrow(const TimeVal& newDuration) noexcept
×
115
{
116
  setDuration(newDuration);
×
117
}
×
118

119
void ProcessModel::setDurationAndShrink(const TimeVal& newDuration) noexcept
×
120
{
121
  setDuration(newDuration);
×
122
}
×
123

124
ProcessModel::ProcessModel(DataStream::Deserializer& vis, QObject* parent)
1,018 ✔
125
    : Entity(vis, parent)
509 ✔
126
{
1,018 ✔
127
  ossia::disable_fpe();
509 ✔
128
  vis.writeTo(*this);
509 ✔
129
  con(metadata(), &score::ModelMetadata::NameChanged, this,
1,018 ✔
130
      [this] { prettyNameChanged(); });
535 ✔
131
}
×
132

133
ProcessModel::ProcessModel(JSONObject::Deserializer& vis, QObject* parent)
1,192 ✔
134
    : Entity(vis, parent)
596 ✔
135
{
1,192 ✔
136
  ossia::disable_fpe();
596 ✔
137
  vis.writeTo(*this);
596 ✔
138
  con(metadata(), &score::ModelMetadata::NameChanged, this,
1,192 ✔
139
      [this] { prettyNameChanged(); });
599 ✔
140
}
×
141

142
QString ProcessModel::prettyName() const noexcept
7,365 ✔
143
{
144
  return metadata().getName();
7,365 ✔
145
}
146

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

172
TimeVal ProcessModel::contentDuration() const noexcept
×
173
{
174
  return TimeVal::zero();
×
175
}
176

177
void ProcessModel::setDuration(const TimeVal& other) noexcept
2,046 ✔
178
{
179
  m_duration = other;
2,046 ✔
180
  durationChanged(m_duration);
2,046 ✔
181
}
2,046 ✔
182

183
const TimeVal& ProcessModel::duration() const noexcept
9,420 ✔
184
{
185
  return m_duration;
9,420 ✔
186
}
187

188
ProcessStateDataInterface* ProcessModel::startStateData() const noexcept
2,520 ✔
189
{
190
  return nullptr;
2,520 ✔
191
}
192

193
ProcessStateDataInterface* ProcessModel::endStateData() const noexcept
2,179 ✔
194
{
195
  return nullptr;
2,179 ✔
196
}
197

198
Selection ProcessModel::selectableChildren() const noexcept
×
199
{
200
  return {};
×
201
}
202

203
Selection ProcessModel::selectedChildren() const noexcept
×
204
{
205
  return {};
×
206
}
207

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

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

219
Process::Inlet* ProcessModel::inlet(const Id<Process::Port>& p) const noexcept
363 ✔
220
{
221
  for(auto e : m_inlets)
55,037 ✔
222
    if(e->id() == p)
55,036 ✔
223
      return e;
362 ✔
224
  return nullptr;
1 ✔
225
}
363 ✔
226

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

235
void ProcessModel::loadPreset(const Preset& preset)
41 ✔
236
{
237
  const rapidjson::Document doc = readJson(preset.data);
41 ✔
238
  loadFixedControls(doc.GetArray(), *this);
41 ✔
239
}
41 ✔
240

241
Preset ProcessModel::savePreset() const noexcept
50 ✔
242
{
243
  Preset p;
50 ✔
244
  p.name = this->metadata().getName();
50 ✔
245
  p.key.key = this->concreteKey();
50 ✔
246

247
  JSONReader r;
50 ✔
248
  saveFixedControls(r, *this);
50 ✔
249
  p.data = r.toByteArray();
50 ✔
250
  return p;
50 ✔
251
}
50 ✔
252

253
std::vector<Preset> ProcessModel::builtinPresets() const noexcept
×
254
{
255
  return {};
×
256
}
257

258
bool ProcessModel::presetMatches(const Preset& preset) const noexcept
×
259
{
260
  return preset.key.key == concreteKey() && preset.key.effect == effect();
×
261
}
262

263
void ProcessModel::ancestorStartDateChanged() { }
5 ✔
264

265
void ProcessModel::ancestorTempoChanged() { }
×
266

267
void ProcessModel::forEachControl(
85 ✔
268
    smallfun::function<void(ControlInlet&, const ossia::value&)> f) const
269
{
270
  for(const auto& inlet : m_inlets)
769 ✔
271
  {
272
    if(auto ctrl = qobject_cast<Process::ControlInlet*>(inlet))
684 ✔
273
    {
274
      f(*ctrl, ctrl->value());
647 ✔
275
    }
647 ✔
276
  }
277
}
85 ✔
278

279
void ProcessModel::setCreatingControls(bool ok) { }
23 ✔
280

281
bool ProcessModel::creatingControls() const noexcept
×
282
{
283
  return this->flags() & ProcessFlags::CreateControls;
×
284
}
285

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

295
void ProcessModel::setLoops(bool b)
26 ✔
296
{
297
  if(b != m_loops)
26 ✔
298
  {
299
    m_loops = b;
23 ✔
300
    loopsChanged(b);
23 ✔
301
  }
23 ✔
302
}
26 ✔
303

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

313
void ProcessModel::setLoopDuration(TimeVal b)
10 ✔
314
{
315
  if(b.msec() < 0.1)
10 ✔
316
    b = TimeVal::fromMsecs(0.1);
×
317

318
  if(b != m_loopDuration)
10 ✔
319
  {
320
    m_loopDuration = b;
10 ✔
321
    loopDurationChanged(b);
10 ✔
322
  }
10 ✔
323
}
10 ✔
324

325
QPointF ProcessModel::position() const noexcept
168,253,098 ✔
326
{
327
  return m_position;
168,253,098 ✔
328
}
329

330
QSizeF ProcessModel::size() const noexcept
167,751,942 ✔
331
{
332
  return m_size;
167,751,942 ✔
333
}
334

335
void ProcessModel::setPosition(const QPointF& v)
3,152 ✔
336
{
337
  if(v != m_position)
3,152 ✔
338
  {
339
    m_position = v;
3,149 ✔
340
    positionChanged(v);
3,149 ✔
341
  }
3,149 ✔
342
}
3,152 ✔
343

344
void ProcessModel::setSize(const QSizeF& v)
990 ✔
345
{
346
  if(v != m_size)
990 ✔
347
  {
348
    m_size = v;
990 ✔
349
    sizeChanged(v);
990 ✔
350
  }
990 ✔
351
}
990 ✔
352

353
FoldMode ProcessModel::foldMode() const noexcept
1,073 ✔
354
{
355
  return m_foldMode;
1,073 ✔
356
}
357

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

367
bool ProcessModel::folded() const noexcept
775 ✔
368
{
369
  switch(m_foldMode)
775 ✔
370
  {
371
    case FoldMode::Folded:
372
      return true;
8 ✔
373
    case FoldMode::Unfolded:
374
      return false;
4 ✔
375
    case FoldMode::Auto:
763 ✔
376
    default:
377
      return std::ssize(m_inlets) > MaxUnpaginatedControls;
763 ✔
378
  }
379
}
775 ✔
380

381
double ProcessModel::getSlotHeight() const noexcept
25,901 ✔
382
{
383
  return m_slotHeight;
25,901 ✔
384
}
385

386
void ProcessModel::setSlotHeight(double v) noexcept
1,269 ✔
387
{
388
  m_slotHeight = v;
1,269 ✔
389
  slotHeightChanged(v);
1,269 ✔
390
}
1,269 ✔
391

392
void ProcessModel::setExecuting(bool e)
3,235 ✔
393
{
394
  m_executing = e;
3,235 ✔
395
}
3,235 ✔
396

397
std::optional<Process::MagneticInfo>
UNCOV
398
ProcessModel::magneticPosition(const QObject* o, const TimeVal t) const noexcept
×
399
{
UNCOV
400
  return {};
×
401
}
402

403
bool ProcessModel::externalSourceOutOfDate() const noexcept
×
404
{
405
  return false;
×
406
}
407

408
score::Command*
409
ProcessModel::refreshFromExternalSource(const score::DocumentContext& ctx) const
×
410
{
411
  return nullptr;
×
412
}
413

414
ProcessModel* parentProcess(QObject* obj) noexcept
4,446 ✔
415
{
416
  if(obj)
4,446 ✔
417
    obj = obj->parent();
4,446 ✔
418

419
  while(obj && !qobject_cast<ProcessModel*>(obj))
10,064 ✔
420
  {
421
    obj = obj->parent();
5,618 ✔
422
  }
423

424
  if(obj)
4,446 ✔
425
    return static_cast<ProcessModel*>(obj);
3,850 ✔
426
  return nullptr;
596 ✔
427
}
4,446 ✔
428

429
const ProcessModel* parentProcess(const QObject* obj) noexcept
7,122 ✔
430
{
431
  if(obj)
7,122 ✔
432
    obj = obj->parent();
7,122 ✔
433

434
  while(obj && !qobject_cast<const ProcessModel*>(obj))
11,546 ✔
435
  {
436
    obj = obj->parent();
4,424 ✔
437
  }
438

439
  if(obj)
7,122 ✔
440
    return static_cast<const ProcessModel*>(obj);
6,675 ✔
441
  return nullptr;
447 ✔
442
}
7,122 ✔
443

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