📄 id3tag.c
字号:
/* * id3tag.c -- Write ID3 version 1 and 2 tags. * * Copyright (C) 2000 Don Melton. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. *//* * HISTORY: This source file is part of LAME (see http://www.mp3dev.org/mp3/) * and was originally adapted by Conrad Sanderson <c.sanderson@me.gu.edu.au> * from mp3info by Ricardo Cerqueira <rmc@rccn.net> to write only ID3 version 1 * tags. Don Melton <don@blivet.com> COMPLETELY rewrote it to support version * 2 tags and be more conformant to other standards while remaining flexible. * * NOTE: See http://id3.org/ for more information about ID3 tag formats. *//* $Id: id3tag.c,v 1.23 2004/02/02 12:38:30 aleidinger Exp $ */#ifdef HAVE_CONFIG_H#include <config.h>#endif#ifdef STDC_HEADERS# include <stddef.h># include <stdlib.h># include <string.h>#else# ifndef HAVE_STRCHR# define strchr index# define strrchr rindex# endifchar *strchr (), *strrchr ();# ifndef HAVE_MEMCPY# define memcpy(d, s, n) bcopy ((s), (d), (n))# define memmove(d, s, n) bcopy ((s), (d), (n))# endif#endif#ifdef _MSC_VER#define snprintf _snprintf#endif#include "lame.h"#include "id3tag.h"#include "util.h"#include "bitstream.h"#ifdef WITH_DMALLOC#include <dmalloc.h>#endifstatic const char *const genre_names[] ={ /* * NOTE: The spelling of these genre names is identical to those found in * Winamp and mp3info. */ "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alt. Rock", "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta Rap", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave", "Psychedelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie", "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", "Synthpop"};#define GENRE_NAME_COUNT \ ((int)(sizeof genre_names / sizeof (const char *const)))static const int genre_alpha_map [] = { 123, 34, 74, 73, 99, 20, 40, 26, 145, 90, 116, 41, 135, 85, 96, 138, 89, 0, 107, 132, 65, 88, 104, 102, 97, 136, 61, 141, 32, 1, 112, 128, 57, 140, 2, 139, 58, 3, 125, 50, 22, 4, 55, 127, 122, 120, 98, 52, 48, 54, 124, 25, 84, 80, 115, 81, 119, 5, 30, 36, 59, 126, 38, 49, 91, 6, 129, 79, 137, 7, 35, 100, 131, 19, 33, 46, 47, 8, 29, 146, 63, 86, 71, 45, 142, 9, 77, 82, 64, 133, 10, 66, 39, 11, 103, 12, 75, 134, 13, 53, 62, 109, 117, 23, 108, 92, 67, 93, 43, 121, 15, 68, 14, 16, 76, 87, 118, 17, 78, 143, 114, 110, 69, 21, 111, 95, 105, 42, 37, 24, 56, 44, 101, 83, 94, 106, 147, 113, 18, 51, 130, 144, 60, 70, 31, 72, 27, 28};#define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int)))voidid3tag_genre_list(void (*handler)(int, const char *, void *), void *cookie){ if (handler) { int i; for (i = 0; i < GENRE_NAME_COUNT; ++i) { if (i < GENRE_ALPHA_COUNT) { int j = genre_alpha_map[i]; handler(j, genre_names[j], cookie); } } }}#define GENRE_NUM_UNKNOWN 255voidid3tag_init(lame_global_flags *gfp){ lame_internal_flags *gfc = gfp->internal_flags; memset(&gfc->tag_spec, 0, sizeof gfc->tag_spec); gfc->tag_spec.genre = GENRE_NUM_UNKNOWN;}voidid3tag_add_v2(lame_global_flags *gfp){ lame_internal_flags *gfc = gfp->internal_flags; gfc->tag_spec.flags &= ~V1_ONLY_FLAG; gfc->tag_spec.flags |= ADD_V2_FLAG;}voidid3tag_v1_only(lame_global_flags *gfp){ lame_internal_flags *gfc = gfp->internal_flags; gfc->tag_spec.flags &= ~(ADD_V2_FLAG | V2_ONLY_FLAG); gfc->tag_spec.flags |= V1_ONLY_FLAG;}voidid3tag_v2_only(lame_global_flags *gfp){ lame_internal_flags *gfc = gfp->internal_flags; gfc->tag_spec.flags &= ~V1_ONLY_FLAG; gfc->tag_spec.flags |= V2_ONLY_FLAG;}voidid3tag_space_v1(lame_global_flags *gfp){ lame_internal_flags *gfc = gfp->internal_flags; gfc->tag_spec.flags &= ~V2_ONLY_FLAG; gfc->tag_spec.flags |= SPACE_V1_FLAG;}voidid3tag_pad_v2(lame_global_flags *gfp){ lame_internal_flags *gfc = gfp->internal_flags; gfc->tag_spec.flags &= ~V1_ONLY_FLAG; gfc->tag_spec.flags |= PAD_V2_FLAG;}voidid3tag_set_title(lame_global_flags *gfp, const char *title){ lame_internal_flags *gfc = gfp->internal_flags; if (title && *title) { gfc->tag_spec.title = title; gfc->tag_spec.flags |= CHANGED_FLAG; }}voidid3tag_set_artist(lame_global_flags *gfp, const char *artist){ lame_internal_flags *gfc = gfp->internal_flags; if (artist && *artist) { gfc->tag_spec.artist = artist; gfc->tag_spec.flags |= CHANGED_FLAG; }}voidid3tag_set_album(lame_global_flags *gfp, const char *album){ lame_internal_flags *gfc = gfp->internal_flags; if (album && *album) { gfc->tag_spec.album = album; gfc->tag_spec.flags |= CHANGED_FLAG; }}voidid3tag_set_year(lame_global_flags *gfp, const char *year){ lame_internal_flags *gfc = gfp->internal_flags; if (year && *year) { int num = atoi(year); if (num < 0) { num = 0; } /* limit a year to 4 digits so it fits in a version 1 tag */ if (num > 9999) { num = 9999; } if (num) { gfc->tag_spec.year = num; gfc->tag_spec.flags |= CHANGED_FLAG; } }}voidid3tag_set_comment(lame_global_flags *gfp, const char *comment){ lame_internal_flags *gfc = gfp->internal_flags; if (comment && *comment) { gfc->tag_spec.comment = comment; gfc->tag_spec.flags |= CHANGED_FLAG; }}voidid3tag_set_track(lame_global_flags *gfp, const char *track){ lame_internal_flags *gfc = gfp->internal_flags; if (track && *track) { int num = atoi(track); if (num < 0) { num = 0; } /* limit a track to 255 so it fits in a version 1 tag even though CD * audio doesn't allow more than 99 tracks */ if (num > 255) { num = 255; } if (num) { gfc->tag_spec.track = num; gfc->tag_spec.flags |= CHANGED_FLAG; } }}/* would use real "strcasecmp" but it isn't portable */static intlocal_strcasecmp(const char *s1, const char *s2){ unsigned char c1; unsigned char c2; do { c1 = tolower(*s1); c2 = tolower(*s2); if (!c1) { break; } ++s1; ++s2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -