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

ossia / score / 34039060546

06 Sep 2026 02:24PM UTC coverage: 26.369% (+1.8%) from 24.579%
34039060546

push

github

jcelerier
3rdparty: updat libossia

60871 of 230846 relevant lines covered (26.37%)

63602.32 hits per line

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

49.9
/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)
241✔
30
  {
31
    static_assert(std::is_nothrow_move_constructible_v<F>);
32
    OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
241✔
33
    self.context.executionQueue.enqueue(std::move(f));
241✔
34
  }
241✔
35
};
36
struct VectorEnqueuer
37
{
38
  Transaction& vec;
39
  template <typename F>
40
  void operator()(F&& f)
831✔
41
  {
42
    static_assert(std::is_nothrow_move_constructible_v<F>);
43
    OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
831✔
44
    vec.push_back(std::move(f));
831✔
45
  }
831✔
46
};
47

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

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

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

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

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

86
template <typename Impl>
87
void SetupContext::disconnect_cable_impl(const Process::Cable& c, Impl&& impl)
50✔
88
{
89
  if(!context.created) {
50✔
90
    return;
31✔
91
  }
92
  auto it = m_cables.find(c.id());
19✔
93
  if(it != m_cables.end())
19✔
94
  {
95
    impl([cable = it->second, graph = context.execGraph] {
38✔
96
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
19✔
97
      graph->disconnect(cable);
19✔
98
    });
19✔
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);
19✔
103
  }
19✔
104
}
50✔
105

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

135
  if(source_node && sink_node && source_port && sink_port)
26✔
136
  {
137
    ossia::edge_ptr edge;
26✔
138
    switch(cable.type())
26✔
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(
52✔
148
            ossia::immediate_glutton_connection{}, std::move(source_port),
26✔
149
            std::move(sink_port), std::move(source_node), std::move(sink_node));
26✔
150
        break;
26✔
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;
26✔
167
    impl([edge, graph = context.execGraph]() mutable {
52✔
168
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
26✔
169
      graph->connect(std::move(edge));
26✔
170
    });
26✔
171
  }
26✔
172
}
54✔
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(
969✔
178
    const Process::Port& proc_port, const T& port, Impl&& append)
179
{
180
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
969✔
181
  const ossia::unit_t& u = proc_port.unit().get();
969✔
182
  if(!u)
969✔
183
    return;
969✔
184

185
  append([port, u] {
×
186
    OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
187
    if(ossia::value_port* dat = port->template target<ossia::value_port>())
×
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>())
×
192
        dat->type = u;
×
193
    }
×
194
  });
×
195
}
969✔
196

197
template <typename Impl>
198
void SetupContext::register_inlet_impl(
831✔
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);
831✔
203
  SCORE_ASSERT(node);
831✔
204
  SCORE_ASSERT(ossia_port);
831✔
205

206
  auto& runtime_connection = runtime_connections[node].inlets;
831✔
207
  auto& con = runtime_connection[proc_port.id()];
831✔
208
  QObject::disconnect(con);
831✔
209
  con = connect(
831✔
210
      &proc_port, &Process::Port::addressChanged, this,
831✔
211
      [this, ossia_port](const State::AddressAccessor& address) {
831✔
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);
831✔
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);
831✔
220

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

224
template <typename Impl>
225
void SetupContext::register_node_impl(
68✔
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);
68✔
230
  if(node)
68✔
231
  {
232
    std::weak_ptr<ossia::graph_interface> wg = context.execGraph;
68✔
233
    exec([wg, node = node]() mutable {
136✔
234
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
68✔
235
      if(auto g = wg.lock())
136✔
236
        g->add_node(std::move(node));
68✔
237
    });
68✔
238

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

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

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

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

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

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

268
void SetupContext::unregister_node(
28✔
269
    const Process::ProcessModel& proc, const std::shared_ptr<ossia::graph_node>& node)
270
{
271
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
28✔
272
  unregister_node(proc.inlets(), proc.outlets(), node);
28✔
273
  proc_map.erase(node.get());
28✔
274
}
28✔
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(
969✔
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);
969✔
300
  auto& s = plug.execState;
969✔
301
  auto& g = plug.execGraph;
969✔
302
  if(!g)
969✔
303
    return;
×
304

305
  if(address.address.device.isEmpty())
969✔
306
  {
307
    append([ws = std::weak_ptr{s}, port, wg = std::weak_ptr{g}] {
1,918✔
308
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
959✔
309
      auto s = ws.lock();
959✔
310
      if(!s)
959✔
311
        return;
×
312
      auto g = wg.lock();
959✔
313
      if(!g)
959✔
314
        return;
×
315
      if(port->address)
959✔
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
    });
959✔
327
    return;
959✔
328
  }
329

330
  auto& qual = address.qualifiers.get();
10✔
331
  if(auto n = findNode(*plug.execState, address.address))
10✔
332
  {
333
    auto p = n->get_parameter();
×
334
    if(p)
×
335
    {
336
      append([ws = std::weak_ptr{s}, port, p, qual = qual, wg = std::weak_ptr{g}] {
×
337
        OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
×
338
        auto s = ws.lock();
×
339
        if(!s)
×
340
          return;
×
341
        auto g = wg.lock();
×
342
        if(!g)
×
343
          return;
×
344
        s->unregister_port(*port);
×
345
        port->address = p;
×
346
        if(ossia::value_port* dat = port->template target<ossia::value_port>())
×
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);
×
354
        g->mark_dirty();
×
355
      });
×
356
    }
×
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
  }
×
374
  else if(auto ad = address.address.toString_unsafe().toStdString();
10✔
375
          ossia::traversal::is_pattern(ad))
20✔
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
}
969✔
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(
58✔
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);
58✔
458
  register_node_impl(proc_inlets, proc_outlets, node, enqueue_in_context(*this));
58✔
459
}
58✔
460

461
void SetupContext::register_node(
10✔
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);
10✔
466
  register_node_impl(proc_inlets, proc_outlets, node, enqueue_in_vector(vec));
10✔
467
}
10✔
468

469
void SetupContext::register_inlet(
612✔
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);
612✔
474
  register_inlet_impl(inlet, exec, node, enqueue_in_vector(vec));
612✔
475
}
612✔
476
void SetupContext::register_outlet(
96✔
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);
96✔
481
  register_outlet_impl(outlet, exec, node, enqueue_in_vector(vec));
96✔
482
}
96✔
483

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

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

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

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

506
void SetupContext::removeCable(const Process::Cable& c)
34✔
507
{
508
  OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Ui);
34✔
509
  disconnect_cable_impl(c, enqueue_in_context(*this));
34✔
510
}
34✔
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(
138✔
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);
138✔
524
  SCORE_ASSERT(node);
138✔
525
  SCORE_ASSERT(ossia_port);
138✔
526
  auto& runtime_connection = runtime_connections[node].outlets;
138✔
527
  auto& con = runtime_connection[proc_port.id()];
138✔
528
  QObject::disconnect(con);
138✔
529
  con = connect(
138✔
530
      &proc_port, &Process::Port::addressChanged, this,
138✔
531
      [this, ossia_port](const State::AddressAccessor& address) {
138✔
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);
138✔
536

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

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

541
  proc_port.mapExecution(
276✔
542
      *ossia_port, [&](Process::Inlet& model_inl, ossia::inlet& ossia_inl) {
232✔
543
        register_inlet_impl(model_inl, &ossia_inl, node, impl);
94✔
544
      });
94✔
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
}
138✔
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(
38✔
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);
38✔
687
  if(node)
38✔
688
  {
689
    std::weak_ptr<ossia::graph_interface> wg = context.execGraph;
38✔
690
    std::weak_ptr<ossia::execution_state> ws = context.execState;
38✔
691
    context.executionQueue.enqueue([wg, ws, node = node] mutable {
40✔
692
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
2✔
693
      if(auto s = ws.lock())
4✔
694
      {
695
        ossia::for_each_inlet(*node, [&](auto& p) { s->unregister_port(p); });
7✔
696
        ossia::for_each_outlet(*node, [&](auto& p) { s->unregister_port(p); });
4✔
697
      }
2✔
698

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

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

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

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

711
  for(auto ptr : proc_inlets)
168✔
712
    inlets.erase(ptr);
130✔
713
  for(auto ptr : proc_outlets)
76✔
714
    outlets.erase(ptr);
38✔
715
}
38✔
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(
62✔
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);
62✔
756
  if(node)
62✔
757
  {
758
    std::weak_ptr<ossia::execution_state> ws = context.execState;
62✔
759
    vec.push_back([ws, node] {
124✔
760
      OSSIA_ENSURE_CURRENT_THREAD_KIND(ossia::thread_type::Audio);
62✔
761
      if(auto s = ws.lock())
124✔
762
      {
763
        ossia::for_each_inlet(*node, [&](auto& p) { s->unregister_port(p); });
697✔
764
        ossia::for_each_outlet(*node, [&](auto& p) { s->unregister_port(p); });
152✔
765
      }
62✔
766
    });
62✔
767
    runtime_connections[node].clear();
62✔
768
    runtime_connections.erase(node);
62✔
769

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

773
  for(auto ptr : proc_inlets)
659✔
774
    inlets.erase(ptr);
597✔
775
  for(auto ptr : proc_outlets)
152✔
776
    outlets.erase(ptr);
90✔
777
}
62✔
778

779
SetupContext::SetupContext(Context& other) noexcept
829✔
780
    : context{other}
829✔
781
{
1,658✔
782
}
829✔
783

784
SetupContext::~SetupContext() { }
829✔
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