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>
11#include <oscpack/osc/OscPrintReceivedElements.h>
12#include <oscpack/osc/OscReceivedElements.h>
14namespace ossia::minuit
16template <minuit_command Req, minuit_operation Op>
21 const oscpack::ReceivedMessage& mess);
24template <minuit_operation Op>
25struct minuit_behavior<minuit_command::Error, Op>
29 const oscpack::ReceivedMessage& mess)
35struct minuit_behavior<minuit_command::Error, minuit_operation::Get>
39 const oscpack::ReceivedMessage& mess)
42 if(mess.ArgumentCount() > 0)
44 auto beg = mess.ArgumentsBegin();
47 proto.get_refreshed(beg->AsStringUnchecked());
55struct minuit_behavior<minuit_command::Request, minuit_operation::Get>
59 const oscpack::ReceivedMessage& mess)
61 std::string_view full_address{mess.ArgumentsBegin()->AsString()};
62 auto idx = full_address.find_first_of(
":");
64 if(idx == std::string::npos)
67 auto node = ossia::net::find_node(dev.get_root_node(), full_address);
70 auto addr = node->get_parameter();
75 proto.name_table.get_action(minuit_action::GetReply), full_address,
80 std::string_view address{full_address.data(), idx};
84 std::string_view(address.data() + idx + 1, full_address.size() - idx - 1));
86 auto node = ossia::net::find_node(dev.get_root_node(), address);
89 auto addr = node->get_parameter();
95 case minuit_attribute::Value:
97 proto.name_table.get_action(minuit_action::GetReply), full_address,
100 case minuit_attribute::Type:
102 proto.name_table.get_action(minuit_action::GetReply), full_address,
103 to_minuit_type_text(addr->get_value_type()));
105 case minuit_attribute::RangeBounds:
107 if(
auto dom = addr->get_domain())
109 auto v0 = dom.convert_min<
float>();
110 auto v1 = dom.convert_max<
float>();
112 proto.name_table.get_action(minuit_action::GetReply), full_address,
117 case minuit_attribute::RangeClipMode:
119 proto.name_table.get_action(minuit_action::GetReply), full_address,
120 to_minuit_bounding_text(addr->get_bounding()));
122 case minuit_attribute::Dataspace:
124 proto.name_table.get_action(minuit_action::GetReply), full_address,
127 case minuit_attribute::DataspaceUnit:
129 proto.name_table.get_action(minuit_action::GetReply), full_address,
132 case minuit_attribute::RepetitionFilter:
134 proto.name_table.get_action(minuit_action::GetReply), full_address,
135 (int32_t)addr->get_repetition_filter());
137 case minuit_attribute::Service:
139 proto.name_table.get_action(minuit_action::GetReply), full_address,
140 to_minuit_service_text(addr->get_access()));
142 case minuit_attribute::Description:
143 if(
const auto& desc = ossia::net::get_description(*node))
145 proto.name_table.get_action(minuit_action::GetReply), full_address,
148 case minuit_attribute::Priority:
149 if(
const auto& priority = ossia::net::get_priority(*node))
151 proto.name_table.get_action(minuit_action::GetReply), full_address,
155 proto.name_table.get_action(minuit_action::GetReply), full_address, 0);
157 case minuit_attribute::ValueStepSize:
158 if(
const auto& ss = ossia::net::get_value_step_size(*node))
160 proto.name_table.get_action(minuit_action::GetReply), full_address, *ss);
172struct minuit_behavior<minuit_command::Request, minuit_operation::Listen>
176 const oscpack::ReceivedMessage& mess)
184struct minuit_behavior<minuit_command::Request, minuit_operation::Namespace>
186 void handle_root(ossia::net::minuit_protocol& proto,
const std::vector<std::string>& c)
189 proto.name_table.get_action(minuit_action::NamespaceReply),
"/",
"Application",
190 "nodes={", c,
"}",
"attributes={",
"}");
191 std::this_thread::sleep_for(std::chrono::milliseconds(1));
194 void handle_container(
195 ossia::net::minuit_protocol& proto, std::string_view address,
196 const std::vector<std::string>& c)
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));
204 void handle_data(ossia::net::minuit_protocol& proto, std::string_view address)
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));
213 void handle_data_container(
214 ossia::net::minuit_protocol& proto, std::string_view address,
215 const std::vector<std::string>& c)
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));
224 std::vector<std::string>
227 auto node = ossia::net::find_node(dev.get_root_node(), address);
231 return node->children_names();
236 const oscpack::ReceivedMessage& mess)
238 std::string_view address{mess.ArgumentsBegin()->AsString()};
240 if(address == std::string_view(
"/"))
242 handle_root(proto, get_children_names(dev, address));
246 auto node = ossia::net::find_node(dev.get_root_node(), address);
250 if(node->children().empty())
252 handle_data(proto, address);
256 if(node->get_parameter())
258 handle_data_container(proto, address, get_children_names(dev, address));
262 handle_container(proto, address, get_children_names(dev, address));
271struct osc_inbound_numeric_visitor
273 osc_inbound_numeric_visitor(oscpack::ReceivedMessageArgumentIterator cur)
278 oscpack::ReceivedMessageArgumentIterator cur_it;
279 ossia::value operator()(ossia::impulse imp)
const {
return imp; }
283 return ossia::net::osc_utilities::get_int(cur_it, i);
288 return ossia::net::osc_utilities::get_float(cur_it, f);
293 return ossia::net::osc_utilities::get_bool(cur_it, b);
298 return ossia::net::osc_utilities::get_char(cur_it, c);
301 ossia::value operator()(
const std::string& str)
const {
return str; }
303 template <std::
size_t N>
306 return ossia::net::osc_utilities::get_float(cur_it, vec[0]);
309 ossia::value operator()(
const std::vector<ossia::value>& t)
311 return ossia::net::osc_utilities::get_float(
312 cur_it, !t.empty() ? ossia::convert<float>(t[0]) : 0.f);
315 ossia::value operator()(
const value_map_type& t) {
return {}; }
320 const ossia::value& current, oscpack::ReceivedMessageArgumentIterator beg_it,
321 oscpack::ReceivedMessageArgumentIterator end_it)
324 return current.apply(osc_inbound_numeric_visitor{beg_it});
326 return current.apply(ossia::net::osc_inbound_impulse_visitor{});
331 oscpack::ReceivedMessageArgumentIterator end_it)
333 ossia::small_vector<ossia::value, 2> val;
334 const auto cur = addr.
value();
337 while(beg_it != end_it)
339 auto cur_it = beg_it;
341 val.push_back(to_numeric_value(cur, cur_it, beg_it));
344 return ossia::make_domain_from_osc(val, cur);
347inline std::optional<double> AsNumber(oscpack::ReceivedMessageArgumentIterator& it)
349 switch(it->TypeTag())
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();
366struct minuit_behavior<minuit_command::Answer, minuit_operation::Listen>
370 const oscpack::ReceivedMessage& mess)
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(
":");
377 if(idx == std::string::npos)
380 auto node = ossia::net::find_node(dev.get_root_node(), full_address);
383 if(
auto addr = node->get_parameter())
385 if(
auto v = ossia::net::get_filtered_value(
386 *addr, ++mess_it, mess.ArgumentsEnd(), mess.ArgumentCount() - 1);
389 addr->set_value(std::move(v));
398 std::string_view address{full_address.data(), idx};
402 std::string_view(address.data() + idx + 1, full_address.size() - idx - 1));
407 if(
auto node = ossia::net::find_node(dev.get_root_node(), address))
408 if(
auto addr = node->get_parameter())
411 case minuit_attribute::Value: {
412 if(
auto v = ossia::net::get_filtered_value(
413 *addr, mess_it, mess.ArgumentsEnd(), mess.ArgumentCount() - 1);
416 addr->set_value(std::move(v));
420 case minuit_attribute::Type: {
421 addr->set_value_type(ossia::minuit::type_from_minuit_type_text(
422 mess_it->AsStringUnchecked()));
426 case minuit_attribute::RangeBounds: {
427 addr->set_domain(get_domain(*addr, mess_it, mess.ArgumentsEnd()));
430 case minuit_attribute::RangeClipMode: {
432 from_minuit_bounding_text(mess_it->AsStringUnchecked()));
435 case minuit_attribute::RepetitionFilter: {
436 addr->set_repetition_filter(
440 case minuit_attribute::Dataspace: {
444 case minuit_attribute::DataspaceUnit: {
449 case minuit_attribute::Service: {
450 addr->set_access(from_minuit_service_text(mess_it->AsStringUnchecked()));
453 case minuit_attribute::Description: {
454 ossia::net::set_description(
455 *node, std::string(mess_it->AsStringUnchecked()));
458 case minuit_attribute::Priority: {
459 ossia::net::set_priority(*node, mess_it->AsInt32());
462 case minuit_attribute::ValueStepSize: {
463 ossia::net::set_value_step_size(*node, AsNumber(mess_it));
476struct minuit_behavior<minuit_command::Answer, minuit_operation::Get>
481 const oscpack::ReceivedMessage& mess)
483 auto addr = minuit_behavior<minuit_command::Answer, minuit_operation::Listen>{}(
485 proto.get_refreshed(addr);
489template <
typename It,
typename Fun>
490auto find_if(It begin, It end, Fun f)
492 for(
auto it = begin; it != end; ++it)
502struct minuit_behavior<minuit_command::Answer, minuit_operation::Namespace>
504 template <
typename Str>
505 static auto get_container(
506 Str s, oscpack::ReceivedMessageArgumentIterator beg_it,
507 oscpack::ReceivedMessageArgumentIterator end_it)
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;
515 if(nodes_beg_it != end_it)
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';
522 if(nodes_end_it != end_it)
524 for(
auto it = nodes_beg_it; it != nodes_end_it; ++it)
526 elements.push_back(it->AsStringUnchecked());
534 static auto get_nodes(
535 oscpack::ReceivedMessageArgumentIterator beg_it,
536 oscpack::ReceivedMessageArgumentIterator end_it)
538 return get_container(
"nodes={", beg_it, end_it);
541 static auto get_attributes(
542 oscpack::ReceivedMessageArgumentIterator beg_it,
543 oscpack::ReceivedMessageArgumentIterator end_it)
545 return get_container(
"attributes={", beg_it, end_it);
548 static auto handle_container(
550 std::string_view address, oscpack::ReceivedMessageArgumentIterator beg_it,
551 oscpack::ReceivedMessageArgumentIterator end_it)
553 using namespace oscpack;
554 auto sub_request = proto.name_table.get_action(minuit_action::NamespaceRequest);
557 std::string child_address{address};
558 if(child_address.back() !=
'/')
559 child_address +=
'/';
560 const auto child_parameter_size = child_address.size();
562 for(
auto child : get_nodes(beg_it, end_it))
564 child_address.resize(child_parameter_size);
567 child_address.append(child.begin(), child.end());
570 ossia::net::find_or_create_node(dev.get_root_node(), address);
573 proto.namespace_refresh(sub_request, child_address);
577 static auto handle_data(
579 std::string_view address, oscpack::ReceivedMessageArgumentIterator beg_it,
580 oscpack::ReceivedMessageArgumentIterator end_it)
582 using namespace oscpack;
585 auto& n = ossia::net::find_or_create_node(dev.get_root_node(), address);
589 handle_container(proto, dev, address, beg_it, end_it);
591 auto sub_request = proto.name_table.get_action(minuit_action::GetRequest);
601 auto attribs = get_attributes(beg_it, end_it);
602 for(
auto it = attribs.begin(); it != attribs.end();)
606 case minuit_attribute::Type:
607 case minuit_attribute::Dataspace: {
609 auto str = std::string(address);
611 str.append(it->begin(), it->end());
612 proto.get_refresh(sub_request, str, std::promise<void>{});
614 it = attribs.erase(it);
623 for(
auto attrib : attribs)
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: {
637 auto str = std::string(address);
639 str.append(attrib.begin(), attrib.end());
640 proto.get_refresh(sub_request, str, std::promise<void>{});
648 static auto handle_minuit(
650 std::string_view address, minuit_type type,
651 oscpack::ReceivedMessageArgumentIterator beg_it,
652 oscpack::ReceivedMessageArgumentIterator end_it)
656 case minuit_type::Application:
657 case minuit_type::Container: {
658 handle_container(proto, dev, address, beg_it, end_it);
661 case minuit_type::Data: {
662 handle_data(proto, dev, address, beg_it, end_it);
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);
676 const oscpack::ReceivedMessage& mess)
678 auto it = mess.ArgumentsBegin();
679 std::string_view address = it->AsString();
680 auto type = get_type((++it)->AsString()[0]);
682 handle_minuit(proto, dev, address, type, it, mess.ArgumentsEnd());
684 proto.namespace_refreshed(address);
694class minuit_message_handler
697 static void handleMinuitMessage(
699 std::string_view address,
const oscpack::ReceivedMessage& m)
702 auto idx = address.find_first_of(
":?!");
704 if(idx != std::string::npos)
706 auto req = get_command(address[idx]);
707 auto op = get_operation(*(address.data() + idx + 1));
710 case minuit_command::Answer:
714 case minuit_operation::Listen:
715 minuit_behavior<minuit_command::Answer, minuit_operation::Listen>{}(
718 case minuit_operation::Get:
719 minuit_behavior<minuit_command::Answer, minuit_operation::Get>{}(
722 case minuit_operation::Namespace:
723 minuit_behavior<minuit_command::Answer, minuit_operation::Namespace>{}(
731 case minuit_command::Request:
735 case minuit_operation::Listen:
736 minuit_behavior<minuit_command::Request, minuit_operation::Listen>{}(
739 case minuit_operation::Get:
740 minuit_behavior<minuit_command::Request, minuit_operation::Get>{}(
743 case minuit_operation::Namespace:
744 minuit_behavior<minuit_command::Request, minuit_operation::Namespace>{}(
752 case minuit_command::Error:
756 case minuit_operation::Listen:
757 minuit_behavior<minuit_command::Error, minuit_operation::Listen>{}(
760 case minuit_operation::Get:
761 minuit_behavior<minuit_command::Error, minuit_operation::Get>{}(
764 case minuit_operation::Namespace:
765 minuit_behavior<minuit_command::Error, minuit_operation::Namespace>{}(
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
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
domain A domain of values
Definition domain_base.hpp:23