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

ossia / score / 31952604910

16 Aug 2026 02:24PM UTC coverage: 19.438% (+3.2%) from 16.231%
31952604910

push

github

jcelerier
execution: fix a crash that has been lurking since 2018 in execution cleanup

0 of 1 new or added line in 1 file covered. (0.0%)

2699 existing lines in 72 files now uncovered.

41088 of 211385 relevant lines covered (19.44%)

4325.7 hits per line

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

0.0
/src/plugins/score-plugin-engine/Execution/BaseScenarioComponent.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 "BaseScenarioComponent.hpp"
5

6
#include <Process/Dataflow/Port.hpp>
7
#include <Process/ExecutionContext.hpp>
8

9
#include <Explorer/DocumentPlugin/DeviceDocumentPlugin.hpp>
10

11
#include <Scenario/Document/BaseScenario/BaseScenario.hpp>
12
#include <Scenario/Document/Event/EventExecution.hpp>
13
#include <Scenario/Document/Interval/IntervalExecution.hpp>
14
#include <Scenario/Document/Interval/IntervalModel.hpp>
15
#include <Scenario/Document/State/StateExecution.hpp>
16
#include <Scenario/Document/TimeSync/TimeSyncExecution.hpp>
17
#include <Scenario/Document/TimeSync/TimeSyncModel.hpp>
18

19
#include <ossia/audio/audio_protocol.hpp>
20
#include <ossia/dataflow/execution_state.hpp>
21
#include <ossia/dataflow/nodes/forward_node.hpp>
22
#include <ossia/editor/scenario/scenario.hpp>
23
#include <ossia/editor/scenario/time_event.hpp>
24
#include <ossia/editor/scenario/time_interval.hpp>
25
#include <ossia/editor/scenario/time_sync.hpp>
26
#include <ossia/editor/state/state.hpp>
27

28
#include <ossia-qt/invoke.hpp>
29

30
#include <wobjectimpl.h>
31

32
W_OBJECT_IMPL(Execution::BaseScenarioElement)
×
33

34
namespace Execution
35
{
36
BaseScenarioElement::BaseScenarioElement(const Context& ctx, QObject* parent)
×
37
    : QObject{nullptr}
×
38
    , m_ctx{ctx}
×
39
{
×
40
}
×
41

42
BaseScenarioElement::~BaseScenarioElement() { }
×
43

44
struct FinishCallback final : public ossia::time_sync_callback
45
{
46
  explicit FinishCallback(BaseScenarioElement& s)
×
47
      : self{&s}
×
48
  {
×
49
  }
×
50

51
  void finished_evaluation(bool) override
×
52
  {
53
    ossia::qt::run_async(self.data(), [s = self] {
×
54
      if(s)
×
55
        s->finished();
×
56
    });
×
57
  }
×
58

59
  QPointer<BaseScenarioElement> self;
60
};
61

62
void BaseScenarioElement::init(bool forcePlay, BaseScenarioRefContainer element)
×
63
{
64
  if(element.interval().outlet && !element.interval().outlet->address().isSet())
×
65
  {
66

67
    QString audio_dev_name;
×
68
    for(auto dev : m_ctx.execState->edit_devices())
×
69
    {
70
      if(dynamic_cast<ossia::audio_protocol*>(&dev->get_protocol()))
×
71
      {
72
        audio_dev_name = QString::fromStdString(dev->get_name());
×
73
        break;
×
74
      }
75
    }
76
    if(!audio_dev_name.isEmpty())
×
77
      element.interval().outlet->setAddress(
×
78
          State::AddressAccessor{{audio_dev_name, {"out", "main"}}});
×
79
  }
×
80
  m_ossia_scenario = std::make_shared<ossia::scenario>();
×
81

82
  auto main_start_node = m_ossia_scenario->get_start_time_sync();
×
83
  auto main_end_node = std::make_shared<ossia::time_sync>();
×
84
  main_end_node->callbacks.callbacks.push_back(new FinishCallback{*this});
×
85
  m_ossia_scenario->add_time_sync(main_end_node);
×
86

87
  auto main_start_event = *main_start_node->emplace(
×
88
      main_start_node->get_time_events().begin(), [](auto&&...) {},
×
89
      ossia::expressions::make_expression_true());
×
90
  auto main_end_event = *main_end_node->emplace(
×
91
      main_end_node->get_time_events().begin(), [](auto&&...) {},
×
92
      ossia::expressions::make_expression_true());
×
93

94
  // TODO PlayDuration of base interval.
95
  // TODO PlayDuration of FullView
96
  auto main_interval = ossia::time_interval::create(
×
97
      {}, *main_start_event, *main_end_event,
×
98
      m_ctx.time(element.interval().duration.defaultDuration()),
×
99
      m_ctx.time(element.interval().duration.minDuration()),
×
100
      m_ctx.time(element.interval().duration.maxDuration()));
×
101
  m_ossia_scenario->add_time_interval(main_interval);
×
102

103
  m_ossia_startTimeSync
×
104
      = std::make_shared<TimeSyncComponent>(element.startTimeSync(), m_ctx, this);
×
105
  m_ossia_endTimeSync
×
106
      = std::make_shared<TimeSyncComponent>(element.endTimeSync(), m_ctx, this);
×
107

108
  m_ossia_startEvent
×
109
      = std::make_shared<EventComponent>(element.startEvent(), m_ctx, this);
×
110
  m_ossia_endEvent = std::make_shared<EventComponent>(element.endEvent(), m_ctx, this);
×
111

112
  m_ossia_startState = std::make_shared<StateComponent>(
×
113
      element.startState(), main_start_event, m_ctx, this);
×
114
  m_ossia_endState = std::make_shared<StateComponent>(
×
115
      element.endState(), main_end_event, m_ctx, this);
×
116

117
  m_ossia_interval = std::make_shared<IntervalComponent>(
×
118
      element.interval(), std::shared_ptr<ossia::scenario>{}, m_ctx, this);
×
119

120
  if(forcePlay)
×
121
  {
122
    m_ossia_startTimeSync->onSetup(
×
123
        main_start_node, ossia::expressions::make_expression_true());
×
124
    m_ossia_endTimeSync->onSetup(
×
125
        main_end_node, ossia::expressions::make_expression_false());
×
126
  }
×
127
  else
128
  {
129
    m_ossia_startTimeSync->onSetup(
×
130
        main_start_node, m_ossia_startTimeSync->makeTrigger());
×
131
    m_ossia_endTimeSync->onSetup(main_end_node, m_ossia_endTimeSync->makeTrigger());
×
132
  }
133

134
  m_ossia_startEvent->onSetup(
×
135
      main_start_event, m_ossia_startEvent->makeExpression(),
×
136
      (ossia::time_event::offset_behavior)element.startEvent().offsetBehavior());
×
137
  m_ossia_endEvent->onSetup(
×
138
      main_end_event, m_ossia_endEvent->makeExpression(),
×
139
      (ossia::time_event::offset_behavior)element.endEvent().offsetBehavior());
×
140

141
  main_start_node->set_start(true);
×
142

143
  // Important: we do not setup the end state in order to not have it
144
  // send its messages twice as this is already handled elsewhere in score.
145
  // (when we press stop manually)
146
  // This should be refactored though, for now it's a bit ugly.
147
  // m_ossia_endState->onSetup();
148
  m_ossia_interval->onSetup(
×
149
      m_ossia_interval, main_interval, m_ossia_interval->makeDurations(), true);
×
150

151
  m_ossia_scenario->start();
×
152
}
×
153

154
void BaseScenarioElement::cleanup()
×
155
{
156
  if(m_ossia_interval)
×
157
    m_ossia_interval->cleanup(m_ossia_interval);
×
158
  if(m_ossia_startState)
×
159
    m_ossia_startState->cleanup(m_ossia_startState);
×
160
  if(m_ossia_endState)
×
NEW
161
    m_ossia_endState->cleanup(m_ossia_endState);
×
162
  if(m_ossia_startEvent)
×
163
    m_ossia_startEvent->cleanup(m_ossia_startEvent);
×
164
  if(m_ossia_endEvent)
×
165
    m_ossia_endEvent->cleanup(m_ossia_endEvent);
×
166
  if(m_ossia_startTimeSync)
×
167
    m_ossia_startTimeSync->cleanup(m_ossia_startTimeSync);
×
168
  if(m_ossia_endTimeSync)
×
169
    m_ossia_endTimeSync->cleanup(m_ossia_endTimeSync);
×
170
  m_ossia_interval.reset();
×
171
  m_ossia_startState.reset();
×
172
  m_ossia_endState.reset();
×
173
  m_ossia_startEvent.reset();
×
174
  m_ossia_endEvent.reset();
×
175
  m_ossia_startTimeSync.reset();
×
176
  m_ossia_endTimeSync.reset();
×
177
  m_ossia_scenario.reset();
×
178
}
×
179

180
ossia::scenario& BaseScenarioElement::baseScenario() const
×
181
{
182
  return *m_ossia_scenario;
×
183
}
184

185
IntervalComponent& BaseScenarioElement::baseInterval() const
×
186
{
187
  return *m_ossia_interval;
×
188
}
189

190
TimeSyncComponent& BaseScenarioElement::startTimeSync() const
×
191
{
192
  return *m_ossia_startTimeSync;
×
193
}
194

195
TimeSyncComponent& BaseScenarioElement::endTimeSync() const
×
196
{
197
  return *m_ossia_endTimeSync;
×
198
}
199

200
EventComponent& BaseScenarioElement::startEvent() const
×
201
{
202
  return *m_ossia_startEvent;
×
203
}
204

205
EventComponent& BaseScenarioElement::endEvent() const
×
206
{
207
  return *m_ossia_endEvent;
×
208
}
209

210
StateComponent& BaseScenarioElement::startState() const
×
211
{
212
  return *m_ossia_startState;
×
213
}
214

215
StateComponent& BaseScenarioElement::endState() const
×
216
{
217
  return *m_ossia_endState;
×
218
}
219
}
220

221
BaseScenarioRefContainer::BaseScenarioRefContainer(
×
222
    Scenario::IntervalModel& interval, Scenario::ScenarioInterface& s)
223
    : m_interval{interval}
×
224
    , m_startState{s.state(interval.startState())}
×
225
    , m_endState{s.state(interval.endState())}
×
226
    , m_startEvent{s.event(m_startState.eventId())}
×
227
    , m_endEvent{s.event(m_endState.eventId())}
×
228
    , m_startNode{s.timeSync(m_startEvent.timeSync())}
×
229
    , m_endNode{s.timeSync(m_endEvent.timeSync())}
×
230
{
231
}
×
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