Audio-Scan
view release on metacpan or search on metacpan
// 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 )