changeset 569:327fd3aa17e6

Shifted the query type condition into setquerytype, so it's no longer stored as a string. Also did some rejigging to get the tabs consistent, and added some comments for a few less obvious areas of code.
author mas01mj
date Wed, 01 Jul 2009 11:44:55 +0000
parents 7a257a2364a4
children d1456b3f490a
files bindings/pd/adbpd.c
diffstat 1 files changed, 226 insertions(+), 227 deletions(-) [+]
line wrap: on
line diff
--- a/bindings/pd/adbpd.c	Wed Jul 01 11:44:49 2009 +0000
+++ b/bindings/pd/adbpd.c	Wed Jul 01 11:44:55 2009 +0000
@@ -30,18 +30,18 @@
 	t_outlet *x_qpos;
 	t_outlet *x_spos;
 
-    t_symbol *x_dbname; //database name
+  t_symbol *x_dbname; //database name
 
-    t_symbol *x_dbquerytype; //sequence, track, etc.
-    t_symbol *x_dbfeature; 
+  t_int x_dbquerytype; //sequence, track, etc.
+  t_symbol *x_dbfeature; 
 //    t_symbol *x_dbpower;
-    t_symbol *x_dbkey;
-    t_float x_dbqpoint;
-    t_float x_dbnumpoints;
-    t_float x_dbradius;
-    t_float x_dbresultlength;
-    t_float x_dbsequencelength;
-    adb_ptr db; 
+  t_symbol *x_dbkey;
+  t_float x_dbqpoint;
+  t_float x_dbnumpoints;
+  t_float x_dbradius;
+  t_float x_dbresultlength;
+  t_float x_dbsequencelength;
+  adb_ptr db; 
 } t_adbpd;
 
 
@@ -86,56 +86,54 @@
 	x->x_qpos = outlet_new(&x->x_obj, &s_float);
 	x->x_spos = outlet_new(&x->x_obj, &s_float);
 
-    /* adb defaults. These are the same but we need to init them */
-    x->x_dbname=gensym("no db has been specified yet");
-    x->x_dbquerytype=gensym("point");
-    x->x_dbfeature=gensym("No feature file yet specified");
-    x->x_dbqpoint=1;
-    x->x_dbnumpoints=10;
-    x->x_dbradius=1;
-    x->x_dbresultlength=10;
-    x->x_dbsequencelength=12;
+  /* adb defaults. These are the same but we need to init them */
+  x->x_dbname=gensym("no db has been specified yet");
+  x->x_dbquerytype=O2_POINT_QUERY;
+  x->x_dbfeature=gensym("No feature file yet specified");
+  x->x_dbqpoint=1;
+  x->x_dbnumpoints=10;
+  x->x_dbradius=1;
+  x->x_dbresultlength=10;
+  x->x_dbsequencelength=12;
 	return(x);
-	
+  
 }
 
-
-
 /* bang just gets the status of the db */
 static void adbpd_bang(t_adbpd *x) {
-    adbpd_doquery(x);
+  adbpd_doquery(x);
 
 }
 
 /* create a database */
 static void adbpd_create(t_adbpd *x){
 	
-    post("creating db '%s'",x->x_dbname->s_name);
-    dbpointer=audiodb_create(x->x_dbname->s_name,0,0,0);
-	
-    if (dbpointer){
-        post("Created");
-        x->db=dbpointer;
-    } else {
-        error("Could not create db. May already exist");
-        x->db=NULL;
-    }
+  post("creating db '%s'",x->x_dbname->s_name);
+  dbpointer=audiodb_create(x->x_dbname->s_name,0,0,0);
+
+  if (dbpointer){
+      post("Created");
+      x->db=dbpointer;
+  } else {
+      error("Could not create db. May already exist");
+      x->db=NULL;
+  }
 	
 }
 
 /* open a database. Need to work out the path stuff here. At present databases need to be in the root directory. Not good. */
 static void adbpd_open(t_adbpd *x){
 	
-    post("Opening db '%s'",x->x_dbname->s_name);
-    dbpointer=audiodb_open(x->x_dbname->s_name,O_RDWR);
-	
-    if (dbpointer){
-		post("Opened db");
-        x->db=dbpointer;
-    } else {
-        error("failed ! Check '%s' exists, or create a new db",x->x_dbname->s_name);
-        x->db=NULL;
-    }
+  post("Opening db '%s'",x->x_dbname->s_name);
+  dbpointer=audiodb_open(x->x_dbname->s_name,O_RDWR);
+
+  if (dbpointer){
+	post("Opened db");
+    x->db=dbpointer;
+  } else {
+    error("failed ! Check '%s' exists, or create a new db",x->x_dbname->s_name);
+    x->db=NULL;
+  }
 	
 }
 
@@ -143,205 +141,192 @@
 static void adbpd_setname(t_adbpd *x, t_symbol *s, int argc, t_atom *argv){
 	
 	/* if we have a properly formed instruction */
-    if (argc == 1 && argv->a_type == A_SYMBOL){
-        x->x_dbname=gensym(argv->a_w.w_symbol->s_name); /* make the internal database reference name the same as the name of the database we want.
-		 This is stupid. There must be a better way of doing this. */
-        post("Name has been set to '%s', and can now be opened.",x->x_dbname->s_name);
-    }
+  if (argc == 1 && argv->a_type == A_SYMBOL){
+    x->x_dbname=gensym(argv->a_w.w_symbol->s_name); /* make the internal database reference name the same as the name of the database we want.
+	 This is stupid. There must be a better way of doing this. */
+    post("Name has been set to '%s', and can now be opened.",x->x_dbname->s_name);
+  }
 	
 	/* now we can open the database as we did with the audiodb_open call above*/
 	
 	post("Opening db '%s'",x->x_dbname->s_name);
-    dbpointer=audiodb_open(x->x_dbname->s_name,O_RDWR); /* opened in read and write mode for when I get round to doing the insert code */
+  dbpointer=audiodb_open(x->x_dbname->s_name,O_RDWR); /* opened in read and write mode for when I get round to doing the insert code */
 	
-    if (dbpointer){ /* yes we have a database*/
-		post("Opened db");
-        x->db=dbpointer;
-    } else {
-        error("failed ! Check '%s' exists, or create a new db",x->x_dbname->s_name);
-        x->db=NULL;
-    }
+  if (dbpointer){ /* yes we have a database*/
+	post("Opened db");
+    x->db=dbpointer;
+  } else {
+    error("failed ! Check '%s' exists, or create a new db",x->x_dbname->s_name);
+    x->db=NULL;
+  }
 }
 
 
 /* this is a status call to the audioDB API */
 static void adbpd_status(t_adbpd *x){
 
-    adb_status_t mystatus; 
-	
-    post("Getting Status");
-	
-    if (x->db && !(audiodb_status(x->db,&mystatus))){
-        post("numFiles %d",mystatus.numFiles);
-        post("dim %d",mystatus.dim);
-        post("length %d",mystatus.length);
-        post("dudCount %d",mystatus.dudCount);
-        post("numCount %d",mystatus.nullCount);
-        post("flags %d",mystatus.flags);
-		post("Bytes Available %d",mystatus.data_region_size);
-    } else {
-        error("Can't get Status. Have you selected a db?");
-    }
+  adb_status_t mystatus; 
+
+  post("Getting Status");
+
+  if (x->db && !(audiodb_status(x->db,&mystatus))){
+    post("numFiles %d",mystatus.numFiles);
+    post("dim %d",mystatus.dim);
+    post("length %d",mystatus.length);
+    post("dudCount %d",mystatus.dudCount);
+    post("numCount %d",mystatus.nullCount);
+    post("flags %d",mystatus.flags);
+    post("Bytes Available %d",mystatus.data_region_size);
+  } else {
+    error("Can't get Status. Have you selected a db?");
+  }
 }
 
 
 static void adbpd_doquery(t_adbpd *x){
 
-    adb_datum_t datum = {0};
-    adb_query_id_t qid = {0};
-    adb_query_parameters_t params = {0};
-    adb_query_refine_t refine = {0};
-    adb_query_spec_t spec = {0};
-     
-    qid.datum = &datum;
-    qid.sequence_length = x->x_dbsequencelength;
-    qid.sequence_start = x->x_dbqpoint;
-    qid.flags = 0;
+  adb_datum_t datum = {0};
+  adb_query_id_t qid = {0};
+  adb_query_parameters_t params = {0};
+  adb_query_refine_t refine = {0};
+  adb_query_spec_t spec = {0};
+  
+  // Configure the start+length of the query, and zero
+  // the flags initially.
+  qid.datum = &datum;
+  qid.sequence_length = x->x_dbsequencelength;
+  qid.sequence_start = x->x_dbqpoint;
+  qid.flags = 0;
 
-    refine.hopsize = 1;
-    refine.flags |= ADB_REFINE_RADIUS;
-    refine.radius = x->x_dbradius;
+  // We don't specify hopsize (yet) so it defaults to 1.
+  refine.hopsize = 1;
+  refine.flags |= ADB_REFINE_RADIUS;
+  refine.radius = x->x_dbradius;
 
-    spec.qid = qid;
-    spec.params = params;
-    spec.refine = refine;
+  spec.qid = qid;
+  spec.params = params;
+  spec.refine = refine;
+  
+  int fd;
+  struct stat st;
+
+  // Read in the feature file - note that this code may contain leaks
+  // (the same chunk also exists in audioDB.cpp).
+  fd = open(x->x_dbfeature->s_name, O_RDONLY);
+  if(fd < 0) {
+    error("failed to open feature file", x->x_dbfeature->s_name);
+    return;
+  }
+  fstat(fd, &st);
+  read(fd, &datum.dim, sizeof(uint32_t));
+  datum.nvectors = (st.st_size - sizeof(uint32_t)) / (datum.dim * sizeof(double));
+  datum.data = (double *) malloc(st.st_size - sizeof(uint32_t));
+  read(fd, datum.data, st.st_size - sizeof(uint32_t));
+  close(fd);
+  
+  // Set up query spec params depending on the query type.
+  switch(x->x_dbquerytype)
+  {
+    case O2_POINT_QUERY:
+      spec.qid.sequence_length = 1;
+      spec.params.accumulation = ADB_ACCUMULATION_DB;
+      spec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
+      spec.params.npoints = x->x_dbnumpoints;
+      spec.params.ntracks = x->x_dbresultlength;
+      break;
+    case O2_TRACK_QUERY:
+      spec.qid.sequence_length = 1;
+      spec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
+      spec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
+      spec.params.npoints = x->x_dbnumpoints;
+      spec.params.ntracks = x->x_dbresultlength;
+    case O2_SEQUENCE_QUERY:
+    case O2_N_SEQUENCE_QUERY:
+      spec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
+      // TODO : Add unit norming param. Defaults to false.
+      // spec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED;
+      spec.params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED;
+      spec.params.npoints = x->x_dbnumpoints;
+      spec.params.ntracks = x->x_dbresultlength;
+      break;
+    case O2_ONE_TO_ONE_N_SEQUENCE_QUERY:
+      spec.params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE;
+      // TODO : Add unit norming param. Defaults to false.
+      // spec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED;
+      spec.params.distance =ADB_DISTANCE_EUCLIDEAN_NORMED;
+      spec.params.npoints = 0;
+      spec.params.ntracks = 0;
+      break;
+    default:
+      post("Unsupported query type");
+  }
+ 
+  adb_query_results_t *rs = audiodb_query_spec(x->db, &spec);
+  
+  if(datum.data) {
+      free(datum.data);
+      datum.data = NULL;
+  }
+  if(datum.power) {
+      free(datum.data);
+      datum.data = NULL;
+  }
+  if(datum.times) {
+      free(datum.data);
+      datum.data = NULL;
+  }
+  
+  if(rs == NULL)
+  {
+    error("Query failed");
+    return;
+  }
+
+  int size = rs->nresults;
+  post("result size:[%d]",(int)size);
+  int i = 0;
+  for(i=0; i<size; i++){
+    adb_result_t r = rs->results[i];
     
-    int fd;
-    struct stat st;
-
-    /* FIXME: around here there are all sorts of hideous leaks. */
-    fd = open(x->x_dbfeature->s_name, O_RDONLY);
-    if(fd < 0) {
-      error("failed to open feature file", x->x_dbfeature->s_name);
-      return;
-    }
-    fstat(fd, &st);
-    read(fd, &datum.dim, sizeof(uint32_t));
-    datum.nvectors = (st.st_size - sizeof(uint32_t)) / (datum.dim * sizeof(double));
-    datum.data = (double *) malloc(st.st_size - sizeof(uint32_t));
-    read(fd, datum.data, st.st_size - sizeof(uint32_t));
-    close(fd);
+    outlet_float(x->x_dist,r.dist);
+    outlet_float(x->x_qpos,r.qpos);
+    outlet_float(x->x_spos,r.ipos);
     
-    int queryType;
-    
-    // query type
-    if(strncmp(x->x_dbquerytype->s_name, "track", MAXSTR)==0)
-      queryType=O2_TRACK_QUERY;
-    else if(strncmp(x->x_dbquerytype->s_name, "point", MAXSTR)==0)
-      queryType=O2_POINT_QUERY;
-    else if(strncmp(x->x_dbquerytype->s_name, "sequence", MAXSTR)==0)
-      queryType=O2_SEQUENCE_QUERY;
-    else if(strncmp(x->x_dbquerytype->s_name, "nsequence", MAXSTR)==0)
-      queryType=O2_N_SEQUENCE_QUERY;
-    else if(strncmp(x->x_dbquerytype->s_name, "onetoonensequence", MAXSTR)==0)
-      queryType=O2_ONE_TO_ONE_N_SEQUENCE_QUERY;
-    else
-      error("unsupported query type");
-    
-    switch(queryType)
-    {
-      case O2_POINT_QUERY:
-        spec.qid.sequence_length = 1;
-        spec.params.accumulation = ADB_ACCUMULATION_DB;
-        spec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
-        spec.params.npoints = x->x_dbnumpoints;
-        spec.params.ntracks = x->x_dbresultlength;
-        break;
-      case O2_TRACK_QUERY:
-        spec.qid.sequence_length = 1;
-        spec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
-        spec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
-        spec.params.npoints = x->x_dbnumpoints;
-        spec.params.ntracks = x->x_dbresultlength;
-      case O2_SEQUENCE_QUERY:
-      case O2_N_SEQUENCE_QUERY:
-        spec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
-        // TODO : Add unit norming param. Defaults to false.
-        // spec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED;
-        spec.params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED;
-        spec.params.npoints = x->x_dbnumpoints;
-        spec.params.ntracks = x->x_dbresultlength;
-        break;
-      case O2_ONE_TO_ONE_N_SEQUENCE_QUERY:
-        spec.params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE;
-        // TODO : Add unit norming param. Defaults to false.
-        // spec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED;
-        spec.params.distance =ADB_DISTANCE_EUCLIDEAN_NORMED;
-        spec.params.npoints = 0;
-        spec.params.ntracks = 0;
-        break;
-      default:
-        post("Unsupported query type");
-    }
-   
-    adb_query_results_t *rs = audiodb_query_spec(x->db, &spec);
-
-    
-    
-    if(datum.data) {
-        free(datum.data);
-        datum.data = NULL;
-    }
-    if(datum.power) {
-        free(datum.data);
-        datum.data = NULL;
-    }
-    if(datum.times) {
-        free(datum.data);
-        datum.data = NULL;
-    }
-    
-    if(rs == NULL)
-    {
-      error("Query failed");
-      return;
-    }
-
-    int size = rs->nresults;
-    post("result size:[%d]",(int)size);
-    int i = 0;
-    for(i=0; i<size; i++){
-        adb_result_t r = rs->results[i];
-        
-        outlet_float(x->x_dist,r.dist);
-        outlet_float(x->x_qpos,r.qpos);
-        outlet_float(x->x_spos,r.ipos);
-        
-        post("in obj key:%s",r.key);
-        post("in obj Dist:%f", r.dist);
-        post("in obj qpos:%d", r.qpos);
-        post("in obj ipos:%d", r.ipos);
-    }
+    post("in obj key:%s",r.key);
+    post("in obj Dist:%f", r.dist);
+    post("in obj qpos:%d", r.qpos);
+    post("in obj ipos:%d", r.ipos);
+  }
     
 }
 
 /* Do I need to set a the power file for this flag to work ? Hmmm. Dunno. Also, should be on/off*/
 
 static void adbpd_power(t_adbpd *x){
-    post("power");
-	
-    if (x->db && !(audiodb_power(x->db))){
-        post("power successfully set on db");
-    } else {
-        error("power flag not working");
-    }   
+  post("power");
+
+  if (x->db && !(audiodb_power(x->db))){
+    post("power successfully set on db");
+  } else {
+    error("power flag not working");
+  }   
 }
 
 /* works fine but would be better if it took an argument to switch it on and off */
 
 static void adbpd_l2norm(t_adbpd *x){
-    post("l2norm");
-	
-    if (x->db && !(audiodb_l2norm(x->db))){
-        post("l2norm successfully set on db");
-    } else {
-        error("l2norm flag not working");
-    }   
+  post("l2norm");
+
+  if (x->db && !(audiodb_l2norm(x->db))){
+    post("l2norm successfully set on db");
+  } else {
+    error("l2norm flag not working");
+  }   
 }
 
 /* reports the name of the current db */
 static void adbpd_getname(t_adbpd *x){
-    post("db name is '%s'",  x->x_dbname->s_name);	
+  post("db name is '%s'",  x->x_dbname->s_name);	
 }
 
 /* this sets the qpoint for the current query*/
@@ -349,7 +334,7 @@
 static void adbpd_setqpoint(t_adbpd *x,t_floatarg f){
 	post("qpoint %.3f",f);
     
-    x->x_dbqpoint=f; 
+  x->x_dbqpoint=f; 
 } 
 
 /* This sets the number of points for current query */
@@ -383,11 +368,11 @@
 /* This sets the feature file to use for the query */
 
 static void adbpd_setfeatures(t_adbpd *x,t_symbol *s,int argc, t_atom *argv){
-	
-    if (argc == 1 && argv->a_type == A_SYMBOL){
-        x->x_dbfeature=gensym(argv->a_w.w_symbol->s_name);
-        post("Features file has been set to '%s'",x->x_dbfeature->s_name);
-    }
+
+  if (argc == 1 && argv->a_type == A_SYMBOL){
+    x->x_dbfeature=gensym(argv->a_w.w_symbol->s_name);
+    post("Features file has been set to '%s'",x->x_dbfeature->s_name);
+  }
 }
 
 /* This sets the query type */
@@ -395,23 +380,38 @@
 static void adbpd_setquerytype(t_adbpd *x,t_symbol *s,int argc, t_atom *argv){ 
     
 	if (argc == 1 && argv->a_type == A_SYMBOL){
-        x->x_dbquerytype=gensym(argv->a_w.w_symbol->s_name);
-        post("Query type has been set to '%s'",x->x_dbquerytype->s_name);
-    }
+  
+    // Determine which constant to use based on the string passed.
+    
+    if(strncmp(argv->a_w.w_symbol->s_name, "track", MAXSTR)==0)
+      x->x_dbquerytype=O2_TRACK_QUERY;
+    else if(strncmp(argv->a_w.w_symbol->s_name, "point", MAXSTR)==0)
+      x->x_dbquerytype=O2_POINT_QUERY;
+    else if(strncmp(argv->a_w.w_symbol->s_name, "sequence", MAXSTR)==0)
+      x->x_dbquerytype=O2_SEQUENCE_QUERY;
+    else if(strncmp(argv->a_w.w_symbol->s_name, "nsequence", MAXSTR)==0)
+      x->x_dbquerytype=O2_N_SEQUENCE_QUERY;
+    else if(strncmp(argv->a_w.w_symbol->s_name, "onetoonensequence", MAXSTR)==0)
+      x->x_dbquerytype=O2_ONE_TO_ONE_N_SEQUENCE_QUERY;
+    else
+      error("unsupported query type");
+ 
+    post("Query type has been set to '%s'",argv->a_w.w_symbol->s_name);
+  }
 }
 
 /* This lists all the parameters */ 
 
 static void adbpd_parameters(t_adbpd *x){
 	
-    post("dbname %s",x->x_dbname->s_name);
-    post("querytype %s",x->x_dbquerytype->s_name);
-    post("features %s",x->x_dbfeature->s_name);
-    post("qpoint %.3f",x->x_dbqpoint);
-    post("numpoints %.3f",x->x_dbnumpoints);
-    post("radius %.3f",x->x_dbradius);
-    post("resultlength %.3f",x->x_dbresultlength);
-    post("sequencelength %.3f",x->x_dbsequencelength);
+  post("dbname %s",x->x_dbname->s_name);
+  post("querytype %d",x->x_dbquerytype);
+  post("features %s",x->x_dbfeature->s_name);
+  post("qpoint %.3f",x->x_dbqpoint);
+  post("numpoints %.3f",x->x_dbnumpoints);
+  post("radius %.3f",x->x_dbradius);
+  post("resultlength %.3f",x->x_dbresultlength);
+  post("sequencelength %.3f",x->x_dbsequencelength);
 }
 
 /* THAR SHE BLOWS. This sets up the object, takes the messages with args and maps them to methods. */
@@ -434,10 +434,9 @@
 	class_addmethod(adbpd_class, (t_method)adbpd_l2norm, gensym("l2norm"), A_NULL);
 	class_addmethod(adbpd_class, (t_method)adbpd_power, gensym("power"), A_NULL);
 	class_addmethod(adbpd_class, (t_method)adbpd_doquery, gensym("doquery"), A_NULL);
-    class_addmethod(adbpd_class, (t_method)adbpd_setquerytype, gensym("querytype"), A_GIMME, 0);
-    class_addmethod(adbpd_class, (t_method)adbpd_setfeatures, gensym("features"), A_GIMME, 0);
+  class_addmethod(adbpd_class, (t_method)adbpd_setquerytype, gensym("querytype"), A_GIMME, 0);
+  class_addmethod(adbpd_class, (t_method)adbpd_setfeatures, gensym("features"), A_GIMME, 0);
 	class_addmethod(adbpd_class, (t_method)adbpd_parameters, gensym("parameters"), A_NULL);
 
-
 }