mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-30 15:49:41 +02:00
891 lines
18 KiB
C
891 lines
18 KiB
C
/*
|
|
* libid3tag - ID3 tag manipulation library
|
|
* Copyright (C) 2000-2004 Underbit Technologies, Inc.
|
|
*
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* $Id: field.c,v 1.3 2004-06-08 06:38:15 dmazzoni Exp $
|
|
*/
|
|
|
|
# ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
# endif
|
|
|
|
# include "global.h"
|
|
|
|
# include <stdlib.h>
|
|
# include <string.h>
|
|
|
|
# ifdef HAVE_ASSERT_H
|
|
# include <assert.h>
|
|
# endif
|
|
|
|
# include "id3tag.h"
|
|
# include "field.h"
|
|
# include "frame.h"
|
|
# include "render.h"
|
|
# include "ucs4.h"
|
|
# include "latin1.h"
|
|
# include "parse.h"
|
|
|
|
/*
|
|
* NAME: field->init()
|
|
* DESCRIPTION: initialize a field to a default value for the given type
|
|
*/
|
|
void id3_field_init(union id3_field *field, enum id3_field_type type)
|
|
{
|
|
assert(field);
|
|
|
|
switch (field->type = type) {
|
|
case ID3_FIELD_TYPE_TEXTENCODING:
|
|
case ID3_FIELD_TYPE_INT8:
|
|
case ID3_FIELD_TYPE_INT16:
|
|
case ID3_FIELD_TYPE_INT24:
|
|
case ID3_FIELD_TYPE_INT32:
|
|
field->number.value = 0;
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_LATIN1:
|
|
case ID3_FIELD_TYPE_LATIN1FULL:
|
|
field->latin1.ptr = 0;
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_LATIN1LIST:
|
|
field->latin1list.nstrings = 0;
|
|
field->latin1list.strings = 0;
|
|
|
|
case ID3_FIELD_TYPE_STRING:
|
|
case ID3_FIELD_TYPE_STRINGFULL:
|
|
field->string.ptr = 0;
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_STRINGLIST:
|
|
field->stringlist.nstrings = 0;
|
|
field->stringlist.strings = 0;
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_LANGUAGE:
|
|
strcpy(field->immediate.value, "XXX");
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_FRAMEID:
|
|
strcpy(field->immediate.value, "XXXX");
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_DATE:
|
|
memset(field->immediate.value, 0, sizeof(field->immediate.value));
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_INT32PLUS:
|
|
case ID3_FIELD_TYPE_BINARYDATA:
|
|
field->binary.data = 0;
|
|
field->binary.length = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* NAME: field->finish()
|
|
* DESCRIPTION: reset a field, deallocating memory if necessary
|
|
*/
|
|
void id3_field_finish(union id3_field *field)
|
|
{
|
|
unsigned int i;
|
|
|
|
assert(field);
|
|
|
|
switch (field->type) {
|
|
case ID3_FIELD_TYPE_TEXTENCODING:
|
|
case ID3_FIELD_TYPE_INT8:
|
|
case ID3_FIELD_TYPE_INT16:
|
|
case ID3_FIELD_TYPE_INT24:
|
|
case ID3_FIELD_TYPE_INT32:
|
|
case ID3_FIELD_TYPE_LANGUAGE:
|
|
case ID3_FIELD_TYPE_FRAMEID:
|
|
case ID3_FIELD_TYPE_DATE:
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_LATIN1:
|
|
case ID3_FIELD_TYPE_LATIN1FULL:
|
|
if (field->latin1.ptr)
|
|
free(field->latin1.ptr);
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_LATIN1LIST:
|
|
for (i = 0; i < field->latin1list.nstrings; ++i)
|
|
free(field->latin1list.strings[i]);
|
|
|
|
if (field->latin1list.strings)
|
|
free(field->latin1list.strings);
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_STRING:
|
|
case ID3_FIELD_TYPE_STRINGFULL:
|
|
if (field->string.ptr)
|
|
free(field->string.ptr);
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_STRINGLIST:
|
|
for (i = 0; i < field->stringlist.nstrings; ++i)
|
|
free(field->stringlist.strings[i]);
|
|
|
|
if (field->stringlist.strings)
|
|
free(field->stringlist.strings);
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_INT32PLUS:
|
|
case ID3_FIELD_TYPE_BINARYDATA:
|
|
if (field->binary.data)
|
|
free(field->binary.data);
|
|
break;
|
|
}
|
|
|
|
id3_field_init(field, field->type);
|
|
}
|
|
|
|
/*
|
|
* NAME: field->type()
|
|
* DESCRIPTION: return the value type of a field
|
|
*/
|
|
enum id3_field_type id3_field_type(union id3_field const *field)
|
|
{
|
|
assert(field);
|
|
|
|
return field->type;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->parse()
|
|
* DESCRIPTION: parse a field value
|
|
*/
|
|
int id3_field_parse(union id3_field *field, id3_byte_t const **ptr,
|
|
id3_length_t length, enum id3_field_textencoding *encoding)
|
|
{
|
|
assert(field);
|
|
|
|
id3_field_finish(field);
|
|
|
|
switch (field->type) {
|
|
case ID3_FIELD_TYPE_INT32:
|
|
if (length < 4)
|
|
goto fail;
|
|
|
|
field->number.value = id3_parse_uint(ptr, 4);
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_INT24:
|
|
if (length < 3)
|
|
goto fail;
|
|
|
|
field->number.value = id3_parse_uint(ptr, 3);
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_INT16:
|
|
if (length < 2)
|
|
goto fail;
|
|
|
|
field->number.value = id3_parse_uint(ptr, 2);
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_INT8:
|
|
case ID3_FIELD_TYPE_TEXTENCODING:
|
|
if (length < 1)
|
|
goto fail;
|
|
|
|
field->number.value = id3_parse_uint(ptr, 1);
|
|
|
|
if (field->type == ID3_FIELD_TYPE_TEXTENCODING)
|
|
*encoding = field->number.value;
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_LANGUAGE:
|
|
if (length < 3)
|
|
goto fail;
|
|
|
|
id3_parse_immediate(ptr, 3, field->immediate.value);
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_FRAMEID:
|
|
if (length < 4)
|
|
goto fail;
|
|
|
|
id3_parse_immediate(ptr, 4, field->immediate.value);
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_DATE:
|
|
if (length < 8)
|
|
goto fail;
|
|
|
|
id3_parse_immediate(ptr, 8, field->immediate.value);
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_LATIN1:
|
|
case ID3_FIELD_TYPE_LATIN1FULL:
|
|
{
|
|
id3_latin1_t *latin1;
|
|
|
|
latin1 = id3_parse_latin1(ptr, length,
|
|
field->type == ID3_FIELD_TYPE_LATIN1FULL);
|
|
if (latin1 == 0)
|
|
goto fail;
|
|
|
|
field->latin1.ptr = latin1;
|
|
}
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_LATIN1LIST:
|
|
{
|
|
id3_byte_t const *end;
|
|
id3_latin1_t *latin1, **strings;
|
|
|
|
end = *ptr + length;
|
|
|
|
while (end - *ptr > 0) {
|
|
latin1 = id3_parse_latin1(ptr, end - *ptr, 0);
|
|
if (latin1 == 0)
|
|
goto fail;
|
|
|
|
strings = realloc(field->latin1list.strings,
|
|
(field->latin1list.nstrings + 1) * sizeof(*strings));
|
|
if (strings == 0) {
|
|
free(latin1);
|
|
goto fail;
|
|
}
|
|
|
|
field->latin1list.strings = strings;
|
|
field->latin1list.strings[field->latin1list.nstrings++] = latin1;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_STRING:
|
|
case ID3_FIELD_TYPE_STRINGFULL:
|
|
{
|
|
id3_ucs4_t *ucs4;
|
|
|
|
ucs4 = id3_parse_string(ptr, length, *encoding,
|
|
field->type == ID3_FIELD_TYPE_STRINGFULL);
|
|
if (ucs4 == 0)
|
|
goto fail;
|
|
|
|
field->string.ptr = ucs4;
|
|
}
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_STRINGLIST:
|
|
{
|
|
id3_byte_t const *end;
|
|
id3_ucs4_t *ucs4, **strings;
|
|
|
|
end = *ptr + length;
|
|
|
|
while (end - *ptr > 0) {
|
|
ucs4 = id3_parse_string(ptr, end - *ptr, *encoding, 0);
|
|
if (ucs4 == 0)
|
|
goto fail;
|
|
|
|
strings = realloc(field->stringlist.strings,
|
|
(field->stringlist.nstrings + 1) * sizeof(*strings));
|
|
if (strings == 0) {
|
|
free(ucs4);
|
|
goto fail;
|
|
}
|
|
|
|
field->stringlist.strings = strings;
|
|
field->stringlist.strings[field->stringlist.nstrings++] = ucs4;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_INT32PLUS:
|
|
case ID3_FIELD_TYPE_BINARYDATA:
|
|
{
|
|
id3_byte_t *data;
|
|
|
|
data = id3_parse_binary(ptr, length);
|
|
if (data == 0)
|
|
goto fail;
|
|
|
|
field->binary.data = data;
|
|
field->binary.length = length;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
fail:
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->render()
|
|
* DESCRIPTION: render a field value
|
|
*/
|
|
id3_length_t id3_field_render(union id3_field const *field, id3_byte_t **ptr,
|
|
enum id3_field_textencoding *encoding,
|
|
int terminate)
|
|
{
|
|
id3_length_t size;
|
|
unsigned int i;
|
|
|
|
assert(field && encoding);
|
|
|
|
switch (field->type) {
|
|
case ID3_FIELD_TYPE_INT32:
|
|
return id3_render_int(ptr, field->number.value, 4);
|
|
|
|
case ID3_FIELD_TYPE_INT24:
|
|
return id3_render_int(ptr, field->number.value, 3);
|
|
|
|
case ID3_FIELD_TYPE_INT16:
|
|
return id3_render_int(ptr, field->number.value, 2);
|
|
|
|
case ID3_FIELD_TYPE_TEXTENCODING:
|
|
*encoding = field->number.value;
|
|
case ID3_FIELD_TYPE_INT8:
|
|
return id3_render_int(ptr, field->number.value, 1);
|
|
|
|
case ID3_FIELD_TYPE_LATIN1:
|
|
case ID3_FIELD_TYPE_LATIN1FULL:
|
|
return id3_render_latin1(ptr, field->latin1.ptr, terminate);
|
|
|
|
case ID3_FIELD_TYPE_LATIN1LIST:
|
|
size = 0;
|
|
for (i = 0; i < field->latin1list.nstrings; ++i) {
|
|
size += id3_render_latin1(ptr, field->latin1list.strings[i],
|
|
(i < field->latin1list.nstrings - 1) ||
|
|
terminate);
|
|
}
|
|
return size;
|
|
|
|
case ID3_FIELD_TYPE_STRING:
|
|
case ID3_FIELD_TYPE_STRINGFULL:
|
|
return id3_render_string(ptr, field->string.ptr, *encoding, terminate);
|
|
|
|
case ID3_FIELD_TYPE_STRINGLIST:
|
|
size = 0;
|
|
for (i = 0; i < field->stringlist.nstrings; ++i) {
|
|
size += id3_render_string(ptr, field->stringlist.strings[i], *encoding,
|
|
(i < field->stringlist.nstrings - 1) ||
|
|
terminate);
|
|
}
|
|
return size;
|
|
|
|
case ID3_FIELD_TYPE_LANGUAGE:
|
|
return id3_render_immediate(ptr, field->immediate.value, 3);
|
|
|
|
case ID3_FIELD_TYPE_FRAMEID:
|
|
return id3_render_immediate(ptr, field->immediate.value, 4);
|
|
|
|
case ID3_FIELD_TYPE_DATE:
|
|
return id3_render_immediate(ptr, field->immediate.value, 8);
|
|
|
|
case ID3_FIELD_TYPE_INT32PLUS:
|
|
case ID3_FIELD_TYPE_BINARYDATA:
|
|
return id3_render_binary(ptr, field->binary.data, field->binary.length);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->setint()
|
|
* DESCRIPTION: set the value of an int field
|
|
*/
|
|
int id3_field_setint(union id3_field *field, signed long number)
|
|
{
|
|
assert(field);
|
|
|
|
switch (field->type) {
|
|
case ID3_FIELD_TYPE_INT8:
|
|
if (number > 0x7f || number < -0x80)
|
|
return -1;
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_INT16:
|
|
if (number > 0x7fff || number < -0x8000)
|
|
return -1;
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_INT24:
|
|
if (number > 0x7fffffL || number < -0x800000L)
|
|
return -1;
|
|
break;
|
|
|
|
case ID3_FIELD_TYPE_INT32:
|
|
if (number > 0x7fffffffL || number < -0x80000000L)
|
|
return -1;
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
id3_field_finish(field);
|
|
|
|
field->number.value = number;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->settextencoding()
|
|
* DESCRIPTION: set the value of a textencoding field
|
|
*/
|
|
int id3_field_settextencoding(union id3_field *field,
|
|
enum id3_field_textencoding encoding)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_TEXTENCODING)
|
|
return -1;
|
|
|
|
id3_field_finish(field);
|
|
|
|
field->number.value = encoding;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
int set_latin1(union id3_field *field, id3_latin1_t const *latin1)
|
|
{
|
|
id3_latin1_t *data;
|
|
|
|
if (latin1 == 0 || *latin1 == 0)
|
|
data = 0;
|
|
else {
|
|
data = id3_latin1_duplicate(latin1);
|
|
if (data == 0)
|
|
return -1;
|
|
}
|
|
|
|
field->latin1.ptr = data;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->setlatin1()
|
|
* DESCRIPTION: set the value of a latin1 field
|
|
*/
|
|
int id3_field_setlatin1(union id3_field *field, id3_latin1_t const *latin1)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_LATIN1)
|
|
return -1;
|
|
|
|
id3_field_finish(field);
|
|
|
|
if (latin1) {
|
|
id3_latin1_t const *ptr;
|
|
|
|
for (ptr = latin1; *ptr; ++ptr) {
|
|
if (*ptr == '\n')
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return set_latin1(field, latin1);
|
|
}
|
|
|
|
/*
|
|
* NAME: field->setfulllatin1()
|
|
* DESCRIPTION: set the value of a full latin1 field
|
|
*/
|
|
int id3_field_setfulllatin1(union id3_field *field, id3_latin1_t const *latin1)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_LATIN1FULL)
|
|
return -1;
|
|
|
|
id3_field_finish(field);
|
|
|
|
return set_latin1(field, latin1);
|
|
}
|
|
|
|
static
|
|
int set_string(union id3_field *field, id3_ucs4_t const *string)
|
|
{
|
|
id3_ucs4_t *data;
|
|
|
|
if (string == 0 || *string == 0)
|
|
data = 0;
|
|
else {
|
|
data = id3_ucs4_duplicate(string);
|
|
if (data == 0)
|
|
return -1;
|
|
}
|
|
|
|
field->string.ptr = data;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->setstring()
|
|
* DESCRIPTION: set the value of a string field
|
|
*/
|
|
int id3_field_setstring(union id3_field *field, id3_ucs4_t const *string)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_STRING)
|
|
return -1;
|
|
|
|
id3_field_finish(field);
|
|
|
|
if (string) {
|
|
id3_ucs4_t const *ptr;
|
|
|
|
for (ptr = string; *ptr; ++ptr) {
|
|
if (*ptr == '\n')
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return set_string(field, string);
|
|
}
|
|
|
|
/*
|
|
* NAME: field->setfullstring()
|
|
* DESCRIPTION: set the value of a full string field
|
|
*/
|
|
int id3_field_setfullstring(union id3_field *field, id3_ucs4_t const *string)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_STRINGFULL)
|
|
return -1;
|
|
|
|
id3_field_finish(field);
|
|
|
|
return set_string(field, string);
|
|
}
|
|
|
|
/*
|
|
* NAME: field->setstrings()
|
|
* DESCRIPTION: set the value of a stringlist field
|
|
*/
|
|
int id3_field_setstrings(union id3_field *field,
|
|
unsigned int length, id3_ucs4_t **ptrs)
|
|
{
|
|
id3_ucs4_t **strings;
|
|
unsigned int i;
|
|
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_STRINGLIST)
|
|
return -1;
|
|
|
|
id3_field_finish(field);
|
|
|
|
if (length == 0)
|
|
return 0;
|
|
|
|
strings = malloc(length * sizeof(*strings));
|
|
if (strings == 0)
|
|
return -1;
|
|
|
|
for (i = 0; i < length; ++i) {
|
|
strings[i] = id3_ucs4_duplicate(ptrs[i]);
|
|
if (strings[i] == 0) {
|
|
while (i--)
|
|
free(strings[i]);
|
|
|
|
free(strings);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
field->stringlist.strings = strings;
|
|
field->stringlist.nstrings = length;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->addstring()
|
|
* DESCRIPTION: add a string to a stringlist field
|
|
*/
|
|
int id3_field_addstring(union id3_field *field, id3_ucs4_t const *string)
|
|
{
|
|
id3_ucs4_t *new, **strings;
|
|
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_STRINGLIST)
|
|
return -1;
|
|
|
|
if (string == 0)
|
|
string = id3_ucs4_empty;
|
|
|
|
new = id3_ucs4_duplicate(string);
|
|
if (new == 0)
|
|
return -1;
|
|
|
|
strings = realloc(field->stringlist.strings,
|
|
(field->stringlist.nstrings + 1) * sizeof(*strings));
|
|
if (strings == 0) {
|
|
free(new);
|
|
return -1;
|
|
}
|
|
|
|
field->stringlist.strings = strings;
|
|
field->stringlist.strings[field->stringlist.nstrings++] = new;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->setlanguage()
|
|
* DESCRIPTION: set the value of a language field
|
|
*/
|
|
int id3_field_setlanguage(union id3_field *field, char const *language)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_LANGUAGE)
|
|
return -1;
|
|
|
|
id3_field_finish(field);
|
|
|
|
if (language) {
|
|
if (strlen(language) != 3)
|
|
return -1;
|
|
|
|
strcpy(field->immediate.value, language);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->setframeid()
|
|
* DESCRIPTION: set the value of a frameid field
|
|
*/
|
|
int id3_field_setframeid(union id3_field *field, char const *id)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_FRAMEID ||
|
|
!id3_frame_validid(id))
|
|
return -1;
|
|
|
|
id3_field_finish(field);
|
|
|
|
field->immediate.value[0] = id[0];
|
|
field->immediate.value[1] = id[1];
|
|
field->immediate.value[2] = id[2];
|
|
field->immediate.value[3] = id[3];
|
|
field->immediate.value[4] = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->setbinarydata()
|
|
* DESCRIPTION: set the value of a binarydata field
|
|
*/
|
|
int id3_field_setbinarydata(union id3_field *field,
|
|
id3_byte_t const *data, id3_length_t length)
|
|
{
|
|
id3_byte_t *mem;
|
|
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_BINARYDATA)
|
|
return -1;
|
|
|
|
id3_field_finish(field);
|
|
|
|
if (length == 0)
|
|
mem = 0;
|
|
else {
|
|
mem = malloc(length);
|
|
if (mem == 0)
|
|
return -1;
|
|
|
|
assert(data);
|
|
|
|
memcpy(mem, data, length);
|
|
}
|
|
|
|
field->binary.data = mem;
|
|
field->binary.length = length;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->getint()
|
|
* DESCRIPTION: return the value of an integer field
|
|
*/
|
|
signed long id3_field_getint(union id3_field const *field)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_INT8 &&
|
|
field->type != ID3_FIELD_TYPE_INT16 &&
|
|
field->type != ID3_FIELD_TYPE_INT24 &&
|
|
field->type != ID3_FIELD_TYPE_INT32)
|
|
return -1;
|
|
|
|
return field->number.value;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->gettextencoding()
|
|
* DESCRIPTION: return the value of a text encoding field
|
|
*/
|
|
enum id3_field_textencoding
|
|
id3_field_gettextencoding(union id3_field const *field)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_TEXTENCODING)
|
|
return -1;
|
|
|
|
return field->number.value;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->getlatin1()
|
|
* DESCRIPTION: return the value of a latin1 field
|
|
*/
|
|
id3_latin1_t const *id3_field_getlatin1(union id3_field const *field)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_LATIN1)
|
|
return 0;
|
|
|
|
return field->latin1.ptr ? field->latin1.ptr : (id3_latin1_t const *) "";
|
|
}
|
|
|
|
/*
|
|
* NAME: field->getfulllatin1()
|
|
* DESCRIPTION: return the value of a full latin1 field
|
|
*/
|
|
id3_latin1_t const *id3_field_getfulllatin1(union id3_field const *field)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_LATIN1FULL)
|
|
return 0;
|
|
|
|
return field->latin1.ptr ? field->latin1.ptr : (id3_latin1_t const *) "";
|
|
}
|
|
|
|
/*
|
|
* NAME: field->getstring()
|
|
* DESCRIPTION: return the value of a string field
|
|
*/
|
|
id3_ucs4_t const *id3_field_getstring(union id3_field const *field)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_STRING)
|
|
return 0;
|
|
|
|
return field->string.ptr ? field->string.ptr : id3_ucs4_empty;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->getfullstring()
|
|
* DESCRIPTION: return the value of a fullstring field
|
|
*/
|
|
id3_ucs4_t const *id3_field_getfullstring(union id3_field const *field)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_STRINGFULL)
|
|
return 0;
|
|
|
|
return field->string.ptr ? field->string.ptr : id3_ucs4_empty;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->getnstrings()
|
|
* DESCRIPTION: return the number of strings in a stringlist field
|
|
*/
|
|
unsigned int id3_field_getnstrings(union id3_field const *field)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_STRINGLIST)
|
|
return 0;
|
|
|
|
return field->stringlist.nstrings;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->getstrings()
|
|
* DESCRIPTION: return one value of a stringlist field
|
|
*/
|
|
id3_ucs4_t const *id3_field_getstrings(union id3_field const *field,
|
|
unsigned int index)
|
|
{
|
|
id3_ucs4_t const *string;
|
|
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_STRINGLIST ||
|
|
index >= field->stringlist.nstrings)
|
|
return 0;
|
|
|
|
string = field->stringlist.strings[index];
|
|
|
|
return string ? string : id3_ucs4_empty;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->getframeid()
|
|
* DESCRIPTION: return the value of a frameid field
|
|
*/
|
|
char const *id3_field_getframeid(union id3_field const *field)
|
|
{
|
|
assert(field);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_FRAMEID)
|
|
return 0;
|
|
|
|
return field->immediate.value;
|
|
}
|
|
|
|
/*
|
|
* NAME: field->getbinarydata()
|
|
* DESCRIPTION: return the value of a binarydata field
|
|
*/
|
|
id3_byte_t const *id3_field_getbinarydata(union id3_field const *field,
|
|
id3_length_t *length)
|
|
{
|
|
static id3_byte_t const empty;
|
|
|
|
assert(field && length);
|
|
|
|
if (field->type != ID3_FIELD_TYPE_BINARYDATA)
|
|
return 0;
|
|
|
|
assert(field->binary.length == 0 || field->binary.data);
|
|
|
|
*length = field->binary.length;
|
|
|
|
return field->binary.data ? field->binary.data : ∅
|
|
}
|