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 c++ class representing a number, and types for a vector of those numbers 00032 class number { 00033 private: 00034 double value; 00035 public: 00036 number(double& newValue) 00037 { 00038 value = newValue; 00039 } 00040 00041 void setValue(const double& newValue) 00042 { 00043 value = newValue; 00044 } 00045 00046 void getValue(double& retrievedValue) 00047 { 00048 retrievedValue = value; 00049 } 00050 }; 00051 typedef std::vector<number> numberVector; 00052 typedef numberVector::iterator numberIterator; 00053 00054 00055 // max object instance data 00056 typedef struct _collect { 00057 t_object c_box; 00058 numberVector *c_vector; // note: you must store this as a pointer and not directly as a member of the object's struct 00059 void *c_outlet; 00060 t_systhread_mutex c_mutex; 00061 } t_collect; 00062 00063 00064 // prototypes 00065 void* collect_new(t_symbol *s, long argc, t_atom *argv); 00066 void collect_free(t_collect* x); 00067 void collect_assist(t_collect *x, void *b, long m, long a, char *s); 00068 void collect_bang(t_collect *x); 00069 void collect_count(t_collect *x); 00070 void collect_int(t_collect *x, long value); 00071 void collect_float(t_collect *x, double value); 00072 void collect_list(t_collect *x, t_symbol *msg, long argc, t_atom *argv); 00073 void collect_clear(t_collect *x); 00074 00075 00076 // globals 00077 static t_class *s_collect_class = NULL; 00078 00079 /************************************************************************************/ 00080 00081 int main(void) 00082 { 00083 t_class *c = class_new("collect", 00084 (method)collect_new, 00085 (method)collect_free, 00086 sizeof(t_collect), 00087 (method)NULL, 00088 A_GIMME, 00089 0); 00090 00091 common_symbols_init(); 00092 00093 class_addmethod(c, (method)collect_bang, "bang", 0); 00094 class_addmethod(c, (method)collect_int, "int", A_LONG, 0); 00095 class_addmethod(c, (method)collect_float, "float", A_FLOAT,0); 00096 class_addmethod(c, (method)collect_list, "list", A_GIMME,0); 00097 class_addmethod(c, (method)collect_clear, "clear", 0); 00098 class_addmethod(c, (method)collect_count, "count", 0); 00099 class_addmethod(c, (method)collect_assist, "assist", A_CANT, 0); 00100 class_addmethod(c, (method)stdinletinfo, "inletinfo", A_CANT, 0); 00101 00102 class_register(_sym_box, c); 00103 s_collect_class = c; 00104 00105 return 0; 00106 } 00107 00108 00109 /************************************************************************************/ 00110 // Object Creation Method 00111 00112 void *collect_new(t_symbol *s, long argc, t_atom *argv) 00113 { 00114 t_collect *x; 00115 00116 x = (t_collect*)object_alloc(s_collect_class); 00117 if (x) { 00118 systhread_mutex_new(&x->c_mutex, 0); 00119 x->c_outlet = outlet_new(x, NULL); 00120 x->c_vector = new numberVector; 00121 x->c_vector->reserve(10); 00122 collect_list(x, _sym_list, argc, argv); 00123 } 00124 return(x); 00125 } 00126 00127 00128 void collect_free(t_collect *x) 00129 { 00130 systhread_mutex_free(x->c_mutex); 00131 delete x->c_vector; 00132 } 00133 00134 00135 /************************************************************************************/ 00136 // Methods bound to input/inlets 00137 00138 void collect_assist(t_collect *x, void *b, long msg, long arg, char *dst) 00139 { 00140 if (msg==1) 00141 strcpy(dst, "input"); 00142 else if (msg==2) 00143 strcpy(dst, "output"); 00144 } 00145 00146 00147 void collect_bang(t_collect *x) 00148 { 00149 numberIterator iter, begin, end; 00150 int i = 0; 00151 long ac = 0; 00152 t_atom *av = NULL; 00153 double value; 00154 00155 DPOST("head\n"); 00156 systhread_mutex_lock(x->c_mutex); 00157 ac = x->c_vector->size(); 00158 00159 DPOST("ac=%ld\n", ac); 00160 if (ac) 00161 av = new t_atom[ac]; 00162 00163 if (ac && av) { 00164 DPOST("assigning begin and end\n"); 00165 begin = x->c_vector->begin(); 00166 end = x->c_vector->end(); 00167 00168 DPOST("assigning iter\n"); 00169 iter = begin; 00170 00171 DPOST("entering for\n", ac); 00172 for (;;) { 00173 DPOST("i=%i\n", i); 00174 (*iter).getValue(value); 00175 atom_setfloat(av+i, value); 00176 00177 DPOST("incrementing\n"); 00178 i++; 00179 iter++; 00180 00181 DPOST("comparing\n"); 00182 if (iter == end) 00183 break; 00184 } 00185 systhread_mutex_unlock(x->c_mutex); // must unlock before calling _clear() or we will deadlock 00186 00187 DPOST("about to clear\n", ac); 00188 collect_clear(x); 00189 00190 DPOST("about to outlet\n", ac); 00191 outlet_anything(x->c_outlet, _sym_list, ac, av); // don't want to call outlets in mutexes either 00192 00193 DPOST("about to delete\n", ac); 00194 delete[] av; 00195 } 00196 else 00197 systhread_mutex_unlock(x->c_mutex); 00198 } 00199 00200 00201 void collect_count(t_collect *x) 00202 { 00203 outlet_int(x->c_outlet, x->c_vector->size()); 00204 } 00205 00206 00207 void collect_int(t_collect *x, long value) 00208 { 00209 collect_float(x, value); 00210 } 00211 00212 00213 void collect_float(t_collect *x, double value) 00214 { 00215 systhread_mutex_lock(x->c_mutex); 00216 x->c_vector->push_back(value); 00217 systhread_mutex_unlock(x->c_mutex); 00218 } 00219 00220 00221 void collect_list(t_collect *x, t_symbol *msg, long argc, t_atom *argv) 00222 { 00223 systhread_mutex_lock(x->c_mutex); 00224 for (int i=0; i<argc; i++) { 00225 double value = atom_getfloat(argv+i); 00226 x->c_vector->push_back(value); 00227 } 00228 systhread_mutex_unlock(x->c_mutex); 00229 } 00230 00231 00232 void collect_clear(t_collect *x) 00233 { 00234 systhread_mutex_lock(x->c_mutex); 00235 x->c_vector->clear(); 00236 systhread_mutex_unlock(x->c_mutex); 00237 } 00238
Copyright © 2008, Cycling '74