Skip to content

Commit

Permalink
[max] Add support for creating attributes in message processors
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Sep 13, 2023
1 parent b6997c1 commit 7bb4812
Show file tree
Hide file tree
Showing 24 changed files with 802 additions and 239 deletions.
4 changes: 4 additions & 0 deletions cmake/avendish.max.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,20 @@ function(avnd_make_max)
"${MAXSDK_MAX_INCLUDE_DIR}/common/commonsyms.c"

"${AVND_SOURCE_DIR}/include/avnd/binding/max/all.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/attributes_setup.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/atom_helpers.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/atom_iterator.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/audio_processor.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/configure.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/dsp.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/from_atoms.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/helpers.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/init.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/inputs.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/message_processor.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/messages.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/outputs.hpp"
"${AVND_SOURCE_DIR}/include/avnd/binding/max/to_atoms.hpp"
)

target_compile_definitions(
Expand Down
26 changes: 26 additions & 0 deletions cmake/avendish.sources.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ endif()
target_sources(Avendish
PUBLIC
"${AVND_SOURCE_DIR}/include/avnd/concepts/all.hpp"
"${AVND_SOURCE_DIR}/include/avnd/concepts/attributes.hpp"
"${AVND_SOURCE_DIR}/include/avnd/concepts/audio_port.hpp"
"${AVND_SOURCE_DIR}/include/avnd/concepts/audio_processor.hpp"
"${AVND_SOURCE_DIR}/include/avnd/concepts/callback.hpp"
Expand All @@ -27,6 +28,7 @@ target_sources(Avendish
"${AVND_SOURCE_DIR}/include/avnd/concepts/parameter.hpp"
"${AVND_SOURCE_DIR}/include/avnd/concepts/port.hpp"
"${AVND_SOURCE_DIR}/include/avnd/concepts/processor.hpp"
"${AVND_SOURCE_DIR}/include/avnd/concepts/schedule.hpp"
"${AVND_SOURCE_DIR}/include/avnd/concepts/soundfile.hpp"
"${AVND_SOURCE_DIR}/include/avnd/concepts/synth.hpp"

Expand Down Expand Up @@ -70,18 +72,42 @@ target_sources(Avendish
"${AVND_SOURCE_DIR}/include/avnd/common/struct_reflection.hpp"
"${AVND_SOURCE_DIR}/include/avnd/common/widechar.hpp"

"${AVND_SOURCE_DIR}/include/halp/attributes.hpp"
"${AVND_SOURCE_DIR}/include/halp/audio.hpp"
"${AVND_SOURCE_DIR}/include/halp/callback.hpp"
"${AVND_SOURCE_DIR}/include/halp/compat/gamma.hpp"
"${AVND_SOURCE_DIR}/include/halp/controls.basic.hpp"
"${AVND_SOURCE_DIR}/include/halp/controls.buttons.hpp"
"${AVND_SOURCE_DIR}/include/halp/controls.enums.hpp"
"${AVND_SOURCE_DIR}/include/halp/controls.hpp"
"${AVND_SOURCE_DIR}/include/halp/controls.sliders.gcc10.hpp"
"${AVND_SOURCE_DIR}/include/halp/controls.sliders.hpp"
"${AVND_SOURCE_DIR}/include/halp/controls.typedefs.hpp"
"${AVND_SOURCE_DIR}/include/halp/controls_fmt.hpp"
"${AVND_SOURCE_DIR}/include/halp/curve.hpp"
"${AVND_SOURCE_DIR}/include/halp/custom_widgets.hpp"
"${AVND_SOURCE_DIR}/include/halp/fft.hpp"
"${AVND_SOURCE_DIR}/include/halp/file_port.hpp"
"${AVND_SOURCE_DIR}/include/halp/geometry.hpp"
"${AVND_SOURCE_DIR}/include/halp/gradient_port.hpp"
"${AVND_SOURCE_DIR}/include/halp/inline.hpp"
"${AVND_SOURCE_DIR}/include/halp/layout.hpp"
"${AVND_SOURCE_DIR}/include/halp/log.hpp"
"${AVND_SOURCE_DIR}/include/halp/mappers.hpp"
"${AVND_SOURCE_DIR}/include/halp/messages.hpp"
"${AVND_SOURCE_DIR}/include/halp/meta.hpp"
"${AVND_SOURCE_DIR}/include/halp/midi.hpp"
"${AVND_SOURCE_DIR}/include/halp/midifile_port.hpp"
"${AVND_SOURCE_DIR}/include/halp/polyfill.hpp"
"${AVND_SOURCE_DIR}/include/halp/reactive_value.hpp"
"${AVND_SOURCE_DIR}/include/halp/sample_accurate_controls.hpp"
"${AVND_SOURCE_DIR}/include/halp/schedule.hpp"
"${AVND_SOURCE_DIR}/include/halp/smoothers.hpp"
"${AVND_SOURCE_DIR}/include/halp/soundfile_port.hpp"
"${AVND_SOURCE_DIR}/include/halp/static_string.hpp"
"${AVND_SOURCE_DIR}/include/halp/texture.hpp"
"${AVND_SOURCE_DIR}/include/halp/texture_formats.hpp"
"${AVND_SOURCE_DIR}/include/halp/value_types.hpp"

"${AVND_SOURCE_DIR}/include/gpp/commands.hpp"
"${AVND_SOURCE_DIR}/include/gpp/generators.hpp"
Expand Down
66 changes: 66 additions & 0 deletions examples/Helpers/Attributes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#pragma once
#include <halp/controls.hpp>
#include <halp/meta.hpp>
#include <iostream>

namespace examples::helpers
{

/**
*/
struct Attributes
{
halp_meta(name, "Attributes")
halp_meta(c_name, "avnd_attributes")
halp_meta(author, "Jean-Michaël Celerier")
halp_meta(category, "Devices")
halp_meta(description, "Test class attribute inputs")
halp_meta(uuid, "8a05bbf1-e8a5-44ec-8f37-b5e1d046bed8")
struct
{
struct : halp::val_port<"Index", int> {
halp_flag(class_attribute);

void update(Attributes& a) {
std::cerr << "Index: " << value << std::endl;
}
} device_index;

struct: halp::val_port<"Serial", std::string> {
halp_flag(class_attribute);
void update(Attributes& a) {
std::cerr << "Serial: " << value << std::endl;
}
} device_serial;

struct: halp::val_port<"Foo", int> {
void update(Attributes& a) {
std::cerr << "Foo: " << value << std::endl;
}
} foo;

struct: halp::val_port<"Connected", bool> {
halp_flag(class_attribute);
void update(Attributes& a) {
std::cerr << "Connected: " << value << std::endl;
}
} connected;

struct: halp::val_port<"Bar", int> {
void update(Attributes& a) {
std::cerr << "Bar: " << value << std::endl;
}
} bar;
} inputs;

struct
{
} outputs;

void operator()()
{

}
};

}
1 change: 1 addition & 0 deletions examples/Raw/Aggregate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <string>
#include <variant>
#include <vector>
#include <map>

namespace examples
{
Expand Down
2 changes: 2 additions & 0 deletions examples/Raw/Callback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct Callback
{
static consteval auto name() { return "bang"; }
halp::basic_callback<void(float)> call;
static_assert(avnd::function_view_ish<decltype(call)>);
} bang;

// Using std::function or similar should also work without issues:
Expand All @@ -56,6 +57,7 @@ struct Callback
{
static consteval auto name() { return "bong"; }
std::function<void(float)> call;
static_assert(avnd::function_ish<decltype(call)>);
} bong;

// TODO: std::function_ref.
Expand Down
75 changes: 75 additions & 0 deletions include/avnd/binding/max/atom_helpers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include <avnd/concepts/parameter.hpp>

#include <ext.h>
#include <string_view>

namespace max
{

template<typename>
inline t_symbol* get_atoms_sym() noexcept
{
return USESYM(atom);
}
template<std::integral>
inline t_symbol* get_atoms_sym() noexcept
{
return USESYM(long);
}
template<>
inline t_symbol* get_atoms_sym<bool>() noexcept
{
return USESYM(long);
}
template<>
inline t_symbol* get_atoms_sym<float>() noexcept
{
return USESYM(float32);
}
template<>
inline t_symbol* get_atoms_sym<double>() noexcept
{
return USESYM(float64);
}
template<>
inline t_symbol* get_atoms_sym<char>() noexcept
{
return USESYM(char);
}
template<>
inline t_symbol* get_atoms_sym<std::string_view>() noexcept
{
return USESYM(symbol);
}
template<>
inline t_symbol* get_atoms_sym<std::string>() noexcept
{
return USESYM(symbol);
}


template<typename F>
constexpr const char* get_atoms_style() noexcept
{
using V = decltype(F::value);
if constexpr(std::is_same_v<V, bool>)
return "onoff";
if constexpr(std::is_enum_v<V>)
return "enumindex";
if constexpr(std::is_same_v<V, std::string>)
return "text";
if constexpr(std::is_arithmetic_v<V>)
return "";
if constexpr(avnd::rgb_value<V>)
return "rgba";

// TODO:
// "enum"
// "rect"
// "font"
// "file"
return "";
}
}
88 changes: 88 additions & 0 deletions include/avnd/binding/max/attributes_setup.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#pragma once
#include <avnd/binding/max/atom_helpers.hpp>
#include <avnd/binding/max/from_atoms.hpp>
#include <avnd/binding/max/to_atoms.hpp>
#include <avnd/introspection/input.hpp>
#include <avnd/introspection/range.hpp>
#include <avnd/concepts/all.hpp>
#include <avnd/concepts/field_names.hpp>
#include <avnd/common/aggregates.hpp>
#include <avnd/common/for_nth.hpp>
#include <avnd/wrappers/metadatas.hpp>
#include <ext.h>

namespace max
{
template <typename Processor, typename T>
struct attribute_register
{
t_class* c{};

template<std::size_t I>
static t_max_err getter(Processor* x, void*, long* ac, t_atom** av)
{
auto& ins = avnd::get_inputs(x->implementation.effect);
auto& field = avnd::input_introspection<T>::template field<I>(ins);

return to_atoms{ac, av}(field.value);
}

template<std::size_t I>
static t_max_err setter(Processor *x, void *attr, long ac, t_atom *av)
{
if (ac && av) {
auto& obj = x->implementation.effect;
auto& ins = avnd::get_inputs(obj);
auto& field = avnd::input_introspection<T>::template field<I>(ins);

if(from_atoms{ac, av}(field.value))
{
if constexpr(requires { field.update(obj); })
{
field.update(obj);
}
}
}
return MAX_ERR_NONE;
};

template<std::size_t I, typename F>
void operator()(avnd::field_reflection<I, F>) {
using V = decltype(F::value);
static constexpr auto name = avnd::get_name<F>();

t_symbol* sym = get_atoms_sym<V>();
if(sym)
{
static constexpr auto get = &attribute_register::getter<I>;
static constexpr auto set = &attribute_register::setter<I>;
auto attr = attribute_new(name.data(), sym, 0, (method)get, (method)set);
class_addattr(c, attr);
CLASS_ATTR_LABEL(c, name.data(), 0, name.data());

if(static constexpr auto style = get_atoms_style<F>(); strlen(style) > 0)
CLASS_ATTR_STYLE(c, name.data(), 0, style);

if constexpr(avnd::parameter_with_minmax_range<V>)
{
static constexpr auto range = avnd::get_range<V>();
CLASS_ATTR_FILTER_CLIP(c, name.data(), range.min, range.max);
const auto init = std::to_string(range.init);
CLASS_ATTR_DEFAULT(c, name.data(), 0, init.c_str());
}

// TODO:
// CLASS_ATTR_SAVE(c, attrname, flags) < saved by the patcher
// CLASS_ATTR_SELFSAVE(c, attrname, flags) < saved in its own way
// CLASS_ATTR_ENUM(c, attrname, flags, parsestr) < parsestr == "v1 v2 v3"
// CLASS_ATTR_ENUMINDEX(c, attrname, flags, parsestr)
// CLASS_ATTR_CATEGORY(c, attrname, flags, parsestr)
// CLASS_ATTR_BASIC(c, attrname, flags)
// CLASS_ATTR_OBSOLETE(c, attrname, flags)
// CLASS_ATTR_INTRODUCED(c, attrname, flags, versionstr)
// CLASS_ATTR_INVISIBLE(c,attrname,flags)
}
}
};

}
5 changes: 5 additions & 0 deletions include/avnd/binding/max/audio_processor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,15 @@ audio_processor_metaclass<T>::audio_processor_metaclass()
constexpr auto obj_new = +[](t_symbol* s, int argc, t_atom* argv) -> void* {
// Initializes the t_object
auto* ptr = object_alloc(g_class);
t_object tmp;
memcpy(&tmp, ptr, sizeof(t_object));

// Initializes the rest
auto obj = reinterpret_cast<instance*>(ptr);
new(obj) instance;

memcpy(&obj->x_obj, &tmp, sizeof(t_object));

obj->init(argc, argv);
return obj;
};
Expand Down
Loading

0 comments on commit 7bb4812

Please sign in to comment.