From 9e4d8bf22e485d33404873b298c21292f9c5f945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Mon, 30 Sep 2024 20:07:07 -0400 Subject: [PATCH] [pd] Handle variants as input in right-inlets --- .gitignore | 2 + docs/max-examples.maxpat | 114 ++++++++++++- docs/pd-examples.pd | 150 +++++++++++------- examples/Complete/CompleteMessageExample.pd | 2 +- examples/Raw/Variant.hpp | 2 - include/avnd/binding/pd/helpers.hpp | 8 +- include/avnd/binding/pd/inputs.hpp | 9 +- include/avnd/binding/pd/message_processor.hpp | 7 +- 8 files changed, 219 insertions(+), 75 deletions(-) diff --git a/.gitignore b/.gitignore index a20d303e..fde7e150 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*.mxe64 +*.mxo *.dll *.dylib book/book diff --git a/docs/max-examples.maxpat b/docs/max-examples.maxpat index 03e9fda7..8078282c 100644 --- a/docs/max-examples.maxpat +++ b/docs/max-examples.maxpat @@ -10,7 +10,7 @@ } , "classnamespace" : "box", - "rect" : [ 663.0, 263.0, 1215.0, 710.0 ], + "rect" : [ 215.0, 572.0, 1215.0, 710.0 ], "bglocked" : 0, "openinpresentation" : 0, "default_fontsize" : 12.0, @@ -39,14 +39,86 @@ "subpatcher_template" : "", "assistshowspatchername" : 0, "boxes" : [ { + "box" : { + "id" : "obj-76", + "linecount" : 5, + "maxclass" : "comment", + "numinlets" : 1, + "numoutlets" : 0, + "patching_rect" : [ 922.0, 320.5, 224.0, 75.0 ], + "presentation_linecount" : 10, + "text" : "Raw/Callback.hpp: When we do not need to store a value we can use function declarations instead, they will be automatically parsed. std::function or just raw function pointers work." + } + + } +, { + "box" : { + "id" : "obj-75", + "maxclass" : "message", + "numinlets" : 2, + "numoutlets" : 1, + "outlettype" : [ "" ], + "patching_rect" : [ 996.0, 489.0, 50.0, 22.0 ], + "text" : "23000." + } + + } +, { + "box" : { + "id" : "obj-74", + "maxclass" : "message", + "numinlets" : 2, + "numoutlets" : 1, + "outlettype" : [ "" ], + "patching_rect" : [ 930.0, 489.0, 50.0, 22.0 ], + "text" : "230." + } + + } +, { + "box" : { + "id" : "obj-68", + "maxclass" : "newobj", + "numinlets" : 1, + "numoutlets" : 2, + "outlettype" : [ "anything", "anything" ], + "patching_rect" : [ 961.0, 452.0, 85.0, 22.0 ], + "text" : "avnd_callback" + } + + } +, { + "box" : { + "id" : "obj-67", + "maxclass" : "number", + "numinlets" : 1, + "numoutlets" : 2, + "outlettype" : [ "", "bang" ], + "parameter_enable" : 0, + "patching_rect" : [ 1024.0, 409.0, 50.0, 22.0 ] + } + + } +, { + "box" : { + "id" : "obj-62", + "maxclass" : "message", + "numinlets" : 2, + "numoutlets" : 1, + "outlettype" : [ "" ], + "patching_rect" : [ 961.0, 409.0, 34.0, 22.0 ], + "text" : "work" + } + + } +, { "box" : { "id" : "obj-26", "linecount" : 3, "maxclass" : "comment", "numinlets" : 1, "numoutlets" : 0, - "patching_rect" : [ 1029.0, 30.0, 155.0, 48.0 ], - "presentation_linecount" : 3, + "patching_rect" : [ 1029.0, 30.0, 157.0, 48.0 ], "text" : "Raw/Variant.hpp: \nHandling polymorphic input types" } @@ -59,7 +131,7 @@ "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 1024.0, 204.0, 106.0, 22.0 ], - "text" : "16" + "text" : "27" } } @@ -71,7 +143,7 @@ "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 1024.0, 177.0, 106.0, 22.0 ], - "text" : "16." + "text" : "27." } } @@ -1173,6 +1245,13 @@ "source" : [ "obj-60", 0 ] } + } +, { + "patchline" : { + "destination" : [ "obj-68", 0 ], + "source" : [ "obj-62", 0 ] + } + } , { "patchline" : { @@ -1187,6 +1266,27 @@ "source" : [ "obj-64", 0 ] } + } +, { + "patchline" : { + "destination" : [ "obj-68", 0 ], + "source" : [ "obj-67", 0 ] + } + + } +, { + "patchline" : { + "destination" : [ "obj-74", 1 ], + "source" : [ "obj-68", 0 ] + } + + } +, { + "patchline" : { + "destination" : [ "obj-75", 1 ], + "source" : [ "obj-68", 1 ] + } + } , { "patchline" : { @@ -1243,6 +1343,10 @@ "name" : "avnd_attributes.mxe64", "type" : "mx64" } +, { + "name" : "avnd_callback.mxe64", + "type" : "mx64" + } , { "name" : "avnd_init.mxe64", "type" : "mx64" diff --git a/docs/pd-examples.pd b/docs/pd-examples.pd index d2c86242..d3d276cd 100644 --- a/docs/pd-examples.pd +++ b/docs/pd-examples.pd @@ -1,76 +1,104 @@ -#N canvas 1133 254 1258 554 12; +#N canvas 1133 254 1258 626 12; #X obj 34 92 avnd_addition; #X floatatom 34 64 5 0 0 0 - - - 0; #X floatatom 122 64 5 0 0 0 - - - 0; -#X obj 34 125 print; -#X obj 421 261 avnd_lowpass; -#X obj 421 351 dac~; -#X msg 421 134 Weight \$1; -#X obj 424 102 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 #fcfcfc -#000000 #000000 0 1; -#X obj 446 161 phasor~ 200; -#X obj 447 226 avnd_persample_1; -#X msg 563 172 Gain 10; -#X msg 563 195 Gain 50; -#X msg 564 150 Gain 1; -#X obj 853 66 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 -#000000; +#X obj 359 248 avnd_lowpass; +#X obj 359 338 dac~; +#X msg 359 121 Weight \$1; +#X obj 362 90 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 #fcfcfc #000000 #000000 0 1; +#X obj 384 148 phasor~ 200; +#X obj 385 213 avnd_persample_1; +#X msg 501 159 Gain 10; +#X msg 501 182 Gain 50; +#X msg 502 137 Gain 1; +#X obj 853 66 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000; #X obj 853 124 print; #X obj 853 94 avnd_init 456 yeah; -#X text 30 35 Addition.hpp: showcases a basic message processor; -#X text 846 33 Example of handling init arguments (Init.hpp); #X obj 846 315 avnd_messages; #X msg 846 203 member 1 3 foo; #X msg 870 265 lambda_function; #X msg 860 235 function 100; -#X obj 819 290 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc -#000000 #000000; +#X obj 819 290 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000; #X obj 846 344 print; -#X text 839 172 Example of handling various messages (Messages.hpp) -; -#X text 417 32 In pd \, multi-channel must be handled by hand :-D still -\, notice that Lowpass.hpp implements per-buffer processing while PerSampleProcessor.hpp -processes per-sample.; -#X obj 848 443 avnd_callback; -#X floatatom 913 410 5 0 0 0 - - - 0; -#X msg 848 410 work; -#X floatatom 848 476 5 0 0 0 - - - 0; -#X floatatom 936 477 5 0 0 0 - - - 0; -#X obj 445 302 avnd_helpers_lowpass; +#X text 355 19 In pd \, multi-channel must be handled by hand :-D still \, notice that Lowpass.hpp implements per-buffer processing while PerSampleProcessor.hpp processes per-sample.; +#X obj 850 471 avnd_callback; +#X floatatom 915 438 5 0 0 0 - - - 0; +#X msg 850 438 work; +#X floatatom 850 504 5 0 0 0 - - - 0; +#X floatatom 938 505 5 0 0 0 - - - 0; +#X obj 383 289 avnd_helpers_lowpass; #X obj 31 273 avnd_random; #X obj 31 245 metro 100; -#X obj 31 218 tgl 15 0 empty empty empty 17 7 0 10 #fcfcfc #000000 -#000000 0 1; +#X obj 31 218 tgl 15 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000 0 1; #X floatatom 31 299 5 0 0 0 - - - 0; -#X text 26 192 Random.hpp: showcases a basic message generator; -#X text 462 325 Helper types allow the exact same thing with a simpler -C++ code; -#X text 848 387 Example of handling callbacks (Callbacks.hpp); -#X connect 0 0 3 0; +#X text 396 313 Helper types allow the exact same thing with a simpler C++ code, f 31; +#X floatatom 34 125 5 0 0 0 - - - 0; +#X obj 32 518 avnd_poles; +#X msg 130 440 length 20; +#X msg 130 465 range 1; +#X msg 131 489 sigma 0.01; +#X obj 32 464 metro 100; +#X obj 32 440 loadbang; +#X obj 35 412 hsl 162 19 -4 4 0 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1; +#X listbox 30 542 50 0 0 0 - - - 0; +#X text 28 348 Helpers/Poles.hpp: Any data type that matches the std:: API works. Here we use boost::vector instead of std::vector, f 33; +#X text 27 179 Raw/Random.hpp: showcases a basic message generator, f 28; +#X text 28 25 Raw/Addition.hpp: showcases a basic message processor, f 28; +#X text 850 25 Raw/Init.hpp: Example of handling init arguments; +#X text 848 169 Helpers/Messages.hpp: Example of handling various messages; +#X text 849 396 Raw/Callbacks.hpp: Example of handling callbacks; +#X msg 503 113 Gain 0; +#X obj 521 486 avnd_variant, f 17; +#X floatatom 637 425 5 0 0 0 - - - 0; +#X floatatom 520 428 5 0 0 0 - - - 0; +#X floatatom 527 514 5 0 0 0 - - - 0; +#X floatatom 644 515 5 0 0 0 - - - 0; +#X symbolatom 521 546 10 0 0 0 - - - 0; +#X symbolatom 637 547 10 0 0 0 - - - 0; +#X msg 522 454 symbol x; +#X msg 637 456 symbol y; +#X text 516 383 Raw/Variant.hpp: Handling polymorphic input types; +#X connect 0 0 33 0; #X connect 1 0 0 0; #X connect 2 0 0 1; -#X connect 4 0 5 0; -#X connect 6 0 4 0; -#X connect 6 0 31 0; -#X connect 7 0 6 0; -#X connect 8 0 9 0; -#X connect 9 0 4 0; -#X connect 9 0 31 0; -#X connect 10 0 9 0; -#X connect 11 0 9 0; -#X connect 12 0 9 0; -#X connect 13 0 15 0; -#X connect 15 0 14 0; -#X connect 18 0 23 0; -#X connect 19 0 18 0; -#X connect 20 0 18 0; -#X connect 21 0 18 0; -#X connect 22 0 18 0; -#X connect 26 0 29 0; -#X connect 26 1 30 0; -#X connect 27 0 26 0; -#X connect 28 0 26 0; -#X connect 31 0 5 1; -#X connect 32 0 35 0; -#X connect 33 0 32 0; -#X connect 34 0 33 0; +#X connect 3 0 4 0; +#X connect 5 0 3 0; +#X connect 5 0 27 0; +#X connect 6 0 5 0; +#X connect 7 0 8 0; +#X connect 8 0 3 0; +#X connect 8 0 27 0; +#X connect 9 0 8 0; +#X connect 10 0 8 0; +#X connect 11 0 8 0; +#X connect 12 0 14 0; +#X connect 14 0 13 0; +#X connect 15 0 20 0; +#X connect 16 0 15 0; +#X connect 17 0 15 0; +#X connect 18 0 15 0; +#X connect 19 0 15 0; +#X connect 22 0 25 0; +#X connect 22 1 26 0; +#X connect 23 0 22 0; +#X connect 24 0 22 0; +#X connect 27 0 4 1; +#X connect 28 0 31 0; +#X connect 29 0 28 0; +#X connect 30 0 29 0; +#X connect 34 0 41 0; +#X connect 35 0 34 0; +#X connect 36 0 34 0; +#X connect 37 0 34 0; +#X connect 38 0 34 0; +#X connect 39 0 38 0; +#X connect 40 0 34 0; +#X connect 48 0 8 0; +#X connect 49 0 52 0; +#X connect 49 0 54 0; +#X connect 49 1 53 0; +#X connect 49 1 55 0; +#X connect 50 0 49 1; +#X connect 51 0 49 0; +#X connect 56 0 49 0; +#X connect 57 0 49 1; diff --git a/examples/Complete/CompleteMessageExample.pd b/examples/Complete/CompleteMessageExample.pd index 33887505..748c4c48 100644 --- a/examples/Complete/CompleteMessageExample.pd +++ b/examples/Complete/CompleteMessageExample.pd @@ -1,4 +1,4 @@ -#N canvas 960 0 956 1002 12; +#N canvas 960 0 956 1165 12; #X floatatom 340 241 5 0 0 0 - - - 0; #X msg 330 39 Test1 1; #X msg 332 191 m1 1 2.3 foobar; diff --git a/examples/Raw/Variant.hpp b/examples/Raw/Variant.hpp index d36ff6bb..0f6643f2 100644 --- a/examples/Raw/Variant.hpp +++ b/examples/Raw/Variant.hpp @@ -5,7 +5,6 @@ #include #include -// clang-format on namespace examples { struct Variant @@ -49,4 +48,3 @@ struct Variant } }; } -// clang-format on diff --git a/include/avnd/binding/pd/helpers.hpp b/include/avnd/binding/pd/helpers.hpp index 22fb8af8..2d006463 100644 --- a/include/avnd/binding/pd/helpers.hpp +++ b/include/avnd/binding/pd/helpers.hpp @@ -135,7 +135,11 @@ static Arg convert(t_atom& atom) template t_symbol* symbol_for_port() { - return &s_anything; // TODO is that correct ? + // https://sourceforge.net/p/pure-data/patches/164/ + // s_list is the "generic" inlet type, + // it is the only type that allows right-inlets to also + // react to float & symbol messages + return &s_list; } template @@ -164,6 +168,8 @@ t_symbol* symbol_for_port() return &s_list; else if constexpr(avnd::tuple_ish) return &s_list; + else if constexpr(avnd::variant_ish) + return &s_list; else if constexpr(avnd::iterable_ish) return &s_list; else if constexpr(std::floating_point) diff --git a/include/avnd/binding/pd/inputs.hpp b/include/avnd/binding/pd/inputs.hpp index 4f2f2a98..67a79d3b 100644 --- a/include/avnd/binding/pd/inputs.hpp +++ b/include/avnd/binding/pd/inputs.hpp @@ -346,9 +346,14 @@ struct inputs // Do not create a port for attributes if constexpr(!avnd::attribute_port) { - static const auto name = pd::symbol_from_name(); + // If we get a message [port_sym 1 2 3) + auto port_sym = pd::symbol_for_port(); - inlet_new(&x_obj, &x_obj.ob_pd, pd::symbol_for_port(), name); + // Then the message through this inlet will be received by "process" + // as [name 1 2 3) + auto name = pd::symbol_from_name(); + + inlet_new(&x_obj, &x_obj.ob_pd, port_sym, name); } } }); diff --git a/include/avnd/binding/pd/message_processor.hpp b/include/avnd/binding/pd/message_processor.hpp index 88cdeaa0..38cd39b9 100644 --- a/include/avnd/binding/pd/message_processor.hpp +++ b/include/avnd/binding/pd/message_processor.hpp @@ -164,6 +164,7 @@ struct message_processor void process(t_symbol* s, int argc, t_atom* argv) { + // First try to process messages handled explicitely in the object if(messages_setup.process_messages(implementation, s, argc, argv)) return; @@ -203,7 +204,7 @@ message_processor_metaclass::message_processor_metaclass() /// Small wrapper methods which will call into our actual type /// // Ctor - constexpr auto obj_new = +[](t_symbol* s, int argc, t_atom* argv) -> void* { + static constexpr auto obj_new = +[](t_symbol* s, int argc, t_atom* argv) -> void* { // Initializes the t_object t_pd* ptr = pd_new(g_class); @@ -215,13 +216,13 @@ message_processor_metaclass::message_processor_metaclass() }; // Dtor - constexpr auto obj_free = +[](instance* obj) -> void { + static constexpr auto obj_free = +[](instance* obj) -> void { obj->destroy(); obj->~instance(); }; // Message processing - constexpr auto obj_process + static constexpr auto obj_process = +[](instance* obj, t_symbol* s, int argc, t_atom* argv) -> void { obj->process(s, argc, argv); };