Example #1
0
static PyObject *
flac_MetadataSimpleIterator_get_application_id (flac_MetadataSimpleIteratorObject *self)
{
	FLAC__byte id[4];

	PyFLAC_CHECK_initialized(self);

	if (FLAC__metadata_simple_iterator_get_application_id(self->iterator, id))
		return PyFLAC_data(id, 4);

	if (flac_MetadataSimpleIterator_PyErr_FromIteratorStatus(self) < 0)
		return NULL;

	Py_RETURN_NONE;
}
Example #2
0
static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error)
{
	FLAC__byte id[4], buffer[12];
	FLAC__off_t offset;
	FLAC__bool type_found = false, ds64_found = false;

	FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8);

	while(FLAC__metadata_simple_iterator_next(it)) {
		if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION)
			continue;
		if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) {
			if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (002)";
			return false;
		}
		if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id)))
			continue;
		offset = FLAC__metadata_simple_iterator_get_block_offset(it);
		/* skip over header and app ID */
		offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
		offset += sizeof(id);
		/* look for format or audio blocks */
		if(fseeko(f, offset, SEEK_SET) < 0) {
			if(error) *error = "seek error (003)";
			return false;
		}
		if(fread(buffer, 1, 4, f) != 4) {
			if(error) *error = "read error (004)";
			return false;
		}
		if(fm->num_blocks == 0) { /* first block? */
			fm->is_rf64 = 0 == memcmp(buffer, "RF64", 4);
			if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && (0 == memcmp(buffer, "RIFF", 4) || fm->is_rf64))
				type_found = true;
			else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64 && 0 == memcmp(buffer, "riff", 4)) /* use first 4 bytes instead of whole GUID */
				type_found = true;
			else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4))
				type_found = true;
			else {
				if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)";
				return false;
			}
		}
		else if(!type_found) {
			FLAC__ASSERT(0);
			/* double protection: */
			if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)";
			return false;
		}
		else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) {
			if(!memcmp(buffer, "fmt ", 4)) {
				if(fm->format_block) {
					if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)";
					return false;
				}
				if(fm->audio_block) {
					if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)";
					return false;
				}
				fm->format_block = fm->num_blocks;
			}
			else if(!memcmp(buffer, "data", 4)) {
				if(fm->audio_block) {
					if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)";
					return false;
				}
				if(!fm->format_block) {
					if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)";
					return false;
				}
				fm->audio_block = fm->num_blocks;
			}
			else if(fm->is_rf64 && fm->num_blocks == 1) {
				if(memcmp(buffer, "ds64", 4)) {
					if(error) *error = "invalid RF64 metadata: second chunk is not \"ds64\" (011)";
					return false;
				}
				ds64_found = true;
			}
		}
		else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64) {
			if(!memcmp(buffer, "fmt ", 4)) { /* use first 4 bytes instead of whole GUID */
				if(fm->format_block) {
					if(error) *error = "invalid Wave64 metadata: multiple \"fmt \" chunks (012)";
					return false;
				}
				if(fm->audio_block) {
					if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (013)";
					return false;
				}
				fm->format_block = fm->num_blocks;
			}
			else if(!memcmp(buffer, "data", 4)) { /* use first 4 bytes instead of whole GUID */
				if(fm->audio_block) {
					if(error) *error = "invalid Wave64 metadata: multiple \"data\" chunks (014)";
					return false;
				}
				if(!fm->format_block) {
					if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (015)";
					return false;
				}
				fm->audio_block = fm->num_blocks;
			}
		}
		else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) {
			if(!memcmp(buffer, "COMM", 4)) {
				if(fm->format_block) {
					if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (016)";
					return false;
				}
				if(fm->audio_block) {
					if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (017)";
					return false;
				}
				fm->format_block = fm->num_blocks;
			}
			else if(!memcmp(buffer, "SSND", 4)) {
				if(fm->audio_block) {
					if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (018)";
					return false;
				}
				if(!fm->format_block) {
					if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (019)";
					return false;
				}
				fm->audio_block = fm->num_blocks;
				/* read SSND offset size */
				if(fread(buffer+4, 1, 8, f) != 8) {
					if(error) *error = "read error (020)";
					return false;
				}
				fm->ssnd_offset_size = unpack32be_(buffer+8);
			}
		}
		else {
			FLAC__ASSERT(0);
			/* double protection: */
			if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (021)";
			return false;
		}
		if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error))
			return false;
	}
	if(!type_found) {
		if(error) *error = "no foreign metadata found (022)";
		return false;
	}
	if(fm->is_rf64 && !ds64_found) {
		if(error) *error = "invalid RF64 file: second chunk is not \"ds64\" (023)";
		return false;
	}
	if(!fm->format_block) {
		if(error)
			*error =
				fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (024)" :
				fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"fmt \" chunk (025)" :
				"invalid AIFF file: missing \"COMM\" chunk (026)";
		return false;
	}
	if(!fm->audio_block) {
		if(error)
			*error =
				fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (027)" :
				fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"data\" chunk (028)" :
				"invalid AIFF file: missing \"SSND\" chunk (029)";
		return false;
	}
	return true;
}