testobex example in pattrsdk.pdf

chuck Clark's icon

hello,
I tried compiling the testobex external in the pattrsdk.pdf and found a few errors. I corrected the errors but still the example does not work correctly.

firstly, void *class_testobex was declared but then was used as testobex_class twice. so i changed it to class_testobex.

secondly, the attribute 'operand' was registered but then 'data' was used in place of 'operand' . I changed all instances of 'data' to 'operand' and it compiled fine.

When i set up a test in max however, the output value was always 0. I did put a value for operand in the object 'command line' ie
@operand 34

any idea on how to correct this?

chuck

chuck Clark's icon

I decided to post the source. It is the same as in pattrsdk.pdf with the changes i mentioned.

I have it working when i manually set operand to the value (which i commented out here), so maybe i am confused by the point of
//handle attribute arguments (e.g. @operand 0.5)
attr_args_process(x, ac, av);

does it not set the values of the attributes to the variable you create and register with class_addattr(c, attr); ?

chuck

#include "ext.h"
#include "ext_obex.h"
typedef struct _testobex
{    t_object ob;
    void *obex;
    float operand;
    void *out;
} t_testobex;

void *class_testobex;
void *testobex_new(t_symbol *s, long ac, t_atom *av);
void testobex_free(t_testobex *x);
void testobex_int(t_testobex *x, long d);
void testobex_float(t_testobex *x, double f);

void main(void)
{    t_class *c;
    t_object *attr;
    long attrflags = 0;

    // define the class – A_GIMME required for attributes
    c = class_new("testobex", (method)testobex_new, (method)testobex_free, sizeof(t_testobex), (method)0L, A_GIMME, 0);

    // register the obex object's offset
    class_obexoffset_set(c, calcoffset(t_testobex, obex));

    // create and register an attribute (attr_offset)
    attr = attr_offset_new("operand", _sym_float32, attrflags, (method)0L, (method)0L, calcoffset(t_testobex, operand));
    class_addattr(c, attr);

    // create and register some methods
    class_addmethod(c, (method)testobex_int, "int", A_LONG, 0);
    class_addmethod(c, (method)testobex_float, "float", A_FLOAT, 0);

    // add dumpout and quickref methods
    class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0);
    class_addmethod(c, (method)object_obex_quickref, "quickref", A_CANT, 0);

    // register the class as an instantiable box
    class_register(CLASS_BOX, c);

    // set the global class variable
    class_testobex = c;
}

void *testobex_new(t_symbol *s, long ac, t_atom *av)
{    t_testobex *x = NULL;
    // allocate a new object
    if (x = (t_testobex *)object_alloc(class_testobex))
    {    // important: initialize class members before processing
        // attribute args. otherwise, you might replace data.
        x->operand = 0;

        //handle attribute arguments (e.g. @operand 0.5)
        attr_args_process(x, ac, av);

        // if (ac > 1)    x->operand = atom_getlong(av+1);

        // create a dumpout outlet, used by attributes
        object_obex_store(x, _sym_dumpout, outlet_new(x, NULL));
        // create another outlet
        x->out = outlet_new(x, NULL);
    }
    return x;
}

void testobex_free(t_testobex *x)
{    ; // nix
}

void testobex_int(t_testobex *x, long d)
{    // int in, int out
    outlet_int(x->out, (long)((float)d * x->operand));
}

void testobex_float(t_testobex *x, double f)
{
// float in, float out
outlet_float(x->out, f * x->operand);
}