view examples/runner-rdf/populate.c @ 577:a3d62f2f864f

Some memory-handling fixes Free the correct bits of datum, not bits that have already been set to NULL, after getting query results back (both in the command-line binary and in the PD external). In the external, free the results structure once the data has been passed into the outlets.
author mas01cr
date Mon, 06 Jul 2009 15:26:24 +0000
parents d25eb017b68e
children 29f3289bb183
line wrap: on
line source
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <librdf.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>

#include <audioDB_API.h>

const char * qstring = 
" PREFIX af: <http://purl.org/ontology/af/>"
" PREFIX dc: <http://purl.org/dc/elements/1.1/>"
" PREFIX mo: <http://purl.org/ontology/mo/>"
" PREFIX tl: <http://purl.org/NET/c4dm/timeline.owl#>"

" SELECT ?key ?value ?sample_rate ?window_length ?hop_size"
" FROM <file:///home/csr21/tmp/rdf/test.n3> "

" WHERE { "

"   ?signal mo:available_as ?key ."

"   ?signal mo:time [ tl:onTimeLine ?signal_timeline ] . "

"   ?timeline_map a tl:UniformSamplingWindowingMap ; "
"     tl:rangeTimeLine ?feature_timeline ; "
"     tl:domainTimeLine ?signal_timeline ; "
"     tl:sampleRate ?sample_rate ; "
"     tl:windowLength ?window_length ; "
"     tl:hopSize ?hop_size . "

"   ?signal af:signal_feature ?feature . "

"   ?feature a ?feature_signal_type ; "
"     mo:time [ tl:onTimeLine ?feature_timeline ] ; "
"     af:value ?value . "

"   ?feature_signal_type dc:title \"Key Strength Plot\""

" } "
;

double *parse_value_string(const char *value_string, size_t *nelements) {
  /* What error checking? */

  *nelements = 0;

  const char *current = value_string;
  char *next = 0;

  size_t size = 1;
  double *buf = (double *) malloc(size * sizeof(double));
  double value = strtod(current, &next);
  while(next != current) {
    buf[(*nelements)++] = value;
    if((*nelements) == size) {
      size *= 2;
      buf = (double *) realloc(buf, 2 * size * sizeof(double));
    }
    current = next;
    value = strtod(current, &next);
  }
  return buf;
}

int main() {
  librdf_world *world;
  if (!(world = librdf_new_world())) 
    goto librdf_error;

  librdf_storage *storage;
  if (!(storage = librdf_new_storage(world, "memory", NULL, NULL)))
    goto librdf_error;

  librdf_model *model;
  if (!(model = librdf_new_model(world, storage, NULL)))
    goto librdf_error;

  librdf_uri *uri;
  if (!(uri = librdf_new_uri(world, "file:data/test.n3")))
    goto librdf_error;

  librdf_parser *parser;
  if (!(parser = librdf_new_parser(world, "guess", NULL, NULL)))
    goto librdf_error;

  if(librdf_parser_parse_into_model(parser, uri, NULL, model))
    goto librdf_error;
  
  librdf_query *query;
  if (!(query = librdf_new_query(world, "sparql", NULL, qstring, NULL)))
    goto librdf_error;

  librdf_query_results *results;
  if (!(results = librdf_query_execute(query, model)))
    goto librdf_error;

  if(!librdf_query_results_is_bindings(results)) 
    goto librdf_error;

  adb_t *adb; 
  if(!(adb = audiodb_open("keyplot.adb", O_RDWR))) {
    struct stat st;
    if(!(stat("keyplot.adb", &st))) {
      fprintf(stderr, "keyplot.adb not opened.\n");
      return 1;
    } else {
      /* FIXME: if we are doing a proper SPARQL query over a
       * potentially unbounded number of results, we could use
       * librdf_query_results_get_count() to estimate how much space
       * our database will need.

       * If we're doing a SPARQL query over a number of RDF files,
       * with an expected number of datasets per file of 1 (as might
       * be produced by runner(?)) then obviously we can use that as
       * an estimate of number of tracks instead.

       * Specifying the data dimensionality should be easy from the
       * semantics of the feature being inserted; it's not immediately
       * obvious to me how to estimate the data size required, unless
       * we maybe do a preliminary query to find out the total time
       * (or similar) of all the tracks we're about to insert.

       * (also NOTE: this audiodb_create() interface is scheduled for
       * being made less inelegant.) */
      if(!(adb = audiodb_create("keyplot.adb", 0, 0, 0))) {
        fprintf(stderr, "failed to create keyplot.adb.\n");
        return 1;
      }
    }
  }

  while(!librdf_query_results_finished(results)) {
    int count = librdf_query_results_get_bindings_count(results);
    adb_datum_t datum = {0};
    datum.dim = 25;
    for (int i = 0; i < count; i++) {
      const char *name = librdf_query_results_get_binding_name(results, i);
      librdf_node *node = librdf_query_results_get_binding_value(results, i);
      if(!node) return 2;

      if(!strcmp(name, "key")) {
        datum.key = librdf_uri_as_string(librdf_node_get_uri(node));
      } else if(!strcmp(name, "value")) {
        size_t nelements = 0;
        datum.data = parse_value_string(librdf_node_get_literal_value(node), &nelements);
        if(nelements % 25) return 4;
        datum.nvectors = nelements / 25;
      } else {
        /* do something with the timeline (and other) information */
        printf("%s: %s\n", name, librdf_node_get_literal_value(node));
      }
      librdf_free_node(node);
    }
    if(audiodb_insert_datum(adb, &datum)) {
      fprintf(stderr, "failed to insert datum with key %s.\n", datum.key);
      return 1;
    }
    free(datum.data);
    librdf_query_results_next(results);
  }

  audiodb_close(adb);
  librdf_free_query_results(results);
  librdf_free_query(query);
  librdf_free_parser(parser);
  librdf_free_uri(uri);
  librdf_free_model(model);
  librdf_free_storage(storage);
  librdf_free_world(world);

  return 0;

 librdf_error:
  fprintf(stderr, "Something went wrong in librdf.\n");
  return 1;
}