diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-05-18 20:37:33 +0200 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-05-30 15:56:14 +0200 |
commit | 099969757f0f74c1fc3a65db05442261227174d3 (patch) | |
tree | d4fd07ed9c2d4416752128b2643d490d7bca93da | |
parent | a42d1ef7ae9bf4d4c3c60b7a9de0abe5a1649309 (diff) | |
download | experiment-player-099969757f0f74c1fc3a65db05442261227174d3.tar.gz |
first draft of experiment-reader API for handling contributions
-rw-r--r-- | lib/experiment-reader/experiment-reader.c | 147 | ||||
-rw-r--r-- | lib/experiment-reader/experiment-reader.h | 15 |
2 files changed, 161 insertions, 1 deletions
diff --git a/lib/experiment-reader/experiment-reader.c b/lib/experiment-reader/experiment-reader.c index cb2757e..8c01904 100644 --- a/lib/experiment-reader/experiment-reader.c +++ b/lib/experiment-reader/experiment-reader.c @@ -8,6 +8,7 @@ #include "config.h" #endif +#include <string.h> #include <assert.h> #include <glib.h> @@ -30,6 +31,9 @@ static gboolean generic_foreach_topic(ExperimentReader *reader, xmlNodeSet *node ExperimentReaderTopicCallback callback, gpointer data); +static gint experiment_reader_contrib_cmp(const ExperimentReaderContrib *a, + const ExperimentReaderContrib *b); + /** @private */ #define EXPERIMENT_READER_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE((obj), EXPERIMENT_TYPE_READER, ExperimentReaderPrivate)) @@ -111,7 +115,8 @@ static xmlNode * get_first_element(xmlNode *children, const gchar *name) { for (xmlNode *cur = children; cur != NULL; cur = cur->next) - if (!g_strcmp0((const gchar *)cur->name, name)) + if (cur->type == XML_ELEMENT_NODE && + !g_strcmp0((const gchar *)cur->name, name)) return cur; return NULL; @@ -149,6 +154,17 @@ generic_foreach_topic(ExperimentReader *reader, xmlNodeSet *nodes, return FALSE; } +static gint +experiment_reader_contrib_cmp(const ExperimentReaderContrib *a, + const ExperimentReaderContrib *b) +{ + if (a->start_time < b->start_time) + return -1; + if (a->start_time > b->start_time) + return 1; + return 0; +} + /* * API */ @@ -176,6 +192,135 @@ experiment_reader_new(const gchar *filename) return reader; } +GList * +experiment_reader_get_contributions_by_speaker(ExperimentReader *reader, + const gchar *speaker) +{ + GList *list = NULL; + + xmlXPathContext *xpathCtx; + xmlXPathObject *xpathObj; + + xmlChar expr[255]; + + xpathCtx = xmlXPathNewContext(reader->priv->doc); + + /* Evaluate xpath expression */ + xmlStrPrintf(expr, sizeof(expr), + (const xmlChar *) + "//contribution[@speaker-reference = " + "/session/speakers/speaker[name = '%s']/@speaker-id]", + speaker); + xpathObj = xmlXPathEvalExpression(expr, xpathCtx); + + for (int i = 0; i < xpathObj->nodesetval->nodeNr; i++) { + xmlNode *contrib = xpathObj->nodesetval->nodeTab[i]; + xmlChar *ref; + gint64 start_time; + + gchar *text = NULL; + + ref = xmlGetProp(contrib, (const xmlChar *)"start-reference"); + start_time = get_timepoint_by_ref(reader->priv->doc, ref); + xmlFree(ref); + + for (xmlNode *cur = contrib->children; cur != NULL; cur = cur->next) { + xmlChar *content; + gchar *new; + + switch (cur->type) { + case XML_TEXT_NODE: + content = xmlNodeGetContent(cur); + + new = g_strconcat(text != NULL ? text : "", + g_strstrip((gchar *)content), + " ", NULL); + g_free(text); + text = new; + + xmlFree(content); + break; + + case XML_ELEMENT_NODE: + if (!xmlStrcmp(cur->name, (const xmlChar *)"pause")) { + xmlChar *duration = xmlGetProp(cur, (const xmlChar *)"duration"); + + if (duration != NULL) { + if (!xmlStrcmp(duration, (const xmlChar *)"micro") || + !xmlStrcmp(duration, (const xmlChar *)"short")) + new = g_strconcat(text != NULL ? text : "", " ...", NULL); + else + new = g_strconcat(text != NULL ? text : "", "\n", NULL); + g_free(text); + text = new; + + xmlFree(duration); + } + } else if (!xmlStrcmp(cur->name, (const xmlChar *)"time")) { + if (text != NULL) { + ExperimentReaderContrib *contrib = g_malloc(sizeof(ExperimentReaderContrib) + strlen(text) + 1); + + contrib->start_time = start_time; + g_stpcpy(contrib->text, text); + + list = g_list_insert_sorted(list, contrib, (GCompareFunc)experiment_reader_contrib_cmp); + + g_free(text); + text = NULL; + } + + ref = xmlGetProp(cur, (const xmlChar *)"timepoint-reference"); + start_time = get_timepoint_by_ref(reader->priv->doc, ref); + xmlFree(ref); + } + break; + + default: + break; + } + } + + if (text != NULL) { + ExperimentReaderContrib *contrib = g_malloc(sizeof(ExperimentReaderContrib) + strlen(text) + 1); + + contrib->start_time = start_time; + g_stpcpy(contrib->text, text); + + list = g_list_insert_sorted(list, contrib, (GCompareFunc)experiment_reader_contrib_cmp); + + g_free(text); + } + } + + xmlXPathFreeObject(xpathObj); + xmlXPathFreeContext(xpathCtx); + + return list; +} + +GList * +experiment_reader_get_contribution_by_time(GList *contribs, + gint64 timept) +{ + for (GList *cur = contribs; cur != NULL; cur = cur->next) { + ExperimentReaderContrib *contrib = (ExperimentReaderContrib *)cur->data; + + if (contrib->start_time >= timept) + return cur; + } + + return NULL; +} + +void +experiment_reader_free_contributions(GList *contribs) +{ + for (GList *cur = contribs; cur != NULL; cur = cur->next) + g_free(cur->data); + + g_list_free(contribs); +} + /** * Calls \e callback with \e userdata for each \b topic in the \b greeting * section of the experiment. diff --git a/lib/experiment-reader/experiment-reader.h b/lib/experiment-reader/experiment-reader.h index 7747d95..19f34dc 100644 --- a/lib/experiment-reader/experiment-reader.h +++ b/lib/experiment-reader/experiment-reader.h @@ -63,16 +63,31 @@ GType experiment_reader_get_type(void); * @param start_time Beginning of first \b contribution in \e topic (milliseconds) * @param data Callback user data */ +/** @todo Perhaps we should use CClosures */ typedef void (*ExperimentReaderTopicCallback)(ExperimentReader *reader, const gchar *topic_id, gint64 start_time, gpointer data); +typedef struct { + gint64 start_time; + gchar text[]; +} ExperimentReaderContrib; + /* * API */ ExperimentReader *experiment_reader_new(const gchar *filename); +GList *experiment_reader_get_contributions_by_speaker( + ExperimentReader *reader, + const gchar *speaker); +GList *experiment_reader_get_contribution_by_time( + GList *contribs, + gint64 timept); +void experiment_reader_free_contributions( + GList *contribs); + void experiment_reader_foreach_greeting_topic( ExperimentReader *reader, ExperimentReaderTopicCallback callback, |