tag_id3: parse ID3 tags in AIFF files
Added a small AIFF parser library, code copied from the RIFF parser (big-endian integers). Look for an "ID3" chunk, and let libid3tag parse it.
This commit is contained in:
		| @@ -104,6 +104,7 @@ mpd_headers = \ | ||||
| 	src/playlist_save.h \ | ||||
| 	src/playlist_state.h \ | ||||
| 	src/riff.h \ | ||||
| 	src/aiff.h \ | ||||
| 	src/queue.h \ | ||||
| 	src/queue_print.h \ | ||||
| 	src/queue_save.h \ | ||||
| @@ -232,7 +233,7 @@ endif | ||||
|  | ||||
| if HAVE_ID3TAG | ||||
| src_mpd_SOURCES += src/tag_id3.c \ | ||||
| 	src/riff.c | ||||
| 	src/riff.c src/aiff.c | ||||
| endif | ||||
|  | ||||
| # archive plugins | ||||
| @@ -560,8 +561,8 @@ test_software_volume_SOURCES = test/software_volume.c \ | ||||
| 	src/pcm_volume.c | ||||
|  | ||||
| if HAVE_ID3TAG | ||||
| test_run_decoder_SOURCES += src/tag_id3.c src/riff.c | ||||
| test_read_tags_SOURCES += src/tag_id3.c src/riff.c | ||||
| test_run_decoder_SOURCES += src/tag_id3.c src/riff.c src/aiff.c | ||||
| test_read_tags_SOURCES += src/tag_id3.c src/riff.c src/aiff.c | ||||
| endif | ||||
|  | ||||
| endif | ||||
|   | ||||
							
								
								
									
										103
									
								
								src/aiff.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/aiff.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| /* | ||||
|  * Copyright (C) 2003-2009 The Music Player Daemon Project | ||||
|  * http://www.musicpd.org | ||||
|  * | ||||
|  * 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 2 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, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #include "aiff.h" | ||||
|  | ||||
| #include <glib.h> | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <unistd.h> | ||||
| #include <errno.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #undef G_LOG_DOMAIN | ||||
| #define G_LOG_DOMAIN "aiff" | ||||
|  | ||||
| struct aiff_header { | ||||
| 	char id[4]; | ||||
| 	uint32_t size; | ||||
| 	char format[4]; | ||||
| }; | ||||
|  | ||||
| struct aiff_chunk_header { | ||||
| 	char id[4]; | ||||
| 	uint32_t size; | ||||
| }; | ||||
|  | ||||
| size_t | ||||
| aiff_seek_id3(FILE *file) | ||||
| { | ||||
| 	int ret; | ||||
| 	struct stat st; | ||||
| 	struct aiff_header header; | ||||
| 	struct aiff_chunk_header chunk; | ||||
| 	size_t size; | ||||
|  | ||||
| 	/* determine the file size */ | ||||
|  | ||||
| 	ret = fstat(fileno(file), &st); | ||||
| 	if (ret < 0) { | ||||
| 		g_warning("Failed to stat file descriptor: %s", | ||||
| 			  strerror(errno)); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* seek to the beginning and read the AIFF header */ | ||||
|  | ||||
| 	ret = fseek(file, 0, SEEK_SET); | ||||
| 	if (ret != 0) { | ||||
| 		g_warning("Failed to seek: %s", g_strerror(errno)); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	size = fread(&header, sizeof(header), 1, file); | ||||
| 	if (size != 1 || | ||||
| 	    memcmp(header.id, "FORM", 4) != 0 || | ||||
| 	    GUINT32_FROM_BE(header.size) > st.st_size || | ||||
| 	    memcmp(header.format, "AIFF", 4) != 0) | ||||
| 		/* not a AIFF file */ | ||||
| 		return 0; | ||||
|  | ||||
| 	while (true) { | ||||
| 		/* read the chunk header */ | ||||
|  | ||||
| 		size = fread(&chunk, sizeof(chunk), 1, file); | ||||
| 		if (size != 1) | ||||
| 			return 0; | ||||
|  | ||||
| 		size = GUINT32_FROM_BE(chunk.size); | ||||
| 		if (size % 2 != 0) | ||||
| 			/* pad byte */ | ||||
| 			++size; | ||||
|  | ||||
| 		if (memcmp(chunk.id, "ID3 ", 4) == 0) | ||||
| 			/* found it! */ | ||||
| 			return size; | ||||
|  | ||||
| 		if ((off_t)size < 0) | ||||
| 			/* integer underflow after cast to signed | ||||
| 			   type */ | ||||
| 			return 0; | ||||
|  | ||||
| 		ret = fseek(file, size, SEEK_CUR); | ||||
| 		if (ret != 0) | ||||
| 			return 0; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										40
									
								
								src/aiff.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/aiff.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
|  * Copyright (C) 2003-2009 The Music Player Daemon Project | ||||
|  * http://www.musicpd.org | ||||
|  * | ||||
|  * 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 2 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, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| /** \file | ||||
|  * | ||||
|  * A parser for the AIFF file format. | ||||
|  */ | ||||
|  | ||||
| #ifndef MPD_AIFF_H | ||||
| #define MPD_AIFF_H | ||||
|  | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| /** | ||||
|  * Seeks the AIFF file to the ID3 chunk. | ||||
|  * | ||||
|  * @return the size of the ID3 chunk on success, or 0 if this is not a | ||||
|  * AIFF file or no ID3 chunk was found | ||||
|  */ | ||||
| size_t | ||||
| aiff_seek_id3(FILE *file); | ||||
|  | ||||
| #endif | ||||
| @@ -86,8 +86,6 @@ riff_seek_id3(FILE *file) | ||||
| 			/* pad byte */ | ||||
| 			++size; | ||||
|  | ||||
| 		g_debug("chunk='%.4s' size=%zu\n", chunk.id, size); | ||||
|  | ||||
| 		if (memcmp(chunk.id, "id3 ", 4) == 0) | ||||
| 			/* found it! */ | ||||
| 			return size; | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
| #include "tag_id3.h" | ||||
| #include "tag.h" | ||||
| #include "riff.h" | ||||
| #include "aiff.h" | ||||
| #include "conf.h" | ||||
|  | ||||
| #include <glib.h> | ||||
| @@ -426,7 +427,7 @@ static struct id3_tag *findId3TagFromEnd(FILE * stream) | ||||
| } | ||||
|  | ||||
| static struct id3_tag * | ||||
| tag_id3_riff_load(FILE *file) | ||||
| tag_id3_riff_aiff_load(FILE *file) | ||||
| { | ||||
| 	size_t size; | ||||
| 	void *buffer; | ||||
| @@ -434,10 +435,12 @@ tag_id3_riff_load(FILE *file) | ||||
| 	struct id3_tag *tag; | ||||
|  | ||||
| 	size = riff_seek_id3(file); | ||||
| 	if (size == 0) | ||||
| 		size = aiff_seek_id3(file); | ||||
| 	if (size == 0) | ||||
| 		return NULL; | ||||
|  | ||||
| 	if (size > 65536) | ||||
| 	if (size > 256 * 1024) | ||||
| 		/* too large, don't allocate so much memory */ | ||||
| 		return NULL; | ||||
|  | ||||
| @@ -469,7 +472,7 @@ struct tag *tag_id3_load(const char *file) | ||||
|  | ||||
| 	tag = findId3TagFromBeginning(stream); | ||||
| 	if (tag == NULL) | ||||
| 		tag = tag_id3_riff_load(stream); | ||||
| 		tag = tag_id3_riff_aiff_load(stream); | ||||
| 	if (!tag) | ||||
| 		tag = findId3TagFromEnd(stream); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann