diff --git a/badger-am.js b/badger-am.js
index d1981be..1b70f97 100755
--- a/badger-am.js
+++ b/badger-am.js
@@ -34,10 +34,10 @@ function badger() {
.action(sort);
// artwork
commander
- .command('artwork ')
+ .command('extract ')
.description('extract cover artwork')
.option('-f, --format ', 'specify audio format (\'flac\', \'mp3\')', '.flac')
- .action(artwork);
+ .action(extract);
// scan
commander
.command('scan ')
@@ -70,22 +70,42 @@ function sort(input, output, options) {
bitrate: options.bitrate || 320,
format: options.format || '.flac'
}, function (err, time) {
- cli.exit(err);
+ cli.exit(err, time);
});
}
// extract artwork
-function artwork(input, options) {
+function extract(input, options) {
audio.batchArtwork({
input: path.normalize(input),
concurrency: commander.concurrency || os.cpus().length,
format: options.format || '.flac'
}, function (err, time) {
- cli.exit(err);
+ cli.exit(err, time);
});
}
// scan files
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);
+ });
+ }
+ });
}
\ No newline at end of file
diff --git a/lib/audio.js b/lib/audio.js
index b842137..b9f5687 100644
--- a/lib/audio.js
+++ b/lib/audio.js
@@ -81,8 +81,8 @@ function convert(source, config, callback) {
], callback);
}
-//
-function batchArtwork(config, callback) {
+// extract all covers
+function batchExtract(config, callback) {
let timestamp = process.hrtime();
async.waterfall([
// get files
@@ -103,7 +103,7 @@ function batchArtwork(config, callback) {
function (files, bar, waterfallCallback) {
timestamp = process.hrtime();
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
- extractArtwork(file, function (err) {
+ artwork(file, function (err) {
bar.tick();
if (err) {
return eachCallback(err);
@@ -121,7 +121,7 @@ function batchArtwork(config, callback) {
}
// extract cover artwork
-function extractArtwork(source, callback) {
+function artwork(source, callback) {
async.waterfall([
// get metadata
function (waterfallCallback) {
@@ -142,9 +142,52 @@ function extractArtwork(source, 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
-function extractMetadata(sourceFile, callback) {
- const stream = fs.createReadStream(sourceFile);
+function extractMetadata(source, callback) {
+ const stream = fs.createReadStream(source);
metadata(stream, function (err, metadata) {
if (err) {
return callback(err);
@@ -156,7 +199,6 @@ function extractMetadata(sourceFile, callback) {
// api
exports.batchConvert = batchConvert;
-exports.convert = convert;
-exports.batchArtwork = batchArtwork;
-exports.extractArtwork = extractArtwork;
+exports.batchArtwork = batchExtract;
+exports.batchScan = batchScan;
exports.extractMetadata = extractMetadata;
\ No newline at end of file
diff --git a/lib/cli.js b/lib/cli.js
index 8dcb74d..aeb815e 100644
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -9,7 +9,7 @@ function printLogo() {
console.log(' | |__ __ _ __| |__ _ ___ _ _ /_\\ | \\/ |');
console.log(' | \'_ \\\/ _` \/ _` \/ _` / -_) \'_\/ _ \\| |\\/| |');
console.log(' |_.__\/\\__,_\\__,_\\__, \\___|_|\/_\/ \\_\\_| |_|');
- console.log(' |___/ ');
+ console.log(' |___/ \n');
}
// display a confirmation prompt
@@ -46,11 +46,15 @@ function createProgressBar(total) {
// shutdown
function exit(err, timestamp) {
+ let message = 'exiting'
+ if (timestamp) {
+ message += ' after ' + util.getTimeDiff(timestamp) + ' seconds';
+ }
+ console.log(message);
if (err) {
console.error(err);
process.exit(1);
}
- console.log('exiting after ' + util.getTimeDiff(timestamp) + ' seconds');
process.exit(0);
}
diff --git a/lib/util.js b/lib/util.js
index 8dc9ac6..9daaa2e 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -17,7 +17,7 @@ function batchSort(config, callback) {
},
// display info, prompt user and create progressbar
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) {
if (err) {
return waterfallCallback(err);
diff --git a/package.json b/package.json
index 5961b73..2544e37 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "badger-am",
- "version": "0.5.4",
+ "version": "0.6.0",
"license": "MIT",
"description": "audio manager",
"author": "Daniel Sommer ",