From 706a4c6e33f6aad1c884769f39bfd0bbdfe7ec87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Mon, 2 Oct 2023 00:05:13 -0400 Subject: [PATCH] [pd] Support much more data types for outlets --- .github/workflows/build_cmake.yml | 5 - cmake/avendish.cmake | 21 +- include/avnd/binding/pd/message_processor.hpp | 6 +- include/avnd/binding/pd/outputs.hpp | 185 ++++++++++++------ 4 files changed, 139 insertions(+), 78 deletions(-) diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index 677ef5a9..b910965a 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -106,11 +106,6 @@ jobs: chmod +x ./fetch-sdk.sh ./fetch-sdk.sh - - uses: maxim-lobanov/setup-xcode@v1 - if: matrix.config.name == 'macOS' - with: - xcode-version: latest-stable - - name: Build debug shell: bash run: | diff --git a/cmake/avendish.cmake b/cmake/avendish.cmake index 02b8ca3e..39f89f68 100644 --- a/cmake/avendish.cmake +++ b/cmake/avendish.cmake @@ -137,19 +137,20 @@ include(avendish.example) # Used for getting completion in IDEs... function(avnd_register) cmake_parse_arguments(AVND "" "TARGET;MAIN_FILE;MAIN_CLASS;C_NAME" "COMPILE_OPTIONS;COMPILE_DEFINITIONS;LINK_LIBRARIES" ${ARGN}) + if(NOT TARGET "${AVND_TARGET}") add_library("${AVND_TARGET}" STATIC $) + endif() - target_sources("${AVND_TARGET}" PRIVATE "${AVND_MAIN_FILE}") - if(AVND_COMPILE_OPTIONS) - target_compile_options("${AVND_TARGET}" PUBLIC "${AVND_COMPILE_OPTIONS}") - endif() - if(AVND_COMPILE_DEFINITIONS) - target_compile_definitions("${AVND_TARGET}" PUBLIC "${AVND_COMPILE_DEFINITIONS}") - endif() - if(AVND_LINK_LIBRARIES) - target_link_libraries("${AVND_TARGET}" PUBLIC "${AVND_LINK_LIBRARIES}") - endif() + target_sources("${AVND_TARGET}" PRIVATE "${AVND_MAIN_FILE}") + if(AVND_COMPILE_OPTIONS) + target_compile_options("${AVND_TARGET}" PUBLIC "${AVND_COMPILE_OPTIONS}") + endif() + if(AVND_COMPILE_DEFINITIONS) + target_compile_definitions("${AVND_TARGET}" PUBLIC "${AVND_COMPILE_DEFINITIONS}") + endif() + if(AVND_LINK_LIBRARIES) + target_link_libraries("${AVND_TARGET}" PUBLIC "${AVND_LINK_LIBRARIES}") endif() endfunction() diff --git a/include/avnd/binding/pd/message_processor.hpp b/include/avnd/binding/pd/message_processor.hpp index 92d611ba..bfb309d6 100644 --- a/include/avnd/binding/pd/message_processor.hpp +++ b/include/avnd/binding/pd/message_processor.hpp @@ -79,6 +79,8 @@ struct message_processor // Reserve space for controls this->control_buffers.reserve_space(implementation, 16); + avnd::prepare(implementation, {}); + /// Initialize controls if constexpr(avnd::has_inputs) { @@ -180,7 +182,7 @@ message_processor_metaclass::message_processor_metaclass() { message_processor_metaclass::instance = this; using instance = message_processor; - + /* #if !defined(_MSC_VER) static_assert(std::is_aggregate_v); static_assert(std::is_aggregate_v); @@ -188,7 +190,7 @@ message_processor_metaclass::message_processor_metaclass() static_assert(std::is_nothrow_move_constructible_v); static_assert(std::is_nothrow_move_assignable_v); #endif - +*/ /// Small wrapper methods which will call into our actual type /// // Ctor diff --git a/include/avnd/binding/pd/outputs.hpp b/include/avnd/binding/pd/outputs.hpp index 3e499e1e..c4ca7fba 100644 --- a/include/avnd/binding/pd/outputs.hpp +++ b/include/avnd/binding/pd/outputs.hpp @@ -10,6 +10,31 @@ namespace pd { template + requires std::is_arithmetic_v +inline void value_to_pd(t_atom& atom, T v) noexcept +{ + atom = {.a_type = A_FLOAT, .a_w = {.w_float = (t_float)v}}; +} + +inline void value_to_pd(t_atom& atom, bool v) noexcept +{ + atom = {.a_type = A_FLOAT, .a_w = {.w_float = v ? 1.0f : 0.0f}}; +} +inline void value_to_pd(t_atom& atom, const char* v) noexcept +{ + atom = {.a_type = A_SYMBOL, .a_w = {.w_symbol = gensym(v)}}; +} +inline void value_to_pd(t_atom& atom, std::string_view v) noexcept +{ + atom = {.a_type = A_SYMBOL, .a_w = {.w_symbol = gensym(v.data())}}; +} +inline void value_to_pd(t_atom& atom, const std::string& v) noexcept +{ + atom = {.a_type = A_SYMBOL, .a_w = {.w_symbol = gensym(v.c_str())}}; +} + +template + requires std::is_aggregate_v void value_to_pd(t_outlet* outlet, T v) { constexpr int sz = avnd::pfr::tuple_size_v; @@ -51,15 +76,102 @@ void value_to_pd(t_outlet* outlet, T v) } } -inline void value_to_pd(t_outlet* outlet, int v) noexcept +template + requires avnd::vector_ish +void value_to_pd(t_outlet* outlet, const T& v) { - outlet_float(outlet, v); + static thread_local std::vector atoms; + const int N = v.size(); + atoms.clear(); + atoms.resize(N); + + for(int i = 0; i < N; i++) + { + value_to_pd(atoms[i], v[i]); + } + outlet_list(outlet, &s_list, v.size(), atoms.data()); +} + +template + requires avnd::array_ish +void value_to_pd(t_outlet* outlet, const T& v) +{ + std::array atoms; + + for(int i = 0; i < N; i++) + { + value_to_pd(atoms[i], v[i]); + } + + outlet_list(outlet, &s_list, v.size(), atoms.data()); +} + +template + requires avnd::set_ish +void value_to_pd(t_outlet* outlet, const T& v) +{ + static thread_local std::vector atoms; + const int N = v.size(); + atoms.clear(); + atoms.resize(N); + + int i = 0; + for(auto& element : v) + { + value_to_pd(atoms[i++], element); + } + outlet_list(outlet, &s_list, v.size(), atoms.data()); +} + +template + requires avnd::map_ish +void value_to_pd(t_outlet* outlet, const T& v) +{ + static thread_local std::vector atoms; + const int N = v.size(); + atoms.clear(); + atoms.resize(2 * N); + + int i = 0; + for(auto& [key, value] : v) + { + value_to_pd(atoms[i++], key); + value_to_pd(atoms[i++], value); + } + outlet_list(outlet, &s_list, v.size(), atoms.data()); } -inline void value_to_pd(t_outlet* outlet, float v) noexcept + +template + requires avnd::variant_ish +void value_to_pd(t_outlet* outlet, const T& v) +{ + using namespace std; + visit(v, [&](const auto& element) { value_to_pd(outlet, element); }); +} + +template + requires avnd::pair_ish +void value_to_pd(t_outlet* outlet, const T& v) +{ + t_atom atoms[2]; + + value_to_pd(atoms[0], v.first); + value_to_pd(atoms[1], v.second); +} + +template + requires avnd::optional_ish +void value_to_pd(t_outlet* outlet, const T& v) +{ + if(v) + value_to_pd(outlet, *v); +} + +inline void value_to_pd(t_outlet* outlet, std::integral auto v) noexcept { outlet_float(outlet, v); } -inline void value_to_pd(t_outlet* outlet, double v) noexcept +inline void value_to_pd(t_outlet* outlet, std::floating_point auto v) noexcept { outlet_float(outlet, v); } @@ -135,69 +247,21 @@ struct value_writer template struct outputs { - template - static void init_func_view(call_type& call, t_outlet& outlet) + template typename F> + static void init_func_view(F& call, t_outlet& outlet) { - using func_t = typename call_type::type; - using refl = avnd::function_reflection_t; - call.context = &outlet; - call.function = nullptr; - if constexpr(refl::count == 0) - { - call.function = [](void* ptr) { - t_outlet* p = static_cast(ptr); - outlet_bang(p); - }; - } - else if constexpr(refl::count == 1) - { - if constexpr(std::is_same_v) - { - call.function = [](void* ptr, float f) { - t_outlet* p = static_cast(ptr); - outlet_float(p, f); - }; - } - else if constexpr(std::is_same_v) - { - call.function = [](void* ptr, const char* f) { - t_outlet* p = static_cast(ptr); - outlet_symbol(p, gensym(f)); - }; - } - } - else - { - AVND_STATIC_TODO(call_type); - } + call.function = [](void* ptr, Args... args) { + t_outlet* p = static_cast(ptr); + value_to_pd(p, std::forward(args)...); + }; } template typename F> static void init_func(F& call, t_outlet& outlet) { - using func_t = R(Args...); - using refl = avnd::function_reflection_t; - - if constexpr(refl::count == 0) - { - call = [&outlet] { outlet_bang(&outlet); }; - } - else if constexpr(refl::count == 1) - { - if constexpr(std::is_same_v) - { - call = [&outlet](float f) { outlet_float(&outlet, f); }; - } - else if constexpr(std::is_same_v) - { - call = [&outlet](const char* f) { outlet_symbol(&outlet, gensym(f)); }; - } - } - else - { - AVND_STATIC_TODO(F); - } + call + = [&outlet](Args... args) { value_to_pd(&outlet, std::forward(args)...); }; } template @@ -251,5 +315,4 @@ struct outputs std::array::size> outlets; }; - }