OSSIA
Open Scenario System for Interactive Application
minuit_parser.hpp
1 #pragma once
2 #include <ossia/detail/small_vector.hpp>
3 #include <ossia/network/base/device.hpp>
6 #include <ossia/network/minuit/detail/minuit_common.hpp>
7 #include <ossia/network/minuit/minuit.hpp>
8 #include <ossia/network/osc/detail/osc.hpp>
9 #include <ossia/network/osc/detail/sender.hpp>
10 
11 #include <oscpack/osc/OscPrintReceivedElements.h>
12 #include <oscpack/osc/OscReceivedElements.h>
13 
14 namespace ossia::minuit
15 {
16 template <minuit_command Req, minuit_operation Op>
17 struct minuit_behavior
18 {
19  void operator()(
20  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
21  const oscpack::ReceivedMessage& mess);
22 };
23 
24 template <minuit_operation Op>
25 struct minuit_behavior<minuit_command::Error, Op>
26 {
27  void operator()(
28  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
29  const oscpack::ReceivedMessage& mess)
30  {
31  }
32 };
33 
34 template <>
35 struct minuit_behavior<minuit_command::Error, minuit_operation::Get>
36 {
37  void operator()(
38  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
39  const oscpack::ReceivedMessage& mess)
40  {
41  // Do nothing
42  if(mess.ArgumentCount() > 0)
43  {
44  auto beg = mess.ArgumentsBegin();
45  if(beg->IsString())
46  {
47  proto.get_refreshed(beg->AsStringUnchecked());
48  }
49  }
50  }
51 };
52 
53 // Get
54 template <>
55 struct minuit_behavior<minuit_command::Request, minuit_operation::Get>
56 {
57  auto operator()(
58  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
59  const oscpack::ReceivedMessage& mess)
60  {
61  std::string_view full_address{mess.ArgumentsBegin()->AsString()};
62  auto idx = full_address.find_first_of(":");
63 
64  if(idx == std::string::npos)
65  {
66  // Value
67  auto node = ossia::net::find_node(dev.get_root_node(), full_address);
68  if(!node)
69  return;
70  auto addr = node->get_parameter();
71  if(!addr)
72  return;
73 
74  proto.sender().send(
75  proto.name_table.get_action(minuit_action::GetReply), full_address,
76  addr->value());
77  }
78  else
79  {
80  std::string_view address{full_address.data(), idx};
81 
82  // Note : bug if address == "foo:"
83  auto attr = get_attribute(
84  std::string_view(address.data() + idx + 1, full_address.size() - idx - 1));
85 
86  auto node = ossia::net::find_node(dev.get_root_node(), address);
87  if(!node)
88  return;
89  auto addr = node->get_parameter();
90  if(!addr)
91  return;
92 
93  switch(attr)
94  {
95  case minuit_attribute::Value:
96  proto.sender().send(
97  proto.name_table.get_action(minuit_action::GetReply), full_address,
98  addr->value());
99  break;
100  case minuit_attribute::Type:
101  proto.sender().send(
102  proto.name_table.get_action(minuit_action::GetReply), full_address,
103  to_minuit_type_text(addr->get_value_type()));
104  break;
105  case minuit_attribute::RangeBounds:
106  {
107  if(auto dom = addr->get_domain())
108  {
109  auto v0 = dom.convert_min<float>();
110  auto v1 = dom.convert_max<float>();
111  proto.sender().send(
112  proto.name_table.get_action(minuit_action::GetReply), full_address,
113  v0, v1);
114  }
115  break;
116  }
117  case minuit_attribute::RangeClipMode:
118  proto.sender().send(
119  proto.name_table.get_action(minuit_action::GetReply), full_address,
120  to_minuit_bounding_text(addr->get_bounding()));
121  break;
122  case minuit_attribute::Dataspace:
123  proto.sender().send(
124  proto.name_table.get_action(minuit_action::GetReply), full_address,
125  ossia::get_dataspace_text(addr->get_unit()));
126  break;
127  case minuit_attribute::DataspaceUnit:
128  proto.sender().send(
129  proto.name_table.get_action(minuit_action::GetReply), full_address,
130  ossia::get_unit_text(addr->get_unit()));
131  break;
132  case minuit_attribute::RepetitionFilter:
133  proto.sender().send(
134  proto.name_table.get_action(minuit_action::GetReply), full_address,
135  (int32_t)addr->get_repetition_filter());
136  break;
137  case minuit_attribute::Service:
138  proto.sender().send(
139  proto.name_table.get_action(minuit_action::GetReply), full_address,
140  to_minuit_service_text(addr->get_access()));
141  break;
142  case minuit_attribute::Description:
143  if(const auto& desc = ossia::net::get_description(*node))
144  proto.sender().send(
145  proto.name_table.get_action(minuit_action::GetReply), full_address,
146  *desc);
147  break;
148  case minuit_attribute::Priority:
149  if(const auto& priority = ossia::net::get_priority(*node))
150  proto.sender().send(
151  proto.name_table.get_action(minuit_action::GetReply), full_address,
152  *priority);
153  else
154  proto.sender().send(
155  proto.name_table.get_action(minuit_action::GetReply), full_address, 0);
156  break;
157  case minuit_attribute::ValueStepSize:
158  if(const auto& ss = ossia::net::get_value_step_size(*node))
159  proto.sender().send(
160  proto.name_table.get_action(minuit_action::GetReply), full_address, *ss);
161  break;
162  // TODO some are missing :refresh rate, tags, instance bounds...
163  default:
164  break;
165  }
166  }
167  }
168 };
169 
170 // Listen
171 template <>
172 struct minuit_behavior<minuit_command::Request, minuit_operation::Listen>
173 {
174  auto operator()(
175  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
176  const oscpack::ReceivedMessage& mess)
177  {
178  // TODO FIXME Add the address to the listeners
179  }
180 };
181 
182 // Namespace
183 template <>
184 struct minuit_behavior<minuit_command::Request, minuit_operation::Namespace>
185 {
186  void handle_root(ossia::net::minuit_protocol& proto, const std::vector<std::string>& c)
187  {
188  proto.sender().send(
189  proto.name_table.get_action(minuit_action::NamespaceReply), "/", "Application",
190  "nodes={", c, "}", "attributes={", "}");
191  std::this_thread::sleep_for(std::chrono::milliseconds(1));
192  }
193 
194  void handle_container(
195  ossia::net::minuit_protocol& proto, std::string_view address,
196  const std::vector<std::string>& c)
197  {
198  proto.sender().send(
199  proto.name_table.get_action(minuit_action::NamespaceReply), address, "Container",
200  "nodes={", c, "}", "attributes={", "}");
201  std::this_thread::sleep_for(std::chrono::milliseconds(1));
202  }
203 
204  void handle_data(ossia::net::minuit_protocol& proto, std::string_view address)
205  {
206  proto.sender().send(
207  proto.name_table.get_action(minuit_action::NamespaceReply), address, "Data",
208  "attributes={", "type", "dataspace", "repetitionsFilter", "service", "priority",
209  "value", "rangeBounds", "rangeClipmode", "dataspaceUnit", "}");
210  std::this_thread::sleep_for(std::chrono::milliseconds(1));
211  }
212 
213  void handle_data_container(
214  ossia::net::minuit_protocol& proto, std::string_view address,
215  const std::vector<std::string>& c)
216  {
217  proto.sender().send(
218  proto.name_table.get_action(minuit_action::NamespaceReply), address, "Data",
219  "attributes={", "type", "dataspace", "repetitionsFilter", "service", "priority",
220  "value", "rangeBounds", "rangeClipmode", "dataspaceUnit", "}");
221  std::this_thread::sleep_for(std::chrono::milliseconds(1));
222  }
223 
224  std::vector<std::string>
225  get_children_names(ossia::net::device_base& dev, std::string_view address)
226  {
227  auto node = ossia::net::find_node(dev.get_root_node(), address);
228  if(!node)
229  return {};
230 
231  return node->children_names();
232  }
233 
234  auto operator()(
235  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
236  const oscpack::ReceivedMessage& mess)
237  {
238  std::string_view address{mess.ArgumentsBegin()->AsString()};
239 
240  if(address == std::string_view("/"))
241  {
242  handle_root(proto, get_children_names(dev, address));
243  }
244  else
245  {
246  auto node = ossia::net::find_node(dev.get_root_node(), address);
247  if(!node)
248  return;
249 
250  if(node->children().empty())
251  {
252  handle_data(proto, address);
253  }
254  else
255  {
256  if(node->get_parameter())
257  {
258  handle_data_container(proto, address, get_children_names(dev, address));
259  }
260  else
261  {
262  handle_container(proto, address, get_children_names(dev, address));
263  }
264  }
265  }
266  }
267 };
268 
269 // Used for domains :
270 
271 struct osc_inbound_numeric_visitor
272 {
273  osc_inbound_numeric_visitor(oscpack::ReceivedMessageArgumentIterator cur)
274  : cur_it{cur}
275  {
276  }
277 
278  oscpack::ReceivedMessageArgumentIterator cur_it;
279  ossia::value operator()(ossia::impulse imp) const { return imp; }
280 
281  ossia::value operator()(int32_t i) const
282  {
283  return ossia::net::osc_utilities::get_int(cur_it, i);
284  }
285 
286  ossia::value operator()(float f) const
287  {
288  return ossia::net::osc_utilities::get_float(cur_it, f);
289  }
290 
291  ossia::value operator()(bool b) const
292  {
293  return ossia::net::osc_utilities::get_bool(cur_it, b);
294  }
295 
296  ossia::value operator()(char c) const
297  {
298  return ossia::net::osc_utilities::get_char(cur_it, c);
299  }
300 
301  ossia::value operator()(const std::string& str) const { return str; }
302 
303  template <std::size_t N>
304  ossia::value operator()(std::array<float, N> vec) const
305  {
306  return ossia::net::osc_utilities::get_float(cur_it, vec[0]);
307  }
308 
309  ossia::value operator()(const std::vector<ossia::value>& t)
310  {
311  return ossia::net::osc_utilities::get_float(
312  cur_it, !t.empty() ? ossia::convert<float>(t[0]) : 0.f);
313  }
314 
315  ossia::value operator()(const value_map_type& t) { return {}; }
316  ossia::value operator()() const { return {}; }
317 };
318 
319 inline ossia::value to_numeric_value(
320  const ossia::value& current, oscpack::ReceivedMessageArgumentIterator beg_it,
321  oscpack::ReceivedMessageArgumentIterator end_it)
322 {
323  if(beg_it != end_it)
324  return current.apply(osc_inbound_numeric_visitor{beg_it});
325  else
326  return current.apply(ossia::net::osc_inbound_impulse_visitor{});
327 }
328 
329 inline ossia::domain get_domain(
330  ossia::net::parameter_base& addr, oscpack::ReceivedMessageArgumentIterator beg_it,
331  oscpack::ReceivedMessageArgumentIterator end_it)
332 {
333  ossia::small_vector<ossia::value, 2> val;
334  const auto cur = addr.value();
335 
336  // We read all the values one by one
337  while(beg_it != end_it)
338  {
339  auto cur_it = beg_it;
340  ++beg_it;
341  val.push_back(to_numeric_value(cur, cur_it, beg_it));
342  }
343 
344  return ossia::make_domain_from_osc(val, cur);
345 }
346 
347 inline std::optional<double> AsNumber(oscpack::ReceivedMessageArgumentIterator& it)
348 {
349  switch(it->TypeTag())
350  {
351  case oscpack::TypeTagValues::INT32_TYPE_TAG:
352  return (double)it->AsInt32Unchecked();
353  case oscpack::TypeTagValues::INT64_TYPE_TAG:
354  return (double)it->AsInt64Unchecked();
355  case oscpack::TypeTagValues::FLOAT_TYPE_TAG:
356  return (double)it->AsFloatUnchecked();
357  case oscpack::TypeTagValues::DOUBLE_TYPE_TAG:
358  return it->AsDoubleUnchecked();
359  default:
360  return std::nullopt;
361  }
362 }
363 
364 // Listen
365 template <>
366 struct minuit_behavior<minuit_command::Answer, minuit_operation::Listen>
367 {
368  auto operator()(
369  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
370  const oscpack::ReceivedMessage& mess)
371  {
372  std::string_view full_address;
373  auto mess_it = mess.ArgumentsBegin();
374  full_address = mess_it->AsStringUnchecked();
375  auto idx = full_address.find_first_of(":");
376 
377  if(idx == std::string::npos)
378  {
379  // The OSC message is a standard OSC one, carrying a value.
380  auto node = ossia::net::find_node(dev.get_root_node(), full_address);
381  if(node)
382  {
383  if(auto addr = node->get_parameter())
384  {
385  if(auto v = ossia::net::get_filtered_value(
386  *addr, ++mess_it, mess.ArgumentsEnd(), mess.ArgumentCount() - 1);
387  v.valid())
388  {
389  addr->set_value(std::move(v));
390  }
391  }
392  }
393  }
394  else
395  {
396  // The OSC message is a Minuit one.
397  // address contains the "sanitized" OSC-like address.
398  std::string_view address{full_address.data(), idx};
399 
400  // Note : bug if address == "foo:"
401  auto attr = get_attribute(
402  std::string_view(address.data() + idx + 1, full_address.size() - idx - 1));
403 
404  ++mess_it;
405  // mess_it is now at the first argument after the address:attribute
406 
407  if(auto node = ossia::net::find_node(dev.get_root_node(), address))
408  if(auto addr = node->get_parameter())
409  switch(attr)
410  {
411  case minuit_attribute::Value: {
412  if(auto v = ossia::net::get_filtered_value(
413  *addr, mess_it, mess.ArgumentsEnd(), mess.ArgumentCount() - 1);
414  v.valid())
415  {
416  addr->set_value(std::move(v));
417  }
418  break;
419  }
420  case minuit_attribute::Type: {
421  addr->set_value_type(ossia::minuit::type_from_minuit_type_text(
422  mess_it->AsStringUnchecked()));
423 
424  break;
425  }
426  case minuit_attribute::RangeBounds: {
427  addr->set_domain(get_domain(*addr, mess_it, mess.ArgumentsEnd()));
428  break;
429  }
430  case minuit_attribute::RangeClipMode: {
431  addr->set_bounding(
432  from_minuit_bounding_text(mess_it->AsStringUnchecked()));
433  break;
434  }
435  case minuit_attribute::RepetitionFilter: {
436  addr->set_repetition_filter(
437  static_cast<repetition_filter>(mess_it->AsInt32Unchecked()));
438  break;
439  }
440  case minuit_attribute::Dataspace: {
441  addr->set_unit(ossia::parse_dataspace(mess_it->AsStringUnchecked()));
442  break;
443  }
444  case minuit_attribute::DataspaceUnit: {
445  addr->set_unit(
446  ossia::parse_unit(mess_it->AsStringUnchecked(), addr->get_unit()));
447  break;
448  }
449  case minuit_attribute::Service: {
450  addr->set_access(from_minuit_service_text(mess_it->AsStringUnchecked()));
451  break;
452  }
453  case minuit_attribute::Description: {
454  ossia::net::set_description(
455  *node, std::string(mess_it->AsStringUnchecked()));
456  break;
457  }
458  case minuit_attribute::Priority: {
459  ossia::net::set_priority(*node, mess_it->AsInt32());
460  break;
461  }
462  case minuit_attribute::ValueStepSize: {
463  ossia::net::set_value_step_size(*node, AsNumber(mess_it));
464  break;
465  }
466  default:
467  break;
468  }
469  }
470  return full_address;
471  }
472 };
473 
474 // Get
475 template <>
476 struct minuit_behavior<minuit_command::Answer, minuit_operation::Get>
477 {
478 
479  void operator()(
480  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
481  const oscpack::ReceivedMessage& mess)
482  {
483  auto addr = minuit_behavior<minuit_command::Answer, minuit_operation::Listen>{}(
484  proto, dev, mess);
485  proto.get_refreshed(addr);
486  }
487 };
488 
489 template <typename It, typename Fun>
490 auto find_if(It begin, It end, Fun f)
491 {
492  for(auto it = begin; it != end; ++it)
493  {
494  if(f(*it))
495  return it;
496  }
497  return end;
498 }
499 
500 // Namespace
501 template <>
502 struct minuit_behavior<minuit_command::Answer, minuit_operation::Namespace>
503 {
504  template <typename Str>
505  static auto get_container(
506  Str s, oscpack::ReceivedMessageArgumentIterator beg_it,
507  oscpack::ReceivedMessageArgumentIterator end_it)
508  {
509  std::vector<std::string_view> elements;
510  auto nodes_beg_it = find_if(beg_it, end_it, [=](const auto& mess) {
511  return mess.IsString() && std::string_view(mess.AsStringUnchecked()) == s;
512  });
513 
514  ++nodes_beg_it; // It will point on the first past "nodes={".
515  if(nodes_beg_it != end_it)
516  {
517  auto nodes_end_it = find_if(nodes_beg_it, end_it, [](const auto& mess) {
518  return mess.IsString() && mess.AsStringUnchecked()[0] == '}'
519  && mess.AsStringUnchecked()[1] == '\0';
520  });
521 
522  if(nodes_end_it != end_it)
523  {
524  for(auto it = nodes_beg_it; it != nodes_end_it; ++it)
525  {
526  elements.push_back(it->AsStringUnchecked());
527  }
528  }
529  }
530 
531  return elements;
532  }
533 
534  static auto get_nodes(
535  oscpack::ReceivedMessageArgumentIterator beg_it,
536  oscpack::ReceivedMessageArgumentIterator end_it)
537  {
538  return get_container("nodes={", beg_it, end_it);
539  }
540 
541  static auto get_attributes(
542  oscpack::ReceivedMessageArgumentIterator beg_it,
543  oscpack::ReceivedMessageArgumentIterator end_it)
544  {
545  return get_container("attributes={", beg_it, end_it);
546  }
547 
548  static auto handle_container(
549  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
550  std::string_view address, oscpack::ReceivedMessageArgumentIterator beg_it,
551  oscpack::ReceivedMessageArgumentIterator end_it)
552  {
553  using namespace oscpack;
554  auto sub_request = proto.name_table.get_action(minuit_action::NamespaceRequest);
555 
556  // Get the sub-nodes
557  std::string child_address{address};
558  if(child_address.back() != '/')
559  child_address += '/';
560  const auto child_parameter_size = child_address.size();
561 
562  for(auto child : get_nodes(beg_it, end_it))
563  {
564  child_address.resize(child_parameter_size);
565 
566  // Address of the node to create
567  child_address.append(child.begin(), child.end());
568 
569  // Create the actual node
570  ossia::net::find_or_create_node(dev.get_root_node(), address);
571 
572  // request children
573  proto.namespace_refresh(sub_request, child_address);
574  }
575  }
576 
577  static auto handle_data(
578  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
579  std::string_view address, oscpack::ReceivedMessageArgumentIterator beg_it,
580  oscpack::ReceivedMessageArgumentIterator end_it)
581  {
582  using namespace oscpack;
583 
584  // Find or create the node
585  auto& n = ossia::net::find_or_create_node(dev.get_root_node(), address);
586  n.create_parameter(ossia::val_type::IMPULSE);
587 
588  // A data can also have child nodes :
589  handle_container(proto, dev, address, beg_it, end_it);
590 
591  auto sub_request = proto.name_table.get_action(minuit_action::GetRequest);
592 
593  // Request all the attributes provided by the node
594  // type and dataspace have to be queried before the others since
595  // value and dataspace_unit correct parsing depends on correct values
596  // prior.
597  // note : we should really use TCP for this since there could be a
598  // reordering...
599  // or a queue of things to query.
600 
601  auto attribs = get_attributes(beg_it, end_it);
602  for(auto it = attribs.begin(); it != attribs.end();)
603  {
604  switch(get_attribute(*it))
605  {
606  case minuit_attribute::Type:
607  case minuit_attribute::Dataspace: {
608  // name?get address:attribute
609  auto str = std::string(address);
610  str += ':';
611  str.append(it->begin(), it->end());
612  proto.get_refresh(sub_request, str, std::promise<void>{});
613 
614  it = attribs.erase(it);
615  }
616  break;
617  default:
618  ++it;
619  break;
620  }
621  }
622 
623  for(auto attrib : attribs)
624  {
625  switch(get_attribute(attrib))
626  {
627  case minuit_attribute::Value:
628  case minuit_attribute::RangeBounds:
629  case minuit_attribute::RangeClipMode:
630  case minuit_attribute::RepetitionFilter:
631  case minuit_attribute::DataspaceUnit:
632  case minuit_attribute::Service:
633  case minuit_attribute::Priority:
634  case minuit_attribute::ValueStepSize:
635  case minuit_attribute::Description: {
636  // name?get address:attribute
637  auto str = std::string(address);
638  str += ':';
639  str.append(attrib.begin(), attrib.end());
640  proto.get_refresh(sub_request, str, std::promise<void>{});
641  }
642  default:
643  break;
644  }
645  }
646  }
647 
648  static auto handle_minuit(
649  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
650  std::string_view address, minuit_type type,
651  oscpack::ReceivedMessageArgumentIterator beg_it,
652  oscpack::ReceivedMessageArgumentIterator end_it)
653  {
654  switch(type)
655  {
656  case minuit_type::Application:
657  case minuit_type::Container: {
658  handle_container(proto, dev, address, beg_it, end_it);
659  break;
660  }
661  case minuit_type::Data: {
662  handle_data(proto, dev, address, beg_it, end_it);
663  break;
664  }
665  case minuit_type::ModelInfo:
666  case minuit_type::UiInfo:
667  case minuit_type::PresetManager:
668  case minuit_type::None:
669  handle_container(proto, dev, address, beg_it, end_it);
670  break;
671  }
672  }
673 
674  auto operator()(
675  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
676  const oscpack::ReceivedMessage& mess)
677  {
678  auto it = mess.ArgumentsBegin();
679  std::string_view address = it->AsString();
680  auto type = get_type((++it)->AsString()[0]);
681 
682  handle_minuit(proto, dev, address, type, it, mess.ArgumentsEnd());
683 
684  proto.namespace_refreshed(address);
685  }
686 };
687 
688 // Namespace request :
689 // app?namespace addr
690 
691 // Namespace answer :
692 // app:namespace addr minuit_type nodes={ n1 n2 n3 } attributes={ foo bar baz }
693 
694 class minuit_message_handler
695 {
696 public:
697  static void handleMinuitMessage(
698  ossia::net::minuit_protocol& proto, ossia::net::device_base& dev,
699  std::string_view address, const oscpack::ReceivedMessage& m)
700  {
701  // Look for either ':' or '?'
702  auto idx = address.find_first_of(":?!");
703 
704  if(idx != std::string::npos)
705  {
706  auto req = get_command(address[idx]);
707  auto op = get_operation(*(address.data() + idx + 1));
708  switch(req)
709  {
710  case minuit_command::Answer: // Receiving an answer
711  {
712  switch(op)
713  {
714  case minuit_operation::Listen:
715  minuit_behavior<minuit_command::Answer, minuit_operation::Listen>{}(
716  proto, dev, m);
717  break;
718  case minuit_operation::Get:
719  minuit_behavior<minuit_command::Answer, minuit_operation::Get>{}(
720  proto, dev, m);
721  break;
722  case minuit_operation::Namespace:
723  minuit_behavior<minuit_command::Answer, minuit_operation::Namespace>{}(
724  proto, dev, m);
725  break;
726  default:
727  break;
728  }
729  break;
730  }
731  case minuit_command::Request: // Receiving a request
732  {
733  switch(op)
734  {
735  case minuit_operation::Listen:
736  minuit_behavior<minuit_command::Request, minuit_operation::Listen>{}(
737  proto, dev, m);
738  break;
739  case minuit_operation::Get:
740  minuit_behavior<minuit_command::Request, minuit_operation::Get>{}(
741  proto, dev, m);
742  break;
743  case minuit_operation::Namespace:
744  minuit_behavior<minuit_command::Request, minuit_operation::Namespace>{}(
745  proto, dev, m);
746  break;
747  default:
748  break;
749  }
750  break;
751  }
752  case minuit_command::Error: // Receiving an error
753  {
754  switch(op)
755  {
756  case minuit_operation::Listen:
757  minuit_behavior<minuit_command::Error, minuit_operation::Listen>{}(
758  proto, dev, m);
759  break;
760  case minuit_operation::Get:
761  minuit_behavior<minuit_command::Error, minuit_operation::Get>{}(
762  proto, dev, m);
763  break;
764  case minuit_operation::Namespace:
765  minuit_behavior<minuit_command::Error, minuit_operation::Namespace>{}(
766  proto, dev, m);
767  break;
768  default:
769  break;
770  }
771  break;
772  }
773  default:
774  break;
775  }
776  }
777  }
778 };
779 }
Root of a device tree.
Definition: ossia/network/base/device.hpp:58
The parameter_base class.
Definition: ossia/network/base/parameter.hpp:48
virtual ossia::value value() const =0
Clone the current value without any network request.
const ossia::unit_t & get_unit() const noexcept
by default there is no filter
Definition: ossia/network/base/parameter.hpp:162
The value class.
Definition: value.hpp:173
@ Get
Definition: ossia-cpp98.hpp:67
@ IMPULSE
array<float, 4>
repetition_filter
If enabled, sending twice the same value will only send it once by network.
Definition: parameter_properties.hpp:70
std::string_view get_dataspace_text(const unit_t &u)
Parse ///.
Definition: dataspace_visitors.cpp:28
auto get_attribute(const any_map &e, std::string_view name)
get_attribute Get an attribute of an any_map.
Definition: any_map.hpp:29
unit_t parse_unit(std::string_view text, const unit_t &dataspace)
parse_unit Takes a text and a dataspace and gives a corresponding unit.
Definition: dataspace_visitors.cpp:57
unit_t parse_dataspace(std::string_view text)
parse_dataspace
Definition: dataspace_visitors.cpp:89
std::string_view get_unit_text(const unit_t &u)
get_unit_text
Definition: dataspace_visitors.cpp:33
float priority
When a node must be sent before other.
Definition: node_attributes.hpp:77
OSSIA_EXPORT node_base & find_or_create_node(node_base &dev, std::string_view parameter_base)
Find a node and create it if it does not exist.
OSSIA_EXPORT ossia::net::node_base * find_node(node_base &dev, std::string_view parameter_base)
Find a node in a device.
domain A domain of values
Definition: domain_base.hpp:23