Audio-Scan

 view release on metacpan or  search on metacpan

src/id3.c  view on Meta::CPAN

    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 )