Max 5 API Reference
00001 /** 00002 @file 00003 dbviewer - demonstrate use of database views for sqlite and jdataview 00004 00005 @ingroup examples 00006 00007 Copyright 2009 - Cycling '74 00008 Timothy Place, tim@cycling74.com 00009 */ 00010 00011 #include "ext.h" 00012 #include "ext_obex.h" 00013 #include "ext_strings.h" 00014 #include "ext_common.h" 00015 #include "ext_symobject.h" 00016 #include "ext_database.h" 00017 #include "jpatcher_api.h" 00018 #include "jgraphics.h" 00019 #include "indexmap.h" 00020 #include "jdataview.h" 00021 00022 00023 enum { 00024 kOutletParameterNames = 0, 00025 kOutletParameterValues, 00026 kOutletPresetNames, 00027 kOutletPluginNames, 00028 kNumContolOutlets 00029 }; 00030 00031 00032 typedef struct _dbviewer { 00033 t_jbox d_box; 00034 t_object *d_dataview; ///< The dataview object 00035 t_hashtab *d_columns; ///< The dataview columns: column name -> column index 00036 t_object *d_view; ///< The dbview object that we need to display in a dataview 00037 t_symbol *d_query; ///< Attribute 00038 t_symbol *d_database; ///< Attribute 00039 t_object *d_db; ///< the actual database object 00040 } t_dbviewer; 00041 00042 00043 00044 // general prototypes 00045 void* dbviewer_new(t_symbol *s, short argc, t_atom *argv); 00046 void dbviewer_initdataview(t_dbviewer *x); 00047 void dbviewer_free(t_dbviewer* x); 00048 void dbviewer_newpatcherview(t_dbviewer *x, t_object *patcherview); 00049 void dbviewer_freepatcherview(t_dbviewer *x, t_object *patcherview); 00050 t_max_err dbviewer_notify(t_dbviewer *x, t_symbol *s, t_symbol *msg, void *sender, void *data); 00051 void dbviewer_assist(t_dbviewer *x, void *b, long m, long a, char *s); 00052 void dbviewer_bang(t_dbviewer *x); 00053 void dbviewer_getcelltext(t_dbviewer *x, t_symbol *colname, long index, char *text, long maxlen); 00054 t_max_err dbviewer_set_query(t_dbviewer *x, void *attr, long argc, t_atom *argv); 00055 t_max_err dbviewer_set_database(t_dbviewer *x, void *attr, long argc, t_atom *argv); 00056 00057 00058 static t_class *s_dbviewer_class = NULL; 00059 static t_symbol *ps_dbview_update = NULL; 00060 static t_symbol *ps_dbview_query_changed = NULL; 00061 00062 /************************************************************************************/ 00063 00064 int main(void) 00065 { 00066 t_class *c; 00067 long flags; 00068 00069 common_symbols_init(); 00070 c = class_new("dbviewer", (method)dbviewer_new, (method)dbviewer_free, sizeof(t_dbviewer), (method)0L, A_GIMME, 0); 00071 c->c_flags |= CLASS_FLAG_NEWDICTIONARY; 00072 flags = JBOX_COLOR; 00073 jbox_initclass(c, flags); 00074 00075 class_addmethod(c, (method)dbviewer_bang, "bang", 0); // refresh 00076 class_addmethod(c, (method)dbviewer_getcelltext, "getcelltext", A_CANT, 0); 00077 class_addmethod(c, (method)dbviewer_newpatcherview, "newpatcherview", A_CANT, 0); 00078 class_addmethod(c, (method)dbviewer_freepatcherview, "freepatcherview", A_CANT, 0); 00079 class_addmethod(c, (method)dbviewer_notify, "notify", A_CANT, 0); 00080 class_addmethod(c, (method)dbviewer_assist, "assist", A_CANT, 0); 00081 class_addmethod(c, (method)stdinletinfo, "inletinfo", A_CANT, 0); 00082 class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0); 00083 00084 CLASS_ATTR_SYM(c, "query", ATTR_SET_DEFER, t_dbviewer, d_query); 00085 CLASS_ATTR_ACCESSORS(c, "query", NULL, dbviewer_set_query); 00086 CLASS_ATTR_SAVE(c, "query", 0); 00087 00088 CLASS_ATTR_SYM(c, "database", ATTR_SET_DEFER, t_dbviewer, d_database); 00089 CLASS_ATTR_ACCESSORS(c, "database", NULL, dbviewer_set_database); 00090 CLASS_ATTR_SAVE(c, "database", 0); 00091 00092 class_register(_sym_box, c); 00093 s_dbviewer_class = c; 00094 00095 ps_dbview_update = gensym("dbview_update"); 00096 ps_dbview_query_changed = gensym("dbview_query_changed"); 00097 return 0; 00098 } 00099 00100 00101 /************************************************************************************/ 00102 // Object Creation Method 00103 00104 void *dbviewer_new(t_symbol *s, short argc, t_atom *argv) 00105 { 00106 t_dbviewer *x; 00107 long flags; 00108 t_dictionary *d = NULL; 00109 00110 if (!(d=object_dictionaryarg(argc, argv))) 00111 return NULL; 00112 00113 x = (t_dbviewer*)object_alloc(s_dbviewer_class); 00114 if(x){ 00115 flags = 0 00116 | JBOX_DRAWFIRSTIN 00117 | JBOX_NODRAWBOX 00118 | JBOX_DRAWINLAST 00119 // | JBOX_TRANSPARENT 00120 // | JBOX_NOGROW 00121 // | JBOX_GROWY 00122 | JBOX_GROWBOTH 00123 // | JBOX_IGNORELOCKCLICK 00124 | JBOX_HILITE 00125 // | JBOX_BACKGROUND 00126 // | JBOX_NOFLOATINSPECTOR 00127 // | JBOX_TEXTFIELD 00128 ; 00129 00130 jbox_new(&x->d_box, flags, argc, argv); 00131 x->d_box.b_firstin = (t_object*)x; 00132 object_obex_store((void *)x, _sym_dumpout, (t_object*)outlet_new(x, NULL)); 00133 00134 x->d_columns = hashtab_new(13); 00135 hashtab_flags(x->d_columns, OBJ_FLAG_DATA); 00136 x->d_query = _sym_nothing; 00137 00138 dbviewer_initdataview(x); 00139 attr_dictionary_process(x, d); 00140 00141 jbox_ready(&x->d_box); 00142 // object_notify(x->d_view, ps_dbview_update, NULL); 00143 } 00144 return(x); 00145 } 00146 00147 00148 void dbviewer_initdataview(t_dbviewer *x) 00149 { 00150 x->d_dataview = (t_object*)jdataview_new(); 00151 jdataview_setclient(x->d_dataview, (t_object*)x); 00152 jdataview_setcolumnheaderheight(x->d_dataview, 40); 00153 jdataview_setheight(x->d_dataview, 16.0); 00154 } 00155 00156 00157 // Memory Deallocation 00158 void dbviewer_free(t_dbviewer *x) 00159 { 00160 db_view_remove(x->d_db, &x->d_view); 00161 db_close(&x->d_db); 00162 jbox_free(&x->d_box); 00163 } 00164 00165 00166 void dbviewer_newpatcherview(t_dbviewer *x, t_object *patcherview) 00167 { 00168 jdataview_patchervis(x->d_dataview, patcherview); 00169 } 00170 00171 void dbviewer_freepatcherview(t_dbviewer *x, t_object *patcherview) 00172 { 00173 jdataview_patcherinvis(x->d_dataview, patcherview); 00174 } 00175 00176 00177 t_max_err dbviewer_notify(t_dbviewer *x, t_symbol *s, t_symbol *msg, void *sender, void *data) 00178 { 00179 if(sender == x->d_view){ 00180 if(msg == ps_dbview_update){ 00181 dbviewer_bang(x); 00182 } 00183 else if(msg == ps_dbview_query_changed){ // dump all of the columns 00184 t_object *column = NULL; 00185 t_symbol **column_names = NULL; 00186 long numcolumns = 0; 00187 long i; 00188 00189 hashtab_getkeys(x->d_columns, &numcolumns, &column_names); 00190 if(column_names){ 00191 for(i=0; i<numcolumns; i++){ 00192 column = jdataview_getnamedcolumn(x->d_dataview, column_names[i]); 00193 if(column) 00194 jdataview_deletecolumn(x->d_dataview, column); 00195 } 00196 sysmem_freeptr(column_names); 00197 } 00198 hashtab_clear(x->d_columns); 00199 } 00200 else if(msg == _sym_free){ 00201 object_detach_byptr((t_object *)x, x->d_view); 00202 x->d_view = NULL; 00203 } 00204 } 00205 return jbox_notify((t_jbox*)x, s, msg, sender, data); 00206 } 00207 00208 00209 /************************************************************************************/ 00210 // Methods bound to input/inlets 00211 00212 // Method for Assistance Messages 00213 void dbviewer_assist(t_dbviewer *x, void *b, long msg, long arg, char *dst) 00214 { 00215 if(msg==1){ // Inlets 00216 switch(arg){ 00217 case 0: strcpy(dst, "(signal, control) Audio Input and Control Messages"); break; 00218 default: strcpy(dst, "(signal) Audio Input"); break; 00219 } 00220 } 00221 else if(msg==2){ // Outlets 00222 if(arg == 0) 00223 strcpy(dst, "(signal) Audio Output"); 00224 else if(arg == 1) 00225 strcpy(dst, "(symbol) Parameter Name Dump"); 00226 else 00227 strcpy(dst, "dumpout"); 00228 } 00229 } 00230 00231 00232 void dbviewer_bang(t_dbviewer *x) 00233 { 00234 t_object *result = NULL; 00235 long numrecords; 00236 long numfields; 00237 long i; 00238 char *fieldname = NULL; 00239 t_symbol *sfieldname = NULL; 00240 t_object *column; 00241 long column_index; 00242 t_rowref *rowrefs = NULL; 00243 t_max_err err; 00244 00245 db_view_getresult(x->d_view, &result); 00246 jdataview_clear(x->d_dataview); 00247 if (!result) 00248 return; 00249 00250 numrecords = (long)object_method(result, _sym_numrecords); 00251 if(numrecords){ 00252 numfields = (long)object_method(result, _sym_numfields); 00253 for(i = 0; i < numfields; i++){ 00254 fieldname = (char*)object_method(result, _sym_fieldnamebyindex, i); 00255 if(fieldname){ 00256 sfieldname = gensym(fieldname); 00257 err = hashtab_lookup(x->d_columns, sfieldname, (t_object**)&column_index); 00258 if(!err){ 00259 ; // column already exists, so we leave it alone 00260 } 00261 else{ 00262 column = jdataview_addcolumn(x->d_dataview, sfieldname, NULL, true); 00263 jcolumn_setlabel(column, sfieldname); 00264 jcolumn_setwidth(column, 110); 00265 jcolumn_setmaxwidth(column, 300); 00266 hashtab_store(x->d_columns, sfieldname, (t_object*)i); 00267 } 00268 } 00269 } 00270 00271 rowrefs = (t_rowref*)malloc(sizeof(t_rowref) * numrecords); 00272 for(i = 0; i < numrecords; i++) 00273 rowrefs[i] = (t_rowref*)(i+1); 00274 jdataview_addrows(x->d_dataview, numrecords, rowrefs); 00275 free(rowrefs); 00276 } 00277 } 00278 00279 00280 void dbviewer_getcelltext(t_dbviewer *x, t_symbol *colname, long index, char *text, long maxlen) 00281 { 00282 t_object *result = (t_object*)object_method(x->d_view, gensym("getresult")); 00283 char *itemtext; 00284 long column_index; 00285 t_max_err err; 00286 00287 if(!result) 00288 return; 00289 00290 err = hashtab_lookup(x->d_columns, colname, (t_object **)&column_index); 00291 if(!err){ 00292 itemtext = (char*)object_method(result, _sym_valuebyindex, index-1, column_index); 00293 00294 if (itemtext && itemtext[0]) { 00295 if (strstr(colname->s_name, "date")) { 00296 t_datetime td; 00297 sysdateformat_strftimetodatetime(itemtext, &td); 00298 sysdateformat_formatdatetime(&td, SYSDATEFORMAT_RELATIVE, 0, text, maxlen-1); 00299 } 00300 else 00301 strncpy_zero(text, itemtext, maxlen-1); 00302 } 00303 } 00304 } 00305 00306 00307 t_max_err dbviewer_set_query(t_dbviewer *x, void *attr, long argc, t_atom *argv) 00308 { 00309 if(argc && argv){ 00310 x->d_query = atom_getsym(argv); 00311 object_attr_setsym(x->d_view, _sym_query, x->d_query); 00312 if (x->d_db && x->d_query) { 00313 db_view_create(x->d_db, x->d_query->s_name, &x->d_view); 00314 object_attach_byptr_register(x, x->d_view, _sym_nobox); 00315 } 00316 } 00317 return MAX_ERR_NONE; 00318 } 00319 00320 00321 t_max_err dbviewer_set_database(t_dbviewer *x, void *attr, long argc, t_atom *argv) 00322 { 00323 t_max_err err; 00324 00325 if(argc && argv){ 00326 db_view_remove(x->d_db, &x->d_view); 00327 db_close(&x->d_db); 00328 00329 x->d_database = atom_getsym(argv); 00330 err = db_open(x->d_database, NULL, &x->d_db); 00331 if (!err && x->d_db && x->d_query) { 00332 db_view_create(x->d_db, x->d_query->s_name, &x->d_view); 00333 object_attach_byptr_register(x, x->d_view, _sym_nobox); 00334 } 00335 } 00336 return MAX_ERR_NONE; 00337 } 00338
Copyright © 2008, Cycling '74