From 8d36eb43da27bef1e7bc3d626f46cb4c92ca2a41 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Thu, 30 Aug 2018 22:09:54 +0200 Subject: [PATCH] mood: Make "duration" a new keyword for the mood grammar. The new keyword makes it possible to define moods which impose a constraint on the duration of the admissible files. For example, the expression duration < 120 * 1000 selects only files which are shorter than two minutes. The implementation is pretty simple. --- mp.c | 21 +++++++++++++++++++++ mp.h | 1 + web/manual.md | 1 + yy/mp.lex | 1 + yy/mp.y | 5 +++++ 5 files changed, 29 insertions(+) diff --git a/mp.c b/mp.c index 416b4f92..b5fa9cac 100644 --- a/mp.c +++ b/mp.c @@ -389,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. * diff --git a/mp.h b/mp.h index febbe324..891bfb05 100644 --- a/mp.h +++ b/mp.h @@ -139,6 +139,7 @@ bool mp_is_set(const char *attr, struct mp_context *ctx); char *mp_path(struct mp_context *ctx); int64_t mp_year(struct mp_context *ctx); int64_t mp_num_attributes_set(struct mp_context *ctx); +int64_t mp_duration(struct mp_context *ctx); /* Generated with MP_AFSI() */ /** \cond MP_AFSI */ diff --git a/web/manual.md b/web/manual.md index db28a699..d73263b3 100644 --- a/web/manual.md +++ b/web/manual.md @@ -1023,6 +1023,7 @@ Keyword | Type | Semantic value `bitrate` | integer | The average bitrate `frequency` | integer | The output sample rate `channels` | integer | The number of channels +`duration` | integer | The number of milliseconds `is_set("foo")` | boolean | True if attribute "foo" is set. [\*] For most audio formats, the year tag is stored as a string. It diff --git a/yy/mp.lex b/yy/mp.lex index 2dbe21b7..4a53db27 100644 --- a/yy/mp.lex +++ b/yy/mp.lex @@ -74,6 +74,7 @@ lyrics_id {return LYRICS_ID;} bitrate {return BITRATE;} frequency {return FREQUENCY;} channels {return CHANNELS;} +duration {return DURATION;} true {return TRUE;} false {return FALSE;} diff --git a/yy/mp.y b/yy/mp.y index 0f2c9cb8..06d76101 100644 --- a/yy/mp.y +++ b/yy/mp.y @@ -210,6 +210,9 @@ static int eval_node(struct mp_ast_node *node, struct mp_context *ctx, case CHANNELS: result->intval= mp_channels(ctx); return ST_INTVAL; + case DURATION: + result->intval= mp_duration(ctx); + return ST_INTVAL; /* bools */ case IS_SET: arg = node->children[0]->sv.strval; @@ -327,6 +330,7 @@ bool mp_eval_ast(struct mp_ast_node *root, struct mp_context *ctx) %token BITRATE %token FREQUENCY %token CHANNELS +%token DURATION %token FALSE TRUE /* keywords without semantic value */ @@ -377,6 +381,7 @@ exp: NUM {$$ = $1;} | BITRATE {$$ = mp_new_ast_leaf_node(BITRATE);} | FREQUENCY {$$ = mp_new_ast_leaf_node(FREQUENCY);} | CHANNELS {$$ = mp_new_ast_leaf_node(CHANNELS);} + | DURATION {$$ = mp_new_ast_leaf_node(DURATION);} ; boolexp: IS_SET '(' STRING_LITERAL ')' {$$ = ast_node_new_unary(IS_SET, $3);} -- 2.39.5