implemented scan functionality

This commit is contained in:
Daniel Sommer 2017-03-28 15:39:37 +02:00
parent db6b470694
commit 71918aedd5
5 changed files with 85 additions and 19 deletions

View file

@ -34,10 +34,10 @@ function badger() {
.action(sort); .action(sort);
// artwork // artwork
commander commander
.command('artwork <input>') .command('extract <input>')
.description('extract cover artwork') .description('extract cover artwork')
.option('-f, --format <format>', 'specify audio format (\'flac\', \'mp3\')', '.flac') .option('-f, --format <format>', 'specify audio format (\'flac\', \'mp3\')', '.flac')
.action(artwork); .action(extract);
// scan // scan
commander commander
.command('scan <input>') .command('scan <input>')
@ -70,22 +70,42 @@ function sort(input, output, options) {
bitrate: options.bitrate || 320, bitrate: options.bitrate || 320,
format: options.format || '.flac' format: options.format || '.flac'
}, function (err, time) { }, function (err, time) {
cli.exit(err); cli.exit(err, time);
}); });
} }
// extract artwork // extract artwork
function artwork(input, options) { function extract(input, options) {
audio.batchArtwork({ audio.batchArtwork({
input: path.normalize(input), input: path.normalize(input),
concurrency: commander.concurrency || os.cpus().length, concurrency: commander.concurrency || os.cpus().length,
format: options.format || '.flac' format: options.format || '.flac'
}, function (err, time) { }, function (err, time) {
cli.exit(err); cli.exit(err, time);
}); });
} }
// scan files // scan files
function scan(input, options) { function scan(input, options) {
audio.batchScan({
input: path.normalize(input),
concurrency: commander.concurrency || os.cpus().length,
format: options.format || '.flac'
}, function (err, missing, time) {
if (!missing || missing.length === 0) {
console.log('no files with missing cover artwork found');
cli.exit(err, time);
} else {
console.log(missing.length + ' files with missing cover artwork found after ' + util.getTimeDiff(time) + ' seconds');
cli.askForConfirmation('list files now?', ['yes', 'y'], function (canceled) {
if (canceled) {
cli.exit(err, time);
}
missing.forEach(function (file) {
console.log(file);
});
cli.exit(err);
});
}
});
} }

View file

@ -81,8 +81,8 @@ function convert(source, config, callback) {
], callback); ], callback);
} }
// // extract all covers
function batchArtwork(config, callback) { function batchExtract(config, callback) {
let timestamp = process.hrtime(); let timestamp = process.hrtime();
async.waterfall([ async.waterfall([
// get files // get files
@ -103,7 +103,7 @@ function batchArtwork(config, callback) {
function (files, bar, waterfallCallback) { function (files, bar, waterfallCallback) {
timestamp = process.hrtime(); timestamp = process.hrtime();
async.eachLimit(files, config.concurrency, function (file, eachCallback) { async.eachLimit(files, config.concurrency, function (file, eachCallback) {
extractArtwork(file, function (err) { artwork(file, function (err) {
bar.tick(); bar.tick();
if (err) { if (err) {
return eachCallback(err); return eachCallback(err);
@ -121,7 +121,7 @@ function batchArtwork(config, callback) {
} }
// extract cover artwork // extract cover artwork
function extractArtwork(source, callback) { function artwork(source, callback) {
async.waterfall([ async.waterfall([
// get metadata // get metadata
function (waterfallCallback) { function (waterfallCallback) {
@ -142,9 +142,52 @@ function extractArtwork(source, callback) {
], callback); ], callback);
} }
// scan files in input directory for missing cover artwork
function batchScan(config, callback) {
let timestamp = process.hrtime();
async.waterfall([
// get files
function (waterfallCallback) {
util.readDirRecursive(config.input, config.format, waterfallCallback);
},
// display info, prompt user and create progressbar
function (files, waterfallCallback) {
console.log(files.length + ' files found after ' + util.getTimeDiff(timestamp) + ' seconds');
cli.askForConfirmation('start scan now?', ['yes', 'y'], function (err) {
if (err) {
return waterfallCallback(err);
}
waterfallCallback(null, files, cli.createProgressBar(files.length));
});
},
// process each file
function (files, bar, waterfallCallback) {
let missing = [];
timestamp = process.hrtime();
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
extractMetadata(file, function (err, metadata) {
bar.tick();
if (err) {
return eachCallback(err);
}
if (!metadata.picture || metadata.picture.length === 0) {
missing.push(file);
}
eachCallback();
});
}, function (err) {
if (err) {
return waterfallCallback(err);
}
waterfallCallback(null, missing, timestamp);
});
}
], callback);
}
// extract metadata for further processing // extract metadata for further processing
function extractMetadata(sourceFile, callback) { function extractMetadata(source, callback) {
const stream = fs.createReadStream(sourceFile); const stream = fs.createReadStream(source);
metadata(stream, function (err, metadata) { metadata(stream, function (err, metadata) {
if (err) { if (err) {
return callback(err); return callback(err);
@ -156,7 +199,6 @@ function extractMetadata(sourceFile, callback) {
// api // api
exports.batchConvert = batchConvert; exports.batchConvert = batchConvert;
exports.convert = convert; exports.batchArtwork = batchExtract;
exports.batchArtwork = batchArtwork; exports.batchScan = batchScan;
exports.extractArtwork = extractArtwork;
exports.extractMetadata = extractMetadata; exports.extractMetadata = extractMetadata;

View file

@ -9,7 +9,7 @@ function printLogo() {
console.log(' | |__ __ _ __| |__ _ ___ _ _ /_\\ | \\/ |'); console.log(' | |__ __ _ __| |__ _ ___ _ _ /_\\ | \\/ |');
console.log(' | \'_ \\\/ _` \/ _` \/ _` / -_) \'_\/ _ \\| |\\/| |'); console.log(' | \'_ \\\/ _` \/ _` \/ _` / -_) \'_\/ _ \\| |\\/| |');
console.log(' |_.__\/\\__,_\\__,_\\__, \\___|_|\/_\/ \\_\\_| |_|'); console.log(' |_.__\/\\__,_\\__,_\\__, \\___|_|\/_\/ \\_\\_| |_|');
console.log(' |___/ '); console.log(' |___/ \n');
} }
// display a confirmation prompt // display a confirmation prompt
@ -46,11 +46,15 @@ function createProgressBar(total) {
// shutdown // shutdown
function exit(err, timestamp) { function exit(err, timestamp) {
let message = 'exiting'
if (timestamp) {
message += ' after ' + util.getTimeDiff(timestamp) + ' seconds';
}
console.log(message);
if (err) { if (err) {
console.error(err); console.error(err);
process.exit(1); process.exit(1);
} }
console.log('exiting after ' + util.getTimeDiff(timestamp) + ' seconds');
process.exit(0); process.exit(0);
} }

View file

@ -17,7 +17,7 @@ function batchSort(config, callback) {
}, },
// display info, prompt user and create progressbar // display info, prompt user and create progressbar
function (files, waterfallCallback) { function (files, waterfallCallback) {
console.log(files.length + ' files found after ' + util.getTimeDiff(timestamp) + ' seconds'); console.log(files.length + ' files found after ' + getTimeDiff(timestamp) + ' seconds');
cli.askForConfirmation('start sorting now?', ['yes', 'y'], function (err) { cli.askForConfirmation('start sorting now?', ['yes', 'y'], function (err) {
if (err) { if (err) {
return waterfallCallback(err); return waterfallCallback(err);

View file

@ -1,6 +1,6 @@
{ {
"name": "badger-am", "name": "badger-am",
"version": "0.5.4", "version": "0.6.0",
"license": "MIT", "license": "MIT",
"description": "audio manager", "description": "audio manager",
"author": "Daniel Sommer <daniel.sommer@velvettear.de>", "author": "Daniel Sommer <daniel.sommer@velvettear.de>",