Max 5 API Reference
00001 /** 00002 @file 00003 dbcuelist - demonstrate use of a sqlite database 00004 00005 This is a very simple example of a cue list: 00006 - an event is simply an array of atom values 00007 - a cue is simply a collection of events with a name 00008 00009 This object itself has a name. 00010 All objects with the same name share the same database (and thus the same cues). 00011 00012 For the syntax of the SQL commands, refer to http://sqlite.org 00013 For the information on the Max database API, refer to the ext_database.h header file. 00014 00015 @ingroup examples 00016 00017 Copyright 2009 - Cycling '74 00018 Timothy Place, tim@cycling74.com 00019 */ 00020 00021 #include "ext.h" 00022 #include "ext_obex.h" 00023 #include "ext_database.h" 00024 00025 00026 // Data Structures 00027 typedef struct _dbcuelist { 00028 t_object d_obj; 00029 void *d_outlet; 00030 t_symbol *d_name; 00031 t_database *d_db; 00032 } t_dbcuelist; 00033 00034 00035 // Prototypes 00036 t_dbcuelist* dbcuelist_new(t_symbol *s, short argc, t_atom *argv); 00037 void dbcuelist_free(t_dbcuelist *x); 00038 void dbcuelist_cue_create(t_dbcuelist *x, t_symbol *s); 00039 void dbcuelist_cue_destroy(t_dbcuelist *x, t_symbol *s); 00040 void dbcuelist_cue_rename(t_dbcuelist *x, t_symbol *s1, t_symbol *s2); 00041 void dbcuelist_cue_do(t_dbcuelist *x, t_symbol *s); 00042 void dbcuelist_event_create(t_dbcuelist *x, t_symbol *s, long argc, t_atom *argv); 00043 void dbcuelist_event_destroy(t_dbcuelist *x, long event_id); 00044 t_max_err dbcuelist_attr_name_set(t_dbcuelist *x, void *attr, long argc, t_atom *argv); 00045 00046 00047 // Globals and Statics 00048 static t_class *s_dbcuelist_class = NULL; 00049 static t_symbol *ps_event = NULL; 00050 00051 /**********************************************************************/ 00052 // Class Definition and Life Cycle 00053 00054 int main(void) 00055 { 00056 t_class *c; 00057 00058 common_symbols_init(); 00059 c = class_new("dbcuelist", 00060 (method)dbcuelist_new, 00061 (method)dbcuelist_free, 00062 sizeof(t_dbcuelist), 00063 (method)NULL, 00064 A_GIMME, 00065 0L); 00066 00067 class_addmethod(c, (method)dbcuelist_cue_create, "cue.create", A_SYM, 0); 00068 class_addmethod(c, (method)dbcuelist_cue_destroy, "cue.destroy", A_SYM, 0); 00069 class_addmethod(c, (method)dbcuelist_cue_rename, "cue.rename", A_SYM, A_SYM, 0); 00070 class_addmethod(c, (method)dbcuelist_cue_do, "cue.do", A_SYM, 0); 00071 00072 class_addmethod(c, (method)dbcuelist_event_create, "event.create", A_GIMME, 0); 00073 class_addmethod(c, (method)dbcuelist_event_destroy, "event.destroy", A_LONG, 0); 00074 00075 CLASS_ATTR_SYM(c, "name", 0, t_dbcuelist, d_name); 00076 CLASS_ATTR_ACCESSORS(c, "name", NULL, dbcuelist_attr_name_set); 00077 00078 class_register(_sym_box, c); 00079 s_dbcuelist_class = c; 00080 ps_event = gensym("event"); 00081 return 0; 00082 } 00083 00084 00085 t_dbcuelist* dbcuelist_new(t_symbol *s, short argc, t_atom *argv) 00086 { 00087 t_dbcuelist* x; 00088 00089 x = (t_dbcuelist*)object_alloc(s_dbcuelist_class); 00090 if (x) { 00091 x->d_outlet = outlet_new(x, 0L); 00092 attr_args_process(x, argc, argv); 00093 } 00094 return x; 00095 } 00096 00097 00098 void dbcuelist_free(t_dbcuelist *x) 00099 { 00100 db_close(&x->d_db); 00101 } 00102 00103 00104 /**********************************************************************/ 00105 // Methods 00106 00107 void dbcuelist_cue_create(t_dbcuelist *x, t_symbol *s) 00108 { 00109 t_max_err err = MAX_ERR_NONE; 00110 00111 err = db_query(x->d_db, NULL, "INSERT INTO cues ( 'name' ) VALUES ( \"%s\" )", s->s_name); 00112 if(err) 00113 object_error((t_object*)x, "error creating event"); 00114 } 00115 00116 00117 void dbcuelist_cue_destroy(t_dbcuelist *x, t_symbol *s) 00118 { 00119 t_max_err err = MAX_ERR_NONE; 00120 00121 err = db_query(x->d_db, NULL, "DELETE FROM cues WHERE name = \"%s\" ", s->s_name); 00122 if(err) 00123 object_error((t_object*)x, "error deleting cue"); 00124 } 00125 00126 00127 void dbcuelist_cue_rename(t_dbcuelist *x, t_symbol *s1, t_symbol *s2) 00128 { 00129 t_max_err err = MAX_ERR_NONE; 00130 00131 err = db_query(x->d_db, NULL, "UPDATE cues SET name = \"%s\" WHERE name = \"%s\" ", s2->s_name, s1->s_name); 00132 if(err) 00133 object_error((t_object*)x, "error deleting cue"); 00134 } 00135 00136 00137 void dbcuelist_cue_do(t_dbcuelist *x, t_symbol *s) 00138 { 00139 t_max_err err = MAX_ERR_NONE; 00140 t_db_result *result = NULL; 00141 char *str = NULL; 00142 int i; 00143 int numrecords; 00144 00145 err = db_query(x->d_db, &result, "SELECT value FROM events WHERE cue_id_ext = \ 00146 (SELECT cue_id FROM cues WHERE name = \"%s\") ", s->s_name); 00147 if(err){ 00148 object_error((t_object*)x, "invalid cue specified for 'do'"); 00149 return; 00150 } 00151 00152 numrecords = db_result_numrecords(result); 00153 for(i=0; i<numrecords; i++){ 00154 t_atom *av = NULL; 00155 long ac = 0; 00156 00157 str = db_result_string(result, i, 0); 00158 atom_setparse(&ac, &av, str); 00159 if(ac && av){ 00160 outlet_anything(x->d_outlet, ps_event, ac, av); 00161 sysmem_freeptr(av); 00162 } 00163 } 00164 } 00165 00166 00167 void dbcuelist_event_create(t_dbcuelist *x, t_symbol *s, long argc, t_atom *argv) 00168 { 00169 t_symbol *name = atom_getsym(argv); 00170 char *text = NULL; 00171 long textsize = 0; 00172 t_max_err err = MAX_ERR_NONE; 00173 00174 if(argc < 2){ 00175 object_error((t_object*)x, "at least two arguments required to create an event"); 00176 return; 00177 } 00178 00179 atom_gettext(argc-1, argv+1, &textsize, &text, 0); 00180 if(text && textsize){ 00181 err = db_query(x->d_db, NULL, "INSERT INTO events ( 'cue_id_ext' , 'value' ) \ 00182 VALUES ( (SELECT cue_id FROM cues WHERE name = \"%s\") , \"%s\") ", 00183 name->s_name, text); 00184 if(err) 00185 object_error((t_object*)x, "error creating event"); 00186 } 00187 } 00188 00189 00190 void dbcuelist_event_destroy(t_dbcuelist *x, long event_id) 00191 { 00192 t_max_err err = MAX_ERR_NONE; 00193 00194 err = db_query(x->d_db, NULL, "DELETE FROM events WHERE event_id = %ld", event_id); 00195 if(err) 00196 object_error((t_object*)x, "error deleting event"); 00197 } 00198 00199 00200 /**********************************************************************/ 00201 // Attribute Accessors 00202 00203 t_max_err dbcuelist_attr_name_set(t_dbcuelist *x, void *attr, long argc, t_atom *argv) 00204 { 00205 t_symbol *newname = atom_getsym(argv); 00206 t_max_err err = MAX_ERR_NONE; 00207 00208 if(newname == x->d_name) 00209 return MAX_ERR_NONE; 00210 00211 // close the old database (if needed) and open the new one 00212 x->d_name = newname; 00213 db_close(&x->d_db); 00214 db_open(x->d_name, NULL, &x->d_db); 00215 00216 // by passing NULL for the second parameter to db_open() we are specifying that 00217 // the db exist solely in memory. 00218 // if you wish for it to be persistent (stored on disk), 00219 // this is left as an exersize for the reader... 00220 00221 // set up the tables in the database 00222 err = db_query_table_new(x->d_db, "cues"); 00223 err = db_query_table_addcolumn(x->d_db, "cues", "name", "VARCHAR(256)", 0); 00224 00225 err = db_query_table_new(x->d_db, "events"); 00226 err = db_query_table_addcolumn(x->d_db, "events", "cue_id_ext", "INTEGER", 0); 00227 err = db_query_table_addcolumn(x->d_db, "events", "value", "TEXT", 0); 00228 00229 // The above will return error codes if the tables or columns already exist. 00230 // This is okay, so we will always return MAX_ERR_NONE. 00231 return MAX_ERR_NONE; 00232 } 00233
Copyright © 2008, Cycling '74