push
This commit is contained in:
296
comment.c
Normal file
296
comment.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright 2008-2013 Various Authors
|
||||
* Copyright 2004-2007 Timo Hirvonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "comment.h"
|
||||
#include "xmalloc.h"
|
||||
#include "utils.h"
|
||||
#include "uchar.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
static int is_various_artists(const char *a)
|
||||
{
|
||||
return strcasecmp(a, "Various Artists") == 0 ||
|
||||
strcasecmp(a, "Various") == 0 ||
|
||||
strcasecmp(a, "VA") == 0 ||
|
||||
strcasecmp(a, "V/A") == 0;
|
||||
}
|
||||
|
||||
int track_is_compilation(const struct keyval *comments)
|
||||
{
|
||||
const char *c, *a, *aa;
|
||||
|
||||
c = keyvals_get_val(comments, "compilation");
|
||||
if (c && is_freeform_true(c))
|
||||
return 1;
|
||||
|
||||
c = keyvals_get_val(comments, "partofacompilation");
|
||||
if (c && is_freeform_true(c))
|
||||
return 1;
|
||||
|
||||
aa = keyvals_get_val(comments, "albumartist");
|
||||
if (aa && is_various_artists(aa))
|
||||
return 1;
|
||||
|
||||
a = keyvals_get_val(comments, "artist");
|
||||
if (a && is_various_artists(a))
|
||||
return 1;
|
||||
|
||||
if (aa && a && !u_strcase_equal(aa, a))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int track_is_va_compilation(const struct keyval *comments)
|
||||
{
|
||||
const char *c, *a, *aa;
|
||||
|
||||
aa = keyvals_get_val(comments, "albumartist");
|
||||
if (aa)
|
||||
return is_various_artists(aa);
|
||||
|
||||
a = keyvals_get_val(comments, "artist");
|
||||
if (a && is_various_artists(a))
|
||||
return 1;
|
||||
|
||||
c = keyvals_get_val(comments, "compilation");
|
||||
if (c && is_freeform_true(c))
|
||||
return 1;
|
||||
|
||||
c = keyvals_get_val(comments, "partofacompilation");
|
||||
if (c && is_freeform_true(c))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *comments_get_albumartist(const struct keyval *comments)
|
||||
{
|
||||
const char *val = keyvals_get_val(comments, "albumartist");
|
||||
|
||||
if (!val || strcmp(val, "") == 0)
|
||||
val = keyvals_get_val(comments, "artist");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
const char *comments_get_artistsort(const struct keyval *comments)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
if (track_is_va_compilation(comments))
|
||||
return NULL;
|
||||
|
||||
val = keyvals_get_val(comments, "albumartistsort");
|
||||
if (!track_is_compilation(comments)) {
|
||||
if (!val || strcmp(val, "") == 0)
|
||||
val = keyvals_get_val(comments, "artistsort");
|
||||
}
|
||||
|
||||
if (!val || strcmp(val, "") == 0)
|
||||
return NULL;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int comments_get_int(const struct keyval *comments, const char *key)
|
||||
{
|
||||
const char *val;
|
||||
long int ival;
|
||||
|
||||
val = keyvals_get_val(comments, key);
|
||||
if (val == NULL)
|
||||
return -1;
|
||||
while (*val && !(*val >= '0' && *val <= '9'))
|
||||
val++;
|
||||
if (str_to_int(val, &ival) == -1)
|
||||
return -1;
|
||||
return ival;
|
||||
}
|
||||
|
||||
int comments_get_signed_int(const struct keyval *comments, const char *key, long int *ival)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = keyvals_get_val(comments, key);
|
||||
if (val == NULL)
|
||||
return -1;
|
||||
while (*val && !(*val == '+' || *val == '-' || (*val >= '0' && *val <= '9')))
|
||||
val++;
|
||||
return str_to_int(val, ival);
|
||||
}
|
||||
|
||||
double comments_get_double(const struct keyval *comments, const char *key)
|
||||
{
|
||||
const char *val;
|
||||
char *end;
|
||||
double d;
|
||||
|
||||
val = keyvals_get_val(comments, key);
|
||||
if (!val || strcmp(val, "") == 0)
|
||||
goto error;
|
||||
|
||||
d = strtod(val, &end);
|
||||
if (val == end)
|
||||
goto error;
|
||||
|
||||
return d;
|
||||
|
||||
error:
|
||||
return strtod("NAN", NULL);
|
||||
}
|
||||
|
||||
/* Return date as an integer in the form YYYYMMDD, for sorting purposes.
|
||||
* This function is not year 10000 compliant. */
|
||||
int comments_get_date(const struct keyval *comments, const char *key)
|
||||
{
|
||||
const char *val;
|
||||
char *endptr;
|
||||
int year, month, day;
|
||||
long int ival;
|
||||
|
||||
val = keyvals_get_val(comments, key);
|
||||
if (val == NULL)
|
||||
return -1;
|
||||
|
||||
year = strtol(val, &endptr, 10);
|
||||
/* Looking for a four-digit number */
|
||||
if (year < 1000 || year > 9999)
|
||||
return -1;
|
||||
ival = year * 10000;
|
||||
|
||||
if (*endptr == '-' || *endptr == ' ' || *endptr == '/') {
|
||||
month = strtol(endptr+1, &endptr, 10);
|
||||
if (month < 1 || month > 12)
|
||||
return ival;
|
||||
ival += month * 100;
|
||||
}
|
||||
|
||||
if (*endptr == '-' || *endptr == ' ' || *endptr == '/') {
|
||||
day = strtol(endptr+1, &endptr, 10);
|
||||
if (day < 1 || day > 31)
|
||||
return ival;
|
||||
ival += day;
|
||||
}
|
||||
|
||||
|
||||
return ival;
|
||||
}
|
||||
|
||||
static const char *interesting[] = {
|
||||
"artist", "album", "title", "tracknumber", "discnumber", "totaldiscs", "genre",
|
||||
"date", "compilation", "partofacompilation", "albumartist", "artistsort", "albumartistsort",
|
||||
"albumsort",
|
||||
"originaldate",
|
||||
"r128_track_gain",
|
||||
"r128_album_gain",
|
||||
"replaygain_track_gain",
|
||||
"replaygain_track_peak",
|
||||
"replaygain_album_gain",
|
||||
"replaygain_album_peak",
|
||||
"musicbrainz_trackid",
|
||||
"comment",
|
||||
"bpm",
|
||||
"arranger", "composer", "conductor", "lyricist", "performer",
|
||||
"remixer", "label", "publisher", "work", "opus",
|
||||
"subtitle", "media",
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct {
|
||||
const char *old;
|
||||
const char *new;
|
||||
} key_map[] = {
|
||||
{ "album_artist", "albumartist" },
|
||||
{ "album artist", "albumartist" },
|
||||
{ "disc", "discnumber" },
|
||||
{ "part", "discnumber" },
|
||||
{ "partnumber", "discnumber" },
|
||||
{ "disctotal", "totaldiscs" },
|
||||
{ "tempo", "bpm" },
|
||||
{ "track", "tracknumber" },
|
||||
{ "WM/Year", "date" },
|
||||
{ "WM/ArtistSortOrder", "artistsort" },
|
||||
{ "WM/AlbumArtistSortOrder", "albumartistsort" },
|
||||
{ "WM/AlbumSortOrder", "albumsort" },
|
||||
{ "WM/OriginalReleaseYear", "originaldate" },
|
||||
{ "WM/Media", "media" },
|
||||
{ "sourcemedia", "media" },
|
||||
{ "MusicBrainz Track Id", "musicbrainz_trackid" },
|
||||
{ "version", "subtitle" },
|
||||
/* ffmpeg id3 */
|
||||
{ "artist-sort", "artistsort" },
|
||||
{ "TSO2", "albumartistsort" },
|
||||
{ "album-sort", "albumsort" },
|
||||
/* ffmpeg mp4 */
|
||||
{ "sort_artist", "artistsort" },
|
||||
{ "sort_album_artist", "albumartistsort" },
|
||||
{ "sort_album", "albumsort" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const char *fix_key(const char *key)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; interesting[i]; i++) {
|
||||
if (!strcasecmp(key, interesting[i]))
|
||||
return interesting[i];
|
||||
}
|
||||
for (i = 0; key_map[i].old; i++) {
|
||||
if (!strcasecmp(key, key_map[i].old))
|
||||
return key_map[i].new;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int comments_add(struct growing_keyvals *c, const char *key, char *val)
|
||||
{
|
||||
if (!strcasecmp(key, "songwriter")) {
|
||||
int r = comments_add_const(c, "lyricist", val);
|
||||
return comments_add(c, "composer", val) && r;
|
||||
}
|
||||
|
||||
key = fix_key(key);
|
||||
if (!key) {
|
||||
free(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(key, "tracknumber") || !strcmp(key, "discnumber")) {
|
||||
char *slash = strchr(val, '/');
|
||||
if (slash)
|
||||
*slash = 0;
|
||||
}
|
||||
|
||||
/* don't add duplicates */
|
||||
if (keyvals_get_val_growing(c, key)) {
|
||||
free(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
keyvals_add(c, key, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int comments_add_const(struct growing_keyvals *c, const char *key, const char *val)
|
||||
{
|
||||
return comments_add(c, key, xstrdup(val));
|
||||
}
|
||||
Reference in New Issue
Block a user