From 5f220204b362860b66863405bc78482f0931d4f0 Mon Sep 17 00:00:00 2001 From: velvettear Date: Fri, 24 Mar 2017 17:05:14 +0100 Subject: [PATCH] implemented basic functionality --- badger-am.js | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 169 insertions(+), 1 deletion(-) diff --git a/badger-am.js b/badger-am.js index 090ff6e..1e742f1 100755 --- a/badger-am.js +++ b/badger-am.js @@ -1 +1,169 @@ -#!/usr/bin/env node \ No newline at end of file +#!/usr/bin/env node + +// requirements +const os = require('os'); +const path = require('path'); +const fs = require('fs'); +const fse = require('fs-extra'); +const async = require('async'); +const commander = require('commander'); +const recursive = require('recursive-readdir'); +const metadata = require('musicmetadata'); +const progress = require('progress'); +const app = require('./package.json'); + +// general options +commander + .version(app.version) + .usage('[options] ') + .option('-c, --concurrency ', 'specify concurrency level', os.cpus().length); + +// conversion mode +commander + .command('convert ') + .description('convert .flac to .mp3 files') + .option('-b, --bitrate ', 'specify conversion bitrate', 320) + .action(function (input, output, options) { + console.log('--- CONVERT MODE ---'); + console.log('input: ' + input); + console.log('output: ' + output); + console.log('bitrate: ' + commander.options.bitrate); + console.log('conc: ' + commander.concurrency); + }); + +// sort mode +commander + .command('sort ') + .description('sort audio files by tags') + .option('-f, --format ', 'specify audio format (\'flac\', \'mp3\')', 'flac') + .action(sort); + +// parse command line arguments +commander.parse(process.argv); + +// functions +function sort(input, output, options) { + const start = process.hrtime(); + const concurrency = commander.concurrency; + console.log('--- SORT MODE ---'); + console.log('concurrency: ' + concurrency); + // get files in input directory + recursive(input, [ignoreFilter], function (err, files) { + if (err) { + exit(err); + } + // display progressbar + const bar = createProgressBar(files.length); + // handle each file + async.eachLimit(files, concurrency, function (file, eachCallback) { + handleSource(output, file, function (err) { + bar.tick(); + if (err) { + return eachCallback(err); + } + eachCallback(); + }); + }, function (err) { + const diff = process.hrtime(start); + console.log('done after ' + (diff[0] * 1000 + diff[1] / 1000000) + ' milliseconds'); + exit(err); + }); + }); + + function ignoreFilter(file, stats) { + return !stats.isDirectory() && path.extname(file).indexOf(options.format) == -1; + } +} + +function exit(err) { + if (err) { + console.error(err); + process.exit(1); + } + console.log('DONE'); + process.exit(0); +} + +function handleSource(output, file, callback) { + async.waterfall([ + function (asyncCallback) { + extractMetadata(file, asyncCallback) + }, + function (metadata, asyncCallback) { + pathFromMetadata(output, metadata, asyncCallback); + } + // TODO: create output directory, append file extension and move file + ], function (err, results) { + if (err) { + return callback(err); + } + callback(null, results); + }); +} + +function extractMetadata(file, callback) { + const stream = fs.createReadStream(file); + metadata(stream, function (err, metadata) { + if (err) { + return callback(err); + } + stream.close(); + callback(null, metadata) + }); +} + +function pathFromMetadata(output, metadata, callback) { + // define directory + let directory = path.normalize(path.join(output)); + if (metadata.albumartist && metadata.albumartist.length > 0) { + let tmp; + const artistCount = metadata.albumartist.length; + for (let counter = 0; counter < artistCount; counter++) { + if (counter > 0) { + tmp += ' - ' + metadata.albumartist[counter]; + } else { + tmp = metadata.albumartist[counter]; + } + } + directory = path.join(directory, tmp); + } else { + directory = path.join(directory, metadata.artist[0]); + } + if (metadata.album) { + directory = path.join(directory, metadata.album); + } + // define filename + let file = ''; + if (metadata.disk.no) { + file += frontFill(metadata.disk.no, '0', 2); + } + if (metadata.track.no) { + if (file) { + file += '-' + frontFill(metadata.track.no, '0', 2) + ' '; + } else { + file += frontFill(metadata.track.no, '0', 2) + ' '; + } + } + if (metadata.artist && metadata.albumartist.length > 0) { + file += metadata.artist[0] + ' - '; + } + if (metadata.title) { + file += metadata.title; + } + + callback(null, directory, file); +} + +function frontFill(string, fill, length) { + while (string.length > length) { + string = fill + string; + } + return string; +} + +function createProgressBar(total) { + return new progress(':bar | progress: :current/:total (:percent) | elapsed: :elapseds | eta: :etas', { + total: total, + width: 32 + }); +} \ No newline at end of file