Loading...
Searching...
No Matches
ProcessModelPortInit.hpp
1#pragma once
2#include <Process/Dataflow/Port.hpp>
3#include <Process/Dataflow/PortFactory.hpp>
4#include <Process/Process.hpp>
5
6#include <Crousti/Concepts.hpp>
7#include <Crousti/SceneConcepts.hpp>
8#include <Media/Sound/Drop/SoundDrop.hpp>
9
10#include <avnd/binding/ossia/port_base.hpp>
11#include <avnd/concepts/all.hpp>
12#if SCORE_PLUGIN_GFX
13#include <Gfx/TexturePort.hpp>
14#endif
15
16namespace oscr
17{
18template <typename Info>
19class ProcessModel;
20}
21
22namespace oscr
23{
24
25template <typename T>
26static AVND_INLINE QString portName()
27{
28 //FIXME
29#if !defined(__APPLE__)
30 static constexpr auto name = avnd::get_name<T>();
31 return fromStringView(name);
32#else
33 auto name = avnd::get_name<T>();
34 return fromStringView(name);
35#endif
36}
37
38template <typename T>
39inline void setupNewPort(Process::Port* obj)
40{
41 if constexpr(avnd::has_description<T>)
42 obj->setDescription(fromStringView(avnd::get_description<T>()));
43}
44
45template <std::size_t N, typename T>
46inline void setupNewPort(const avnd::field_reflection<N, T>& spec, Process::Port* obj)
47{
48 setupNewPort<T>(obj);
49}
50
51template <typename T>
52inline void setupNewPort(const T& spec, Process::Port* obj)
53{
54 setupNewPort<T>(obj);
55}
56
57template <typename Node>
59{
61 Process::Inlets& ins;
62 int inlet = 0;
63
64 template <oscr::ossia_value_port T>
65 void operator()(const T& in, auto idx)
66 {
67 auto p = new Process::ValueInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
68 setupNewPort(in, p);
69 ins.push_back(p);
70 }
71 template <oscr::ossia_audio_port T>
72 void operator()(const T& in, auto idx)
73 {
74 auto p = new Process::AudioInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
75 setupNewPort(in, p);
76 ins.push_back(p);
77 }
78 template <oscr::ossia_midi_port T>
79 void operator()(const T& in, auto idx)
80 {
81 auto p = new Process::MidiInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
82 setupNewPort(in, p);
83 ins.push_back(p);
84 }
85
86 template <avnd::audio_port T>
87 void operator()(const T& in, auto idx)
88 {
89 auto p = new Process::AudioInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
90 setupNewPort(in, p);
91 ins.push_back(p);
92 }
93 template <avnd::midi_port T>
94 void operator()(const T& in, auto idx)
95 {
96 auto p = new Process::MidiInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
97 setupNewPort(in, p);
98 ins.push_back(p);
99 }
100
101 static QString toFilters(const QSet<QString>& exts)
102 {
103 QString res;
104 for(const auto& s : exts)
105 {
106 res += "*.";
107 res += s;
108 res += " ";
109 }
110 if(!res.isEmpty())
111 res.resize(res.size() - 1);
112 return res;
113 }
114
115 template <typename P>
116 static QString getFilters(P& p)
117 {
118 if constexpr(requires { P::filters(); })
119 {
120 using filter = decltype(P::filters());
121 if constexpr(requires { filter::sound; } || requires { filter::audio; })
122 {
123 return QString{"Sound files (%1)"}.arg(
124 toFilters(Media::Sound::DropHandler{}.fileExtensions()));
125 }
126 else if constexpr(requires { filter::video; })
127 {
128 // FIXME refactor supported formats with Video process
129 QSet<QString> files = {"mkv", "mov", "mp4", "h264", "avi", "hap", "mpg", "mpeg",
130 "imf", "mxf", "mts", "m2ts", "mj2", "webm", "y4m", "nut", "ts"};
131 return QString{"Videos (%1)"}.arg(toFilters(files));
132 }
133 else if constexpr(requires { filter::image; })
134 {
135 // FIXME refactor supported formats with Image List Chooser
136 return QString{"Images (*.png *.jpg *.jpeg *.gif *.bmp *.tiff)"};
137 }
138 else if constexpr(requires { filter::midi; })
139 {
140 return "MIDI (*.mid)";
141 }
142 else if constexpr(avnd::string_ish<filter>)
143 {
144 static constexpr auto text_filters = P::filters();
145 return fromStringView(P::filters());
146 }
147 else
148 {
149 return "";
150 }
151 }
152 else if constexpr(requires { P::extensions(); })
153 {
154 static constexpr auto text_filters = P::extensions();
155 return fromStringView(text_filters);
156 }
157 else
158 {
159 return "";
160 }
161 }
162
163 template <avnd::soundfile_port T>
164 void operator()(const T& in, auto idx)
165 {
166 static constexpr auto name = avnd::get_name<T>();
168 if constexpr(requires { T::waveform; })
169 {
171 "", getFilters(in), QString::fromUtf8(name.data(), name.size()),
172 Id<Process::Port>(inlet++), &self};
173 }
174 else
175 {
176 p = new Process::FileChooser{
177 "", getFilters(in), QString::fromUtf8(name.data(), name.size()),
178 Id<Process::Port>(inlet++), &self};
179 }
180
181 p->displayHandledExplicitly = true;
182 ins.push_back(p);
183
184 if constexpr(avnd::tag_file_watch<T>)
185 {
186 p->enableFileWatch();
187 }
188 }
189
190 template <typename T>
191 requires avnd::midifile_port<T> || avnd::raw_file_port<T>
192 void operator()(const T& in, auto idx)
193 {
194 static constexpr auto name = avnd::get_name<T>();
195
196 auto p = new Process::FileChooser{
197 "", getFilters(in), QString::fromUtf8(name.data(), name.size()),
198 Id<Process::Port>(inlet++), &self};
199 p->displayHandledExplicitly = true;
200 ins.push_back(p);
201
202 if constexpr(avnd::tag_file_watch<T>)
203 {
204 p->enableFileWatch();
205 }
206 }
207
208 template <avnd::dynamic_ports_port T, std::size_t N>
209 void operator()(const T& in, avnd::field_index<N> i)
210 {
211 using port_type = typename decltype(in.ports)::value_type;
212 port_type p;
213 (*this)(p, i);
214 }
215
216 template <avnd::parameter_port T, std::size_t N>
217 requires(!oscr::ossia_port<T>)
218 void operator()(const T& in, avnd::field_index<N>)
219 {
220 if constexpr(avnd::has_widget<T> || avnd::curve_port<T>)
221 {
222 auto p = oscr::make_control_in<Node, T>(
223 avnd::field_index<N>{}, Id<Process::Port>(inlet), &self);
224 using port_ptr_type = std::decay_t<decltype(p)>;
225 if constexpr(!std::is_same_v<port_ptr_type, std::nullptr_t>)
226 {
227 if constexpr(
228 !std::is_same_v<port_ptr_type, Process::ControlInlet*>
229 && !std::is_same_v<port_ptr_type, Process::ValueInlet*>)
230 p->displayHandledExplicitly = true;
231
232 setupNewPort(in, p);
233 ins.push_back(p);
234 }
235 else
236 {
237 auto vp
238 = new Process::ValueInlet(portName<T>(), Id<Process::Port>(inlet), &self);
239 setupNewPort(in, vp);
240 ins.push_back(vp);
241 }
242 }
243 else
244 {
245 auto vp = new Process::ValueInlet(portName<T>(), Id<Process::Port>(inlet), &self);
246 setupNewPort(in, vp);
247 ins.push_back(vp);
248 }
249 inlet++;
250 }
251
252 template <avnd::buffer_port T>
253 void operator()(const T& in, auto idx)
254 {
255#if SCORE_PLUGIN_GFX
256 auto p = new Gfx::TextureInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
257 setupNewPort(in, p);
258 ins.push_back(p);
259#endif
260 }
261
262 template <avnd::texture_port T>
263 void operator()(const T& in, auto idx)
264 {
265#if SCORE_PLUGIN_GFX
266 auto p = new Gfx::TextureInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
267 setupNewPort(in, p);
268 ins.push_back(p);
269#endif
270 }
271
272 template <avnd::geometry_port T>
273 void operator()(const T& in, auto idx)
274 {
275#if SCORE_PLUGIN_GFX
276 auto p = new Gfx::GeometryInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
277 setupNewPort(in, p);
278 ins.push_back(p);
279#endif
280 }
281
282 // Scene inputs reuse Gfx::GeometryInlet — a scene is a richer form of
283 // geometry and travels through the same Process-layer port. Mirror of the
284 // outlet overload below. Needed so scene-modifying halp nodes (Transform,
285 // SceneFilter, ...) can declare `struct { ossia::scene_spec scene; } scene_in;`
286 // in their inputs{} struct and get wired up by the framework.
287 template <scene_port T>
288 requires(!avnd::geometry_port<T>)
289 void operator()(const T& in, auto idx)
290 {
291#if SCORE_PLUGIN_GFX
292 auto p = new Gfx::GeometryInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
293 setupNewPort(in, p);
294 ins.push_back(p);
295#endif
296 }
297
298 template <std::size_t Idx, avnd::message T>
299 void operator()(const avnd::field_reflection<Idx, T>& in, auto dummy)
300 {
301 auto p = new Process::ValueInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
302 setupNewPort(in, p);
303 ins.push_back(p);
304 }
305
306 template <std::size_t Idx, avnd::unreflectable_message<Node> T>
307 void operator()(const avnd::field_reflection<Idx, T>& in, auto dummy)
308 {
309 auto p = new Process::ValueInlet(portName<T>(), Id<Process::Port>(inlet++), &self);
310 setupNewPort(in, p);
311 ins.push_back(p);
312 }
313
314 void operator()(const auto& ctrl, auto idx)
315 {
316 //(avnd::message<std::decay_t<decltype(ctrl)>>);
317 qDebug() << fromStringView(avnd::get_name(ctrl)) << "unhandled";
318 }
319};
320
321template <typename Node>
323{
325 Process::Outlets& outs;
326 int outlet = 0;
327
328 template <oscr::ossia_value_port T>
329 void operator()(const T& out, auto idx)
330 {
331 auto p = new Process::ValueOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
332 setupNewPort(out, p);
333 outs.push_back(p);
334 }
335
336 template <oscr::ossia_audio_port T>
337 void operator()(const T& out, auto idx)
338 {
339 auto p = new Process::AudioOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
340 setupNewPort(out, p);
341 outs.push_back(p);
342 }
343
344 template <oscr::ossia_midi_port T>
345 void operator()(const T& out, auto idx)
346 {
347 auto p = new Process::MidiOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
348 setupNewPort(out, p);
349 outs.push_back(p);
350 }
351
352 template <avnd::dynamic_ports_port T, std::size_t N>
353 void operator()(const T& in, avnd::field_index<N> i)
354 {
355 using port_type = typename decltype(in.ports)::value_type;
356 port_type p;
357 (*this)(p, i);
358 }
359
360 template <avnd::audio_port T>
361 void operator()(const T& out, auto idx)
362 {
363 auto p = new Process::AudioOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
364 setupNewPort(out, p);
365 if(outlet == 1)
366 p->setPropagate(true);
367 outs.push_back(p);
368 }
369
370 template <avnd::midi_port T>
371 void operator()(const T& out, auto idx)
372 {
373 auto p = new Process::MidiOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
374 setupNewPort(out, p);
375 outs.push_back(p);
376 }
377
378 template <avnd::parameter_port T, std::size_t N>
379 requires(!oscr::ossia_port<T>)
380 void operator()(const T& out, avnd::field_index<N>)
381 {
382 if constexpr(avnd::has_widget<T>)
383 {
384 if(auto p = oscr::make_control_out<T>(
385 avnd::field_index<N>{}, Id<Process::Port>(outlet), &self))
386 {
387 p->displayHandledExplicitly = true;
388 setupNewPort(out, p);
389 outs.push_back(p);
390 }
391 else
392 {
393 // FIXME ControlOutlet?
394 auto vp
395 = new Process::ValueOutlet(portName<T>(), Id<Process::Port>(outlet), &self);
396 setupNewPort(out, vp);
397 outs.push_back(vp);
398 }
399 }
400 else
401 {
402 auto vp
403 = new Process::ValueOutlet(portName<T>(), Id<Process::Port>(outlet), &self);
404 setupNewPort(out, vp);
405 outs.push_back(vp);
406 }
407 outlet++;
408 }
409
410 template <avnd::buffer_port T>
411 void operator()(const T& out, auto idx)
412 {
413#if SCORE_PLUGIN_GFX
414 auto p = new Gfx::TextureOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
415 setupNewPort(out, p);
416 outs.push_back(p);
417#endif
418 }
419
420 template <avnd::texture_port T>
421 void operator()(const T& out, auto idx)
422 {
423#if SCORE_PLUGIN_GFX
424 auto p = new Gfx::TextureOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
425 setupNewPort(out, p);
426 outs.push_back(p);
427#endif
428 }
429
430 template <avnd::gpu_render_target_output_port T>
431 void operator()(const T& out, auto idx)
432 {
433#if SCORE_PLUGIN_GFX
434 auto p = new Gfx::TextureOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
435 setupNewPort(out, p);
436 outs.push_back(p);
437#endif
438 }
439
440 template <avnd::geometry_port T>
441 void operator()(const T& out, auto idx)
442 {
443#if SCORE_PLUGIN_GFX
444 auto p = new Gfx::GeometryOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
445 setupNewPort(out, p);
446 outs.push_back(p);
447#endif
448 }
449
450 // Scene outputs reuse Gfx::GeometryOutlet — a scene is a richer form of
451 // geometry that travels through the same Process-layer port. The Crousti
452 // upload path publishes scene_spec via NodeRenderer::process(scene_spec).
453 template <scene_port T>
454 requires(!avnd::geometry_port<T>)
455 void operator()(const T& out, auto idx)
456 {
457#if SCORE_PLUGIN_GFX
458 auto p = new Gfx::GeometryOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
459 setupNewPort(out, p);
460 outs.push_back(p);
461#endif
462 }
463
464 template <avnd::curve_port T>
465 void operator()(const T& out, auto idx)
466 {
467 auto p = new Process::ValueOutlet(portName<T>(), Id<Process::Port>(outlet++), &self);
468 setupNewPort(out, p);
469 outs.push_back(p);
470 }
471
472 template <avnd::callback T, std::size_t N>
473 void operator()(const T& out, avnd::field_index<N>)
474 {
475 if constexpr(avnd::control_port<T>)
476 {
477 if(auto p = oscr::make_control_out<T>(
478 avnd::field_index<N>{}, Id<Process::Port>(outlet), &self))
479 {
480 p->hidden = true;
481 outs.push_back(p);
482 }
483 else
484 {
485 // FIXME ControlOutlet?
486 auto vp
487 = new Process::ValueOutlet(portName<T>(), Id<Process::Port>(outlet), &self);
488 setupNewPort(out, vp);
489 outs.push_back(vp);
490 }
491 }
492 else if constexpr(requires { T::control; })
493 {
494 // FIXME remove this duplication
495 auto p
496 = new Process::ControlOutlet(portName<T>(), Id<Process::Port>(outlet), &self);
497 setupNewPort(out, p);
498 outs.push_back(p);
499 }
500 else
501 {
502 auto p = new Process::ValueOutlet(portName<T>(), Id<Process::Port>(outlet), &self);
503 setupNewPort(out, p);
504 outs.push_back(p);
505 }
506 outlet++;
507 }
508
509 void operator()(const auto& ctrl, auto idx)
510 {
511 qDebug() << fromStringView(avnd::get_name(ctrl)) << "unhandled";
512 }
513};
514}
Definition TexturePort.hpp:154
Definition TexturePort.hpp:177
The DropHandler class If something with audio mime type is dropped, then we create a box with an audi...
Definition SoundDrop.hpp:26
Definition Port.hpp:327
Definition Port.hpp:350
Definition Port.hpp:452
Definition Port.hpp:406
Definition Port.hpp:429
Definition Port.hpp:104
The Process class.
Definition score-lib-process/Process/Process.hpp:75
Definition Port.hpp:518
Definition Port.hpp:544
The id_base_t class.
Definition Identifier.hpp:59
Definition Controls.hpp:27
Definition WidgetInlets.hpp:418
Definition WidgetInlets.hpp:362
Definition WidgetInlets.hpp:383
Definition PortForward.hpp:23
Definition PortForward.hpp:27
Definition ProcessModelPortInit.hpp:59
Definition ProcessModelPortInit.hpp:323