paraslash 0.7.3
[paraslash.git] / mp.c
diff --git a/mp.c b/mp.c
index 12fe336ef682823df8de17ead3669f1b7d120ec6..a068b043faf3c09b72befde39771058108f1aec9 100644 (file)
--- a/mp.c
+++ b/mp.c
@@ -1,8 +1,4 @@
-/*
- * Copyright (C) 2017 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* Copyright (C) 2017 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
 
 /**
  * \file mp.c Mood parser helper functions.
  * This file contains the public and the private API of the flex/bison based
  * mood parser.
  *
- * The public API (at the bottom of the file) allows to parse the same mood
+ * The public API (at the bottom of the file) allows parsing the same mood
  * definition many times in an efficient manner.
  *
- * The first function to all is \ref mp_init(), which analyzes the given mood
+ * The first function to call is \ref mp_init(), which analyzes the given mood
  * definition syntactically. It returns the abstract syntax tree of the mood
  * definition and pre-compiles all regular expression patterns to make later
  * pattern matching efficient.
@@ -65,8 +61,8 @@ struct mp_context {
  *
  * This function turns a generalized C99 string literal like "xyz\n" into a C
  * string (containing the three characters 'x', 'y' and 'z', followed by a
- * newline character and the terminating zero byte). The function allows to
- * specify different quote characters so that, for example, regular expression
+ * newline character and the terminating zero byte). The function receives
+ * quote characters as an argument so that, for example, regular expression
  * patterns enclosed in '/' can be parsed as well. To parse a proper string
  * literal, one has to pass two double quotes as the second argument.
  *
@@ -94,7 +90,7 @@ unsigned parse_quoted_string(const char *src, const char quote_chars[2],
 
        assert(len >= 2);
        assert(src[0] == quote_chars[0]);
-       p = dst = para_malloc(len - 1);
+       p = dst = alloc(len - 1);
        backslash = false;
        for (n = 1;; n++) {
                char c;
@@ -393,6 +389,27 @@ MP_AFHI(frequency)
 MP_AFHI(channels)
 /** \endcond */
 
+/**
+ * Return the duration of the audio file from the afh info structure.
+ *
+ * \param ctx See \ref mp_path().
+ *
+ * The duration is computed by multiplying the number of chunks and the
+ * duration of one chunk.
+ *
+ * \return The approximate number of milliseconds.
+ */
+int64_t mp_duration(struct mp_context *ctx)
+{
+       struct timeval tmp;
+       int ret = get_afhi(ctx);
+
+       if (ret < 0)
+               return 0;
+       tv_scale(ctx->afhi.chunks_total, &ctx->afhi.chunk_tv, &tmp);
+       return tv2ms(&tmp);
+}
+
 /**
  * Define a function which extracts and returns the value of a meta tag.
  *
@@ -495,13 +512,13 @@ int mp_init(const char *definition, int nbytes, struct mp_context **result,
        struct mp_context *ctx;
        struct yy_buffer_state *buffer_state;
 
+       *result = NULL;
        if (!definition || nbytes == 0) { /* dummy mood */
                if (errmsg)
                        *errmsg = NULL;
-               *result = NULL;
                return 0;
        }
-       ctx = para_calloc(sizeof(*ctx));
+       ctx = zalloc(sizeof(*ctx));
        ctx->errmsg = NULL;
        ctx->ast = NULL;
 
@@ -514,6 +531,7 @@ int mp_init(const char *definition, int nbytes, struct mp_context **result,
        mp_yy_delete_buffer(buffer_state, scanner);
        mp_yylex_destroy(scanner);
        if (ctx->errmsg) { /* parse error */
+               mp_free_ast(ctx->ast);
                if (errmsg)
                        *errmsg = ctx->errmsg;
                else
@@ -539,12 +557,14 @@ int mp_init(const char *definition, int nbytes, struct mp_context **result,
  * function returns true (without looking at the audio file metadata) to
  * indicate that the given audio file should be considered admissible.
  *
- * \sa \ref change_current_mood(), \ref mp_eval_ast().
+ * \sa \ref mood_load(), \ref mp_eval_ast().
  */
 bool mp_eval_row(const struct osl_row *aft_row, struct mp_context *ctx)
 {
        if (!ctx) /* dummy mood */
                return true;
+       if (!ctx->ast) /* empty mood */
+               return true;
        assert(aft_row);
        ctx->aft_row = aft_row;
        ctx->have_afsi = false;