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 <Media/Sound/Drop/SoundDrop.hpp>
8 
9 #include <avnd/binding/ossia/port_base.hpp>
10 #include <avnd/concepts/all.hpp>
11 #if SCORE_PLUGIN_GFX
12 #include <Gfx/TexturePort.hpp>
13 #endif
14 
15 namespace oscr
16 {
17 template <typename Info>
18 class ProcessModel;
19 }
20 
21 namespace oscr
22 {
23 
24 template <typename T>
25 inline void setupNewPort(Process::Port* obj)
26 {
27  //FIXME
28 #if !defined(__APPLE__)
29  constexpr auto name = avnd::get_name<T>();
30  obj->setName(fromStringView(name));
31  if constexpr(avnd::has_description<T>)
32  obj->setDescription(fromStringView(avnd::get_description<T>()));
33 #else
34  auto name = avnd::get_name<T>();
35  obj->setName(fromStringView(name));
36  if constexpr(avnd::has_description<T>)
37  obj->setDescription(fromStringView(avnd::get_description<T>()));
38 #endif
39 }
40 
41 template <std::size_t N, typename T>
42 inline void setupNewPort(const avnd::field_reflection<N, T>& spec, Process::Port* obj)
43 {
44  setupNewPort<T>(obj);
45 }
46 
47 template <typename T>
48 inline void setupNewPort(const T& spec, Process::Port* obj)
49 {
50  setupNewPort<T>(obj);
51 }
52 
53 template <typename Node>
55 {
57  Process::Inlets& ins;
58  int inlet = 0;
59 
60  void operator()(const oscr::ossia_value_port auto& in, auto idx)
61  {
62  auto p = new Process::ValueInlet(Id<Process::Port>(inlet++), &self);
63  setupNewPort(in, p);
64  ins.push_back(p);
65  }
66  void operator()(const oscr::ossia_audio_port auto& in, auto idx)
67  {
68  auto p = new Process::AudioInlet(Id<Process::Port>(inlet++), &self);
69  setupNewPort(in, p);
70  ins.push_back(p);
71  }
72  void operator()(const oscr::ossia_midi_port auto& in, auto idx)
73  {
74  auto p = new Process::MidiInlet(Id<Process::Port>(inlet++), &self);
75  setupNewPort(in, p);
76  ins.push_back(p);
77  }
78 
79  void operator()(const avnd::audio_port auto& in, auto idx)
80  {
81  auto p = new Process::AudioInlet(Id<Process::Port>(inlet++), &self);
82  setupNewPort(in, p);
83  ins.push_back(p);
84  }
85  void operator()(const avnd::midi_port auto& in, auto idx)
86  {
87  auto p = new Process::MidiInlet(Id<Process::Port>(inlet++), &self);
88  setupNewPort(in, p);
89  ins.push_back(p);
90  }
91 
92  static QString toFilters(const QSet<QString>& exts)
93  {
94  QString res;
95  for(const auto& s : exts)
96  {
97  res += "*.";
98  res += s;
99  res += " ";
100  }
101  if(!res.isEmpty())
102  res.resize(res.size() - 1);
103  return res;
104  }
105 
106  template <typename P>
107  static QString getFilters(P& p)
108  {
109  if constexpr(requires { P::filters(); })
110  {
111  using filter = decltype(P::filters());
112  if constexpr(requires { filter::sound; } || requires { filter::audio; })
113  {
114  return QString{"Sound files (%1)"}.arg(
115  toFilters(Media::Sound::DropHandler{}.fileExtensions()));
116  }
117  else if constexpr(requires { filter::video; })
118  {
119  // FIXME refactor supported formats with Video process
120  QSet<QString> files = {"mkv", "mov", "mp4", "h264", "avi", "hap", "mpg",
121  "mpeg", "imf", "mxf", "mts", "m2ts", "mj2", "webm"};
122  return QString{"Videos (%1)"}.arg(toFilters(files));
123  }
124  else if constexpr(requires { filter::image; })
125  {
126  // FIXME refactor supported formats with Image List Chooser
127  return QString{"Images (*.png *.jpg *.jpeg *.gif *.bmp *.tiff)"};
128  }
129  else if constexpr(requires { filter::midi; })
130  {
131  return "MIDI (*.mid)";
132  }
133  else if constexpr(avnd::string_ish<filter>)
134  {
135  static constexpr auto text_filters = P::filters();
136  return fromStringView(P::filters());
137  }
138  else
139  {
140  return "";
141  }
142  }
143  else if constexpr(requires { P::extensions(); })
144  {
145  static constexpr auto text_filters = P::extensions();
146  return fromStringView(text_filters);
147  }
148  else
149  {
150  return "";
151  }
152  }
153 
154  template <typename T>
155  requires avnd::soundfile_port<T>
156  void operator()(const T& in, auto idx)
157  {
158  static constexpr auto name = avnd::get_name<T>();
159  Process::FileChooserBase* p{};
160  if constexpr(requires { T::waveform; })
161  {
162  p = new Process::AudioFileChooser{
163  "", getFilters(in), QString::fromUtf8(name.data(), name.size()),
164  Id<Process::Port>(inlet++), &self};
165  }
166  else
167  {
168  p = new Process::FileChooser{
169  "", getFilters(in), QString::fromUtf8(name.data(), name.size()),
170  Id<Process::Port>(inlet++), &self};
171  }
172 
173  p->hidden = true;
174  ins.push_back(p);
175 
176  if constexpr(avnd::tag_file_watch<T>)
177  {
178  p->enableFileWatch();
179  }
180  }
181 
182  template <typename T>
183  requires avnd::midifile_port<T> || avnd::raw_file_port<T>
184  void operator()(const T& in, auto idx)
185  {
186  static constexpr auto name = avnd::get_name<T>();
187 
188  auto p = new Process::FileChooser{
189  "", getFilters(in), QString::fromUtf8(name.data(), name.size()),
190  Id<Process::Port>(inlet++), &self};
191  p->hidden = true;
192  ins.push_back(p);
193 
194  if constexpr(avnd::tag_file_watch<T>)
195  {
196  p->enableFileWatch();
197  }
198  }
199 
200  template <avnd::dynamic_ports_port T, std::size_t N>
201  void operator()(const T& in, avnd::field_index<N> i)
202  {
203  using port_type = typename decltype(in.ports)::value_type;
204  port_type p;
205  (*this)(p, i);
206  }
207 
208  template <avnd::parameter T, std::size_t N>
209  requires(!oscr::ossia_port<T>)
210  void operator()(const T& in, avnd::field_index<N>)
211  {
212  if constexpr(avnd::has_widget<T> || avnd::curve_port<T>)
213  {
214  auto p = oscr::make_control_in<Node, T>(
215  avnd::field_index<N>{}, Id<Process::Port>(inlet), &self);
216  if constexpr(!std::is_same_v<std::decay_t<decltype(p)>, std::nullptr_t>)
217  {
218  p->hidden = true;
219  ins.push_back(p);
220  }
221  else
222  {
223  auto vp = new Process::ValueInlet(Id<Process::Port>(inlet), &self);
224  setupNewPort(in, vp);
225  ins.push_back(vp);
226  }
227  }
228  else
229  {
230  auto vp = new Process::ValueInlet(Id<Process::Port>(inlet), &self);
231  setupNewPort(in, vp);
232  ins.push_back(vp);
233  }
234  inlet++;
235  }
236 
237 #if SCORE_PLUGIN_GFX
238  void operator()(const avnd::texture_port auto& in, auto idx)
239  {
240  auto p = new Gfx::TextureInlet(Id<Process::Port>(inlet++), &self);
241  setupNewPort(in, p);
242  ins.push_back(p);
243  }
244  void operator()(const avnd::geometry_port auto& in, auto idx)
245  {
246  auto p = new Gfx::GeometryInlet(Id<Process::Port>(inlet++), &self);
247  setupNewPort(in, p);
248  ins.push_back(p);
249  }
250 #endif
251 
252  template <std::size_t Idx, avnd::message T>
253  void operator()(const avnd::field_reflection<Idx, T>& in, auto dummy)
254  {
255  auto p = new Process::ValueInlet(Id<Process::Port>(inlet++), &self);
256  setupNewPort(in, p);
257  ins.push_back(p);
258  }
259 
260  template <std::size_t Idx, avnd::unreflectable_message<Node> T>
261  void operator()(const avnd::field_reflection<Idx, T>& in, auto dummy)
262  {
263  auto p = new Process::ValueInlet(Id<Process::Port>(inlet++), &self);
264  setupNewPort(in, p);
265  ins.push_back(p);
266  }
267 
268  void operator()(const auto& ctrl, auto idx)
269  {
270  //(avnd::message<std::decay_t<decltype(ctrl)>>);
271  qDebug() << fromStringView(avnd::get_name(ctrl)) << "unhandled";
272  }
273 };
274 
275 template <typename Node>
277 {
278  Process::ProcessModel& self;
279  Process::Outlets& outs;
280  int outlet = 0;
281 
282  void operator()(const oscr::ossia_value_port auto& out, auto idx)
283  {
284  auto p = new Process::ValueOutlet(Id<Process::Port>(outlet++), &self);
285  setupNewPort(out, p);
286  outs.push_back(p);
287  }
288  void operator()(const oscr::ossia_audio_port auto& out, auto idx)
289  {
290  auto p = new Process::AudioOutlet(Id<Process::Port>(outlet++), &self);
291  setupNewPort(out, p);
292  outs.push_back(p);
293  }
294  void operator()(const oscr::ossia_midi_port auto& out, auto idx)
295  {
296  auto p = new Process::MidiOutlet(Id<Process::Port>(outlet++), &self);
297  setupNewPort(out, p);
298  outs.push_back(p);
299  }
300 
301  template <avnd::dynamic_ports_port T, std::size_t N>
302  void operator()(const T& in, avnd::field_index<N> i)
303  {
304  using port_type = typename decltype(in.ports)::value_type;
305  port_type p;
306  (*this)(p, i);
307  }
308 
309  void operator()(const avnd::audio_port auto& out, auto idx)
310  {
311  auto p = new Process::AudioOutlet(Id<Process::Port>(outlet++), &self);
312  setupNewPort(out, p);
313  if(outlet == 1)
314  p->setPropagate(true);
315  outs.push_back(p);
316  }
317 
318  void operator()(const avnd::midi_port auto& out, auto idx)
319  {
320  auto p = new Process::MidiOutlet(Id<Process::Port>(outlet++), &self);
321  setupNewPort(out, p);
322  outs.push_back(p);
323  }
324 
325  template <avnd::parameter T, std::size_t N>
326  requires(!oscr::ossia_port<T>)
327  void operator()(const T& out, avnd::field_index<N>)
328  {
329  if constexpr(avnd::has_widget<T>)
330  {
331  if(auto p = oscr::make_control_out<T>(
332  avnd::field_index<N>{}, Id<Process::Port>(outlet), &self))
333  {
334  p->hidden = true;
335  outs.push_back(p);
336  }
337  else
338  {
339  // FIXME ControlOutlet?
340  auto vp = new Process::ValueOutlet(Id<Process::Port>(outlet), &self);
341  setupNewPort(out, vp);
342  outs.push_back(vp);
343  }
344  }
345  else
346  {
347  auto vp = new Process::ValueOutlet(Id<Process::Port>(outlet), &self);
348  setupNewPort(out, vp);
349  outs.push_back(vp);
350  }
351  outlet++;
352  }
353 
354 #if SCORE_PLUGIN_GFX
355  void operator()(const avnd::texture_port auto& out, auto idx)
356  {
357  auto p = new Gfx::TextureOutlet(Id<Process::Port>(outlet++), &self);
358  setupNewPort(out, p);
359  outs.push_back(p);
360  }
361  void operator()(const avnd::geometry_port auto& out, auto idx)
362  {
363  auto p = new Gfx::GeometryOutlet(Id<Process::Port>(outlet++), &self);
364  setupNewPort(out, p);
365  outs.push_back(p);
366  }
367 #endif
368 
369  void operator()(const avnd::curve_port auto& out, auto idx)
370  {
371  auto p = new Process::ValueOutlet(Id<Process::Port>(outlet++), &self);
372  setupNewPort(out, p);
373  outs.push_back(p);
374  }
375 
376  template <avnd::callback T, std::size_t N>
377  void operator()(const T& out, avnd::field_index<N>)
378  {
379  if constexpr(avnd::control<T>)
380  {
381  if(auto p = oscr::make_control_out<T>(
382  avnd::field_index<N>{}, Id<Process::Port>(outlet), &self))
383  {
384  p->hidden = true;
385  outs.push_back(p);
386  }
387  else
388  {
389  // FIXME ControlOutlet?
390  auto vp = new Process::ValueOutlet(Id<Process::Port>(outlet), &self);
391  setupNewPort(out, vp);
392  outs.push_back(vp);
393  }
394  }
395  else if constexpr(requires { T::control; })
396  {
397  // FIXME remove this duplication
398  auto p = new Process::ControlOutlet(Id<Process::Port>(outlet), &self);
399  setupNewPort(out, p);
400  outs.push_back(p);
401  }
402  else
403  {
404  auto p = new Process::ValueOutlet(Id<Process::Port>(outlet), &self);
405  setupNewPort(out, p);
406  outs.push_back(p);
407  }
408  outlet++;
409  }
410 
411  void operator()(const auto& ctrl, auto idx)
412  {
413  qDebug() << fromStringView(avnd::get_name(ctrl)) << "unhandled";
414  }
415 };
416 }
Definition: TexturePort.hpp:121
Definition: TexturePort.hpp:144
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:300
Definition: Port.hpp:323
Definition: Port.hpp:425
Definition: Port.hpp:379
Definition: Port.hpp:402
Definition: Port.hpp:102
The Process class.
Definition: score-lib-process/Process/Process.hpp:61
Definition: Port.hpp:492
Definition: Port.hpp:515
The id_base_t class.
Definition: Identifier.hpp:57
Definition: Factories.hpp:19
Definition: PortForward.hpp:23
Definition: PortForward.hpp:27
Definition: ProcessModelPortInit.hpp:55
Definition: ProcessModelPortInit.hpp:277