• 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

40.68
/src/plugins/score-plugin-controlsurface/ControlSurface/Process.cpp
1
#include "Process.hpp"
2

3
#include <State/ValueConversion.hpp>
4

5
#include <Process/Dataflow/Port.hpp>
6
#include <Process/Dataflow/PortFactory.hpp>
7
#include <Process/Dataflow/WidgetInlets.hpp>
8

9
#include <Curve/CurveModel.hpp>
10

11
#include <Explorer/Explorer/DeviceExplorerModel.hpp>
12

13
#include <score/application/GUIApplicationContext.hpp>
14
#include <score/serialization/MapSerialization.hpp>
15

16
#include <ossia/network/base/node_attributes.hpp>
17
#include <ossia/network/common/destination_qualifiers.hpp>
18
#include <ossia/network/dataspace/dataspace.hpp>
19
#include <ossia/network/dataspace/dataspace_visitors.hpp>
20
#include <ossia/network/domain/domain.hpp>
21

22
#include <wobjectimpl.h>
23

24
W_OBJECT_IMPL(ControlSurface::Model)
1✔
25
namespace ControlSurface
26
{
27

28
Model::Model(
1✔
29
    const TimeVal& duration, const Id<Process::ProcessModel>& id, QObject* parent)
30
    : Process::ProcessModel{duration, id, "ControlSurfaceProcess", parent}
1✔
31
    , m_observer{Explorer::deviceExplorerFromObject(*parent), Apply{*this}}
1✔
32
{
1✔
33
  metadata().setInstanceName(*this);
1✔
34
}
1✔
35

36
Model::~Model() { }
6✔
37

38
Process::ControlInlet* makeControlFromType(
4✔
39
    const Id<Process::Port>& id, const Device::FullAddressAccessorSettings& addr,
40
    QObject* parent)
41
{
42
  // SliderWithOutputAddress<Process::IntSlider>();
43
  // TODO make better widgets if we have more information.
44

45
  // Values of the parameter's own type: a vecf_domain lists bounds per
46
  // component, not values the parameter takes.
47
  if(auto values = ossia::get_values(addr.domain.get());
7✔
48
     !values.empty() && values.front().valid()
4✔
49
     && (!addr.value.valid() || values.front().get_type() == addr.value.get_type()))
6✔
50
  {
51
    std::vector<std::pair<QString, ossia::value>> alternatives;
2✔
52
    alternatives.reserve(values.size());
2✔
53
    for(auto& v : values)
8✔
54
      alternatives.emplace_back(State::convert::toDisplayString(v), v);
6✔
55

56
    return new Process::ComboBox{
4✔
57
        std::move(alternatives), addr.value, "Control", id, parent};
2✔
58
  }
2✔
59

60
  auto& unit = addr.address.qualifiers.get().unit.v;
2✔
61
  if(unit.target<ossia::color_u>())
2✔
62
  {
UNCOV
63
    return new Process::HSVSlider{"Control", id, parent};
×
64
  }
65
  if(unit.target<ossia::position_u>() && addr.value.get_type() == ossia::val_type::VEC2F)
2✔
66
  {
67
    return new Process::XYSlider{"Control", id, parent};
×
68
  }
69
  switch(addr.value.get_type())
2✔
70
  {
71
    case ossia::val_type::IMPULSE:
UNCOV
72
      return new Process::ImpulseButton{"Control", id, parent};
×
73
    case ossia::val_type::INT:
UNCOV
74
      return new Process::IntSlider{"Control", id, parent};
×
75
    case ossia::val_type::FLOAT:
76
      return new Process::FloatSlider{"Control", id, parent};
1✔
77
    case ossia::val_type::BOOL:
UNCOV
78
      return new Process::Toggle{"Control", id, parent};
×
79
    case ossia::val_type::STRING:
80
      return new Process::LineEdit{"Control", id, parent};
×
81
    case ossia::val_type::VEC2F:
82
    case ossia::val_type::VEC4F:
83
      return new Process::MultiSlider{"Control", id, parent};
×
84
    case ossia::val_type::VEC3F:
85
      return new Process::XYZSlider{"Control", id, parent};
1✔
86
    default:
UNCOV
87
      return new Process::ControlInlet("Control", id, parent);
×
88
  }
89
}
4✔
90

91
void Model::setupControl(Process::ControlInlet* ctl, const State::AddressAccessor& addr)
×
92
{
93
  int32_t id = ctl->id().val();
×
UNCOV
94
  m_outputAddresses[id] = addr;
×
95
  ctl->displayHandledExplicitly = true;
×
96

UNCOV
97
  inlets().push_back(ctl);
×
98
  controlAdded(ctl->id());
×
99
}
×
100

UNCOV
101
void Model::addControl(
×
102
    const Id<Process::Port>& id, const Device::FullAddressAccessorSettings& msg)
103
{
UNCOV
104
  auto ctl = makeControlFromType(id, msg, this);
×
105
  // ctl->setAddress(msg.address);
106
  ctl->setValue(msg.value);
×
107
  ctl->setDomain(msg.domain);
×
108

109
  m_observer.listen(msg.address.address, id.val());
×
110

111
  if(auto desc = ossia::net::get_description(msg.extendedAttributes))
×
112
  {
UNCOV
113
    ctl->setDescription(QString::fromStdString(*desc));
×
114
  }
×
115

116
  auto setName = [ctl](const State::AddressAccessor& addr) {
×
UNCOV
117
    int length_limit = 20;
×
118
    if(addr.address.path.isEmpty())
×
119
    {
UNCOV
120
      ctl->setName("-");
×
121
    }
×
122
    else
123
    {
UNCOV
124
      auto quals = State::toString(addr.qualifiers);
×
125
      length_limit -= quals.length();
×
126

127
      QString str;
×
128

UNCOV
129
      auto it = addr.address.path.rbegin();
×
130
      while(it != addr.address.path.rend())
×
131
      {
UNCOV
132
        QString new_str = str;
×
133

134
        new_str.prepend("/" + *it);
×
135

UNCOV
136
        ++it;
×
137
        if(new_str.length() <= length_limit)
×
138
        {
139
          str = new_str;
×
UNCOV
140
        }
×
141
        else
142
        {
143
          break;
×
144
        }
145
      }
×
146

147
      // Remove the first / if it's not a whole address
UNCOV
148
      if(it != addr.address.path.rend())
×
UNCOV
149
        str.remove(0, 1);
×
150

151
      ctl->setName(str + quals);
×
152
    }
×
153
  };
×
154

155
  setName(msg.address);
×
156

UNCOV
157
  setupControl(ctl, msg.address);
×
158

159
  //  QObject::connect(ctl, &Process::ControlInlet::addressChanged,
160
  //                   ctl, setName);
UNCOV
161
}
×
162

163
void Model::removeControl(const Id<Process::Port>& m_id)
×
164
{
165
  m_outputAddresses.erase(m_id.val());
×
166

167
  auto it
UNCOV
168
      = ossia::find_if(inlets(), [&](const auto& inlet) { return inlet->id() == m_id; });
×
169
  SCORE_ASSERT(it != inlets().end());
×
UNCOV
170
  controlRemoved(**it);
×
171
  auto ptr = *it;
×
172
  inlets().erase(it);
×
UNCOV
173
  delete ptr;
×
174
}
×
175

176
QString Model::prettyName() const noexcept
×
177
{
178
  return tr("Control surface");
×
179
}
180

UNCOV
181
void Model::setDurationAndScale(const TimeVal& newDuration) noexcept { }
×
182

UNCOV
183
void Model::setDurationAndGrow(const TimeVal& newDuration) noexcept { }
×
184

UNCOV
185
void Model::setDurationAndShrink(const TimeVal& newDuration) noexcept { }
×
186

UNCOV
187
void Model::Apply::operator()(Device::Node* n, int id)
×
188
{
UNCOV
189
  auto& ctl
×
UNCOV
190
      = *static_cast<Process::ControlInlet*>(this->model.inlet(Id<Process::Port>{id}));
×
191

UNCOV
192
  if(auto addr = n->target<Device::AddressSettings>())
×
193
  {
UNCOV
194
    ctl.setDomain(addr->domain);
×
UNCOV
195
  }
×
UNCOV
196
}
×
197

198
}
199
template <>
200
void DataStreamReader::read(const ControlSurface::Model& proc)
2✔
201
{
202
  readPorts(*this, proc.m_inlets, proc.m_outlets);
2✔
203
  m_stream << proc.m_outputAddresses;
2✔
204
  insertDelimiter();
2✔
205
}
2✔
206

207
template <>
208
void DataStreamWriter::write(ControlSurface::Model& proc)
1✔
209
{
210
  writePorts(
1✔
211
      *this, components.interfaces<Process::PortFactoryList>(), proc.m_inlets,
1✔
212
      proc.m_outlets, &proc);
1✔
213
  m_stream >> proc.m_outputAddresses;
1✔
214
  checkDelimiter();
1✔
215
}
1✔
216

217
template <>
218
void JSONReader::read(const ControlSurface::Model& proc)
2✔
219
{
220
  readPorts(*this, proc.m_inlets, proc.m_outlets);
2✔
221
  obj["Addresses"] = proc.m_outputAddresses;
2✔
222
}
2✔
223

224
template <>
225
void JSONWriter::write(ControlSurface::Model& proc)
1✔
226
{
227
  writePorts(
1✔
228
      *this, components.interfaces<Process::PortFactoryList>(), proc.m_inlets,
1✔
229
      proc.m_outlets, &proc);
1✔
230

231
  proc.m_outputAddresses <<= obj["Addresses"];
1✔
232
}
1✔
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