static PyObject * flac_MetadataSimpleIterator_get_block_length (flac_MetadataSimpleIteratorObject *self) { PyFLAC_CHECK_initialized(self); return PyFLAC_unsigned(FLAC__metadata_simple_iterator_get_block_length(self->iterator)); }
static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error) { FLAC__byte buffer[4]; const unsigned ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8; size_t block_num = 0; FLAC__ASSERT(sizeof(buffer) >= ID_LEN); while(block_num < fm->num_blocks) { /* find next matching padding block */ do { /* even on the first chunk's loop there will be a skippable STREAMINFO block, on subsequent loops we are first moving past the PADDING we just used */ if(!FLAC__metadata_simple_iterator_next(it)) { if(error) *error = "no matching PADDING block found (004)"; return false; } } while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING); if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) { if(error) *error = "PADDING block with wrong size found (005)"; return false; } /* transfer chunk into APPLICATION block */ /* first set up the file pointers */ if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) { if(error) *error = "seek failed in WAVE/AIFF file (006)"; return false; } if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) { if(error) *error = "seek failed in FLAC file (007)"; return false; } /* update the type */ buffer[0] = FLAC__METADATA_TYPE_APPLICATION; if(FLAC__metadata_simple_iterator_is_last(it)) buffer[0] |= 0x80; /*MAGIC number*/ if(fwrite(buffer, 1, 1, fout) < 1) { if(error) *error = "write failed in FLAC file (008)"; return false; } /* length stays the same so skip over it */ if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) { if(error) *error = "seek failed in FLAC file (009)"; return false; } /* write the APPLICATION ID */ memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN); if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) { if(error) *error = "write failed in FLAC file (010)"; return false; } /* transfer the foreign metadata */ if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)")) return false; block_num++; } return true; }
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; }