3#include <ossia/detail/fmt.hpp>
5#include <ossia/network/domain/domain.hpp>
7#include <ossia-pd/src/client.hpp>
8#include <ossia-pd/src/model.hpp>
9#include <ossia-pd/src/object_base.hpp>
10#include <ossia-pd/src/ossia-pd.hpp>
11#include <ossia-pd/src/parameter.hpp>
12#include <ossia-pd/src/remote.hpp>
13#include <ossia-pd/src/view.hpp>
21template <
typename TimeT = std::chrono::microseconds>
24 template <
typename F,
typename... Args>
25 static typename TimeT::rep execution(F&& func, Args&&... args)
27 auto start = std::chrono::steady_clock::now();
29 std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
31 = std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now() - start);
32 return duration.count();
36#pragma mark Value type conversion helper
40 std::vector<t_atom>& data;
41 void operator()(impulse)
const
44 SETSYMBOL(&a, gensym(
"bang"));
48 void operator()(int32_t i)
const
51 SETFLOAT(&a, (t_float)i);
55 void operator()(
float f)
const
62 void operator()(
bool b)
const
65 t_float f = b ? 1. : 0.;
70 void operator()(
const std::string& str)
const
72 t_symbol* s = gensym(str.c_str());
78 void operator()(
char c)
const
81 SETFLOAT(&a, (
float)c);
85 template <std::
size_t N>
86 void operator()(std::array<float, N> vec)
const
88 data.reserve(data.size() + N);
89 for(std::size_t i = 0; i < N; i++)
97 void operator()(
const std::vector<ossia::value>& t)
const
99 data.reserve(data.size() + t.size());
100 for(
const auto& v : t)
104 void operator()(
const ossia::value_map_type& t)
const
109 void operator()()
const { }
117 void operator()(impulse)
const
124 outlet_bang(x->m_dataout);
127 outlet_bang(x->m_setout);
129 void operator()(int32_t i)
const
132 SETFLOAT(&a, (t_float)i);
134 outlet_float(x->m_dataout, (t_float)i);
137 outlet_anything(x->m_setout, ossia_pd::o_sym_set, 1, &a);
139 void operator()(
float f)
const
144 outlet_float(x->m_dataout, (t_float)f);
147 outlet_anything(x->m_setout, ossia_pd::o_sym_set, 1, &a);
149 void operator()(
bool b)
const
152 t_float f = b ? 1. : 0.;
155 outlet_float(x->m_dataout, f);
158 outlet_anything(x->m_setout, ossia_pd::o_sym_set, 1, &a);
160 void operator()(
const std::string& str)
const
162 t_symbol* s = gensym(str.c_str());
166 outlet_symbol(x->m_dataout, s);
169 outlet_anything(x->m_setout, ossia_pd::o_sym_set, 1, &a);
172 template <std::
size_t N>
173 void operator()(std::array<float, N> vec)
const
177 for(std::size_t i = 0; i < N; i++)
179 SETFLOAT(a + i, vec[i]);
183 outlet_list(x->m_dataout, gensym(
"list"), N, a);
186 outlet_anything(x->m_setout, ossia_pd::o_sym_set, N, a);
189 void operator()(
const std::vector<ossia::value>& t)
const
191 std::vector<t_atom> va;
197 for(
const auto& v : t)
200 t_atom* list_ptr = !va.empty() ? va.data() :
nullptr;
202 outlet_list(x->m_dataout, gensym(
"list"), va.size(), list_ptr);
205 outlet_anything(x->m_setout, ossia_pd::o_sym_set, va.size(), list_ptr);
208 void operator()(
const ossia::value_map_type& t)
const { }
210 void operator()()
const { pd_error(x,
"%s received invalid data", x->m_name->s_name); }
217 template <
typename T>
218 void operator()(ossia::domain_base<T>& d)
223 SETFLOAT(x->m_range, *d.min);
224 SETFLOAT(x->m_range + 1, *d.max);
230 SETFLOAT(x->m_min, *d.min);
236 SETFLOAT(x->m_max, *d.max);
240 void operator()(ossia::domain_base<bool>& d)
245 void operator()(ossia::domain_base<impulse>& d)
249 void operator()(ossia::domain_base<std::string> d)
251 if(!d.values.empty())
253 x->m_range_size = d.values.size() > OSSIA_PD_MAX_ATTR_SIZE ? OSSIA_PD_MAX_ATTR_SIZE
255 for(
int i = 0; i < x->m_range_size; i++)
261 void operator()(ossia::domain_base<ossia::value> d)
270 if(!d.values.empty())
275 template <std::
size_t N>
276 void operator()(ossia::vecf_domain<N>& d)
279 = d.min.size() > OSSIA_PD_MAX_ATTR_SIZE ? OSSIA_PD_MAX_ATTR_SIZE : d.min.size();
281 = d.max.size() > OSSIA_PD_MAX_ATTR_SIZE ? OSSIA_PD_MAX_ATTR_SIZE : d.max.size();
283 for(
int i = 0; i < x->m_max_size; i++)
284 atom_setfloat(&x->m_max[i], *d.max[i]);
286 for(
int i = 0; i < x->m_min_size; i++)
287 atom_setfloat(&x->m_min[i], *d.min[i]);
290 if(x->m_min_size == x->m_max_size && x->m_min_size > 1)
293 for(
int i = 1; i < x->m_min_size && flag; i++)
295 flag |= *d.min[0] == *d.min[i];
296 flag |= *d.max[0] == *d.max[i];
303 atom_setfloat(&x->m_range[0], *d.min[0]);
304 atom_setfloat(&x->m_range[1], *d.max[0]);
309 void operator()(ossia::vector_domain& d)
311 std::vector<t_atom> vamin, vamax;
312 value2atom minvisitor{vamin};
313 value2atom maxvisitor{vamax};
316 = vamin.size() > OSSIA_PD_MAX_ATTR_SIZE ? OSSIA_PD_MAX_ATTR_SIZE : vamin.size();
318 = vamax.size() > OSSIA_PD_MAX_ATTR_SIZE ? OSSIA_PD_MAX_ATTR_SIZE : vamax.size();
320 for(
const auto& v : d.
min)
322 for(
unsigned int i = 0; i < vamin.size(); i++)
323 x->m_min[i] = vamin[i];
325 for(
const auto& v : d.
max)
327 for(
unsigned int i = 0; i < vamax.size(); i++)
328 x->m_max[i] = vamax[i];
333 void operator()() { }
336ossia::value atom2value(t_symbol* s,
int argc, t_atom* argv);
338#pragma mark Prototype
340std::vector<std::string> parse_tags_symbol(t_symbol* tags_symbol);
341std::string string_from_path(
const std::vector<std::string>& vs);
346void register_quarantinized();
349std::vector<T*> get_objects(
typename T::is_model* =
nullptr)
351 return ossia_pd::instance().models.copy();
355std::vector<T*> get_objects(
typename T::is_device* =
nullptr)
357 return ossia_pd::instance().devices.copy();
361std::vector<T*> get_objects(
typename T::is_client* =
nullptr)
363 return ossia_pd::instance().clients.copy();
367std::vector<T*> get_objects(
typename T::is_attribute* =
nullptr)
369 return ossia_pd::instance().attributes.copy();
373std::vector<T*> get_objects(
typename T::is_parameter* =
nullptr)
375 return ossia_pd::instance().parameters.copy();
379std::vector<T*> get_objects(
typename T::is_remote* =
nullptr)
381 return ossia_pd::instance().remotes.copy();
385std::vector<T*> get_objects(
typename T::is_view* =
nullptr)
387 return ossia_pd::instance().views.copy();
405T* find_parent(object_base* x,
unsigned int start_level,
int* level)
407 if(start_level > x->m_patcher_hierarchy.size())
411 std::vector<T*> objects = get_objects<T>();
418 return obj->m_patcher_hierarchy.size() > x->m_patcher_hierarchy.size();
423 ossia::remove_one(objects, x);
427 ossia::sort(objects, [](
auto o1,
auto o2) {
428 return o1->m_patcher_hierarchy.size() > o2->m_patcher_hierarchy.size();
431 for(
unsigned int i = start_level; i < x->m_patcher_hierarchy.size(); i++)
434 auto size = x->m_patcher_hierarchy.size() - i;
437 objects, [&](T* obj) {
return obj->m_patcher_hierarchy.size() > size; }),
440 for(
auto o : objects)
442 if(x->m_patcher_hierarchy[i] == o->m_patcher_hierarchy[0])
456std::string replace_brackets(
const string_view);
467static inline T* find_parent_alive(object_base* x,
int start_level,
int* level)
469 T* obj = find_parent<T>(x, start_level, level);
472 while(obj && obj->m_dead)
474 obj = find_parent_alive<T>(obj, 1, level);
477 assert(!obj || !obj->m_dead);
483std::string get_absolute_path(object_base* x);
490const std::vector<t_matcher>& find_parent_node(object_base* x);
500std::vector<object_base*>
501find_child_to_register(object_base* x, t_gobj* start_list, t_symbol* classname);
508bool find_peer(object_base* x);
515std::vector<ossia::net::node_base*> find_global_nodes(ossia::string_view addr);
523std::vector<ossia::value> attribute2value(t_atom* atom,
long size);
550std::vector<ossia::pd::t_matcher*>
555#pragma mark Templates
569bool ossia_register(T* x)
574 std::vector<t_matcher> tmp;
575 std::vector<t_matcher>* matchers = &tmp;
576 std::vector<ossia::net::node_base*> nodes;
578 if(x->m_addr_scope == ossia::net::address_scope::global)
580 std::string addr = x->m_name->s_name;
581 if(x->m_otype == object_class::param || x->m_otype == object_class::model)
584 while(pos != std::string::npos && nodes.empty())
587 pos = addr.find_last_of(
'/');
588 if(pos < addr.size())
590 addr = addr.substr(0, pos);
592 nodes = ossia::pd::find_global_nodes(addr +
"/");
598 nodes = ossia::pd::find_global_nodes(addr);
601 tmp.reserve(nodes.size());
604 tmp.emplace_back(n, (object_base*)
nullptr);
609 std::pair<int, ossia::pd::device*> device{};
610 device.second = find_parent_alive<ossia::pd::device>(x, 0, &device.first);
612 std::pair<int, ossia::pd::client*> client{};
613 client.second = find_parent_alive<ossia::pd::client>(x, 0, &client.first);
615 std::pair<int, ossia::pd::model*> model{};
616 std::pair<int, ossia::pd::view*> view{};
619 if(x->m_otype == object_class::view || x->m_otype == object_class::model)
624 if(x->m_addr_scope == net::address_scope::relative)
627 if(x->m_otype == object_class::view || x->m_otype == object_class::remote)
629 view.second = find_parent_alive<ossia::pd::view>(x, start_level, &view.first);
634 model.second = find_parent_alive<ossia::pd::model>(x, 0, &model.first);
638 std::vector<std::pair<int, object_base*>> vec{device, client, model, view};
640 std::sort(vec.begin(), vec.end());
646 matchers = &p.second->m_matchers;
651 if(matchers == &tmp && x->m_addr_scope != ossia::net::address_scope::global)
654 &ossia_pd::get_default_device()->get_root_node(), (object_base*)
nullptr);
658 return x->register_node(*matchers);
662void ossia_check_and_register(T* x)
664 auto& map = ossia_pd::instance().m_root_patcher;
665 auto it = map.find(x->m_patcher_hierarchy.back());
669 if(it != map.end() && it->second.is_loadbanged)
674void address_mess_cb(T* x, t_symbol* address)
677 std::string name = replace_brackets(address->s_name);
678 x->m_name = gensym(name.c_str());
679 x->m_addr_scope = ossia::net::get_address_scope(x->m_name->s_name);
686bool obj_is_quarantined(T* x)
688 return x->quarantine().contains(x);
692void obj_quarantining(T* x)
694 x->quarantine().push_back(x);
698void obj_dequarantining(T* x)
700 x->quarantine().remove_all(x);
The node_base class.
Definition node.hpp:48
The value class.
Definition value.hpp:173
OSSIA_INLINE constexpr auto min(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
min function tailored for values
Definition math.hpp:125
val_type
Enum to represent the types that a value can take.
Definition parameter_properties.hpp:16
bounding_mode
Address behaviors at crossing domain boundaries.
Definition parameter_properties.hpp:56
access_mode
Address behaviors at crossing domain boundaries time.
Definition parameter_properties.hpp:46
OSSIA_INLINE constexpr auto max(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
max function tailored for values
Definition math.hpp:96