/* ** Copyright (C) 2010-2017 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser 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. */ #include "sfconfig.h" #include #include #include #include #include "sndfile.h" #include "sfendian.h" #include "common.h" #include "id3.h" #if HAVE_MPEG #include struct id3v1_genre_handler_userdata { int number ; const char *ret ; } ; static void id3v1_genre_handler (int number, const char *description, void *userdata) { struct id3v1_genre_handler_userdata *data = (struct id3v1_genre_handler_userdata *) userdata ; if (data->number == number) data->ret = description ; } const char * id3_lookup_v1_genre (int number) { struct id3v1_genre_handler_userdata data ; data.number = number ; data.ret = NULL ; id3tag_genre_list (id3v1_genre_handler, &data) ; return data.ret ; } #else /* HAVE_MPEG */ const char * id3_lookup_v1_genre (int UNUSED (number)) { return NULL ; } #endif int id3_skip (SF_PRIVATE * psf) { unsigned char buf [10] ; int offset ; memset (buf, 0, sizeof (buf)) ; psf_binheader_readf (psf, "pb", 0, buf, 10) ; if (buf [0] == 'I' && buf [1] == 'D' && buf [2] == '3') { psf->id3_header.minor_version = buf [3] ; offset = buf [6] & 0x7f ; offset = (offset << 7) | (buf [7] & 0x7f) ; offset = (offset << 7) | (buf [8] & 0x7f) ; offset = (offset << 7) | (buf [9] & 0x7f) ; /* ** ID3 count field is how many bytes of ID3v2 header FOLLOW the ten ** bytes of header magic and offset, NOT the total ID3v2 header len. */ psf->id3_header.len = offset + 10 ; psf->id3_header.offset = psf->fileoffset ; psf_log_printf (psf, " ID3v2.%d header length : %d\n----------------------------------------\n", psf->id3_header.minor_version, psf->id3_header.len) ; /* Never want to jump backwards in a file. */ if (offset < 0) return 0 ; /* Position ourselves at the new file offset. */ if (psf->fileoffset + psf->id3_header.len < psf->filelength) { psf_binheader_readf (psf, "p!", psf->id3_header.len) ; psf->fileoffset += psf->id3_header.len ; return 1 ; } ; } ; return 0 ; } /* id3_skip */ const char * id3_process_v2_genre (const char *genre) { int num = 0 ; char c ; const char *ptr ; if (!genre) return NULL ; /* ** Genre may require more processing. ** ** It is allowed to have numeric references to the genre table from ID3v1. ** We'll just convert the simple case here, strings of the format "(nnn)". */ ptr = genre ; if (ptr [0] == '(' && (c = *++ ptr) && isdigit (c)) { num = c - '0' ; while ((c == *++ ptr) && isdigit (c)) num = num * 10 + (c - '0') ; if (c == ')' && (c = *++ ptr) == '\0' && num < 256) if ((ptr = id3_lookup_v1_genre (num))) return ptr ; } ; return genre ; } /* id3_process_v2_genre */