1/* 2** Copyright (C) 2010-2017 Erik de Castro Lopo <erikd@mega-nerd.com> 3** 4** This program is free software; you can redistribute it and/or modify 5** it under the terms of the GNU Lesser General Public License as published by 6** the Free Software Foundation; either version 2.1 of the License, or 7** (at your option) any later version. 8** 9** This program is distributed in the hope that it will be useful, 10** but WITHOUT ANY WARRANTY; without even the implied warranty of 11** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12** GNU Lesser General Public License for more details. 13** 14** You should have received a copy of the GNU Lesser General Public License 15** along with this program; if not, write to the Free Software 16** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17*/ 18 19#include "sfconfig.h" 20 21#include <stdio.h> 22#include <fcntl.h> 23#include <string.h> 24#include <ctype.h> 25 26#include "sndfile.h" 27#include "sfendian.h" 28#include "common.h" 29#include "id3.h" 30 31#if HAVE_MPEG 32#include <lame/lame.h> 33 34struct id3v1_genre_handler_userdata 35{ int number ; 36 const char *ret ; 37} ; 38 39static void 40id3v1_genre_handler (int number, const char *description, void *userdata) 41{ struct id3v1_genre_handler_userdata *data = (struct id3v1_genre_handler_userdata *) userdata ; 42 if (data->number == number) 43 data->ret = description ; 44} 45 46const char * 47id3_lookup_v1_genre (int number) 48{ struct id3v1_genre_handler_userdata data ; 49 50 data.number = number ; 51 data.ret = NULL ; 52 id3tag_genre_list (id3v1_genre_handler, &data) ; 53 54 return data.ret ; 55} 56 57#else /* HAVE_MPEG */ 58 59const char * 60id3_lookup_v1_genre (int UNUSED (number)) 61{ return NULL ; 62 } 63 64#endif 65 66int 67id3_skip (SF_PRIVATE * psf) 68{ unsigned char buf [10] ; 69 int offset ; 70 71 memset (buf, 0, sizeof (buf)) ; 72 psf_binheader_readf (psf, "pb", 0, buf, 10) ; 73 74 if (buf [0] == 'I' && buf [1] == 'D' && buf [2] == '3') 75 { psf->id3_header.minor_version = buf [3] ; 76 offset = buf [6] & 0x7f ; 77 offset = (offset << 7) | (buf [7] & 0x7f) ; 78 offset = (offset << 7) | (buf [8] & 0x7f) ; 79 offset = (offset << 7) | (buf [9] & 0x7f) ; 80 81 /* 82 ** ID3 count field is how many bytes of ID3v2 header FOLLOW the ten 83 ** bytes of header magic and offset, NOT the total ID3v2 header len. 84 */ 85 psf->id3_header.len = offset + 10 ; 86 psf->id3_header.offset = psf->fileoffset ; 87 88 psf_log_printf (psf, " ID3v2.%d header length : %d\n----------------------------------------\n", 89 psf->id3_header.minor_version, psf->id3_header.len) ; 90 91 /* Never want to jump backwards in a file. */ 92 if (offset < 0) 93 return 0 ; 94 95 /* Position ourselves at the new file offset. */ 96 if (psf->fileoffset + psf->id3_header.len < psf->filelength) 97 { psf_binheader_readf (psf, "p!", psf->id3_header.len) ; 98 psf->fileoffset += psf->id3_header.len ; 99 return 1 ; 100 } ; 101 } ; 102 103 return 0 ; 104} /* id3_skip */ 105 106const char * 107id3_process_v2_genre (const char *genre) 108{ int num = 0 ; 109 char c ; 110 const char *ptr ; 111 112 if (!genre) 113 return NULL ; 114 115 /* 116 ** Genre may require more processing. 117 ** 118 ** It is allowed to have numeric references to the genre table from ID3v1. 119 ** We'll just convert the simple case here, strings of the format "(nnn)". 120 */ 121 ptr = genre ; 122 if (ptr [0] == '(' && (c = *++ ptr) && isdigit (c)) 123 { num = c - '0' ; 124 while ((c == *++ ptr) && isdigit (c)) 125 num = num * 10 + (c - '0') ; 126 if (c == ')' && (c = *++ ptr) == '\0' && num < 256) 127 if ((ptr = id3_lookup_v1_genre (num))) 128 return ptr ; 129 } ; 130 131 return genre ; 132} /* id3_process_v2_genre */ 133