Forums > Dev

enumindex with custom get/set

February 8, 2011 | 7:30 am

Hi there,

I have declared an attribute as such:

CLASS_ATTR_LONG(c,      	"myattr", 	0, t_myobj, myattr);
CLASS_ATTR_ACCESSORS(c,		"myattr",    	(method)myobj_myattr_get, (method)myobj_myattr_set);
CLASS_ATTR_ENUMINDEX(c,		"myattr",	0, "Left Center Right");
CLASS_ATTR_DEFAULT_SAVE_PAINT(c,"myattr",    	0, "0");

The custom getter and setter:

t_max_err myobj_myattr_get(t_myobj *x, t_object *attr, long *argc, t_atom **argv)
{
    char alloc;

    if (argc && argv) {
	if (atom_alloc(argc, argv, &alloc)) {
            return MAX_ERR_OUT_OF_MEM;
        }
        if (alloc) {
            atom_setlong(*argv, x->myattr);
	}
    }
    return MAX_ERR_NONE;
}

t_max_err myobj_myattr_set(t_myobj *x, t_object *attr, long argc, t_atom *argv)
{
    if (argc && argv) {
        x->myattr = atom_getlong(argv);
    }
    return MAX_ERR_NONE;
}

Pretty straightforward, however I have one problem:
if I understand everything clearly, the CLASS_ATTR_ENUMINDEX macro creates an "enumindex" attribute, which becomes an attribute of the "myattr" attribute.
However it seems I am having problems updating the "enumindex" attribute when I use a custom getter and setter.

In other words, when the user clicks on an inlet of my object and the quickref menu gets displayed, the string portion of "myattr" always says "Left" even though the numeric value associated with "myattr" might change. I also see a ‘bad number’ error in the Max window.

So I am guessing that there must be a way to update the "enumindex" attribute after changing the value of myattr in order for the two to be synced together.
Probably I need to do it manually since I defeat the internal setter and getter. But how ???

Any suggestions ?

Thanks.

- Luigi


February 8, 2011 | 9:19 am

Unless I didn’t read properly, you shouldn’t need to have a custom gettr, so the following should work.

CLASS_ATTR_ACCESSORS(c,		"myattr",    	(method)NULL, (method)myobj_myattr_set);

In this case it uses the standard gettr method.


February 8, 2011 | 11:14 am

I know, but I do need a custom getter…
how do I make it work with a custom getter ?

- Luigi


February 8, 2011 | 4:56 pm

it should be something like this. alloc doesn’t return anything really interesting in this case.


t_max_err myobj_myattr_get(t_myobj *x, t_object *attr, long *argc, t_atom **argv)
{
    char alloc;

    if (argc && argv) {
	if (atom_alloc(argc, argv, &alloc)) {
            return MAX_ERR_GENERIC;
        }
        atom_setlong(*argv, x->myattr);
    }
    return MAX_ERR_NONE;
}


February 9, 2011 | 2:44 am

yes, that’s what I would think too…

However the above custom getter produces an "enumindex: bad number" error in the Max window and fails to update the symbol portion of the attribute.

Curiously enough, if the same attribute is declared as ENUM (with a symbol datatype) everything works fine.

To better illustrate the problem I wrote a simple UI external with just one attribute defined as ENUMINDEX with custom getter and setter.

If you compile it and then open the help file you will find instructions to reproduce the problem exactly as it appears to me.

Please, let me know what you guys think…

Thanks a lot.

- Luigi

Attachments:
  1. myenum.maxpat

February 9, 2011 | 9:31 am

tha alloc is true only when atom_alloc allocates the memory. But if ac && av that you pass as argument of the method are non NULL, atom_alloc will not allocate memory and use the already allocated memory instead. What you really want to look at to see if the memory is valid is the return value of atom_alloc, if the t_max_err value returned is MAX_ERR_NONE you’re god to go.


February 9, 2011 | 11:41 am

Of course…. sorry for my silliness…. it was late at night….
Problem is solved exactly like you guys said.

Emmanuel and Vanille, thank you so much for your help.

- Luigi


Viewing 7 posts - 1 through 7 (of 7 total)