monome / norns

norns is many sound instruments.
http://monome.org
GNU General Public License v3.0
633 stars 147 forks source link

arbitrary engine commands #3

Closed catfact closed 7 years ago

catfact commented 7 years ago

arbitrary engine commands

commands = [ 
    // apply a fade-in to a buffer
    // arg 1: name of buffer
    // arg 2: duration in seconds
    // arg 3: curve
    (name:"buffer/fadeIn", format:"sff")

    // play a buffer from the beginning to the end, with a given amplitude
    // arg 1: name of buffer
    // arg 2: amp
    (name:"buffer/playAll", format:"sf")
];

in matron:

oracle.c:

events.c

weaver.c:

-- lua code, generated on the fly:

buffer.fadeIn = function (name, dur, curve)
   send_command(0, name, dur, curve)
end

buffer.playAll = function (name, amp)
   send_command(1, name, amp)
end

and elsewhere:

// this function is registered with lua
send_command(id, ...) {
    // pop index from stack
    // look up OSC string
    // look up format
    // pop arguments from stack, verify types against format string
    // send OSC with string, format and args...
    // ... (how to glue varargs to varargs??)
}
catfact commented 7 years ago

huh, turns out nesting vargs functions in C is non trivial: http://c-faq.com/varargs/handoff.html

internaly, liblo's vargs functions are wrappers around va_list (as they should be):

in lo_macros.h.in:

#define lo_send(targ, path, types...) \
        lo_send_internal(targ, __FILE__, __LINE__, path, types, \
             LO_MARKER_A, LO_MARKER_B)

in send.c:

int lo_send_internal(lo_address t, const char *file, const int line,
                     const char *path, const char *types, ...)
{
    va_list ap;
    va_start(ap, types);
    return lo_send_varargs_internal(t, file, line, path, types, ap);
}
#if defined(USE_ANSI_C) || defined(DLL_EXPORT)
int lo_send(lo_address t, const char *path, const char *types, ...)
{
    const char *file = "";
    int line = 0;
    va_list ap;
    va_start(ap, types);
    return lo_send_varargs_internal(t, file, line, path, types, ap);
}
#endif

so it seems fine to hack our own wrappers, no need to fork liblo or anything.

catfact commented 7 years ago

ech, actually no joy there: most everything in liblo that accepts a va_list has static linkage; we can build a message but we can't do anything with it without access to liblo's opaque data structures. rather than hacking into those, i'd rather: a) just fork liblo and make some light modifictions to wrap e.g. lo_send(...) around vlo_send(va_list) in the typical C manner b) use the gnu extensions for explicitly building function calls: http://tigcc.ticalc.org/doc/gnuexts.html#SEC67

catfact commented 7 years ago

conclusion: nested varargs in C are nigh-impossible, but fortunately liblo gives us the abilility to dynamically construct a message and then pass it to the send internals directly. the end.

3bbfeae8033c6e30d20dc91c574c1922b642045b