Codes

*Template for creating Max externals

These are created using the visual studio 2005 environment. The relevant include files and libraries for creating externals can be obtained at www.cycling74.com. The source code for all the objects and tutorial demos are included in the toolkit.

Max.cpp.h file
/*
Based on the original C++ MSP template written by Graham Wakefield.
www.mat.ucsb.edu/~wakefield/maxcpp.htm

This version contains only the basics needed for max/obex objects.

All credits and lots of thanks to Graham for sharing his templates!!
*/

#ifndef MAX_CPP_H
#define MAX_CPP_H

#include "ext.h"
#include "ext_common.h"
#include "ext_obex.h"
#include "ext_path.h"
#include "commonsyms.h"

template <class T>
class MaxCpp
{

protected:
// for Max external-loading & Obex:
t_object maxOb; // Max 'instance' pointer
void * maxObex; // Max Obex container
static void * maxClass; // Max 'class' pointer

private:
static void * maxAlloc(t_symbol *s, long argc, t_atom *argv);
static void maxFree(T *x);
static void * operator new(size_t);
static void operator delete(void *);

public:

// called from 'main' to create class ptr
static t_class * maxMakeClass(char* name); // use this for Max objects

// use normal C++ constructors & destructors:
MaxCpp();
~MaxCpp();

// 'dump' obex outlet:
t_object * maxObexOutlet;
};

// singleton class object
template <class T>
void * MaxCpp<T>::maxClass = 0;

template <class T>
inline t_class * MaxCpp<T>::maxMakeClass(char* name)
{

t_class * _class = class_new(
name,
(method)T::maxAlloc,
(method)T::maxFree,
(short)sizeof(T),
0L,
A_GIMME,
0);

// initialize the common symbols, since we want to use them
common_symbols_init();

// register the byte offset of obex with the class
class_obexoffset_set(_class, calcoffset(T, maxObex));

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

// store static ref
MaxCpp<T>::maxClass = _class;

return _class;
}

template <class T> inline void * MaxCpp<T> :: maxAlloc(t_symbol *sym, long ac, t_atom *av)
{
return new T(sym, ac, av);
}

template <class T> inline void MaxCpp<T> :: maxFree(T *x)
{
delete x;
}

template <class T> inline void * MaxCpp<T> :: operator new(size_t t)
{
return object_alloc((t_class *)MaxCpp<T>::maxClass);
}

template <class T> inline void MaxCpp<T> :: operator delete(void *)
{
// nothing to do - Max will manage the memory
}

template <class T> inline MaxCpp<T>::MaxCpp()
{
// add a generic outlet
maxObexOutlet = (t_object *)outlet_new(this, 0L);
object_obex_store(this, _sym_dumpout, maxObexOutlet); // also set it as dumpout
}

template <class T> inline MaxCpp<T> :: ~MaxCpp()
{
}

#endif
Cpp.max.example.h file

/*
Based on a modified version of Graham Wakefields original C++ template code.
www.mat.ucsb.edu/~wakefield/maxcpp.htm
*/

#ifndef __CPP_MAX_EXAMPLE_H
#define __CPP_MAX_EXAMPLE_H

#include "max.cpp.h"
#include <vector>

class CPPMaxExample : public MaxCpp<CPPMaxExample>
{
public:

CPPMaxExample(t_symbol * s, long ac, t_atom * av);
~CPPMaxExample();

// make sure all max methods are declared static, with a class pointer as first
// argument, to make them available to the C API
static void aMaxMethod(CPPMaxExample *x);

// attributes, keep public but not static
float m_floatAttribute;

private:

// some C++ goodies.
std::vector<float> m_floatList;
void aClassMethod();

};

#endif // __CPP_MAX_EXAMPLE_H /*

Cpp.max.example.cpp file

Based on a modified version of Graham Wakefields original C++ template code.
www.mat.ucsb.edu/~wakefield/maxcpp.htm
*/

#include "cpp.max.example.h"

// called when library is loaded
extern "C" int main(void)
{
t_class *c;
t_object *attr;
long attrflags = 0;

c = CPPMaxExample::maxMakeClass("cpp_max_example");

// add your attributes
attr = attr_offset_new("float_attribute", _sym_float32, attrflags,
(method)0L, (method)0L, calcoffset(CPPMaxExample, m_floatAttribute));
class_addattr(c, attr);

// add your (static) max methods
class_addmethod(c, (method)CPPMaxExample::aMaxMethod, "aMaxMethod", A_NOTHING, 0);

// we want this class to instantiate inside of the Max UI
class_register(CLASS_BOX, c);
}

CPPMaxExample::CPPMaxExample(t_symbol *s, long ac, t_atom *av) : MaxCpp<CPPMaxExample>()
{
post("cpp_max_example constructor");

// init member variables
m_floatAttribute = 0.f;

// process the attribute values which are typed in object box
attr_args_process(this, ac, av);
}

CPPMaxExample :: ~CPPMaxExample()
{
// undo stuff
post("cpp_max_example destructor");
}

void CPPMaxExample::aMaxMethod(CPPMaxExample *x)
{
post("call max method");
// you can then call member methods if you want
x->aClassMethod();
}

void CPPMaxExample::aClassMethod()
{
post("call class method");
m_floatAttribute = 666.f;
}

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License