/* $Id$ */ /* * Cantus Tag Editor * Copyright © 2002-2004 by Samuel Abels * Copyright © 2007 by Tim Huetz * * 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 3 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, see **/ #include #include #include #include #include #include #include #include //#define _DEBUG_ #if defined( __cplusplus ) extern "C" { #endif /* * Purpose: Reads the ID3 tag from a file. * Parameters: tag - The structure to store the tag in, filename - The name of * the file to operate on. * Returns: * 0 if successful, * 1 if an error occured when opening the file * 2 if error while reading tag. * 3 if no TAG found. */ int get_id3v1_tag(Tag *tag, const char *filename) { FILE *mp3file; char *buffer = (char*)malloc(2048); id3v1Tag *v1 = (id3v1Tag*)malloc(sizeof(id3v1Tag)); short int foundtag = FALSE; int i = -1; memset(tag, 0, sizeof(Tag)); memset(v1, 0, sizeof(id3v1Tag)); memset(buffer, 0, 2048); #ifdef _DEBUG_ printf("get_id3v1_tag(): Opening %s.\n", filename); #endif mp3file = fopen(filename, "rb"); if (!mp3file) return 1; /* Read the last 200 bytes of the file. */ /* In the most cases, the last 128 bytes would be enough, but some buggy tags, /* again... */ #ifdef _DEBUG_ printf("get_id3v1_tag(): Reading the last 200 bytes of the file...\n"); #endif fseek(mp3file, -200, SEEK_END); if (!fread(buffer, 1, 400, mp3file)) { free(buffer); free(v1); fclose(mp3file); return 2; } fclose(mp3file); /* Parse through the raw data, if a "TAG" sign is found, we copy the raw */ /* data to a struct. */ #ifdef _DEBUG_ printf("get_id3v1_tag(): Searching for the TAG symbol...\n"); #endif i = -1; while (++i <= (200-128)) { if ((*(buffer + i + 0) == 'T') && (*(buffer + i + 1) == 'A') && (*(buffer + i + 2) == 'G')) { memcpy(v1, buffer + i + 3, 125); foundtag = TRUE; break; } } free(buffer); if (!foundtag) { free(v1); return 3; } #ifdef _DEBUG_ printf("get_id3v1_tag(): Tag found. This looks pretty good.\n"); #endif strncpy(tag->title, v1->title, 30); strncpy(tag->artist, v1->artist, 30); strncpy(tag->album, v1->album, 30); strncpy(tag->year, v1->year, 4); if (v1->comment[28]=='\0' && v1->comment[29]!='\0') { strncpy(tag->comment, v1->comment, 28); snprintf(tag->track, 3, "%i", v1->comment[29]); tag->comment[29] = '\0'; } else { strncpy(tag->comment, v1->comment, 30); tag->comment[30] = '\0'; } if (v1->genre > 147) strncpy(tag->genre, genre[12], 511); else strncpy(tag->genre, genre[v1->genre], 511); free(v1); return 0; } /* * Purpose: Writes the ID3 tag to the file. * Parameters: tag - The tag to write, filename - The name of the file to * operate on. * Returns: * 0 if successful, * 1 if an error occured when opening the file for reading * 2 if error while reading whole file. * 3 if an error occured while writing the whole file * 4 if error while opening file for tagadding. * 5 if error while writing the tag. */ int set_id3v1_tag(Tag *tag, const char *filename) { FILE *mp3file = NULL; id3v1Tag *v1; int i = 0; del_id3v1_tag(filename); /* Prepare users data for writing. */ v1 = (id3v1Tag*)malloc(sizeof(id3v1Tag)); memcpy(v1->title, tag->title, 30); memcpy(v1->artist, tag->artist, 30); memcpy(v1->album, tag->album, 30); memcpy(v1->year, tag->year, 4); if (tag->track) { memcpy(v1->comment, tag->comment, 28); v1->comment[28]='\0'; *(v1->comment + 29) = atoi(tag->track); } else { memcpy(v1->comment, tag->comment, 30); } /* Find the genre number. */ i = -1; while (genre[++i]) { if (strcmp(genre[i], tag->genre) == 0) break; } /* ...or set the genre to "other". */ if (!genre[i]) i = 12; v1->genre = i; mp3file = fopen(filename, "r+b"); if (!mp3file) { free(v1); return 4; } /* Now add the new tag. */ fseek(mp3file, 0, SEEK_END); fputc('T', mp3file); fputc('A', mp3file); fputc('G', mp3file); if (!fwrite(v1, 1, sizeof(id3v1Tag), mp3file)) { free(v1); fclose(mp3file); return 5; } fclose(mp3file); free(v1); return 0; } /* * Name says it all. * Returns: * 0 if successful, * 1 if an error occured when opening the file * 2 if error while reading file. * 3 if no TAG found. */ int del_id3v1_tag(const char *filename) { FILE *mp3stream; int mp3file; long i = 0, len; char buffer[400]; /* Find length of the file. */ mp3stream = fopen(filename, "r+b"); if(!mp3stream) return 1; fseek(mp3stream, 0, SEEK_END); len = ftell(mp3stream); fclose(mp3stream); /* Open file for writing. */ mp3file = open(filename, O_RDWR); if(mp3file == -1) return 1; /* If there is an existing tag, delete it. */ memset(buffer, 0, 400); /* Read the last 400 bytes of the file. */ /* In most cases, the last 128 bytes would be enough, but some buggy tags, /* again... */ lseek(mp3file, -400L, SEEK_END); if (read(mp3file, buffer, 400) < 400) { close(mp3file); return 2; } i = -1; while (++i <= 400) { if (buffer[i] == 'T' && buffer[i + 1] == 'A' && buffer[i + 2] == 'G') { ftruncate(mp3file, len - (400 - i)); break; } } close(mp3file); return 0; } #if defined( __cplusplus ) } #endif