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

ossia / score / 35899133125

23 Sep 2026 05:57PM UTC coverage: 41.488% (+1.2%) from 40.337%
35899133125

push

github

jcelerier
3rdparty: follow the merged libossia

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PWVTQ1pm3X2Uz7goFgULtC

123236 of 297041 relevant lines covered (41.49%)

113626.05 hits per line

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

55.6
/src/plugins/score-lib-process/Process/ExecutionSetup.cpp
1
#include <State/Address.hpp>
2

3
#include <Process/Dataflow/Cable.hpp>
4
#include <Process/Dataflow/Port.hpp>
5
#include <Process/ExecutionContext.hpp>
6
#include <Process/ExecutionFunctions.hpp>
7
#include <Process/ExecutionSetup.hpp>
8
#include <Process/ExecutionTransaction.hpp>
9
#include <Process/Process.hpp>
10

11
#include <ossia/dataflow/execution_state.hpp>
12
#include <ossia/dataflow/for_each_port.hpp>
13
#include <ossia/dataflow/graph/graph_interface.hpp>
14
#include <ossia/dataflow/graph_edge.hpp>
15
#include <ossia/dataflow/graph_node.hpp>
16
#include <ossia/dataflow/port.hpp>
17
#include <ossia/editor/scenario/time_process.hpp>
18
#include <ossia/network/common/destination_qualifiers.hpp>
19

20
namespace Execution
21
{
22

23
namespace
24
{
25
struct ContextEnqueuer
26
{
27
  SetupContext& self;
28
  template <typename F>
29
  void operator()(F&& f)
1,829✔
30
  {
31
    static_assert(std::is_nothrow_move_constructible_v<F>);
32
    OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
1,829✔
33
    self.context.executionQueue.enqueue(std::move(f));
1,829✔
34
  }
1,829✔
35
};
36
struct VectorEnqueuer
37
{
38
  Transaction& vec;
39
  template <typename F>
40
  void operator()(F&& f)
1,060✔
41
  {
42
    static_assert(std::is_nothrow_move_constructible_v<F>);
43
    OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
1,060✔
44
    vec.push_back(std::move(f));
1,060✔
45
  }
1,060✔
46
};
47

48
// Changed from lambda to explicit struct to improve debuggability
49
static auto enqueue_in_context(SetupContext& self) noexcept
469✔
50
{
51
  return ContextEnqueuer{self};
469✔
52
}
53

54
static auto enqueue_in_vector(Transaction& vec) noexcept
806✔
55
{
56
  return VectorEnqueuer{vec};
806✔
57
}
58
}
59
ossia::net::node_base*
60
findNode(const ossia::execution_state& st, const State::Address& addr)
69✔
61
{
62
  auto& devs = st.edit_devices();
69✔
63
  auto dev_p = ossia::find_if(
69✔
64
      devs, [d = addr.device.toStdString()](auto& dev) { return dev->get_name() == d; });
176✔
65
  if(dev_p == devs.end())
69✔
66
    return nullptr;
×
67
  return ossia::net::find_node(
69✔
68
      (*dev_p)->get_root_node(), addr.path.join("/").toStdString());
69✔
69
}
69✔
70

71
std::optional<ossia::destination> makeDestination(
1✔
72
    const ossia::execution_state& devices, const State::AddressAccessor& addr)
73
{
74
  auto n = findNode(devices, addr.address);
1✔
75
  if(!n)
1✔
76
    return {};
×
77

78
  auto p = n->get_parameter();
1✔
79
  if(!p)
1✔
80
    return {};
×
81

82
  auto& qual = addr.qualifiers.get();
1✔
83
  return ossia::destination{*p, qual.accessors, qual.unit};
1✔
84
}
1✔
85

86
template <typename Impl>
87
void SetupContext::disconnect_cable_impl(const Process::Cable& c, Impl&& impl)
76✔
88
{
89
  if(!context.created) {
76✔
90
    return;
56✔
91
  }
92
  auto it = m_cables.find(c.id());
20✔
93
  if(it != m_cables.end())
20✔
94
  {
95
    impl([cable = it->second, graph = context.execGraph] {
40✔
96
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
20✔
97
      graph->disconnect(cable);
20✔
98
    });
20✔
99
    // The edge is gone from the graph: a later connectCable() for the same
100
    // id makes a new one, and whoever asks whether the cable is wired up
101
    // (a node rebuilding its ports) must not find this one.
102
    m_cables.erase(it);
20✔
103
  }
20✔
104
}
76✔
105

106
template <typename Impl>
107
void SetupContext::connect_cable_impl(Process::Cable& cable, Impl&& impl)
84✔
108
{
109
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
84✔
110
  if(!context.created) {
84✔
111
    return;
53✔
112
  }
113
  ossia::node_ptr source_node{}, sink_node{};
31✔
114
  ossia::outlet_ptr source_port{};
31✔
115
  ossia::inlet_ptr sink_port{};
31✔
116
  if(auto port_src = cable.source().try_find(context.doc))
31✔
117
  {
118
    auto it = outlets.find(port_src);
31✔
119
    if(it != outlets.end())
31✔
120
    {
121
      source_node = it->second.first;
31✔
122
      source_port = it->second.second;
31✔
123
    }
31✔
124
  }
31✔
125
  if(auto port_snk = cable.sink().try_find(context.doc))
31✔
126
  {
127
    auto it = inlets.find(port_snk);
31✔
128
    if(it != inlets.end())
31✔
129
    {
130
      sink_node = it->second.first;
31✔
131
      sink_port = it->second.second;
31✔
132
    }
31✔
133
  }
31✔
134

135
  if(source_node && sink_node && source_port && sink_port)
31✔
136
  {
137
    ossia::edge_ptr edge;
31✔
138
    switch(cable.type())
31✔
139
    {
140
      case Process::CableType::ImmediateStrict: {
141
        edge = context.execGraph->allocate_edge(
×
142
            ossia::immediate_strict_connection{}, std::move(source_port),
×
143
            std::move(sink_port), std::move(source_node), std::move(sink_node));
144
        break;
145
      }
146
      case Process::CableType::ImmediateGlutton: {
147
        edge = context.execGraph->allocate_edge(
62✔
148
            ossia::immediate_glutton_connection{}, std::move(source_port),
31✔
149
            std::move(sink_port), std::move(source_node), std::move(sink_node));
31✔
150
        break;
31✔
151
      }
152
      case Process::CableType::DelayedStrict: {
153
        edge = context.execGraph->allocate_edge(
×
154
            ossia::delayed_strict_connection{}, std::move(source_port),
×
155
            std::move(sink_port), std::move(source_node), std::move(sink_node));
156
        break;
157
      }
158
      case Process::CableType::DelayedGlutton: {
159
        edge = context.execGraph->allocate_edge(
×
160
            ossia::delayed_glutton_connection{}, std::move(source_port),
×
161
            std::move(sink_port), std::move(source_node), std::move(sink_node));
162
        break;
163
      }
164
    }
165

166
    m_cables[cable.id()] = edge;
31✔
167
    impl([edge, graph = context.execGraph]() mutable {
62✔
168
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
31✔
169
      graph->connect(std::move(edge));
31✔
170
    });
31✔
171
  }
31✔
172
}
84✔
173

174
// Pushed once, when the node is registered; the address machinery never touches
175
// `type` afterwards.
176
template <typename T, typename Impl>
177
static void set_declared_unit_impl(
2,419✔
178
    const Process::Port& proc_port, const T& port, Impl&& append)
179
{
180
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
2,419✔
181
  const ossia::unit_t& u = proc_port.unit().get();
2,419✔
182
  if(!u)
2,419✔
183
    return;
2,402✔
184

185
  append([port, u] {
34✔
186
    OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
17✔
187
    if(ossia::value_port* dat = port->template target<ossia::value_port>())
17✔
188
    {
189
      // A unit the node declared is more precise than the widget's and wins; a
190
      // plain value type does not.
191
      if(!dat->type.target<ossia::unit_t>())
17✔
192
        dat->type = u;
×
193
    }
17✔
194
  });
17✔
195
}
2,419✔
196

197
template <typename Impl>
198
void SetupContext::register_inlet_impl(
1,937✔
199
    Process::Inlet& proc_port, const ossia::inlet_ptr& ossia_port,
200
    const std::shared_ptr<ossia::graph_node>& node, Impl&& impl)
201
{
202
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
1,937✔
203
  SCORE_ASSERT(node);
1,937✔
204
  SCORE_ASSERT(ossia_port);
1,937✔
205

206
  auto& runtime_connection = runtime_connections[node].inlets;
1,937✔
207
  auto& con = runtime_connection[proc_port.id()];
1,937✔
208
  QObject::disconnect(con);
1,937✔
209
  con = connect(
1,937✔
210
      &proc_port, &Process::Port::addressChanged, this,
1,937✔
211
      [this, ossia_port](const State::AddressAccessor& address) {
1,937✔
212
    OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
213
    set_destination(address, ossia_port);
×
214
  });
×
215
  set_declared_unit_impl(proc_port, ossia_port, impl);
1,937✔
216

217
  // Also registers the port with the execution state, once, when the address
218
  // resolves.
219
  set_destination_impl(context, proc_port.address(), ossia_port, impl);
1,937✔
220

221
  inlets.insert({&proc_port, std::make_pair(node, ossia_port)});
1,937✔
222
}
1,937✔
223

224
template <typename Impl>
225
void SetupContext::register_node_impl(
402✔
226
    const Process::Inlets& proc_inlets, const Process::Outlets& proc_outlets,
227
    const std::shared_ptr<ossia::graph_node>& node, Impl&& exec)
228
{
229
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
402✔
230
  if(node)
402✔
231
  {
232
    std::weak_ptr<ossia::graph_interface> wg = context.execGraph;
402✔
233
    exec([wg, node = node]() mutable {
804✔
234
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
402✔
235
      if(auto g = wg.lock())
804✔
236
        g->add_node(std::move(node));
402✔
237
    });
402✔
238

239
    const std::size_t proc_n_inlets = proc_inlets.size();
402✔
240
    const std::size_t proc_n_outlets = proc_outlets.size();
402✔
241

242
    const std::size_t ossia_n_inlets = node->root_inputs().size();
402✔
243
    const std::size_t ossia_n_outlets = node->root_outputs().size();
402✔
244

245
    std::size_t n_inlets = std::min(proc_n_inlets, ossia_n_inlets);
402✔
246
    std::size_t n_outlets = std::min(proc_n_outlets, ossia_n_outlets);
402✔
247

248
    for(std::size_t i = 0; i < n_inlets; i++)
1,425✔
249
    {
250
      register_inlet_impl(*proc_inlets[i], node->root_inputs()[i], node, exec);
1,023✔
251
    }
1,023✔
252

253
    for(std::size_t i = 0; i < n_outlets; i++)
787✔
254
    {
255
      register_outlet_impl(*proc_outlets[i], node->root_outputs()[i], node, exec);
385✔
256
    }
385✔
257
  }
402✔
258
}
402✔
259

260
void SetupContext::register_node(
210✔
261
    const Process::ProcessModel& proc, const std::shared_ptr<ossia::graph_node>& node)
262
{
263
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
210✔
264
  register_node(proc.inlets(), proc.outlets(), node);
210✔
265
  proc_map[node.get()] = &proc;
210✔
266
}
210✔
267

268
void SetupContext::unregister_node(
210✔
269
    const Process::ProcessModel& proc, const std::shared_ptr<ossia::graph_node>& node)
270
{
271
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
210✔
272
  unregister_node(proc.inlets(), proc.outlets(), node);
210✔
273
  proc_map.erase(node.get());
210✔
274
}
210✔
275

276
void SetupContext::register_node(
×
277
    const Process::ProcessModel& proc, const std::shared_ptr<ossia::graph_node>& node,
278
    Transaction& vec)
279
{
280
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
281
  register_node(proc.inlets(), proc.outlets(), node, vec);
×
282
  proc_map[node.get()] = &proc;
×
283
}
×
284

285
void SetupContext::unregister_node(
×
286
    const Process::ProcessModel& proc, const std::shared_ptr<ossia::graph_node>& node,
287
    Transaction& vec)
288
{
289
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
290
  unregister_node(proc.inlets(), proc.outlets(), node, vec);
×
291
  proc_map.erase(node.get());
×
292
}
×
293

294
template <typename T, typename Impl>
295
void set_destination_impl(
2,419✔
296
    const Context& plug, const State::AddressAccessor& address, const T& port,
297
    Impl&& append)
298
{
299
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
2,419✔
300
  auto& s = plug.execState;
2,419✔
301
  auto& g = plug.execGraph;
2,419✔
302
  if(!g)
2,419✔
303
    return;
×
304

305
  if(address.address.device.isEmpty())
2,419✔
306
  {
307
    append([ws = std::weak_ptr{s}, port, wg = std::weak_ptr{g}] {
4,702✔
308
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
2,351✔
309
      auto s = ws.lock();
2,351✔
310
      if(!s)
2,351✔
311
        return;
×
312
      auto g = wg.lock();
2,351✔
313
      if(!g)
2,351✔
314
        return;
×
315
      if(port->address)
2,351✔
316
      {
317
        s->unregister_port(*port);
×
318
        port->address = {};
×
319
        if(ossia::value_port* dat = port->template target<ossia::value_port>())
×
320
        {
321
          dat->address_unit = {};
×
322
          dat->index = {};
×
323
        }
×
324
        g->mark_dirty();
×
325
      }
×
326
    });
2,351✔
327
    return;
2,351✔
328
  }
329

330
  auto& qual = address.qualifiers.get();
68✔
331
  if(auto n = findNode(*plug.execState, address.address))
68✔
332
  {
333
    auto p = n->get_parameter();
68✔
334
    if(p)
68✔
335
    {
336
      append([ws = std::weak_ptr{s}, port, p, qual = qual, wg = std::weak_ptr{g}] {
136✔
337
        OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
68✔
338
        auto s = ws.lock();
68✔
339
        if(!s)
68✔
340
          return;
×
341
        auto g = wg.lock();
68✔
342
        if(!g)
68✔
343
          return;
×
344
        s->unregister_port(*port);
68✔
345
        port->address = p;
68✔
346
        if(ossia::value_port* dat = port->template target<ossia::value_port>())
68✔
347
        {
348
          // Unconditionally, like the index: dropping the qualifier has to give
349
          // the process's declaration back.
350
          dat->address_unit = qual.unit;
×
351
          dat->index = qual.accessors;
×
352
        }
×
353
        s->register_port(*port);
68✔
354
        g->mark_dirty();
68✔
355
      });
68✔
356
    }
68✔
357
    else
358
    {
359
      append([ws = std::weak_ptr{s}, n, port, wg = std::weak_ptr{g}] {
×
360
        auto s = ws.lock();
×
361
        if(!s)
×
362
          return;
×
363
        auto g = wg.lock();
×
364
        if(!g)
×
365
          return;
×
366
        OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
367
        s->unregister_port(*port);
×
368
        port->address = n;
×
369
        s->register_port(*port);
×
370
        g->mark_dirty();
×
371
      });
×
372
    }
373
  }
68✔
374
  else if(auto ad = address.address.toString_unsafe().toStdString();
×
375
          ossia::traversal::is_pattern(ad))
×
376
  {
377
    // OPTIMIZEME
378
    auto path = ossia::traversal::make_path(ad);
×
379
    if(path)
×
380
    {
381
      append([ws = std::weak_ptr{s}, p = *path, port, wg = std::weak_ptr{g}]() mutable {
×
382
        OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
383
        auto s = ws.lock();
×
384
        if(!s)
×
385
          return;
×
386
        auto g = wg.lock();
×
387
        if(!g)
×
388
          return;
×
389
        s->unregister_port(*port);
×
390
        port->address = std::move(p);
×
391
        if(ossia::value_port* dat = port->template target<ossia::value_port>())
×
392
        {
393
          dat->address_unit = {};
×
394
          dat->index.clear();
×
395
        }
×
396
        s->register_port(*port);
×
397
        g->mark_dirty();
×
398
      });
×
399
    }
×
400
    else
401
    {
402
      append([ws = std::weak_ptr{s}, n, port, wg = std::weak_ptr{g}] {
×
403
        OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
404
        auto s = ws.lock();
×
405
        if(!s)
×
406
          return;
×
407
        auto g = wg.lock();
×
408
        if(!g)
×
409
          return;
×
410
        s->unregister_port(*port);
×
411
        port->address = {};
×
412
        if(ossia::value_port* dat = port->template target<ossia::value_port>())
×
413
        {
414
          dat->address_unit = {};
×
415
          dat->index.clear();
×
416
        }
×
417
        s->register_port(*port);
×
418
        g->mark_dirty();
×
419
      });
×
420
    }
421
  }
×
422
}
2,419✔
423

424
void SetupContext::set_destination(
×
425
    const State::AddressAccessor& address, const ossia::inlet_ptr& port)
426
{
427
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
428
  set_destination_impl(context, address, port, enqueue_in_context(*this));
×
429
}
×
430

431
void SetupContext::set_destination(
×
432
    const State::AddressAccessor& address, const ossia::outlet_ptr& port)
433
{
434
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
435
  set_destination_impl(context, address, port, enqueue_in_context(*this));
×
436
}
×
437

438
void SetupContext::register_inlet(
×
439
    Process::Inlet& inlet, const ossia::inlet_ptr& exec,
440
    const std::shared_ptr<ossia::graph_node>& node)
441
{
442
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
443
  register_inlet_impl(inlet, exec, node, enqueue_in_context(*this));
×
444
}
×
445
void SetupContext::register_outlet(
×
446
    Process::Outlet& outlet, const ossia::outlet_ptr& exec,
447
    const std::shared_ptr<ossia::graph_node>& node)
448
{
449
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
450
  register_outlet_impl(outlet, exec, node, enqueue_in_context(*this));
×
451
}
×
452

453
void SetupContext::register_node(
350✔
454
    const Process::Inlets& proc_inlets, const Process::Outlets& proc_outlets,
455
    const std::shared_ptr<ossia::graph_node>& node)
456
{
457
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
350✔
458
  register_node_impl(proc_inlets, proc_outlets, node, enqueue_in_context(*this));
350✔
459
}
350✔
460

461
void SetupContext::register_node(
52✔
462
    const Process::Inlets& proc_inlets, const Process::Outlets& proc_outlets,
463
    const std::shared_ptr<ossia::graph_node>& node, Transaction& vec)
464
{
465
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
52✔
466
  register_node_impl(proc_inlets, proc_outlets, node, enqueue_in_vector(vec));
52✔
467
}
52✔
468

469
void SetupContext::register_inlet(
616✔
470
    Process::Inlet& inlet, const ossia::inlet_ptr& exec,
471
    const std::shared_ptr<ossia::graph_node>& node, Transaction& vec)
472
{
473
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
616✔
474
  register_inlet_impl(inlet, exec, node, enqueue_in_vector(vec));
616✔
475
}
616✔
476
void SetupContext::register_outlet(
97✔
477
    Process::Outlet& outlet, const ossia::outlet_ptr& exec,
478
    const std::shared_ptr<ossia::graph_node>& node, Transaction& vec)
479
{
480
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
97✔
481
  register_outlet_impl(outlet, exec, node, enqueue_in_vector(vec));
97✔
482
}
97✔
483

484
void SetupContext::on_cableCreated(Process::Cable& c)
59✔
485
{
486
  connectCable(c);
59✔
487
}
59✔
488

489
void SetupContext::on_cableRemoved(const Process::Cable& c)
60✔
490
{
491
  removeCable(c);
60✔
492
}
60✔
493

494
void SetupContext::connectCable(Process::Cable& c)
59✔
495
{
496
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
59✔
497
  connect_cable_impl(c, enqueue_in_context(*this));
59✔
498
}
59✔
499

500
void SetupContext::connectCable(Process::Cable& c, Transaction& vec)
25✔
501
{
502
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
25✔
503
  connect_cable_impl(c, enqueue_in_vector(vec));
25✔
504
}
25✔
505

506
void SetupContext::removeCable(const Process::Cable& c)
60✔
507
{
508
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
60✔
509
  disconnect_cable_impl(c, enqueue_in_context(*this));
60✔
510
}
60✔
511

512
void SetupContext::removeCable(const Process::Cable& c, Transaction& vec)
16✔
513
{
514
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
16✔
515
  disconnect_cable_impl(c, enqueue_in_vector(vec));
16✔
516
}
16✔
517

518
template <typename Impl>
519
void SetupContext::register_outlet_impl(
482✔
520
    Process::Outlet& proc_port, const ossia::outlet_ptr& ossia_port,
521
    const std::shared_ptr<ossia::graph_node>& node, Impl&& impl)
522
{
523
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
482✔
524
  SCORE_ASSERT(node);
482✔
525
  SCORE_ASSERT(ossia_port);
482✔
526
  auto& runtime_connection = runtime_connections[node].outlets;
482✔
527
  auto& con = runtime_connection[proc_port.id()];
482✔
528
  QObject::disconnect(con);
482✔
529
  con = connect(
482✔
530
      &proc_port, &Process::Port::addressChanged, this,
482✔
531
      [this, ossia_port](const State::AddressAccessor& address) {
482✔
532
    OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
533
    set_destination(address, ossia_port);
×
534
  });
×
535
  set_declared_unit_impl(proc_port, ossia_port, impl);
482✔
536

537
  set_destination_impl(context, proc_port.address(), ossia_port, impl);
482✔
538

539
  outlets.insert({&proc_port, std::make_pair(node, ossia_port)});
482✔
540

541
  proc_port.mapExecution(
964✔
542
      *ossia_port, [&](Process::Inlet& model_inl, ossia::inlet& ossia_inl) {
780✔
543
        register_inlet_impl(model_inl, &ossia_inl, node, impl);
298✔
544
      });
298✔
545

546
  // Unneeded : the execution_state only needs inlets to be registered,
547
  // in order to set up data value queues from the network thread
548

549
  // std::weak_ptr<ossia::execution_state> ws = context.execState;
550
  // impl([ws, ossia_port] {
551
  //   if (auto state = ws.lock())
552
  //     state->register_outlet(*ossia_port);
553
  // });
554
}
482✔
555

556
void SetupContext::unregister_inlet(
×
557
    const Process::Inlet& proc_port, const std::shared_ptr<ossia::graph_node>& node)
558
{
559
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
560
  if(node)
×
561
  {
562
    auto& runtime_connection = runtime_connections[node].inlets;
×
563
    auto it = runtime_connection.find(proc_port.id());
×
564
    if(it != runtime_connection.end())
×
565
    {
566
      QObject::disconnect(it->second);
×
567
      runtime_connection.erase(it);
×
568
    }
×
569

570
    auto ossia_port_it = inlets.find(const_cast<Process::Inlet*>(&proc_port));
×
571
    if(ossia_port_it != inlets.end())
×
572
    {
573
      std::weak_ptr<ossia::execution_state> ws = context.execState;
×
574
      context.executionQueue.enqueue([ws, ossia_port = ossia_port_it->second.second] {
×
575
        OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
576
        if(auto state = ws.lock())
×
577
          state->unregister_port(*ossia_port);
×
578
      });
×
579

580
      inlets.erase(ossia_port_it);
×
581
    }
×
582
  }
×
583
  else
584
  {
585
    inlets.erase(const_cast<Process::Inlet*>(&proc_port));
×
586
  }
587
}
×
588

589
void SetupContext::unregister_outlet(
×
590
    const Process::Outlet& proc_port, const std::shared_ptr<ossia::graph_node>& node)
591
{
592
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
593
  if(node)
×
594
  {
595
    auto& runtime_connection = runtime_connections[node].outlets;
×
596
    auto it = runtime_connection.find(proc_port.id());
×
597
    if(it != runtime_connection.end())
×
598
    {
599
      QObject::disconnect(it->second);
×
600
      runtime_connection.erase(it);
×
601
    }
×
602

603
    proc_port.forChildInlets([&](Process::Inlet& model_inl) {
×
604
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
605
      unregister_inlet(model_inl, node);
×
606
    });
×
607
  }
×
608

609
  outlets.erase(const_cast<Process::Outlet*>(&proc_port));
×
610
}
×
611

612
void SetupContext::unregister_inlet(
×
613
    const Process::Inlet& proc_port, const std::shared_ptr<ossia::graph_node>& node,
614
    Transaction& commands)
615
{
616
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
617
  if(node)
×
618
  {
619
    auto& runtime_connection = runtime_connections[node].inlets;
×
620
    auto it = runtime_connection.find(proc_port.id());
×
621
    if(it != runtime_connection.end())
×
622
    {
623
      QObject::disconnect(it->second);
×
624
      runtime_connection.erase(it);
×
625
    }
×
626

627
    auto ossia_port_it = inlets.find(const_cast<Process::Inlet*>(&proc_port));
×
628
    if(ossia_port_it != inlets.end())
×
629
    {
630
      std::weak_ptr<ossia::execution_state> ws = context.execState;
×
631
      commands.push_back([ws, ossia_port = ossia_port_it->second.second] {
×
632
        OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
633
        if(auto state = ws.lock())
×
634
          state->unregister_port(*ossia_port);
×
635
      });
×
636

637
      inlets.erase(ossia_port_it);
×
638
    }
×
639
  }
×
640
  else
641
  {
642
    inlets.erase(const_cast<Process::Inlet*>(&proc_port));
×
643
  }
644
}
×
645

646
void SetupContext::unregister_outlet(
×
647
    const Process::Outlet& proc_port, const std::shared_ptr<ossia::graph_node>& node,
648
    Transaction& commands)
649
{
650
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
651
  if(node)
×
652
  {
653
    auto& runtime_connection = runtime_connections[node].outlets;
×
654
    auto it = runtime_connection.find(proc_port.id());
×
655
    if(it != runtime_connection.end())
×
656
    {
657
      QObject::disconnect(it->second);
×
658
      runtime_connection.erase(it);
×
659
    }
×
660

661
    proc_port.forChildInlets([&](Process::Inlet& model_inl) {
×
662
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
663
      unregister_inlet(model_inl, node);
×
664
    });
×
665
  }
×
666

667
  outlets.erase(const_cast<Process::Outlet*>(&proc_port));
×
668
}
×
669

670
void SetupContext::replace_node(
×
671
    const std::shared_ptr<ossia::time_process>& process,
672
    const std::shared_ptr<ossia::graph_node>& node, Transaction& commands)
673
{
674
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
675
  commands.push_back([p = process, n = node]() mutable {
×
676
    OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
677
    using namespace std;
678
    swap(p->node, n);
×
679
  });
×
680
}
×
681

682
void SetupContext::unregister_node(
318✔
683
    const Process::Inlets& proc_inlets, const Process::Outlets& proc_outlets,
684
    const std::shared_ptr<ossia::graph_node>& node)
685
{
686
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
318✔
687
  if(node)
318✔
688
  {
689
    std::weak_ptr<ossia::graph_interface> wg = context.execGraph;
318✔
690
    std::weak_ptr<ossia::execution_state> ws = context.execState;
318✔
691
    context.executionQueue.enqueue([wg, ws, node = node] mutable {
510✔
692
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
192✔
693
      if(auto s = ws.lock())
384✔
694
      {
695
        ossia::for_each_inlet(*node, [&](auto& p) { s->unregister_port(p); });
1,098✔
696
        ossia::for_each_outlet(*node, [&](auto& p) { s->unregister_port(p); });
469✔
697
      }
192✔
698

699
      if(auto g = wg.lock())
384✔
700
        g->remove_node(node);
192✔
701

702
      node->clear();
192✔
703
    });
192✔
704

705
    runtime_connections[node].clear();
318✔
706
    runtime_connections.erase(node);
318✔
707

708
    proc_map.erase(node.get());
318✔
709
  }
318✔
710

711
  for(auto ptr : proc_inlets)
1,328✔
712
    inlets.erase(ptr);
1,010✔
713
  for(auto ptr : proc_outlets)
681✔
714
    outlets.erase(ptr);
363✔
715
}
318✔
716

717
void SetupContext::unregister_node(
×
718
    const Process::Inlets& proc_inlets, const Process::Outlets& proc_outlets,
719
    const std::shared_ptr<ossia::graph_node>& node, Transaction& vec)
720
{
721
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
×
722
  if(node)
×
723
  {
724
    std::weak_ptr<ossia::graph_interface> wg = context.execGraph;
×
725
    std::weak_ptr<ossia::execution_state> ws = context.execState;
×
726
    vec.push_back([wg, ws, node] {
×
727
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
728
      if(auto s = ws.lock())
×
729
      {
730
        ossia::for_each_inlet(*node, [&](auto& p) { s->unregister_port(p); });
×
731
        ossia::for_each_outlet(*node, [&](auto& p) { s->unregister_port(p); });
×
732
      }
×
733

734
      if(auto g = wg.lock())
×
735
        g->remove_node(node);
×
736
      node->clear();
×
737
    });
×
738

739
    runtime_connections[node].clear();
×
740
    runtime_connections.erase(node);
×
741

742
    proc_map.erase(node.get());
×
743
  }
×
744

745
  for(auto ptr : proc_inlets)
×
746
    inlets.erase(ptr);
×
747
  for(auto ptr : proc_outlets)
×
748
    outlets.erase(ptr);
×
749
}
×
750

751
void SetupContext::unregister_node_soft(
63✔
752
    const Process::Inlets& proc_inlets, const Process::Outlets& proc_outlets,
753
    const std::shared_ptr<ossia::graph_node>& node, Transaction& vec)
754
{
755
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
63✔
756
  if(node)
63✔
757
  {
758
    std::weak_ptr<ossia::execution_state> ws = context.execState;
63✔
759
    vec.push_back([ws, node] {
126✔
760
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
63✔
761
      if(auto s = ws.lock())
126✔
762
      {
763
        ossia::for_each_inlet(*node, [&](auto& p) { s->unregister_port(p); });
702✔
764
        ossia::for_each_outlet(*node, [&](auto& p) { s->unregister_port(p); });
154✔
765
      }
63✔
766
    });
63✔
767
    runtime_connections[node].clear();
63✔
768
    runtime_connections.erase(node);
63✔
769

770
    proc_map.erase(node.get());
63✔
771
  }
63✔
772

773
  for(auto ptr : proc_inlets)
664✔
774
    inlets.erase(ptr);
601✔
775
  for(auto ptr : proc_outlets)
154✔
776
    outlets.erase(ptr);
91✔
777
}
63✔
778

779
SetupContext::SetupContext(Context& other) noexcept
1,967✔
780
    : context{other}
1,967✔
781
{
3,934✔
782
}
1,967✔
783

784
SetupContext::~SetupContext() { }
1,956✔
785

786
}
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