- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <inttypes.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <math.h>
- #include <iconv.h>
- #define MAX_ID3_KEYS 16
- struct id3_v2_header
- {
- char id3[4];
- char ver_major;
- char ver_minor;
- char flags;
- uint32_t size;
- };
- struct id3_v2_frame_header
- {
- char id[4];
- uint32_t size;
- uint16_t flags;
- };
- struct id3_v2_frame_contents
- {
- unsigned char id[4];
- unsigned int size;
- unsigned char *contents;
- };
- struct id3tag
- {
- int num;
- struct id3_v2_frame_contents v2[MAX_ID3_KEYS];
- };
- char *utf16_to_utf8(const char *from, const char *to, char *src_str, int count)
- {
- iconv_t cv;
- size_t len, utf8len;
- char *pin, *pout, *utf8p;
- cv = iconv_open(to, from);
- if (cv < 0)
- {
- printf("iconv_open error\\n");
- return NULL;
- }
- len = count;
- pin = src_str;
- utf8len = 4 * len;
- pout = (char *)calloc(1, utf8len);
- utf8p = pout;
- if (iconv(cv, &pin, &len, &pout, &utf8len) < 0)
- {
- printf("iconv error\\n");
- return NULL;
- }
- iconv_close(cv);
- return utf8p;
- }
- static int output_id3tag(struct id3tag *id3)
- {
- int fd;
- int i;
- char *out_string;
- char *tmp;
- fd = open("id3.txt", O_CREAT | O_RDWR, S_IRWXU);
- for (i = 0; i < MAX_ID3_KEYS; i++)
- {
- if (id3->v2[i].size != 0)
- {
- if (strncmp(id3->v2[i].id, "APIC", 4) != 0 && strncmp(id3->v2[i].id, "TXXX", 4) != 0)
- {
- write(fd, id3->v2[i].contents, id3->v2[i].size);
- out_string = utf16_to_utf8("UTF-16LE", "UTF-8", id3->v2[i].contents, id3->v2[i].size);
- if (out_string) {
- printf ("--- %s---\\n", out_string);
- tmp = id3->v2[i].contents;
- id3->v2[i].contents = out_string;
- free(tmp);
- }
- }
- }
- }
- close(fd);
- }
- void id3tag_init(struct id3tag *id3)
- {
- memset(id3, 0, sizeof(*id3));
- }
- void id3tag_free(struct id3tag *id3)
- {
- int i;
- for (i = 0; i < MAX_ID3_KEYS; i++)
- if (id3->v2[i].contents != NULL)
- free(id3->v2[i].contents);
- }
- static int add_id3tag(struct id3tag *id3, struct id3_v2_frame_header *fh, unsigned char *buf)
- {
- char *tmp, *out_string;
- int i;
- if (id3->num < MAX_ID3_KEYS)
- {
- strncpy( id3->v2[id3->num].id, fh->id, 4);
- id3->v2[id3->num].contents = (unsigned char *)calloc(1, fh->size);
- memcpy(id3->v2[id3->num].contents, buf+11, fh->size-1);
- id3->v2[id3->num].size = fh->size - 1;
- if (id3->v2[i].size != 0)
- {
- if (strncmp(id3->v2[id3->num].id, "APIC", 4) != 0 && strncmp(id3->v2[id3->num].id, "TXXX", 4) != 0)
- {
- out_string = utf16_to_utf8("UTF-16", "UTF-8", id3->v2[id3->num].contents, id3->v2[id3->num].size);
- if (out_string) {
- // printf ("--- %s---\\n", out_string);
- tmp = id3->v2[id3->num].contents;
- id3->v2[id3->num].contents = out_string;
- free(tmp);
- }
- }
- }
- id3->num++;
- }
- }
- static void print_id3tag(struct id3tag *id3)
- {
- int i;
- for (i = 0; i < MAX_ID3_KEYS; i++)
- {
- if (id3->v2[i].size != 0)
- {
- printf("%c%c%c%c:", id3->v2[i].id[0],id3->v2[i].id[1],id3->v2[i].id[2],id3->v2[i].id[3]);
- printf("%s\\n", id3->v2[i].contents);
- }
- }
- }
- static ssize_t read_all(int fd, void *buf, size_t count)
- {
- char *buffer = buf;
- int pos = 0;
- do
- {
- int rc;
- rc = read(fd, buffer + pos, count - pos);
- if (rc == -1) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- return -1;
- }
- if (rc == 0) {
- /* eof */
- break;
- }
- pos += rc;
- } while (count - pos > 0);
- return pos;
- }
- static void print_v2_header(struct id3_v2_header *vh)
- {
- printf("%s\\n" , vh->id3);
- printf("major:%d\\n", vh->ver_major);
- printf("minor:%d\\n", vh->ver_minor);
- printf("flags:%d\\n", vh->flags);
- printf("Size:%d\\n", vh->size);
- }
- static void print_v2_frame_header(struct id3_v2_frame_header *fh)
- {
- if (fh->size == 0)
- return;
- printf("%c%c%c%c\\n", fh->id[0], fh->id[1], fh->id[2], fh->id[3]);
- printf("frame->size:%d\\n", fh->size);
- printf("frame->flags:%d\\n", fh->flags);
- }
- int parse_id3_v2_header(struct id3_v2_header *vh, int fd)
- {
- char buf[20];
- int i;
- uint32_t s = 0;
- memset(buf, 0, 20);
- read_all(fd, buf, 10);
- vh->id3[0] = buf[0];
- vh->id3[1] = buf[1];
- vh->id3[2] = buf[2];
- vh->id3[3] = 0;
- vh->ver_major = buf[3];
- vh->ver_minor = buf[4];
- vh->flags = buf[5];
- for (i = 0; i < 4; i++)
- {
- s = s << 7;
- s |= buf[6+i];
- }
- vh->size = s;
- if (vh->ver_major != 3)
- {
- printf("Can't parse id3 with major:%d (Only major:3)", vh->ver_major);
- return 1;
- }
- return 0;
- }
- static int get_id3_v2_frame_header(unsigned char *buf, struct id3_v2_frame_header *fh)
- {
- int i;
- uint32_t b, s = 0;
- uint16_t f = 0;
- fh->id[0] = buf[0];
- fh->id[1] = buf[1];
- fh->id[2] = buf[2];
- fh->id[3] = buf[3];
- for (i = 0; i < 4; i++)
- {
- b = buf[4 + i];
- s = s << 8;
- s |= b;
- }
- fh->size = s;
- for (i = 0; i < 2; i++)
- {
- f = f << 8;
- f |= buf[8+i];
- }
- fh->flags = f;
- }
- static int parse_id3_v2_frame(struct id3tag *id3, struct id3_v2_header *vh, int fd)
- {
- unsigned char *buf, *tmp;
- int i;
- uint32_t s;
- struct id3_v2_frame_header fh;
- int f;
- lseek(fd, 0, SEEK_SET);
- tmp = (unsigned char *)calloc(1, vh->size + 10);
- read_all(fd, tmp, vh->size + 10);
- buf = tmp + 10;
- i = 0;
- while (i < vh->size - 10)
- {
- get_id3_v2_frame_header(buf + i, &fh);
- if (vh->size - i < fh.size)
- {
- printf("Error id3_v2_header size\\n");
- return 1;
- }
- // print_v2_frame_header(&fh);
- if (fh.size != 0)
- add_id3tag(id3, &fh, buf+i);
- i += fh.size + 10;
- }
- free(tmp);
- return 0;
- }
- int main(int argc, char *argv[])
- {
- int fd;
- uint32_t size;
- struct id3_v2_header vh;
- struct id3tag id3;
- fd = open(argv[1], O_RDONLY);
- if (fd == 0)
- {
- fprintf(stderr, "Can't open file %s\\n", argv[1]);
- exit(1);
- }
- parse_id3_v2_header(&vh, fd);
- // print_v2_header(&vh);
- id3tag_init(&id3);
- parse_id3_v2_frame(&id3, &vh, fd);
- // output_id3tag(&id3);
- print_id3tag(&id3);
- id3tag_free(&id3);
- close(fd);
- return 0;
- }
- //该片段来自于http://www.codesnippet.cn/detail/081020136283.html
来源: http://www.codesnippet.cn/detail/081020136283.html