From: Andre Noll Date: Mon, 22 Nov 2021 13:39:27 +0000 (+0100) Subject: Merge branch 'refs/heads/t/duration-keyword' X-Git-Tag: v0.7.0~14 X-Git-Url: http://git.tuebingen.mpg.de/?a=commitdiff_plain;h=b624392bcbc6aec9836ded20b7776f42408bd84d;hp=e65afce0dd0b070ea03ae778fef54e7c3d477d15;p=paraslash.git Merge branch 'refs/heads/t/duration-keyword' A single patch which was created already in 2018 but did not propagate to next and master for no good reason. Cooking for a month. * refs/heads/t/duration-keyword: mood: Make "duration" a new keyword for the mood grammar. --- diff --git a/NEWS.md b/NEWS.md index 073f2647..10826710 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,8 @@ NEWS 0.7.0 (to be announced) "seismic orbit" --------------------------------------- +- The new "duration" keyword of the mood grammar makes it possible to + impose a constraint on the duration of the admissible files. - Paraslash writers handle early end-of-file more gracefully. - The alsa writer no longer warns about spurious underruns. - The score formula of the audio file selector has been reworked. 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);}