Audio-Scan
view release on metacpan or search on metacpan
for (i = 0; i < frametype->nfields; ++i) {
DEBUG_TRACE(" %d", frametype->fields[i]);
}
DEBUG_TRACE("\n");
}
#endif
// If frame was compressed, temporarily set the id3 buffer to use the decompressed buffer
if (decompressed) {
tmp_buf = id3->buf;
id3->buf = decompressed;
}
if ( !_id3_parse_v2_frame_data(id3, (char *)&id, decoded_size ? decoded_size : size, frametype) ) {
DEBUG_TRACE(" error parsing frame, aborting\n");
ret = 0;
goto out;
}
if (id3->size_remain > size) {
id3->size_remain -= size;
}
else {
id3->size_remain = 0;
}
// Consume extra bytes if we had to unsync this frame
if (unsync_extra) {
DEBUG_TRACE(" consuming extra bytes after unsync: %d\n", unsync_extra);
buffer_consume(id3->buf, unsync_extra);
}
out:
if (decompressed) {
// Reset id3 buffer and consume rest of compressed frame
id3->buf = tmp_buf;
buffer_consume(id3->buf, size);
buffer_free(decompressed);
Safefree(decompressed);
}
return ret;
}
int
_id3_parse_v2_frame_data(id3info *id3, char const *id, uint32_t size, id3_frametype const *frametype)
{
int ret = 1;
uint32_t read = 0;
int8_t encoding = -1;
uint8_t buffer_art = ( !strcmp(id, "APIC") ) ? 1 : 0;
uint8_t skip_art = ( buffer_art && _env_true("AUDIO_SCAN_NO_ARTWORK") ) ? 1 : 0;
// Bug 16703, a completely empty frame is against the rules, skip it
if (!size)
return 1;
if (skip_art) {
// Only buffer enough for the APIC header fields, this is only a rough guess
// because the description could technically be very long
if ( !_check_buf(id3->infile, id3->buf, 128, ID3_BLOCK_SIZE) ) {
return 0;
}
DEBUG_TRACE(" partial read due to AUDIO_SCAN_NO_ARTWORK\n");
}
else {
// Use a special buffering mode for binary artwork, to avoid
// using 2x the memory of the APIC frame (once for buffer, once for SV)
if (buffer_art) {
// Buffer enough for encoding/MIME/picture type/description
if ( !_check_buf(id3->infile, id3->buf, 128, ID3_BLOCK_SIZE) ) {
return 0;
}
}
else {
// Buffer the entire frame
if ( !_check_buf(id3->infile, id3->buf, size, ID3_BLOCK_SIZE) ) {
return 0;
}
}
}
if ( frametype->fields[0] == ID3_FIELD_TYPE_TEXTENCODING ) {
// many frames have an encoding byte, read it here
encoding = buffer_get_char(id3->buf);
read++;
DEBUG_TRACE(" encoding: %d\n", encoding);
if (encoding < 0 || encoding > 3) {
DEBUG_TRACE(" invalid encoding, skipping frame\n");
goto out;
}
}
// Special handling for TXXX/WXXX frames
if ( !strcmp(id, "TXXX") || !strcmp(id, "WXXX") ) {
// Read key and uppercase it
SV *key = NULL;
SV *value = NULL;
read += _id3_get_utf8_string(id3, &key, size - read, encoding);
if (key != NULL && SvPOK(key) && sv_len(key)) {
upcase(SvPVX(key));
// Read value
if (frametype->fields[2] == ID3_FIELD_TYPE_LATIN1) {
// WXXX frames have a latin1 value field regardless of encoding byte
encoding = ISO_8859_1;
}
read += _id3_get_utf8_string(id3, &value, size - read, encoding);
// (T|W)XXX frames don't support multiple strings separated by nulls, even in v2.4
// Only one tag per unique key value is allowed, that's why there is no array support here
if (value != NULL && SvPOK(value) && sv_len(value)) {
my_hv_store_ent( id3->tags, key, value );
}
( run in 1.274 second using v1.01-cache-2.11-cpan-39bf76dae61 )