player: change --display-tags behavior

Remove the "all" special-behavior, and instead interpret trailing "*"
characters. --display-tags=all is replaced by --display-tags=* as a
special-case of the new behavior.

See #1404.

Note that the most straight-forward value for matchlen in the normal
case would be INT_MAX, because it should be using the entire string.
I used keylen+1 instead, because glibc seems to handle this case
incorrectly:

    snprintf(buf, sizeof(buf), "%.*s", INT_MAX, "hello");

The result is empty, instead of just containing the string argument.
This might be a glibc bug; it works with other libcs (even MinGW-w64).
This commit is contained in:
wm4 2015-01-12 04:54:34 +01:00
parent f3a978cd17
commit 3f3e1547ba
2 changed files with 18 additions and 8 deletions

View File

@ -3217,7 +3217,8 @@ Miscellaneous
``--display-tags=tag1,tags2,...``
Set the list of tags that should be displayed on the terminal. Tags that
are in the list, but are not present in the played file, will not be shown.
The special value ``all`` disables filtering.
If a value ends with ``*``, all tags are matched by prefix (though there
is no general globbing). Just passing ``*`` essentially filtering.
The default includes a common list of tags, call mpv with ``--list-options``
to see it.

View File

@ -15,6 +15,9 @@
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <limits.h>
#include <strings.h>
#include <libavutil/dict.h>
#include "tags.h"
#include "misc/bstr.h"
@ -76,19 +79,25 @@ struct mp_tags *mp_tags_dup(void *tparent, struct mp_tags *tags)
// Return a copy of the tags, but containing only keys in list. Also forces
// the order and casing of the keys (for cosmetic reasons).
// The special key "all" matches all keys.
// A trailing '*' matches the rest.
struct mp_tags *mp_tags_filtered(void *tparent, struct mp_tags *tags, char **list)
{
struct mp_tags *new = talloc_zero(tparent, struct mp_tags);
for (int n = 0; list && list[n]; n++) {
char *key = list[n];
if (strcasecmp(key, "all") == 0) {
talloc_free(new);
return mp_tags_dup(tparent, tags);
size_t keylen = strlen(key);
if (keylen >= INT_MAX)
continue;
bool prefix = keylen && key[keylen - 1] == '*';
int matchlen = prefix ? keylen - 1 : keylen + 1;
for (int x = 0; x < tags->num_keys; x++) {
if (strncasecmp(tags->keys[x], key, matchlen) == 0) {
char skey[320];
snprintf(skey, sizeof(skey), "%.*s%s", matchlen, key,
prefix ? tags->keys[x] + keylen - 1 : "");
mp_tags_set_str(new, skey, tags->values[x]);
}
}
char *value = mp_tags_get_str(tags, key);
if (value)
mp_tags_set_str(new, key, value);
}
return new;
}