Skip to content

Commit

Permalink
[patchers] Add support for sink messages
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Aug 30, 2024
1 parent eb95e68 commit a6b6d05
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 6 deletions.
14 changes: 8 additions & 6 deletions include/avnd/binding/max/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,23 +88,25 @@ static void process_generic_message(T& implementation, t_symbol* s)
template <typename Arg>
static constexpr bool compatible(short type)
{
if constexpr(requires(Arg arg) { arg = 0.f; })
return type == A_FLOAT || type == A_LONG;
else if constexpr(requires(Arg arg) { arg = "str"; })
// NOTE! has to be in this order as std::string x = 0.f; builds...
if constexpr(requires(Arg arg) { arg = "str"; })
return type == A_SYM;
else if constexpr(requires(Arg arg) { arg = 0.f; })
return type == A_FLOAT || type == A_LONG;

return false;
}

template <typename Arg>
static Arg convert(t_atom& atom)
{
if constexpr(std::floating_point<Arg>)
if constexpr(requires(Arg arg) { arg = "str"; })
return atom.a_w.w_sym->s_name;
else if constexpr(std::floating_point<Arg>)
return atom.a_type == A_FLOAT ? atom.a_w.w_float : atom.a_w.w_long;
else if constexpr(std::integral<Arg>)
return atom.a_type == A_LONG ? atom.a_w.w_long : atom.a_w.w_float;
else if constexpr(requires(Arg arg) { arg = "str"; })
return atom.a_w.w_sym->s_name;

else
static_assert(std::is_same_v<void, Arg>, "Argument type not handled yet");
}
Expand Down
23 changes: 23 additions & 0 deletions include/avnd/binding/max/messages.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ struct messages
{
bool ok = false;
std::string_view symname = s->s_name;

// First try to locate explicit messages
avnd::messages_introspection<T>::for_all(
avnd::get_messages(implementation), [&]<typename M>(M& field) {
if(ok)
Expand All @@ -175,6 +177,27 @@ struct messages
ok = process_message(implementation.effect, field, symname, argc, argv);
}
});

// If that fails try to look for a sink message which accepts anything
if(!ok)
{
avnd::messages_introspection<T>::for_all(
avnd::get_messages(implementation), [&]<typename M>(M& field) {
if(ok)
return;
if(avnd::tag_process_any_message<M>)
{
static thread_local std::vector<t_atom> atoms;
atoms.clear();
atoms.resize(argc + 1);
atoms[0] = t_atom{.a_type = A_SYM, .a_w = std::bit_cast<word>(s)};
for(int i = 0; i < argc; i++)
atoms[i + 1] = *argv;
ok = process_message(
implementation.effect, field, symname, atoms.size(), atoms.data());
}
});
}
return ok;
}
return false;
Expand Down
9 changes: 9 additions & 0 deletions include/avnd/concepts/message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/* SPDX-License-Identifier: GPL-3.0-or-later OR BSL-1.0 OR CC0-1.0 OR CC-PDCC OR 0BSD */

#include <avnd/common/concepts_polyfill.hpp>
#include <avnd/common/enums.hpp>
#include <avnd/common/function_reflection.hpp>
#include <avnd/concepts/generic.hpp>

Expand Down Expand Up @@ -131,4 +132,12 @@ using second_message_argument
template <typename M>
using third_message_argument
= boost::mp11::mp_third<typename message_reflection<M>::arguments>;

/**
* This tag indicates that the message accepts any command
* and ignores its own message name.
*/
AVND_DEFINE_TAG(process_any_message)
template <typename T>
concept any_message_port = tag_process_any_message<T>;
}

0 comments on commit a6b6d05

Please sign in to comment.