diff --git a/dist/cli.js b/dist/cli.js index 27bf80d..74d8058 100644 --- a/dist/cli.js +++ b/dist/cli.js @@ -57,7 +57,7 @@ exports['default'] = function () { console.log('volume: ' + Math.floor(vol * 100)); } - (0, _keypress2['default'])(process.stdin); + _keypress2['default'](process.stdin); var paused = false; diff --git a/dist/cli.js.map b/dist/cli.js.map index 6395964..ad536f3 100644 --- a/dist/cli.js.map +++ b/dist/cli.js.map @@ -1 +1 @@ -{"version":3,"sources":["../libs/cli.js"],"names":[],"mappings":"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","file":"cli.js","sourcesContent":["import path from 'path'\nimport keypress from 'keypress'\nimport Player from '../dist/player'\n\nexport default function() {\n var command = process.argv[2]\n if (!command)\n return\n\n var songs = process.argv.splice(3)\n if (!songs || songs.length === 0)\n return\n\n var player = new Player(format(songs))\n\n try {\n player[command]()\n } catch (err) {\n console.log(err)\n }\n\n function format(songs) {\n return songs.map((songPath) => {\n if (isAbs(songPath))\n return songPath\n\n return path.join(process.cwd(), songPath)\n })\n }\n\n function isAbs(str) {\n if (str.indexOf('http') === 0 || str.indexOf('https') === 0)\n return true\n\n var beginWith = str.charAt(0)\n if (beginWith === '~' || beginWith == '/')\n return true\n\n return false\n }\n\n var vol = 1\n\n function updateVolume() {\n player.setVolume(vol)\n console.log('volume: ' + Math.floor(vol * 100))\n }\n\n keypress(process.stdin);\n\n var paused = false\n\n process.stdin.on('keypress', function (ch, key) {\n if (key && key.ctrl && key.name == 'c') {\n process.exit(0)\n }\n if (key && key.name == 'space') {\n player.pause()\n if(!paused)\n console.log('paused')\n else\n console.log('resuming')\n paused = !paused\n }\n if (key && key.name == 'x') {\n player.stop()\n console.log('stopped')\n }\n if (key && key.name == 's') {\n player.play()\n console.log('playing')\n }\n if (key && key.name == 'up') {\n vol += 0.1;\n if(vol > 1) {\n vol = 1\n }\n updateVolume()\n }\n if (key && key.name == 'down') {\n vol -= 0.1;\n if(vol < 0) {\n vol = 0\n }\n updateVolume()\n }\n });\n\n process.stdin.setRawMode(true)\n process.stdin.resume()\n\n console.log('press \"x\" to stop, press \"s\" to play, press \"space\" to pause / resume')\n console.log('press \"Up\" to increase volume, press \"Down\" to decrease volume')\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../libs/cli.js"],"names":[],"mappings":"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","file":"libs/cli.js","sourcesContent":["import path from 'path'\nimport keypress from 'keypress'\nimport Player from '../dist/player'\n\nexport default function() {\n var command = process.argv[2]\n if (!command)\n return\n\n var songs = process.argv.splice(3)\n if (!songs || songs.length === 0)\n return\n\n var player = new Player(format(songs))\n\n try {\n player[command]()\n } catch (err) {\n console.log(err)\n }\n\n function format(songs) {\n return songs.map((songPath) => {\n if (isAbs(songPath))\n return songPath\n\n return path.join(process.cwd(), songPath)\n })\n }\n\n function isAbs(str) {\n if (str.indexOf('http') === 0 || str.indexOf('https') === 0)\n return true\n\n var beginWith = str.charAt(0)\n if (beginWith === '~' || beginWith == '/')\n return true\n\n return false\n }\n\n var vol = 1\n\n function updateVolume() {\n player.setVolume(vol)\n console.log('volume: ' + Math.floor(vol * 100))\n }\n\n keypress(process.stdin);\n\n var paused = false\n\n process.stdin.on('keypress', function (ch, key) {\n if (key && key.ctrl && key.name == 'c') {\n process.exit(0)\n }\n if (key && key.name == 'space') {\n player.pause()\n if(!paused)\n console.log('paused')\n else\n console.log('resuming')\n paused = !paused\n }\n if (key && key.name == 'x') {\n player.stop()\n console.log('stopped')\n }\n if (key && key.name == 's') {\n player.play()\n console.log('playing')\n }\n if (key && key.name == 'up') {\n vol += 0.1;\n if(vol > 1) {\n vol = 1\n }\n updateVolume()\n }\n if (key && key.name == 'down') {\n vol -= 0.1;\n if(vol < 0) {\n vol = 0\n }\n updateVolume()\n }\n });\n\n process.stdin.setRawMode(true)\n process.stdin.resume()\n\n console.log('press \"x\" to stop, press \"s\" to play, press \"space\" to pause / resume')\n console.log('press \"Up\" to increase volume, press \"Down\" to decrease volume')\n}\n"]} \ No newline at end of file diff --git a/dist/player.js b/dist/player.js index 0187436..ed626fe 100644 --- a/dist/player.js +++ b/dist/player.js @@ -1,11 +1,3 @@ -/** -* -* Command line interface mp3 player based on Node.js -* @Author: [turingou](http://guoyu.me) -* @Created: [2013/07/20] -* -**/ - 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -14,13 +6,23 @@ Object.defineProperty(exports, '__esModule', { var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); -var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; +var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { desc = parent = getter = undefined; _again = false; var object = _x2, + property = _x3, + receiver = _x4; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } -function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } + +/** +* +* Command line interface mp3 player based on Node.js +* @Author: [turingou](http://guoyu.me) +* @Created: [2013/07/20] +* +**/ var _fs = require('fs'); @@ -30,7 +32,7 @@ var _path = require('path'); var _path2 = _interopRequireDefault(_path); -var _util = require("util"); +var _util = require('util'); var _util2 = _interopRequireDefault(_util); @@ -60,7 +62,7 @@ var _pcmVolume = require('pcm-volume'); var _pcmVolume2 = _interopRequireDefault(_pcmVolume); -var _events = require("events"); +var _events = require('events'); var _utils = require('./utils'); @@ -69,9 +71,8 @@ var defaults = { 'cache': false, 'stream': false, 'shuffle': false, - 'downloads': (0, _home2['default'])(), - 'http_proxy': process.env.HTTP_PROXY || process.env.http_proxy || null -}; + 'downloads': _home2['default'](), + 'http_proxy': process.env.HTTP_PROXY || process.env.http_proxy || null }; /** * [Class Player] @@ -80,8 +81,6 @@ var defaults = { */ var Player = (function (_EventEmitter) { - _inherits(Player, _EventEmitter); - function Player(songs, params) { _classCallCheck(this, Player); @@ -94,14 +93,16 @@ var Player = (function (_EventEmitter) { this.history = []; this.paused = false; this.options = _underscore2['default'].extend(defaults, params); - this._list = (0, _utils.format)(songs || [], this.options.src); + this._list = _utils.format(songs || [], this.options.src); if (!this._list || !this._list.length) this._list = []; } - // Enable or disable a option + _inherits(Player, _EventEmitter); _createClass(Player, [{ key: 'enable', + + // Enable or disable a option value: function enable(k) { this.options[k] = true; return this; @@ -112,12 +113,32 @@ var Player = (function (_EventEmitter) { this.options[k] = false; return this; } + }, { + key: 'list', /** * [Lists songs in the playlist, * Displays the src for each song returned in array, * Access with prop `player.list`] */ + get: function () { + var _this2 = this; + + if (!this._list) return; + + return this._list.map(function (el) { + return el[_this2.options.src]; + }); + } + }, { + key: 'playing', + + // Get the lastest playing song + get: function () { + if (!this.history.length) return null; + + return this._list[this.history[this.history.length - 1]]; + } }, { key: 'play', @@ -126,9 +147,9 @@ var Player = (function (_EventEmitter) { * @param {Number} index [the selected index of first played song] */ value: function play() { - var _this = this; + var _this3 = this; - var index = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; + var index = arguments[0] === undefined ? 0 : arguments[0]; if (this._list.length <= 0) return; if (!_underscore2['default'].isNumber(index)) index = 0; @@ -139,16 +160,16 @@ var Player = (function (_EventEmitter) { this.paused = false; this.read(song[this.options.src], function (err, pool) { - if (err) return _this.emit('error', err); + if (err) return _this3.emit('error', err); - _this.meta(pool, function (err, data) { + _this3.meta(pool, function (err, data) { if (!err) song.meta = data; }); - _this.lameStream = new _lame2['default'].Decoder(); + _this3.lameStream = new _lame2['default'].Decoder(); - pool.pipe(_this.lameStream).once('format', onPlaying).once('finish', function () { - return _this.next(); + pool.pipe(_this3.lameStream).once('format', onPlaying).once('finish', function () { + return _this3.next(); }); function onPlaying(f) { @@ -158,8 +179,7 @@ var Player = (function (_EventEmitter) { self.speaker = { 'readableStream': this, - 'Speaker': speaker - }; + 'Speaker': speaker }; self.emit('playing', song); self.history.push(index); @@ -175,45 +195,45 @@ var Player = (function (_EventEmitter) { return this; } + }, { + key: 'setVolume', /** * [Set playback volume] * @param {Number} volume [Volume level percentage 0.0-1.0] */ - }, { - key: 'setVolume', value: function setVolume(volume) { if (!this.speaker) return; this.speaker.Speaker.setVolume(volume); } + }, { + key: 'read', /** * [Read MP3 src and check if we're going to download it.] * @param {String} src [MP3 file src, would be local path or URI (http/https)] * @param {Function} callback [callback with err and file stream] */ - }, { - key: 'read', value: function read(src, callback) { var isLocal = !(src.indexOf('http') == 0 || src.indexOf('https') == 0); // Read local file stream if not a valid URI if (isLocal) return callback(null, _fs2['default'].createReadStream(src)); - var file = _path2['default'].join(this.options.downloads, (0, _utils.fetchName)(src)); + var file = _path2['default'].join(this.options.downloads, _utils.fetchName(src)); if (_fs2['default'].existsSync(file)) return callback(null, _fs2['default'].createReadStream(file)); this.download(src, callback); } + }, { + key: 'pause', /** * [Pause or resume audio] * @return {player} this */ - }, { - key: 'pause', value: function pause() { if (this.paused) { this.speaker.Speaker = new _pcmVolume2['default'](); @@ -227,14 +247,14 @@ var Player = (function (_EventEmitter) { this.paused = !this.paused; return this; } + }, { + key: 'stop', /** * [Stop playing and unpipe stream. * No params for now.] * @return {Bool} [always `false`] */ - }, { - key: 'stop', value: function stop() { if (!this.speaker) return; @@ -244,18 +264,18 @@ var Player = (function (_EventEmitter) { return; } + }, { + key: 'next', /** * [Stop playing and switch to next song, * if there is no next song, trigger a `No next song` error event] * @return {player} this */ - }, { - key: 'next', value: function next() { var list = this._list; var current = this.playing; - var nextIndex = this.options.shuffle ? (0, _utils.chooseRandom)(_underscore2['default'].difference(list, [current._id])) : current._id + 1; + var nextIndex = this.options.shuffle ? _utils.chooseRandom(_underscore2['default'].difference(list, [current._id])) : current._id + 1; if (nextIndex >= list.length) { this.emit('error', 'No next song was found'); @@ -268,34 +288,34 @@ var Player = (function (_EventEmitter) { return this; } + }, { + key: 'add', /** * [Add a new song to the playlist, * If provided `song` is a String, it will be converted to a `Song` Object.] * @param {String|Object} song [src URI of new song or the object of new song.] */ - }, { - key: 'add', value: function add(song) { var latest = _underscore2['default'].isObject(song) ? song : {}; latest._id = this._list.length; if (_underscore2['default'].isString(song)) { - latest._name = (0, _utils.splitName)(song); + latest._name = _utils.splitName(song); latest[this.options.src] = song; } this._list.push(latest); } + }, { + key: 'download', /** * [Download a mp3 file from its URI] * @param {String} src [the src URI of mp3 file] * @param {Function} callback [callback with err and file stream] */ - }, { - key: 'download', value: function download(src, callback) { var self = this; var called = false; @@ -335,7 +355,7 @@ var Player = (function (_EventEmitter) { if (!isSave) return callback(null, pool); // Save this stream as file in download directory - var file = _path2['default'].join(self.options.downloads, (0, _utils.fetchName)(src)); + var file = _path2['default'].join(self.options.downloads, _utils.fetchName(src)); self.emit('downloading', src); pool.pipe(_fs2['default'].createWriteStream(file)); @@ -348,12 +368,12 @@ var Player = (function (_EventEmitter) { if (!called) callback(err); } } - - // Fetch metadata from local or remote mp3 stream }, { key: 'meta', + + // Fetch metadata from local or remote mp3 stream value: function meta(stream, callback) { - var _this2 = this; + var _this4 = this; try { var mm = require('musicmetadata'); @@ -366,16 +386,16 @@ var Player = (function (_EventEmitter) { }; stream.on('error', function (err) { - return _this2.emit('error', '出错了 ' + err.code + ': ' + err.path); + return _this4.emit('error', '出错了 ' + err.code + ': ' + err.path); }); return mm(stream, options, callback); } + }, { + key: 'progress', // Format metadata with template // And output to `stdout` - }, { - key: 'progress', value: function progress(metadata) { var total = 70; var info = metadata.title; @@ -390,7 +410,7 @@ var Player = (function (_EventEmitter) { // Move cursor to beginning of line stdout.cursorTo(0); - stdout.write((0, _utils.getProgress)(total - dots, total, info)); + stdout.write(_utils.getProgress(total - dots, total, info)); setTimeout(callback, speed); @@ -403,26 +423,6 @@ var Player = (function (_EventEmitter) { stdout.cursorTo(0); }); } - }, { - key: 'list', - get: function get() { - var _this3 = this; - - if (!this._list) return; - - return this._list.map(function (el) { - return el[_this3.options.src]; - }); - } - - // Get the lastest playing song - }, { - key: 'playing', - get: function get() { - if (!this.history.length) return null; - - return this._list[this.history[this.history.length - 1]]; - } }]); return Player; diff --git a/dist/player.js.map b/dist/player.js.map index 07fa321..baf73d2 100644 --- a/dist/player.js.map +++ b/dist/player.js.map @@ -1 +1 @@ -{"version":3,"sources":["../libs/player.js"],"names":[],"mappings":"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","file":"player.js","sourcesContent":["/**\n*\n* Command line interface mp3 player based on Node.js\n* @Author: [turingou](http://guoyu.me)\n* @Created: [2013/07/20]\n*\n**/\n\nimport fs from 'fs'\nimport path from 'path'\nimport util from \"util\"\nimport { http, https } from 'follow-redirects'\nimport home from 'home'\nimport lame from 'lame'\nimport _ from 'underscore'\nimport Speaker from 'speaker'\nimport PoolStream from 'pool_stream'\nimport Volume from 'pcm-volume'\nimport { EventEmitter } from \"events\"\nimport { fetchName, splitName, format, getProgress, chooseRandom } from './utils'\n\nconst defaults = {\n 'src': 'src',\n 'cache': false,\n 'stream': false,\n 'shuffle': false,\n 'downloads': home(),\n 'http_proxy': process.env.HTTP_PROXY || process.env.http_proxy || null,\n}\n\n/**\n * [Class Player]\n * @param {Array|String} songs [A list of songs or a single song URI string.]\n * @param {Object} params [Optional options when init a instance]\n */\nexport default class Player extends EventEmitter {\n constructor(songs, params) {\n// if (!songs)\n// return\n\n // Inherits eventEmitter\n super()\n\n this.history = []\n this.paused = false\n this.options = _.extend(defaults, params)\n this._list = format(songs || [], this.options.src)\n if (!this._list || !this._list.length) this._list = []\n }\n\n // Enable or disable a option\n enable(k) {\n this.options[k] = true\n return this\n }\n\n disable(k) {\n this.options[k] = false\n return this\n }\n\n /**\n * [Lists songs in the playlist,\n * Displays the src for each song returned in array,\n * Access with prop `player.list`]\n */\n get list() {\n if (!this._list)\n return\n\n return this._list.map(el => el[this.options.src])\n }\n\n // Get the lastest playing song\n get playing() {\n if (!this.history.length)\n return null\n\n return this._list[this.history[this.history.length - 1]]\n }\n\n /**\n * [Play a MP3 encoded audio file]\n * @param {Number} index [the selected index of first played song]\n */\n play(index = 0) {\n if (this._list.length <= 0)\n return\n if (!_.isNumber(index))\n index = 0\n if (index >= this._list.length) index = this._list.length - 1;\n\n let self = this\n let song = this._list[index]\n\n this.paused = false\n this.read(song[this.options.src], (err, pool) => {\n if (err)\n return this.emit('error', err)\n\n this.meta(pool, (err, data) => {\n if (!err) \n song.meta = data\n })\n\n this.lameStream = new lame.Decoder()\n\n pool\n .pipe(this.lameStream)\n .once('format', onPlaying)\n .once('finish', () => this.next())\n\n function onPlaying(f) {\n self.lameFormat = f\n var speaker = new Volume()\n speaker.pipe(new Speaker(self.lameFormat))\n\n self.speaker = {\n 'readableStream': this,\n 'Speaker': speaker,\n }\n\n self.emit('playing', song)\n self.history.push(index)\n\n // This is where the song acturaly played end,\n // can't trigger playend event here cause\n // unpipe will fire this speaker's close event.\n this.pipe(speaker)\n .once('close', () => \n self.emit('playend', song))\n }\n })\n\n return this\n }\n\n /**\n * [Set playback volume]\n * @param {Number} volume [Volume level percentage 0.0-1.0]\n */\n setVolume(volume) {\n if(!this.speaker)\n return;\n\n this.speaker.Speaker.setVolume(volume);\n }\n\n /**\n * [Read MP3 src and check if we're going to download it.]\n * @param {String} src [MP3 file src, would be local path or URI (http/https)]\n * @param {Function} callback [callback with err and file stream]\n */\n read(src, callback) {\n var isLocal = !(src.indexOf('http') == 0 || src.indexOf('https') == 0)\n\n // Read local file stream if not a valid URI\n if (isLocal)\n return callback(null, fs.createReadStream(src))\n\n var file = path.join(\n this.options.downloads,\n fetchName(src)\n )\n\n if (fs.existsSync(file))\n return callback(null, fs.createReadStream(file))\n\n this.download(src, callback)\n }\n\n /**\n * [Pause or resume audio]\n * @return {player} this\n */\n pause() {\n if (this.paused) {\n this.speaker.Speaker = new Volume()\n this.speaker.Speaker.pipe(new Speaker(this.lameFormat))\n\n this.lameStream.pipe(this.speaker.Speaker)\n } else {\n this.speaker.Speaker.end()\n }\n\n this.paused = !this.paused\n return this\t\n }\n\n /**\n * [Stop playing and unpipe stream.\n * No params for now.]\n * @return {Bool} [always `false`]\n */\n stop() {\n if (!this.speaker)\n return\n\n this.speaker\n .readableStream\n .unpipe()\n\n this.speaker\n .Speaker\n .end()\n\n return\n }\n\n /**\n * [Stop playing and switch to next song,\n * if there is no next song, trigger a `No next song` error event]\n * @return {player} this\n */\n next() {\n let list = this._list\n let current = this.playing\n let nextIndex = this.options.shuffle ? \n chooseRandom(_.difference(list, [current._id])) :\n current._id + 1\n\n if (nextIndex >= list.length) {\n this.emit('error', 'No next song was found')\n this.emit('finish', current)\n return this\n }\n\n this.stop()\n this.play(nextIndex)\n\n return this\n }\n\n /**\n * [Add a new song to the playlist,\n * If provided `song` is a String, it will be converted to a `Song` Object.]\n * @param {String|Object} song [src URI of new song or the object of new song.]\n */\n add(song) {\n var latest = _.isObject(song) ? song : {}\n\n latest._id = this._list.length\n\n if (_.isString(song)) {\n latest._name = splitName(song)\n latest[this.options.src] = song\n }\n\n this._list.push(latest)\n }\n\n /**\n * [Download a mp3 file from its URI]\n * @param {String} src [the src URI of mp3 file]\n * @param {Function} callback [callback with err and file stream]\n */\n download(src, callback) {\n var self = this\n var called = false\n var proxyReg = /http:\\/\\/((?:\\d{1,3}\\.){3}\\d{1,3}):(\\d+)/\n var http_proxy = self.options.http_proxy\n var request = src.indexOf('https') === 0 ? https : http\n var query = src\n\n if (http_proxy && proxyReg.test(http_proxy)) {\n var proxyGroup = http_proxy.match(proxyReg)\n query = {}\n query.path = src\n query.host = proxyGroup[1]\n query.port = proxyGroup[2]\n }\n\n request\n .get(query, responseHandler)\n .once('error', errorHandler)\n\n function responseHandler(res) {\n called = true\n\n var isOk = (res.statusCode === 200)\n var isAudio = (res.headers['content-type'].indexOf('audio/mpeg') > -1)\n var isSave = self.options.cache\n var isStream = self.options.stream\n\n if (!isOk)\n return callback(new Error('Resource invalid'))\n if (isStream)\n return callback(null, res)\n if (!isAudio)\n return callback(new Error('Resource type is unsupported'))\n\n // Create a pool\n var pool = new PoolStream()\n // Pipe into memory\n res.pipe(pool)\n\n // Check if we're going to save this stream\n if (!isSave)\n return callback(null, pool)\n\n // Save this stream as file in download directory\n var file = path.join(\n self.options.downloads,\n fetchName(src)\n )\n\n self.emit('downloading', src)\n pool.pipe(fs.createWriteStream(file))\n\n // Callback the pool\n callback(null, pool)\n }\n\n function errorHandler(err) {\n if (!called)\n callback(err)\n }\n }\n\n // Fetch metadata from local or remote mp3 stream\n meta(stream, callback) {\n try {\n var mm = require('musicmetadata')\n } catch (err) {\n return callback(err)\n }\n\n var options = {\n 'duration': true\n }\n\n stream.on('error', err => \n this.emit('error', `出错了 ${err.code}: ${err.path}`))\n\n return mm(stream, options, callback)\n }\n\n // Format metadata with template \n // And output to `stdout`\n progress(metadata) {\n var total = 70\n var info = metadata.title\n var duration = parseInt(metadata.duration)\n var dots = total - 1\n var speed = (duration * 1000) / total\n var stdout = process.stdout\n\n require('async').doWhilst(\n (callback) => {\n // Clear console\n stdout.write('\\u001B[2J\\u001B[0;0f')\n\n // Move cursor to beginning of line\n stdout.cursorTo(0)\n stdout.write(getProgress(total - dots, total, info))\n\n setTimeout(callback, speed)\n\n dots--\n },\n () => dots > 0,\n (done) => {\n stdout.moveCursor(0, -1)\n stdout.clearLine()\n stdout.cursorTo(0)\n }\n )\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../libs/player.js"],"names":[],"mappings":"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","file":"libs/player.js","sourcesContent":["/**\n*\n* Command line interface mp3 player based on Node.js\n* @Author: [turingou](http://guoyu.me)\n* @Created: [2013/07/20]\n*\n**/\n\nimport fs from 'fs'\nimport path from 'path'\nimport util from \"util\"\nimport { http, https } from 'follow-redirects'\nimport home from 'home'\nimport lame from 'lame'\nimport _ from 'underscore'\nimport Speaker from 'speaker'\nimport PoolStream from 'pool_stream'\nimport Volume from 'pcm-volume'\nimport { EventEmitter } from \"events\"\nimport { fetchName, splitName, format, getProgress, chooseRandom } from './utils'\n\nconst defaults = {\n 'src': 'src',\n 'cache': false,\n 'stream': false,\n 'shuffle': false,\n 'downloads': home(),\n 'http_proxy': process.env.HTTP_PROXY || process.env.http_proxy || null,\n}\n\n/**\n * [Class Player]\n * @param {Array|String} songs [A list of songs or a single song URI string.]\n * @param {Object} params [Optional options when init a instance]\n */\nexport default class Player extends EventEmitter {\n constructor(songs, params) {\n// if (!songs)\n// return\n\n // Inherits eventEmitter\n super()\n\n this.history = []\n this.paused = false\n this.options = _.extend(defaults, params)\n this._list = format(songs || [], this.options.src)\n if (!this._list || !this._list.length) this._list = []\n }\n\n // Enable or disable a option\n enable(k) {\n this.options[k] = true\n return this\n }\n\n disable(k) {\n this.options[k] = false\n return this\n }\n\n /**\n * [Lists songs in the playlist,\n * Displays the src for each song returned in array,\n * Access with prop `player.list`]\n */\n get list() {\n if (!this._list)\n return\n\n return this._list.map(el => el[this.options.src])\n }\n\n // Get the lastest playing song\n get playing() {\n if (!this.history.length)\n return null\n\n return this._list[this.history[this.history.length - 1]]\n }\n\n /**\n * [Play a MP3 encoded audio file]\n * @param {Number} index [the selected index of first played song]\n */\n play(index = 0) {\n if (this._list.length <= 0)\n return\n if (!_.isNumber(index))\n index = 0\n if (index >= this._list.length) index = this._list.length - 1;\n\n let self = this\n let song = this._list[index]\n\n this.paused = false\n this.read(song[this.options.src], (err, pool) => {\n if (err)\n return this.emit('error', err)\n\n this.meta(pool, (err, data) => {\n if (!err) \n song.meta = data\n })\n\n this.lameStream = new lame.Decoder()\n\n pool\n .pipe(this.lameStream)\n .once('format', onPlaying)\n .once('finish', () => this.next())\n\n function onPlaying(f) {\n self.lameFormat = f\n var speaker = new Volume()\n speaker.pipe(new Speaker(self.lameFormat))\n\n self.speaker = {\n 'readableStream': this,\n 'Speaker': speaker,\n }\n\n self.emit('playing', song)\n self.history.push(index)\n\n // This is where the song acturaly played end,\n // can't trigger playend event here cause\n // unpipe will fire this speaker's close event.\n this.pipe(speaker)\n .once('close', () => \n self.emit('playend', song))\n }\n })\n\n return this\n }\n\n /**\n * [Set playback volume]\n * @param {Number} volume [Volume level percentage 0.0-1.0]\n */\n setVolume(volume) {\n if(!this.speaker)\n return;\n\n this.speaker.Speaker.setVolume(volume);\n }\n\n /**\n * [Read MP3 src and check if we're going to download it.]\n * @param {String} src [MP3 file src, would be local path or URI (http/https)]\n * @param {Function} callback [callback with err and file stream]\n */\n read(src, callback) {\n var isLocal = !(src.indexOf('http') == 0 || src.indexOf('https') == 0)\n\n // Read local file stream if not a valid URI\n if (isLocal)\n return callback(null, fs.createReadStream(src))\n\n var file = path.join(\n this.options.downloads,\n fetchName(src)\n )\n\n if (fs.existsSync(file))\n return callback(null, fs.createReadStream(file))\n\n this.download(src, callback)\n }\n\n /**\n * [Pause or resume audio]\n * @return {player} this\n */\n pause() {\n if (this.paused) {\n this.speaker.Speaker = new Volume()\n this.speaker.Speaker.pipe(new Speaker(this.lameFormat))\n\n this.lameStream.pipe(this.speaker.Speaker)\n } else {\n this.speaker.Speaker.end()\n }\n\n this.paused = !this.paused\n return this\t\n }\n\n /**\n * [Stop playing and unpipe stream.\n * No params for now.]\n * @return {Bool} [always `false`]\n */\n stop() {\n if (!this.speaker)\n return\n\n this.speaker\n .readableStream\n .unpipe()\n\n this.speaker\n .Speaker\n .end()\n\n return\n }\n\n /**\n * [Stop playing and switch to next song,\n * if there is no next song, trigger a `No next song` error event]\n * @return {player} this\n */\n next() {\n let list = this._list\n let current = this.playing\n let nextIndex = this.options.shuffle ? \n chooseRandom(_.difference(list, [current._id])) :\n current._id + 1\n\n if (nextIndex >= list.length) {\n this.emit('error', 'No next song was found')\n this.emit('finish', current)\n return this\n }\n\n this.stop()\n this.play(nextIndex)\n\n return this\n }\n\n /**\n * [Add a new song to the playlist,\n * If provided `song` is a String, it will be converted to a `Song` Object.]\n * @param {String|Object} song [src URI of new song or the object of new song.]\n */\n add(song) {\n var latest = _.isObject(song) ? song : {}\n\n latest._id = this._list.length\n\n if (_.isString(song)) {\n latest._name = splitName(song)\n latest[this.options.src] = song\n }\n\n this._list.push(latest)\n }\n\n /**\n * [Download a mp3 file from its URI]\n * @param {String} src [the src URI of mp3 file]\n * @param {Function} callback [callback with err and file stream]\n */\n download(src, callback) {\n var self = this\n var called = false\n var proxyReg = /http:\\/\\/((?:\\d{1,3}\\.){3}\\d{1,3}):(\\d+)/\n var http_proxy = self.options.http_proxy\n var request = src.indexOf('https') === 0 ? https : http\n var query = src\n\n if (http_proxy && proxyReg.test(http_proxy)) {\n var proxyGroup = http_proxy.match(proxyReg)\n query = {}\n query.path = src\n query.host = proxyGroup[1]\n query.port = proxyGroup[2]\n }\n\n request\n .get(query, responseHandler)\n .once('error', errorHandler)\n\n function responseHandler(res) {\n called = true\n\n var isOk = (res.statusCode === 200)\n var isAudio = (res.headers['content-type'].indexOf('audio/mpeg') > -1)\n var isSave = self.options.cache\n var isStream = self.options.stream\n\n if (!isOk)\n return callback(new Error('Resource invalid'))\n if (isStream)\n return callback(null, res)\n if (!isAudio)\n return callback(new Error('Resource type is unsupported'))\n\n // Create a pool\n var pool = new PoolStream()\n // Pipe into memory\n res.pipe(pool)\n\n // Check if we're going to save this stream\n if (!isSave)\n return callback(null, pool)\n\n // Save this stream as file in download directory\n var file = path.join(\n self.options.downloads,\n fetchName(src)\n )\n\n self.emit('downloading', src)\n pool.pipe(fs.createWriteStream(file))\n\n // Callback the pool\n callback(null, pool)\n }\n\n function errorHandler(err) {\n if (!called)\n callback(err)\n }\n }\n\n // Fetch metadata from local or remote mp3 stream\n meta(stream, callback) {\n try {\n var mm = require('musicmetadata')\n } catch (err) {\n return callback(err)\n }\n\n var options = {\n 'duration': true\n }\n\n stream.on('error', err => \n this.emit('error', `出错了 ${err.code}: ${err.path}`))\n\n return mm(stream, options, callback)\n }\n\n // Format metadata with template \n // And output to `stdout`\n progress(metadata) {\n var total = 70\n var info = metadata.title\n var duration = parseInt(metadata.duration)\n var dots = total - 1\n var speed = (duration * 1000) / total\n var stdout = process.stdout\n\n require('async').doWhilst(\n (callback) => {\n // Clear console\n stdout.write('\\u001B[2J\\u001B[0;0f')\n\n // Move cursor to beginning of line\n stdout.cursorTo(0)\n stdout.write(getProgress(total - dots, total, info))\n\n setTimeout(callback, speed)\n\n dots--\n },\n () => dots > 0,\n (done) => {\n stdout.moveCursor(0, -1)\n stdout.clearLine()\n stdout.cursorTo(0)\n }\n )\n }\n}\n"]} \ No newline at end of file diff --git a/dist/utils.js b/dist/utils.js index ecfc2b8..7b0c457 100644 --- a/dist/utils.js +++ b/dist/utils.js @@ -9,7 +9,7 @@ exports.chooseRandom = chooseRandom; exports.getProgress = getProgress; exports.splitName = splitName; -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _defineProperty(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } function fetchName(str) { var filename = str.substr(str.lastIndexOf('/') + 1); diff --git a/dist/utils.js.map b/dist/utils.js.map index 92c193e..f4db90b 100644 --- a/dist/utils.js.map +++ b/dist/utils.js.map @@ -1 +1 @@ -{"version":3,"sources":["../libs/utils.js"],"names":[],"mappings":";;;;;;;;;;;;;AAAO,SAAS,SAAS,CAAC,GAAG,EAAE;AAC7B,MAAI,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;;;AAGnD,MAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE;AAChC,QAAI,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AAC/B,YAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;GACpB;;AAED,SAAO,QAAQ,CAAA;CAChB;;AAEM,SAAS,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE;AACnC,MAAI,KAAK,GAAG,EAAE,CAAA;;AAEd,MAAI,OAAO,IAAI,AAAC,KAAK,QAAQ,EAAE;;;AAC7B,SAAK,CAAC,IAAI,iDACN,MAAM,EAAI,IAAI,gCAChB,KAAK,EAAE,CAAC,gCACR,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,gBACxB,CAAA;;AAEF,WAAO,KAAK,CAAA;GACb;;AAED,MAAI,CAAC,OAAO,CAAC,UAAC,IAAI,EAAE,KAAK,EAAK;;;;AAE5B,QAAI,OAAO,IAAI,AAAC,KAAK,QAAQ,EAAE;AAC7B,UAAI,CAAC,GAAG,GAAG,KAAK,CAAA;;AAEhB,UAAI,IAAI,CAAC,MAAM,CAAC,EACd,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;;AAEtC,WAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAChB,aAAM;KACP;;;AAGD,SAAK,CAAC,IAAI,mDACN,MAAM,EAAI,IAAI,iCAChB,KAAK,EAAE,KAAK,iCACZ,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,iBACxB,CAAA;GACH,CAAC,CAAA;;AAEF,SAAO,KAAK,CAAA;CACb;;AAEM,SAAS,YAAY,CAAC,GAAG,EAAE;AAChC,MAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EACrB,OAAO,CAAC,CAAA;;AAEV,MAAI,GAAG,GAAG,CAAC,CAAA;AACX,MAAI,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAA;;AAExB,SAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,CAAA,AAAC,CAAC,GAAG,GAAG,CAAA;CACzD;;AAEM,SAAS,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE;AACtC,MAAI,GAAG,GAAG,EAAE,CAAA;AACZ,KAAG,IAAK,eAAe,GAAG,IAAI,AAAC,CAAA;AAC/B,KAAG,IAAI,KAAK,CAAA;;AAEZ,OAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EACxB,GAAG,IAAI,GAAG,CAAA;;AAEZ,OAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAC5B,GAAG,IAAI,GAAG,CAAA;;AAEZ,KAAG,IAAI,GAAG,CAAA;;AAEV,SAAO,GAAG,CAAA;CACX;;AAEM,SAAS,SAAS,CAAC,GAAG,EAAE;AAC7B,SAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAA;CAC5B","file":"utils.js","sourcesContent":["export function fetchName(str) {\n var filename = str.substr(str.lastIndexOf('/') + 1)\n\n // Escape URI like this: `http://domain.com/xxx.mp3?xcode=fasda`\n if (filename.indexOf('?') !== -1) {\n var parts = filename.split('?')\n filename = parts[0]\n }\n\n return filename\n}\n\nexport function format(list, srcKey) {\n var songs = []\n\n if (typeof(list) === 'string') {\n songs.push({\n [ srcKey ]: list,\n '_id': 0,\n '_name': splitName(list),\n })\n\n return songs\n }\n\n list.forEach((item, index) => {\n // If `songs` is a Map\n if (typeof(item) === 'object') {\n item._id = index\n\n if (item[srcKey])\n item._name = splitName(item[srcKey])\n\n songs.push(item)\n return\n }\n\n // If `songs` is a Array\n songs.push({\n [ srcKey ]: item,\n '_id': index,\n '_name': splitName(item)\n })\n })\n\n return songs\n}\n\nexport function chooseRandom(arr) {\n if (!arr || !arr.length)\n return 0\n\n let min = 0\n let max = arr.length - 1\n\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\nexport function getProgress(p, t, info) {\n var bar = ''\n bar += ('Now playing: ' + info)\n bar += '\\n['\n\n for (var i = 0; i < p; i++)\n bar += '>'\n\n for (var i = p; i < t - 1; i++)\n bar += ' '\n\n bar += ']'\n\n return bar\n}\n\nexport function splitName(str) {\n return str.split('/').pop()\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../libs/utils.js"],"names":[],"mappings":";;;;;QAAgB,SAAS,GAAT,SAAS;QAYT,MAAM,GAAN,MAAM;QAoCN,YAAY,GAAZ,YAAY;QAUZ,WAAW,GAAX,WAAW;QAgBX,SAAS,GAAT,SAAS;;;;AA1ElB,SAAS,SAAS,CAAC,GAAG,EAAE;AAC7B,MAAI,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;;;AAGnD,MAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE;AAChC,QAAI,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AAC/B,YAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;GACpB;;AAED,SAAO,QAAQ,CAAA;CAChB;;AAEM,SAAS,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE;AACnC,MAAI,KAAK,GAAG,EAAE,CAAA;;AAEd,MAAI,OAAO,IAAI,AAAC,KAAK,QAAQ,EAAE;;;AAC7B,SAAK,CAAC,IAAI,iDACN,MAAM,EAAI,IAAI,gCAChB,KAAK,EAAE,CAAC,gCACR,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,gBACxB,CAAA;;AAEF,WAAO,KAAK,CAAA;GACb;;AAED,MAAI,CAAC,OAAO,CAAC,UAAC,IAAI,EAAE,KAAK,EAAK;;;;AAE5B,QAAI,OAAO,IAAI,AAAC,KAAK,QAAQ,EAAE;AAC7B,UAAI,CAAC,GAAG,GAAG,KAAK,CAAA;;AAEhB,UAAI,IAAI,CAAC,MAAM,CAAC,EACd,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;;AAEtC,WAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAChB,aAAM;KACP;;;AAGD,SAAK,CAAC,IAAI,mDACN,MAAM,EAAI,IAAI,iCAChB,KAAK,EAAE,KAAK,iCACZ,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,iBACxB,CAAA;GACH,CAAC,CAAA;;AAEF,SAAO,KAAK,CAAA;CACb;;AAEM,SAAS,YAAY,CAAC,GAAG,EAAE;AAChC,MAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EACrB,OAAO,CAAC,CAAA;;AAEV,MAAI,GAAG,GAAG,CAAC,CAAA;AACX,MAAI,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAA;;AAExB,SAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,CAAA,AAAC,CAAC,GAAG,GAAG,CAAA;CACzD;;AAEM,SAAS,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE;AACtC,MAAI,GAAG,GAAG,EAAE,CAAA;AACZ,KAAG,IAAK,eAAe,GAAG,IAAI,AAAC,CAAA;AAC/B,KAAG,IAAI,KAAK,CAAA;;AAEZ,OAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EACxB,GAAG,IAAI,GAAG,CAAA;;AAEZ,OAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAC5B,GAAG,IAAI,GAAG,CAAA;;AAEZ,KAAG,IAAI,GAAG,CAAA;;AAEV,SAAO,GAAG,CAAA;CACX;;AAEM,SAAS,SAAS,CAAC,GAAG,EAAE;AAC7B,SAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAA;CAC5B","file":"libs/utils.js","sourcesContent":["export function fetchName(str) {\n var filename = str.substr(str.lastIndexOf('/') + 1)\n\n // Escape URI like this: `http://domain.com/xxx.mp3?xcode=fasda`\n if (filename.indexOf('?') !== -1) {\n var parts = filename.split('?')\n filename = parts[0]\n }\n\n return filename\n}\n\nexport function format(list, srcKey) {\n var songs = []\n\n if (typeof(list) === 'string') {\n songs.push({\n [ srcKey ]: list,\n '_id': 0,\n '_name': splitName(list),\n })\n\n return songs\n }\n\n list.forEach((item, index) => {\n // If `songs` is a Map\n if (typeof(item) === 'object') {\n item._id = index\n\n if (item[srcKey])\n item._name = splitName(item[srcKey])\n\n songs.push(item)\n return\n }\n\n // If `songs` is a Array\n songs.push({\n [ srcKey ]: item,\n '_id': index,\n '_name': splitName(item)\n })\n })\n\n return songs\n}\n\nexport function chooseRandom(arr) {\n if (!arr || !arr.length)\n return 0\n\n let min = 0\n let max = arr.length - 1\n\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\nexport function getProgress(p, t, info) {\n var bar = ''\n bar += ('Now playing: ' + info)\n bar += '\\n['\n\n for (var i = 0; i < p; i++)\n bar += '>'\n\n for (var i = p; i < t - 1; i++)\n bar += ' '\n\n bar += ']'\n\n return bar\n}\n\nexport function splitName(str) {\n return str.split('/').pop()\n}\n"]} \ No newline at end of file