Max 5 API Reference
00001 /** 00002 @file 00003 collect - collect numbers and operate on them. 00004 - demonstrates use of C++ and the STL in a Max external 00005 - also demonstrates use of a mutex for thread safety 00006 - on Windows, demonstrate project setup for static linking to the Microsoft Runtime 00007 00008 @ingroup examples 00009 00010 Copyright 2009 - Cycling '74 00011 Timothy Place, tim@cycling74.com 00012 */ 00013 00014 #include "ext.h" 00015 #include "ext_obex.h" 00016 #include "ext_strings.h" 00017 #include "ext_common.h" 00018 #include "ext_systhread.h" 00019 00020 #include <vector> 00021 using namespace std; 00022 00023 // a wrapper for cpost() only called for debug builds on Windows 00024 // to see these console posts, run the DbgView program (part of the SysInternals package distributed by Microsoft) 00025 #if defined( NDEBUG ) || defined( MAC_VERSION ) 00026 #define DPOST 00027 #else 00028 #define DPOST cpost 00029 #endif 00030 00031 // a macro to mark exported symbols in the code without requiring an external file to define them 00032 #ifdef WIN_VERSION 00033 // note that this the required syntax on windows regardless of whether the compiler is msvc or gcc 00034 #define T_EXPORT __declspec(dllexport) 00035 #else // MAC_VERSION 00036 // the mac uses the standard gcc syntax, you should also set the -fvisibility=hidden flag to hide the non-marked symbols 00037 #define T_EXPORT __attribute__((visibility("default"))) 00038 #endif 00039 00040 // a c++ class representing a number, and types for a vector of those numbers 00041 class number { 00042 private: 00043 double value; 00044 public: 00045 number(double& newValue) 00046 { 00047 value = newValue; 00048 } 00049 00050 void setValue(const double& newValue) 00051 { 00052 value = newValue; 00053 } 00054 00055 void getValue(double& retrievedValue) 00056 { 00057 retrievedValue = value; 00058 } 00059 }; 00060 typedef std::vector<number> numberVector; 00061 typedef numberVector::iterator numberIterator; 00062 00063 00064 // max object instance data 00065 typedef struct _collect { 00066 t_object c_box; 00067 numberVector *c_vector; // note: you must store this as a pointer and not directly as a member of the object's struct 00068 void *c_outlet; 00069 t_systhread_mutex c_mutex; 00070 } t_collect; 00071 00072 00073 // prototypes 00074 void* collect_new(t_symbol *s, long argc, t_atom *argv); 00075 void collect_free(t_collect* x); 00076 void collect_assist(t_collect *x, void *b, long m, long a, char *s); 00077 void collect_bang(t_collect *x); 00078 void collect_count(t_collect *x); 00079 void collect_int(t_collect *x, long value); 00080 void collect_float(t_collect *x, double value); 00081 void collect_list(t_collect *x, t_symbol *msg, long argc, t_atom *argv); 00082 void collect_clear(t_collect *x); 00083 00084 00085 // globals 00086 static t_class *s_collect_class = NULL; 00087 00088 /************************************************************************************/ 00089 00090 int T_EXPORT main(void) 00091 { 00092 t_class *c = class_new("collect", 00093 (method)collect_new, 00094 (method)collect_free, 00095 sizeof(t_collect), 00096 (method)NULL, 00097 A_GIMME, 00098 0); 00099 00100 common_symbols_init(); 00101 00102 class_addmethod(c, (method)collect_bang, "bang", 0); 00103 class_addmethod(c, (method)collect_int, "int", A_LONG, 0); 00104 class_addmethod(c, (method)collect_float, "float", A_FLOAT,0); 00105 class_addmethod(c, (method)collect_list, "list", A_GIMME,0); 00106 class_addmethod(c, (method)collect_clear, "clear", 0); 00107 class_addmethod(c, (method)collect_count, "count", 0); 00108 class_addmethod(c, (method)collect_assist, "assist", A_CANT, 0); 00109 class_addmethod(c, (method)stdinletinfo, "inletinfo", A_CANT, 0); 00110 00111 class_register(_sym_box, c); 00112 s_collect_class = c; 00113 00114 return 0; 00115 } 00116 00117 00118 /************************************************************************************/ 00119 // Object Creation Method 00120 00121 void *collect_new(t_symbol *s, long argc, t_atom *argv) 00122 { 00123 t_collect *x; 00124 00125 x = (t_collect*)object_alloc(s_collect_class); 00126 if (x) { 00127 systhread_mutex_new(&x->c_mutex, 0); 00128 x->c_outlet = outlet_new(x, NULL); 00129 x->c_vector = new numberVector; 00130 x->c_vector->reserve(10); 00131 collect_list(x, _sym_list, argc, argv); 00132 } 00133 return(x); 00134 } 00135 00136 00137 void collect_free(t_collect *x) 00138 { 00139 systhread_mutex_free(x->c_mutex); 00140 delete x->c_vector; 00141 } 00142 00143 00144 /************************************************************************************/ 00145 // Methods bound to input/inlets 00146 00147 void collect_assist(t_collect *x, void *b, long msg, long arg, char *dst) 00148 { 00149 if (msg==1) 00150 strcpy(dst, "input"); 00151 else if (msg==2) 00152 strcpy(dst, "output"); 00153 } 00154 00155 00156 void collect_bang(t_collect *x) 00157 { 00158 numberIterator iter, begin, end; 00159 int i = 0; 00160 long ac = 0; 00161 t_atom *av = NULL; 00162 double value; 00163 00164 DPOST("head\n"); 00165 systhread_mutex_lock(x->c_mutex); 00166 ac = x->c_vector->size(); 00167 00168 DPOST("ac=%ld\n", ac); 00169 if (ac) 00170 av = new t_atom[ac]; 00171 00172 if (ac && av) { 00173 DPOST("assigning begin and end\n"); 00174 begin = x->c_vector->begin(); 00175 end = x->c_vector->end(); 00176 00177 DPOST("assigning iter\n"); 00178 iter = begin; 00179 00180 DPOST("entering for\n", ac); 00181 for (;;) { 00182 DPOST("i=%i\n", i); 00183 (*iter).getValue(value); 00184 atom_setfloat(av+i, value); 00185 00186 DPOST("incrementing\n"); 00187 i++; 00188 iter++; 00189 00190 DPOST("comparing\n"); 00191 if (iter == end) 00192 break; 00193 } 00194 systhread_mutex_unlock(x->c_mutex); // must unlock before calling _clear() or we will deadlock 00195 00196 DPOST("about to clear\n", ac); 00197 collect_clear(x); 00198 00199 DPOST("about to outlet\n", ac); 00200 outlet_anything(x->c_outlet, _sym_list, ac, av); // don't want to call outlets in mutexes either 00201 00202 DPOST("about to delete\n", ac); 00203 delete[] av; 00204 } 00205 else 00206 systhread_mutex_unlock(x->c_mutex); 00207 } 00208 00209 00210 void collect_count(t_collect *x) 00211 { 00212 outlet_int(x->c_outlet, x->c_vector->size()); 00213 } 00214 00215 00216 void collect_int(t_collect *x, long value) 00217 { 00218 collect_float(x, value); 00219 } 00220 00221 00222 void collect_float(t_collect *x, double value) 00223 { 00224 systhread_mutex_lock(x->c_mutex); 00225 x->c_vector->push_back(value); 00226 systhread_mutex_unlock(x->c_mutex); 00227 } 00228 00229 00230 void collect_list(t_collect *x, t_symbol *msg, long argc, t_atom *argv) 00231 { 00232 systhread_mutex_lock(x->c_mutex); 00233 for (int i=0; i<argc; i++) { 00234 double value = atom_getfloat(argv+i); 00235 x->c_vector->push_back(value); 00236 } 00237 systhread_mutex_unlock(x->c_mutex); 00238 } 00239 00240 00241 void collect_clear(t_collect *x) 00242 { 00243 systhread_mutex_lock(x->c_mutex); 00244 x->c_vector->clear(); 00245 systhread_mutex_unlock(x->c_mutex); 00246 } 00247
Copyright © 2008, Cycling '74