Supported port types

The supported port types depend on the back-end. There is, however, some flexibility.

Simple ports

Float

They should work everywhere.

struct {
  float value;
} my_port;

Double

They will not work in Max / Pd message processors (but will work in Max / Pd audio processors) as their API expect a pointer to an existing float value.

struct {
  double value;
} my_port;

Int

Same than double.

struct {
  int value;
} my_port;

Bool

Same than double.

struct {
  bool value;
} my_port;

Note that depending on the widget you use, UIs may create a toggle, a maintained button or a momentary bang.

String

Will not work in environments such as VST3 for obvious reasons.

struct {
  std::string value;
} my_port;

Enumerations

Enumerations are interesting. There are multiple ways to implement them.

Mapping a string to a value

Consider the following port:

template<typename T>
using my_pair = std::pair<std::string_view, T>;
struct {
  halp_meta(name, "Enum 1");
  enum widget { combobox };

  struct range {
    my_pair<float> values[3]{{"Foo", -10.f}, {"Bar", 5.f}, {"Baz", 10.f}};
    int init{1}; // == Bar
  };

  float value{}; // Will be initialized to 5.f
} combobox;

Here, using a range definition of the form:

struct range {
  <string -> value map> values[N] = {
    { key_1, value_1}, { key_2, value_2 }, ...
  };

  <integer> init = /* initial index */;
};

allows to initialize a combobox in the UI, with a predetermined set of values. The value type is the actual one which will be used for the port - Avendish will translate as needed.

Enumerating with only string

Consider the following port:

struct {
  halp_meta(name, "Enum 2");
  enum widget { enumeration };

  struct range {
    std::string_view values[4]{"Roses", "Red", "Violets", "Blue"};
    int init{1}; // Red
  };

  std::string_view value;
};

Here, we can use std::string_view: the assigned value will always be one from the range::values array ; these strings live in static memory so there is no need to duplicate them in an std::string.

It is also possible to use an int for the port value:

struct {
  halp_meta(name, "Enum 3");
  enum widget { enumeration };

  struct range {
    std::string_view values[4]{"Roses", "Red", "Violets", "Blue"};
    int init{1}; // Red
  };

  int value{};
};

Here, the int will just be the index of the selected thing.

Enumerating with proper enums :-)

Finally, we can also use actual enums.

enum my_enum { A, B, C };
struct {
  halp_meta(name, "Enum 3");
  enum widget { enumeration };

  struct range
  {
    std::string_view values[3]{"A", "B", "C"};
    my_enum init = my_enum::B;
  };

  my_enum value{};
}

The enum must be contiguous, representable in an int32 and start at 0: enum { A = 3, B, C }; will not work. enum { A, B, C, AA = 10 }; will not work. enum { A, B, C, ... 4 billion values later ..., XXXX }; will not work. enum { A, B, C }; will work.

An helper is provided, which is sadly a macro as we cannot do proper enum reflection yet:

halp__enum("Simple Enum", Peg, Square, Peg, Round, Hole) my_port;

declares a port named "Simple Enum". The default value will be "Peg", the 4 enumerators are Square, Peg, Round, Hole.

Advanced types

2D position: xy

Here a special shape of struct is recognized:

struct {
  struct { float x, y; } value;
} my_port;

Color

Here a special shape of struct is recognized:

struct {
  struct { float r, g, b, a; } value;
} my_port;