Problem beim Auslesen des ID3v1 Tags einer mp3 Datei



  • Hallo,
    ich will den ID3v1 Tag einer mp3 Datei auslesen. Dazu habe ich bis ejtzt folgende Struktur definiert:

    struct id3 {
    		char			tag[3];
    		char			title[31];
    		char			artist[31];
    		char			album[31];
    		char			year[5];
    		char			comment[31];
    		int 			genre;
    		int			track;
    	} play1;
    

    Folgende Funktion soll den Tag auslesen:

    id3 readid3(char *szPath) {    /* szPath ist der Pfad zur mp3Datei */
    
    		FILE	*datei_ptr;
    		char 	ver[2];
    
    		datei_ptr = fopen(szPath, "r+b");
    
    		if ( datei_ptr != 0) {
    
    			if (fseek(datei_ptr,-128,SEEK_END) == 0) {
                                         fgets(play1.tag,4,datei_ptr);
    				fgets(play1.title,31,datei_ptr);
    				fgets(play1.artist,31,datei_ptr);
    				fgets(play1.album,31,datei_ptr);
    				fgets(play1.year,5,datei_ptr);
    				fgets(play1.comment,31,datei_ptr);
    				fgets(ver,2,datei_ptr);
    				play1.genre = atoi(ver);
                                }
    			else 
    				printf("Zeiger konnte nicht gesetzt werden!");
                                         fclose(datei_ptr);
    	 	}
    
    		else
    			printf("Fehler beim öffnen der Datei!");
    
    		return play1;
    
    	}
    

    Mit printf kann ich mir damit die Werte von Titel, Artist, Album, Jahr und Kommentar richtig anzeigen lassen. Doch bei Genre wird immer 0 ausgegeben, obwohl die Datei eine Information über das Genre enthält. Woran kann das liegen?
    Ich hoffe, dass ihr mir helfen könnt.

    MFG, VLT02



  • Wenn ichs richtig sehe, ist das Genre als ein Byte Zahl gespeichert. Du liest einen String und versuchst dannd ie Zahl auszulesen, das klappt so nicht.

    Ich denke mal

    fread(&play1.genre, sizeof(unsigned char), 1, datei_ptr)
    

    sollte besser klappen, nicht vergessen genre im struct als unsigned char zu deklarieren.



  • Herzlichen Dank, TriPhoenix, für deine Hilfe!
    Jetzt klappt es so wie ich es mir vorstelle 🙂

    MFG, VLT02



  • Hallo,

    jetzt hab ich leider wieder ein Problem.
    Meine Funktion sieht jetzt so aus:

    id3 readid3(char *szPath) { /* Pfad zur .mp3-Datei */
    
    		FILE	*datei_ptr = NULL;
    		char	ver[4];
    
    		datei_ptr = fopen(szPath, "r+b");
    
    		if ( datei_ptr != 0) {
    
    			/* Nach ID3v2 Tag suchen*/
    			fseek(datei_ptr,0,SEEK_SET);
    			fread(ver,3,1,datei_ptr);
    
    			if (strcmp(ver, "ID3") == 0) 
    				printf("ID3v2 Tag vorhanden!");
    
    			/* Nach ID3v1 Tag suchen */
    			if (fseek(datei_ptr,-128,SEEK_END) == 0) {
    
    				fread(play.tag,3,1,datei_ptr);
    
    				if (strcmp(play.tag, "TAG") == 0) {
    					fread(play.title,30,1,datei_ptr);
    					fread(play.artist,30,1,datei_ptr);
    					fread(play.album,30,1,datei_ptr);
    					fread(play.year,4,1,datei_ptr);
    					fread(play.comment,29,1,datei_ptr);
    					fread(&play.genre, sizeof(unsigned char), 1, datei_ptr);
    					fread(&play.track, sizeof(unsigned char), 1, datei_ptr);
    					play.title[30]='\0';
    					play.artist[30]='\0';
    					play.album[30]='\0';
    					play.year[4]='\0';
    					play.comment[30]='\0';
    				}	
    
    			}
    			else 
    				printf("Zeiger konnte nicht gesetzt werden!");
    
    			fclose(datei_ptr);
    	 	}
    
    		else
    			printf("Fehler beim öffnen der Datei!");
    
    		return play;
    
    	}
    

    Wenn ich die Funktion jetzt einmal aufrufe funktioniert alles bestens.
    Wenn ich aber folgendes eingebe:

    strcpy(pfad, "c:\\mp3s\\Faith No More - I'm Easy.mp3");
    		readid3(pfad);
    strcpy(pfad, "c:\\mp3s\\Metallica - Enter Sandman.mp3");
    		readid3(pfad);
    

    steht nach dem zweiten Aufruf in play.title immer noch I'm easy und nicht Enter - Sandman.
    Hab seit gestern schon alles mögliche ausprobiert, aber weis nicht woran das liegt. Hängt das irgendwie mit st_atime zusammen?

    MFG, VLT02



  • ist play eine globale Variable? Wenn ja: warum?

    Ich nehme an, es steht einfach noch der alte Datensatz da drinnen



  • Ja in play steht noch der alte Datensatz drin.
    Und play muss doch eine globale Variable sein, weil ich ansonsten in meinem Hauptprogramm nicht auf die Elemente von play zugreifen kann.
    Ich hab schon probiert bei jedem Funktionsaufruf die Struktur am Anfang neu zu initialisieren mit:

    strcpy(play.title, "0");
    strcpy(play.artist, "0");
    strcpy(play.album, "0");
    strcpy(play.tag, "0");
    play.genre = 0;
    play.track = 0;
    strcpy(play.year, "0");
    strcpy(play.comment, "0");
    

    Dann steht aber nur noch 0 in den einzelnen Werten und fread überschreibt das nicht mehr.
    Ist die Möglichkeit vom Ansatz her richtig oder macht man das besser anders?

    MFG, VLT02



  • returnst play doch aus deiner funktion... also leg play auch dort an...

    btw: wenn eine funktion fehlschlaegt, sollte sie dies melden (und zwar nicht mit einem printf, sondern eben einen fehler zurueck geben)

    einziges was mir einfaellt ist, dass
    if (strcmp(play.tag, "TAG") == 0)
    unwahr ist und somit die struktur nicht geaendert wird...



  • So jetzt klappt es eigentlich 😉

    if (strcmp(play.tag, "TAG") == 0)
    

    traff tatsächlich nicht zu, da ich nicht

    play.tag[3]='\0';
    

    eingegeben habe stand beim zweiten Aufruf der Funktion in play.tag "TAG+der Name des Liedes" und war nicht mehr 3 bytes lang sonder 33.
    Wie kann das sein, wenn ich in der Struktur geschrieben habe, dass play.tag nur 3 bytes lang sein darf?



  • und danke für deine Hilfe 😃

    MFG, VLT02



  • VLT02 schrieb:

    So jetzt klappt es eigentlich 😉

    if (strcmp(play.tag, "TAG") == 0)
    

    traff tatsächlich nicht zu, da ich nicht

    play.tag[3]='\0';
    

    eingegeben habe stand beim zweiten Aufruf der Funktion in play.tag "TAG+der Name des Liedes" und war nicht mehr 3 bytes lang sonder 33.
    Wie kann das sein, wenn ich in der Struktur geschrieben habe, dass play.tag nur 3 bytes lang sein darf?

    Das 0 setzen von play.tag[3] ist eigentlich keine gute Idee. Da du ja eigentlich auf den Speicherbereich hinter play.tag[3] schreibst. Entweder du erhöhst den Speicherbereich von tag auf 4 oder du schreibst deine Überprüfung anders, und zwar nicht mit strcmp() sondern mit strncmp() da kannst du nämlich angeben wieviele Zeichen überprüft werden sollen (in deinem Fall als nur 3). strncmp() überprüft hald solange bis es das Stringendezeichen (-> \0) gefunden hat bei einem der beiden und überprüft auch dieses!


Anmelden zum Antworten