MP3: ID3v2 auslesen
-
Ich möchte gerne die Metadaten von MP3-Dateien auslesen, nur die Standardsachen (Künstler, Titel, Album, ...). Für ID3v1 funktioniert das ganze schon prima. Nur komme ich bei ID3v2 nicht so recht weiter.
In ID3v2 hat ja jedes Element einen Identifier. Wenn ich jetzt z. B. den Künstler suche, muss ich nach TPE1 suchen. Wie kann ich das in der Funktion getId3v2Tag effizient realisieren?
Meine Idee war es, alle Tags auszulesen und in ein Liste zu packen um sie dann anschließend zuzuordnen. Nur wie erkenne ich am besten, wann ein neuer Tag anfängt und der alte aufhört?
#include <iostream> #include <iomanip> #include <string> #include <cstring> #include <vector> #include <fstream> #include <windows.h> using namespace std; struct id3v1 { char title[30]; char artist[30]; char album[30]; char year[4]; char comment[28]; char track[2]; char genere[1]; }; struct id3v2 { char title[]; char artist[]; char album[]; char year[]; char comment[]; char track[]; char genere[]; }; string *getId3v2Tag(string id) { return 0; } id3v2 *readId3v2(string path) { // Datei öffnen fstream media; media.open(path.c_str(), ios::in | ios::binary); // wenn nicht Einleitung mit "ID3" dann keine Id3v2 Informationen char id[3]; media.read(id, 3); if (strncmp(id, "ID3", 3) != 0) return 0; // Tag lesen id3v2 *tag = new id3v2; //tag->title = getId3v2Tag("TIT2"); //tag->artist = getId3v2Tag("TPE1"); //tag->album = getId3v2Tag("TALB"); //tag->year = getId3v2Tag("TDRC"); //tag->track = getId3v2Tag("TRCK"); // Datei schließen media.close(); // Ausgabe Konsole cout << path << endl; cout << "TITLE : " << setw(30) << tag->title << " "; cout << "ARTIST : " << setw(30) << tag->artist << endl; cout << "ALBUM : " << setw(30) << tag->album << " "; cout << "YEAR : " << setw(30) << tag->year << endl; cout << "COMMENT: " << setw(30) << tag->comment << " "; cout << "TRACK : " << setw(30) << tag->track << endl; cout << "GENERE : " << setw(30) << tag->genere << endl; return tag; } /* * ID3 Informationen auslesen * letzten 128 Zeichen lesen und auswerten * title[30] + artist[30] + album[30] + year[4] + comment[28] + track[2] + genere[1] */ id3v1 *readId3v1(string path) { // Datei öffnen fstream media; media.open(path.c_str(), ios::in | ios::binary); // "Vorspulen" und die letzten 128 Zeichen einlesen char input[128]; media.seekg(-128, ios::end); // wenn nicht Einleitung mit "TAG" dann keine Id3v1 Informationen char id[3]; media.read(id, 3); if (strncmp(id, "TAG", 3) != 0) return 0; // Tag lesen id3v1 *tag = new id3v1; media.read(tag->title, 30); media.read(tag->artist, 30); media.read(tag->album, 30); media.read(tag->year, 4); media.read(tag->comment, 28); media.read(tag->track, 2); media.read(tag->genere, 1); // Datei schließen media.close(); // Ausgabe Konsole cout << path << endl; cout << "TITLE : " << setw(30) << tag->title << " "; cout << "ARTIST : " << setw(30) << tag->artist << endl; cout << "ALBUM : " << setw(30) << tag->album << " "; cout << "YEAR : " << setw(30) << tag->year << endl; cout << "COMMENT: " << setw(30) << tag->comment << " "; cout << "TRACK : " << setw(30) << tag->track << endl; cout << "GENERE : " << setw(30) << tag->genere << endl; return tag; } void scanDir(string path) { HANDLE fHandle; WIN32_FIND_DATA wfd; fHandle = FindFirstFile((path + "\\*").c_str(), &wfd); do { // Wenn . oder .. dann weiter if (wfd.cFileName[0] == '.' && wfd.cFileName[1] == 0) continue; if (wfd.cFileName[0] == '.' && wfd.cFileName[1] == '.' && wfd.cFileName[2] == 0) continue; // Wenn Ordner -> scanne Unterordner if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) scanDir(path + "\\" + wfd.cFileName); // Sonst Datei -> ausgeben else { string fileName = wfd.cFileName; // nur Dateien mit der Endung mp3 if (fileName.substr(fileName.length()-3, 3) == "mp3") readId3v1(path + "\\" + fileName); } } while (FindNextFile(fHandle, &wfd)); FindClose(fHandle); } int main() { scanDir("D:\\Friska Viljor"); return 0; }