Audio-Scan

 view release on metacpan or  search on metacpan

Scan.xs  view on Meta::CPAN

    // Read bytes from middle of file to reduce chance of silence generating false matches
    start_offset = audio_offset;
    start_offset += (audio_size / 2) - (size / 2);
    if (start_offset < audio_offset)
      start_offset = audio_offset;
  }
  
  if (size >= audio_size) {
    size = audio_size;
  }
  
  DEBUG_TRACE("Using %d bytes for audio MD5, starting at %d\n", size, start_offset);
  
  if (PerlIO_seek(infile, start_offset, SEEK_SET) < 0) {
    warn("Audio::Scan unable to determine MD5 for %s\n", file);
    goto out;
  }
  
  while (size > 0) {
    if ( !_check_buf(infile, &buf, 1, MIN(size, MD5_BUFFER_SIZE)) ) {
      warn("Audio::Scan unable to determine MD5 for %s\n", file);
      goto out;
    }
    
    md5_append(&md5, buffer_ptr(&buf), buffer_len(&buf));
    
    size -= buffer_len(&buf);
    buffer_consume(&buf, buffer_len(&buf));
    DEBUG_TRACE("%d bytes left\n", size);
  }
  
  md5_finish(&md5, digest);
  
  for (di = 0; di < 16; ++di)
    sprintf(hexdigest + di * 2, "%02x", digest[di]);
  
  my_hv_store(info, "audio_md5", newSVpvn(hexdigest, 32));
  
out:
  buffer_free(&buf);
}

static uint32_t
_generate_hash(const char *file)
{
  char hashstr[MAX_PATH_STR_LEN];
  int mtime = 0;
  uint64_t size = 0;
  uint32_t hash;

#ifdef _MSC_VER
  BOOL fOk;
  WIN32_FILE_ATTRIBUTE_DATA fileInfo;

  fOk = GetFileAttributesEx(file, GetFileExInfoStandard, (void *)&fileInfo);
  mtime = fileInfo.ftLastWriteTime.dwLowDateTime;
  size = (uint64_t)fileInfo.nFileSizeLow;
#else
  struct stat buf;

  if (stat(file, &buf) != -1) {
    mtime = (int)buf.st_mtime;
    size = (uint64_t)buf.st_size;
  }
#endif

  memset(hashstr, 0, sizeof(hashstr));
  snprintf(hashstr, sizeof(hashstr) - 1, "%s%d%llu", file, mtime, size);
  hash = hashlittle(hashstr, strlen(hashstr), 0);
  
  return hash;
}

MODULE = Audio::Scan		PACKAGE = Audio::Scan

HV *
_scan( char *, char *suffix, PerlIO *infile, SV *path, int filter, int md5_size, int md5_offset )
CODE:
{
  taghandler *hdl;
  RETVAL = newHV();
  
  // don't leak
  sv_2mortal( (SV*)RETVAL );
  
  hdl = _get_taghandler(suffix);
  
  if (hdl) {
    HV *info = newHV();

    // Ignore filter if a file type has only one function (FLAC/Ogg)
    if ( !hdl->get_fileinfo ) {
      filter = FILTER_TYPE_INFO | FILTER_TYPE_TAGS;
    }

    if ( hdl->get_fileinfo && (filter & FILTER_TYPE_INFO) ) {
      hdl->get_fileinfo(infile, SvPVX(path), info);
    }

    if ( hdl->get_tags && (filter & FILTER_TYPE_TAGS) ) {
      HV *tags = newHV();
      hdl->get_tags(infile, SvPVX(path), info, tags);
      hv_store( RETVAL, "tags", 4, newRV_noinc( (SV *)tags ), 0 );
    }
    
    // Generate audio MD5 value
    if ( md5_size > 0
      && my_hv_exists(info, "audio_offset")
      && my_hv_exists(info, "audio_size")
      && !my_hv_exists(info, "audio_md5")
    ) {
      _generate_md5(infile, SvPVX(path), md5_size, md5_offset, info);
    }
    
    // Generate hash value
    my_hv_store(info, "jenkins_hash", newSVuv( _generate_hash(SvPVX(path)) ));

    // Info may be used in tag function, i.e. to find tag version
    hv_store( RETVAL, "info", 4, newRV_noinc( (SV *)info ), 0 );
  }
  else {



( run in 1.229 second using v1.01-cache-2.11-cpan-39bf76dae61 )