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

ossia / score / 30754311710

02 Aug 2026 03:25PM UTC coverage: 15.222% (-0.04%) from 15.263%
30754311710

Pull #2163

github

web-flow
Merge 8b7bf0aad into e99b6a5da
Pull Request #2163: Fix backwards playback for audio plug-ins (VST, VST3, LV2, JSFX)

0 of 57 new or added lines in 5 files covered. (0.0%)

343 existing lines in 16 files now uncovered.

30381 of 199582 relevant lines covered (15.22%)

1075.26 hits per line

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

31.82
/src/plugins/score-plugin-scenario/Scenario/Process/ScenarioModel.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

4
#include "ScenarioModel.hpp"
5

6
#include "Algorithms/StandardCreationPolicy.hpp"
7

8
#include <Process/Process.hpp>
9
#include <Process/TimeValue.hpp>
10

11
#include <Scenario/Application/Menus/ScenarioCopy.hpp>
12
#include <Scenario/Commands/Scenario/Displacement/MoveEventMeta.hpp>
13
#include <Scenario/Commands/Scenario/Merge/MergeTimeSyncs.hpp>
14
#include <Scenario/Commands/Scenario/ScenarioPasteElements.hpp>
15
#include <Scenario/Document/CommentBlock/CommentBlockModel.hpp>
16
#include <Scenario/Document/Event/EventModel.hpp>
17
#include <Scenario/Document/Graph.hpp>
18
#include <Scenario/Document/Interval/IntervalDurations.hpp>
19
#include <Scenario/Document/Interval/IntervalModel.hpp>
20
#include <Scenario/Document/ScenarioDocument/ScenarioDocumentModel.hpp>
21
#include <Scenario/Document/State/StateModel.hpp>
22
#include <Scenario/Document/TimeSync/TimeSyncModel.hpp>
23
#include <Scenario/Palette/ScenarioPoint.hpp>
24
#include <Scenario/Process/Algorithms/Accessors.hpp>
25
#include <Scenario/Process/Algorithms/ProcessPolicy.hpp>
26
#include <Scenario/Process/ScenarioProcessMetadata.hpp>
27

28
#include <score/command/Dispatchers/CommandDispatcher.hpp>
29
#include <score/document/DocumentContext.hpp>
30
#include <score/document/DocumentInterface.hpp>
31
#include <score/model/EntityMap.hpp>
32
#include <score/model/ModelMetadata.hpp>
33
#include <score/selection/Selectable.hpp>
34
#include <score/selection/SelectionDispatcher.hpp>
35
#include <score/serialization/DataStreamVisitor.hpp>
36
#include <score/tools/IdentifierGeneration.hpp>
37

38
#include <core/document/Document.hpp>
39

40
#include <wobjectimpl.h>
41

42
#include <vector>
43
W_OBJECT_IMPL(Scenario::ProcessModel)
480✔
44
namespace Scenario
45
{
46

47
ProcessModel::ProcessModel(
38✔
48
    const TimeVal& duration, const Id<Process::ProcessModel>& id,
49
    const score::DocumentContext& ctx, QObject* parent)
50
    : Process::
19✔
51
          ProcessModel{duration, id, Metadata<ObjectKey_k, Scenario::ProcessModel>::get(), parent}
19✔
52
    , inlet{std::make_unique<Process::AudioInlet>(
38✔
53
          "Audio In", Id<Process::Port>(0), this)}
19✔
54
    , outlet{std::make_unique<Process::AudioOutlet>(
38✔
55
          "Audio Out", Id<Process::Port>(0), this)}
19✔
56
    , m_context{ctx}
57
    , m_startTimeSyncId{Scenario::startId<TimeSyncModel>()}
58
    , m_startEventId{Scenario::startId<EventModel>()}
59
    , m_startStateId{Scenario::startId<StateModel>()}
60
{
38✔
61
  auto& start_tn
19✔
62
      = ScenarioCreate<TimeSyncModel>::redo(m_startTimeSyncId, TimeVal::zero(), *this);
19✔
63
  start_tn.metadata().setName("Sync.start");
19✔
64
  start_tn.setStartPoint(true);
19✔
65

66
  auto& start_ev = ScenarioCreate<EventModel>::redo(m_startEventId, start_tn, *this);
19✔
67
  start_ev.metadata().setName("Event.start");
19✔
68
  auto& start_st
19✔
69
      = ScenarioCreate<StateModel>::redo(m_startStateId, start_ev, 0.02, *this);
19✔
70
  start_st.metadata().setName("State.start");
19✔
71
  // At the end because plug-ins depend on the start/end timesync & al being
72
  // here
73
  metadata().setInstanceName(*this);
19✔
74

75
  outlet->setPropagate(true);
19✔
76

77
  init();
19✔
78
}
×
79

80
void ProcessModel::init()
23✔
81
{
82
  inlet->setName("In");
23✔
83
  outlet->setName("Out");
23✔
84
  m_inlets.push_back(inlet.get());
23✔
85
  m_outlets.push_back(outlet.get());
23✔
86

87
  m_graph = std::make_unique<TimenodeGraph>(*this);
23✔
88

89
  auto stopExec = [this] {
23✔
UNCOV
90
    for(EventModel& ev : events)
×
91
    {
UNCOV
92
      ev.setStatus(ExecutionStatus::Editing, *this);
×
93
    }
UNCOV
94
  };
×
95

96
  auto reset = [this] {
23✔
UNCOV
97
    for(auto& interval : intervals)
×
98
    {
99
      interval.reset();
×
100
      interval.executionEvent(Scenario::IntervalExecutionEvent::Finished);
×
101
    }
102

UNCOV
103
    for(auto& ts : timeSyncs)
×
104
    {
UNCOV
105
      ts.setWaiting(false);
×
106
    }
107

UNCOV
108
    for(auto& event : events)
×
109
    {
UNCOV
110
      event.setStatus(Scenario::ExecutionStatus::Editing, *this);
×
111
    }
UNCOV
112
  };
×
113

114
  connect(this, &ProcessModel::stopExecution, this, stopExec);
23✔
115
  connect(this, &ProcessModel::resetExecution, this, reset);
23✔
116
}
23✔
117

118
bool ProcessModel::hasCycles() const noexcept
×
119
{
120
  return m_graph->hasCycles();
×
121
}
122

123
ProcessModel::~ProcessModel()
46✔
124
{
23✔
125
  try
126
  {
127
    score::IDocument::documentContext(*parent()).selectionStack.clear();
23✔
128
  }
23✔
129
  catch(...)
130
  {
131
    // Sometimes the scenario isn't in the hierarchy, e.G. in
132
    // ScenarioPasteElements
133
  }
×
134
  comments.clear();
23✔
135
  intervals.clear();
23✔
136
  states.clear();
23✔
137
  events.clear();
23✔
138
  timeSyncs.clear();
23✔
139

140
  identified_object_destroying(this);
23✔
141
}
46✔
142

143
void ProcessModel::setDurationAndScale(const TimeVal& newDuration) noexcept
×
144
{
145
  if(duration() == TimeVal::zero())
×
146
    return;
×
147

148
  double scale = newDuration / duration();
×
149

150
  for(auto& timesync : timeSyncs)
×
151
  {
152
    timesync.setDate(timesync.date() * scale);
×
153
    // Since events will also move we do not need
154
    // to move the timesync.
155
  }
156

157
  for(auto& event : events)
×
158
  {
159
    event.setDate(event.date() * scale);
×
160
  }
161
  for(auto& cmt : comments)
×
162
  {
163
    cmt.setDate(cmt.date() * scale);
×
164
  }
165

166
  for(auto& interval : intervals)
×
167
  {
168
    interval.setStartDate(interval.date() * scale);
×
169
    // Note : scale the min / max.
170

171
    auto newdur = interval.duration.defaultDuration() * scale;
×
172
    IntervalDurations::Algorithms::scaleAllDurations(interval, newdur);
×
173

174
    for(auto& process : interval.processes)
×
175
    {
176
      process.setParentDuration(ExpandMode::Scale, newdur);
×
177
    }
178

179
    intervalMoved(&interval);
×
180
  }
181

182
  this->setDuration(newDuration);
×
183
}
×
184

185
void ProcessModel::setDurationAndGrow(const TimeVal& newDuration) noexcept
×
186
{
187
  this->setDuration(newDuration);
×
188
}
×
189

190
void ProcessModel::setDurationAndShrink(const TimeVal& newDuration) noexcept
×
191
{
192
  this->setDuration(newDuration);
×
193
  return; // Disabled by Asana
×
194
}
195

196
Selection ProcessModel::selectableChildren() const noexcept
×
197
{
198
  Selection objects;
×
199
  apply([&](const auto& m) {
×
200
    for(auto& elt : this->*m)
×
201
      objects.append(elt);
×
202
  });
×
203
  return objects;
×
204
}
×
205

206
template <typename InputVec, typename OutputVec>
207
static void copySelected(const InputVec& in, OutputVec& out)
×
208
{
209
  for(const auto& elt : in)
×
210
  {
211
    if(elt.selection.get())
×
212
      out.append(elt);
×
213
  }
214
}
×
215

216
Selection ProcessModel::selectedChildren() const noexcept
×
217
{
218
  Selection objects;
×
219
  apply([&](const auto& m) { copySelected(this->*m, objects); });
×
220
  return objects;
×
221
}
×
222

223
void ProcessModel::setSelection(const Selection& s) const noexcept
10✔
224
{
225
  // OPTIMIZEME
226
  apply([&](auto&& m) {
60✔
227
    for(auto& elt : this->*m)
68✔
228
      elt.selection.set(s.contains(&elt));
18✔
229
  });
50✔
230
}
10✔
231

232
const QVector<Id<IntervalModel>> intervalsBeforeTimeSync(
×
233
    const Scenario::ProcessModel& scenar, const Id<TimeSyncModel>& timeSyncId)
234
{
235
  QVector<Id<IntervalModel>> cstrs;
×
236
  const auto& tn = scenar.timeSyncs.at(timeSyncId);
×
237
  for(const auto& ev : tn.events())
×
238
  {
239
    const auto& evM = scenar.events.at(ev);
×
240
    for(const auto& st : evM.states())
×
241
    {
242
      const auto& stM = scenar.states.at(st);
×
243
      if(stM.previousInterval())
×
244
        cstrs.push_back(*stM.previousInterval());
×
245
    }
246
  }
247

248
  return cstrs;
×
249
}
×
250

251
TimeVal ProcessModel::contentDuration() const noexcept
×
252
{
253
  TimeVal max_tn_pos = TimeVal::zero();
×
254
  for(TimeSyncModel& t : timeSyncs)
×
255
  {
256
    if(t.date() > max_tn_pos)
×
257
      max_tn_pos = t.date();
×
258
  }
259
  return max_tn_pos;
×
260
}
261

262
void ProcessModel::ancestorStartDateChanged()
×
263
{
264
  for(auto& itv : intervals)
×
265
    itv.ancestorStartDateChanged();
×
266
}
×
267

268
void ProcessModel::ancestorTempoChanged()
×
269
{
270
  for(auto& itv : intervals)
×
271
    itv.ancestorTempoChanged();
×
272
}
×
273

274
void ProcessModel::loadPreset(const Process::Preset& preset)
×
275
{
276
  // TODO we must not paste but replace !
277
  Scenario::Command::ScenarioPasteElements cmd{
×
278
      *this, readJson(preset.data), Scenario::Point{}};
×
279
  cmd.redo(score::IDocument::documentContext(*this));
×
280
  for(TimeSyncModel& sync : timeSyncs)
×
281
  {
282
    if(&sync != &startTimeSync() && sync.date() == TimeVal::zero())
×
283
    {
284
      Scenario::Command::MergeTimeSyncs merge(*this, sync.id(), startTimeSync().id());
×
285
      break;
286
    }
×
287
  }
288
}
×
289

290
Process::Preset ProcessModel::savePreset() const noexcept
×
291
{
292
  Process::Preset p;
×
293
  p.name = this->metadata().getName();
×
294
  p.key = {this->concreteKey(), {}};
×
295

296
  JSONReader r;
×
297
  copyWholeScenario(r, *this);
×
298

299
  p.data = r.toByteArray();
×
300
  return p;
×
301
}
×
302

303
Scenario::ProcessModel* closestParentScenario(const QObject* parentObj) noexcept
×
304
{
305
  while(parentObj && !qobject_cast<const Scenario::ProcessModel*>(parentObj))
×
306
  {
307
    parentObj = parentObj->parent();
×
308
  }
309
  return static_cast<Scenario::ProcessModel*>(const_cast<QObject*>(parentObj));
×
310
}
311
}
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