From 525377f88c2c6cc32d758645b375f9e7292b3ae7 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Tue, 4 Oct 2016 10:29:30 +1300 Subject: [PATCH 01/96] Move changes to release-2.0 branch --- .eslintrc.json | 44 -- .gitignore | 30 +- .gitmodules | 3 + .travis.yml | 9 + LICENSE.md | 7 + binding.gyp | 22 + browser-direct.js | 15 - browser-stream.js | 22 - cli.js | 0 direct.js | 97 --- element.html | 1 - element.js | 44 -- index.js | 3 - package.json | 57 +- pull.js | 22 - readme.md | 63 +- src/binding.cpp | 196 ++++++ src/config/win/ia32/out123.h | 583 ++++++++++++++++ src/config/win/x64/out123.h | 583 ++++++++++++++++ src/mpg123.gyp | 161 +++++ src/pointer_wrapper.h | 29 + src/util/getopt.c | 1228 ++++++++++++++++++++++++++++++++++ src/util/getopt.h | 173 +++++ src/util/unistd.h | 52 ++ stream.js | 57 -- test.html | 29 - test.js | 181 ----- todo.md | 16 - 28 files changed, 3101 insertions(+), 626 deletions(-) delete mode 100644 .eslintrc.json create mode 100644 .gitmodules create mode 100644 LICENSE.md create mode 100644 binding.gyp delete mode 100644 browser-direct.js delete mode 100644 browser-stream.js delete mode 100644 cli.js delete mode 100644 direct.js delete mode 100644 element.html delete mode 100644 element.js delete mode 100644 index.js delete mode 100644 pull.js create mode 100644 src/binding.cpp create mode 100644 src/config/win/ia32/out123.h create mode 100644 src/config/win/x64/out123.h create mode 100644 src/mpg123.gyp create mode 100644 src/pointer_wrapper.h create mode 100644 src/util/getopt.c create mode 100644 src/util/getopt.h create mode 100644 src/util/unistd.h delete mode 100644 stream.js delete mode 100644 test.html delete mode 100644 test.js delete mode 100644 todo.md diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 3b2d996..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "env": { - "browser": true, - "node": true, - "commonjs": true, - "es6": true - }, - "extends": "eslint:recommended", - "rules": { - "strict": 2, - "indent": 0, - "linebreak-style": 0, - "quotes": 0, - "semi": 0, - "no-cond-assign": 1, - "no-console": 1, - "no-constant-condition": 1, - "no-duplicate-case": 1, - "no-empty": 1, - "no-ex-assign": 1, - "no-extra-boolean-cast": 1, - "no-extra-semi": 1, - "no-fallthrough": 1, - "no-func-assign": 1, - "no-global-assign": 1, - "no-implicit-globals": 2, - "no-inner-declarations": ["error", "functions"], - "no-irregular-whitespace": 2, - "no-loop-func": 1, - "no-multi-str": 1, - "no-mixed-spaces-and-tabs": 1, - "no-proto": 1, - "no-sequences": 1, - "no-throw-literal": 1, - "no-unmodified-loop-condition": 1, - "no-useless-call": 1, - "no-void": 1, - "no-with": 2, - "wrap-iife": 1, - "no-redeclare": 1, - "no-unused-vars": ["error", { "vars": "all", "args": "none" }], - "no-sparse-arrays": 1 - } -} diff --git a/.gitignore b/.gitignore index 95ccccf..e45e238 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,33 @@ git config --global core.excludesfile ~/.gitignore //update files since .ignore won't if already tracked git rm --cached +# Node GYP # +############ +/build + +# Binding # +########### +Makefile +Makefile.in +configure +config.h +config.status +config.h.in +config.log +config.cache +autom4te.cache +aclocal.m4 +libmpg123.pc +libout123.pc +libmpg123.spec +mpg123.spec +unix2dos +unix2dos.c +/libtool +/.Tpo +/.deps +/.libs + # Compiled source # ################### *.com @@ -91,6 +118,7 @@ bower_components .CVS intermediate publish +.vscode .idea .graphics _test @@ -104,5 +132,5 @@ tmp .netrwhist bundle.* -build + _demo \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..57019a1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/mpg123"] + path = src/mpg123 + url = https://github.com/audiojs/mpg123 diff --git a/.travis.yml b/.travis.yml index 9300167..4751737 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,15 @@ node_js: - "4" - "0.12" - "0.10" +addons: + apt: + packages: + - libgnome-keyring-dev + - g++-4.8 + sources: + - ubuntu-toolchain-r-test +env: + - CXX=g++-4.8 matrix: fast_finish: true allow_failures: diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..6f3ab14 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,7 @@ +Copyright (c) 2016 AudioJS + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/binding.gyp b/binding.gyp new file mode 100644 index 0000000..1489f30 --- /dev/null +++ b/binding.gyp @@ -0,0 +1,22 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'win_delay_load_hook': 'true', + 'sources': [ + 'src/binding.cpp', + 'src/util/getopt.c' + ], + 'include_dirs': [ + 'src/util', + 'src/mpg123/src', + 'src/mpg123/src/libmpg123', + 'src/mpg123/src/libout123', + ' { - ended = true; - write(true); - } - - return write; - - function write (chunk, cb) { - if (chunk == null || chunk === true || ended) { - ended = true; - cb && cb(true); - return; - } - - let buf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, format) : chunk; - speaker.write(buf, () => { - if (ended) { - speaker.close(); - speaker.end(); - return cb && cb(true); - } - cb && cb(null, chunk); - }); - } -} - -function createSink (opts) { - let ended = false; - - let sampleRate = opts.sampleRate || 44100; - let samplesPerFrame = opts.samplesPerFrame || 1024; - - let sink = Sink((data, cb) => { - if (ended || data == null || data == true) return cb && cb(true); - cb && setTimeout(cb, samplesPerFrame / sampleRate); - }); - - sink.end = () => { - ended = true; - sink(true); - } - - return sink; -} - - diff --git a/element.html b/element.html deleted file mode 100644 index a5d18b7..0000000 --- a/element.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/element.js b/element.js deleted file mode 100644 index 4ded7d0..0000000 --- a/element.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * html element - * - * Does not export anything as it is not a module, it is pre-cooked web-component. - * - * To make it work, browserify bundle first with dependencies: - * `browserify -r audio-element -r audio-speaker` - * and connect it before the import link: - * - * - * @module audio-speaker/element - */ -'use strict'; - -var Speaker = require('audio-speaker'); -var AudioElement = require('audio-element'); - - -/** - * Audio speaker element API - */ -var SpeakerProto = Object.create(AudioElement.prototype); - -SpeakerProto.createdCallback = function () { - this.stream = Speaker(); - - AudioElement.prototype.createdCallback.call(this); -}; - - -/** Meta */ -SpeakerProto.label = 'Speaker'; -SpeakerProto.thumbnail = ''; -SpeakerProto.description = 'Output the sound'; - - -/** Connection logic */ -SpeakerProto.numberOfOutputs = 0; -SpeakerProto.numberOfInputs = 1; - - -document.registerElement('audio-speaker', { - prototype: SpeakerProto -}); diff --git a/index.js b/index.js deleted file mode 100644 index 861c11e..0000000 --- a/index.js +++ /dev/null @@ -1,3 +0,0 @@ -/** @module audio-speaker */ -'use strict'; -module.exports = require('./direct'); diff --git a/package.json b/package.json index d59d229..d2a5d22 100644 --- a/package.json +++ b/package.json @@ -1,59 +1,32 @@ { "name": "audio-speaker", - "version": "1.4.3", - "description": "Output audio data to speaker in browser/node", - "main": "stream.js", + "version": "2.0.0", + "description": "Output PCM data to a device or library.", + "main": "lib/index.js", "scripts": { - "preversion": "npm run lint && npm run test", - "lint": "eslint *.js --ignore-pattern test*", - "test:browser": "budo test.js", - "test": "node test" + "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", - "url": "https://github.com/audiojs/audio-speaker" + "url": "git+https://github.com/audiojs/out.git" }, "keywords": [ + "PCM", + "output", "audio", "audiojs", - "pcm", - "speaker", - "web-audio", - "sound", - "sink" + "binding", + "native" ], - "browser": { - "./direct.js": "./browser-direct.js", - "./stream.js": "./browser-stream.js" - }, - "author": "Dima Yv ", + "author": "Connor Hartley (https://github.com/connorhartley)", "license": "MIT", "bugs": { - "url": "https://github.com/audiojs/audio-speaker/issues" - }, - "homepage": "https://github.com/audiojs/audio-speaker", - "devDependencies": { - "audio-buffer-utils": "^3.1.2", - "audio-context": "^0.1.0", - "audio-generator": "^2.0.1", - "eslint": "^3.4.0", - "insert-styles": "^1.2.1", - "pcm-util": "^2.0.2", - "pcm-volume": "^1.0.0", - "tst": "^1.1.8", - "wavefont": "^1.2.1" - }, - "optionalDependencies": { - "audio-sink": "^1.0.2", - "speaker": "^0.3.0" + "url": "https://github.com/audiojs/out/issues" }, + "homepage": "https://github.com/audiojs/out#readme", "dependencies": { - "audio-through": "^2.1.1", - "inherits": "^2.0.1", - "is-audio-buffer": "^1.0.1", - "pcm-util": "^2.0.3", - "pull-stream": "^3.4.5", - "web-audio-stream": "^2.1.2", - "xtend": "^4.0.1" + "bindings": "^1.2.1", + "debug": "^2.2.0", + "nan": "2.2.0" } } diff --git a/pull.js b/pull.js deleted file mode 100644 index 95c1b95..0000000 --- a/pull.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @module audio-speaker/pull - * - */ -'use strict'; - -const Writer = require('./direct'); -const drain = require('pull-stream/sinks/drain'); -const asyncMap = require('pull-stream/throughs/async-map'); -const pull = require('pull-stream/pull'); - - -module.exports = function PullSpeaker (opts) { - let sinkFn = Writer(opts); - let d = drain(); - - let sink = pull(asyncMap(sinkFn), d); - - sink.abort = d.abort; - - return sink; -} diff --git a/readme.md b/readme.md index e1fe16c..9c6f6bd 100644 --- a/readme.md +++ b/readme.md @@ -1,63 +1,22 @@ -#audio-speaker [![Build Status](https://travis-ci.org/audiojs/audio-speaker.svg?branch=master)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) +#audio-speaker [![Build Status](https://travis-ci.org/audiojs/audio-speaker.svg?branch=master)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/unstable.svg)](http://github.com/badges/stability-badges) -Output audio stream to speaker in node or browser. +Output audio stream natively in node or through Web Audio in the browser. -[![npm install audio-speaker](https://nodei.co/npm/audio-speaker.png?mini=true)](https://npmjs.org/package/audio-speaker/) +More documentation coming soon. +## Credits -### Use as a stream - -```js -var Speaker = require('audio-speaker/stream'); -var Generator = require('audio-generator/stream'); - -Generator(function (time) { - //panned unisson effect - var τ = Math.PI * 2; - return [Math.sin(τ * time * 441), Math.sin(τ * time * 439)]; -}) -.pipe(Speaker({ - //PCM input format defaults, optional. - //channels: 2, - //sampleRate: 44100, - //byteOrder: 'LE', - //bitDepth: 16, - //signed: true, - //float: false, - //interleaved: true, -})); -``` - -### Use as a pull-stream - -```js -const pull = require('pull-stream/pull'); -const speaker = require('audio-speaker/pull'); -const osc = require('audio-oscillator/pull'); - -pull(osc({frequency: 440}), speaker()); -``` - -### Use directly - -Speaker is [async-sink](https://github.com/audiojs/contributing/wiki/Streams-convention) with `fn(data, cb)` notation. - -```js -const createSpeaker = require('audio-speaker'); -const createGenerator = require('audio-generator'); - -let output = createSpeaker(); -let generate = createGenerator(t => Math.sin(t * Math.PI * 2 * 440)); - -(function loop (err, buf) { - let buffer = generate(); - output(buffer, loop); -})(); -``` +| ![connor][connor-avatar] | +| :---------------------------: | +| [Connor Hartley][connor-link] | #### Related +> [mpg123](https://github.com/audiojs/mpg123) - modifications to mpg123 to suit audio-speaker.
> [web-audio-stream](https://github.com/audiojs/web-audio-stream) — stream data to web-audio.
> [audio-through](http://npmjs.org/package/audio-through) — universal stream for processing audio.
> [node-speaker](http://npmjs.org/package/speaker) — output pcm stream to speaker in node.
> [audio-feeder](https://github.com/brion/audio-feeder) — cross-browser speaker for pcm data.
+ + [connor-avatar]: https://avatars0.githubusercontent.com/u/12867785?v=3&s=125 + [connor-link]: https://github.com/connorhartley diff --git a/src/binding.cpp b/src/binding.cpp new file mode 100644 index 0000000..7cc6476 --- /dev/null +++ b/src/binding.cpp @@ -0,0 +1,196 @@ +#include "pointer_wrapper.h" +#include "out123.h" + +using namespace node; +using namespace v8; + +namespace { + + struct write_req { + uv_work_t req; + out123_handle *ao; + unsigned char *buffer; + int length; + int done; + Nan::Callback *callback; + }; + + void result_callback(Nan::Callback *cb, int result); + + void write_async(uv_work_t *); + void write_after(uv_work_t *); + + NAN_METHOD(create) { + Nan::EscapableHandleScope scope; + + out123_handle *ao = out123_new(); + + if(!ao) { + fprintf(stderr, "Failed to initialize output handle."); + out123_del(ao); + } else if(out123_open(ao, NULL, NULL) != OUT123_OK) { + fprintf(stderr, "Failed to open output: %s", out123_strerror(ao)); + out123_del(ao); + } + + info.GetReturnValue().Set(scope.Escape(WrapPointer(&ao, static_cast(sizeof(&ao))))); + } + + NAN_METHOD(start) { + Nan::HandleScope scope; + + out123_handle *ao = UnwrapPointer(info[0]); + + long rate = (long) info[1]->Int32Value(); + int channels = info[2]->Int32Value(); + int encoding = info[3]->Int32Value(); + + int value = 0; + + if(out123_start(ao, rate, channels, encoding) && !ao) { + fprintf(stderr, "Failed to start output: %s", out123_strerror(ao)); + out123_del(ao); + value = 0; + } else { + value = 1; + } + + result_callback(new Nan::Callback(info[4].As()), value); + + info.GetReturnValue().SetUndefined(); + } + + NAN_METHOD(write) { + Nan::HandleScope scope; + + out123_handle *ao = UnwrapPointer(info[0]); + unsigned char *buffer = UnwrapPointer(info[1]); + int length = info[2]->Int32Value(); + + write_req *req = new write_req; + req->ao = ao; + req->buffer = buffer; + req->length = length; + req->done = 0; + req->callback = new Nan::Callback(info[3].As()); + + req->req.data = req; + + uv_queue_work(uv_default_loop(), &req->req, write_async, (uv_after_work_cb) write_after); + + info.GetReturnValue().SetUndefined(); + } + + NAN_METHOD(flush) { + Nan::HandleScope scope; + + out123_handle *ao = UnwrapPointer(info[0]); + + int value = 0; + + if(ao) { + out123_drain(ao); + value = 1; + } else { + value = 0; + } + + result_callback(new Nan::Callback(info[1].As()), value); + + info.GetReturnValue().SetUndefined(); + } + + NAN_METHOD(close) { + Nan::HandleScope scope; + + out123_handle *ao = UnwrapPointer(info[0]); + + int value = 0; + + if(ao) { + out123_close(ao); + value = 1; + } else { + value = 0; + } + + result_callback(new Nan::Callback(info[1].As()), value); + + info.GetReturnValue().SetUndefined(); + } + + void result_callback(Nan::Callback *callback, int result) { + Nan::HandleScope scope; + + Local argv[] = { + Nan::New(static_cast(result)) + }; + + callback->Call(1, argv); + } + + void write_async(uv_work_t *req) { + write_req *wreq = reinterpret_cast(req->data); + wreq->done = out123_play(wreq->ao, wreq->buffer, wreq->length); + } + + void write_after(uv_work_t *req) { + Nan::HandleScope scope; + + write_req *wreq = reinterpret_cast(req->data); + + Local argv[] = { + Nan::New(wreq->done) + }; + + wreq->callback->Call(1, argv); + + delete wreq->callback; + } + + void InitializeModule(Handle target) { + Nan::HandleScope scope; + + printf("Creating a test handler."); // Debug message. + + out123_handle *ao = out123_new(); + + long rate = 44100; + int channels = 2; + int encoding = MPG123_ENC_SIGNED_16; + int framesize = 1; + + if(!ao) { + fprintf(stderr, "Failed to initialize output handle."); + out123_del(ao); + } else if(out123_open(ao, NULL, NULL) != OUT123_OK) { + fprintf(stderr, "Failed to open output: %s", out123_strerror(ao)); + out123_del(ao); + } + + printf("Successfully created a test handler. Will destroy handler and continue normal operation."); // Debug message. + + #define CONST_INT(value) \ + Nan::ForceSet(target, Nan::New(#value).ToLocalChecked(), Nan::New(value), \ + static_cast(ReadOnly|DontDelete)); + + CONST_INT(MPG123_ENC_FLOAT_32); + CONST_INT(MPG123_ENC_FLOAT_64); + CONST_INT(MPG123_ENC_SIGNED_8); + CONST_INT(MPG123_ENC_UNSIGNED_8); + CONST_INT(MPG123_ENC_SIGNED_16); + CONST_INT(MPG123_ENC_UNSIGNED_16); + CONST_INT(MPG123_ENC_SIGNED_24); + CONST_INT(MPG123_ENC_UNSIGNED_24); + CONST_INT(MPG123_ENC_SIGNED_32); + CONST_INT(MPG123_ENC_UNSIGNED_32); + + Nan::SetMethod(target, "create", create); + Nan::SetMethod(target, "start", start); + Nan::SetMethod(target, "write", write); + Nan::SetMethod(target, "flush", flush); + Nan::SetMethod(target, "close", close); + } +} + +NODE_MODULE(binding, InitializeModule); \ No newline at end of file diff --git a/src/config/win/ia32/out123.h b/src/config/win/ia32/out123.h new file mode 100644 index 0000000..627df1a --- /dev/null +++ b/src/config/win/ia32/out123.h @@ -0,0 +1,583 @@ +/* + out123: audio output interface + + copyright 1995-2016 by the mpg123 project, + free software under the terms of the LGPL 2.1 + + see COPYING and AUTHORS files in distribution or http://mpg123.org + initially written as audio.h by Michael Hipp, reworked into out123 API + by Thomas Orgis +*/ + +#ifndef _OUT123_H_ +#define _OUT123_H_ + +/** \file out123.h The header file for the libout123 audio output facility. */ + +/* We only need size_t definition. */ +#include + +/* Common audio encoding specification, including a macro for getting + * size of encodined samples in bytes. Said macro is still hardcoded + * into out123_encsize(). Relying on this one may help an old program + * know sizes of encodings added to fmt123.h later on. + * If you don't care, just use the macro. + */ +#include + +/** A macro to check at compile time which set of API functions to expect. + * This should be incremented at least each time a new symbol is added + * to the header. + */ +#define OUT123_API_VERSION 1 + +/** Defines needed for MS Visual Studio(tm) DLL builds. + * Every public function must be prefixed with MPG123_EXPORT. When building + * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible + * for clients and includes it in the import library which is created together + * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which + * imports the functions from the DLL. + */ +#ifdef BUILD_MPG123_DLL +/* The dll exports. */ +#define MPG123_EXPORT __declspec(dllexport) +#else +#ifdef LINK_MPG123_DLL +/* The exe imports. */ +#define MPG123_EXPORT __declspec(dllimport) +#else +/* Nothing on normal/UNIX builds */ +#define MPG123_EXPORT +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup out123_api out123 library API + * This is out123, a library focused on continuous playback of audio streams + * via various platform-specific output methods. It glosses over details of + * the native APIs to give an interface close to simply writing data to a + * file. There might be the option to tune details like buffer (period) sizes + * and the number of them on the device side in future, but the focus of the + * library is to ease the use case of just getting that raw audio data out + * there, without interruptions. + * + * The basic idea is to create a handle with out123_new() and open a certain + * output device (using a certain driver module, possibly build-time defaults) + * with out123_open(). Now, you can query the output device for supported + * encodings for given rate and channel count with out123_get_encodings() and + * decide what to use for actually starting playback with out123_start(). + * + * Then, you just need to provide (interleaved pcm) data for playback with + * out123_play(), which will block when the device's buffers are full. You get + * your timing from that (instead of callbacks). If your program does the + * production of the audio data just a little bit faster than the playback, + * causing out123_play() to block ever so briefly, you're fine. + * + * You stop playback with out123_stop(), or just close the device and driver + * via out123_close(), or even just decide to drop it all and do out123_del() + * right away when you're done. + * + * There are other functions for specific needs, but the basic idea should be + * covered by the above. + @{ + */ + +/** Opaque structure for the libout123 handle. */ +struct out123_struct; +/** Typedef shortcut as preferrend name for the handle type. */ +typedef struct out123_struct out123_handle; + +/** Enumeration of codes for the parameters that it is possible to set/get. */ +enum out123_parms +{ + OUT123_FLAGS = 1 /**< integer, various flags, see enum out123_flags */ +, OUT123_PRELOAD /**< float, fraction of buffer to fill before playback */ +, OUT123_GAIN /**< integer, output device gain (module-specific) */ +, OUT123_VERBOSE /**< integer, verbosity to stderr, >= 0 */ +, OUT123_DEVICEBUFFER /**< + * float, length of device buffer in seconds; + * This might be ignored, might have only a loose relation to actual + * buffer sizes and latency, depending on output driver. Try to tune + * this before opening a device if you want to influcence latency or reduce + * dropouts. Value <= 0 uses some default, usually favouring stable playback + * over low latency. Values above 0.5 are probably too much. + */ +, OUT123_PROPFLAGS /**< integer, query driver/device property flags (r/o) */ +, OUT123_NAME /**< string, name of this instance (NULL restores default); + * The value returned by out123_getparam() might be different if the audio + * backend changed it (to be unique among clients, p.ex.). + * TODO: The name provided here is used as prefix in diagnostic messages. */ +}; + +/** Flags to tune out123 behaviour */ +enum out123_flags +{ + OUT123_HEADPHONES = 0x01 /**< output to headphones (if supported) */ +, OUT123_INTERNAL_SPEAKER = 0x02 /**< output to speaker (if supported) */ +, OUT123_LINE_OUT = 0x04 /**< output to line out (if supported) */ +, OUT123_QUIET = 0x08 /**< no printouts to standard error */ +, OUT123_KEEP_PLAYING = 0x10 /**< + * When this is set (default), playback continues in a loop when the device + * does not consume all given data at once. This happens when encountering + * signals (like SIGSTOP, SIGCONT) that cause interruption of the underlying + * functions. + * Note that this flag is meaningless when the optional buffer is employed, + * There, your program will always block until the buffer completely took + * over the data given to it via out123_play(), unless a communcation error + * arises. + */ +}; + +/** Read-only output driver/device property flags (OUT123_PROPFLAGS). */ +enum out123_propflags +{ + OUT123_PROP_LIVE = 0x01 /**< This is a live output, meaning that + * special care might be needed for pauses in playback (p.ex. stream + * of silence instead of interruption), as opposed to files on disk. + */ +, OUT123_PROP_PERSISTENT = 0x02 /**< This (live) output does not need + * special care for pauses (continues with silence itself), + * out123_pause() does nothing to the device. + */ +}; + +/** Create a new output handle. + * This only allocates and initializes memory, so the only possible + * error condition is running out of memory. + * \return pointer to new handle or NULL on error + */ +MPG123_EXPORT +out123_handle *out123_new(void); + +/** Delete output handle. + * This implies out123_close(). + */ +MPG123_EXPORT +void out123_del(out123_handle *ao); + +/** Error code enumeration + * API calls return a useful (positve) value or zero (OUT123_OK) on simple + * success. A negative value (-1 == OUT123_ERR) usually indicates that some + * error occured. Which one, that can be queried using out123_errcode() + * and friends. + */ +enum out123_error +{ + OUT123_ERR = -1 /**< generic alias for verbosity, always == -1 */ +, OUT123_OK = 0 /**< just a name for zero, not going to change */ +, OUT123_DOOM /**< dazzled, out of memory */ +, OUT123_BAD_DRIVER_NAME /**< bad driver name given */ +, OUT123_BAD_DRIVER /**< unspecified issue loading a driver */ +, OUT123_NO_DRIVER /**< no driver loaded */ +, OUT123_NOT_LIVE /**< no active audio device */ +, OUT123_DEV_PLAY /**< some device playback error */ +, OUT123_DEV_OPEN /**< error opening device */ +, OUT123_BUFFER_ERROR /**< + * Some (really unexpected) error in buffer infrastructure. + */ +, OUT123_MODULE_ERROR /**< basic failure in module loading */ +, OUT123_ARG_ERROR /**< some bad function arguments supplied */ +, OUT123_BAD_PARAM /**< unknown parameter code */ +, OUT123_SET_RO_PARAM /**< attempt to set read-only parameter */ +, OUT123_BAD_HANDLE /**< bad handle pointer (NULL, usually) */ +, OUT123_ERRCOUNT /**< placeholder for shaping arrays */ +}; + +/** Get string representation of last encountered error in the + * context of given handle. + * \param ao handle + * \return error string + */ +MPG123_EXPORT +const char* out123_strerror(out123_handle *ao); + +/** Get the plain errcode intead of a string. + * Note that this used to return OUT123_ERR instead of + * OUT123_BAD_HANDLE in case of ao==NULL before mpg123-1.23.5 . + * \param ao handle + * \return error code recorded in handle or OUT123_BAD_HANDLE + */ +MPG123_EXPORT +int out123_errcode(out123_handle *ao); + +/** Return the error string for a given error code. + * \param errcode the integer error code + * \return error string + */ +MPG123_EXPORT +const char* out123_plain_strerror(int errcode); + +/** Set a desired output buffer size. + * This starts a separate process that handles the audio output, decoupling + * the latter from the main process with a memory buffer and saving you the + * burden to ensure sparing CPU cycles for actual playback. + * This is for applicatons that prefer continuous playback over small latency. + * In other words: The kind of applications that out123 is designed for. + * This routine always kills off any currently active audio output module / + * device, even if you just disable the buffer when there is no buffer. + * + * Keep this in mind for memory-constrainted systems: Activating the + * buffer causes a fork of the calling process, doubling the virtual memory + * use. Depending on your operating system kernel's behaviour regarding + * memory overcommit, it might be wise to call out123_set_buffer() very + * early in your program before allocating lots of memory. + * + * There _might_ be a change to threads in future, but for now this is + * classic fork with shared memory, working without any threading library. + * If your platform or build does not support that, you will always get an + * error on trying to set up a non-zero buffer (but the API call will be + * present). + * + * Also, if you do intend to use this from a multithreaded program, think + * twice and make sure that your setup is happy with forking full-blown + * processes off threaded programs. Probably you are better off spawning a + * buffer thread yourself. + * + * \param ao handle + * \param buffer_bytes size (bytes) of a memory buffer for decoded audio, + * a value of zero disables the buffer. + * \return 0 on success, OUT123_ERR on error + */ +MPG123_EXPORT +int out123_set_buffer(out123_handle *ao, size_t buffer_bytes); + +/** Set a specific parameter, for a specific out123_handle, using a parameter + * code chosen from the out123_parms enumeration, to the specified value. + * The parameters usually only change what happens on next out123_open, not + * incfluencing running operation. + * \param ao handle + * \param code parameter code + * \param value input value for integer parameters + * \param fvalue input value for floating point parameters + * \param svalue input value for string parameters (contens are copied) + * \return 0 on success, OUT123_ERR on error. + */ +MPG123_EXPORT +int out123_param( out123_handle *ao, enum out123_parms code +, long value, double fvalue, const char *svalue ); +#define out123_param_int(ao, code, value) \ + out123_param((ao), (code), (value), 0., NULL) +#define out123_param_float(ao, code, value) \ + out123_param((ao), (code), 0, (value), NULL) +#define out123_param_string(ao, code, value) \ + out123_param((ao), (code), 0, 0., (value)) + +/** Get a specific parameter, for a specific out123_handle, using a parameter + * code chosen from the out123_parms enumeration, to the specified value. + * \param ao handle + * \param code parameter code + * \param ret_value output address for integer parameters + * \param ret_fvalue output address for floating point parameters + * \param ret_svalue output address for string parameters (pointer to + * internal memory, so no messing around, please) + * \return 0 on success, OUT123_ERR on error (bad parameter name or bad handle). + */ +MPG123_EXPORT +int out123_getparam( out123_handle *ao, enum out123_parms code +, long *ret_value, double *ret_fvalue, char* *ret_svalue ); +#define out123_getparam_int(ao, code, value) \ + out123_getparam((ao), (code), (value), NULL, NULL) +#define out123_getparam_float(ao, code, value) \ + out123_getparam((ao), (code), NULL, (value), NULL) +#define out123_getparam_string(ao, code, value) \ + out123_getparam((ao), (code), NULL, NULL, (value)) + +/** Copy parameters from another out123_handle. + * \param ao handle + * \param from_ao the handle to copy parameters from + * \return 0 in success, -1 on error + */ +MPG123_EXPORT +int out123_param_from(out123_handle *ao, out123_handle* from_ao); + +/** Get list of driver modules reachable in system in C argv-style format. + * The client is responsible for freeing the memory of both the individual + * strings and the lists themselves. + * A module that is not loadable because of missing libraries is simply + * skipped. You will get stderr messages about that unless OUT123_QUIET was + * was set, though. Failure to open the module directory is a serious error, + * resulting in negative return value. + * \param ao handle + * \param names address for storing list of names + * \param descr address for storing list of descriptions + * \return number of drivers found, -1 on error + */ +MPG123_EXPORT +int out123_drivers(out123_handle *ao, char ***names, char ***descr); + +/** Open an output device with a certain driver + * Note: Opening means that the driver code is loaded and the desired + * device name recorded, possibly tested for availability or tentatively + * opened. After out123_open(), you can ask for supported encodings + * and then really open the device for playback with out123_start(). + * \param ao handle + * \param driver (comma-separated list of) output driver name(s to try), + * NULL for default (stdout for file-based drivers) + * \param device device name to open, NULL for default + * \return 0 on success, -1 on error. + */ +MPG123_EXPORT +int out123_open(out123_handle *ao, const char* driver, const char* device); + +/** Give info about currently loaded driver and device + * Any of the return addresses can be NULL if you are not interested in + * everything. You get pointers to internal storage. They are valid + * as long as the driver/device combination is opened. + * The device may be NULL indicating some unnamed default. + * TODO: Make the driver modules return names for such defaults. + * \param ao handle + * \param driver return address for driver name + * \param device return address for device name + * \return 0 on success, -1 on error (i.e. no driver loaded) + */ +MPG123_EXPORT +int out123_driver_info(out123_handle *ao, char **driver, char **device); + +/** Close the current output device and driver. + * This implies out123_drain() to ensure no data is lost. + * With a buffer, that might cause considerable delay during + * which your main application is blocked waiting. + * Call out123_drop() beforehand if you want to end things + * quickly. + * \param ao handle + */ +MPG123_EXPORT +void out123_close(out123_handle *ao); + +/** Get supported audio encodings for given rate and channel count, + * for the currently openend audio device. + * TODO: Reopening the underlying audio device for each query + * is dumb, at least when dealing with JACK. It takes + * a long time and is just a waste. Reconsider that. + * Make sure that all output modules are fine with it, though! + * Usually, a wider range of rates is supported, but the number + * of sample encodings is limited, as is the number of channels. + * So you can call this with some standard rate and hope that the + * returned encodings work also for others, with the tested channel + * count. + * The return value of -1 on some encountered error conveniently also + * does not match any defined format (only 15 bits used for encodings, + * so this would even work with 16 bit integers). + * This implies out123_stop() to enter query mode. + * \param ao handle + * \param rate sampling rate + * \param channels number of channels + * \return supported encodings combined with bitwise or, to be checked + * against your favourite bitmask, -1 on error + */ +MPG123_EXPORT +int out123_encodings(out123_handle *ao, long rate, int channels); + +/** Return the size (in bytes) of one mono sample of the named encoding. + * \param encoding The encoding value to analyze. + * \return positive size of encoding in bytes, 0 on invalid encoding. */ +MPG123_EXPORT int out123_encsize(int encoding); + +/** Get list of supported formats for currently opened audio device. + * Given a list of sampling rates and minimal/maximal channel count, + * this quickly checks what formats are supported with these + * constraints. The first entry is always reserved for a default + * format for the output device. If there is no such default, + * all values of the format are -1. + * For each requested combination of rate and channels, a format entry is + * created, possible with encoding value 0 to indicate that this combination + * has been tested and rejected. So, when there is no basic error, the + * number of returned format entries should be + * (ratecount*(maxchannels-minchannels+1)+1) + * . But instead of forcing you to guess, this will be allocated by + * successful run. + * For the first entry, the encoding member is supposed to be a definite + * encoding, for the others it is a bitwise combination of all possible + * encodings. + * This function is more efficient than many calls to out123_encodings(). + * \param ao handle + * \param rates pointer to an array of sampling rates, may be NULL for none + * \param ratecount number of provided sampling rates + * \param minchannels minimal channel count + * \param maxchannels maximal channel count + * \param fmtlist return address for array of supported formats + * the encoding field of each entry is a combination of all + * supported encodings at this rate and channel count; + * Memory shall be freed by user. + * \return number of returned format enries, -1 on error + */ +MPG123_EXPORT +int out123_formats( out123_handle *ao, const long *rates, int ratecount + , int minchannels, int maxchannels + , struct mpg123_fmt **fmtlist ); + +/** Get list of encodings known to the library. + * You are responsible for freeing the allocated array. + * \param enclist return address for allocated array of encoding codes + * \return number of encodings, -1 on error + */ +MPG123_EXPORT +int out123_enc_list(int **enclist); + +/** Find encoding code by name. + * \param name short or long name to find encoding code for + * \return encoding if found (enum mpg123_enc_enum), else 0 + */ +MPG123_EXPORT +int out123_enc_byname(const char *name); + +/** Get name of encoding. + * \param encoding code (enum mpg123_enc_enum) + * \return short name for valid encodings, NULL otherwise + */ +MPG123_EXPORT +const char* out123_enc_name(int encoding); + +/** Get long name of encoding. + * \param encoding code (enum mpg123_enc_enum) + * \return long name for valid encodings, NULL otherwise + */ +MPG123_EXPORT +const char* out123_enc_longname(int encoding); + +/** Start playback with a certain output format + * It might be a good idea to have audio data handy to feed after this + * returns with success. + * Rationale for not taking a pointer to struct mpg123_fmt: This would + * always force you to deal with that type and needlessly enlarge the + * shortest possible program. + * \param ao handle + * \param encoding sample encoding (values matching libmpg123 API) + * \param channels number of channels (1 or 2, usually) + * \param rate sampling rate + * \return 0 on success, negative on error (bad format, usually) + */ +MPG123_EXPORT +int out123_start( out123_handle *ao +, long rate, int channels, int encoding ); + +/** Pause playback + * Interrupt playback, holding any data in the optional buffer. + * + * This closes the audio device if it is a live sink, ready to be re-opened + * by out123_continue() or out123_play() with the existing parameters. + * \param ao handle + */ +MPG123_EXPORT +void out123_pause(out123_handle *ao); + +/** Continue playback + * The counterpart to out123_pause(). Announce to the driver that playback + * shall continue. + * + * Playback might not resume immediately if the optional buffer is configured + * to wait for a minimum fill and close to being empty. You can force playback + * of the last scrap with out123_drain(), or just by feeding more data with + * out123_play(), which will trigger out123_continue() for you, too. + * \param ao handle + */ +MPG123_EXPORT +void out123_continue(out123_handle *ao); + +/** Stop playback. + * This waits for pending audio data to drain to the speakers. + * You might want to call out123_drop() before stopping if you want + * to end things right away. + * \param ao handle + */ +MPG123_EXPORT +void out123_stop(out123_handle *ao); + +/** Hand over data for playback and wait in case audio device is busy. + * This survives non-fatal signals like SIGSTOP/SIGCONT and keeps on + * playing until the buffer is done with if the flag + * OUT123_KEEP_PLAYING ist set (default). So, per default, if + * you provided a byte count divisible by the PCM frame size, it is an + * error when less bytes than given are played. + * To be sure if an error occured, check out123_errcode(). + * Also note that it is no accident that the buffer parameter is not marked + * as constant. Some output drivers might need to do things like swap + * byte order. This is done in-place instead of wasting memory on yet + * another copy. + * \param ao handle + * \param buffer pointer to raw audio data to be played + * \param bytes number of bytes to read from the buffer + * \return number of bytes played (might be less than given, even zero) + */ +MPG123_EXPORT +size_t out123_play( out123_handle *ao + , void *buffer, size_t bytes ); + +/** Drop any buffered data, making next provided data play right away. + * This does not imply an actual pause in playback. + * You are expected to play something, unless you called out123_pause(). + * Feel free to call out123_stop() afterwards instead for a quicker + * exit than the implied out123_drain(). + * For live sinks, this may include dropping data from their buffers. + * For others (files), this only concerns data in the optional buffer. + * \param ao handle + */ +MPG123_EXPORT +void out123_drop(out123_handle *ao); + +/** Drain the output, waiting until all data went to the hardware. + * This does imply out123_continue() before and out123_pause() + * after draining. + * This might involve only the optional buffer process, or the + * buffers on the audio driver side, too. + * \param ao handle + */ +MPG123_EXPORT +void out123_drain(out123_handle *ao); + +/** Drain the output, but only partially up to the given number of + * bytes. This gives you the opportunity to do something while + * the optional buffer is writing remaining data instead of having + * one atomic API call for it all. + * + * It is wholly expected that the return value of out123_buffered() + * before and after calling this has a bigger difference than the + * provided limit, as the buffer is writing all the time in the + * background. + * + * This is just a plain out123_drain() if the optional buffer is not + * in use. Also triggers out123_continue(), but only out123_pause() + * if there is no buffered data anymore. + * \param ao handle + * \param bytes limit of buffered bytes to drain + * \return number of bytes drained from buffer + */ +MPG123_EXPORT +void out123_ndrain(out123_handle *ao, size_t bytes); + +/** Get an indication of how many bytes reside in the optional buffer. + * This might get extended to tell the number of bytes queued up in the + * audio backend, too. + * \param ao handle + * \return number of bytes in out123 library buffer + */ +MPG123_EXPORT +size_t out123_buffered(out123_handle *ao); + +/** Extract currently used audio format from handle. + * matching mpg123_getformat(). + * Given return addresses may be NULL to indicate no interest. + * \param ao handle + * \param rate address for sample rate + * \param channels address for channel count + * \param encoding address for encoding + * \param framesize size of a full PCM frame (for convenience) + * \return 0 on success, -1 on error + */ +MPG123_EXPORT +int out123_getformat( out123_handle *ao +, long *rate, int *channels, int *encoding, int *framesize ); + +/* @} */ + +#ifdef __cplusplus +} +#endif + +#undef MPG123_EXPORT + +#endif + diff --git a/src/config/win/x64/out123.h b/src/config/win/x64/out123.h new file mode 100644 index 0000000..627df1a --- /dev/null +++ b/src/config/win/x64/out123.h @@ -0,0 +1,583 @@ +/* + out123: audio output interface + + copyright 1995-2016 by the mpg123 project, + free software under the terms of the LGPL 2.1 + + see COPYING and AUTHORS files in distribution or http://mpg123.org + initially written as audio.h by Michael Hipp, reworked into out123 API + by Thomas Orgis +*/ + +#ifndef _OUT123_H_ +#define _OUT123_H_ + +/** \file out123.h The header file for the libout123 audio output facility. */ + +/* We only need size_t definition. */ +#include + +/* Common audio encoding specification, including a macro for getting + * size of encodined samples in bytes. Said macro is still hardcoded + * into out123_encsize(). Relying on this one may help an old program + * know sizes of encodings added to fmt123.h later on. + * If you don't care, just use the macro. + */ +#include + +/** A macro to check at compile time which set of API functions to expect. + * This should be incremented at least each time a new symbol is added + * to the header. + */ +#define OUT123_API_VERSION 1 + +/** Defines needed for MS Visual Studio(tm) DLL builds. + * Every public function must be prefixed with MPG123_EXPORT. When building + * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible + * for clients and includes it in the import library which is created together + * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which + * imports the functions from the DLL. + */ +#ifdef BUILD_MPG123_DLL +/* The dll exports. */ +#define MPG123_EXPORT __declspec(dllexport) +#else +#ifdef LINK_MPG123_DLL +/* The exe imports. */ +#define MPG123_EXPORT __declspec(dllimport) +#else +/* Nothing on normal/UNIX builds */ +#define MPG123_EXPORT +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup out123_api out123 library API + * This is out123, a library focused on continuous playback of audio streams + * via various platform-specific output methods. It glosses over details of + * the native APIs to give an interface close to simply writing data to a + * file. There might be the option to tune details like buffer (period) sizes + * and the number of them on the device side in future, but the focus of the + * library is to ease the use case of just getting that raw audio data out + * there, without interruptions. + * + * The basic idea is to create a handle with out123_new() and open a certain + * output device (using a certain driver module, possibly build-time defaults) + * with out123_open(). Now, you can query the output device for supported + * encodings for given rate and channel count with out123_get_encodings() and + * decide what to use for actually starting playback with out123_start(). + * + * Then, you just need to provide (interleaved pcm) data for playback with + * out123_play(), which will block when the device's buffers are full. You get + * your timing from that (instead of callbacks). If your program does the + * production of the audio data just a little bit faster than the playback, + * causing out123_play() to block ever so briefly, you're fine. + * + * You stop playback with out123_stop(), or just close the device and driver + * via out123_close(), or even just decide to drop it all and do out123_del() + * right away when you're done. + * + * There are other functions for specific needs, but the basic idea should be + * covered by the above. + @{ + */ + +/** Opaque structure for the libout123 handle. */ +struct out123_struct; +/** Typedef shortcut as preferrend name for the handle type. */ +typedef struct out123_struct out123_handle; + +/** Enumeration of codes for the parameters that it is possible to set/get. */ +enum out123_parms +{ + OUT123_FLAGS = 1 /**< integer, various flags, see enum out123_flags */ +, OUT123_PRELOAD /**< float, fraction of buffer to fill before playback */ +, OUT123_GAIN /**< integer, output device gain (module-specific) */ +, OUT123_VERBOSE /**< integer, verbosity to stderr, >= 0 */ +, OUT123_DEVICEBUFFER /**< + * float, length of device buffer in seconds; + * This might be ignored, might have only a loose relation to actual + * buffer sizes and latency, depending on output driver. Try to tune + * this before opening a device if you want to influcence latency or reduce + * dropouts. Value <= 0 uses some default, usually favouring stable playback + * over low latency. Values above 0.5 are probably too much. + */ +, OUT123_PROPFLAGS /**< integer, query driver/device property flags (r/o) */ +, OUT123_NAME /**< string, name of this instance (NULL restores default); + * The value returned by out123_getparam() might be different if the audio + * backend changed it (to be unique among clients, p.ex.). + * TODO: The name provided here is used as prefix in diagnostic messages. */ +}; + +/** Flags to tune out123 behaviour */ +enum out123_flags +{ + OUT123_HEADPHONES = 0x01 /**< output to headphones (if supported) */ +, OUT123_INTERNAL_SPEAKER = 0x02 /**< output to speaker (if supported) */ +, OUT123_LINE_OUT = 0x04 /**< output to line out (if supported) */ +, OUT123_QUIET = 0x08 /**< no printouts to standard error */ +, OUT123_KEEP_PLAYING = 0x10 /**< + * When this is set (default), playback continues in a loop when the device + * does not consume all given data at once. This happens when encountering + * signals (like SIGSTOP, SIGCONT) that cause interruption of the underlying + * functions. + * Note that this flag is meaningless when the optional buffer is employed, + * There, your program will always block until the buffer completely took + * over the data given to it via out123_play(), unless a communcation error + * arises. + */ +}; + +/** Read-only output driver/device property flags (OUT123_PROPFLAGS). */ +enum out123_propflags +{ + OUT123_PROP_LIVE = 0x01 /**< This is a live output, meaning that + * special care might be needed for pauses in playback (p.ex. stream + * of silence instead of interruption), as opposed to files on disk. + */ +, OUT123_PROP_PERSISTENT = 0x02 /**< This (live) output does not need + * special care for pauses (continues with silence itself), + * out123_pause() does nothing to the device. + */ +}; + +/** Create a new output handle. + * This only allocates and initializes memory, so the only possible + * error condition is running out of memory. + * \return pointer to new handle or NULL on error + */ +MPG123_EXPORT +out123_handle *out123_new(void); + +/** Delete output handle. + * This implies out123_close(). + */ +MPG123_EXPORT +void out123_del(out123_handle *ao); + +/** Error code enumeration + * API calls return a useful (positve) value or zero (OUT123_OK) on simple + * success. A negative value (-1 == OUT123_ERR) usually indicates that some + * error occured. Which one, that can be queried using out123_errcode() + * and friends. + */ +enum out123_error +{ + OUT123_ERR = -1 /**< generic alias for verbosity, always == -1 */ +, OUT123_OK = 0 /**< just a name for zero, not going to change */ +, OUT123_DOOM /**< dazzled, out of memory */ +, OUT123_BAD_DRIVER_NAME /**< bad driver name given */ +, OUT123_BAD_DRIVER /**< unspecified issue loading a driver */ +, OUT123_NO_DRIVER /**< no driver loaded */ +, OUT123_NOT_LIVE /**< no active audio device */ +, OUT123_DEV_PLAY /**< some device playback error */ +, OUT123_DEV_OPEN /**< error opening device */ +, OUT123_BUFFER_ERROR /**< + * Some (really unexpected) error in buffer infrastructure. + */ +, OUT123_MODULE_ERROR /**< basic failure in module loading */ +, OUT123_ARG_ERROR /**< some bad function arguments supplied */ +, OUT123_BAD_PARAM /**< unknown parameter code */ +, OUT123_SET_RO_PARAM /**< attempt to set read-only parameter */ +, OUT123_BAD_HANDLE /**< bad handle pointer (NULL, usually) */ +, OUT123_ERRCOUNT /**< placeholder for shaping arrays */ +}; + +/** Get string representation of last encountered error in the + * context of given handle. + * \param ao handle + * \return error string + */ +MPG123_EXPORT +const char* out123_strerror(out123_handle *ao); + +/** Get the plain errcode intead of a string. + * Note that this used to return OUT123_ERR instead of + * OUT123_BAD_HANDLE in case of ao==NULL before mpg123-1.23.5 . + * \param ao handle + * \return error code recorded in handle or OUT123_BAD_HANDLE + */ +MPG123_EXPORT +int out123_errcode(out123_handle *ao); + +/** Return the error string for a given error code. + * \param errcode the integer error code + * \return error string + */ +MPG123_EXPORT +const char* out123_plain_strerror(int errcode); + +/** Set a desired output buffer size. + * This starts a separate process that handles the audio output, decoupling + * the latter from the main process with a memory buffer and saving you the + * burden to ensure sparing CPU cycles for actual playback. + * This is for applicatons that prefer continuous playback over small latency. + * In other words: The kind of applications that out123 is designed for. + * This routine always kills off any currently active audio output module / + * device, even if you just disable the buffer when there is no buffer. + * + * Keep this in mind for memory-constrainted systems: Activating the + * buffer causes a fork of the calling process, doubling the virtual memory + * use. Depending on your operating system kernel's behaviour regarding + * memory overcommit, it might be wise to call out123_set_buffer() very + * early in your program before allocating lots of memory. + * + * There _might_ be a change to threads in future, but for now this is + * classic fork with shared memory, working without any threading library. + * If your platform or build does not support that, you will always get an + * error on trying to set up a non-zero buffer (but the API call will be + * present). + * + * Also, if you do intend to use this from a multithreaded program, think + * twice and make sure that your setup is happy with forking full-blown + * processes off threaded programs. Probably you are better off spawning a + * buffer thread yourself. + * + * \param ao handle + * \param buffer_bytes size (bytes) of a memory buffer for decoded audio, + * a value of zero disables the buffer. + * \return 0 on success, OUT123_ERR on error + */ +MPG123_EXPORT +int out123_set_buffer(out123_handle *ao, size_t buffer_bytes); + +/** Set a specific parameter, for a specific out123_handle, using a parameter + * code chosen from the out123_parms enumeration, to the specified value. + * The parameters usually only change what happens on next out123_open, not + * incfluencing running operation. + * \param ao handle + * \param code parameter code + * \param value input value for integer parameters + * \param fvalue input value for floating point parameters + * \param svalue input value for string parameters (contens are copied) + * \return 0 on success, OUT123_ERR on error. + */ +MPG123_EXPORT +int out123_param( out123_handle *ao, enum out123_parms code +, long value, double fvalue, const char *svalue ); +#define out123_param_int(ao, code, value) \ + out123_param((ao), (code), (value), 0., NULL) +#define out123_param_float(ao, code, value) \ + out123_param((ao), (code), 0, (value), NULL) +#define out123_param_string(ao, code, value) \ + out123_param((ao), (code), 0, 0., (value)) + +/** Get a specific parameter, for a specific out123_handle, using a parameter + * code chosen from the out123_parms enumeration, to the specified value. + * \param ao handle + * \param code parameter code + * \param ret_value output address for integer parameters + * \param ret_fvalue output address for floating point parameters + * \param ret_svalue output address for string parameters (pointer to + * internal memory, so no messing around, please) + * \return 0 on success, OUT123_ERR on error (bad parameter name or bad handle). + */ +MPG123_EXPORT +int out123_getparam( out123_handle *ao, enum out123_parms code +, long *ret_value, double *ret_fvalue, char* *ret_svalue ); +#define out123_getparam_int(ao, code, value) \ + out123_getparam((ao), (code), (value), NULL, NULL) +#define out123_getparam_float(ao, code, value) \ + out123_getparam((ao), (code), NULL, (value), NULL) +#define out123_getparam_string(ao, code, value) \ + out123_getparam((ao), (code), NULL, NULL, (value)) + +/** Copy parameters from another out123_handle. + * \param ao handle + * \param from_ao the handle to copy parameters from + * \return 0 in success, -1 on error + */ +MPG123_EXPORT +int out123_param_from(out123_handle *ao, out123_handle* from_ao); + +/** Get list of driver modules reachable in system in C argv-style format. + * The client is responsible for freeing the memory of both the individual + * strings and the lists themselves. + * A module that is not loadable because of missing libraries is simply + * skipped. You will get stderr messages about that unless OUT123_QUIET was + * was set, though. Failure to open the module directory is a serious error, + * resulting in negative return value. + * \param ao handle + * \param names address for storing list of names + * \param descr address for storing list of descriptions + * \return number of drivers found, -1 on error + */ +MPG123_EXPORT +int out123_drivers(out123_handle *ao, char ***names, char ***descr); + +/** Open an output device with a certain driver + * Note: Opening means that the driver code is loaded and the desired + * device name recorded, possibly tested for availability or tentatively + * opened. After out123_open(), you can ask for supported encodings + * and then really open the device for playback with out123_start(). + * \param ao handle + * \param driver (comma-separated list of) output driver name(s to try), + * NULL for default (stdout for file-based drivers) + * \param device device name to open, NULL for default + * \return 0 on success, -1 on error. + */ +MPG123_EXPORT +int out123_open(out123_handle *ao, const char* driver, const char* device); + +/** Give info about currently loaded driver and device + * Any of the return addresses can be NULL if you are not interested in + * everything. You get pointers to internal storage. They are valid + * as long as the driver/device combination is opened. + * The device may be NULL indicating some unnamed default. + * TODO: Make the driver modules return names for such defaults. + * \param ao handle + * \param driver return address for driver name + * \param device return address for device name + * \return 0 on success, -1 on error (i.e. no driver loaded) + */ +MPG123_EXPORT +int out123_driver_info(out123_handle *ao, char **driver, char **device); + +/** Close the current output device and driver. + * This implies out123_drain() to ensure no data is lost. + * With a buffer, that might cause considerable delay during + * which your main application is blocked waiting. + * Call out123_drop() beforehand if you want to end things + * quickly. + * \param ao handle + */ +MPG123_EXPORT +void out123_close(out123_handle *ao); + +/** Get supported audio encodings for given rate and channel count, + * for the currently openend audio device. + * TODO: Reopening the underlying audio device for each query + * is dumb, at least when dealing with JACK. It takes + * a long time and is just a waste. Reconsider that. + * Make sure that all output modules are fine with it, though! + * Usually, a wider range of rates is supported, but the number + * of sample encodings is limited, as is the number of channels. + * So you can call this with some standard rate and hope that the + * returned encodings work also for others, with the tested channel + * count. + * The return value of -1 on some encountered error conveniently also + * does not match any defined format (only 15 bits used for encodings, + * so this would even work with 16 bit integers). + * This implies out123_stop() to enter query mode. + * \param ao handle + * \param rate sampling rate + * \param channels number of channels + * \return supported encodings combined with bitwise or, to be checked + * against your favourite bitmask, -1 on error + */ +MPG123_EXPORT +int out123_encodings(out123_handle *ao, long rate, int channels); + +/** Return the size (in bytes) of one mono sample of the named encoding. + * \param encoding The encoding value to analyze. + * \return positive size of encoding in bytes, 0 on invalid encoding. */ +MPG123_EXPORT int out123_encsize(int encoding); + +/** Get list of supported formats for currently opened audio device. + * Given a list of sampling rates and minimal/maximal channel count, + * this quickly checks what formats are supported with these + * constraints. The first entry is always reserved for a default + * format for the output device. If there is no such default, + * all values of the format are -1. + * For each requested combination of rate and channels, a format entry is + * created, possible with encoding value 0 to indicate that this combination + * has been tested and rejected. So, when there is no basic error, the + * number of returned format entries should be + * (ratecount*(maxchannels-minchannels+1)+1) + * . But instead of forcing you to guess, this will be allocated by + * successful run. + * For the first entry, the encoding member is supposed to be a definite + * encoding, for the others it is a bitwise combination of all possible + * encodings. + * This function is more efficient than many calls to out123_encodings(). + * \param ao handle + * \param rates pointer to an array of sampling rates, may be NULL for none + * \param ratecount number of provided sampling rates + * \param minchannels minimal channel count + * \param maxchannels maximal channel count + * \param fmtlist return address for array of supported formats + * the encoding field of each entry is a combination of all + * supported encodings at this rate and channel count; + * Memory shall be freed by user. + * \return number of returned format enries, -1 on error + */ +MPG123_EXPORT +int out123_formats( out123_handle *ao, const long *rates, int ratecount + , int minchannels, int maxchannels + , struct mpg123_fmt **fmtlist ); + +/** Get list of encodings known to the library. + * You are responsible for freeing the allocated array. + * \param enclist return address for allocated array of encoding codes + * \return number of encodings, -1 on error + */ +MPG123_EXPORT +int out123_enc_list(int **enclist); + +/** Find encoding code by name. + * \param name short or long name to find encoding code for + * \return encoding if found (enum mpg123_enc_enum), else 0 + */ +MPG123_EXPORT +int out123_enc_byname(const char *name); + +/** Get name of encoding. + * \param encoding code (enum mpg123_enc_enum) + * \return short name for valid encodings, NULL otherwise + */ +MPG123_EXPORT +const char* out123_enc_name(int encoding); + +/** Get long name of encoding. + * \param encoding code (enum mpg123_enc_enum) + * \return long name for valid encodings, NULL otherwise + */ +MPG123_EXPORT +const char* out123_enc_longname(int encoding); + +/** Start playback with a certain output format + * It might be a good idea to have audio data handy to feed after this + * returns with success. + * Rationale for not taking a pointer to struct mpg123_fmt: This would + * always force you to deal with that type and needlessly enlarge the + * shortest possible program. + * \param ao handle + * \param encoding sample encoding (values matching libmpg123 API) + * \param channels number of channels (1 or 2, usually) + * \param rate sampling rate + * \return 0 on success, negative on error (bad format, usually) + */ +MPG123_EXPORT +int out123_start( out123_handle *ao +, long rate, int channels, int encoding ); + +/** Pause playback + * Interrupt playback, holding any data in the optional buffer. + * + * This closes the audio device if it is a live sink, ready to be re-opened + * by out123_continue() or out123_play() with the existing parameters. + * \param ao handle + */ +MPG123_EXPORT +void out123_pause(out123_handle *ao); + +/** Continue playback + * The counterpart to out123_pause(). Announce to the driver that playback + * shall continue. + * + * Playback might not resume immediately if the optional buffer is configured + * to wait for a minimum fill and close to being empty. You can force playback + * of the last scrap with out123_drain(), or just by feeding more data with + * out123_play(), which will trigger out123_continue() for you, too. + * \param ao handle + */ +MPG123_EXPORT +void out123_continue(out123_handle *ao); + +/** Stop playback. + * This waits for pending audio data to drain to the speakers. + * You might want to call out123_drop() before stopping if you want + * to end things right away. + * \param ao handle + */ +MPG123_EXPORT +void out123_stop(out123_handle *ao); + +/** Hand over data for playback and wait in case audio device is busy. + * This survives non-fatal signals like SIGSTOP/SIGCONT and keeps on + * playing until the buffer is done with if the flag + * OUT123_KEEP_PLAYING ist set (default). So, per default, if + * you provided a byte count divisible by the PCM frame size, it is an + * error when less bytes than given are played. + * To be sure if an error occured, check out123_errcode(). + * Also note that it is no accident that the buffer parameter is not marked + * as constant. Some output drivers might need to do things like swap + * byte order. This is done in-place instead of wasting memory on yet + * another copy. + * \param ao handle + * \param buffer pointer to raw audio data to be played + * \param bytes number of bytes to read from the buffer + * \return number of bytes played (might be less than given, even zero) + */ +MPG123_EXPORT +size_t out123_play( out123_handle *ao + , void *buffer, size_t bytes ); + +/** Drop any buffered data, making next provided data play right away. + * This does not imply an actual pause in playback. + * You are expected to play something, unless you called out123_pause(). + * Feel free to call out123_stop() afterwards instead for a quicker + * exit than the implied out123_drain(). + * For live sinks, this may include dropping data from their buffers. + * For others (files), this only concerns data in the optional buffer. + * \param ao handle + */ +MPG123_EXPORT +void out123_drop(out123_handle *ao); + +/** Drain the output, waiting until all data went to the hardware. + * This does imply out123_continue() before and out123_pause() + * after draining. + * This might involve only the optional buffer process, or the + * buffers on the audio driver side, too. + * \param ao handle + */ +MPG123_EXPORT +void out123_drain(out123_handle *ao); + +/** Drain the output, but only partially up to the given number of + * bytes. This gives you the opportunity to do something while + * the optional buffer is writing remaining data instead of having + * one atomic API call for it all. + * + * It is wholly expected that the return value of out123_buffered() + * before and after calling this has a bigger difference than the + * provided limit, as the buffer is writing all the time in the + * background. + * + * This is just a plain out123_drain() if the optional buffer is not + * in use. Also triggers out123_continue(), but only out123_pause() + * if there is no buffered data anymore. + * \param ao handle + * \param bytes limit of buffered bytes to drain + * \return number of bytes drained from buffer + */ +MPG123_EXPORT +void out123_ndrain(out123_handle *ao, size_t bytes); + +/** Get an indication of how many bytes reside in the optional buffer. + * This might get extended to tell the number of bytes queued up in the + * audio backend, too. + * \param ao handle + * \return number of bytes in out123 library buffer + */ +MPG123_EXPORT +size_t out123_buffered(out123_handle *ao); + +/** Extract currently used audio format from handle. + * matching mpg123_getformat(). + * Given return addresses may be NULL to indicate no interest. + * \param ao handle + * \param rate address for sample rate + * \param channels address for channel count + * \param encoding address for encoding + * \param framesize size of a full PCM frame (for convenience) + * \return 0 on success, -1 on error + */ +MPG123_EXPORT +int out123_getformat( out123_handle *ao +, long *rate, int *channels, int *encoding, int *framesize ); + +/* @} */ + +#ifdef __cplusplus +} +#endif + +#undef MPG123_EXPORT + +#endif + diff --git a/src/mpg123.gyp b/src/mpg123.gyp new file mode 100644 index 0000000..cb6a366 --- /dev/null +++ b/src/mpg123.gyp @@ -0,0 +1,161 @@ +{ + 'variables': { + 'target_arch%': 'ia32' + }, + 'target_defaults': { + 'configurations': { + 'Debug': { + 'defines': [ + 'DEBUG' + ], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 1 + } + } + }, + 'Release': { + 'defines': [ + 'NDEBUG' + ], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 0 + } + } + } + }, + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true' + } + }, + 'conditions': [ + ['OS=="mac"', { + 'conditions': [ + ['target_arch=="ia32"', { 'xcode_settings': { 'ARCHS': [ 'i386' ] } }], + ['target_arch=="x64"', { 'xcode_settings': { 'ARCHS': [ 'x86_64' ] } }] + ] + }] + ] + }, + 'targets': [ + { + 'target_name': 'out123', + 'type': 'static_library', + 'dependencies': [ 'compat' ], + 'include_dirs': [ + 'mpg123/src/libout123', + 'config/<(OS)/<(target_arch)' + ], + 'defines': [ + 'PIC', + 'NOXFERMEM', + 'HAVE_CONFIG_H' + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'mpg123/src/libout123', + 'config/<(OS)/<(target_arch)' + ] + }, + 'sources': [ + 'mpg123/src/libout123/legacy_module.c', + 'mpg123/src/libout123/libout123.c', + 'mpg123/src/libout123/sfifo.c', + 'mpg123/src/libout123/stringlists.c', + 'mpg123/src/libout123/wav.c' + ] + }, + { + 'target_name': 'compat', + 'type': 'static_library', + 'include_dirs': [ + 'util', + 'mpg123/src', + 'mpg123/src/compat', + 'mpg123/src/libmpg123', + 'config/<(OS)/<(target_arch)' + ], + 'defines': [ + 'PIC', + 'NOXFERMEM', + 'HAVE_CONFIG_H' + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'util', + 'mpg123/src', + 'mpg123/src/compat', + 'mpg123/src/libmpg123', + 'config/<(OS)/<(target_arch)' + ] + }, + 'sources': [ + 'mpg123/src/compat/compat.c', + 'mpg123/src/compat/compat_str.c' + ] + }, + { + 'target_name': 'module', + 'type': 'static_library', + 'dependencies': ['compat', 'out123' ], + 'variables': { + 'conditions': [ + ['OS=="mac"', { + 'mpg123_module%': 'coreaudio' + }], + ['OS=="win"', { + 'mpg123_module%': 'win32' + }], + ['OS=="linux"', { + 'mpg123_module%': 'alsa' + }] + ] + }, + 'include_dirs': [ + 'mpg123/src/libout123/modules', + 'config/<(OS)/<(target_arch)' + ], + 'defines': [ + 'PIC', + 'NOXFERMEM', + 'REAL_IS_FLOAT', + 'HAVE_CONFIG_H', + 'BUILDING_OUTPUT_MODULES=1' + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'mpg123/src/libout123/modules', + 'config/<(OS)/<(target_arch)' + ] + }, + 'conditions': [ + ['mpg123_module=="coreaudio"', { + 'link_settings': { + 'libraries': [ + '-framework AudioToolbox', + '-framework AudioUnit', + '-framework CoreServices' + ] + } + }], + ['mpg123_module=="win32"', { + 'link_settings': { + 'libraries': [ + '-lwinmm.lib' + ] + } + }], + ['mpg123_module=="alsa"', { + 'link_settings': { + 'libraries': [ + '-lasound' + ] + } + }] + ], + 'sources': [ 'mpg123/src/libout123/modules/<(mpg123_module).c' ] + } + ] +} diff --git a/src/pointer_wrapper.h b/src/pointer_wrapper.h new file mode 100644 index 0000000..f708d74 --- /dev/null +++ b/src/pointer_wrapper.h @@ -0,0 +1,29 @@ +#include + +inline static void wrap_pointer_cb(char *data, void *hint) { + fprintf(stderr, "Wrapped pointer was garbage collected."); // Debug message. +} + +inline static v8::Local WrapPointer(void *ptr, size_t length) { + void *user_data = NULL; + fprintf(stderr, "Wrapping pointer to a Node Buffer."); // Debug message. + return Nan::NewBuffer((char *)ptr, length, wrap_pointer_cb, user_data).ToLocalChecked(); +} + +inline static v8::Local WrapPointer(void *ptr) { + return WrapPointer((char *)ptr, 0); +} + +inline static char * UnwrapPointer(v8::Local buffer, int64_t offset = 0) { + if(node::Buffer::HasInstance(buffer)) { + fprintf(stderr, "Unwrapping pointer from Node Buffer."); // Debug message. + return node::Buffer::Data(buffer.As()) + offset; + } else { + return NULL; + } +} + +template +inline static Type UnwrapPointer(v8::Local buffer) { + return reinterpret_cast(UnwrapPointer(buffer)); +} \ No newline at end of file diff --git a/src/util/getopt.c b/src/util/getopt.c new file mode 100644 index 0000000..c3fe2a7 --- /dev/null +++ b/src/util/getopt.c @@ -0,0 +1,1228 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +# ifndef const +# define const +# endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include +# include +#endif /* GNU C library. */ + +#ifdef VMS +# include +# if HAVE_STRING_H - 0 +# include +# endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. */ +# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC +# include +# ifndef _ +# define _(msgid) gettext (msgid) +# endif +# else +# define _(msgid) (msgid) +# endif +# if defined _LIBC && defined USE_IN_LIBIO +# include +# endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + On entry to `getopt', zero means this is the first call; initialize. + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +# include +# define my_index strchr +#else + +# if HAVE_STRING_H || WIN32 /* Pete Wilson mod 7/28/02 */ +# include +# else +# include +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +# if (!defined __STDC__ || !__STDC__) && !defined strlen +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +# endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Stored original parameters. + XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ +extern int __libc_argc; +extern char **__libc_argv; + +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +# ifdef USE_NONOPTION_FLAGS +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; +# endif + +# ifdef USE_NONOPTION_FLAGS +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +# else +# define SWAP_FLAGS(ch1, ch2) +# endif +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined __STDC__ && __STDC__ +static void exchange (char **); +#endif + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined __STDC__ && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + if (posixly_correct == NULL + && argc == __libc_argc && argv == __libc_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen (orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + int print_errors = opterr; + if (optstring[0] == ':') + print_errors = 0; + + if (argc < 1) + return -1; + + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring); + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#if defined _LIBC && defined USE_NONOPTION_FLAGS +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT and LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); +#endif + } + nextchar += strlen (nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; +#endif + + if (argv[optind - 1][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("\ +%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#else + fprintf (stderr, _("\ +%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("\ +%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], + pfound->name); +#else + fprintf (stderr, _("\ +%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#endif + } + + nextchar += strlen (nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); +#endif + } + nextchar += strlen (nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; +#endif + + if (argv[optind][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); +#else + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); +#else + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#endif + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; +#endif + + if (posixly_correct) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("%s: illegal option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); +#endif + } + else + { +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("%s: invalid option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#endif + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (print_errors) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, _("%s: option requires an argument -- %c\n"), + argv[0], c); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); +#endif + } + nextchar += strlen (nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, _("\ +%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); +#endif + } + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (print_errors) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +/* #define TEST */ /* Pete Wilson mod 7/28/02 */ +#ifdef TEST + +#ifndef exit /* Pete Wilson mod 7/28/02 */ + int exit(int); /* Pete Wilson mod 7/28/02 */ +#endif /* Pete Wilson mod 7/28/02 */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ \ No newline at end of file diff --git a/src/util/getopt.h b/src/util/getopt.h new file mode 100644 index 0000000..a1d4778 --- /dev/null +++ b/src/util/getopt.h @@ -0,0 +1,173 @@ +/* getopt.h */ +/* Declarations for getopt. + Copyright (C) 1989-1994, 1996-1999, 2001 Free Software + Foundation, Inc. This file is part of the GNU C Library. + The GNU C Library is free software; you can redistribute + it and/or modify it under the terms of the GNU Lesser + General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or + (at your option) any later version. + The GNU C Library is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + You should have received a copy of the GNU Lesser General + Public License along with the GNU C Library; if not, write + to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. */ + + + + +#ifndef _GETOPT_H + +#ifndef __need_getopt +# define _GETOPT_H 1 +#endif + +/* If __GNU_LIBRARY__ is not already defined, either we are being used + standalone, or this is the first header included in the source file. + If we are being used with glibc, we need to include , but + that does not exist if we are standalone. So: if __GNU_LIBRARY__ is + not defined, include , which will pull in for us + if it's from glibc. (Why ctype.h? It's guaranteed to exist and it + doesn't flood the namespace with stuff the way some other headers do.) */ +#if !defined __GNU_LIBRARY__ +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + On entry to `getopt', zero means this is the first call; initialize. + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +#ifndef __need_getopt +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +# if (defined __STDC__ && __STDC__) || defined __cplusplus + const char *name; +# else + char *name; +# endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 +#endif /* need getopt */ + + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, `optopt' is set to the option letter, and '?' is + returned. + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in `optarg'. + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU `getopt'. + The argument `--' causes premature termination of argument + scanning, explicitly telling `getopt' that there are no more + options. + If OPTS begins with `--', then non-option arguments are treated as + arguments to the option '\0'. This behavior is specific to the GNU + `getopt'. */ + +#if (defined __STDC__ && __STDC__) || defined __cplusplus +# ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); +# else /* not __GNU_LIBRARY__ */ +extern int getopt (); +# endif /* __GNU_LIBRARY__ */ + +# ifndef __need_getopt +extern int getopt_long (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind); +extern int getopt_long_only (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only); +# endif +#else /* not __STDC__ */ +extern int getopt (); +# ifndef __need_getopt +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +# endif +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +#undef __need_getopt + +#endif /* getopt.h */ \ No newline at end of file diff --git a/src/util/unistd.h b/src/util/unistd.h new file mode 100644 index 0000000..8995895 --- /dev/null +++ b/src/util/unistd.h @@ -0,0 +1,52 @@ +#ifndef _UNISTD_H +#define _UNISTD_H 1 + +/* This file intended to serve as a drop-in replacement for + * unistd.h on Windows + * Please add functionality as neeeded + */ + +#include +#include +#include /* getopt at: https://gist.github.com/ashelly/7776712 */ +#include /* for getpid() and the exec..() family */ +#include /* for _getcwd() and _chdir() */ + +#define srandom srand +#define random rand + +/* Values for the second argument to access. + These may be OR'd together. */ +#define R_OK 4 /* Test for read permission. */ +#define W_OK 2 /* Test for write permission. */ +//#define X_OK 1 /* execute permission - unsupported in windows*/ +#define F_OK 0 /* Test for existence. */ + +#define access _access +#define dup2 _dup2 +#define execve _execve +#define ftruncate _chsize +#define unlink _unlink +#define fileno _fileno +#define getcwd _getcwd +#define chdir _chdir +#define isatty _isatty +#define lseek _lseek +/* read, write, and close are NOT being #defined here, because while there are file handle specific versions for Windows, they probably don't work for sockets. You need to look at your app and consider whether to call e.g. closesocket(). */ + +#define ssize_t int + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +/* should be in some equivalent to */ +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +#endif /* unistd.h */ \ No newline at end of file diff --git a/stream.js b/stream.js deleted file mode 100644 index 67203c1..0000000 --- a/stream.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @module audio-speaker - * - * Wraps node-speaker to ensure format. - * - */ -'use strict'; - -var inherits = require('inherits'); -var extend = require('xtend/mutable'); -var Through = require('audio-through'); - -var NodeSpeaker; -try { - NodeSpeaker = require('speaker'); -} catch (e) { - console.warn('`speaker` package was not found. Using `audio-sink` instead.'); - NodeSpeaker = require('audio-sink'); -} - -/** - * Speaker is just a format wrapper for node-speaker, - * as node-speaker doesn’t support any input format in some platforms, like windows. - * So we need to force the most safe format. - * - * @constructor - */ -function AudioSpeaker (opts) { - if (!(this instanceof AudioSpeaker)) { - return new AudioSpeaker(opts); - } - - Through.call(this, opts); - - //create node-speaker with default options - the most cross-platform case - this.speaker = new NodeSpeaker({ - channels: this.channels - }); - - this.pipe(this.speaker); -} - -inherits(AudioSpeaker, Through); - - -/** - * Predefined format for node-speaker - */ -extend(AudioSpeaker.prototype, { - float: false, - interleaved: true, - bitDepth: 16, - signed: true -}); - - -module.exports = AudioSpeaker; diff --git a/test.html b/test.html deleted file mode 100644 index bab0f2e..0000000 --- a/test.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Audio-speaker browser and custom element test - - - - - - - - - \ No newline at end of file diff --git a/test.js b/test.js deleted file mode 100644 index 52fc521..0000000 --- a/test.js +++ /dev/null @@ -1,181 +0,0 @@ -'use strict'; - -var Speaker = require('./stream'); -var Generator = require('audio-generator/stream'); -var Generate = require('audio-generator/index'); -var Readable = require('stream').Readable; -var util = require('audio-buffer-utils'); -var pcm = require('pcm-util'); -var Through = require('audio-through'); -Through.log = true; -var Volume = require('pcm-volume'); -var test = require('tst')//.only(); -var SpeakerWriter = require('./direct'); -var pull = require('pull-stream'); -var PullSpeaker = require('./pull'); -var pullGenerator = require('audio-generator/pull'); - - -require('insert-styles')(` - @font-face { - font-family: wavefont; - src: url(./wavefont.otf) format("opentype"); - } -`); - -test('Pure function', function (done) { - let generate = Generate(t => { - return Math.sin(t * Math.PI * 2 * 440); - }, 1); - - let write = SpeakerWriter(); - - (function loop (err, buf) { - if (err) return write(null); - write(generate(buf), loop) - })(); - - setTimeout(() => { - write(null); - done(); - }, 200); -}); - -test('Pull stream', function (done) { - let out = PullSpeaker(); - - pull( - pullGenerator(time => 2 * time * 440 - 1, {frequency: 440}), - out - ); - - setTimeout(() => { - out.abort(); - done(); - }, 500); -}); - -test('Cleanness of wave', function () { - Through(function (buffer) { - var self = this; - util.fill(buffer, function (sample, idx, channel) { - return Math.sin(Math.PI * 2 * (self.count + idx) * 440 / 44100); - }); - - if (this.time > 1) return this.end(); - - return buffer; - }) - .pipe(Speaker()); - // .pipe(WAASteam(context.destination)); -}); - -test('Feed audio-through', function () { - Generator({ - generate: function (time) { - return [ - Math.sin(Math.PI * 2 * time * 538 ) / 5, - Math.sin(Math.PI * 2 * time * 542 ) / 5 - // Math.random() - ] - }, - duration: .4 - }).pipe(Speaker()); -}); - -test('Feed raw pcm', function () { - var count = 0; - Readable({ - read: function (size) { - var abuf = util.create(2, 1024, 44100); - - //EGG: swap ch & i and hear wonderful sfx - util.fill(abuf, function (v, i, ch) { - v = Math.sin(Math.PI * 2 * ((count + i)/44100) * (738 + ch*2) ) / 5; - return v; - }); - - count += 1024; - - if (count > 1e4 ) return this.push(null); - - let buf = pcm.toBuffer(abuf); - - this.push(buf); - } - }) - .pipe(Speaker({ - channels: 2 - })); -}); - -//FIXME: use transform stream here to send floats data to speaker -test.skip('Feed custom pcm', function () { - var count = 0; - Readable({ - // objectMode: 1, - read: function (size) { - var abuf = util.create(2, 1024, 44100); - - util.fill(abuf, function (v, i, ch) { - return Math.sin(Math.PI * 2 * ((count + i)/44100) * (938 + ch*2) ); - }); - - count += 1024; - - if (count > 1e4 ) return this.push(null); - - let buf = pcm.toBuffer(abuf, { - float: true - }); - - this.push(buf); - } - }).pipe(Speaker({ - channels: 2, - - //EGG: comment this and hear wonderful sfx - float: true - })); -}); - -test.skip('Feed random buffer size'); - -test('Volume case', function () { - Generator({ - generate: function (time) { - return [ - Math.sin(Math.PI * 2 * time * 1038 ) / 5, - Math.sin(Math.PI * 2 * time * 1042 ) / 5 - ]; - }, - duration: 1 - }) - .pipe(Volume(5)) - .pipe(Speaker()); -}); - - - - -//little debigger -if (typeof document !== 'undefined') { - var el = document.body.appendChild(document.createElement('div')); - el.style.cssText = ` - font-family: wavefont; - max-width: 100vw; - word-break: break-all; - white-space: pre-wrap; - font-size: 32px; - `; - - function draw (arr) { - let str = ''; - - for (let i = 0; i < arr.length; i++) { - str += String.fromCharCode(0x200 + Math.floor(arr[i] * 128 * 5)); - } - - el.innerHTML += '\n' + str; - } -} diff --git a/todo.md b/todo.md deleted file mode 100644 index 4181ef1..0000000 --- a/todo.md +++ /dev/null @@ -1,16 +0,0 @@ -* Restrain buffers piping to node-speaker, bind to RT. Do not generate more than needed. - * node-speaker restrains pressure, but with a 3s buffer - it should be able to be regulated. -* replace node-speaker with good implementation. It fails on estimating big buffers -* Decrease buffer, significantly. Make gain work realtime -* Flash fallback -* Create scriptProcessorNode mode. As an alternative. -* For old browsers generate sound like t='data:audio/wav;base64,UklGRl9vT19XQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgA',new Audio(t+btoa(t+S)).play() - * http://www.p01.org/JS1K_Speech_Synthesizer/ - -* Detect audioBufferSize based on some performance measure, to avoid GC glitches -* Test in Firefox, Opera, Safari, iOS Safari, IE, others. - -* Test variety of channels -* Test different sample rates - -* CLI \ No newline at end of file From 937c85b7a8016fc08d9ed47f20fbad2024b46eb4 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Tue, 4 Oct 2016 10:33:55 +1300 Subject: [PATCH 02/96] Add node-gyp to install in travis --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4751737..c95a388 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,10 @@ addons: - ubuntu-toolchain-r-test env: - CXX=g++-4.8 +install: + - npm install -g npm + - npm install -g node-gyp + - npm install matrix: fast_finish: true allow_failures: From 49f1b07d36fa06fdd8c4c604334eb24b63e40363 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Tue, 4 Oct 2016 10:55:20 +1300 Subject: [PATCH 03/96] Add mpg123 submodule --- src/mpg123 | 1 + 1 file changed, 1 insertion(+) create mode 160000 src/mpg123 diff --git a/src/mpg123 b/src/mpg123 new file mode 160000 index 0000000..db28c90 --- /dev/null +++ b/src/mpg123 @@ -0,0 +1 @@ +Subproject commit db28c905f297d3e11574b9e8d7df975dab44587c From 0edb96d6026e9ee6bffd9c66fe6e22ac10076a1a Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Tue, 4 Oct 2016 10:56:02 +1300 Subject: [PATCH 04/96] Modify gitignore --- .gitignore | 3 +-- readme.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index e45e238..cfb822d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,6 @@ git rm --cached Makefile Makefile.in configure -config.h config.status config.h.in config.log @@ -133,4 +132,4 @@ tmp bundle.* -_demo \ No newline at end of file +_demo diff --git a/readme.md b/readme.md index 9c6f6bd..786101b 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -#audio-speaker [![Build Status](https://travis-ci.org/audiojs/audio-speaker.svg?branch=master)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/unstable.svg)](http://github.com/badges/stability-badges) +#audio-speaker [![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/unstable.svg)](http://github.com/badges/stability-badges) Output audio stream natively in node or through Web Audio in the browser. From e63ab3699a093220c2bab20bcce29d0d21e310e7 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Tue, 4 Oct 2016 11:32:49 +1300 Subject: [PATCH 05/96] Add windows configurations --- src/config/win/ia32/config.h | 463 +++++++++++++++++++++++++++++++++++ src/config/win/x64/config.h | 463 +++++++++++++++++++++++++++++++++++ 2 files changed, 926 insertions(+) create mode 100644 src/config/win/ia32/config.h create mode 100644 src/config/win/x64/config.h diff --git a/src/config/win/ia32/config.h b/src/config/win/ia32/config.h new file mode 100644 index 0000000..1a6192a --- /dev/null +++ b/src/config/win/ia32/config.h @@ -0,0 +1,463 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if your architecture wants/needs/can use attribute_align_arg and + alignment checks. It is for 32bit x86... */ +/* #undef ABI_ALIGN_FUN */ + +/* Define to use proper rounding. */ +/* #undef ACCURATE_ROUNDING */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define if .balign is present. */ +#define ASMALIGN_BALIGN 1 + +/* Define if .align just takes byte count. */ +/* #undef ASMALIGN_BYTE */ + +/* Define if .align takes 3 for alignment of 2^3=8 bytes instead of 8. */ +/* #undef ASMALIGN_EXP */ + +/* Define if __attribute__((aligned(16))) shall be used */ +#define CCALIGN 1 + +/* Define if debugging is enabled. */ +/* #undef DEBUG */ + +/* The default audio output module(s) to use */ +#define DEFAULT_OUTPUT_MODULE "oss,win32,win32_wasapi" + +/* Define if building with dynamcally linked libmpg123 */ +#define DYNAMIC_BUILD 1 + +/* Use EFBIG as substitude for EOVERFLOW, mingw.org may lack the latter */ +/* #undef EOVERFLOW */ + +/* Define if FIFO support is enabled. */ +#define FIFO 1 + +/* Define if frame index should be used. */ +#define FRAME_INDEX 1 + +/* Define if gapless is enabled. */ +#define GAPLESS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALIB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_ALC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_AL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_AUDIOIO_H */ + +/* Define to 1 if you have the `atoll' function. */ +#define HAVE_ATOLL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOTOOLBOX_AUDIOTOOLBOX_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOUNIT_AUDIOUNIT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CORESERVICES_CORESERVICES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CULIB_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */ +#define HAVE_GAI_ADDRCONFIG 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `getuid' function. */ +#define HAVE_GETUID 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LANGINFO_H 1 + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `mx' library (-lmx). */ +/* #undef HAVE_LIBMX */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if libltdl is available */ +#define HAVE_LTDL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACHINE_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#define HAVE_MKFIFO 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the `nl_langinfo' function. */ +#define HAVE_NL_LANGINFO 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENAL_ALC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENAL_AL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OS2ME_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OS2_H */ + +/* Define to 1 if you have the `random' function. */ +#define HAVE_RANDOM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SCHED_H 1 + +/* Define to 1 if you have the `sched_setscheduler' function. */ +#define HAVE_SCHED_SETSCHEDULER 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setpriority' function. */ +#define HAVE_SETPRIORITY 1 + +/* Define to 1 if you have the `setuid' function. */ +#define HAVE_SETUID 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SNDIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SUN_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOUNDCARD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define this if you have the POSIX termios library */ +#define HAVE_TERMIOS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to indicate that float storage follows IEEE754. */ +#define IEEE_FLOAT 1 + +/* size of the frame index seek table */ +#define INDEX_SIZE 1000 + +/* Define if IPV6 support is enabled. */ +#define IPV6 1 + +/* Define this to the size of native offset type in bits, used for LFS alias + functions. */ +#define LFS_ALIAS_BITS 64 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* The suffix for module files. */ +#define MODULE_FILE_SUFFIX ".la" + +/* Define if network support is enabled. */ +#define NETWORK 1 + +/* Define to disable 16 bit integer output. */ +/* #undef NO_16BIT */ + +/* Define to disable 32 bit and 24 bit integer output. */ +/* #undef NO_32BIT */ + +/* Define to disable 8 bit integer output. */ +/* #undef NO_8BIT */ + +/* Define to disable downsampled decoding. */ +/* #undef NO_DOWNSAMPLE */ + +/* Define to disable equalizer. */ +/* #undef NO_EQUALIZER */ + +/* Define to disable error messages in combination with a return value (the + return is left intact). */ +/* #undef NO_ERETURN */ + +/* Define to disable error messages. */ +/* #undef NO_ERRORMSG */ + +/* Define to disable feeder and buffered readers. */ +/* #undef NO_FEEDER */ + +/* Define to disable ICY handling. */ +/* #undef NO_ICY */ + +/* Define to disable ID3v2 parsing. */ +/* #undef NO_ID3V2 */ + +/* Define to disable layer I. */ +/* #undef NO_LAYER1 */ + +/* Define to disable layer II. */ +/* #undef NO_LAYER2 */ + +/* Define to disable layer III. */ +/* #undef NO_LAYER3 */ + +/* Define to disable ntom resampling. */ +/* #undef NO_NTOM */ + +/* Define to disable real output. */ +/* #undef NO_REAL */ + +/* Define to disable string functions. */ +/* #undef NO_STRING */ + +/* Define for post-processed 32 bit formats. */ +/* #undef NO_SYNTH32 */ + +/* Define to disable warning messages. */ +/* #undef NO_WARNING */ + +/* Name of package */ +#define PACKAGE "mpg123" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "maintainer@mpg123.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "mpg123" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "mpg123 1.24.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "mpg123" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.24.0" + +/* Define if portaudio v18 API is wanted. */ +/* #undef PORTAUDIO18 */ + +/* The size of `int32_t', as computed by sizeof. */ +#define SIZEOF_INT32_T 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `ssize_t', as computed by sizeof. */ +#define SIZEOF_SSIZE_T 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if modules are enabled */ +#define USE_MODULES 1 + +/* Define for new Huffman decoding scheme. */ +#define USE_NEW_HUFFTABLE 1 + +/* Define to use yasm for assemble AVX sources. */ +/* #undef USE_YASM_FOR_AVX */ + +/* Version number of package */ +#define VERSION "1.24.0" + +/* Define to use Win32 named pipes */ +/* #undef WANT_WIN32_FIFO */ + +/* Define to use Win32 sockets */ +/* #undef WANT_WIN32_SOCKETS */ + +/* Define to use Unicode for Windows */ +/* #undef WANT_WIN32_UNICODE */ + +/* WinXP and above for ipv6 */ +/* #undef WINVER */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* WinXP and above for ipv6 */ +/* #undef _WIN32_WINNT */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `short' if does not define. */ +/* #undef int16_t */ + +/* Define to `int' if does not define. */ +/* #undef int32_t */ + +/* Define to `long long' if does not define. */ +/* #undef int64_t */ + +/* Define to the native offset type (long or actually off_t). */ +#define lfs_alias_t off_t + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to `unsigned long' if does not define. */ +/* #undef size_t */ + +/* Define to `long' if does not define. */ +/* #undef ssize_t */ + +/* Define to `unsigned short' if does not define. */ +/* #undef uint16_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef uint32_t */ + +/* Define to `unsigned long' if does not define. */ +/* #undef uintptr_t */ diff --git a/src/config/win/x64/config.h b/src/config/win/x64/config.h new file mode 100644 index 0000000..8dea24b --- /dev/null +++ b/src/config/win/x64/config.h @@ -0,0 +1,463 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if your architecture wants/needs/can use attribute_align_arg and + alignment checks. It is for 32bit x86... */ +/* #undef ABI_ALIGN_FUN */ + +/* Define to use proper rounding. */ +/* #undef ACCURATE_ROUNDING */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define if .balign is present. */ +#define ASMALIGN_BALIGN 1 + +/* Define if .align just takes byte count. */ +/* #undef ASMALIGN_BYTE */ + +/* Define if .align takes 3 for alignment of 2^3=8 bytes instead of 8. */ +/* #undef ASMALIGN_EXP */ + +/* Define if __attribute__((aligned(16))) shall be used */ +#define CCALIGN 1 + +/* Define if debugging is enabled. */ +/* #undef DEBUG */ + +/* The default audio output module(s) to use */ +#define DEFAULT_OUTPUT_MODULE "oss,win32,win32_wasapi" + +/* Define if building with dynamcally linked libmpg123 */ +#define DYNAMIC_BUILD 1 + +/* Use EFBIG as substitude for EOVERFLOW, mingw.org may lack the latter */ +/* #undef EOVERFLOW */ + +/* Define if FIFO support is enabled. */ +#define FIFO 1 + +/* Define if frame index should be used. */ +#define FRAME_INDEX 1 + +/* Define if gapless is enabled. */ +#define GAPLESS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALIB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_ALC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_AL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_AUDIOIO_H */ + +/* Define to 1 if you have the `atoll' function. */ +#define HAVE_ATOLL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOTOOLBOX_AUDIOTOOLBOX_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOUNIT_AUDIOUNIT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CORESERVICES_CORESERVICES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CULIB_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */ +#define HAVE_GAI_ADDRCONFIG 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `getuid' function. */ +/* #undef HAVE_GETUID */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LANGINFO_H 1 + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `mx' library (-lmx). */ +/* #undef HAVE_LIBMX */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if libltdl is available */ +/* #undef HAVE_LTDL */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACHINE_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#define HAVE_MKFIFO 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the `nl_langinfo' function. */ +#define HAVE_NL_LANGINFO 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENAL_ALC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENAL_AL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OS2ME_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OS2_H */ + +/* Define to 1 if you have the `random' function. */ +#define HAVE_RANDOM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SCHED_H 1 + +/* Define to 1 if you have the `sched_setscheduler' function. */ +#define HAVE_SCHED_SETSCHEDULER 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setpriority' function. */ +#define HAVE_SETPRIORITY 1 + +/* Define to 1 if you have the `setuid' function. */ +/* #undef HAVE_SETUID */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SNDIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STRINGS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SUN_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOUNDCARD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_TIME_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define this if you have the POSIX termios library */ +#define HAVE_TERMIOS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to indicate that float storage follows IEEE754. */ +#define IEEE_FLOAT 1 + +/* size of the frame index seek table */ +#define INDEX_SIZE 1000 + +/* Define if IPV6 support is enabled. */ +#define IPV6 1 + +/* Define this to the size of native offset type in bits, used for LFS alias + functions. */ +#define LFS_ALIAS_BITS 64 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* The suffix for module files. */ +#define MODULE_FILE_SUFFIX ".la" + +/* Define if network support is enabled. */ +#define NETWORK 1 + +/* Define to disable 16 bit integer output. */ +/* #undef NO_16BIT */ + +/* Define to disable 32 bit and 24 bit integer output. */ +/* #undef NO_32BIT */ + +/* Define to disable 8 bit integer output. */ +/* #undef NO_8BIT */ + +/* Define to disable downsampled decoding. */ +/* #undef NO_DOWNSAMPLE */ + +/* Define to disable equalizer. */ +/* #undef NO_EQUALIZER */ + +/* Define to disable error messages in combination with a return value (the + return is left intact). */ +/* #undef NO_ERETURN */ + +/* Define to disable error messages. */ +/* #undef NO_ERRORMSG */ + +/* Define to disable feeder and buffered readers. */ +/* #undef NO_FEEDER */ + +/* Define to disable ICY handling. */ +/* #undef NO_ICY */ + +/* Define to disable ID3v2 parsing. */ +/* #undef NO_ID3V2 */ + +/* Define to disable layer I. */ +/* #undef NO_LAYER1 */ + +/* Define to disable layer II. */ +/* #undef NO_LAYER2 */ + +/* Define to disable layer III. */ +/* #undef NO_LAYER3 */ + +/* Define to disable ntom resampling. */ +/* #undef NO_NTOM */ + +/* Define to disable real output. */ +/* #undef NO_REAL */ + +/* Define to disable string functions. */ +/* #undef NO_STRING */ + +/* Define for post-processed 32 bit formats. */ +/* #undef NO_SYNTH32 */ + +/* Define to disable warning messages. */ +/* #undef NO_WARNING */ + +/* Name of package */ +#define PACKAGE "mpg123" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "maintainer@mpg123.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "mpg123" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "mpg123 1.24.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "mpg123" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.24.0" + +/* Define if portaudio v18 API is wanted. */ +/* #undef PORTAUDIO18 */ + +/* The size of `int32_t', as computed by sizeof. */ +#define SIZEOF_INT32_T 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `ssize_t', as computed by sizeof. */ +#define SIZEOF_SSIZE_T 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if modules are enabled */ +#define USE_MODULES 1 + +/* Define for new Huffman decoding scheme. */ +#define USE_NEW_HUFFTABLE 1 + +/* Define to use yasm for assemble AVX sources. */ +/* #undef USE_YASM_FOR_AVX */ + +/* Version number of package */ +#define VERSION "1.24.0" + +/* Define to use Win32 named pipes */ +/* #undef WANT_WIN32_FIFO */ + +/* Define to use Win32 sockets */ +/* #undef WANT_WIN32_SOCKETS */ + +/* Define to use Unicode for Windows */ +/* #undef WANT_WIN32_UNICODE */ + +/* WinXP and above for ipv6 */ +/* #undef WINVER */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* WinXP and above for ipv6 */ +/* #undef _WIN32_WINNT */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `short' if does not define. */ +/* #undef int16_t */ + +/* Define to `int' if does not define. */ +/* #undef int32_t */ + +/* Define to `long long' if does not define. */ +/* #undef int64_t */ + +/* Define to the native offset type (long or actually off_t). */ +#define lfs_alias_t off_t + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to `unsigned long' if does not define. */ +/* #undef size_t */ + +/* Define to `long' if does not define. */ +/* #undef ssize_t */ + +/* Define to `unsigned short' if does not define. */ +/* #undef uint16_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef uint32_t */ + +/* Define to `unsigned long' if does not define. */ +/* #undef uintptr_t */ From 2a5a37bd15dfd95b072a9c1dfbfde9cb0f90267c Mon Sep 17 00:00:00 2001 From: Jamen Marz Date: Wed, 5 Oct 2016 19:01:49 -0600 Subject: [PATCH 06/96] Add Linux config for mpg123 --- src/config/linux/x64/config.h | 463 +++++++++++++++++++++++++++ src/config/linux/x64/out123.h | 583 ++++++++++++++++++++++++++++++++++ src/mpg123.gyp | 96 ++++-- 3 files changed, 1111 insertions(+), 31 deletions(-) create mode 100644 src/config/linux/x64/config.h create mode 100644 src/config/linux/x64/out123.h diff --git a/src/config/linux/x64/config.h b/src/config/linux/x64/config.h new file mode 100644 index 0000000..d6344e5 --- /dev/null +++ b/src/config/linux/x64/config.h @@ -0,0 +1,463 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if your architecture wants/needs/can use attribute_align_arg and + alignment checks. It is for 32bit x86... */ +/* #undef ABI_ALIGN_FUN */ + +/* Define to use proper rounding. */ +/* #undef ACCURATE_ROUNDING */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define if .balign is present. */ +#define ASMALIGN_BALIGN 1 + +/* Define if .align just takes byte count. */ +/* #undef ASMALIGN_BYTE */ + +/* Define if .align takes 3 for alignment of 2^3=8 bytes instead of 8. */ +/* #undef ASMALIGN_EXP */ + +/* Define if __attribute__((aligned(16))) shall be used */ +#define CCALIGN 1 + +/* Define if debugging is enabled. */ +/* #undef DEBUG */ + +/* The default audio output module(s) to use */ +#define DEFAULT_OUTPUT_MODULE "alsa,oss,jack,pulse,sdl,openal" + +/* Define if building with dynamcally linked libmpg123 */ +#define DYNAMIC_BUILD 1 + +/* Use EFBIG as substitude for EOVERFLOW, mingw.org may lack the latter */ +/* #undef EOVERFLOW */ + +/* Define if FIFO support is enabled. */ +#define FIFO 1 + +/* Define if frame index should be used. */ +#define FRAME_INDEX 1 + +/* Define if gapless is enabled. */ +#define GAPLESS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALIB_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_AL_ALC_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_AL_AL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_AUDIOIO_H */ + +/* Define to 1 if you have the `atoll' function. */ +#define HAVE_ATOLL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOTOOLBOX_AUDIOTOOLBOX_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOUNIT_AUDIOUNIT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CORESERVICES_CORESERVICES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CULIB_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */ +#define HAVE_GAI_ADDRCONFIG 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `getuid' function. */ +#define HAVE_GETUID 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LANGINFO_H 1 + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `mx' library (-lmx). */ +/* #undef HAVE_LIBMX */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_SOUNDCARD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if libltdl is available */ +#define HAVE_LTDL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACHINE_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#define HAVE_MKFIFO 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the `nl_langinfo' function. */ +#define HAVE_NL_LANGINFO 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENAL_ALC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENAL_AL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OS2ME_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OS2_H */ + +/* Define to 1 if you have the `random' function. */ +#define HAVE_RANDOM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SCHED_H 1 + +/* Define to 1 if you have the `sched_setscheduler' function. */ +#define HAVE_SCHED_SETSCHEDULER 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setpriority' function. */ +#define HAVE_SETPRIORITY 1 + +/* Define to 1 if you have the `setuid' function. */ +#define HAVE_SETUID 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SNDIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SUN_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOUNDCARD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define this if you have the POSIX termios library */ +#define HAVE_TERMIOS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to indicate that float storage follows IEEE754. */ +#define IEEE_FLOAT 1 + +/* size of the frame index seek table */ +#define INDEX_SIZE 1000 + +/* Define if IPV6 support is enabled. */ +#define IPV6 1 + +/* Define this to the size of native offset type in bits, used for LFS alias + functions. */ +#define LFS_ALIAS_BITS 64 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* The suffix for module files. */ +#define MODULE_FILE_SUFFIX ".la" + +/* Define if network support is enabled. */ +#define NETWORK 1 + +/* Define to disable 16 bit integer output. */ +/* #undef NO_16BIT */ + +/* Define to disable 32 bit and 24 bit integer output. */ +/* #undef NO_32BIT */ + +/* Define to disable 8 bit integer output. */ +/* #undef NO_8BIT */ + +/* Define to disable downsampled decoding. */ +/* #undef NO_DOWNSAMPLE */ + +/* Define to disable equalizer. */ +/* #undef NO_EQUALIZER */ + +/* Define to disable error messages in combination with a return value (the + return is left intact). */ +/* #undef NO_ERETURN */ + +/* Define to disable error messages. */ +/* #undef NO_ERRORMSG */ + +/* Define to disable feeder and buffered readers. */ +/* #undef NO_FEEDER */ + +/* Define to disable ICY handling. */ +/* #undef NO_ICY */ + +/* Define to disable ID3v2 parsing. */ +/* #undef NO_ID3V2 */ + +/* Define to disable layer I. */ +/* #undef NO_LAYER1 */ + +/* Define to disable layer II. */ +/* #undef NO_LAYER2 */ + +/* Define to disable layer III. */ +/* #undef NO_LAYER3 */ + +/* Define to disable ntom resampling. */ +/* #undef NO_NTOM */ + +/* Define to disable real output. */ +/* #undef NO_REAL */ + +/* Define to disable string functions. */ +/* #undef NO_STRING */ + +/* Define for post-processed 32 bit formats. */ +/* #undef NO_SYNTH32 */ + +/* Define to disable warning messages. */ +/* #undef NO_WARNING */ + +/* Name of package */ +#define PACKAGE "mpg123" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "maintainer@mpg123.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "mpg123" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "mpg123 1.24.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "mpg123" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.24.0" + +/* Define if portaudio v18 API is wanted. */ +/* #undef PORTAUDIO18 */ + +/* The size of `int32_t', as computed by sizeof. */ +#define SIZEOF_INT32_T 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `ssize_t', as computed by sizeof. */ +#define SIZEOF_SSIZE_T 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if modules are enabled */ +#define USE_MODULES 1 + +/* Define for new Huffman decoding scheme. */ +#define USE_NEW_HUFFTABLE 1 + +/* Define to use yasm for assemble AVX sources. */ +/* #undef USE_YASM_FOR_AVX */ + +/* Version number of package */ +#define VERSION "1.24.0" + +/* Define to use Win32 named pipes */ +/* #undef WANT_WIN32_FIFO */ + +/* Define to use Win32 sockets */ +/* #undef WANT_WIN32_SOCKETS */ + +/* Define to use Unicode for Windows */ +/* #undef WANT_WIN32_UNICODE */ + +/* WinXP and above for ipv6 */ +/* #undef WINVER */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* WinXP and above for ipv6 */ +/* #undef _WIN32_WINNT */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `short' if does not define. */ +/* #undef int16_t */ + +/* Define to `int' if does not define. */ +/* #undef int32_t */ + +/* Define to `long long' if does not define. */ +/* #undef int64_t */ + +/* Define to the native offset type (long or actually off_t). */ +#define lfs_alias_t off_t + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to `unsigned long' if does not define. */ +/* #undef size_t */ + +/* Define to `long' if does not define. */ +/* #undef ssize_t */ + +/* Define to `unsigned short' if does not define. */ +/* #undef uint16_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef uint32_t */ + +/* Define to `unsigned long' if does not define. */ +/* #undef uintptr_t */ diff --git a/src/config/linux/x64/out123.h b/src/config/linux/x64/out123.h new file mode 100644 index 0000000..8fde88b --- /dev/null +++ b/src/config/linux/x64/out123.h @@ -0,0 +1,583 @@ +/* + out123: audio output interface + + copyright 1995-2016 by the mpg123 project, + free software under the terms of the LGPL 2.1 + + see COPYING and AUTHORS files in distribution or http://mpg123.org + initially written as audio.h by Michael Hipp, reworked into out123 API + by Thomas Orgis +*/ + +#ifndef _OUT123_H_ +#define _OUT123_H_ + +/** \file out123.h The header file for the libout123 audio output facility. */ + +/* We only need size_t definition. */ +#include + +/* Common audio encoding specification, including a macro for getting + * size of encodined samples in bytes. Said macro is still hardcoded + * into out123_encsize(). Relying on this one may help an old program + * know sizes of encodings added to fmt123.h later on. + * If you don't care, just use the macro. + */ +#include + +/** A macro to check at compile time which set of API functions to expect. + * This should be incremented at least each time a new symbol is added + * to the header. + */ +#define OUT123_API_VERSION 1 + +#ifndef MPG123_EXPORT +/** Defines needed for MS Visual Studio(tm) DLL builds. + * Every public function must be prefixed with MPG123_EXPORT. When building + * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible + * for clients and includes it in the import library which is created together + * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which + * imports the functions from the DLL. + */ +#ifdef BUILD_MPG123_DLL +/* The dll exports. */ +#define MPG123_EXPORT __declspec(dllexport) +#else +#ifdef LINK_MPG123_DLL +/* The exe imports. */ +#define MPG123_EXPORT __declspec(dllimport) +#else +/* Nothing on normal/UNIX builds */ +#define MPG123_EXPORT +#endif +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup out123_api out123 library API + * This is out123, a library focused on continuous playback of audio streams + * via various platform-specific output methods. It glosses over details of + * the native APIs to give an interface close to simply writing data to a + * file. There might be the option to tune details like buffer (period) sizes + * and the number of them on the device side in future, but the focus of the + * library is to ease the use case of just getting that raw audio data out + * there, without interruptions. + * + * The basic idea is to create a handle with out123_new() and open a certain + * output device (using a certain driver module, possibly build-time defaults) + * with out123_open(). Now, you can query the output device for supported + * encodings for given rate and channel count with out123_get_encodings() and + * decide what to use for actually starting playback with out123_start(). + * + * Then, you just need to provide (interleaved pcm) data for playback with + * out123_play(), which will block when the device's buffers are full. You get + * your timing from that (instead of callbacks). If your program does the + * production of the audio data just a little bit faster than the playback, + * causing out123_play() to block ever so briefly, you're fine. + * + * You stop playback with out123_stop(), or just close the device and driver + * via out123_close(), or even just decide to drop it all and do out123_del() + * right away when you're done. + * + * There are other functions for specific needs, but the basic idea should be + * covered by the above. + @{ + */ + +/** Opaque structure for the libout123 handle. */ +struct out123_struct; +/** Typedef shortcut as preferrend name for the handle type. */ +typedef struct out123_struct out123_handle; + +/** Enumeration of codes for the parameters that it is possible to set/get. */ +enum out123_parms +{ + OUT123_FLAGS = 1 /**< integer, various flags, see enum out123_flags */ +, OUT123_PRELOAD /**< float, fraction of buffer to fill before playback */ +, OUT123_GAIN /**< integer, output device gain (module-specific) */ +, OUT123_VERBOSE /**< integer, verbosity to stderr, >= 0 */ +, OUT123_DEVICEBUFFER /**< + * float, length of device buffer in seconds; + * This might be ignored, might have only a loose relation to actual + * buffer sizes and latency, depending on output driver. Try to tune + * this before opening a device if you want to influcence latency or reduce + * dropouts. Value <= 0 uses some default, usually favouring stable playback + * over low latency. Values above 0.5 are probably too much. + */ +, OUT123_PROPFLAGS /**< integer, query driver/device property flags (r/o) */ +, OUT123_NAME /**< string, name of this instance (NULL restores default); + * The value returned by out123_getparam() might be different if the audio + * backend changed it (to be unique among clients, p.ex.). + * TODO: The name provided here is used as prefix in diagnostic messages. */ +}; + +/** Flags to tune out123 behaviour */ +enum out123_flags +{ + OUT123_HEADPHONES = 0x01 /**< output to headphones (if supported) */ +, OUT123_INTERNAL_SPEAKER = 0x02 /**< output to speaker (if supported) */ +, OUT123_LINE_OUT = 0x04 /**< output to line out (if supported) */ +, OUT123_QUIET = 0x08 /**< no printouts to standard error */ +, OUT123_KEEP_PLAYING = 0x10 /**< + * When this is set (default), playback continues in a loop when the device + * does not consume all given data at once. This happens when encountering + * signals (like SIGSTOP, SIGCONT) that cause interruption of the underlying + * functions. + * Note that this flag is meaningless when the optional buffer is employed, + * There, your program will always block until the buffer completely took + * over the data given to it via out123_play(), unless a communcation error + * arises. + */ +}; + +/** Read-only output driver/device property flags (OUT123_PROPFLAGS). */ +enum out123_propflags +{ + OUT123_PROP_LIVE = 0x01 /**< This is a live output, meaning that + * special care might be needed for pauses in playback (p.ex. stream + * of silence instead of interruption), as opposed to files on disk. + */ +, OUT123_PROP_PERSISTENT = 0x02 /**< This (live) output does not need + * special care for pauses (continues with silence itself), + * out123_pause() does nothing to the device. + */ +}; + +/** Create a new output handle. + * This only allocates and initializes memory, so the only possible + * error condition is running out of memory. + * \return pointer to new handle or NULL on error + */ +MPG123_EXPORT +out123_handle *out123_new(void); + +/** Delete output handle. + * This implies out123_close(). + */ +MPG123_EXPORT +void out123_del(out123_handle *ao); + +/** Error code enumeration + * API calls return a useful (positve) value or zero (OUT123_OK) on simple + * success. A negative value (-1 == OUT123_ERR) usually indicates that some + * error occured. Which one, that can be queried using out123_errcode() + * and friends. + */ +enum out123_error +{ + OUT123_ERR = -1 /**< generic alias for verbosity, always == -1 */ +, OUT123_OK = 0 /**< just a name for zero, not going to change */ +, OUT123_DOOM /**< dazzled, out of memory */ +, OUT123_BAD_DRIVER_NAME /**< bad driver name given */ +, OUT123_BAD_DRIVER /**< unspecified issue loading a driver */ +, OUT123_NO_DRIVER /**< no driver loaded */ +, OUT123_NOT_LIVE /**< no active audio device */ +, OUT123_DEV_PLAY /**< some device playback error */ +, OUT123_DEV_OPEN /**< error opening device */ +, OUT123_BUFFER_ERROR /**< + * Some (really unexpected) error in buffer infrastructure. + */ +, OUT123_MODULE_ERROR /**< basic failure in module loading */ +, OUT123_ARG_ERROR /**< some bad function arguments supplied */ +, OUT123_BAD_PARAM /**< unknown parameter code */ +, OUT123_SET_RO_PARAM /**< attempt to set read-only parameter */ +, OUT123_BAD_HANDLE /**< bad handle pointer (NULL, usually) */ +, OUT123_ERRCOUNT /**< placeholder for shaping arrays */ +}; + +/** Get string representation of last encountered error in the + * context of given handle. + * \param ao handle + * \return error string + */ +MPG123_EXPORT +const char* out123_strerror(out123_handle *ao); + +/** Get the plain errcode intead of a string. + * Note that this used to return OUT123_ERR instead of + * OUT123_BAD_HANDLE in case of ao==NULL before mpg123-1.23.5 . + * \param ao handle + * \return error code recorded in handle or OUT123_BAD_HANDLE + */ +MPG123_EXPORT +int out123_errcode(out123_handle *ao); + +/** Return the error string for a given error code. + * \param errcode the integer error code + * \return error string + */ +MPG123_EXPORT +const char* out123_plain_strerror(int errcode); + +/** Set a desired output buffer size. + * This starts a separate process that handles the audio output, decoupling + * the latter from the main process with a memory buffer and saving you the + * burden to ensure sparing CPU cycles for actual playback. + * This is for applicatons that prefer continuous playback over small latency. + * In other words: The kind of applications that out123 is designed for. + * This routine always kills off any currently active audio output module / + * device, even if you just disable the buffer when there is no buffer. + * + * Keep this in mind for memory-constrainted systems: Activating the + * buffer causes a fork of the calling process, doubling the virtual memory + * use. Depending on your operating system kernel's behaviour regarding + * memory overcommit, it might be wise to call out123_set_buffer() very + * early in your program before allocating lots of memory. + * + * There _might_ be a change to threads in future, but for now this is + * classic fork with shared memory, working without any threading library. + * If your platform or build does not support that, you will always get an + * error on trying to set up a non-zero buffer (but the API call will be + * present). + * + * Also, if you do intend to use this from a multithreaded program, think + * twice and make sure that your setup is happy with forking full-blown + * processes off threaded programs. Probably you are better off spawning a + * buffer thread yourself. + * + * \param ao handle + * \param buffer_bytes size (bytes) of a memory buffer for decoded audio, + * a value of zero disables the buffer. + * \return 0 on success, OUT123_ERR on error + */ +MPG123_EXPORT +int out123_set_buffer(out123_handle *ao, size_t buffer_bytes); + +/** Set a specific parameter, for a specific out123_handle, using a parameter + * code chosen from the out123_parms enumeration, to the specified value. + * The parameters usually only change what happens on next out123_open, not + * incfluencing running operation. + * \param ao handle + * \param code parameter code + * \param value input value for integer parameters + * \param fvalue input value for floating point parameters + * \param svalue input value for string parameters (contens are copied) + * \return 0 on success, OUT123_ERR on error. + */ +MPG123_EXPORT +int out123_param( out123_handle *ao, enum out123_parms code +, long value, double fvalue, const char *svalue ); +#define out123_param_int(ao, code, value) \ + out123_param((ao), (code), (value), 0., NULL) +#define out123_param_float(ao, code, value) \ + out123_param((ao), (code), 0, (value), NULL) +#define out123_param_string(ao, code, value) \ + out123_param((ao), (code), 0, 0., (value)) + +/** Get a specific parameter, for a specific out123_handle, using a parameter + * code chosen from the out123_parms enumeration, to the specified value. + * \param ao handle + * \param code parameter code + * \param ret_value output address for integer parameters + * \param ret_fvalue output address for floating point parameters + * \param ret_svalue output address for string parameters (pointer to + * internal memory, so no messing around, please) + * \return 0 on success, OUT123_ERR on error (bad parameter name or bad handle). + */ +MPG123_EXPORT +int out123_getparam( out123_handle *ao, enum out123_parms code +, long *ret_value, double *ret_fvalue, char* *ret_svalue ); +#define out123_getparam_int(ao, code, value) \ + out123_getparam((ao), (code), (value), NULL, NULL) +#define out123_getparam_float(ao, code, value) \ + out123_getparam((ao), (code), NULL, (value), NULL) +#define out123_getparam_string(ao, code, value) \ + out123_getparam((ao), (code), NULL, NULL, (value)) + +/** Copy parameters from another out123_handle. + * \param ao handle + * \param from_ao the handle to copy parameters from + * \return 0 in success, -1 on error + */ +MPG123_EXPORT +int out123_param_from(out123_handle *ao, out123_handle* from_ao); + +/** Get list of driver modules reachable in system in C argv-style format. + * The client is responsible for freeing the memory of both the individual + * strings and the lists themselves. + * A module that is not loadable because of missing libraries is simply + * skipped. You will get stderr messages about that unless OUT123_QUIET was + * was set, though. Failure to open the module directory is a serious error, + * resulting in negative return value. + * \param ao handle + * \param names address for storing list of names + * \param descr address for storing list of descriptions + * \return number of drivers found, -1 on error + */ +MPG123_EXPORT +int out123_drivers(out123_handle *ao, char ***names, char ***descr); + +/** Open an output device with a certain driver + * Note: Opening means that the driver code is loaded and the desired + * device name recorded, possibly tested for availability or tentatively + * opened. After out123_open(), you can ask for supported encodings + * and then really open the device for playback with out123_start(). + * \param ao handle + * \param driver (comma-separated list of) output driver name(s to try), + * NULL for default (stdout for file-based drivers) + * \param device device name to open, NULL for default + * \return 0 on success, -1 on error. + */ +MPG123_EXPORT +int out123_open(out123_handle *ao, const char* driver, const char* device); + +/** Give info about currently loaded driver and device + * Any of the return addresses can be NULL if you are not interested in + * everything. You get pointers to internal storage. They are valid + * as long as the driver/device combination is opened. + * The device may be NULL indicating some unnamed default. + * TODO: Make the driver modules return names for such defaults. + * \param ao handle + * \param driver return address for driver name + * \param device return address for device name + * \return 0 on success, -1 on error (i.e. no driver loaded) + */ +MPG123_EXPORT +int out123_driver_info(out123_handle *ao, char **driver, char **device); + +/** Close the current output device and driver. + * This implies out123_drain() to ensure no data is lost. + * With a buffer, that might cause considerable delay during + * which your main application is blocked waiting. + * Call out123_drop() beforehand if you want to end things + * quickly. + * \param ao handle + */ +MPG123_EXPORT +void out123_close(out123_handle *ao); + +/** Get supported audio encodings for given rate and channel count, + * for the currently openend audio device. + * TODO: Reopening the underlying audio device for each query + * is dumb, at least when dealing with JACK. It takes + * a long time and is just a waste. Reconsider that. + * Make sure that all output modules are fine with it, though! + * Usually, a wider range of rates is supported, but the number + * of sample encodings is limited, as is the number of channels. + * So you can call this with some standard rate and hope that the + * returned encodings work also for others, with the tested channel + * count. + * The return value of -1 on some encountered error conveniently also + * does not match any defined format (only 15 bits used for encodings, + * so this would even work with 16 bit integers). + * This implies out123_stop() to enter query mode. + * \param ao handle + * \param rate sampling rate + * \param channels number of channels + * \return supported encodings combined with bitwise or, to be checked + * against your favourite bitmask, -1 on error + */ +MPG123_EXPORT +int out123_encodings(out123_handle *ao, long rate, int channels); + +/** Return the size (in bytes) of one mono sample of the named encoding. + * \param encoding The encoding value to analyze. + * \return positive size of encoding in bytes, 0 on invalid encoding. */ +MPG123_EXPORT int out123_encsize(int encoding); + +/** Get list of supported formats for currently opened audio device. + * Given a list of sampling rates and minimal/maximal channel count, + * this quickly checks what formats are supported with these + * constraints. The first entry is always reserved for a default + * format for the output device. If there is no such default, + * all values of the format are -1. + * For each requested combination of rate and channels, a format entry is + * created, possible with encoding value 0 to indicate that this combination + * has been tested and rejected. So, when there is no basic error, the + * number of returned format entries should be + * (ratecount*(maxchannels-minchannels+1)+1) + * . But instead of forcing you to guess, this will be allocated by + * successful run. + * For the first entry, the encoding member is supposed to be a definite + * encoding, for the others it is a bitwise combination of all possible + * encodings. + * This function is more efficient than many calls to out123_encodings(). + * \param ao handle + * \param rates pointer to an array of sampling rates, may be NULL for none + * \param ratecount number of provided sampling rates + * \param minchannels minimal channel count + * \param maxchannels maximal channel count + * \param fmtlist return address for array of supported formats + * the encoding field of each entry is a combination of all + * supported encodings at this rate and channel count; + * Memory shall be freed by user. + * \return number of returned format enries, -1 on error + */ +MPG123_EXPORT +int out123_formats( out123_handle *ao, const long *rates, int ratecount + , int minchannels, int maxchannels + , struct mpg123_fmt **fmtlist ); + +/** Get list of encodings known to the library. + * You are responsible for freeing the allocated array. + * \param enclist return address for allocated array of encoding codes + * \return number of encodings, -1 on error + */ +MPG123_EXPORT +int out123_enc_list(int **enclist); + +/** Find encoding code by name. + * \param name short or long name to find encoding code for + * \return encoding if found (enum mpg123_enc_enum), else 0 + */ +MPG123_EXPORT +int out123_enc_byname(const char *name); + +/** Get name of encoding. + * \param encoding code (enum mpg123_enc_enum) + * \return short name for valid encodings, NULL otherwise + */ +MPG123_EXPORT +const char* out123_enc_name(int encoding); + +/** Get long name of encoding. + * \param encoding code (enum mpg123_enc_enum) + * \return long name for valid encodings, NULL otherwise + */ +MPG123_EXPORT +const char* out123_enc_longname(int encoding); + +/** Start playback with a certain output format + * It might be a good idea to have audio data handy to feed after this + * returns with success. + * Rationale for not taking a pointer to struct mpg123_fmt: This would + * always force you to deal with that type and needlessly enlarge the + * shortest possible program. + * \param ao handle + * \param encoding sample encoding (values matching libmpg123 API) + * \param channels number of channels (1 or 2, usually) + * \param rate sampling rate + * \return 0 on success, negative on error (bad format, usually) + */ +MPG123_EXPORT +int out123_start( out123_handle *ao +, long rate, int channels, int encoding ); + +/** Pause playback + * Interrupt playback, holding any data in the optional buffer. + * + * This closes the audio device if it is a live sink, ready to be re-opened + * by out123_continue() or out123_play() with the existing parameters. + * \param ao handle + */ +MPG123_EXPORT +void out123_pause(out123_handle *ao); + +/** Continue playback + * The counterpart to out123_pause(). Announce to the driver that playback + * shall continue. + * + * Playback might not resume immediately if the optional buffer is configured + * to wait for a minimum fill and close to being empty. You can force playback + * of the last scrap with out123_drain(), or just by feeding more data with + * out123_play(), which will trigger out123_continue() for you, too. + * \param ao handle + */ +MPG123_EXPORT +void out123_continue(out123_handle *ao); + +/** Stop playback. + * This waits for pending audio data to drain to the speakers. + * You might want to call out123_drop() before stopping if you want + * to end things right away. + * \param ao handle + */ +MPG123_EXPORT +void out123_stop(out123_handle *ao); + +/** Hand over data for playback and wait in case audio device is busy. + * This survives non-fatal signals like SIGSTOP/SIGCONT and keeps on + * playing until the buffer is done with if the flag + * OUT123_KEEP_PLAYING ist set (default). So, per default, if + * you provided a byte count divisible by the PCM frame size, it is an + * error when less bytes than given are played. + * To be sure if an error occured, check out123_errcode(). + * Also note that it is no accident that the buffer parameter is not marked + * as constant. Some output drivers might need to do things like swap + * byte order. This is done in-place instead of wasting memory on yet + * another copy. + * \param ao handle + * \param buffer pointer to raw audio data to be played + * \param bytes number of bytes to read from the buffer + * \return number of bytes played (might be less than given, even zero) + */ +MPG123_EXPORT +size_t out123_play( out123_handle *ao + , void *buffer, size_t bytes ); + +/** Drop any buffered data, making next provided data play right away. + * This does not imply an actual pause in playback. + * You are expected to play something, unless you called out123_pause(). + * Feel free to call out123_stop() afterwards instead for a quicker + * exit than the implied out123_drain(). + * For live sinks, this may include dropping data from their buffers. + * For others (files), this only concerns data in the optional buffer. + * \param ao handle + */ +MPG123_EXPORT +void out123_drop(out123_handle *ao); + +/** Drain the output, waiting until all data went to the hardware. + * This does imply out123_continue() before and out123_pause() + * after draining. + * This might involve only the optional buffer process, or the + * buffers on the audio driver side, too. + * \param ao handle + */ +MPG123_EXPORT +void out123_drain(out123_handle *ao); + +/** Drain the output, but only partially up to the given number of + * bytes. This gives you the opportunity to do something while + * the optional buffer is writing remaining data instead of having + * one atomic API call for it all. + * + * It is wholly expected that the return value of out123_buffered() + * before and after calling this has a bigger difference than the + * provided limit, as the buffer is writing all the time in the + * background. + * + * This is just a plain out123_drain() if the optional buffer is not + * in use. Also triggers out123_continue(), but only out123_pause() + * if there is no buffered data anymore. + * \param ao handle + * \param bytes limit of buffered bytes to drain + * \return number of bytes drained from buffer + */ +MPG123_EXPORT +void out123_ndrain(out123_handle *ao, size_t bytes); + +/** Get an indication of how many bytes reside in the optional buffer. + * This might get extended to tell the number of bytes queued up in the + * audio backend, too. + * \param ao handle + * \return number of bytes in out123 library buffer + */ +MPG123_EXPORT +size_t out123_buffered(out123_handle *ao); + +/** Extract currently used audio format from handle. + * matching mpg123_getformat(). + * Given return addresses may be NULL to indicate no interest. + * \param ao handle + * \param rate address for sample rate + * \param channels address for channel count + * \param encoding address for encoding + * \param framesize size of a full PCM frame (for convenience) + * \return 0 on success, -1 on error + */ +MPG123_EXPORT +int out123_getformat( out123_handle *ao +, long *rate, int *channels, int *encoding, int *framesize ); + +/* @} */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mpg123.gyp b/src/mpg123.gyp index cb6a366..835283c 100644 --- a/src/mpg123.gyp +++ b/src/mpg123.gyp @@ -1,6 +1,17 @@ { 'variables': { - 'target_arch%': 'ia32' + 'target_arch%': 'ia32', + 'conditions': [ + ['OS=="mac"', { + 'mpg123_module%': 'coreaudio' + }], + ['OS=="win"', { + 'mpg123_module%': 'win32' + }], + ['OS=="linux"', { + 'mpg123_module%': 'alsa' + }] + ] }, 'target_defaults': { 'configurations': { @@ -70,49 +81,72 @@ { 'target_name': 'compat', 'type': 'static_library', - 'include_dirs': [ - 'util', - 'mpg123/src', - 'mpg123/src/compat', - 'mpg123/src/libmpg123', - 'config/<(OS)/<(target_arch)' - ], 'defines': [ 'PIC', 'NOXFERMEM', 'HAVE_CONFIG_H' ], - 'direct_dependent_settings': { - 'include_dirs': [ - 'util', - 'mpg123/src', - 'mpg123/src/compat', - 'mpg123/src/libmpg123', - 'config/<(OS)/<(target_arch)' - ] - }, 'sources': [ 'mpg123/src/compat/compat.c', 'mpg123/src/compat/compat_str.c' - ] + ], + 'conditions': [ + ['mpg123_module=="coreaudio"', { + 'direct_dependent_settings': { + 'include_dirs': [ + 'mpg123/src', + 'mpg123/src/compat', + 'mpg123/src/libmpg123', + 'config/<(OS)/<(target_arch)' + ] + }, + 'include_dirs': [ + 'mpg123/src', + 'mpg123/src/compat', + 'mpg123/src/libmpg123', + 'config/<(OS)/<(target_arch)' + ], + }], + ['mpg123_module=="win32"', { + 'direct_dependent_settings': { + 'include_dirs': [ + 'util', + 'mpg123/src', + 'mpg123/src/compat', + 'mpg123/src/libmpg123', + 'config/<(OS)/<(target_arch)' + ] + }, + 'include_dirs': [ + 'util', + 'mpg123/src', + 'mpg123/src/compat', + 'mpg123/src/libmpg123', + 'config/<(OS)/<(target_arch)' + ], + }], + ['mpg123_module=="alsa"', { + 'direct_dependent_settings': { + 'include_dirs': [ + 'mpg123/src', + 'mpg123/src/compat', + 'mpg123/src/libmpg123', + 'config/<(OS)/<(target_arch)' + ] + }, + 'include_dirs': [ + 'mpg123/src', + 'mpg123/src/compat', + 'mpg123/src/libmpg123', + 'config/<(OS)/<(target_arch)' + ], + }] + ], }, { 'target_name': 'module', 'type': 'static_library', 'dependencies': ['compat', 'out123' ], - 'variables': { - 'conditions': [ - ['OS=="mac"', { - 'mpg123_module%': 'coreaudio' - }], - ['OS=="win"', { - 'mpg123_module%': 'win32' - }], - ['OS=="linux"', { - 'mpg123_module%': 'alsa' - }] - ] - }, 'include_dirs': [ 'mpg123/src/libout123/modules', 'config/<(OS)/<(target_arch)' From 23ca6f9cc317f9c23b591cb138abd365a5bddb42 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Thu, 6 Oct 2016 14:15:31 +1300 Subject: [PATCH 07/96] Add libasound to .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c95a388..201d39b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ addons: packages: - libgnome-keyring-dev - g++-4.8 + - libasound2-dev sources: - ubuntu-toolchain-r-test env: From 9b83b6d5ac428b71bd9c4b26253775103626f8df Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Thu, 6 Oct 2016 14:37:03 +1300 Subject: [PATCH 08/96] Add node-gyp to travis script --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 201d39b..b41206d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,10 @@ install: - npm install -g npm - npm install -g node-gyp - npm install +script: + - node -v + - npm -v + - node-gyp rebuild matrix: fast_finish: true allow_failures: From 988ab971f5b5bface711d7de0a61c014b45401b7 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 15 Oct 2016 12:21:08 +1300 Subject: [PATCH 09/96] JavaScript Implementation (#24) JavaScript implementation for audio-speaker release-2.0. --- index.js | 185 ++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 +- src/binding.cpp | 30 +++++--- 3 files changed, 208 insertions(+), 12 deletions(-) create mode 100644 index.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..06de379 --- /dev/null +++ b/index.js @@ -0,0 +1,185 @@ +var os = require('os') +var objectAssign = require('object-assign') +var binding = require('bindings')('binding') +var pcm = require('pcm-util') +var isAudioBuffer = require('is-audio-buffer') +var debug = require('debug')('speaker') + +var endianess = 'function' == os.endianess ? os.endianess() : 'LE' + +module.exports = Speaker + +function Speaker (opts) { + debug('Speaker()') + var options = {} + + objectAssign(options, opts) + + if (options.handler) { + throw new Error('_create() was called more than once. Only one handler should exist') + } + + options._closed = false; + + _validate(options) + + var format = exports.getFormat(options); + if (format === null) { + throw new Error('Invalid format options') + } + + options.blockAlign = options.bitDepth / 8 * options.channels + + options.chunkSize = options.blockAlign * options.samplesPerFrame + + options.handler = binding.create() + + if (options.handler !== null) { + debug('_start(%o)', Object.values(options)) + binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { + if (success != 1) { + throw new Error('Could not start the audio output with these properties') + } else { + debug('Created and started handler successfully') + } + }) + } + + return function write (chunk, callback) { + debug('write() (%o bytes)', chunk.length) + if (options._closed) return debug('write() cannot be called after the speaker is closed.') + + if (options.handler) { + var buffer = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk + + var current + var remaining + + if (remaining.length > 0) { + current = remaining + remaining = chunk + } else { + current = chunk + remaining = null + } + + if (current.length > options.chunkSize) { + var temp = current + current = temp.slice(0, options.chunkSize) + remaining = temp.slice(options.chunkSize) + } else { + remaining = null + } + + debug('Writing %o byte chunk', current.length) + binding.write(options.handler, current, current.length, ) + + function onWrite (written) { + debug('Wrote %o bytes', chunk.length) + if (written != chunk.length) { + callback(new Error('write() failed when writing: ' + chunk), chunk) + } else if (remaining) { + debug('Writing %o remaining bytes in the chunk.', left.length) + write() + } else { + debug('Finished writing chunk.') + callback(null, chunk) + } + } + } + } + + function _validate (options) { + debug('Format: Setting options - %o', Object.keys(options)) + if (options.channels !== null) { + debug('Format: Setting %o - %o', 'channels', options.channels) + } else { + debug('Format: Setting %o - %o', 'channels', 2) + options.channels = 2 + } + if (options.bitDepth !== null) { + debug('Format: Setting %o - %o', 'bitDepth', options.bitDepth) + } else { + debug('Format: Setting %o - %o', 'bitDepth', options.float ? 32 : 16) + options.bitDepth = options.float ? 32 : 16 + } + if (options.sampleRate !== null) { + debug('Format: Setting %o - %o', 'sampleRate', options.sampleRate) + } else { + debug('Format: Setting %o - %o', 'sampleRate', 44100) + options.sampleRate = 44100 + } + if (options.signed !== null) { + debug('Format: Setting %o - %o', 'signed', options.signed) + } else { + debug('Format: Setting %o - %o', 'signed', options.bitDepth != 8) + options.signed = options.bitDepth != 8 + } + if (options.samplesPerFrame !== null) { + debug('Format: Setting %o - %o', 'samplesPerFrame', options.samplesPerFrame) + } else { + debug('Format: Settings &o - %o', 'samplesPerFrame', 1024) + options.samplesPerFrame = 1024 + } + if (options.float !== null) { + debug('Format: Setting %o - %o', 'float', options.float) + } + options.endianess = endianess; + debug('Format: Settings applied') + } + + function function end (flush, callback) { + debug('end(%o)', flush) + if (options._closed) return debug('_end() was called more than once. Already ended') + + if (options.handler) { + if (flush) { + debug('Flushing the audio output') + binding.flush(options.handler, function (success) { + if (success != 1) { + debug('Could not flush the audio output') + } else { + return close(callback) + } + }) + } else { + return close(callback) + } + } else { + debug('Could not flush the audio output because handler does not exist') + } + + function close (callback) { + debug('close()') + binding.close(options.handler, callback) + options._closed = true + options.handler = null + } + } +} + +Speaker.getFormat = function getFormat (format) { + var f = null; + if (format.bitDepth == 32 && format.float && format.signed) { + f = binding.MPG123_ENC_FLOAT_32; + } else if (format.bitDepth == 64 && format.float && format.signed) { + f = binding.MPG123_ENC_FLOAT_64; + } else if (format.bitDepth == 8 && format.signed) { + f = binding.MPG123_ENC_SIGNED_8; + } else if (format.bitDepth == 8 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_8; + } else if (format.bitDepth == 16 && format.signed) { + f = binding.MPG123_ENC_SIGNED_16; + } else if (format.bitDepth == 16 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_16; + } else if (format.bitDepth == 24 && format.signed) { + f = binding.MPG123_ENC_SIGNED_24; + } else if (format.bitDepth == 24 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_24; + } else if (format.bitDepth == 32 && format.signed) { + f = binding.MPG123_ENC_SIGNED_32; + } else if (format.bitDepth == 32 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_32; + } + return f; +} diff --git a/package.json b/package.json index d2a5d22..488f4c0 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,9 @@ "dependencies": { "bindings": "^1.2.1", "debug": "^2.2.0", - "nan": "2.2.0" + "is-audio-buffer": "^1.0.1", + "nan": "2.2.0", + "object-assign": "^4.1.0", + "pcm-util": "^2.0.3" } } diff --git a/src/binding.cpp b/src/binding.cpp index 7cc6476..dda0cd6 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -10,8 +10,8 @@ namespace { uv_work_t req; out123_handle *ao; unsigned char *buffer; - int length; - int done; + int len; + int written; Nan::Callback *callback; }; @@ -23,20 +23,28 @@ namespace { NAN_METHOD(create) { Nan::EscapableHandleScope scope; + int value = 0; + out123_handle *ao = out123_new(); if(!ao) { fprintf(stderr, "Failed to initialize output handle."); out123_del(ao); + value = 0; } else if(out123_open(ao, NULL, NULL) != OUT123_OK) { fprintf(stderr, "Failed to open output: %s", out123_strerror(ao)); out123_del(ao); + value = 0; + } else { + value = 1; } + result_callback(new Nan::Callback(info[4].As()), value); + info.GetReturnValue().Set(scope.Escape(WrapPointer(&ao, static_cast(sizeof(&ao))))); } - NAN_METHOD(start) { + NAN_METHOD(open) { Nan::HandleScope scope; out123_handle *ao = UnwrapPointer(info[0]); @@ -46,7 +54,7 @@ namespace { int encoding = info[3]->Int32Value(); int value = 0; - + if(out123_start(ao, rate, channels, encoding) && !ao) { fprintf(stderr, "Failed to start output: %s", out123_strerror(ao)); out123_del(ao); @@ -70,8 +78,8 @@ namespace { write_req *req = new write_req; req->ao = ao; req->buffer = buffer; - req->length = length; - req->done = 0; + req->len = length; + req->written = 0; req->callback = new Nan::Callback(info[3].As()); req->req.data = req; @@ -83,7 +91,7 @@ namespace { NAN_METHOD(flush) { Nan::HandleScope scope; - + out123_handle *ao = UnwrapPointer(info[0]); int value = 0; @@ -131,7 +139,7 @@ namespace { void write_async(uv_work_t *req) { write_req *wreq = reinterpret_cast(req->data); - wreq->done = out123_play(wreq->ao, wreq->buffer, wreq->length); + wreq->written = out123_play(wreq->ao, wreq->buffer, wreq->len); } void write_after(uv_work_t *req) { @@ -140,7 +148,7 @@ namespace { write_req *wreq = reinterpret_cast(req->data); Local argv[] = { - Nan::New(wreq->done) + Nan::New(wreq->written) }; wreq->callback->Call(1, argv); @@ -186,11 +194,11 @@ namespace { CONST_INT(MPG123_ENC_UNSIGNED_32); Nan::SetMethod(target, "create", create); - Nan::SetMethod(target, "start", start); + Nan::SetMethod(target, "open", open); Nan::SetMethod(target, "write", write); Nan::SetMethod(target, "flush", flush); Nan::SetMethod(target, "close", close); } } -NODE_MODULE(binding, InitializeModule); \ No newline at end of file +NODE_MODULE(binding, InitializeModule); From b8969197df0b42e8433816c0f82cb4223a3d7fb7 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 22 Oct 2016 13:35:54 +1300 Subject: [PATCH 10/96] Add test and fix most bugs --- index.js | 39 +++++++++++++++++++++--------------- package.json | 8 ++++++-- src/binding.cpp | 24 +++++++++++++--------- src/config/win/ia32/config.h | 2 +- src/config/win/x64/config.h | 2 +- src/pointer_wrapper.h | 8 ++++---- test.js | 13 ++++++++++++ 7 files changed, 63 insertions(+), 33 deletions(-) create mode 100644 test.js diff --git a/index.js b/index.js index 06de379..ec5a818 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,7 @@ var objectAssign = require('object-assign') var binding = require('bindings')('binding') var pcm = require('pcm-util') var isAudioBuffer = require('is-audio-buffer') +var audioBuffer = require('audio-buffer') var debug = require('debug')('speaker') var endianess = 'function' == os.endianess ? os.endianess() : 'LE' @@ -23,7 +24,7 @@ function Speaker (opts) { _validate(options) - var format = exports.getFormat(options); + var format = Speaker.getFormat(options); if (format === null) { throw new Error('Invalid format options') } @@ -32,12 +33,18 @@ function Speaker (opts) { options.chunkSize = options.blockAlign * options.samplesPerFrame - options.handler = binding.create() + options.handler = binding.create((success) => { + if(!success) { + throw new Error('Failed to create the audio handler.') + } else { + debug('_create() audio handle successfully.') + } + }) if (options.handler !== null) { - debug('_start(%o)', Object.values(options)) + debug('_start(%o)', Object.keys(options)) binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { - if (success != 1) { + if (!success) { throw new Error('Could not start the audio output with these properties') } else { debug('Created and started handler successfully') @@ -55,11 +62,11 @@ function Speaker (opts) { var current var remaining - if (remaining.length > 0) { - current = remaining - remaining = chunk + if (remaining != null) { + current = new audioBuffer(options.channels, remaining) + remaining = new audioBuffer(options.channels, chunk) } else { - current = chunk + current = new audioBuffer(options.channels, chunk) remaining = null } @@ -72,7 +79,7 @@ function Speaker (opts) { } debug('Writing %o byte chunk', current.length) - binding.write(options.handler, current, current.length, ) + binding.write(options.handler, current, current.length, onWrite) function onWrite (written) { debug('Wrote %o bytes', chunk.length) @@ -91,44 +98,44 @@ function Speaker (opts) { function _validate (options) { debug('Format: Setting options - %o', Object.keys(options)) - if (options.channels !== null) { + if (options.channels !== undefined) { debug('Format: Setting %o - %o', 'channels', options.channels) } else { debug('Format: Setting %o - %o', 'channels', 2) options.channels = 2 } - if (options.bitDepth !== null) { + if (options.bitDepth !== undefined) { debug('Format: Setting %o - %o', 'bitDepth', options.bitDepth) } else { debug('Format: Setting %o - %o', 'bitDepth', options.float ? 32 : 16) options.bitDepth = options.float ? 32 : 16 } - if (options.sampleRate !== null) { + if (options.sampleRate !== undefined) { debug('Format: Setting %o - %o', 'sampleRate', options.sampleRate) } else { debug('Format: Setting %o - %o', 'sampleRate', 44100) options.sampleRate = 44100 } - if (options.signed !== null) { + if (options.signed !== undefined) { debug('Format: Setting %o - %o', 'signed', options.signed) } else { debug('Format: Setting %o - %o', 'signed', options.bitDepth != 8) options.signed = options.bitDepth != 8 } - if (options.samplesPerFrame !== null) { + if (options.samplesPerFrame !== undefined) { debug('Format: Setting %o - %o', 'samplesPerFrame', options.samplesPerFrame) } else { debug('Format: Settings &o - %o', 'samplesPerFrame', 1024) options.samplesPerFrame = 1024 } - if (options.float !== null) { + if (options.float !== undefined) { debug('Format: Setting %o - %o', 'float', options.float) } options.endianess = endianess; debug('Format: Settings applied') } - function function end (flush, callback) { + function end (flush, callback) { debug('end(%o)', flush) if (options._closed) return debug('_end() was called more than once. Already ended') diff --git a/package.json b/package.json index 488f4c0..f4856cb 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Output PCM data to a device or library.", "main": "lib/index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "node test" }, "repository": { "type": "git", @@ -30,6 +30,10 @@ "is-audio-buffer": "^1.0.1", "nan": "2.2.0", "object-assign": "^4.1.0", - "pcm-util": "^2.0.3" + "pcm-util": "^2.0.3", + "audio-buffer": "^2.4.5" + }, + "devDependencies": { + "audio-lena": "^1.1.0" } } diff --git a/src/binding.cpp b/src/binding.cpp index dda0cd6..bd7b886 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -28,20 +28,21 @@ namespace { out123_handle *ao = out123_new(); if(!ao) { - fprintf(stderr, "Failed to initialize output handle."); + fprintf(stderr, "Failed to initialize output handle. \n"); out123_del(ao); value = 0; } else if(out123_open(ao, NULL, NULL) != OUT123_OK) { - fprintf(stderr, "Failed to open output: %s", out123_strerror(ao)); + fprintf(stderr, "Failed to open output: %s \n", out123_strerror(ao)); out123_del(ao); value = 0; } else { + printf("Created audio handle at %i \n", ao); value = 1; } - result_callback(new Nan::Callback(info[4].As()), value); + result_callback(new Nan::Callback(info[0].As()), value); - info.GetReturnValue().Set(scope.Escape(WrapPointer(&ao, static_cast(sizeof(&ao))))); + info.GetReturnValue().Set(scope.Escape(WrapPointer(ao, static_cast(sizeof(ao))))); } NAN_METHOD(open) { @@ -55,8 +56,13 @@ namespace { int value = 0; - if(out123_start(ao, rate, channels, encoding) && !ao) { - fprintf(stderr, "Failed to start output: %s", out123_strerror(ao)); + const char *encname; + encname = out123_enc_name(encoding); + + printf("Playing with %i channels and %li Hz, encoding %s, handle %u.\n", channels, rate, encname ? encname : "???", ao); + + if(out123_start(ao, rate, channels, encoding) || !ao) { + fprintf(stderr, "Failed to start output: %s \n", out123_strerror(ao)); out123_del(ao); value = 0; } else { @@ -159,7 +165,7 @@ namespace { void InitializeModule(Handle target) { Nan::HandleScope scope; - printf("Creating a test handler."); // Debug message. + printf("Creating a test handler. \n"); // Debug message. out123_handle *ao = out123_new(); @@ -169,14 +175,14 @@ namespace { int framesize = 1; if(!ao) { - fprintf(stderr, "Failed to initialize output handle."); + fprintf(stderr, "Failed to initialize output handle. \n"); out123_del(ao); } else if(out123_open(ao, NULL, NULL) != OUT123_OK) { fprintf(stderr, "Failed to open output: %s", out123_strerror(ao)); out123_del(ao); } - printf("Successfully created a test handler. Will destroy handler and continue normal operation."); // Debug message. + printf("Successfully created a test handler. Will destroy handler and continue normal operation. \n"); // Debug message. #define CONST_INT(value) \ Nan::ForceSet(target, Nan::New(#value).ToLocalChecked(), Nan::New(value), \ diff --git a/src/config/win/ia32/config.h b/src/config/win/ia32/config.h index 1a6192a..cf5e305 100644 --- a/src/config/win/ia32/config.h +++ b/src/config/win/ia32/config.h @@ -27,7 +27,7 @@ /* #undef DEBUG */ /* The default audio output module(s) to use */ -#define DEFAULT_OUTPUT_MODULE "oss,win32,win32_wasapi" +#define DEFAULT_OUTPUT_MODULE "win32,win32_wasapi,oss" /* Define if building with dynamcally linked libmpg123 */ #define DYNAMIC_BUILD 1 diff --git a/src/config/win/x64/config.h b/src/config/win/x64/config.h index 8dea24b..df2a369 100644 --- a/src/config/win/x64/config.h +++ b/src/config/win/x64/config.h @@ -27,7 +27,7 @@ /* #undef DEBUG */ /* The default audio output module(s) to use */ -#define DEFAULT_OUTPUT_MODULE "oss,win32,win32_wasapi" +#define DEFAULT_OUTPUT_MODULE "win32,win32_wasapi,oss" /* Define if building with dynamcally linked libmpg123 */ #define DYNAMIC_BUILD 1 diff --git a/src/pointer_wrapper.h b/src/pointer_wrapper.h index f708d74..861daa2 100644 --- a/src/pointer_wrapper.h +++ b/src/pointer_wrapper.h @@ -1,12 +1,12 @@ #include inline static void wrap_pointer_cb(char *data, void *hint) { - fprintf(stderr, "Wrapped pointer was garbage collected."); // Debug message. + fprintf(stderr, "Wrapped pointer was garbage collected. \n"); // Debug message. } inline static v8::Local WrapPointer(void *ptr, size_t length) { void *user_data = NULL; - fprintf(stderr, "Wrapping pointer to a Node Buffer."); // Debug message. + fprintf(stderr, "Wrapping pointer to a Node Buffer. \n"); // Debug message. return Nan::NewBuffer((char *)ptr, length, wrap_pointer_cb, user_data).ToLocalChecked(); } @@ -16,7 +16,7 @@ inline static v8::Local WrapPointer(void *ptr) { inline static char * UnwrapPointer(v8::Local buffer, int64_t offset = 0) { if(node::Buffer::HasInstance(buffer)) { - fprintf(stderr, "Unwrapping pointer from Node Buffer."); // Debug message. + fprintf(stderr, "Unwrapping pointer from Node Buffer. \n"); // Debug message. return node::Buffer::Data(buffer.As()) + offset; } else { return NULL; @@ -26,4 +26,4 @@ inline static char * UnwrapPointer(v8::Local buffer, int64_t offset = template inline static Type UnwrapPointer(v8::Local buffer) { return reinterpret_cast(UnwrapPointer(buffer)); -} \ No newline at end of file +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..451ddf4 --- /dev/null +++ b/test.js @@ -0,0 +1,13 @@ +var AudioBuffer = require('audio-buffer') +var LenaBuffer = require('audio-lena/buffer') +var AudioSpeaker = require('./index') +var debug = require('debug')('test') + +console.log('Starting test.') +var Speaker = AudioSpeaker({ float: false, bitDepth: 16, signed: true }) +var buf = new AudioBuffer(1, LenaBuffer) + +console.log('Writing audio.') +console.dir(Speaker) +Speaker(buf, function (err, chunk) { +}) From dd4d4c9062a81adacf0e99dce06bff8255629495 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 22 Oct 2016 13:53:47 +1300 Subject: [PATCH 11/96] Clean up debug messages --- index.js | 4 ++-- src/binding.cpp | 17 ++++++----------- src/pointer_wrapper.h | 4 +--- test.js | 7 ++++--- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/index.js b/index.js index ec5a818..c4d4270 100644 --- a/index.js +++ b/index.js @@ -53,7 +53,7 @@ function Speaker (opts) { } return function write (chunk, callback) { - debug('write() (%o bytes)', chunk.length) + debug('write() %o total bytes', chunk.length) if (options._closed) return debug('write() cannot be called after the speaker is closed.') if (options.handler) { @@ -125,7 +125,7 @@ function Speaker (opts) { if (options.samplesPerFrame !== undefined) { debug('Format: Setting %o - %o', 'samplesPerFrame', options.samplesPerFrame) } else { - debug('Format: Settings &o - %o', 'samplesPerFrame', 1024) + debug('Format: Settings %o - %o', 'samplesPerFrame', 1024) options.samplesPerFrame = 1024 } if (options.float !== undefined) { diff --git a/src/binding.cpp b/src/binding.cpp index bd7b886..5290092 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -28,15 +28,14 @@ namespace { out123_handle *ao = out123_new(); if(!ao) { - fprintf(stderr, "Failed to initialize output handle. \n"); + fprintf(stderr, "Failed to initialize output handle.\n"); out123_del(ao); value = 0; } else if(out123_open(ao, NULL, NULL) != OUT123_OK) { - fprintf(stderr, "Failed to open output: %s \n", out123_strerror(ao)); + fprintf(stderr, "Failed to open output: %s\n", out123_strerror(ao)); out123_del(ao); value = 0; } else { - printf("Created audio handle at %i \n", ao); value = 1; } @@ -59,10 +58,10 @@ namespace { const char *encname; encname = out123_enc_name(encoding); - printf("Playing with %i channels and %li Hz, encoding %s, handle %u.\n", channels, rate, encname ? encname : "???", ao); + printf("Playing with %i channels and %li Hz, encoding %s.\n", channels, rate, encname ? encname : "???"); if(out123_start(ao, rate, channels, encoding) || !ao) { - fprintf(stderr, "Failed to start output: %s \n", out123_strerror(ao)); + fprintf(stderr, "Failed to start output: %s\n", out123_strerror(ao)); out123_del(ao); value = 0; } else { @@ -165,8 +164,6 @@ namespace { void InitializeModule(Handle target) { Nan::HandleScope scope; - printf("Creating a test handler. \n"); // Debug message. - out123_handle *ao = out123_new(); long rate = 44100; @@ -175,15 +172,13 @@ namespace { int framesize = 1; if(!ao) { - fprintf(stderr, "Failed to initialize output handle. \n"); + fprintf(stderr, "Failed to initialize output handle.\n"); out123_del(ao); } else if(out123_open(ao, NULL, NULL) != OUT123_OK) { - fprintf(stderr, "Failed to open output: %s", out123_strerror(ao)); + fprintf(stderr, "Failed to open output: %s\n", out123_strerror(ao)); out123_del(ao); } - printf("Successfully created a test handler. Will destroy handler and continue normal operation. \n"); // Debug message. - #define CONST_INT(value) \ Nan::ForceSet(target, Nan::New(#value).ToLocalChecked(), Nan::New(value), \ static_cast(ReadOnly|DontDelete)); diff --git a/src/pointer_wrapper.h b/src/pointer_wrapper.h index 861daa2..1c33e14 100644 --- a/src/pointer_wrapper.h +++ b/src/pointer_wrapper.h @@ -1,12 +1,11 @@ #include inline static void wrap_pointer_cb(char *data, void *hint) { - fprintf(stderr, "Wrapped pointer was garbage collected. \n"); // Debug message. + fprintf(stderr, "Wrapped pointer was garbage collected. \n"); } inline static v8::Local WrapPointer(void *ptr, size_t length) { void *user_data = NULL; - fprintf(stderr, "Wrapping pointer to a Node Buffer. \n"); // Debug message. return Nan::NewBuffer((char *)ptr, length, wrap_pointer_cb, user_data).ToLocalChecked(); } @@ -16,7 +15,6 @@ inline static v8::Local WrapPointer(void *ptr) { inline static char * UnwrapPointer(v8::Local buffer, int64_t offset = 0) { if(node::Buffer::HasInstance(buffer)) { - fprintf(stderr, "Unwrapping pointer from Node Buffer. \n"); // Debug message. return node::Buffer::Data(buffer.As()) + offset; } else { return NULL; diff --git a/test.js b/test.js index 451ddf4..f25d4e5 100644 --- a/test.js +++ b/test.js @@ -1,13 +1,14 @@ var AudioBuffer = require('audio-buffer') var LenaBuffer = require('audio-lena/buffer') var AudioSpeaker = require('./index') -var debug = require('debug')('test') console.log('Starting test.') + var Speaker = AudioSpeaker({ float: false, bitDepth: 16, signed: true }) var buf = new AudioBuffer(1, LenaBuffer) -console.log('Writing audio.') -console.dir(Speaker) Speaker(buf, function (err, chunk) { + if(!err) { + console.log('Wrote (' + chunk.length + '/' + buf.length +')') + } else throw err }) From e401110cb4b9871a935564a7c05cfdf75f442b61 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 22 Oct 2016 17:36:35 +1300 Subject: [PATCH 12/96] Fix write method --- index.js | 105 +++++++++++++++++++++++++++++++++++++++---------------- test.js | 8 ++--- 2 files changed, 78 insertions(+), 35 deletions(-) diff --git a/index.js b/index.js index c4d4270..ebf7731 100644 --- a/index.js +++ b/index.js @@ -20,11 +20,12 @@ function Speaker (opts) { throw new Error('_create() was called more than once. Only one handler should exist') } - options._closed = false; + options._closed = false + options._busy = false _validate(options) - var format = Speaker.getFormat(options); + var format = Speaker.getFormat(options) if (format === null) { throw new Error('Invalid format options') } @@ -52,48 +53,92 @@ function Speaker (opts) { }) } - return function write (chunk, callback) { - debug('write() %o total bytes', chunk.length) + return function write (chunk, callback, remainder) { + debug('write()') if (options._closed) return debug('write() cannot be called after the speaker is closed.') + if (chunk && options._busy) return debug('write() cannot be called until the previous buffer has been written.') if (options.handler) { - var buffer = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk + options._busy = true - var current - var remaining + var chunkBuf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk || new Buffer(0) + var remainderBuf = isAudioBuffer(remainder) ? pcm.toBuffer(remainder, options) : remainder || new Buffer(0) - if (remaining != null) { - current = new audioBuffer(options.channels, remaining) - remaining = new audioBuffer(options.channels, chunk) - } else { - current = new audioBuffer(options.channels, chunk) - remaining = null - } + var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) - if (current.length > options.chunkSize) { - var temp = current - current = temp.slice(0, options.chunkSize) - remaining = temp.slice(options.chunkSize) - } else { - remaining = null - } + debug("%o bytes total queued for output.", queue.length) - debug('Writing %o byte chunk', current.length) - binding.write(options.handler, current, current.length, onWrite) + var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue + var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) + + debug("%o bytes writing to the speaker.", output.length) + debug("%o bytes remaining in the queue.", remaining.length) + + binding.write(options.handler, output, output.length, onWrite) function onWrite (written) { - debug('Wrote %o bytes', chunk.length) - if (written != chunk.length) { - callback(new Error('write() failed when writing: ' + chunk), chunk) - } else if (remaining) { - debug('Writing %o remaining bytes in the chunk.', left.length) - write() + debug('Wrote %o bytes this chunk.', written) + if(!remaining.length < 1) { + debug('Writing remaining chunks.') + write(null, callback, remaining) } else { + binding.flush(options.handler, function (success) { + if (success != 1) { + debug('Could not flush the audio output') + } else { + debug('Flushed audio successfully.') + } + }) debug('Finished writing chunk.') - callback(null, chunk) + options._busy = false + callback(null, written) } } } + + // if (options.handler) { + // var buffer = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk + // + // var currentT = null + // var remainingT = null + // + // if (rem !== null) { + // currentT = new audioBuffer(options.channels, rem, options.sampleRate) + // remainingT = new audioBuffer(options.channels, chunk, options.sampleRate) + // } else { + // currentT = chunk != null ? new audioBuffer(options.channels, chunk, options.sampleRate) : null + // remainingT = null + // } + // + // var current = currentT ? currentT.data.buffer : null + // var remaining = remainingT ? remainingT.data.buffer : null + // + // if (current && current.byteLength > options.chunkSize) { + // current = current ? current.slice(0, options.chunkSize) : null + // remaining = remaining ? remaining.slice(options.chunkSize) : null + // } else { + // remaining = null + // } + // + // console.dir(current) + // console.dir(remaining) + // + // debug('Writing %o byte chunk', current.byteLength) + // binding.write(options.handler, current, current.byteLength, onWrite) + // + // function onWrite (written) { + // debug('Wrote %o bytes', current.byteLength) + // if (written != chunk.length) { + // callback(new Error('write() failed when writing: ' + current), null) + // } else if (remaining) { + // debug('Writing %o remaining bytes in the chunk.', remaining.byteLength) + // write(null, callback, remaining) + // } else { + // debug('Finished writing chunk.') + // callback(null, chunk) + // } + // } + // } } function _validate (options) { diff --git a/test.js b/test.js index f25d4e5..675109c 100644 --- a/test.js +++ b/test.js @@ -4,11 +4,9 @@ var AudioSpeaker = require('./index') console.log('Starting test.') -var Speaker = AudioSpeaker({ float: false, bitDepth: 16, signed: true }) +var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = new AudioBuffer(1, LenaBuffer) -Speaker(buf, function (err, chunk) { - if(!err) { - console.log('Wrote (' + chunk.length + '/' + buf.length +')') - } else throw err +Speaker(buf, function (err, written) { + console.log('Wrote (' + written + '/' + buf.length +')') }) From f21c47db7e16b7fb21d9918d30854d2b210de7b4 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 22 Oct 2016 17:53:29 +1300 Subject: [PATCH 13/96] Fix test message output --- test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.js b/test.js index 675109c..2c9d892 100644 --- a/test.js +++ b/test.js @@ -8,5 +8,5 @@ var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: tr var buf = new AudioBuffer(1, LenaBuffer) Speaker(buf, function (err, written) { - console.log('Wrote (' + written + '/' + buf.length +')') + console.log('Wrote (' + buf.length +')') }) From 9625c5d7ce5bb46590a4037771c767ba3429f209 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 22 Oct 2016 18:12:12 +1300 Subject: [PATCH 14/96] Update submodule to 1.23.8 --- src/mpg123 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mpg123 b/src/mpg123 index db28c90..3ee4664 160000 --- a/src/mpg123 +++ b/src/mpg123 @@ -1 +1 @@ -Subproject commit db28c905f297d3e11574b9e8d7df975dab44587c +Subproject commit 3ee46645660d3da22aca34313b87b314307188bc From 123327c4b0efc1cf5f76737bfa4f11fb6b6b8112 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sun, 23 Oct 2016 10:46:23 +1300 Subject: [PATCH 15/96] Add autoFlush option and add end method to test --- index.js | 73 ++++++++++++++----------------------------------- src/binding.cpp | 1 + test.js | 9 ++++-- 3 files changed, 28 insertions(+), 55 deletions(-) diff --git a/index.js b/index.js index ebf7731..d8628c5 100644 --- a/index.js +++ b/index.js @@ -53,7 +53,10 @@ function Speaker (opts) { }) } - return function write (chunk, callback, remainder) { + write.end = end + return write + + function write (chunk, remainder, callback) { debug('write()') if (options._closed) return debug('write() cannot be called after the speaker is closed.') if (chunk && options._busy) return debug('write() cannot be called until the previous buffer has been written.') @@ -80,69 +83,33 @@ function Speaker (opts) { debug('Wrote %o bytes this chunk.', written) if(!remaining.length < 1) { debug('Writing remaining chunks.') - write(null, callback, remaining) + write(null, remaining, callback) } else { - binding.flush(options.handler, function (success) { - if (success != 1) { - debug('Could not flush the audio output') - } else { - debug('Flushed audio successfully.') - } - }) debug('Finished writing chunk.') options._busy = false callback(null, written) + if (options.autoFlush) { + binding.flush(options.handler, function (success) { + if (success != 1) { + debug('Could not flush the audio output') + } else { + debug('Flushed audio successfully.') + } + }) + } } } } - - // if (options.handler) { - // var buffer = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk - // - // var currentT = null - // var remainingT = null - // - // if (rem !== null) { - // currentT = new audioBuffer(options.channels, rem, options.sampleRate) - // remainingT = new audioBuffer(options.channels, chunk, options.sampleRate) - // } else { - // currentT = chunk != null ? new audioBuffer(options.channels, chunk, options.sampleRate) : null - // remainingT = null - // } - // - // var current = currentT ? currentT.data.buffer : null - // var remaining = remainingT ? remainingT.data.buffer : null - // - // if (current && current.byteLength > options.chunkSize) { - // current = current ? current.slice(0, options.chunkSize) : null - // remaining = remaining ? remaining.slice(options.chunkSize) : null - // } else { - // remaining = null - // } - // - // console.dir(current) - // console.dir(remaining) - // - // debug('Writing %o byte chunk', current.byteLength) - // binding.write(options.handler, current, current.byteLength, onWrite) - // - // function onWrite (written) { - // debug('Wrote %o bytes', current.byteLength) - // if (written != chunk.length) { - // callback(new Error('write() failed when writing: ' + current), null) - // } else if (remaining) { - // debug('Writing %o remaining bytes in the chunk.', remaining.byteLength) - // write(null, callback, remaining) - // } else { - // debug('Finished writing chunk.') - // callback(null, chunk) - // } - // } - // } } function _validate (options) { debug('Format: Setting options - %o', Object.keys(options)) + if (options.autoFlush !== undefined) { + debug('Format: Setting %o - %o', 'autoFlush', options.autoFlush) + } else { + debug('Format: Setting %o - %o', 'autoFlush', false) + options.autoFlush = false + } if (options.channels !== undefined) { debug('Format: Setting %o - %o', 'channels', options.channels) } else { diff --git a/src/binding.cpp b/src/binding.cpp index 5290092..4eecac0 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -121,6 +121,7 @@ namespace { int value = 0; if(ao) { + out123_drop(ao); out123_close(ao); value = 1; } else { diff --git a/test.js b/test.js index 2c9d892..52e53bf 100644 --- a/test.js +++ b/test.js @@ -7,6 +7,11 @@ console.log('Starting test.') var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = new AudioBuffer(1, LenaBuffer) -Speaker(buf, function (err, written) { - console.log('Wrote (' + buf.length +')') +console.log(AudioSpeaker) + +Speaker(buf, null, function (err, written) { + console.log('Test wrote ' + buf.length +' bytes of audio-lena.') + Speaker.end(true, (success) => { + console.log('Finished test.') + }) }) From 802cb5a8c4abe9672a901a9a7619026b1fd3c097 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sun, 23 Oct 2016 11:02:01 +1300 Subject: [PATCH 16/96] Delete audio handler on close --- index.js | 18 +++++++++--------- src/binding.cpp | 2 +- test.js | 2 -- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index d8628c5..3e20e0c 100644 --- a/index.js +++ b/index.js @@ -17,7 +17,7 @@ function Speaker (opts) { objectAssign(options, opts) if (options.handler) { - throw new Error('_create() was called more than once. Only one handler should exist') + throw new Error('_create() was called more than once. Only one handler should exist.') } options._closed = false @@ -27,7 +27,7 @@ function Speaker (opts) { var format = Speaker.getFormat(options) if (format === null) { - throw new Error('Invalid format options') + throw new Error('Invalid format options.') } options.blockAlign = options.bitDepth / 8 * options.channels @@ -46,9 +46,9 @@ function Speaker (opts) { debug('_start(%o)', Object.keys(options)) binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { if (!success) { - throw new Error('Could not start the audio output with these properties') + throw new Error('Could not start the audio output with these properties.') } else { - debug('Created and started handler successfully') + debug('Created and started handler successfully.') } }) } @@ -91,7 +91,7 @@ function Speaker (opts) { if (options.autoFlush) { binding.flush(options.handler, function (success) { if (success != 1) { - debug('Could not flush the audio output') + debug('Could not flush the audio output.') } else { debug('Flushed audio successfully.') } @@ -149,14 +149,14 @@ function Speaker (opts) { function end (flush, callback) { debug('end(%o)', flush) - if (options._closed) return debug('_end() was called more than once. Already ended') + if (options._closed) return debug('_end() was called more than once. Already ended.') if (options.handler) { if (flush) { - debug('Flushing the audio output') + debug('Flushing the audio output.') binding.flush(options.handler, function (success) { if (success != 1) { - debug('Could not flush the audio output') + debug('Could not flush the audio output.') } else { return close(callback) } @@ -165,7 +165,7 @@ function Speaker (opts) { return close(callback) } } else { - debug('Could not flush the audio output because handler does not exist') + debug('Could not flush the audio output because handler does not exist.') } function close (callback) { diff --git a/src/binding.cpp b/src/binding.cpp index 4eecac0..c3e45a7 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -122,7 +122,7 @@ namespace { if(ao) { out123_drop(ao); - out123_close(ao); + out123_del(ao); value = 1; } else { value = 0; diff --git a/test.js b/test.js index 52e53bf..0d15508 100644 --- a/test.js +++ b/test.js @@ -7,8 +7,6 @@ console.log('Starting test.') var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = new AudioBuffer(1, LenaBuffer) -console.log(AudioSpeaker) - Speaker(buf, null, function (err, written) { console.log('Test wrote ' + buf.length +' bytes of audio-lena.') Speaker.end(true, (success) => { From 17ffb55ed5754fa81d1293c17e89acdec6e4ac3f Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sun, 23 Oct 2016 11:57:25 +1300 Subject: [PATCH 17/96] Add autoFlush test --- index.js | 5 +++-- package.json | 3 ++- test.js => tests/one.js | 6 +++--- tests/two.js | 18 ++++++++++++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) rename test.js => tests/one.js (77%) create mode 100644 tests/two.js diff --git a/index.js b/index.js index 3e20e0c..1004944 100644 --- a/index.js +++ b/index.js @@ -86,9 +86,8 @@ function Speaker (opts) { write(null, remaining, callback) } else { debug('Finished writing chunk.') - options._busy = false - callback(null, written) if (options.autoFlush) { + debug('Flushing the audio output.') binding.flush(options.handler, function (success) { if (success != 1) { debug('Could not flush the audio output.') @@ -97,6 +96,8 @@ function Speaker (opts) { } }) } + options._busy = false + callback(null, written) } } } diff --git a/package.json b/package.json index f4856cb..d1728e3 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Output PCM data to a device or library.", "main": "lib/index.js", "scripts": { - "test": "node test" + "test": "node tests/one", + "testtwo": "node tests/two" }, "repository": { "type": "git", diff --git a/test.js b/tests/one.js similarity index 77% rename from test.js rename to tests/one.js index 0d15508..0035d1e 100644 --- a/test.js +++ b/tests/one.js @@ -1,8 +1,8 @@ var AudioBuffer = require('audio-buffer') var LenaBuffer = require('audio-lena/buffer') -var AudioSpeaker = require('./index') +var AudioSpeaker = require('../index') -console.log('Starting test.') +console.log('Starting test one.') var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = new AudioBuffer(1, LenaBuffer) @@ -10,6 +10,6 @@ var buf = new AudioBuffer(1, LenaBuffer) Speaker(buf, null, function (err, written) { console.log('Test wrote ' + buf.length +' bytes of audio-lena.') Speaker.end(true, (success) => { - console.log('Finished test.') + console.log('Finished test one.') }) }) diff --git a/tests/two.js b/tests/two.js new file mode 100644 index 0000000..ecf1b0f --- /dev/null +++ b/tests/two.js @@ -0,0 +1,18 @@ +var AudioBuffer = require('audio-buffer') +var LenaBuffer = require('audio-lena/buffer') +var AudioSpeaker = require('../index') + +console.log('Starting test two.') + +var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) +var buf = new AudioBuffer(1, LenaBuffer) + +Speaker(buf, null, function (err, written) { + console.log('Test wrote ' + buf.length +' bytes of audio-lena.') + Speaker(buf, null, function (err, done) { + console.log('Test wrote ' + (buf.length * 2) + ' bytes of audio-lena total over two runs.') + Speaker.end(false, (success) => { + console.log('Finished test two.') + }) + }) +}) From 960f5e5e36c85f7ddf2ae1d2b62c63ccf581b43c Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 2 Nov 2016 17:12:19 +1300 Subject: [PATCH 18/96] Add sink implementation --- direct.js | 74 +++++++++++++++++++ index.js | 206 +--------------------------------------------------- native.js | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 288 insertions(+), 204 deletions(-) create mode 100644 direct.js create mode 100644 native.js diff --git a/direct.js b/direct.js new file mode 100644 index 0000000..e5f5a83 --- /dev/null +++ b/direct.js @@ -0,0 +1,74 @@ +'use strict' + +var AudioBuffer = require('audio-buffer') +var AudioSink = require('audio-sink/direct') +var isAudioBuffer = require('is-audio-buffer') +var NativeSpeaker = require('./native') +var objectAssign = require('object-assign') + +var format = { + float: false, + bitDepth: 16, + signed: true, + sampleRate: 44100, + samplesPerFrame: 1024 +}; + +module.exports = function (opts) { + var options = objectAssign(options, format, opts) + + return !options.sink ? createNativeSpeaker(options) : createAudioSink(options) + + function createNativeSpeaker (options) { + var Speaker = NativeSpeaker(options) + var isClosed = false + + write.end = end + return write + + function end () { + isClosed = true + write(true) + } + + function write (chunk, callback) { + if (chunk == null || chunk === true || isClosed) { + isClosed = true + callback(true) + } else { + var input = null + if (isAudioBuffer(chunk) ? input = chunk : chunk = new AudioBuffer(options.channels, chunk, options.sampleRate)) + Speaker(input, null, (err, written) => { + if (isClosed) { + Speaker.end(options.autoFlush || true, (success) => { + if (success) { + callback(true) + } else { + callback(new Error('Could not end speaker.')) + } + }) + } else { + callback(null, chunk) + } + }) + } + } + } + + function createAudioSink (options) { + var isClosed = false + + sink.end = end + return sink + + var sink = AudioSink((data, callback) => { + if (isClosed || data == null || data == true) return callback(true) + setTimeout(callback, samplesPerFrame / sampleRate) + }) + + function end () { + isClosed = true + sink(true) + } + } +} diff --git a/index.js b/index.js index 1004944..d92014b 100644 --- a/index.js +++ b/index.js @@ -1,205 +1,3 @@ -var os = require('os') -var objectAssign = require('object-assign') -var binding = require('bindings')('binding') -var pcm = require('pcm-util') -var isAudioBuffer = require('is-audio-buffer') -var audioBuffer = require('audio-buffer') -var debug = require('debug')('speaker') +'use strict' -var endianess = 'function' == os.endianess ? os.endianess() : 'LE' - -module.exports = Speaker - -function Speaker (opts) { - debug('Speaker()') - var options = {} - - objectAssign(options, opts) - - if (options.handler) { - throw new Error('_create() was called more than once. Only one handler should exist.') - } - - options._closed = false - options._busy = false - - _validate(options) - - var format = Speaker.getFormat(options) - if (format === null) { - throw new Error('Invalid format options.') - } - - options.blockAlign = options.bitDepth / 8 * options.channels - - options.chunkSize = options.blockAlign * options.samplesPerFrame - - options.handler = binding.create((success) => { - if(!success) { - throw new Error('Failed to create the audio handler.') - } else { - debug('_create() audio handle successfully.') - } - }) - - if (options.handler !== null) { - debug('_start(%o)', Object.keys(options)) - binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { - if (!success) { - throw new Error('Could not start the audio output with these properties.') - } else { - debug('Created and started handler successfully.') - } - }) - } - - write.end = end - return write - - function write (chunk, remainder, callback) { - debug('write()') - if (options._closed) return debug('write() cannot be called after the speaker is closed.') - if (chunk && options._busy) return debug('write() cannot be called until the previous buffer has been written.') - - if (options.handler) { - options._busy = true - - var chunkBuf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk || new Buffer(0) - var remainderBuf = isAudioBuffer(remainder) ? pcm.toBuffer(remainder, options) : remainder || new Buffer(0) - - var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) - - debug("%o bytes total queued for output.", queue.length) - - var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue - var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) - - debug("%o bytes writing to the speaker.", output.length) - debug("%o bytes remaining in the queue.", remaining.length) - - binding.write(options.handler, output, output.length, onWrite) - - function onWrite (written) { - debug('Wrote %o bytes this chunk.', written) - if(!remaining.length < 1) { - debug('Writing remaining chunks.') - write(null, remaining, callback) - } else { - debug('Finished writing chunk.') - if (options.autoFlush) { - debug('Flushing the audio output.') - binding.flush(options.handler, function (success) { - if (success != 1) { - debug('Could not flush the audio output.') - } else { - debug('Flushed audio successfully.') - } - }) - } - options._busy = false - callback(null, written) - } - } - } - } - - function _validate (options) { - debug('Format: Setting options - %o', Object.keys(options)) - if (options.autoFlush !== undefined) { - debug('Format: Setting %o - %o', 'autoFlush', options.autoFlush) - } else { - debug('Format: Setting %o - %o', 'autoFlush', false) - options.autoFlush = false - } - if (options.channels !== undefined) { - debug('Format: Setting %o - %o', 'channels', options.channels) - } else { - debug('Format: Setting %o - %o', 'channels', 2) - options.channels = 2 - } - if (options.bitDepth !== undefined) { - debug('Format: Setting %o - %o', 'bitDepth', options.bitDepth) - } else { - debug('Format: Setting %o - %o', 'bitDepth', options.float ? 32 : 16) - options.bitDepth = options.float ? 32 : 16 - } - if (options.sampleRate !== undefined) { - debug('Format: Setting %o - %o', 'sampleRate', options.sampleRate) - } else { - debug('Format: Setting %o - %o', 'sampleRate', 44100) - options.sampleRate = 44100 - } - if (options.signed !== undefined) { - debug('Format: Setting %o - %o', 'signed', options.signed) - } else { - debug('Format: Setting %o - %o', 'signed', options.bitDepth != 8) - options.signed = options.bitDepth != 8 - } - if (options.samplesPerFrame !== undefined) { - debug('Format: Setting %o - %o', 'samplesPerFrame', options.samplesPerFrame) - } else { - debug('Format: Settings %o - %o', 'samplesPerFrame', 1024) - options.samplesPerFrame = 1024 - } - if (options.float !== undefined) { - debug('Format: Setting %o - %o', 'float', options.float) - } - options.endianess = endianess; - debug('Format: Settings applied') - } - - function end (flush, callback) { - debug('end(%o)', flush) - if (options._closed) return debug('_end() was called more than once. Already ended.') - - if (options.handler) { - if (flush) { - debug('Flushing the audio output.') - binding.flush(options.handler, function (success) { - if (success != 1) { - debug('Could not flush the audio output.') - } else { - return close(callback) - } - }) - } else { - return close(callback) - } - } else { - debug('Could not flush the audio output because handler does not exist.') - } - - function close (callback) { - debug('close()') - binding.close(options.handler, callback) - options._closed = true - options.handler = null - } - } -} - -Speaker.getFormat = function getFormat (format) { - var f = null; - if (format.bitDepth == 32 && format.float && format.signed) { - f = binding.MPG123_ENC_FLOAT_32; - } else if (format.bitDepth == 64 && format.float && format.signed) { - f = binding.MPG123_ENC_FLOAT_64; - } else if (format.bitDepth == 8 && format.signed) { - f = binding.MPG123_ENC_SIGNED_8; - } else if (format.bitDepth == 8 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_8; - } else if (format.bitDepth == 16 && format.signed) { - f = binding.MPG123_ENC_SIGNED_16; - } else if (format.bitDepth == 16 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_16; - } else if (format.bitDepth == 24 && format.signed) { - f = binding.MPG123_ENC_SIGNED_24; - } else if (format.bitDepth == 24 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_24; - } else if (format.bitDepth == 32 && format.signed) { - f = binding.MPG123_ENC_SIGNED_32; - } else if (format.bitDepth == 32 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_32; - } - return f; -} +module.exports = require('./direct') diff --git a/native.js b/native.js new file mode 100644 index 0000000..d6ac944 --- /dev/null +++ b/native.js @@ -0,0 +1,212 @@ +'use strict' + +var os = require('os') +var objectAssign = require('object-assign') +var binding = require('bindings')('binding') +var pcm = require('pcm-util') +var isAudioBuffer = require('is-audio-buffer') +var audioBuffer = require('audio-buffer') +var debug = require('debug')('speaker') + +var endianess = 'function' == os.endianess ? os.endianess() : 'LE' + +module.exports = Speaker + +function Speaker (opts) { + debug('Speaker()') + var options = {} + + objectAssign(options, opts) + + if (options.handler) { + throw new Error('_create() was called more than once. Only one handler should exist.') + } + + options._closed = false + options._busy = false + + _validate(options) + + var format = Speaker.getFormat(options) + if (format === null) { + throw new Error('Invalid format options.') + } + + options.blockAlign = options.bitDepth / 8 * options.channels + + options.chunkSize = options.blockAlign * options.samplesPerFrame + + options.handler = binding.create((success) => { + if(!success) { + throw new Error('Failed to create the audio handler.') + } else { + debug('_create() audio handle successfully.') + } + }) + + if (options.handler !== null) { + debug('_start(%o)', Object.keys(options)) + binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { + if (!success) { + throw new Error('Could not start the audio output with these properties.') + } else { + debug('Created and started handler successfully.') + } + }) + } + + write.end = end + return write + + function write (chunk, remainder, callback) { + debug('write()') + if (options._closed) return debug('write() cannot be called after the speaker is closed.') + if (chunk && options._busy) return debug('write() cannot be called until the previous buffer has been written.') + + if (options.handler) { + options._busy = true + + var chunkBuf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk || new Buffer(0) + var remainderBuf = isAudioBuffer(remainder) ? pcm.toBuffer(remainder, options) : remainder || new Buffer(0) + + var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) + + debug("%o bytes total queued for output.", queue.length) + + var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue + var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) + + debug("%o bytes writing to the speaker.", output.length) + debug("%o bytes remaining in the queue.", remaining.length) + + binding.write(options.handler, output, output.length, onWrite) + + function onWrite (written) { + debug('Wrote %o bytes this chunk.', written) + if(!remaining.length < 1) { + debug('Writing remaining chunks.') + write(null, remaining, callback) + } else { + debug('Finished writing chunk.') + if (options.autoFlush) { + debug('Flushing the audio output.') + binding.flush(options.handler, function (success) { + if (success != 1) { + debug('Could not flush the audio output.') + options._busy = false + callback(new Error('Could not flush the audio output.'), written) + } else { + debug('Flushed audio successfully.') + options._busy = false + callback(null, written) + } + }) + } else { + options._busy = false + callback(null, written) + } + } + } + } + } + + function _validate (options) { + debug('Format: Setting options - %o', Object.keys(options)) + if (options.autoFlush !== undefined) { + debug('Format: Setting %o - %o', 'autoFlush', options.autoFlush) + } else { + debug('Format: Setting %o - %o', 'autoFlush', false) + options.autoFlush = false + } + if (options.channels !== undefined) { + debug('Format: Setting %o - %o', 'channels', options.channels) + } else { + debug('Format: Setting %o - %o', 'channels', 2) + options.channels = 2 + } + if (options.bitDepth !== undefined) { + debug('Format: Setting %o - %o', 'bitDepth', options.bitDepth) + } else { + debug('Format: Setting %o - %o', 'bitDepth', options.float ? 32 : 16) + options.bitDepth = options.float ? 32 : 16 + } + if (options.sampleRate !== undefined) { + debug('Format: Setting %o - %o', 'sampleRate', options.sampleRate) + } else { + debug('Format: Setting %o - %o', 'sampleRate', 44100) + options.sampleRate = 44100 + } + if (options.signed !== undefined) { + debug('Format: Setting %o - %o', 'signed', options.signed) + } else { + debug('Format: Setting %o - %o', 'signed', options.bitDepth != 8) + options.signed = options.bitDepth != 8 + } + if (options.samplesPerFrame !== undefined) { + debug('Format: Setting %o - %o', 'samplesPerFrame', options.samplesPerFrame) + } else { + debug('Format: Settings %o - %o', 'samplesPerFrame', 1024) + options.samplesPerFrame = 1024 + } + if (options.float !== undefined) { + debug('Format: Setting %o - %o', 'float', options.float) + } + options.endianess = endianess; + debug('Format: Settings applied') + } + + function end (flush, callback) { + debug('end(%o)', flush) + if (options._closed) return debug('_end() was called more than once. Already ended.') + + if (options.handler) { + if (flush) { + debug('Flushing the audio output.') + binding.flush(options.handler, function (success) { + if (success != 1) { + debug('Could not flush the audio output.') + } else { + return close(callback) + } + }) + } else { + return close(callback) + } + } else { + debug('Could not flush the audio output because handler does not exist.') + } + + function close (callback) { + debug('close()') + binding.close(options.handler, callback) + options._closed = true + options.handler = null + } + } +} + +Speaker.getFormat = function getFormat (format) { + var f = null; + if (format.bitDepth == 32 && format.float && format.signed) { + f = binding.MPG123_ENC_FLOAT_32; + } else if (format.bitDepth == 64 && format.float && format.signed) { + f = binding.MPG123_ENC_FLOAT_64; + } else if (format.bitDepth == 8 && format.signed) { + f = binding.MPG123_ENC_SIGNED_8; + } else if (format.bitDepth == 8 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_8; + } else if (format.bitDepth == 16 && format.signed) { + f = binding.MPG123_ENC_SIGNED_16; + } else if (format.bitDepth == 16 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_16; + } else if (format.bitDepth == 24 && format.signed) { + f = binding.MPG123_ENC_SIGNED_24; + } else if (format.bitDepth == 24 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_24; + } else if (format.bitDepth == 32 && format.signed) { + f = binding.MPG123_ENC_SIGNED_32; + } else if (format.bitDepth == 32 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_32; + } + return f; +} From 1f2955358be20fc3e38b74938a92f78f1aa845b3 Mon Sep 17 00:00:00 2001 From: connorhartley Date: Fri, 4 Nov 2016 13:41:38 +1300 Subject: [PATCH 19/96] Simplify implementation --- direct.js | 245 +++++++++++++++++++++++++++++++++++++++--------- native.js | 212 ----------------------------------------- package.json | 5 +- src/binding.cpp | 2 +- tests/one.js | 12 ++- 5 files changed, 210 insertions(+), 266 deletions(-) delete mode 100644 native.js diff --git a/direct.js b/direct.js index e5f5a83..b245e7e 100644 --- a/direct.js +++ b/direct.js @@ -1,74 +1,227 @@ 'use strict' -var AudioBuffer = require('audio-buffer') -var AudioSink = require('audio-sink/direct') -var isAudioBuffer = require('is-audio-buffer') -var NativeSpeaker = require('./native') +var os = require('os') var objectAssign = require('object-assign') +var binding = require('bindings')('binding') +var pcm = require('pcm-util') +var isAudioBuffer = require('is-audio-buffer') +var audioBuffer = require('audio-buffer') +var audioSink = require('audio-sink/direct') +var debug = require('debug')('speaker') + +var endianess = 'function' == os.endianess ? os.endianess() : 'LE' + +module.exports = Speaker + +function Speaker (opts) { + debug('Speaker()') + var options = {} + + objectAssign(options, opts) -var format = { - float: false, - bitDepth: 16, - signed: true, - sampleRate: 44100, - samplesPerFrame: 1024 -}; + if (options.handler) { + throw new Error('_create() was called more than once. Only one handler should exist.') + } + + options._closed = false + options._busy = false -module.exports = function (opts) { - var options = objectAssign(options, format, opts) + _validate(options) - return !options.sink ? createNativeSpeaker(options) : createAudioSink(options) + var format = Speaker.getFormat(options) + if (format === null) { + throw new Error('Invalid format options.') + } - function createNativeSpeaker (options) { - var Speaker = NativeSpeaker(options) - var isClosed = false + options.blockAlign = options.bitDepth / 8 * options.channels - write.end = end - return write + options.chunkSize = options.blockAlign * options.samplesPerFrame - function end () { - isClosed = true - write(true) + options.handler = binding.create((success) => { + if(!success) { + throw new Error('Failed to create the audio handler.') + } else { + debug('_create() audio handle successfully.') } + }) - function write (chunk, callback) { - if (chunk == null || chunk === true || isClosed) { - isClosed = true - callback(true) + if (options.handler !== null) { + debug('_start(%o)', Object.keys(options)) + binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { + if (!success) { + throw new Error('Could not start the audio output with these properties.') } else { - var input = null - if (isAudioBuffer(chunk) ? input = chunk : chunk = new AudioBuffer(options.channels, chunk, options.sampleRate)) - Speaker(input, null, (err, written) => { - if (isClosed) { - Speaker.end(options.autoFlush || true, (success) => { - if (success) { - callback(true) + debug('Created and started handler successfully.') + } + }) + } + + write.end = end + return options.sink ? sink : write + + function write (chunk, remainder, callback) { + debug('write()') + if (options._closed) return debug('write() cannot be called after the speaker is closed.') + if (chunk && options._busy) return debug('write() cannot be called until the previous buffer has been written.') + + if (options.handler) { + options._busy = true + + var chunkBuf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk || new Buffer(0) + var remainderBuf = isAudioBuffer(remainder) ? pcm.toBuffer(remainder, options) : remainder || new Buffer(0) + + var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) + + debug("%o bytes total queued for output.", queue.length) + + var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue + var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) + + debug("%o bytes writing to the speaker.", output.length) + debug("%o bytes remaining in the queue.", remaining.length) + + binding.write(options.handler, output, output.length, onWrite) + + function onWrite (written) { + debug('Wrote %o bytes this chunk.', written) + if(!remaining.length < 1) { + debug('Writing remaining chunks.') + write(null, remaining, callback) + } else { + debug('Finished writing chunk.') + if (options.autoFlush) { + debug('Flushing the audio output.') + binding.flush(options.handler, function (success) { + if (success != 1) { + debug('Could not flush the audio output.') + options._busy = false + callback(new Error('Could not flush the audio output.'), written) } else { - callback(new Error('Could not end speaker.')) + debug('Flushed audio successfully.') + options._busy = false + callback(null, written) } }) } else { - callback(null, chunk) + options._busy = false + callback(null, written) } - }) + } } } } - function createAudioSink (options) { - var isClosed = false - - sink.end = end - return sink + function sink () { + if (options._closed) return callback(true) - var sink = AudioSink((data, callback) => { - if (isClosed || data == null || data == true) return callback(true) + return audioSink((data, callback) => { setTimeout(callback, samplesPerFrame / sampleRate) }) + } + + function _validate (options) { + debug('Format: Setting options - %o', Object.keys(options)) + if (options.autoFlush !== undefined) { + debug('Format: Setting %o - %o', 'autoFlush', options.autoFlush) + } else { + debug('Format: Setting %o - %o', 'autoFlush', false) + options.autoFlush = false + } + if (options.channels !== undefined) { + debug('Format: Setting %o - %o', 'channels', options.channels) + } else { + debug('Format: Setting %o - %o', 'channels', 2) + options.channels = 2 + } + if (options.bitDepth !== undefined) { + debug('Format: Setting %o - %o', 'bitDepth', options.bitDepth) + } else { + debug('Format: Setting %o - %o', 'bitDepth', options.float ? 32 : 16) + options.bitDepth = options.float ? 32 : 16 + } + if (options.sampleRate !== undefined) { + debug('Format: Setting %o - %o', 'sampleRate', options.sampleRate) + } else { + debug('Format: Setting %o - %o', 'sampleRate', 44100) + options.sampleRate = 44100 + } + if (options.signed !== undefined) { + debug('Format: Setting %o - %o', 'signed', options.signed) + } else { + debug('Format: Setting %o - %o', 'signed', options.bitDepth != 8) + options.signed = options.bitDepth != 8 + } + if (options.samplesPerFrame !== undefined) { + debug('Format: Setting %o - %o', 'samplesPerFrame', options.samplesPerFrame) + } else { + debug('Format: Settings %o - %o', 'samplesPerFrame', 1024) + options.samplesPerFrame = 1024 + } + if (options.float !== undefined) { + debug('Format: Setting %o - %o', 'float', options.float) + } + options.endianess = endianess; + debug('Format: Settings applied') + } + + function end (flush, callback) { + debug('end(%o)', flush) + if (options._closed) return debug('_end() was called more than once. Already ended.') + + if (options.handler) { + if (flush) { + debug('Flushing the audio output.') + binding.flush(options.handler, function (success) { + if (success != 1) { + debug('Could not flush the audio output.') + } else { + return close(callback) + } + }) + } else { + return close(callback) + } + } else { + debug('Could not flush the audio output because handler does not exist.') + } - function end () { - isClosed = true - sink(true) + function close (callback) { + debug('close()') + if (callback) { + binding.close(options.handler, callback) + } else { + binding.close(options.handler, (success) => { + if (success != 1) throw new Error('Failed to close speaker.') + }) + } + options._closed = true + options.handler = null } } } + +Speaker.getFormat = function getFormat (format) { + var f = null; + if (format.bitDepth == 32 && format.float && format.signed) { + f = binding.MPG123_ENC_FLOAT_32; + } else if (format.bitDepth == 64 && format.float && format.signed) { + f = binding.MPG123_ENC_FLOAT_64; + } else if (format.bitDepth == 8 && format.signed) { + f = binding.MPG123_ENC_SIGNED_8; + } else if (format.bitDepth == 8 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_8; + } else if (format.bitDepth == 16 && format.signed) { + f = binding.MPG123_ENC_SIGNED_16; + } else if (format.bitDepth == 16 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_16; + } else if (format.bitDepth == 24 && format.signed) { + f = binding.MPG123_ENC_SIGNED_24; + } else if (format.bitDepth == 24 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_24; + } else if (format.bitDepth == 32 && format.signed) { + f = binding.MPG123_ENC_SIGNED_32; + } else if (format.bitDepth == 32 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_32; + } + return f; +} diff --git a/native.js b/native.js deleted file mode 100644 index d6ac944..0000000 --- a/native.js +++ /dev/null @@ -1,212 +0,0 @@ -'use strict' - -var os = require('os') -var objectAssign = require('object-assign') -var binding = require('bindings')('binding') -var pcm = require('pcm-util') -var isAudioBuffer = require('is-audio-buffer') -var audioBuffer = require('audio-buffer') -var debug = require('debug')('speaker') - -var endianess = 'function' == os.endianess ? os.endianess() : 'LE' - -module.exports = Speaker - -function Speaker (opts) { - debug('Speaker()') - var options = {} - - objectAssign(options, opts) - - if (options.handler) { - throw new Error('_create() was called more than once. Only one handler should exist.') - } - - options._closed = false - options._busy = false - - _validate(options) - - var format = Speaker.getFormat(options) - if (format === null) { - throw new Error('Invalid format options.') - } - - options.blockAlign = options.bitDepth / 8 * options.channels - - options.chunkSize = options.blockAlign * options.samplesPerFrame - - options.handler = binding.create((success) => { - if(!success) { - throw new Error('Failed to create the audio handler.') - } else { - debug('_create() audio handle successfully.') - } - }) - - if (options.handler !== null) { - debug('_start(%o)', Object.keys(options)) - binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { - if (!success) { - throw new Error('Could not start the audio output with these properties.') - } else { - debug('Created and started handler successfully.') - } - }) - } - - write.end = end - return write - - function write (chunk, remainder, callback) { - debug('write()') - if (options._closed) return debug('write() cannot be called after the speaker is closed.') - if (chunk && options._busy) return debug('write() cannot be called until the previous buffer has been written.') - - if (options.handler) { - options._busy = true - - var chunkBuf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk || new Buffer(0) - var remainderBuf = isAudioBuffer(remainder) ? pcm.toBuffer(remainder, options) : remainder || new Buffer(0) - - var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) - - debug("%o bytes total queued for output.", queue.length) - - var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue - var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) - - debug("%o bytes writing to the speaker.", output.length) - debug("%o bytes remaining in the queue.", remaining.length) - - binding.write(options.handler, output, output.length, onWrite) - - function onWrite (written) { - debug('Wrote %o bytes this chunk.', written) - if(!remaining.length < 1) { - debug('Writing remaining chunks.') - write(null, remaining, callback) - } else { - debug('Finished writing chunk.') - if (options.autoFlush) { - debug('Flushing the audio output.') - binding.flush(options.handler, function (success) { - if (success != 1) { - debug('Could not flush the audio output.') - options._busy = false - callback(new Error('Could not flush the audio output.'), written) - } else { - debug('Flushed audio successfully.') - options._busy = false - callback(null, written) - } - }) - } else { - options._busy = false - callback(null, written) - } - } - } - } - } - - function _validate (options) { - debug('Format: Setting options - %o', Object.keys(options)) - if (options.autoFlush !== undefined) { - debug('Format: Setting %o - %o', 'autoFlush', options.autoFlush) - } else { - debug('Format: Setting %o - %o', 'autoFlush', false) - options.autoFlush = false - } - if (options.channels !== undefined) { - debug('Format: Setting %o - %o', 'channels', options.channels) - } else { - debug('Format: Setting %o - %o', 'channels', 2) - options.channels = 2 - } - if (options.bitDepth !== undefined) { - debug('Format: Setting %o - %o', 'bitDepth', options.bitDepth) - } else { - debug('Format: Setting %o - %o', 'bitDepth', options.float ? 32 : 16) - options.bitDepth = options.float ? 32 : 16 - } - if (options.sampleRate !== undefined) { - debug('Format: Setting %o - %o', 'sampleRate', options.sampleRate) - } else { - debug('Format: Setting %o - %o', 'sampleRate', 44100) - options.sampleRate = 44100 - } - if (options.signed !== undefined) { - debug('Format: Setting %o - %o', 'signed', options.signed) - } else { - debug('Format: Setting %o - %o', 'signed', options.bitDepth != 8) - options.signed = options.bitDepth != 8 - } - if (options.samplesPerFrame !== undefined) { - debug('Format: Setting %o - %o', 'samplesPerFrame', options.samplesPerFrame) - } else { - debug('Format: Settings %o - %o', 'samplesPerFrame', 1024) - options.samplesPerFrame = 1024 - } - if (options.float !== undefined) { - debug('Format: Setting %o - %o', 'float', options.float) - } - options.endianess = endianess; - debug('Format: Settings applied') - } - - function end (flush, callback) { - debug('end(%o)', flush) - if (options._closed) return debug('_end() was called more than once. Already ended.') - - if (options.handler) { - if (flush) { - debug('Flushing the audio output.') - binding.flush(options.handler, function (success) { - if (success != 1) { - debug('Could not flush the audio output.') - } else { - return close(callback) - } - }) - } else { - return close(callback) - } - } else { - debug('Could not flush the audio output because handler does not exist.') - } - - function close (callback) { - debug('close()') - binding.close(options.handler, callback) - options._closed = true - options.handler = null - } - } -} - -Speaker.getFormat = function getFormat (format) { - var f = null; - if (format.bitDepth == 32 && format.float && format.signed) { - f = binding.MPG123_ENC_FLOAT_32; - } else if (format.bitDepth == 64 && format.float && format.signed) { - f = binding.MPG123_ENC_FLOAT_64; - } else if (format.bitDepth == 8 && format.signed) { - f = binding.MPG123_ENC_SIGNED_8; - } else if (format.bitDepth == 8 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_8; - } else if (format.bitDepth == 16 && format.signed) { - f = binding.MPG123_ENC_SIGNED_16; - } else if (format.bitDepth == 16 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_16; - } else if (format.bitDepth == 24 && format.signed) { - f = binding.MPG123_ENC_SIGNED_24; - } else if (format.bitDepth == 24 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_24; - } else if (format.bitDepth == 32 && format.signed) { - f = binding.MPG123_ENC_SIGNED_32; - } else if (format.bitDepth == 32 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_32; - } - return f; -} diff --git a/package.json b/package.json index d1728e3..a341d6c 100644 --- a/package.json +++ b/package.json @@ -26,13 +26,14 @@ }, "homepage": "https://github.com/audiojs/out#readme", "dependencies": { + "audio-buffer": "^2.4.5", + "audio-sink": "^1.1.6", "bindings": "^1.2.1", "debug": "^2.2.0", "is-audio-buffer": "^1.0.1", "nan": "2.2.0", "object-assign": "^4.1.0", - "pcm-util": "^2.0.3", - "audio-buffer": "^2.4.5" + "pcm-util": "^2.0.3" }, "devDependencies": { "audio-lena": "^1.1.0" diff --git a/src/binding.cpp b/src/binding.cpp index c3e45a7..b29ca12 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -58,7 +58,7 @@ namespace { const char *encname; encname = out123_enc_name(encoding); - printf("Playing with %i channels and %li Hz, encoding %s.\n", channels, rate, encname ? encname : "???"); + printf("Playing with %i channel(s), %li Hz(s) and encoding %s.\n", channels, rate, encname ? encname : "???"); if(out123_start(ao, rate, channels, encoding) || !ao) { fprintf(stderr, "Failed to start output: %s\n", out123_strerror(ao)); diff --git a/tests/one.js b/tests/one.js index 0035d1e..5bd29d0 100644 --- a/tests/one.js +++ b/tests/one.js @@ -7,9 +7,11 @@ console.log('Starting test one.') var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = new AudioBuffer(1, LenaBuffer) -Speaker(buf, null, function (err, written) { - console.log('Test wrote ' + buf.length +' bytes of audio-lena.') - Speaker.end(true, (success) => { - console.log('Finished test one.') - }) +Speaker(buf, null, (err, chunk) => { + if(err || chunk === true) { + console.log('Test ended with errors.') + } else { + Speaker.end(true) + console.log('Test ended with no errors.') + } }) From d1af218b67a046e999337fed45d2b5421338b32e Mon Sep 17 00:00:00 2001 From: connorhartley Date: Fri, 4 Nov 2016 13:42:32 +1300 Subject: [PATCH 20/96] Remove support for node 0.10 and 0.12 --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index b41206d..4c66cc1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,6 @@ node_js: - "6" - "5" - "4" - - "0.12" - - "0.10" addons: apt: packages: @@ -26,6 +24,3 @@ script: - node-gyp rebuild matrix: fast_finish: true - allow_failures: - - node_js: "0.10" - - node_js: "0.12" From ceac771c0d5cc3facd0f70eb03e25cba2769730b Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Fri, 4 Nov 2016 17:49:23 +1300 Subject: [PATCH 21/96] Add streams implementation --- direct.js | 12 ++++++++---- package.json | 6 ++++-- stream.js | 28 ++++++++++++++++++++++++++++ tests/{one.js => play_once.js} | 0 tests/play_stream.js | 20 ++++++++++++++++++++ tests/{two.js => play_twice.js} | 0 6 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 stream.js rename tests/{one.js => play_once.js} (100%) create mode 100644 tests/play_stream.js rename tests/{two.js => play_twice.js} (100%) diff --git a/direct.js b/direct.js index b245e7e..2942ac3 100644 --- a/direct.js +++ b/direct.js @@ -57,7 +57,10 @@ function Speaker (opts) { } write.end = end - return options.sink ? sink : write + write.sink = sink + sink.end = end + return write + function write (chunk, remainder, callback) { debug('write()') @@ -89,7 +92,7 @@ function Speaker (opts) { write(null, remaining, callback) } else { debug('Finished writing chunk.') - if (options.autoFlush) { + if (options.autoFlush && remaining.length < 1) { debug('Flushing the audio output.') binding.flush(options.handler, function (success) { if (success != 1) { @@ -111,10 +114,11 @@ function Speaker (opts) { } } - function sink () { - if (options._closed) return callback(true) + function sink (callback) { + debug('sink()') return audioSink((data, callback) => { + if (options._closed) return callback(true) setTimeout(callback, samplesPerFrame / sampleRate) }) } diff --git a/package.json b/package.json index a341d6c..313fd2d 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,9 @@ "description": "Output PCM data to a device or library.", "main": "lib/index.js", "scripts": { - "test": "node tests/one", - "testtwo": "node tests/two" + "test": "node tests/play_once", + "testtwice": "node tests/play_twice", + "teststream": "node tests/play_stream" }, "repository": { "type": "git", @@ -36,6 +37,7 @@ "pcm-util": "^2.0.3" }, "devDependencies": { + "audio-through": "^2.1.9", "audio-lena": "^1.1.0" } } diff --git a/stream.js b/stream.js new file mode 100644 index 0000000..e34dcf5 --- /dev/null +++ b/stream.js @@ -0,0 +1,28 @@ +'use strict' + +var inherits = require('util').inherits +var objectAssign = require('object-assign') +var audioThrough = require('audio-through') +var Speaker = require('./index') + +module.exports = StreamSpeaker + +function StreamSpeaker (opts) { + if (!(this instanceof StreamSpeaker)) return new StreamSpeaker(opts) + + var options = {} + objectAssign(options, opts) + + audioThrough.call(this, options) + + this.speaker = Speaker(options) + + StreamSpeaker.prototype._write = function (chunk, encoding, callback) { + this.speaker(chunk, null, (err, written) => { + return err ? callback(err) : callback() + }) + } + + StreamSpeaker.prototype.end = this.speaker.end +} +inherits(StreamSpeaker, audioThrough) diff --git a/tests/one.js b/tests/play_once.js similarity index 100% rename from tests/one.js rename to tests/play_once.js diff --git a/tests/play_stream.js b/tests/play_stream.js new file mode 100644 index 0000000..2e1c0d5 --- /dev/null +++ b/tests/play_stream.js @@ -0,0 +1,20 @@ +var AudioBuffer = require('audio-buffer') +var LenaBuffer = require('audio-lena/buffer') +var AudioSpeaker = require('../stream') +var AudioThrough = require('audio-through') + +console.log('Starting test three.') + +var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) +var buf = new AudioBuffer(1, LenaBuffer) + +var through = new AudioThrough(function (buffer) { + return through.count > 1 ? through.end().on('finish', finish()) : buf + + function finish () { + Speaker.end(true) + console.log('Finished test three.') + } +}) + +through.pipe(Speaker) diff --git a/tests/two.js b/tests/play_twice.js similarity index 100% rename from tests/two.js rename to tests/play_twice.js From 02097dc1583aad539ebd02a490cc911911fbc27b Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Fri, 4 Nov 2016 19:45:29 +1300 Subject: [PATCH 22/96] Add pullstream implementation --- package.json | 6 ++++-- pull.js | 28 ++++++++++++++++++++++++++++ readme.md | 6 ++++-- tests/play_pull.js | 25 +++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 pull.js create mode 100644 tests/play_pull.js diff --git a/package.json b/package.json index 313fd2d..85744d5 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "scripts": { "test": "node tests/play_once", "testtwice": "node tests/play_twice", - "teststream": "node tests/play_stream" + "teststream": "node tests/play_stream", + "testpull": "node tests/play_pull" }, "repository": { "type": "git", @@ -34,7 +35,8 @@ "is-audio-buffer": "^1.0.1", "nan": "2.2.0", "object-assign": "^4.1.0", - "pcm-util": "^2.0.3" + "pcm-util": "^2.0.3", + "pull-stream": "^3.5.0" }, "devDependencies": { "audio-through": "^2.1.9", diff --git a/pull.js b/pull.js new file mode 100644 index 0000000..86b29d8 --- /dev/null +++ b/pull.js @@ -0,0 +1,28 @@ +'use strict' + +var drain = require('pull-stream/sinks/drain') +var asyncMap = require('pull-stream/throughs/async-map') +var pull = require('pull-stream/pull') +var Speaker = require('./index') + +module.exports = PullSpeaker + +function PullSpeaker (opts) { + var speaker = Speaker(opts) + var d = drain() + + var sink = pull(asyncMap(function (buf, done) { + done(true) + speaker(buf, null, (err, written) => { + if (err) { + speaker.end(false) + done(err) + } else { + speaker.end(true) + } + }) + }), d) + + sink.abort = d.abort + return sink +} diff --git a/readme.md b/readme.md index 786101b..10dc03b 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,8 @@ -#audio-speaker [![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/unstable.svg)](http://github.com/badges/stability-badges) +#audio-speaker -Output audio stream natively in node or through Web Audio in the browser. +> Output audio natively in node. + +[![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/unstable.svg)](http://github.com/badges/stability-badges) More documentation coming soon. diff --git a/tests/play_pull.js b/tests/play_pull.js new file mode 100644 index 0000000..febf09e --- /dev/null +++ b/tests/play_pull.js @@ -0,0 +1,25 @@ +var AudioBuffer = require('audio-buffer') +var LenaBuffer = require('audio-lena/buffer') +var pull = require('pull-stream') +var AudioSpeaker = require('../pull') + +console.log('Starting test four.') + +var buf = new AudioBuffer(1, LenaBuffer) + +function input () { + return function (end, callback) { + var plays = 0; + if (end) return callback(end) + + if (plays > 1) { + AudioSpeaker.abort() + console.log('Finished test four.') + return callback(true, null) + } + plays++ + return callback(null, buf) + } +} + +pull(input(), AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true })) From ad5247ac3dc7ce848a2c87d01226e5ffe3961af5 Mon Sep 17 00:00:00 2001 From: Dustin Dowell Date: Fri, 4 Nov 2016 03:12:50 -0500 Subject: [PATCH 23/96] mac config --- src/config/mac/x64/config.h | 463 ++++++++++++++++++++++++++++ src/config/mac/x64/out123.h | 583 ++++++++++++++++++++++++++++++++++++ 2 files changed, 1046 insertions(+) create mode 100644 src/config/mac/x64/config.h create mode 100644 src/config/mac/x64/out123.h diff --git a/src/config/mac/x64/config.h b/src/config/mac/x64/config.h new file mode 100644 index 0000000..07a6add --- /dev/null +++ b/src/config/mac/x64/config.h @@ -0,0 +1,463 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if your architecture wants/needs/can use attribute_align_arg and + alignment checks. It is for 32bit x86... */ +/* #undef ABI_ALIGN_FUN */ + +/* Define to use proper rounding. */ +/* #undef ACCURATE_ROUNDING */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define if .balign is present. */ +#define ASMALIGN_BALIGN 1 + +/* Define if .align just takes byte count. */ +/* #undef ASMALIGN_BYTE */ + +/* Define if .align takes 3 for alignment of 2^3=8 bytes instead of 8. */ +/* #undef ASMALIGN_EXP */ + +/* Define if __attribute__((aligned(16))) shall be used */ +#define CCALIGN 1 + +/* Define if debugging is enabled. */ +/* #undef DEBUG */ + +/* The default audio output module(s) to use */ +#define DEFAULT_OUTPUT_MODULE "coreaudio,openal" + +/* Define if building with dynamcally linked libmpg123 */ +#define DYNAMIC_BUILD 1 + +/* Use EFBIG as substitude for EOVERFLOW, mingw.org may lack the latter */ +/* #undef EOVERFLOW */ + +/* Define if FIFO support is enabled. */ +#define FIFO 1 + +/* Define if frame index should be used. */ +#define FRAME_INDEX 1 + +/* Define if gapless is enabled. */ +#define GAPLESS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALIB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_ALC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_AL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_AUDIOIO_H */ + +/* Define to 1 if you have the `atoll' function. */ +#define HAVE_ATOLL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_AUDIOTOOLBOX_AUDIOTOOLBOX_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_AUDIOUNIT_AUDIOUNIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CORESERVICES_CORESERVICES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CULIB_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */ +#define HAVE_GAI_ADDRCONFIG 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `getuid' function. */ +#define HAVE_GETUID 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LANGINFO_H 1 + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `mx' library (-lmx). */ +#define HAVE_LIBMX 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if libltdl is available */ +#define HAVE_LTDL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACHINE_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#define HAVE_MKFIFO 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the `nl_langinfo' function. */ +#define HAVE_NL_LANGINFO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENAL_ALC_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENAL_AL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OS2ME_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OS2_H */ + +/* Define to 1 if you have the `random' function. */ +#define HAVE_RANDOM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SCHED_H 1 + +/* Define to 1 if you have the `sched_setscheduler' function. */ +/* #undef HAVE_SCHED_SETSCHEDULER */ + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setpriority' function. */ +#define HAVE_SETPRIORITY 1 + +/* Define to 1 if you have the `setuid' function. */ +#define HAVE_SETUID 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SNDIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SUN_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define this if you have the POSIX termios library */ +#define HAVE_TERMIOS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to indicate that float storage follows IEEE754. */ +#define IEEE_FLOAT 1 + +/* size of the frame index seek table */ +#define INDEX_SIZE 1000 + +/* Define if IPV6 support is enabled. */ +#define IPV6 1 + +/* Define this to the size of native offset type in bits, used for LFS alias + functions. */ +#define LFS_ALIAS_BITS 64 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* The suffix for module files. */ +#define MODULE_FILE_SUFFIX ".la" + +/* Define if network support is enabled. */ +#define NETWORK 1 + +/* Define to disable 16 bit integer output. */ +/* #undef NO_16BIT */ + +/* Define to disable 32 bit and 24 bit integer output. */ +/* #undef NO_32BIT */ + +/* Define to disable 8 bit integer output. */ +/* #undef NO_8BIT */ + +/* Define to disable downsampled decoding. */ +/* #undef NO_DOWNSAMPLE */ + +/* Define to disable equalizer. */ +/* #undef NO_EQUALIZER */ + +/* Define to disable error messages in combination with a return value (the + return is left intact). */ +/* #undef NO_ERETURN */ + +/* Define to disable error messages. */ +/* #undef NO_ERRORMSG */ + +/* Define to disable feeder and buffered readers. */ +/* #undef NO_FEEDER */ + +/* Define to disable ICY handling. */ +/* #undef NO_ICY */ + +/* Define to disable ID3v2 parsing. */ +/* #undef NO_ID3V2 */ + +/* Define to disable layer I. */ +/* #undef NO_LAYER1 */ + +/* Define to disable layer II. */ +/* #undef NO_LAYER2 */ + +/* Define to disable layer III. */ +/* #undef NO_LAYER3 */ + +/* Define to disable ntom resampling. */ +/* #undef NO_NTOM */ + +/* Define to disable real output. */ +/* #undef NO_REAL */ + +/* Define to disable string functions. */ +/* #undef NO_STRING */ + +/* Define for post-processed 32 bit formats. */ +/* #undef NO_SYNTH32 */ + +/* Define to disable warning messages. */ +/* #undef NO_WARNING */ + +/* Name of package */ +#define PACKAGE "mpg123" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "maintainer@mpg123.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "mpg123" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "mpg123 1.24.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "mpg123" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.24.0" + +/* Define if portaudio v18 API is wanted. */ +/* #undef PORTAUDIO18 */ + +/* The size of `int32_t', as computed by sizeof. */ +#define SIZEOF_INT32_T 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `ssize_t', as computed by sizeof. */ +#define SIZEOF_SSIZE_T 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if modules are enabled */ +#define USE_MODULES 1 + +/* Define for new Huffman decoding scheme. */ +#define USE_NEW_HUFFTABLE 1 + +/* Define to use yasm for assemble AVX sources. */ +/* #undef USE_YASM_FOR_AVX */ + +/* Version number of package */ +#define VERSION "1.24.0" + +/* Define to use Win32 named pipes */ +/* #undef WANT_WIN32_FIFO */ + +/* Define to use Win32 sockets */ +/* #undef WANT_WIN32_SOCKETS */ + +/* Define to use Unicode for Windows */ +/* #undef WANT_WIN32_UNICODE */ + +/* WinXP and above for ipv6 */ +/* #undef WINVER */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* WinXP and above for ipv6 */ +/* #undef _WIN32_WINNT */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `short' if does not define. */ +/* #undef int16_t */ + +/* Define to `int' if does not define. */ +/* #undef int32_t */ + +/* Define to `long long' if does not define. */ +/* #undef int64_t */ + +/* Define to the native offset type (long or actually off_t). */ +#define lfs_alias_t off_t + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to `unsigned long' if does not define. */ +/* #undef size_t */ + +/* Define to `long' if does not define. */ +/* #undef ssize_t */ + +/* Define to `unsigned short' if does not define. */ +/* #undef uint16_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef uint32_t */ + +/* Define to `unsigned long' if does not define. */ +/* #undef uintptr_t */ diff --git a/src/config/mac/x64/out123.h b/src/config/mac/x64/out123.h new file mode 100644 index 0000000..8fde88b --- /dev/null +++ b/src/config/mac/x64/out123.h @@ -0,0 +1,583 @@ +/* + out123: audio output interface + + copyright 1995-2016 by the mpg123 project, + free software under the terms of the LGPL 2.1 + + see COPYING and AUTHORS files in distribution or http://mpg123.org + initially written as audio.h by Michael Hipp, reworked into out123 API + by Thomas Orgis +*/ + +#ifndef _OUT123_H_ +#define _OUT123_H_ + +/** \file out123.h The header file for the libout123 audio output facility. */ + +/* We only need size_t definition. */ +#include + +/* Common audio encoding specification, including a macro for getting + * size of encodined samples in bytes. Said macro is still hardcoded + * into out123_encsize(). Relying on this one may help an old program + * know sizes of encodings added to fmt123.h later on. + * If you don't care, just use the macro. + */ +#include + +/** A macro to check at compile time which set of API functions to expect. + * This should be incremented at least each time a new symbol is added + * to the header. + */ +#define OUT123_API_VERSION 1 + +#ifndef MPG123_EXPORT +/** Defines needed for MS Visual Studio(tm) DLL builds. + * Every public function must be prefixed with MPG123_EXPORT. When building + * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible + * for clients and includes it in the import library which is created together + * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which + * imports the functions from the DLL. + */ +#ifdef BUILD_MPG123_DLL +/* The dll exports. */ +#define MPG123_EXPORT __declspec(dllexport) +#else +#ifdef LINK_MPG123_DLL +/* The exe imports. */ +#define MPG123_EXPORT __declspec(dllimport) +#else +/* Nothing on normal/UNIX builds */ +#define MPG123_EXPORT +#endif +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup out123_api out123 library API + * This is out123, a library focused on continuous playback of audio streams + * via various platform-specific output methods. It glosses over details of + * the native APIs to give an interface close to simply writing data to a + * file. There might be the option to tune details like buffer (period) sizes + * and the number of them on the device side in future, but the focus of the + * library is to ease the use case of just getting that raw audio data out + * there, without interruptions. + * + * The basic idea is to create a handle with out123_new() and open a certain + * output device (using a certain driver module, possibly build-time defaults) + * with out123_open(). Now, you can query the output device for supported + * encodings for given rate and channel count with out123_get_encodings() and + * decide what to use for actually starting playback with out123_start(). + * + * Then, you just need to provide (interleaved pcm) data for playback with + * out123_play(), which will block when the device's buffers are full. You get + * your timing from that (instead of callbacks). If your program does the + * production of the audio data just a little bit faster than the playback, + * causing out123_play() to block ever so briefly, you're fine. + * + * You stop playback with out123_stop(), or just close the device and driver + * via out123_close(), or even just decide to drop it all and do out123_del() + * right away when you're done. + * + * There are other functions for specific needs, but the basic idea should be + * covered by the above. + @{ + */ + +/** Opaque structure for the libout123 handle. */ +struct out123_struct; +/** Typedef shortcut as preferrend name for the handle type. */ +typedef struct out123_struct out123_handle; + +/** Enumeration of codes for the parameters that it is possible to set/get. */ +enum out123_parms +{ + OUT123_FLAGS = 1 /**< integer, various flags, see enum out123_flags */ +, OUT123_PRELOAD /**< float, fraction of buffer to fill before playback */ +, OUT123_GAIN /**< integer, output device gain (module-specific) */ +, OUT123_VERBOSE /**< integer, verbosity to stderr, >= 0 */ +, OUT123_DEVICEBUFFER /**< + * float, length of device buffer in seconds; + * This might be ignored, might have only a loose relation to actual + * buffer sizes and latency, depending on output driver. Try to tune + * this before opening a device if you want to influcence latency or reduce + * dropouts. Value <= 0 uses some default, usually favouring stable playback + * over low latency. Values above 0.5 are probably too much. + */ +, OUT123_PROPFLAGS /**< integer, query driver/device property flags (r/o) */ +, OUT123_NAME /**< string, name of this instance (NULL restores default); + * The value returned by out123_getparam() might be different if the audio + * backend changed it (to be unique among clients, p.ex.). + * TODO: The name provided here is used as prefix in diagnostic messages. */ +}; + +/** Flags to tune out123 behaviour */ +enum out123_flags +{ + OUT123_HEADPHONES = 0x01 /**< output to headphones (if supported) */ +, OUT123_INTERNAL_SPEAKER = 0x02 /**< output to speaker (if supported) */ +, OUT123_LINE_OUT = 0x04 /**< output to line out (if supported) */ +, OUT123_QUIET = 0x08 /**< no printouts to standard error */ +, OUT123_KEEP_PLAYING = 0x10 /**< + * When this is set (default), playback continues in a loop when the device + * does not consume all given data at once. This happens when encountering + * signals (like SIGSTOP, SIGCONT) that cause interruption of the underlying + * functions. + * Note that this flag is meaningless when the optional buffer is employed, + * There, your program will always block until the buffer completely took + * over the data given to it via out123_play(), unless a communcation error + * arises. + */ +}; + +/** Read-only output driver/device property flags (OUT123_PROPFLAGS). */ +enum out123_propflags +{ + OUT123_PROP_LIVE = 0x01 /**< This is a live output, meaning that + * special care might be needed for pauses in playback (p.ex. stream + * of silence instead of interruption), as opposed to files on disk. + */ +, OUT123_PROP_PERSISTENT = 0x02 /**< This (live) output does not need + * special care for pauses (continues with silence itself), + * out123_pause() does nothing to the device. + */ +}; + +/** Create a new output handle. + * This only allocates and initializes memory, so the only possible + * error condition is running out of memory. + * \return pointer to new handle or NULL on error + */ +MPG123_EXPORT +out123_handle *out123_new(void); + +/** Delete output handle. + * This implies out123_close(). + */ +MPG123_EXPORT +void out123_del(out123_handle *ao); + +/** Error code enumeration + * API calls return a useful (positve) value or zero (OUT123_OK) on simple + * success. A negative value (-1 == OUT123_ERR) usually indicates that some + * error occured. Which one, that can be queried using out123_errcode() + * and friends. + */ +enum out123_error +{ + OUT123_ERR = -1 /**< generic alias for verbosity, always == -1 */ +, OUT123_OK = 0 /**< just a name for zero, not going to change */ +, OUT123_DOOM /**< dazzled, out of memory */ +, OUT123_BAD_DRIVER_NAME /**< bad driver name given */ +, OUT123_BAD_DRIVER /**< unspecified issue loading a driver */ +, OUT123_NO_DRIVER /**< no driver loaded */ +, OUT123_NOT_LIVE /**< no active audio device */ +, OUT123_DEV_PLAY /**< some device playback error */ +, OUT123_DEV_OPEN /**< error opening device */ +, OUT123_BUFFER_ERROR /**< + * Some (really unexpected) error in buffer infrastructure. + */ +, OUT123_MODULE_ERROR /**< basic failure in module loading */ +, OUT123_ARG_ERROR /**< some bad function arguments supplied */ +, OUT123_BAD_PARAM /**< unknown parameter code */ +, OUT123_SET_RO_PARAM /**< attempt to set read-only parameter */ +, OUT123_BAD_HANDLE /**< bad handle pointer (NULL, usually) */ +, OUT123_ERRCOUNT /**< placeholder for shaping arrays */ +}; + +/** Get string representation of last encountered error in the + * context of given handle. + * \param ao handle + * \return error string + */ +MPG123_EXPORT +const char* out123_strerror(out123_handle *ao); + +/** Get the plain errcode intead of a string. + * Note that this used to return OUT123_ERR instead of + * OUT123_BAD_HANDLE in case of ao==NULL before mpg123-1.23.5 . + * \param ao handle + * \return error code recorded in handle or OUT123_BAD_HANDLE + */ +MPG123_EXPORT +int out123_errcode(out123_handle *ao); + +/** Return the error string for a given error code. + * \param errcode the integer error code + * \return error string + */ +MPG123_EXPORT +const char* out123_plain_strerror(int errcode); + +/** Set a desired output buffer size. + * This starts a separate process that handles the audio output, decoupling + * the latter from the main process with a memory buffer and saving you the + * burden to ensure sparing CPU cycles for actual playback. + * This is for applicatons that prefer continuous playback over small latency. + * In other words: The kind of applications that out123 is designed for. + * This routine always kills off any currently active audio output module / + * device, even if you just disable the buffer when there is no buffer. + * + * Keep this in mind for memory-constrainted systems: Activating the + * buffer causes a fork of the calling process, doubling the virtual memory + * use. Depending on your operating system kernel's behaviour regarding + * memory overcommit, it might be wise to call out123_set_buffer() very + * early in your program before allocating lots of memory. + * + * There _might_ be a change to threads in future, but for now this is + * classic fork with shared memory, working without any threading library. + * If your platform or build does not support that, you will always get an + * error on trying to set up a non-zero buffer (but the API call will be + * present). + * + * Also, if you do intend to use this from a multithreaded program, think + * twice and make sure that your setup is happy with forking full-blown + * processes off threaded programs. Probably you are better off spawning a + * buffer thread yourself. + * + * \param ao handle + * \param buffer_bytes size (bytes) of a memory buffer for decoded audio, + * a value of zero disables the buffer. + * \return 0 on success, OUT123_ERR on error + */ +MPG123_EXPORT +int out123_set_buffer(out123_handle *ao, size_t buffer_bytes); + +/** Set a specific parameter, for a specific out123_handle, using a parameter + * code chosen from the out123_parms enumeration, to the specified value. + * The parameters usually only change what happens on next out123_open, not + * incfluencing running operation. + * \param ao handle + * \param code parameter code + * \param value input value for integer parameters + * \param fvalue input value for floating point parameters + * \param svalue input value for string parameters (contens are copied) + * \return 0 on success, OUT123_ERR on error. + */ +MPG123_EXPORT +int out123_param( out123_handle *ao, enum out123_parms code +, long value, double fvalue, const char *svalue ); +#define out123_param_int(ao, code, value) \ + out123_param((ao), (code), (value), 0., NULL) +#define out123_param_float(ao, code, value) \ + out123_param((ao), (code), 0, (value), NULL) +#define out123_param_string(ao, code, value) \ + out123_param((ao), (code), 0, 0., (value)) + +/** Get a specific parameter, for a specific out123_handle, using a parameter + * code chosen from the out123_parms enumeration, to the specified value. + * \param ao handle + * \param code parameter code + * \param ret_value output address for integer parameters + * \param ret_fvalue output address for floating point parameters + * \param ret_svalue output address for string parameters (pointer to + * internal memory, so no messing around, please) + * \return 0 on success, OUT123_ERR on error (bad parameter name or bad handle). + */ +MPG123_EXPORT +int out123_getparam( out123_handle *ao, enum out123_parms code +, long *ret_value, double *ret_fvalue, char* *ret_svalue ); +#define out123_getparam_int(ao, code, value) \ + out123_getparam((ao), (code), (value), NULL, NULL) +#define out123_getparam_float(ao, code, value) \ + out123_getparam((ao), (code), NULL, (value), NULL) +#define out123_getparam_string(ao, code, value) \ + out123_getparam((ao), (code), NULL, NULL, (value)) + +/** Copy parameters from another out123_handle. + * \param ao handle + * \param from_ao the handle to copy parameters from + * \return 0 in success, -1 on error + */ +MPG123_EXPORT +int out123_param_from(out123_handle *ao, out123_handle* from_ao); + +/** Get list of driver modules reachable in system in C argv-style format. + * The client is responsible for freeing the memory of both the individual + * strings and the lists themselves. + * A module that is not loadable because of missing libraries is simply + * skipped. You will get stderr messages about that unless OUT123_QUIET was + * was set, though. Failure to open the module directory is a serious error, + * resulting in negative return value. + * \param ao handle + * \param names address for storing list of names + * \param descr address for storing list of descriptions + * \return number of drivers found, -1 on error + */ +MPG123_EXPORT +int out123_drivers(out123_handle *ao, char ***names, char ***descr); + +/** Open an output device with a certain driver + * Note: Opening means that the driver code is loaded and the desired + * device name recorded, possibly tested for availability or tentatively + * opened. After out123_open(), you can ask for supported encodings + * and then really open the device for playback with out123_start(). + * \param ao handle + * \param driver (comma-separated list of) output driver name(s to try), + * NULL for default (stdout for file-based drivers) + * \param device device name to open, NULL for default + * \return 0 on success, -1 on error. + */ +MPG123_EXPORT +int out123_open(out123_handle *ao, const char* driver, const char* device); + +/** Give info about currently loaded driver and device + * Any of the return addresses can be NULL if you are not interested in + * everything. You get pointers to internal storage. They are valid + * as long as the driver/device combination is opened. + * The device may be NULL indicating some unnamed default. + * TODO: Make the driver modules return names for such defaults. + * \param ao handle + * \param driver return address for driver name + * \param device return address for device name + * \return 0 on success, -1 on error (i.e. no driver loaded) + */ +MPG123_EXPORT +int out123_driver_info(out123_handle *ao, char **driver, char **device); + +/** Close the current output device and driver. + * This implies out123_drain() to ensure no data is lost. + * With a buffer, that might cause considerable delay during + * which your main application is blocked waiting. + * Call out123_drop() beforehand if you want to end things + * quickly. + * \param ao handle + */ +MPG123_EXPORT +void out123_close(out123_handle *ao); + +/** Get supported audio encodings for given rate and channel count, + * for the currently openend audio device. + * TODO: Reopening the underlying audio device for each query + * is dumb, at least when dealing with JACK. It takes + * a long time and is just a waste. Reconsider that. + * Make sure that all output modules are fine with it, though! + * Usually, a wider range of rates is supported, but the number + * of sample encodings is limited, as is the number of channels. + * So you can call this with some standard rate and hope that the + * returned encodings work also for others, with the tested channel + * count. + * The return value of -1 on some encountered error conveniently also + * does not match any defined format (only 15 bits used for encodings, + * so this would even work with 16 bit integers). + * This implies out123_stop() to enter query mode. + * \param ao handle + * \param rate sampling rate + * \param channels number of channels + * \return supported encodings combined with bitwise or, to be checked + * against your favourite bitmask, -1 on error + */ +MPG123_EXPORT +int out123_encodings(out123_handle *ao, long rate, int channels); + +/** Return the size (in bytes) of one mono sample of the named encoding. + * \param encoding The encoding value to analyze. + * \return positive size of encoding in bytes, 0 on invalid encoding. */ +MPG123_EXPORT int out123_encsize(int encoding); + +/** Get list of supported formats for currently opened audio device. + * Given a list of sampling rates and minimal/maximal channel count, + * this quickly checks what formats are supported with these + * constraints. The first entry is always reserved for a default + * format for the output device. If there is no such default, + * all values of the format are -1. + * For each requested combination of rate and channels, a format entry is + * created, possible with encoding value 0 to indicate that this combination + * has been tested and rejected. So, when there is no basic error, the + * number of returned format entries should be + * (ratecount*(maxchannels-minchannels+1)+1) + * . But instead of forcing you to guess, this will be allocated by + * successful run. + * For the first entry, the encoding member is supposed to be a definite + * encoding, for the others it is a bitwise combination of all possible + * encodings. + * This function is more efficient than many calls to out123_encodings(). + * \param ao handle + * \param rates pointer to an array of sampling rates, may be NULL for none + * \param ratecount number of provided sampling rates + * \param minchannels minimal channel count + * \param maxchannels maximal channel count + * \param fmtlist return address for array of supported formats + * the encoding field of each entry is a combination of all + * supported encodings at this rate and channel count; + * Memory shall be freed by user. + * \return number of returned format enries, -1 on error + */ +MPG123_EXPORT +int out123_formats( out123_handle *ao, const long *rates, int ratecount + , int minchannels, int maxchannels + , struct mpg123_fmt **fmtlist ); + +/** Get list of encodings known to the library. + * You are responsible for freeing the allocated array. + * \param enclist return address for allocated array of encoding codes + * \return number of encodings, -1 on error + */ +MPG123_EXPORT +int out123_enc_list(int **enclist); + +/** Find encoding code by name. + * \param name short or long name to find encoding code for + * \return encoding if found (enum mpg123_enc_enum), else 0 + */ +MPG123_EXPORT +int out123_enc_byname(const char *name); + +/** Get name of encoding. + * \param encoding code (enum mpg123_enc_enum) + * \return short name for valid encodings, NULL otherwise + */ +MPG123_EXPORT +const char* out123_enc_name(int encoding); + +/** Get long name of encoding. + * \param encoding code (enum mpg123_enc_enum) + * \return long name for valid encodings, NULL otherwise + */ +MPG123_EXPORT +const char* out123_enc_longname(int encoding); + +/** Start playback with a certain output format + * It might be a good idea to have audio data handy to feed after this + * returns with success. + * Rationale for not taking a pointer to struct mpg123_fmt: This would + * always force you to deal with that type and needlessly enlarge the + * shortest possible program. + * \param ao handle + * \param encoding sample encoding (values matching libmpg123 API) + * \param channels number of channels (1 or 2, usually) + * \param rate sampling rate + * \return 0 on success, negative on error (bad format, usually) + */ +MPG123_EXPORT +int out123_start( out123_handle *ao +, long rate, int channels, int encoding ); + +/** Pause playback + * Interrupt playback, holding any data in the optional buffer. + * + * This closes the audio device if it is a live sink, ready to be re-opened + * by out123_continue() or out123_play() with the existing parameters. + * \param ao handle + */ +MPG123_EXPORT +void out123_pause(out123_handle *ao); + +/** Continue playback + * The counterpart to out123_pause(). Announce to the driver that playback + * shall continue. + * + * Playback might not resume immediately if the optional buffer is configured + * to wait for a minimum fill and close to being empty. You can force playback + * of the last scrap with out123_drain(), or just by feeding more data with + * out123_play(), which will trigger out123_continue() for you, too. + * \param ao handle + */ +MPG123_EXPORT +void out123_continue(out123_handle *ao); + +/** Stop playback. + * This waits for pending audio data to drain to the speakers. + * You might want to call out123_drop() before stopping if you want + * to end things right away. + * \param ao handle + */ +MPG123_EXPORT +void out123_stop(out123_handle *ao); + +/** Hand over data for playback and wait in case audio device is busy. + * This survives non-fatal signals like SIGSTOP/SIGCONT and keeps on + * playing until the buffer is done with if the flag + * OUT123_KEEP_PLAYING ist set (default). So, per default, if + * you provided a byte count divisible by the PCM frame size, it is an + * error when less bytes than given are played. + * To be sure if an error occured, check out123_errcode(). + * Also note that it is no accident that the buffer parameter is not marked + * as constant. Some output drivers might need to do things like swap + * byte order. This is done in-place instead of wasting memory on yet + * another copy. + * \param ao handle + * \param buffer pointer to raw audio data to be played + * \param bytes number of bytes to read from the buffer + * \return number of bytes played (might be less than given, even zero) + */ +MPG123_EXPORT +size_t out123_play( out123_handle *ao + , void *buffer, size_t bytes ); + +/** Drop any buffered data, making next provided data play right away. + * This does not imply an actual pause in playback. + * You are expected to play something, unless you called out123_pause(). + * Feel free to call out123_stop() afterwards instead for a quicker + * exit than the implied out123_drain(). + * For live sinks, this may include dropping data from their buffers. + * For others (files), this only concerns data in the optional buffer. + * \param ao handle + */ +MPG123_EXPORT +void out123_drop(out123_handle *ao); + +/** Drain the output, waiting until all data went to the hardware. + * This does imply out123_continue() before and out123_pause() + * after draining. + * This might involve only the optional buffer process, or the + * buffers on the audio driver side, too. + * \param ao handle + */ +MPG123_EXPORT +void out123_drain(out123_handle *ao); + +/** Drain the output, but only partially up to the given number of + * bytes. This gives you the opportunity to do something while + * the optional buffer is writing remaining data instead of having + * one atomic API call for it all. + * + * It is wholly expected that the return value of out123_buffered() + * before and after calling this has a bigger difference than the + * provided limit, as the buffer is writing all the time in the + * background. + * + * This is just a plain out123_drain() if the optional buffer is not + * in use. Also triggers out123_continue(), but only out123_pause() + * if there is no buffered data anymore. + * \param ao handle + * \param bytes limit of buffered bytes to drain + * \return number of bytes drained from buffer + */ +MPG123_EXPORT +void out123_ndrain(out123_handle *ao, size_t bytes); + +/** Get an indication of how many bytes reside in the optional buffer. + * This might get extended to tell the number of bytes queued up in the + * audio backend, too. + * \param ao handle + * \return number of bytes in out123 library buffer + */ +MPG123_EXPORT +size_t out123_buffered(out123_handle *ao); + +/** Extract currently used audio format from handle. + * matching mpg123_getformat(). + * Given return addresses may be NULL to indicate no interest. + * \param ao handle + * \param rate address for sample rate + * \param channels address for channel count + * \param encoding address for encoding + * \param framesize size of a full PCM frame (for convenience) + * \return 0 on success, -1 on error + */ +MPG123_EXPORT +int out123_getformat( out123_handle *ao +, long *rate, int *channels, int *encoding, int *framesize ); + +/* @} */ + +#ifdef __cplusplus +} +#endif + +#endif + From b385e05f179047c0e9754f868738ae0ffc20c628 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 10:10:17 +1300 Subject: [PATCH 24/96] Add usage into readme --- readme.md | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 10dc03b..a72ae21 100644 --- a/readme.md +++ b/readme.md @@ -4,7 +4,56 @@ [![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/unstable.svg)](http://github.com/badges/stability-badges) -More documentation coming soon. +## Usage + +Accepts options in main function: + + - channels (default 2) + - sampleRate (default 44100) + - endianess (default 'LE') + - bitDepth (default 16) + - signed (default true) + - float (default false) + - autoFlush (default false) + +More documentation on these options will be added soon. + +We have some variety in the way you can write to the Speaker. + +### Stream +```js +var speaker = require('audio-speaker/stream') +var generator = require('audio-generator/stream') + +generator(function (time) { + var p = Math.PI * 2 + return [Math.sin(p * time * 441), Math.sin(p * time * 439)] +}).pipe(speaker({ autoFlush: true })) +``` + +### Pull-stream +```js +var pull = require('pull-stream/pull') +var speaker = require('audio-speaker/pull') +var osc = require('audio-oscillator/pull') + +pull(osc({frequency: 440}), speaker({ autoFlush: true })) +``` + +### Direct + +```js +var speaker = require('audio-speaker') +var generator = require('audio-generator') + +var output = speaker({ autoFlush: true }) +var input = generator(t => Math.sin(t * Math.PI * 2 * 440)) + +(function loop (err, buf) { + var buffer = input() + output(buffer, null, loop) +}) +``` ## Credits @@ -12,6 +61,8 @@ More documentation coming soon. | :---------------------------: | | [Connor Hartley][connor-link] | +Thanks to @jamen and @dustindowell22 for the mpg123 env configurations. + #### Related > [mpg123](https://github.com/audiojs/mpg123) - modifications to mpg123 to suit audio-speaker.
From b463e0b1d3abf4aa62fa960a66e9f2b416db3418 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 10:50:19 +1300 Subject: [PATCH 25/96] Add docs to direct --- direct.js | 47 +++++++++++++++++++++++++++++++++++++-------- readme.md | 2 +- tests/play_once.js | 9 +++++---- tests/play_twice.js | 4 ++-- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/direct.js b/direct.js index 2942ac3..6a4c6aa 100644 --- a/direct.js +++ b/direct.js @@ -13,6 +13,15 @@ var endianess = 'function' == os.endianess ? os.endianess() : 'LE' module.exports = Speaker +/** + * The Speaker function initializes a new audio handler, + * then returns the write method to output audio to. + * + * @param {Object} opts options for the speaker + * @return {Function} write write audio from a buffer or audiobuffer + * @module Speaker + * @api public + */ function Speaker (opts) { debug('Speaker()') var options = {} @@ -61,7 +70,20 @@ function Speaker (opts) { sink.end = end return write - + /** + * The write function takes a buffer or audiobuffer and + * writes it to the speaker output. If the chunks are too + * large it will break it up and put the remainding chunks + * into a queue. + * NOTE: You can only write new chunks once the callback is + * called with no errors. + * + * @param {AudioBuffer} chunk (or Buffer) containing the data to be output + * @param {AudioBuffer} remainer (or Buffer) containing the remaining data, that should be kept null + * @param {Function} callback callback with error and chunk parameters + * @return void + * @api public + */ function write (chunk, remainder, callback) { debug('write()') if (options._closed) return debug('write() cannot be called after the speaker is closed.') @@ -168,6 +190,17 @@ function Speaker (opts) { debug('Format: Settings applied') } + /** + * The end function closes the speaker and stops + * it from writing anymore data. The output data + * that was already written can be optionally flushed. + * NOTE: You cannot write anymore data after closing the speaker. + * + * @param {Boolean} flush flushes the written data (default is false) + * @param {Function} callback callback with error parameter + * @return void + * @api public + */ function end (flush, callback) { debug('end(%o)', flush) if (options._closed) return debug('_end() was called more than once. Already ended.') @@ -191,13 +224,11 @@ function Speaker (opts) { function close (callback) { debug('close()') - if (callback) { - binding.close(options.handler, callback) - } else { - binding.close(options.handler, (success) => { - if (success != 1) throw new Error('Failed to close speaker.') - }) - } + binding.close(options.handler, (success) => { + if (callback) { + success ? callback() : callback(new Error('Failed to close speaker.')) + } + }) options._closed = true options.handler = null } diff --git a/readme.md b/readme.md index a72ae21..6d6dd2e 100644 --- a/readme.md +++ b/readme.md @@ -2,7 +2,7 @@ > Output audio natively in node. -[![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/unstable.svg)](http://github.com/badges/stability-badges) +[![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) ## Usage diff --git a/tests/play_once.js b/tests/play_once.js index 5bd29d0..8a4c423 100644 --- a/tests/play_once.js +++ b/tests/play_once.js @@ -8,10 +8,11 @@ var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: tr var buf = new AudioBuffer(1, LenaBuffer) Speaker(buf, null, (err, chunk) => { - if(err || chunk === true) { - console.log('Test ended with errors.') + if (err || chunk === true) { + console.log('Finished test with errors.') } else { - Speaker.end(true) - console.log('Test ended with no errors.') + Speaker.end(true, (err) => { + err ? console.log('Finished test with errors.') : console.log('Finished test with no errors.') + }) } }) diff --git a/tests/play_twice.js b/tests/play_twice.js index ecf1b0f..f648c71 100644 --- a/tests/play_twice.js +++ b/tests/play_twice.js @@ -11,8 +11,8 @@ Speaker(buf, null, function (err, written) { console.log('Test wrote ' + buf.length +' bytes of audio-lena.') Speaker(buf, null, function (err, done) { console.log('Test wrote ' + (buf.length * 2) + ' bytes of audio-lena total over two runs.') - Speaker.end(false, (success) => { - console.log('Finished test two.') + Speaker.end(false, (err) => { + err ? console.log('Finished test two with errors.') : console.log('Finished test two with no errors.') }) }) }) From 52d54c3066550d5ed874a6fd60ff2afeba8a448c Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 10:55:02 +1300 Subject: [PATCH 26/96] Add docs to pull --- pull.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pull.js b/pull.js index 86b29d8..a7d84bc 100644 --- a/pull.js +++ b/pull.js @@ -7,6 +7,16 @@ var Speaker = require('./index') module.exports = PullSpeaker +/** + * The PullSpeaker function initializes a speaker + * and returns a sink for data to be pulled to, which + * is then written to the speaker. + * + * @param {Object} opts options for the speaker + * @return {Drain} drain pull-stream sink for the data to be pulled to + * @module PullSpeaker + * @api public + */ function PullSpeaker (opts) { var speaker = Speaker(opts) var d = drain() From 26161800f82999c5e6b458facbaa9041b03cd4aa Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 10:59:10 +1300 Subject: [PATCH 27/96] Add docs to stream --- stream.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/stream.js b/stream.js index e34dcf5..45d01d0 100644 --- a/stream.js +++ b/stream.js @@ -7,6 +7,16 @@ var Speaker = require('./index') module.exports = StreamSpeaker +/** + * The StreamSpeaker function initializes a speaker + * and inherits {Module} AudioThrough for pipable data + * functionality. + * + * @param {Object} opts options for the speaker + * @return void + * @module StreamSpeaker + * @api public + */ function StreamSpeaker (opts) { if (!(this instanceof StreamSpeaker)) return new StreamSpeaker(opts) From e1c7bee9df97a32f6c11c09dadfde569bca1b077 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 11:09:49 +1300 Subject: [PATCH 28/96] Remove remaining param from write publicly --- direct.js | 73 +++++++++++++++++++++++---------------------- pull.js | 2 +- readme.md | 2 +- stream.js | 2 +- tests/play_once.js | 2 +- tests/play_twice.js | 2 +- 6 files changed, 43 insertions(+), 40 deletions(-) diff --git a/direct.js b/direct.js index 6a4c6aa..c2d3b1d 100644 --- a/direct.js +++ b/direct.js @@ -79,57 +79,60 @@ function Speaker (opts) { * called with no errors. * * @param {AudioBuffer} chunk (or Buffer) containing the data to be output - * @param {AudioBuffer} remainer (or Buffer) containing the remaining data, that should be kept null * @param {Function} callback callback with error and chunk parameters * @return void * @api public */ - function write (chunk, remainder, callback) { + function write (chunk, callback) { debug('write()') if (options._closed) return debug('write() cannot be called after the speaker is closed.') if (chunk && options._busy) return debug('write() cannot be called until the previous buffer has been written.') - if (options.handler) { - options._busy = true + next(chunk, null, callback) + + function next (chunk, remainder, callback) { + if (options.handler) { + options._busy = true - var chunkBuf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk || new Buffer(0) - var remainderBuf = isAudioBuffer(remainder) ? pcm.toBuffer(remainder, options) : remainder || new Buffer(0) + var chunkBuf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk || new Buffer(0) + var remainderBuf = isAudioBuffer(remainder) ? pcm.toBuffer(remainder, options) : remainder || new Buffer(0) - var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) + var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) - debug("%o bytes total queued for output.", queue.length) + debug("%o bytes total queued for output.", queue.length) - var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue - var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) + var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue + var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) - debug("%o bytes writing to the speaker.", output.length) - debug("%o bytes remaining in the queue.", remaining.length) + debug("%o bytes writing to the speaker.", output.length) + debug("%o bytes remaining in the queue.", remaining.length) - binding.write(options.handler, output, output.length, onWrite) + binding.write(options.handler, output, output.length, onWrite) - function onWrite (written) { - debug('Wrote %o bytes this chunk.', written) - if(!remaining.length < 1) { - debug('Writing remaining chunks.') - write(null, remaining, callback) - } else { - debug('Finished writing chunk.') - if (options.autoFlush && remaining.length < 1) { - debug('Flushing the audio output.') - binding.flush(options.handler, function (success) { - if (success != 1) { - debug('Could not flush the audio output.') - options._busy = false - callback(new Error('Could not flush the audio output.'), written) - } else { - debug('Flushed audio successfully.') - options._busy = false - callback(null, written) - } - }) + function onWrite (written) { + debug('Wrote %o bytes this chunk.', written) + if(!remaining.length < 1) { + debug('Writing remaining chunks.') + next(null, remaining, callback) } else { - options._busy = false - callback(null, written) + debug('Finished writing chunk.') + if (options.autoFlush && remaining.length < 1) { + debug('Flushing the audio output.') + binding.flush(options.handler, function (success) { + if (success != 1) { + debug('Could not flush the audio output.') + options._busy = false + callback(new Error('Could not flush the audio output.'), written) + } else { + debug('Flushed audio successfully.') + options._busy = false + callback(null, written) + } + }) + } else { + options._busy = false + callback(null, written) + } } } } diff --git a/pull.js b/pull.js index a7d84bc..c3ab39a 100644 --- a/pull.js +++ b/pull.js @@ -23,7 +23,7 @@ function PullSpeaker (opts) { var sink = pull(asyncMap(function (buf, done) { done(true) - speaker(buf, null, (err, written) => { + speaker(buf, (err, written) => { if (err) { speaker.end(false) done(err) diff --git a/readme.md b/readme.md index 6d6dd2e..89741da 100644 --- a/readme.md +++ b/readme.md @@ -51,7 +51,7 @@ var input = generator(t => Math.sin(t * Math.PI * 2 * 440)) (function loop (err, buf) { var buffer = input() - output(buffer, null, loop) + output(buffer, loop) }) ``` diff --git a/stream.js b/stream.js index 45d01d0..8f8abb2 100644 --- a/stream.js +++ b/stream.js @@ -28,7 +28,7 @@ function StreamSpeaker (opts) { this.speaker = Speaker(options) StreamSpeaker.prototype._write = function (chunk, encoding, callback) { - this.speaker(chunk, null, (err, written) => { + this.speaker(chunk, (err, written) => { return err ? callback(err) : callback() }) } diff --git a/tests/play_once.js b/tests/play_once.js index 8a4c423..e6d663e 100644 --- a/tests/play_once.js +++ b/tests/play_once.js @@ -7,7 +7,7 @@ console.log('Starting test one.') var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = new AudioBuffer(1, LenaBuffer) -Speaker(buf, null, (err, chunk) => { +Speaker(buf, (err, chunk) => { if (err || chunk === true) { console.log('Finished test with errors.') } else { diff --git a/tests/play_twice.js b/tests/play_twice.js index f648c71..41dfa3a 100644 --- a/tests/play_twice.js +++ b/tests/play_twice.js @@ -7,7 +7,7 @@ console.log('Starting test two.') var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) var buf = new AudioBuffer(1, LenaBuffer) -Speaker(buf, null, function (err, written) { +Speaker(buf, function (err, written) { console.log('Test wrote ' + buf.length +' bytes of audio-lena.') Speaker(buf, null, function (err, done) { console.log('Test wrote ' + (buf.length * 2) + ' bytes of audio-lena total over two runs.') From a9da5e3d0a135c3d66486a366f308e36c75ceeac Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 11:13:58 +1300 Subject: [PATCH 29/96] Add browser note --- readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.md b/readme.md index 89741da..8a48c8d 100644 --- a/readme.md +++ b/readme.md @@ -4,6 +4,9 @@ [![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) +NOTE: The browser implementation for this is being moved to a separate module to +save space from mpg123 library and other node-only functions. + ## Usage Accepts options in main function: From 31b832a50497e0bdb98c8f2fd6a2dbb547349df9 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 12:39:41 +1300 Subject: [PATCH 30/96] Use tape for tests --- direct.js | 4 ++-- package.json | 11 ++++++----- tests/play_once.js | 27 +++++++++++++++------------ tests/play_pull.js | 30 ++++++++++++++++-------------- tests/play_stream.js | 25 ++++++++++++++----------- tests/play_twice.js | 21 ++++++++++++--------- 6 files changed, 65 insertions(+), 53 deletions(-) diff --git a/direct.js b/direct.js index c2d3b1d..80d2c82 100644 --- a/direct.js +++ b/direct.js @@ -159,8 +159,8 @@ function Speaker (opts) { if (options.channels !== undefined) { debug('Format: Setting %o - %o', 'channels', options.channels) } else { - debug('Format: Setting %o - %o', 'channels', 2) - options.channels = 2 + debug('Format: Setting %o - %o', 'channels', 1) + options.channels = 1 } if (options.bitDepth !== undefined) { debug('Format: Setting %o - %o', 'bitDepth', options.bitDepth) diff --git a/package.json b/package.json index 85744d5..a921850 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,10 @@ "description": "Output PCM data to a device or library.", "main": "lib/index.js", "scripts": { - "test": "node tests/play_once", - "testtwice": "node tests/play_twice", - "teststream": "node tests/play_stream", - "testpull": "node tests/play_pull" + "test": "tape tests/play_once.js", + "testtwice": "tape tests/play_twice.js", + "teststream": "tape tests/play_stream.js", + "testpull": "tape tests/play_pull.js" }, "repository": { "type": "git", @@ -39,7 +39,8 @@ "pull-stream": "^3.5.0" }, "devDependencies": { + "audio-lena": "^1.1.0", "audio-through": "^2.1.9", - "audio-lena": "^1.1.0" + "tape": "^4.6.2" } } diff --git a/tests/play_once.js b/tests/play_once.js index e6d663e..90376dc 100644 --- a/tests/play_once.js +++ b/tests/play_once.js @@ -1,18 +1,21 @@ +var test = require('tape') + var AudioBuffer = require('audio-buffer') var LenaBuffer = require('audio-lena/buffer') var AudioSpeaker = require('../index') -console.log('Starting test one.') - -var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) -var buf = new AudioBuffer(1, LenaBuffer) +test('play audio once test', function (t) { + var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) + var buf = new AudioBuffer(1, LenaBuffer) -Speaker(buf, (err, chunk) => { - if (err || chunk === true) { - console.log('Finished test with errors.') - } else { - Speaker.end(true, (err) => { - err ? console.log('Finished test with errors.') : console.log('Finished test with no errors.') - }) - } + Speaker(buf, (err, chunk) => { + if (err || chunk === true) { + t.error(err, 'Write callback caught an unexpected error.') + } else { + Speaker.end(true, (err) => { + err ? t.error(err) : t.pass('Output successful.') + t.end() + }) + } + }) }) diff --git a/tests/play_pull.js b/tests/play_pull.js index febf09e..b7e3745 100644 --- a/tests/play_pull.js +++ b/tests/play_pull.js @@ -1,25 +1,27 @@ +var test = require('tape') + var AudioBuffer = require('audio-buffer') var LenaBuffer = require('audio-lena/buffer') var pull = require('pull-stream') var AudioSpeaker = require('../pull') -console.log('Starting test four.') +test('play pull stream audio', function(t) { + var buf = new AudioBuffer(1, LenaBuffer) -var buf = new AudioBuffer(1, LenaBuffer) + function input () { + return function (end, callback) { + var plays = 0; -function input () { - return function (end, callback) { - var plays = 0; - if (end) return callback(end) + if (plays > 1 || end) { + t.pass('Output successful.') + t.end() + return callback(end) + } - if (plays > 1) { - AudioSpeaker.abort() - console.log('Finished test four.') - return callback(true, null) + plays++ + return callback(null, buf) } - plays++ - return callback(null, buf) } -} -pull(input(), AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true })) + pull(input(), AudioSpeaker()) +}) diff --git a/tests/play_stream.js b/tests/play_stream.js index 2e1c0d5..bd25202 100644 --- a/tests/play_stream.js +++ b/tests/play_stream.js @@ -1,20 +1,23 @@ +var test = require('tape') + var AudioBuffer = require('audio-buffer') var LenaBuffer = require('audio-lena/buffer') var AudioSpeaker = require('../stream') var AudioThrough = require('audio-through') -console.log('Starting test three.') +test('play node stream audio', function(t) { + var buf = new AudioBuffer(1, LenaBuffer) + var Speaker = new AudioSpeaker() -var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) -var buf = new AudioBuffer(1, LenaBuffer) + var through = new AudioThrough(function (buffer) { + return through.count > 1 ? through.end().on('finish', finish()) : buf -var through = new AudioThrough(function (buffer) { - return through.count > 1 ? through.end().on('finish', finish()) : buf + function finish () { + Speaker.end(true) + t.pass('Output successful.') + t.end() + } + }) - function finish () { - Speaker.end(true) - console.log('Finished test three.') - } + through.pipe(Speaker) }) - -through.pipe(Speaker) diff --git a/tests/play_twice.js b/tests/play_twice.js index 41dfa3a..d107a6c 100644 --- a/tests/play_twice.js +++ b/tests/play_twice.js @@ -1,18 +1,21 @@ +var test = require('tape') + var AudioBuffer = require('audio-buffer') var LenaBuffer = require('audio-lena/buffer') var AudioSpeaker = require('../index') -console.log('Starting test two.') - -var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) -var buf = new AudioBuffer(1, LenaBuffer) +test('play audio twice test', function(t) { + var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) + var buf = new AudioBuffer(1, LenaBuffer) -Speaker(buf, function (err, written) { - console.log('Test wrote ' + buf.length +' bytes of audio-lena.') - Speaker(buf, null, function (err, done) { - console.log('Test wrote ' + (buf.length * 2) + ' bytes of audio-lena total over two runs.') + Speaker(buf, function (err, written) { + err ? t.error(err, 'Write callback caught an unexpected error.') : t.pass('Test wrote ' + buf.length +' bytes of audio-lena.') + Speaker(buf, function (err, done) { + err ? t.error(err, 'Write callback caught an unexpected error.') : t.pass('Test wrote ' + (buf.length * 2) +' bytes of audio-lena.') Speaker.end(false, (err) => { - err ? console.log('Finished test two with errors.') : console.log('Finished test two with no errors.') + err ? t.error(err) : t.pass('Output successful.') + t.end() }) }) + }) }) From 613e8f90e22357d725fc7a270dcd85de857c98e7 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 13:10:45 +1300 Subject: [PATCH 31/96] Replace validate with objectAssign --- direct.js | 58 ++++++++++--------------------------------------------- 1 file changed, 10 insertions(+), 48 deletions(-) diff --git a/direct.js b/direct.js index 80d2c82..30f31c1 100644 --- a/direct.js +++ b/direct.js @@ -26,7 +26,16 @@ function Speaker (opts) { debug('Speaker()') var options = {} - objectAssign(options, opts) + options = objectAssign({ + channels: 1, + float: false, + bitDepth: opts.float ? 32 : 64, + signed: (opts.float ? 32 : 64) != 8, + samplesPerFrame: 1024, + sampleRate: 44100, + endianess: endianess, + autoFlush: false + }, opts) if (options.handler) { throw new Error('_create() was called more than once. Only one handler should exist.') @@ -35,8 +44,6 @@ function Speaker (opts) { options._closed = false options._busy = false - _validate(options) - var format = Speaker.getFormat(options) if (format === null) { throw new Error('Invalid format options.') @@ -148,51 +155,6 @@ function Speaker (opts) { }) } - function _validate (options) { - debug('Format: Setting options - %o', Object.keys(options)) - if (options.autoFlush !== undefined) { - debug('Format: Setting %o - %o', 'autoFlush', options.autoFlush) - } else { - debug('Format: Setting %o - %o', 'autoFlush', false) - options.autoFlush = false - } - if (options.channels !== undefined) { - debug('Format: Setting %o - %o', 'channels', options.channels) - } else { - debug('Format: Setting %o - %o', 'channels', 1) - options.channels = 1 - } - if (options.bitDepth !== undefined) { - debug('Format: Setting %o - %o', 'bitDepth', options.bitDepth) - } else { - debug('Format: Setting %o - %o', 'bitDepth', options.float ? 32 : 16) - options.bitDepth = options.float ? 32 : 16 - } - if (options.sampleRate !== undefined) { - debug('Format: Setting %o - %o', 'sampleRate', options.sampleRate) - } else { - debug('Format: Setting %o - %o', 'sampleRate', 44100) - options.sampleRate = 44100 - } - if (options.signed !== undefined) { - debug('Format: Setting %o - %o', 'signed', options.signed) - } else { - debug('Format: Setting %o - %o', 'signed', options.bitDepth != 8) - options.signed = options.bitDepth != 8 - } - if (options.samplesPerFrame !== undefined) { - debug('Format: Setting %o - %o', 'samplesPerFrame', options.samplesPerFrame) - } else { - debug('Format: Settings %o - %o', 'samplesPerFrame', 1024) - options.samplesPerFrame = 1024 - } - if (options.float !== undefined) { - debug('Format: Setting %o - %o', 'float', options.float) - } - options.endianess = endianess; - debug('Format: Settings applied') - } - /** * The end function closes the speaker and stops * it from writing anymore data. The output data From 3e24ec35c6c3f1a92f514f32843f497750c42d8e Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 14:04:10 +1300 Subject: [PATCH 32/96] Update submodule to fix coreaudio and remove unnecessary compat headers --- src/mpg123 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mpg123 b/src/mpg123 index 3ee4664..5ed76a9 160000 --- a/src/mpg123 +++ b/src/mpg123 @@ -1 +1 @@ -Subproject commit 3ee46645660d3da22aca34313b87b314307188bc +Subproject commit 5ed76a99aebb471e5705b8b1949f59338499402c From fbcd237c47409a6b341e570f83233d1ef62096f8 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 15:35:00 +1300 Subject: [PATCH 33/96] Add browser implementation --- browser-direct.js | 21 +++++++++++++++++++++ browser-stream.js | 24 ++++++++++++++++++++++++ readme.md | 5 +++-- 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 browser-direct.js create mode 100644 browser-stream.js diff --git a/browser-direct.js b/browser-direct.js new file mode 100644 index 0000000..bb0474c --- /dev/null +++ b/browser-direct.js @@ -0,0 +1,21 @@ +'use strict' + +var writer = require('web-audio-stream') +var context = require('audio-context') + +module.exports = BrowserSpeaker + +/** + * The BrowserSpeaker function initalizes and returns + * a {Module} webaudiostream to write to. + * + * @param {Object} opts options for the speaker + * @return {Module} webaudiostream for writing data to + * @module BrowserSpeaker + * @api public + */ +function BrowserSpeaker (opts) { + var ctx = opts && opts.context || context + + return write(ctx.destination, opts) +} diff --git a/browser-stream.js b/browser-stream.js new file mode 100644 index 0000000..c9aaefb --- /dev/null +++ b/browser-stream.js @@ -0,0 +1,24 @@ +'use strict' + +var inherits = require('util').inherits +var WAAStream = require('web-audio-stream/writable') +var context = require('audio-context') + +module.exports = BrowserStreamSpeaker + +/** + * The BrowserSpeaker function initalizes and returns + * a {Module} webaudiostream to write to from a stream. + * + * @param {Object} opts options for the speaker + * @return {Module} webaudiostream for writing data to + * @module BrowserSpeaker + * @api public + */ +function BrowserStreamSpeaker (opts) { + if (!(this instanceof BrowserStreamSpeaker)) return new BrowserStreamSpeaker(opts) + + var ctx = opts && opts.context || context + + WAAStream.call(this, ctx.destination, opts) +} diff --git a/readme.md b/readme.md index 8a48c8d..ee3ab81 100644 --- a/readme.md +++ b/readme.md @@ -4,8 +4,9 @@ [![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) -NOTE: The browser implementation for this is being moved to a separate module to -save space from mpg123 library and other node-only functions. +## Install + +`npm install audio-speaker`` ## Usage From 280da98fc38cd0263543cb9f149df4d86936aab4 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 16:26:39 +1300 Subject: [PATCH 34/96] Add mpg123 as an optional dependency --- binding.gyp | 22 - direct.js | 2 +- package.json | 5 +- src/binding.cpp | 206 ------ src/config/linux/x64/config.h | 463 ------------- src/config/linux/x64/out123.h | 583 ---------------- src/config/mac/x64/config.h | 463 ------------- src/config/mac/x64/out123.h | 583 ---------------- src/config/win/ia32/config.h | 463 ------------- src/config/win/ia32/out123.h | 583 ---------------- src/config/win/x64/config.h | 463 ------------- src/config/win/x64/out123.h | 583 ---------------- src/mpg123 | 1 - src/mpg123.gyp | 195 ------ src/pointer_wrapper.h | 27 - src/util/getopt.c | 1228 --------------------------------- src/util/getopt.h | 173 ----- src/util/unistd.h | 52 -- 18 files changed, 4 insertions(+), 6091 deletions(-) delete mode 100644 binding.gyp delete mode 100644 src/binding.cpp delete mode 100644 src/config/linux/x64/config.h delete mode 100644 src/config/linux/x64/out123.h delete mode 100644 src/config/mac/x64/config.h delete mode 100644 src/config/mac/x64/out123.h delete mode 100644 src/config/win/ia32/config.h delete mode 100644 src/config/win/ia32/out123.h delete mode 100644 src/config/win/x64/config.h delete mode 100644 src/config/win/x64/out123.h delete mode 160000 src/mpg123 delete mode 100644 src/mpg123.gyp delete mode 100644 src/pointer_wrapper.h delete mode 100644 src/util/getopt.c delete mode 100644 src/util/getopt.h delete mode 100644 src/util/unistd.h diff --git a/binding.gyp b/binding.gyp deleted file mode 100644 index 1489f30..0000000 --- a/binding.gyp +++ /dev/null @@ -1,22 +0,0 @@ -{ - 'targets': [ - { - 'target_name': 'binding', - 'win_delay_load_hook': 'true', - 'sources': [ - 'src/binding.cpp', - 'src/util/getopt.c' - ], - 'include_dirs': [ - 'src/util', - 'src/mpg123/src', - 'src/mpg123/src/libmpg123', - 'src/mpg123/src/libout123', - '()), value); - - info.GetReturnValue().Set(scope.Escape(WrapPointer(ao, static_cast(sizeof(ao))))); - } - - NAN_METHOD(open) { - Nan::HandleScope scope; - - out123_handle *ao = UnwrapPointer(info[0]); - - long rate = (long) info[1]->Int32Value(); - int channels = info[2]->Int32Value(); - int encoding = info[3]->Int32Value(); - - int value = 0; - - const char *encname; - encname = out123_enc_name(encoding); - - printf("Playing with %i channel(s), %li Hz(s) and encoding %s.\n", channels, rate, encname ? encname : "???"); - - if(out123_start(ao, rate, channels, encoding) || !ao) { - fprintf(stderr, "Failed to start output: %s\n", out123_strerror(ao)); - out123_del(ao); - value = 0; - } else { - value = 1; - } - - result_callback(new Nan::Callback(info[4].As()), value); - - info.GetReturnValue().SetUndefined(); - } - - NAN_METHOD(write) { - Nan::HandleScope scope; - - out123_handle *ao = UnwrapPointer(info[0]); - unsigned char *buffer = UnwrapPointer(info[1]); - int length = info[2]->Int32Value(); - - write_req *req = new write_req; - req->ao = ao; - req->buffer = buffer; - req->len = length; - req->written = 0; - req->callback = new Nan::Callback(info[3].As()); - - req->req.data = req; - - uv_queue_work(uv_default_loop(), &req->req, write_async, (uv_after_work_cb) write_after); - - info.GetReturnValue().SetUndefined(); - } - - NAN_METHOD(flush) { - Nan::HandleScope scope; - - out123_handle *ao = UnwrapPointer(info[0]); - - int value = 0; - - if(ao) { - out123_drain(ao); - value = 1; - } else { - value = 0; - } - - result_callback(new Nan::Callback(info[1].As()), value); - - info.GetReturnValue().SetUndefined(); - } - - NAN_METHOD(close) { - Nan::HandleScope scope; - - out123_handle *ao = UnwrapPointer(info[0]); - - int value = 0; - - if(ao) { - out123_drop(ao); - out123_del(ao); - value = 1; - } else { - value = 0; - } - - result_callback(new Nan::Callback(info[1].As()), value); - - info.GetReturnValue().SetUndefined(); - } - - void result_callback(Nan::Callback *callback, int result) { - Nan::HandleScope scope; - - Local argv[] = { - Nan::New(static_cast(result)) - }; - - callback->Call(1, argv); - } - - void write_async(uv_work_t *req) { - write_req *wreq = reinterpret_cast(req->data); - wreq->written = out123_play(wreq->ao, wreq->buffer, wreq->len); - } - - void write_after(uv_work_t *req) { - Nan::HandleScope scope; - - write_req *wreq = reinterpret_cast(req->data); - - Local argv[] = { - Nan::New(wreq->written) - }; - - wreq->callback->Call(1, argv); - - delete wreq->callback; - } - - void InitializeModule(Handle target) { - Nan::HandleScope scope; - - out123_handle *ao = out123_new(); - - long rate = 44100; - int channels = 2; - int encoding = MPG123_ENC_SIGNED_16; - int framesize = 1; - - if(!ao) { - fprintf(stderr, "Failed to initialize output handle.\n"); - out123_del(ao); - } else if(out123_open(ao, NULL, NULL) != OUT123_OK) { - fprintf(stderr, "Failed to open output: %s\n", out123_strerror(ao)); - out123_del(ao); - } - - #define CONST_INT(value) \ - Nan::ForceSet(target, Nan::New(#value).ToLocalChecked(), Nan::New(value), \ - static_cast(ReadOnly|DontDelete)); - - CONST_INT(MPG123_ENC_FLOAT_32); - CONST_INT(MPG123_ENC_FLOAT_64); - CONST_INT(MPG123_ENC_SIGNED_8); - CONST_INT(MPG123_ENC_UNSIGNED_8); - CONST_INT(MPG123_ENC_SIGNED_16); - CONST_INT(MPG123_ENC_UNSIGNED_16); - CONST_INT(MPG123_ENC_SIGNED_24); - CONST_INT(MPG123_ENC_UNSIGNED_24); - CONST_INT(MPG123_ENC_SIGNED_32); - CONST_INT(MPG123_ENC_UNSIGNED_32); - - Nan::SetMethod(target, "create", create); - Nan::SetMethod(target, "open", open); - Nan::SetMethod(target, "write", write); - Nan::SetMethod(target, "flush", flush); - Nan::SetMethod(target, "close", close); - } -} - -NODE_MODULE(binding, InitializeModule); diff --git a/src/config/linux/x64/config.h b/src/config/linux/x64/config.h deleted file mode 100644 index d6344e5..0000000 --- a/src/config/linux/x64/config.h +++ /dev/null @@ -1,463 +0,0 @@ -/* src/config.h. Generated from config.h.in by configure. */ -/* src/config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if your architecture wants/needs/can use attribute_align_arg and - alignment checks. It is for 32bit x86... */ -/* #undef ABI_ALIGN_FUN */ - -/* Define to use proper rounding. */ -/* #undef ACCURATE_ROUNDING */ - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define if .balign is present. */ -#define ASMALIGN_BALIGN 1 - -/* Define if .align just takes byte count. */ -/* #undef ASMALIGN_BYTE */ - -/* Define if .align takes 3 for alignment of 2^3=8 bytes instead of 8. */ -/* #undef ASMALIGN_EXP */ - -/* Define if __attribute__((aligned(16))) shall be used */ -#define CCALIGN 1 - -/* Define if debugging is enabled. */ -/* #undef DEBUG */ - -/* The default audio output module(s) to use */ -#define DEFAULT_OUTPUT_MODULE "alsa,oss,jack,pulse,sdl,openal" - -/* Define if building with dynamcally linked libmpg123 */ -#define DYNAMIC_BUILD 1 - -/* Use EFBIG as substitude for EOVERFLOW, mingw.org may lack the latter */ -/* #undef EOVERFLOW */ - -/* Define if FIFO support is enabled. */ -#define FIFO 1 - -/* Define if frame index should be used. */ -#define FRAME_INDEX 1 - -/* Define if gapless is enabled. */ -#define GAPLESS 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ALC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ALIB_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_AL_ALC_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_AL_AL_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AL_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ASM_AUDIOIO_H */ - -/* Define to 1 if you have the `atoll' function. */ -#define HAVE_ATOLL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AUDIOS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AUDIOTOOLBOX_AUDIOTOOLBOX_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AUDIOUNIT_AUDIOUNIT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CORESERVICES_CORESERVICES_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CULIB_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */ -#define HAVE_GAI_ADDRCONFIG 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getpagesize' function. */ -#define HAVE_GETPAGESIZE 1 - -/* Define to 1 if you have the `getuid' function. */ -#define HAVE_GETUID 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LANGINFO_H 1 - -/* Define to 1 if you have the `m' library (-lm). */ -#define HAVE_LIBM 1 - -/* Define to 1 if you have the `mx' library (-lmx). */ -/* #undef HAVE_LIBMX */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LINUX_SOUNDCARD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define if libltdl is available */ -#define HAVE_LTDL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACHINE_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `mkfifo' function. */ -#define HAVE_MKFIFO 1 - -/* Define to 1 if you have a working `mmap' system call. */ -#define HAVE_MMAP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETDB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETINET_IN_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETINET_TCP_H */ - -/* Define to 1 if you have the `nl_langinfo' function. */ -#define HAVE_NL_LANGINFO 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OPENAL_ALC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OPENAL_AL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OS2ME_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OS2_H */ - -/* Define to 1 if you have the `random' function. */ -#define HAVE_RANDOM 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SCHED_H 1 - -/* Define to 1 if you have the `sched_setscheduler' function. */ -#define HAVE_SCHED_SETSCHEDULER 1 - -/* Define to 1 if you have the `setlocale' function. */ -#define HAVE_SETLOCALE 1 - -/* Define to 1 if you have the `setpriority' function. */ -#define HAVE_SETPRIORITY 1 - -/* Define to 1 if you have the `setuid' function. */ -#define HAVE_SETUID 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SNDIO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SUN_AUDIOIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIOIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_RESOURCE_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SIGNAL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOUNDCARD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define this if you have the POSIX termios library */ -#define HAVE_TERMIOS 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WINDOWS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WS2TCPIP_H */ - -/* Define to indicate that float storage follows IEEE754. */ -#define IEEE_FLOAT 1 - -/* size of the frame index seek table */ -#define INDEX_SIZE 1000 - -/* Define if IPV6 support is enabled. */ -#define IPV6 1 - -/* Define this to the size of native offset type in bits, used for LFS alias - functions. */ -#define LFS_ALIAS_BITS 64 - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#define LT_OBJDIR ".libs/" - -/* The suffix for module files. */ -#define MODULE_FILE_SUFFIX ".la" - -/* Define if network support is enabled. */ -#define NETWORK 1 - -/* Define to disable 16 bit integer output. */ -/* #undef NO_16BIT */ - -/* Define to disable 32 bit and 24 bit integer output. */ -/* #undef NO_32BIT */ - -/* Define to disable 8 bit integer output. */ -/* #undef NO_8BIT */ - -/* Define to disable downsampled decoding. */ -/* #undef NO_DOWNSAMPLE */ - -/* Define to disable equalizer. */ -/* #undef NO_EQUALIZER */ - -/* Define to disable error messages in combination with a return value (the - return is left intact). */ -/* #undef NO_ERETURN */ - -/* Define to disable error messages. */ -/* #undef NO_ERRORMSG */ - -/* Define to disable feeder and buffered readers. */ -/* #undef NO_FEEDER */ - -/* Define to disable ICY handling. */ -/* #undef NO_ICY */ - -/* Define to disable ID3v2 parsing. */ -/* #undef NO_ID3V2 */ - -/* Define to disable layer I. */ -/* #undef NO_LAYER1 */ - -/* Define to disable layer II. */ -/* #undef NO_LAYER2 */ - -/* Define to disable layer III. */ -/* #undef NO_LAYER3 */ - -/* Define to disable ntom resampling. */ -/* #undef NO_NTOM */ - -/* Define to disable real output. */ -/* #undef NO_REAL */ - -/* Define to disable string functions. */ -/* #undef NO_STRING */ - -/* Define for post-processed 32 bit formats. */ -/* #undef NO_SYNTH32 */ - -/* Define to disable warning messages. */ -/* #undef NO_WARNING */ - -/* Name of package */ -#define PACKAGE "mpg123" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "maintainer@mpg123.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "mpg123" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "mpg123 1.24.0" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "mpg123" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.24.0" - -/* Define if portaudio v18 API is wanted. */ -/* #undef PORTAUDIO18 */ - -/* The size of `int32_t', as computed by sizeof. */ -#define SIZEOF_INT32_T 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 8 - -/* The size of `off_t', as computed by sizeof. */ -#define SIZEOF_OFF_T 8 - -/* The size of `size_t', as computed by sizeof. */ -#define SIZEOF_SIZE_T 8 - -/* The size of `ssize_t', as computed by sizeof. */ -#define SIZEOF_SSIZE_T 8 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if modules are enabled */ -#define USE_MODULES 1 - -/* Define for new Huffman decoding scheme. */ -#define USE_NEW_HUFFTABLE 1 - -/* Define to use yasm for assemble AVX sources. */ -/* #undef USE_YASM_FOR_AVX */ - -/* Version number of package */ -#define VERSION "1.24.0" - -/* Define to use Win32 named pipes */ -/* #undef WANT_WIN32_FIFO */ - -/* Define to use Win32 sockets */ -/* #undef WANT_WIN32_SOCKETS */ - -/* Define to use Unicode for Windows */ -/* #undef WANT_WIN32_UNICODE */ - -/* WinXP and above for ipv6 */ -/* #undef WINVER */ - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Enable large inode numbers on Mac OS X 10.5. */ -#ifndef _DARWIN_USE_64_BIT_INODE -# define _DARWIN_USE_64_BIT_INODE 1 -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* WinXP and above for ipv6 */ -/* #undef _WIN32_WINNT */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `short' if does not define. */ -/* #undef int16_t */ - -/* Define to `int' if does not define. */ -/* #undef int32_t */ - -/* Define to `long long' if does not define. */ -/* #undef int64_t */ - -/* Define to the native offset type (long or actually off_t). */ -#define lfs_alias_t off_t - -/* Define to `long int' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned long' if does not define. */ -/* #undef size_t */ - -/* Define to `long' if does not define. */ -/* #undef ssize_t */ - -/* Define to `unsigned short' if does not define. */ -/* #undef uint16_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef uint32_t */ - -/* Define to `unsigned long' if does not define. */ -/* #undef uintptr_t */ diff --git a/src/config/linux/x64/out123.h b/src/config/linux/x64/out123.h deleted file mode 100644 index 8fde88b..0000000 --- a/src/config/linux/x64/out123.h +++ /dev/null @@ -1,583 +0,0 @@ -/* - out123: audio output interface - - copyright 1995-2016 by the mpg123 project, - free software under the terms of the LGPL 2.1 - - see COPYING and AUTHORS files in distribution or http://mpg123.org - initially written as audio.h by Michael Hipp, reworked into out123 API - by Thomas Orgis -*/ - -#ifndef _OUT123_H_ -#define _OUT123_H_ - -/** \file out123.h The header file for the libout123 audio output facility. */ - -/* We only need size_t definition. */ -#include - -/* Common audio encoding specification, including a macro for getting - * size of encodined samples in bytes. Said macro is still hardcoded - * into out123_encsize(). Relying on this one may help an old program - * know sizes of encodings added to fmt123.h later on. - * If you don't care, just use the macro. - */ -#include - -/** A macro to check at compile time which set of API functions to expect. - * This should be incremented at least each time a new symbol is added - * to the header. - */ -#define OUT123_API_VERSION 1 - -#ifndef MPG123_EXPORT -/** Defines needed for MS Visual Studio(tm) DLL builds. - * Every public function must be prefixed with MPG123_EXPORT. When building - * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible - * for clients and includes it in the import library which is created together - * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which - * imports the functions from the DLL. - */ -#ifdef BUILD_MPG123_DLL -/* The dll exports. */ -#define MPG123_EXPORT __declspec(dllexport) -#else -#ifdef LINK_MPG123_DLL -/* The exe imports. */ -#define MPG123_EXPORT __declspec(dllimport) -#else -/* Nothing on normal/UNIX builds */ -#define MPG123_EXPORT -#endif -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** \defgroup out123_api out123 library API - * This is out123, a library focused on continuous playback of audio streams - * via various platform-specific output methods. It glosses over details of - * the native APIs to give an interface close to simply writing data to a - * file. There might be the option to tune details like buffer (period) sizes - * and the number of them on the device side in future, but the focus of the - * library is to ease the use case of just getting that raw audio data out - * there, without interruptions. - * - * The basic idea is to create a handle with out123_new() and open a certain - * output device (using a certain driver module, possibly build-time defaults) - * with out123_open(). Now, you can query the output device for supported - * encodings for given rate and channel count with out123_get_encodings() and - * decide what to use for actually starting playback with out123_start(). - * - * Then, you just need to provide (interleaved pcm) data for playback with - * out123_play(), which will block when the device's buffers are full. You get - * your timing from that (instead of callbacks). If your program does the - * production of the audio data just a little bit faster than the playback, - * causing out123_play() to block ever so briefly, you're fine. - * - * You stop playback with out123_stop(), or just close the device and driver - * via out123_close(), or even just decide to drop it all and do out123_del() - * right away when you're done. - * - * There are other functions for specific needs, but the basic idea should be - * covered by the above. - @{ - */ - -/** Opaque structure for the libout123 handle. */ -struct out123_struct; -/** Typedef shortcut as preferrend name for the handle type. */ -typedef struct out123_struct out123_handle; - -/** Enumeration of codes for the parameters that it is possible to set/get. */ -enum out123_parms -{ - OUT123_FLAGS = 1 /**< integer, various flags, see enum out123_flags */ -, OUT123_PRELOAD /**< float, fraction of buffer to fill before playback */ -, OUT123_GAIN /**< integer, output device gain (module-specific) */ -, OUT123_VERBOSE /**< integer, verbosity to stderr, >= 0 */ -, OUT123_DEVICEBUFFER /**< - * float, length of device buffer in seconds; - * This might be ignored, might have only a loose relation to actual - * buffer sizes and latency, depending on output driver. Try to tune - * this before opening a device if you want to influcence latency or reduce - * dropouts. Value <= 0 uses some default, usually favouring stable playback - * over low latency. Values above 0.5 are probably too much. - */ -, OUT123_PROPFLAGS /**< integer, query driver/device property flags (r/o) */ -, OUT123_NAME /**< string, name of this instance (NULL restores default); - * The value returned by out123_getparam() might be different if the audio - * backend changed it (to be unique among clients, p.ex.). - * TODO: The name provided here is used as prefix in diagnostic messages. */ -}; - -/** Flags to tune out123 behaviour */ -enum out123_flags -{ - OUT123_HEADPHONES = 0x01 /**< output to headphones (if supported) */ -, OUT123_INTERNAL_SPEAKER = 0x02 /**< output to speaker (if supported) */ -, OUT123_LINE_OUT = 0x04 /**< output to line out (if supported) */ -, OUT123_QUIET = 0x08 /**< no printouts to standard error */ -, OUT123_KEEP_PLAYING = 0x10 /**< - * When this is set (default), playback continues in a loop when the device - * does not consume all given data at once. This happens when encountering - * signals (like SIGSTOP, SIGCONT) that cause interruption of the underlying - * functions. - * Note that this flag is meaningless when the optional buffer is employed, - * There, your program will always block until the buffer completely took - * over the data given to it via out123_play(), unless a communcation error - * arises. - */ -}; - -/** Read-only output driver/device property flags (OUT123_PROPFLAGS). */ -enum out123_propflags -{ - OUT123_PROP_LIVE = 0x01 /**< This is a live output, meaning that - * special care might be needed for pauses in playback (p.ex. stream - * of silence instead of interruption), as opposed to files on disk. - */ -, OUT123_PROP_PERSISTENT = 0x02 /**< This (live) output does not need - * special care for pauses (continues with silence itself), - * out123_pause() does nothing to the device. - */ -}; - -/** Create a new output handle. - * This only allocates and initializes memory, so the only possible - * error condition is running out of memory. - * \return pointer to new handle or NULL on error - */ -MPG123_EXPORT -out123_handle *out123_new(void); - -/** Delete output handle. - * This implies out123_close(). - */ -MPG123_EXPORT -void out123_del(out123_handle *ao); - -/** Error code enumeration - * API calls return a useful (positve) value or zero (OUT123_OK) on simple - * success. A negative value (-1 == OUT123_ERR) usually indicates that some - * error occured. Which one, that can be queried using out123_errcode() - * and friends. - */ -enum out123_error -{ - OUT123_ERR = -1 /**< generic alias for verbosity, always == -1 */ -, OUT123_OK = 0 /**< just a name for zero, not going to change */ -, OUT123_DOOM /**< dazzled, out of memory */ -, OUT123_BAD_DRIVER_NAME /**< bad driver name given */ -, OUT123_BAD_DRIVER /**< unspecified issue loading a driver */ -, OUT123_NO_DRIVER /**< no driver loaded */ -, OUT123_NOT_LIVE /**< no active audio device */ -, OUT123_DEV_PLAY /**< some device playback error */ -, OUT123_DEV_OPEN /**< error opening device */ -, OUT123_BUFFER_ERROR /**< - * Some (really unexpected) error in buffer infrastructure. - */ -, OUT123_MODULE_ERROR /**< basic failure in module loading */ -, OUT123_ARG_ERROR /**< some bad function arguments supplied */ -, OUT123_BAD_PARAM /**< unknown parameter code */ -, OUT123_SET_RO_PARAM /**< attempt to set read-only parameter */ -, OUT123_BAD_HANDLE /**< bad handle pointer (NULL, usually) */ -, OUT123_ERRCOUNT /**< placeholder for shaping arrays */ -}; - -/** Get string representation of last encountered error in the - * context of given handle. - * \param ao handle - * \return error string - */ -MPG123_EXPORT -const char* out123_strerror(out123_handle *ao); - -/** Get the plain errcode intead of a string. - * Note that this used to return OUT123_ERR instead of - * OUT123_BAD_HANDLE in case of ao==NULL before mpg123-1.23.5 . - * \param ao handle - * \return error code recorded in handle or OUT123_BAD_HANDLE - */ -MPG123_EXPORT -int out123_errcode(out123_handle *ao); - -/** Return the error string for a given error code. - * \param errcode the integer error code - * \return error string - */ -MPG123_EXPORT -const char* out123_plain_strerror(int errcode); - -/** Set a desired output buffer size. - * This starts a separate process that handles the audio output, decoupling - * the latter from the main process with a memory buffer and saving you the - * burden to ensure sparing CPU cycles for actual playback. - * This is for applicatons that prefer continuous playback over small latency. - * In other words: The kind of applications that out123 is designed for. - * This routine always kills off any currently active audio output module / - * device, even if you just disable the buffer when there is no buffer. - * - * Keep this in mind for memory-constrainted systems: Activating the - * buffer causes a fork of the calling process, doubling the virtual memory - * use. Depending on your operating system kernel's behaviour regarding - * memory overcommit, it might be wise to call out123_set_buffer() very - * early in your program before allocating lots of memory. - * - * There _might_ be a change to threads in future, but for now this is - * classic fork with shared memory, working without any threading library. - * If your platform or build does not support that, you will always get an - * error on trying to set up a non-zero buffer (but the API call will be - * present). - * - * Also, if you do intend to use this from a multithreaded program, think - * twice and make sure that your setup is happy with forking full-blown - * processes off threaded programs. Probably you are better off spawning a - * buffer thread yourself. - * - * \param ao handle - * \param buffer_bytes size (bytes) of a memory buffer for decoded audio, - * a value of zero disables the buffer. - * \return 0 on success, OUT123_ERR on error - */ -MPG123_EXPORT -int out123_set_buffer(out123_handle *ao, size_t buffer_bytes); - -/** Set a specific parameter, for a specific out123_handle, using a parameter - * code chosen from the out123_parms enumeration, to the specified value. - * The parameters usually only change what happens on next out123_open, not - * incfluencing running operation. - * \param ao handle - * \param code parameter code - * \param value input value for integer parameters - * \param fvalue input value for floating point parameters - * \param svalue input value for string parameters (contens are copied) - * \return 0 on success, OUT123_ERR on error. - */ -MPG123_EXPORT -int out123_param( out123_handle *ao, enum out123_parms code -, long value, double fvalue, const char *svalue ); -#define out123_param_int(ao, code, value) \ - out123_param((ao), (code), (value), 0., NULL) -#define out123_param_float(ao, code, value) \ - out123_param((ao), (code), 0, (value), NULL) -#define out123_param_string(ao, code, value) \ - out123_param((ao), (code), 0, 0., (value)) - -/** Get a specific parameter, for a specific out123_handle, using a parameter - * code chosen from the out123_parms enumeration, to the specified value. - * \param ao handle - * \param code parameter code - * \param ret_value output address for integer parameters - * \param ret_fvalue output address for floating point parameters - * \param ret_svalue output address for string parameters (pointer to - * internal memory, so no messing around, please) - * \return 0 on success, OUT123_ERR on error (bad parameter name or bad handle). - */ -MPG123_EXPORT -int out123_getparam( out123_handle *ao, enum out123_parms code -, long *ret_value, double *ret_fvalue, char* *ret_svalue ); -#define out123_getparam_int(ao, code, value) \ - out123_getparam((ao), (code), (value), NULL, NULL) -#define out123_getparam_float(ao, code, value) \ - out123_getparam((ao), (code), NULL, (value), NULL) -#define out123_getparam_string(ao, code, value) \ - out123_getparam((ao), (code), NULL, NULL, (value)) - -/** Copy parameters from another out123_handle. - * \param ao handle - * \param from_ao the handle to copy parameters from - * \return 0 in success, -1 on error - */ -MPG123_EXPORT -int out123_param_from(out123_handle *ao, out123_handle* from_ao); - -/** Get list of driver modules reachable in system in C argv-style format. - * The client is responsible for freeing the memory of both the individual - * strings and the lists themselves. - * A module that is not loadable because of missing libraries is simply - * skipped. You will get stderr messages about that unless OUT123_QUIET was - * was set, though. Failure to open the module directory is a serious error, - * resulting in negative return value. - * \param ao handle - * \param names address for storing list of names - * \param descr address for storing list of descriptions - * \return number of drivers found, -1 on error - */ -MPG123_EXPORT -int out123_drivers(out123_handle *ao, char ***names, char ***descr); - -/** Open an output device with a certain driver - * Note: Opening means that the driver code is loaded and the desired - * device name recorded, possibly tested for availability or tentatively - * opened. After out123_open(), you can ask for supported encodings - * and then really open the device for playback with out123_start(). - * \param ao handle - * \param driver (comma-separated list of) output driver name(s to try), - * NULL for default (stdout for file-based drivers) - * \param device device name to open, NULL for default - * \return 0 on success, -1 on error. - */ -MPG123_EXPORT -int out123_open(out123_handle *ao, const char* driver, const char* device); - -/** Give info about currently loaded driver and device - * Any of the return addresses can be NULL if you are not interested in - * everything. You get pointers to internal storage. They are valid - * as long as the driver/device combination is opened. - * The device may be NULL indicating some unnamed default. - * TODO: Make the driver modules return names for such defaults. - * \param ao handle - * \param driver return address for driver name - * \param device return address for device name - * \return 0 on success, -1 on error (i.e. no driver loaded) - */ -MPG123_EXPORT -int out123_driver_info(out123_handle *ao, char **driver, char **device); - -/** Close the current output device and driver. - * This implies out123_drain() to ensure no data is lost. - * With a buffer, that might cause considerable delay during - * which your main application is blocked waiting. - * Call out123_drop() beforehand if you want to end things - * quickly. - * \param ao handle - */ -MPG123_EXPORT -void out123_close(out123_handle *ao); - -/** Get supported audio encodings for given rate and channel count, - * for the currently openend audio device. - * TODO: Reopening the underlying audio device for each query - * is dumb, at least when dealing with JACK. It takes - * a long time and is just a waste. Reconsider that. - * Make sure that all output modules are fine with it, though! - * Usually, a wider range of rates is supported, but the number - * of sample encodings is limited, as is the number of channels. - * So you can call this with some standard rate and hope that the - * returned encodings work also for others, with the tested channel - * count. - * The return value of -1 on some encountered error conveniently also - * does not match any defined format (only 15 bits used for encodings, - * so this would even work with 16 bit integers). - * This implies out123_stop() to enter query mode. - * \param ao handle - * \param rate sampling rate - * \param channels number of channels - * \return supported encodings combined with bitwise or, to be checked - * against your favourite bitmask, -1 on error - */ -MPG123_EXPORT -int out123_encodings(out123_handle *ao, long rate, int channels); - -/** Return the size (in bytes) of one mono sample of the named encoding. - * \param encoding The encoding value to analyze. - * \return positive size of encoding in bytes, 0 on invalid encoding. */ -MPG123_EXPORT int out123_encsize(int encoding); - -/** Get list of supported formats for currently opened audio device. - * Given a list of sampling rates and minimal/maximal channel count, - * this quickly checks what formats are supported with these - * constraints. The first entry is always reserved for a default - * format for the output device. If there is no such default, - * all values of the format are -1. - * For each requested combination of rate and channels, a format entry is - * created, possible with encoding value 0 to indicate that this combination - * has been tested and rejected. So, when there is no basic error, the - * number of returned format entries should be - * (ratecount*(maxchannels-minchannels+1)+1) - * . But instead of forcing you to guess, this will be allocated by - * successful run. - * For the first entry, the encoding member is supposed to be a definite - * encoding, for the others it is a bitwise combination of all possible - * encodings. - * This function is more efficient than many calls to out123_encodings(). - * \param ao handle - * \param rates pointer to an array of sampling rates, may be NULL for none - * \param ratecount number of provided sampling rates - * \param minchannels minimal channel count - * \param maxchannels maximal channel count - * \param fmtlist return address for array of supported formats - * the encoding field of each entry is a combination of all - * supported encodings at this rate and channel count; - * Memory shall be freed by user. - * \return number of returned format enries, -1 on error - */ -MPG123_EXPORT -int out123_formats( out123_handle *ao, const long *rates, int ratecount - , int minchannels, int maxchannels - , struct mpg123_fmt **fmtlist ); - -/** Get list of encodings known to the library. - * You are responsible for freeing the allocated array. - * \param enclist return address for allocated array of encoding codes - * \return number of encodings, -1 on error - */ -MPG123_EXPORT -int out123_enc_list(int **enclist); - -/** Find encoding code by name. - * \param name short or long name to find encoding code for - * \return encoding if found (enum mpg123_enc_enum), else 0 - */ -MPG123_EXPORT -int out123_enc_byname(const char *name); - -/** Get name of encoding. - * \param encoding code (enum mpg123_enc_enum) - * \return short name for valid encodings, NULL otherwise - */ -MPG123_EXPORT -const char* out123_enc_name(int encoding); - -/** Get long name of encoding. - * \param encoding code (enum mpg123_enc_enum) - * \return long name for valid encodings, NULL otherwise - */ -MPG123_EXPORT -const char* out123_enc_longname(int encoding); - -/** Start playback with a certain output format - * It might be a good idea to have audio data handy to feed after this - * returns with success. - * Rationale for not taking a pointer to struct mpg123_fmt: This would - * always force you to deal with that type and needlessly enlarge the - * shortest possible program. - * \param ao handle - * \param encoding sample encoding (values matching libmpg123 API) - * \param channels number of channels (1 or 2, usually) - * \param rate sampling rate - * \return 0 on success, negative on error (bad format, usually) - */ -MPG123_EXPORT -int out123_start( out123_handle *ao -, long rate, int channels, int encoding ); - -/** Pause playback - * Interrupt playback, holding any data in the optional buffer. - * - * This closes the audio device if it is a live sink, ready to be re-opened - * by out123_continue() or out123_play() with the existing parameters. - * \param ao handle - */ -MPG123_EXPORT -void out123_pause(out123_handle *ao); - -/** Continue playback - * The counterpart to out123_pause(). Announce to the driver that playback - * shall continue. - * - * Playback might not resume immediately if the optional buffer is configured - * to wait for a minimum fill and close to being empty. You can force playback - * of the last scrap with out123_drain(), or just by feeding more data with - * out123_play(), which will trigger out123_continue() for you, too. - * \param ao handle - */ -MPG123_EXPORT -void out123_continue(out123_handle *ao); - -/** Stop playback. - * This waits for pending audio data to drain to the speakers. - * You might want to call out123_drop() before stopping if you want - * to end things right away. - * \param ao handle - */ -MPG123_EXPORT -void out123_stop(out123_handle *ao); - -/** Hand over data for playback and wait in case audio device is busy. - * This survives non-fatal signals like SIGSTOP/SIGCONT and keeps on - * playing until the buffer is done with if the flag - * OUT123_KEEP_PLAYING ist set (default). So, per default, if - * you provided a byte count divisible by the PCM frame size, it is an - * error when less bytes than given are played. - * To be sure if an error occured, check out123_errcode(). - * Also note that it is no accident that the buffer parameter is not marked - * as constant. Some output drivers might need to do things like swap - * byte order. This is done in-place instead of wasting memory on yet - * another copy. - * \param ao handle - * \param buffer pointer to raw audio data to be played - * \param bytes number of bytes to read from the buffer - * \return number of bytes played (might be less than given, even zero) - */ -MPG123_EXPORT -size_t out123_play( out123_handle *ao - , void *buffer, size_t bytes ); - -/** Drop any buffered data, making next provided data play right away. - * This does not imply an actual pause in playback. - * You are expected to play something, unless you called out123_pause(). - * Feel free to call out123_stop() afterwards instead for a quicker - * exit than the implied out123_drain(). - * For live sinks, this may include dropping data from their buffers. - * For others (files), this only concerns data in the optional buffer. - * \param ao handle - */ -MPG123_EXPORT -void out123_drop(out123_handle *ao); - -/** Drain the output, waiting until all data went to the hardware. - * This does imply out123_continue() before and out123_pause() - * after draining. - * This might involve only the optional buffer process, or the - * buffers on the audio driver side, too. - * \param ao handle - */ -MPG123_EXPORT -void out123_drain(out123_handle *ao); - -/** Drain the output, but only partially up to the given number of - * bytes. This gives you the opportunity to do something while - * the optional buffer is writing remaining data instead of having - * one atomic API call for it all. - * - * It is wholly expected that the return value of out123_buffered() - * before and after calling this has a bigger difference than the - * provided limit, as the buffer is writing all the time in the - * background. - * - * This is just a plain out123_drain() if the optional buffer is not - * in use. Also triggers out123_continue(), but only out123_pause() - * if there is no buffered data anymore. - * \param ao handle - * \param bytes limit of buffered bytes to drain - * \return number of bytes drained from buffer - */ -MPG123_EXPORT -void out123_ndrain(out123_handle *ao, size_t bytes); - -/** Get an indication of how many bytes reside in the optional buffer. - * This might get extended to tell the number of bytes queued up in the - * audio backend, too. - * \param ao handle - * \return number of bytes in out123 library buffer - */ -MPG123_EXPORT -size_t out123_buffered(out123_handle *ao); - -/** Extract currently used audio format from handle. - * matching mpg123_getformat(). - * Given return addresses may be NULL to indicate no interest. - * \param ao handle - * \param rate address for sample rate - * \param channels address for channel count - * \param encoding address for encoding - * \param framesize size of a full PCM frame (for convenience) - * \return 0 on success, -1 on error - */ -MPG123_EXPORT -int out123_getformat( out123_handle *ao -, long *rate, int *channels, int *encoding, int *framesize ); - -/* @} */ - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/config/mac/x64/config.h b/src/config/mac/x64/config.h deleted file mode 100644 index 07a6add..0000000 --- a/src/config/mac/x64/config.h +++ /dev/null @@ -1,463 +0,0 @@ -/* src/config.h. Generated from config.h.in by configure. */ -/* src/config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if your architecture wants/needs/can use attribute_align_arg and - alignment checks. It is for 32bit x86... */ -/* #undef ABI_ALIGN_FUN */ - -/* Define to use proper rounding. */ -/* #undef ACCURATE_ROUNDING */ - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define if .balign is present. */ -#define ASMALIGN_BALIGN 1 - -/* Define if .align just takes byte count. */ -/* #undef ASMALIGN_BYTE */ - -/* Define if .align takes 3 for alignment of 2^3=8 bytes instead of 8. */ -/* #undef ASMALIGN_EXP */ - -/* Define if __attribute__((aligned(16))) shall be used */ -#define CCALIGN 1 - -/* Define if debugging is enabled. */ -/* #undef DEBUG */ - -/* The default audio output module(s) to use */ -#define DEFAULT_OUTPUT_MODULE "coreaudio,openal" - -/* Define if building with dynamcally linked libmpg123 */ -#define DYNAMIC_BUILD 1 - -/* Use EFBIG as substitude for EOVERFLOW, mingw.org may lack the latter */ -/* #undef EOVERFLOW */ - -/* Define if FIFO support is enabled. */ -#define FIFO 1 - -/* Define if frame index should be used. */ -#define FRAME_INDEX 1 - -/* Define if gapless is enabled. */ -#define GAPLESS 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ALC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ALIB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AL_ALC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AL_AL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AL_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ASM_AUDIOIO_H */ - -/* Define to 1 if you have the `atoll' function. */ -#define HAVE_ATOLL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AUDIOS_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_AUDIOTOOLBOX_AUDIOTOOLBOX_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_AUDIOUNIT_AUDIOUNIT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_CORESERVICES_CORESERVICES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CULIB_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */ -#define HAVE_GAI_ADDRCONFIG 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getpagesize' function. */ -#define HAVE_GETPAGESIZE 1 - -/* Define to 1 if you have the `getuid' function. */ -#define HAVE_GETUID 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LANGINFO_H 1 - -/* Define to 1 if you have the `m' library (-lm). */ -#define HAVE_LIBM 1 - -/* Define to 1 if you have the `mx' library (-lmx). */ -#define HAVE_LIBMX 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define if libltdl is available */ -#define HAVE_LTDL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACHINE_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `mkfifo' function. */ -#define HAVE_MKFIFO 1 - -/* Define to 1 if you have a working `mmap' system call. */ -#define HAVE_MMAP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETDB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETINET_IN_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETINET_TCP_H */ - -/* Define to 1 if you have the `nl_langinfo' function. */ -#define HAVE_NL_LANGINFO 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_OPENAL_ALC_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_OPENAL_AL_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OS2ME_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OS2_H */ - -/* Define to 1 if you have the `random' function. */ -#define HAVE_RANDOM 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SCHED_H 1 - -/* Define to 1 if you have the `sched_setscheduler' function. */ -/* #undef HAVE_SCHED_SETSCHEDULER */ - -/* Define to 1 if you have the `setlocale' function. */ -#define HAVE_SETLOCALE 1 - -/* Define to 1 if you have the `setpriority' function. */ -#define HAVE_SETPRIORITY 1 - -/* Define to 1 if you have the `setuid' function. */ -#define HAVE_SETUID 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SNDIO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SUN_AUDIOIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIOIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_RESOURCE_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SIGNAL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define this if you have the POSIX termios library */ -#define HAVE_TERMIOS 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WINDOWS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WS2TCPIP_H */ - -/* Define to indicate that float storage follows IEEE754. */ -#define IEEE_FLOAT 1 - -/* size of the frame index seek table */ -#define INDEX_SIZE 1000 - -/* Define if IPV6 support is enabled. */ -#define IPV6 1 - -/* Define this to the size of native offset type in bits, used for LFS alias - functions. */ -#define LFS_ALIAS_BITS 64 - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#define LT_OBJDIR ".libs/" - -/* The suffix for module files. */ -#define MODULE_FILE_SUFFIX ".la" - -/* Define if network support is enabled. */ -#define NETWORK 1 - -/* Define to disable 16 bit integer output. */ -/* #undef NO_16BIT */ - -/* Define to disable 32 bit and 24 bit integer output. */ -/* #undef NO_32BIT */ - -/* Define to disable 8 bit integer output. */ -/* #undef NO_8BIT */ - -/* Define to disable downsampled decoding. */ -/* #undef NO_DOWNSAMPLE */ - -/* Define to disable equalizer. */ -/* #undef NO_EQUALIZER */ - -/* Define to disable error messages in combination with a return value (the - return is left intact). */ -/* #undef NO_ERETURN */ - -/* Define to disable error messages. */ -/* #undef NO_ERRORMSG */ - -/* Define to disable feeder and buffered readers. */ -/* #undef NO_FEEDER */ - -/* Define to disable ICY handling. */ -/* #undef NO_ICY */ - -/* Define to disable ID3v2 parsing. */ -/* #undef NO_ID3V2 */ - -/* Define to disable layer I. */ -/* #undef NO_LAYER1 */ - -/* Define to disable layer II. */ -/* #undef NO_LAYER2 */ - -/* Define to disable layer III. */ -/* #undef NO_LAYER3 */ - -/* Define to disable ntom resampling. */ -/* #undef NO_NTOM */ - -/* Define to disable real output. */ -/* #undef NO_REAL */ - -/* Define to disable string functions. */ -/* #undef NO_STRING */ - -/* Define for post-processed 32 bit formats. */ -/* #undef NO_SYNTH32 */ - -/* Define to disable warning messages. */ -/* #undef NO_WARNING */ - -/* Name of package */ -#define PACKAGE "mpg123" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "maintainer@mpg123.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "mpg123" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "mpg123 1.24.0" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "mpg123" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.24.0" - -/* Define if portaudio v18 API is wanted. */ -/* #undef PORTAUDIO18 */ - -/* The size of `int32_t', as computed by sizeof. */ -#define SIZEOF_INT32_T 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 8 - -/* The size of `off_t', as computed by sizeof. */ -#define SIZEOF_OFF_T 8 - -/* The size of `size_t', as computed by sizeof. */ -#define SIZEOF_SIZE_T 8 - -/* The size of `ssize_t', as computed by sizeof. */ -#define SIZEOF_SSIZE_T 8 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if modules are enabled */ -#define USE_MODULES 1 - -/* Define for new Huffman decoding scheme. */ -#define USE_NEW_HUFFTABLE 1 - -/* Define to use yasm for assemble AVX sources. */ -/* #undef USE_YASM_FOR_AVX */ - -/* Version number of package */ -#define VERSION "1.24.0" - -/* Define to use Win32 named pipes */ -/* #undef WANT_WIN32_FIFO */ - -/* Define to use Win32 sockets */ -/* #undef WANT_WIN32_SOCKETS */ - -/* Define to use Unicode for Windows */ -/* #undef WANT_WIN32_UNICODE */ - -/* WinXP and above for ipv6 */ -/* #undef WINVER */ - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Enable large inode numbers on Mac OS X 10.5. */ -#ifndef _DARWIN_USE_64_BIT_INODE -# define _DARWIN_USE_64_BIT_INODE 1 -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* WinXP and above for ipv6 */ -/* #undef _WIN32_WINNT */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `short' if does not define. */ -/* #undef int16_t */ - -/* Define to `int' if does not define. */ -/* #undef int32_t */ - -/* Define to `long long' if does not define. */ -/* #undef int64_t */ - -/* Define to the native offset type (long or actually off_t). */ -#define lfs_alias_t off_t - -/* Define to `long int' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned long' if does not define. */ -/* #undef size_t */ - -/* Define to `long' if does not define. */ -/* #undef ssize_t */ - -/* Define to `unsigned short' if does not define. */ -/* #undef uint16_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef uint32_t */ - -/* Define to `unsigned long' if does not define. */ -/* #undef uintptr_t */ diff --git a/src/config/mac/x64/out123.h b/src/config/mac/x64/out123.h deleted file mode 100644 index 8fde88b..0000000 --- a/src/config/mac/x64/out123.h +++ /dev/null @@ -1,583 +0,0 @@ -/* - out123: audio output interface - - copyright 1995-2016 by the mpg123 project, - free software under the terms of the LGPL 2.1 - - see COPYING and AUTHORS files in distribution or http://mpg123.org - initially written as audio.h by Michael Hipp, reworked into out123 API - by Thomas Orgis -*/ - -#ifndef _OUT123_H_ -#define _OUT123_H_ - -/** \file out123.h The header file for the libout123 audio output facility. */ - -/* We only need size_t definition. */ -#include - -/* Common audio encoding specification, including a macro for getting - * size of encodined samples in bytes. Said macro is still hardcoded - * into out123_encsize(). Relying on this one may help an old program - * know sizes of encodings added to fmt123.h later on. - * If you don't care, just use the macro. - */ -#include - -/** A macro to check at compile time which set of API functions to expect. - * This should be incremented at least each time a new symbol is added - * to the header. - */ -#define OUT123_API_VERSION 1 - -#ifndef MPG123_EXPORT -/** Defines needed for MS Visual Studio(tm) DLL builds. - * Every public function must be prefixed with MPG123_EXPORT. When building - * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible - * for clients and includes it in the import library which is created together - * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which - * imports the functions from the DLL. - */ -#ifdef BUILD_MPG123_DLL -/* The dll exports. */ -#define MPG123_EXPORT __declspec(dllexport) -#else -#ifdef LINK_MPG123_DLL -/* The exe imports. */ -#define MPG123_EXPORT __declspec(dllimport) -#else -/* Nothing on normal/UNIX builds */ -#define MPG123_EXPORT -#endif -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** \defgroup out123_api out123 library API - * This is out123, a library focused on continuous playback of audio streams - * via various platform-specific output methods. It glosses over details of - * the native APIs to give an interface close to simply writing data to a - * file. There might be the option to tune details like buffer (period) sizes - * and the number of them on the device side in future, but the focus of the - * library is to ease the use case of just getting that raw audio data out - * there, without interruptions. - * - * The basic idea is to create a handle with out123_new() and open a certain - * output device (using a certain driver module, possibly build-time defaults) - * with out123_open(). Now, you can query the output device for supported - * encodings for given rate and channel count with out123_get_encodings() and - * decide what to use for actually starting playback with out123_start(). - * - * Then, you just need to provide (interleaved pcm) data for playback with - * out123_play(), which will block when the device's buffers are full. You get - * your timing from that (instead of callbacks). If your program does the - * production of the audio data just a little bit faster than the playback, - * causing out123_play() to block ever so briefly, you're fine. - * - * You stop playback with out123_stop(), or just close the device and driver - * via out123_close(), or even just decide to drop it all and do out123_del() - * right away when you're done. - * - * There are other functions for specific needs, but the basic idea should be - * covered by the above. - @{ - */ - -/** Opaque structure for the libout123 handle. */ -struct out123_struct; -/** Typedef shortcut as preferrend name for the handle type. */ -typedef struct out123_struct out123_handle; - -/** Enumeration of codes for the parameters that it is possible to set/get. */ -enum out123_parms -{ - OUT123_FLAGS = 1 /**< integer, various flags, see enum out123_flags */ -, OUT123_PRELOAD /**< float, fraction of buffer to fill before playback */ -, OUT123_GAIN /**< integer, output device gain (module-specific) */ -, OUT123_VERBOSE /**< integer, verbosity to stderr, >= 0 */ -, OUT123_DEVICEBUFFER /**< - * float, length of device buffer in seconds; - * This might be ignored, might have only a loose relation to actual - * buffer sizes and latency, depending on output driver. Try to tune - * this before opening a device if you want to influcence latency or reduce - * dropouts. Value <= 0 uses some default, usually favouring stable playback - * over low latency. Values above 0.5 are probably too much. - */ -, OUT123_PROPFLAGS /**< integer, query driver/device property flags (r/o) */ -, OUT123_NAME /**< string, name of this instance (NULL restores default); - * The value returned by out123_getparam() might be different if the audio - * backend changed it (to be unique among clients, p.ex.). - * TODO: The name provided here is used as prefix in diagnostic messages. */ -}; - -/** Flags to tune out123 behaviour */ -enum out123_flags -{ - OUT123_HEADPHONES = 0x01 /**< output to headphones (if supported) */ -, OUT123_INTERNAL_SPEAKER = 0x02 /**< output to speaker (if supported) */ -, OUT123_LINE_OUT = 0x04 /**< output to line out (if supported) */ -, OUT123_QUIET = 0x08 /**< no printouts to standard error */ -, OUT123_KEEP_PLAYING = 0x10 /**< - * When this is set (default), playback continues in a loop when the device - * does not consume all given data at once. This happens when encountering - * signals (like SIGSTOP, SIGCONT) that cause interruption of the underlying - * functions. - * Note that this flag is meaningless when the optional buffer is employed, - * There, your program will always block until the buffer completely took - * over the data given to it via out123_play(), unless a communcation error - * arises. - */ -}; - -/** Read-only output driver/device property flags (OUT123_PROPFLAGS). */ -enum out123_propflags -{ - OUT123_PROP_LIVE = 0x01 /**< This is a live output, meaning that - * special care might be needed for pauses in playback (p.ex. stream - * of silence instead of interruption), as opposed to files on disk. - */ -, OUT123_PROP_PERSISTENT = 0x02 /**< This (live) output does not need - * special care for pauses (continues with silence itself), - * out123_pause() does nothing to the device. - */ -}; - -/** Create a new output handle. - * This only allocates and initializes memory, so the only possible - * error condition is running out of memory. - * \return pointer to new handle or NULL on error - */ -MPG123_EXPORT -out123_handle *out123_new(void); - -/** Delete output handle. - * This implies out123_close(). - */ -MPG123_EXPORT -void out123_del(out123_handle *ao); - -/** Error code enumeration - * API calls return a useful (positve) value or zero (OUT123_OK) on simple - * success. A negative value (-1 == OUT123_ERR) usually indicates that some - * error occured. Which one, that can be queried using out123_errcode() - * and friends. - */ -enum out123_error -{ - OUT123_ERR = -1 /**< generic alias for verbosity, always == -1 */ -, OUT123_OK = 0 /**< just a name for zero, not going to change */ -, OUT123_DOOM /**< dazzled, out of memory */ -, OUT123_BAD_DRIVER_NAME /**< bad driver name given */ -, OUT123_BAD_DRIVER /**< unspecified issue loading a driver */ -, OUT123_NO_DRIVER /**< no driver loaded */ -, OUT123_NOT_LIVE /**< no active audio device */ -, OUT123_DEV_PLAY /**< some device playback error */ -, OUT123_DEV_OPEN /**< error opening device */ -, OUT123_BUFFER_ERROR /**< - * Some (really unexpected) error in buffer infrastructure. - */ -, OUT123_MODULE_ERROR /**< basic failure in module loading */ -, OUT123_ARG_ERROR /**< some bad function arguments supplied */ -, OUT123_BAD_PARAM /**< unknown parameter code */ -, OUT123_SET_RO_PARAM /**< attempt to set read-only parameter */ -, OUT123_BAD_HANDLE /**< bad handle pointer (NULL, usually) */ -, OUT123_ERRCOUNT /**< placeholder for shaping arrays */ -}; - -/** Get string representation of last encountered error in the - * context of given handle. - * \param ao handle - * \return error string - */ -MPG123_EXPORT -const char* out123_strerror(out123_handle *ao); - -/** Get the plain errcode intead of a string. - * Note that this used to return OUT123_ERR instead of - * OUT123_BAD_HANDLE in case of ao==NULL before mpg123-1.23.5 . - * \param ao handle - * \return error code recorded in handle or OUT123_BAD_HANDLE - */ -MPG123_EXPORT -int out123_errcode(out123_handle *ao); - -/** Return the error string for a given error code. - * \param errcode the integer error code - * \return error string - */ -MPG123_EXPORT -const char* out123_plain_strerror(int errcode); - -/** Set a desired output buffer size. - * This starts a separate process that handles the audio output, decoupling - * the latter from the main process with a memory buffer and saving you the - * burden to ensure sparing CPU cycles for actual playback. - * This is for applicatons that prefer continuous playback over small latency. - * In other words: The kind of applications that out123 is designed for. - * This routine always kills off any currently active audio output module / - * device, even if you just disable the buffer when there is no buffer. - * - * Keep this in mind for memory-constrainted systems: Activating the - * buffer causes a fork of the calling process, doubling the virtual memory - * use. Depending on your operating system kernel's behaviour regarding - * memory overcommit, it might be wise to call out123_set_buffer() very - * early in your program before allocating lots of memory. - * - * There _might_ be a change to threads in future, but for now this is - * classic fork with shared memory, working without any threading library. - * If your platform or build does not support that, you will always get an - * error on trying to set up a non-zero buffer (but the API call will be - * present). - * - * Also, if you do intend to use this from a multithreaded program, think - * twice and make sure that your setup is happy with forking full-blown - * processes off threaded programs. Probably you are better off spawning a - * buffer thread yourself. - * - * \param ao handle - * \param buffer_bytes size (bytes) of a memory buffer for decoded audio, - * a value of zero disables the buffer. - * \return 0 on success, OUT123_ERR on error - */ -MPG123_EXPORT -int out123_set_buffer(out123_handle *ao, size_t buffer_bytes); - -/** Set a specific parameter, for a specific out123_handle, using a parameter - * code chosen from the out123_parms enumeration, to the specified value. - * The parameters usually only change what happens on next out123_open, not - * incfluencing running operation. - * \param ao handle - * \param code parameter code - * \param value input value for integer parameters - * \param fvalue input value for floating point parameters - * \param svalue input value for string parameters (contens are copied) - * \return 0 on success, OUT123_ERR on error. - */ -MPG123_EXPORT -int out123_param( out123_handle *ao, enum out123_parms code -, long value, double fvalue, const char *svalue ); -#define out123_param_int(ao, code, value) \ - out123_param((ao), (code), (value), 0., NULL) -#define out123_param_float(ao, code, value) \ - out123_param((ao), (code), 0, (value), NULL) -#define out123_param_string(ao, code, value) \ - out123_param((ao), (code), 0, 0., (value)) - -/** Get a specific parameter, for a specific out123_handle, using a parameter - * code chosen from the out123_parms enumeration, to the specified value. - * \param ao handle - * \param code parameter code - * \param ret_value output address for integer parameters - * \param ret_fvalue output address for floating point parameters - * \param ret_svalue output address for string parameters (pointer to - * internal memory, so no messing around, please) - * \return 0 on success, OUT123_ERR on error (bad parameter name or bad handle). - */ -MPG123_EXPORT -int out123_getparam( out123_handle *ao, enum out123_parms code -, long *ret_value, double *ret_fvalue, char* *ret_svalue ); -#define out123_getparam_int(ao, code, value) \ - out123_getparam((ao), (code), (value), NULL, NULL) -#define out123_getparam_float(ao, code, value) \ - out123_getparam((ao), (code), NULL, (value), NULL) -#define out123_getparam_string(ao, code, value) \ - out123_getparam((ao), (code), NULL, NULL, (value)) - -/** Copy parameters from another out123_handle. - * \param ao handle - * \param from_ao the handle to copy parameters from - * \return 0 in success, -1 on error - */ -MPG123_EXPORT -int out123_param_from(out123_handle *ao, out123_handle* from_ao); - -/** Get list of driver modules reachable in system in C argv-style format. - * The client is responsible for freeing the memory of both the individual - * strings and the lists themselves. - * A module that is not loadable because of missing libraries is simply - * skipped. You will get stderr messages about that unless OUT123_QUIET was - * was set, though. Failure to open the module directory is a serious error, - * resulting in negative return value. - * \param ao handle - * \param names address for storing list of names - * \param descr address for storing list of descriptions - * \return number of drivers found, -1 on error - */ -MPG123_EXPORT -int out123_drivers(out123_handle *ao, char ***names, char ***descr); - -/** Open an output device with a certain driver - * Note: Opening means that the driver code is loaded and the desired - * device name recorded, possibly tested for availability or tentatively - * opened. After out123_open(), you can ask for supported encodings - * and then really open the device for playback with out123_start(). - * \param ao handle - * \param driver (comma-separated list of) output driver name(s to try), - * NULL for default (stdout for file-based drivers) - * \param device device name to open, NULL for default - * \return 0 on success, -1 on error. - */ -MPG123_EXPORT -int out123_open(out123_handle *ao, const char* driver, const char* device); - -/** Give info about currently loaded driver and device - * Any of the return addresses can be NULL if you are not interested in - * everything. You get pointers to internal storage. They are valid - * as long as the driver/device combination is opened. - * The device may be NULL indicating some unnamed default. - * TODO: Make the driver modules return names for such defaults. - * \param ao handle - * \param driver return address for driver name - * \param device return address for device name - * \return 0 on success, -1 on error (i.e. no driver loaded) - */ -MPG123_EXPORT -int out123_driver_info(out123_handle *ao, char **driver, char **device); - -/** Close the current output device and driver. - * This implies out123_drain() to ensure no data is lost. - * With a buffer, that might cause considerable delay during - * which your main application is blocked waiting. - * Call out123_drop() beforehand if you want to end things - * quickly. - * \param ao handle - */ -MPG123_EXPORT -void out123_close(out123_handle *ao); - -/** Get supported audio encodings for given rate and channel count, - * for the currently openend audio device. - * TODO: Reopening the underlying audio device for each query - * is dumb, at least when dealing with JACK. It takes - * a long time and is just a waste. Reconsider that. - * Make sure that all output modules are fine with it, though! - * Usually, a wider range of rates is supported, but the number - * of sample encodings is limited, as is the number of channels. - * So you can call this with some standard rate and hope that the - * returned encodings work also for others, with the tested channel - * count. - * The return value of -1 on some encountered error conveniently also - * does not match any defined format (only 15 bits used for encodings, - * so this would even work with 16 bit integers). - * This implies out123_stop() to enter query mode. - * \param ao handle - * \param rate sampling rate - * \param channels number of channels - * \return supported encodings combined with bitwise or, to be checked - * against your favourite bitmask, -1 on error - */ -MPG123_EXPORT -int out123_encodings(out123_handle *ao, long rate, int channels); - -/** Return the size (in bytes) of one mono sample of the named encoding. - * \param encoding The encoding value to analyze. - * \return positive size of encoding in bytes, 0 on invalid encoding. */ -MPG123_EXPORT int out123_encsize(int encoding); - -/** Get list of supported formats for currently opened audio device. - * Given a list of sampling rates and minimal/maximal channel count, - * this quickly checks what formats are supported with these - * constraints. The first entry is always reserved for a default - * format for the output device. If there is no such default, - * all values of the format are -1. - * For each requested combination of rate and channels, a format entry is - * created, possible with encoding value 0 to indicate that this combination - * has been tested and rejected. So, when there is no basic error, the - * number of returned format entries should be - * (ratecount*(maxchannels-minchannels+1)+1) - * . But instead of forcing you to guess, this will be allocated by - * successful run. - * For the first entry, the encoding member is supposed to be a definite - * encoding, for the others it is a bitwise combination of all possible - * encodings. - * This function is more efficient than many calls to out123_encodings(). - * \param ao handle - * \param rates pointer to an array of sampling rates, may be NULL for none - * \param ratecount number of provided sampling rates - * \param minchannels minimal channel count - * \param maxchannels maximal channel count - * \param fmtlist return address for array of supported formats - * the encoding field of each entry is a combination of all - * supported encodings at this rate and channel count; - * Memory shall be freed by user. - * \return number of returned format enries, -1 on error - */ -MPG123_EXPORT -int out123_formats( out123_handle *ao, const long *rates, int ratecount - , int minchannels, int maxchannels - , struct mpg123_fmt **fmtlist ); - -/** Get list of encodings known to the library. - * You are responsible for freeing the allocated array. - * \param enclist return address for allocated array of encoding codes - * \return number of encodings, -1 on error - */ -MPG123_EXPORT -int out123_enc_list(int **enclist); - -/** Find encoding code by name. - * \param name short or long name to find encoding code for - * \return encoding if found (enum mpg123_enc_enum), else 0 - */ -MPG123_EXPORT -int out123_enc_byname(const char *name); - -/** Get name of encoding. - * \param encoding code (enum mpg123_enc_enum) - * \return short name for valid encodings, NULL otherwise - */ -MPG123_EXPORT -const char* out123_enc_name(int encoding); - -/** Get long name of encoding. - * \param encoding code (enum mpg123_enc_enum) - * \return long name for valid encodings, NULL otherwise - */ -MPG123_EXPORT -const char* out123_enc_longname(int encoding); - -/** Start playback with a certain output format - * It might be a good idea to have audio data handy to feed after this - * returns with success. - * Rationale for not taking a pointer to struct mpg123_fmt: This would - * always force you to deal with that type and needlessly enlarge the - * shortest possible program. - * \param ao handle - * \param encoding sample encoding (values matching libmpg123 API) - * \param channels number of channels (1 or 2, usually) - * \param rate sampling rate - * \return 0 on success, negative on error (bad format, usually) - */ -MPG123_EXPORT -int out123_start( out123_handle *ao -, long rate, int channels, int encoding ); - -/** Pause playback - * Interrupt playback, holding any data in the optional buffer. - * - * This closes the audio device if it is a live sink, ready to be re-opened - * by out123_continue() or out123_play() with the existing parameters. - * \param ao handle - */ -MPG123_EXPORT -void out123_pause(out123_handle *ao); - -/** Continue playback - * The counterpart to out123_pause(). Announce to the driver that playback - * shall continue. - * - * Playback might not resume immediately if the optional buffer is configured - * to wait for a minimum fill and close to being empty. You can force playback - * of the last scrap with out123_drain(), or just by feeding more data with - * out123_play(), which will trigger out123_continue() for you, too. - * \param ao handle - */ -MPG123_EXPORT -void out123_continue(out123_handle *ao); - -/** Stop playback. - * This waits for pending audio data to drain to the speakers. - * You might want to call out123_drop() before stopping if you want - * to end things right away. - * \param ao handle - */ -MPG123_EXPORT -void out123_stop(out123_handle *ao); - -/** Hand over data for playback and wait in case audio device is busy. - * This survives non-fatal signals like SIGSTOP/SIGCONT and keeps on - * playing until the buffer is done with if the flag - * OUT123_KEEP_PLAYING ist set (default). So, per default, if - * you provided a byte count divisible by the PCM frame size, it is an - * error when less bytes than given are played. - * To be sure if an error occured, check out123_errcode(). - * Also note that it is no accident that the buffer parameter is not marked - * as constant. Some output drivers might need to do things like swap - * byte order. This is done in-place instead of wasting memory on yet - * another copy. - * \param ao handle - * \param buffer pointer to raw audio data to be played - * \param bytes number of bytes to read from the buffer - * \return number of bytes played (might be less than given, even zero) - */ -MPG123_EXPORT -size_t out123_play( out123_handle *ao - , void *buffer, size_t bytes ); - -/** Drop any buffered data, making next provided data play right away. - * This does not imply an actual pause in playback. - * You are expected to play something, unless you called out123_pause(). - * Feel free to call out123_stop() afterwards instead for a quicker - * exit than the implied out123_drain(). - * For live sinks, this may include dropping data from their buffers. - * For others (files), this only concerns data in the optional buffer. - * \param ao handle - */ -MPG123_EXPORT -void out123_drop(out123_handle *ao); - -/** Drain the output, waiting until all data went to the hardware. - * This does imply out123_continue() before and out123_pause() - * after draining. - * This might involve only the optional buffer process, or the - * buffers on the audio driver side, too. - * \param ao handle - */ -MPG123_EXPORT -void out123_drain(out123_handle *ao); - -/** Drain the output, but only partially up to the given number of - * bytes. This gives you the opportunity to do something while - * the optional buffer is writing remaining data instead of having - * one atomic API call for it all. - * - * It is wholly expected that the return value of out123_buffered() - * before and after calling this has a bigger difference than the - * provided limit, as the buffer is writing all the time in the - * background. - * - * This is just a plain out123_drain() if the optional buffer is not - * in use. Also triggers out123_continue(), but only out123_pause() - * if there is no buffered data anymore. - * \param ao handle - * \param bytes limit of buffered bytes to drain - * \return number of bytes drained from buffer - */ -MPG123_EXPORT -void out123_ndrain(out123_handle *ao, size_t bytes); - -/** Get an indication of how many bytes reside in the optional buffer. - * This might get extended to tell the number of bytes queued up in the - * audio backend, too. - * \param ao handle - * \return number of bytes in out123 library buffer - */ -MPG123_EXPORT -size_t out123_buffered(out123_handle *ao); - -/** Extract currently used audio format from handle. - * matching mpg123_getformat(). - * Given return addresses may be NULL to indicate no interest. - * \param ao handle - * \param rate address for sample rate - * \param channels address for channel count - * \param encoding address for encoding - * \param framesize size of a full PCM frame (for convenience) - * \return 0 on success, -1 on error - */ -MPG123_EXPORT -int out123_getformat( out123_handle *ao -, long *rate, int *channels, int *encoding, int *framesize ); - -/* @} */ - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/config/win/ia32/config.h b/src/config/win/ia32/config.h deleted file mode 100644 index cf5e305..0000000 --- a/src/config/win/ia32/config.h +++ /dev/null @@ -1,463 +0,0 @@ -/* src/config.h. Generated from config.h.in by configure. */ -/* src/config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if your architecture wants/needs/can use attribute_align_arg and - alignment checks. It is for 32bit x86... */ -/* #undef ABI_ALIGN_FUN */ - -/* Define to use proper rounding. */ -/* #undef ACCURATE_ROUNDING */ - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define if .balign is present. */ -#define ASMALIGN_BALIGN 1 - -/* Define if .align just takes byte count. */ -/* #undef ASMALIGN_BYTE */ - -/* Define if .align takes 3 for alignment of 2^3=8 bytes instead of 8. */ -/* #undef ASMALIGN_EXP */ - -/* Define if __attribute__((aligned(16))) shall be used */ -#define CCALIGN 1 - -/* Define if debugging is enabled. */ -/* #undef DEBUG */ - -/* The default audio output module(s) to use */ -#define DEFAULT_OUTPUT_MODULE "win32,win32_wasapi,oss" - -/* Define if building with dynamcally linked libmpg123 */ -#define DYNAMIC_BUILD 1 - -/* Use EFBIG as substitude for EOVERFLOW, mingw.org may lack the latter */ -/* #undef EOVERFLOW */ - -/* Define if FIFO support is enabled. */ -#define FIFO 1 - -/* Define if frame index should be used. */ -#define FRAME_INDEX 1 - -/* Define if gapless is enabled. */ -#define GAPLESS 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ALC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ALIB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AL_ALC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AL_AL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AL_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ASM_AUDIOIO_H */ - -/* Define to 1 if you have the `atoll' function. */ -#define HAVE_ATOLL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AUDIOS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AUDIOTOOLBOX_AUDIOTOOLBOX_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AUDIOUNIT_AUDIOUNIT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CORESERVICES_CORESERVICES_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CULIB_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */ -#define HAVE_GAI_ADDRCONFIG 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getpagesize' function. */ -#define HAVE_GETPAGESIZE 1 - -/* Define to 1 if you have the `getuid' function. */ -#define HAVE_GETUID 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LANGINFO_H 1 - -/* Define to 1 if you have the `m' library (-lm). */ -#define HAVE_LIBM 1 - -/* Define to 1 if you have the `mx' library (-lmx). */ -/* #undef HAVE_LIBMX */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define if libltdl is available */ -#define HAVE_LTDL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACHINE_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `mkfifo' function. */ -#define HAVE_MKFIFO 1 - -/* Define to 1 if you have a working `mmap' system call. */ -#define HAVE_MMAP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETDB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETINET_IN_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETINET_TCP_H */ - -/* Define to 1 if you have the `nl_langinfo' function. */ -#define HAVE_NL_LANGINFO 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OPENAL_ALC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OPENAL_AL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OS2ME_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OS2_H */ - -/* Define to 1 if you have the `random' function. */ -#define HAVE_RANDOM 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SCHED_H 1 - -/* Define to 1 if you have the `sched_setscheduler' function. */ -#define HAVE_SCHED_SETSCHEDULER 1 - -/* Define to 1 if you have the `setlocale' function. */ -#define HAVE_SETLOCALE 1 - -/* Define to 1 if you have the `setpriority' function. */ -#define HAVE_SETPRIORITY 1 - -/* Define to 1 if you have the `setuid' function. */ -#define HAVE_SETUID 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SNDIO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SUN_AUDIOIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIOIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_RESOURCE_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SIGNAL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOUNDCARD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define this if you have the POSIX termios library */ -#define HAVE_TERMIOS 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WINDOWS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WS2TCPIP_H */ - -/* Define to indicate that float storage follows IEEE754. */ -#define IEEE_FLOAT 1 - -/* size of the frame index seek table */ -#define INDEX_SIZE 1000 - -/* Define if IPV6 support is enabled. */ -#define IPV6 1 - -/* Define this to the size of native offset type in bits, used for LFS alias - functions. */ -#define LFS_ALIAS_BITS 64 - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#define LT_OBJDIR ".libs/" - -/* The suffix for module files. */ -#define MODULE_FILE_SUFFIX ".la" - -/* Define if network support is enabled. */ -#define NETWORK 1 - -/* Define to disable 16 bit integer output. */ -/* #undef NO_16BIT */ - -/* Define to disable 32 bit and 24 bit integer output. */ -/* #undef NO_32BIT */ - -/* Define to disable 8 bit integer output. */ -/* #undef NO_8BIT */ - -/* Define to disable downsampled decoding. */ -/* #undef NO_DOWNSAMPLE */ - -/* Define to disable equalizer. */ -/* #undef NO_EQUALIZER */ - -/* Define to disable error messages in combination with a return value (the - return is left intact). */ -/* #undef NO_ERETURN */ - -/* Define to disable error messages. */ -/* #undef NO_ERRORMSG */ - -/* Define to disable feeder and buffered readers. */ -/* #undef NO_FEEDER */ - -/* Define to disable ICY handling. */ -/* #undef NO_ICY */ - -/* Define to disable ID3v2 parsing. */ -/* #undef NO_ID3V2 */ - -/* Define to disable layer I. */ -/* #undef NO_LAYER1 */ - -/* Define to disable layer II. */ -/* #undef NO_LAYER2 */ - -/* Define to disable layer III. */ -/* #undef NO_LAYER3 */ - -/* Define to disable ntom resampling. */ -/* #undef NO_NTOM */ - -/* Define to disable real output. */ -/* #undef NO_REAL */ - -/* Define to disable string functions. */ -/* #undef NO_STRING */ - -/* Define for post-processed 32 bit formats. */ -/* #undef NO_SYNTH32 */ - -/* Define to disable warning messages. */ -/* #undef NO_WARNING */ - -/* Name of package */ -#define PACKAGE "mpg123" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "maintainer@mpg123.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "mpg123" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "mpg123 1.24.0" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "mpg123" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.24.0" - -/* Define if portaudio v18 API is wanted. */ -/* #undef PORTAUDIO18 */ - -/* The size of `int32_t', as computed by sizeof. */ -#define SIZEOF_INT32_T 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 8 - -/* The size of `off_t', as computed by sizeof. */ -#define SIZEOF_OFF_T 8 - -/* The size of `size_t', as computed by sizeof. */ -#define SIZEOF_SIZE_T 8 - -/* The size of `ssize_t', as computed by sizeof. */ -#define SIZEOF_SSIZE_T 8 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if modules are enabled */ -#define USE_MODULES 1 - -/* Define for new Huffman decoding scheme. */ -#define USE_NEW_HUFFTABLE 1 - -/* Define to use yasm for assemble AVX sources. */ -/* #undef USE_YASM_FOR_AVX */ - -/* Version number of package */ -#define VERSION "1.24.0" - -/* Define to use Win32 named pipes */ -/* #undef WANT_WIN32_FIFO */ - -/* Define to use Win32 sockets */ -/* #undef WANT_WIN32_SOCKETS */ - -/* Define to use Unicode for Windows */ -/* #undef WANT_WIN32_UNICODE */ - -/* WinXP and above for ipv6 */ -/* #undef WINVER */ - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Enable large inode numbers on Mac OS X 10.5. */ -#ifndef _DARWIN_USE_64_BIT_INODE -# define _DARWIN_USE_64_BIT_INODE 1 -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* WinXP and above for ipv6 */ -/* #undef _WIN32_WINNT */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `short' if does not define. */ -/* #undef int16_t */ - -/* Define to `int' if does not define. */ -/* #undef int32_t */ - -/* Define to `long long' if does not define. */ -/* #undef int64_t */ - -/* Define to the native offset type (long or actually off_t). */ -#define lfs_alias_t off_t - -/* Define to `long int' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned long' if does not define. */ -/* #undef size_t */ - -/* Define to `long' if does not define. */ -/* #undef ssize_t */ - -/* Define to `unsigned short' if does not define. */ -/* #undef uint16_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef uint32_t */ - -/* Define to `unsigned long' if does not define. */ -/* #undef uintptr_t */ diff --git a/src/config/win/ia32/out123.h b/src/config/win/ia32/out123.h deleted file mode 100644 index 627df1a..0000000 --- a/src/config/win/ia32/out123.h +++ /dev/null @@ -1,583 +0,0 @@ -/* - out123: audio output interface - - copyright 1995-2016 by the mpg123 project, - free software under the terms of the LGPL 2.1 - - see COPYING and AUTHORS files in distribution or http://mpg123.org - initially written as audio.h by Michael Hipp, reworked into out123 API - by Thomas Orgis -*/ - -#ifndef _OUT123_H_ -#define _OUT123_H_ - -/** \file out123.h The header file for the libout123 audio output facility. */ - -/* We only need size_t definition. */ -#include - -/* Common audio encoding specification, including a macro for getting - * size of encodined samples in bytes. Said macro is still hardcoded - * into out123_encsize(). Relying on this one may help an old program - * know sizes of encodings added to fmt123.h later on. - * If you don't care, just use the macro. - */ -#include - -/** A macro to check at compile time which set of API functions to expect. - * This should be incremented at least each time a new symbol is added - * to the header. - */ -#define OUT123_API_VERSION 1 - -/** Defines needed for MS Visual Studio(tm) DLL builds. - * Every public function must be prefixed with MPG123_EXPORT. When building - * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible - * for clients and includes it in the import library which is created together - * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which - * imports the functions from the DLL. - */ -#ifdef BUILD_MPG123_DLL -/* The dll exports. */ -#define MPG123_EXPORT __declspec(dllexport) -#else -#ifdef LINK_MPG123_DLL -/* The exe imports. */ -#define MPG123_EXPORT __declspec(dllimport) -#else -/* Nothing on normal/UNIX builds */ -#define MPG123_EXPORT -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** \defgroup out123_api out123 library API - * This is out123, a library focused on continuous playback of audio streams - * via various platform-specific output methods. It glosses over details of - * the native APIs to give an interface close to simply writing data to a - * file. There might be the option to tune details like buffer (period) sizes - * and the number of them on the device side in future, but the focus of the - * library is to ease the use case of just getting that raw audio data out - * there, without interruptions. - * - * The basic idea is to create a handle with out123_new() and open a certain - * output device (using a certain driver module, possibly build-time defaults) - * with out123_open(). Now, you can query the output device for supported - * encodings for given rate and channel count with out123_get_encodings() and - * decide what to use for actually starting playback with out123_start(). - * - * Then, you just need to provide (interleaved pcm) data for playback with - * out123_play(), which will block when the device's buffers are full. You get - * your timing from that (instead of callbacks). If your program does the - * production of the audio data just a little bit faster than the playback, - * causing out123_play() to block ever so briefly, you're fine. - * - * You stop playback with out123_stop(), or just close the device and driver - * via out123_close(), or even just decide to drop it all and do out123_del() - * right away when you're done. - * - * There are other functions for specific needs, but the basic idea should be - * covered by the above. - @{ - */ - -/** Opaque structure for the libout123 handle. */ -struct out123_struct; -/** Typedef shortcut as preferrend name for the handle type. */ -typedef struct out123_struct out123_handle; - -/** Enumeration of codes for the parameters that it is possible to set/get. */ -enum out123_parms -{ - OUT123_FLAGS = 1 /**< integer, various flags, see enum out123_flags */ -, OUT123_PRELOAD /**< float, fraction of buffer to fill before playback */ -, OUT123_GAIN /**< integer, output device gain (module-specific) */ -, OUT123_VERBOSE /**< integer, verbosity to stderr, >= 0 */ -, OUT123_DEVICEBUFFER /**< - * float, length of device buffer in seconds; - * This might be ignored, might have only a loose relation to actual - * buffer sizes and latency, depending on output driver. Try to tune - * this before opening a device if you want to influcence latency or reduce - * dropouts. Value <= 0 uses some default, usually favouring stable playback - * over low latency. Values above 0.5 are probably too much. - */ -, OUT123_PROPFLAGS /**< integer, query driver/device property flags (r/o) */ -, OUT123_NAME /**< string, name of this instance (NULL restores default); - * The value returned by out123_getparam() might be different if the audio - * backend changed it (to be unique among clients, p.ex.). - * TODO: The name provided here is used as prefix in diagnostic messages. */ -}; - -/** Flags to tune out123 behaviour */ -enum out123_flags -{ - OUT123_HEADPHONES = 0x01 /**< output to headphones (if supported) */ -, OUT123_INTERNAL_SPEAKER = 0x02 /**< output to speaker (if supported) */ -, OUT123_LINE_OUT = 0x04 /**< output to line out (if supported) */ -, OUT123_QUIET = 0x08 /**< no printouts to standard error */ -, OUT123_KEEP_PLAYING = 0x10 /**< - * When this is set (default), playback continues in a loop when the device - * does not consume all given data at once. This happens when encountering - * signals (like SIGSTOP, SIGCONT) that cause interruption of the underlying - * functions. - * Note that this flag is meaningless when the optional buffer is employed, - * There, your program will always block until the buffer completely took - * over the data given to it via out123_play(), unless a communcation error - * arises. - */ -}; - -/** Read-only output driver/device property flags (OUT123_PROPFLAGS). */ -enum out123_propflags -{ - OUT123_PROP_LIVE = 0x01 /**< This is a live output, meaning that - * special care might be needed for pauses in playback (p.ex. stream - * of silence instead of interruption), as opposed to files on disk. - */ -, OUT123_PROP_PERSISTENT = 0x02 /**< This (live) output does not need - * special care for pauses (continues with silence itself), - * out123_pause() does nothing to the device. - */ -}; - -/** Create a new output handle. - * This only allocates and initializes memory, so the only possible - * error condition is running out of memory. - * \return pointer to new handle or NULL on error - */ -MPG123_EXPORT -out123_handle *out123_new(void); - -/** Delete output handle. - * This implies out123_close(). - */ -MPG123_EXPORT -void out123_del(out123_handle *ao); - -/** Error code enumeration - * API calls return a useful (positve) value or zero (OUT123_OK) on simple - * success. A negative value (-1 == OUT123_ERR) usually indicates that some - * error occured. Which one, that can be queried using out123_errcode() - * and friends. - */ -enum out123_error -{ - OUT123_ERR = -1 /**< generic alias for verbosity, always == -1 */ -, OUT123_OK = 0 /**< just a name for zero, not going to change */ -, OUT123_DOOM /**< dazzled, out of memory */ -, OUT123_BAD_DRIVER_NAME /**< bad driver name given */ -, OUT123_BAD_DRIVER /**< unspecified issue loading a driver */ -, OUT123_NO_DRIVER /**< no driver loaded */ -, OUT123_NOT_LIVE /**< no active audio device */ -, OUT123_DEV_PLAY /**< some device playback error */ -, OUT123_DEV_OPEN /**< error opening device */ -, OUT123_BUFFER_ERROR /**< - * Some (really unexpected) error in buffer infrastructure. - */ -, OUT123_MODULE_ERROR /**< basic failure in module loading */ -, OUT123_ARG_ERROR /**< some bad function arguments supplied */ -, OUT123_BAD_PARAM /**< unknown parameter code */ -, OUT123_SET_RO_PARAM /**< attempt to set read-only parameter */ -, OUT123_BAD_HANDLE /**< bad handle pointer (NULL, usually) */ -, OUT123_ERRCOUNT /**< placeholder for shaping arrays */ -}; - -/** Get string representation of last encountered error in the - * context of given handle. - * \param ao handle - * \return error string - */ -MPG123_EXPORT -const char* out123_strerror(out123_handle *ao); - -/** Get the plain errcode intead of a string. - * Note that this used to return OUT123_ERR instead of - * OUT123_BAD_HANDLE in case of ao==NULL before mpg123-1.23.5 . - * \param ao handle - * \return error code recorded in handle or OUT123_BAD_HANDLE - */ -MPG123_EXPORT -int out123_errcode(out123_handle *ao); - -/** Return the error string for a given error code. - * \param errcode the integer error code - * \return error string - */ -MPG123_EXPORT -const char* out123_plain_strerror(int errcode); - -/** Set a desired output buffer size. - * This starts a separate process that handles the audio output, decoupling - * the latter from the main process with a memory buffer and saving you the - * burden to ensure sparing CPU cycles for actual playback. - * This is for applicatons that prefer continuous playback over small latency. - * In other words: The kind of applications that out123 is designed for. - * This routine always kills off any currently active audio output module / - * device, even if you just disable the buffer when there is no buffer. - * - * Keep this in mind for memory-constrainted systems: Activating the - * buffer causes a fork of the calling process, doubling the virtual memory - * use. Depending on your operating system kernel's behaviour regarding - * memory overcommit, it might be wise to call out123_set_buffer() very - * early in your program before allocating lots of memory. - * - * There _might_ be a change to threads in future, but for now this is - * classic fork with shared memory, working without any threading library. - * If your platform or build does not support that, you will always get an - * error on trying to set up a non-zero buffer (but the API call will be - * present). - * - * Also, if you do intend to use this from a multithreaded program, think - * twice and make sure that your setup is happy with forking full-blown - * processes off threaded programs. Probably you are better off spawning a - * buffer thread yourself. - * - * \param ao handle - * \param buffer_bytes size (bytes) of a memory buffer for decoded audio, - * a value of zero disables the buffer. - * \return 0 on success, OUT123_ERR on error - */ -MPG123_EXPORT -int out123_set_buffer(out123_handle *ao, size_t buffer_bytes); - -/** Set a specific parameter, for a specific out123_handle, using a parameter - * code chosen from the out123_parms enumeration, to the specified value. - * The parameters usually only change what happens on next out123_open, not - * incfluencing running operation. - * \param ao handle - * \param code parameter code - * \param value input value for integer parameters - * \param fvalue input value for floating point parameters - * \param svalue input value for string parameters (contens are copied) - * \return 0 on success, OUT123_ERR on error. - */ -MPG123_EXPORT -int out123_param( out123_handle *ao, enum out123_parms code -, long value, double fvalue, const char *svalue ); -#define out123_param_int(ao, code, value) \ - out123_param((ao), (code), (value), 0., NULL) -#define out123_param_float(ao, code, value) \ - out123_param((ao), (code), 0, (value), NULL) -#define out123_param_string(ao, code, value) \ - out123_param((ao), (code), 0, 0., (value)) - -/** Get a specific parameter, for a specific out123_handle, using a parameter - * code chosen from the out123_parms enumeration, to the specified value. - * \param ao handle - * \param code parameter code - * \param ret_value output address for integer parameters - * \param ret_fvalue output address for floating point parameters - * \param ret_svalue output address for string parameters (pointer to - * internal memory, so no messing around, please) - * \return 0 on success, OUT123_ERR on error (bad parameter name or bad handle). - */ -MPG123_EXPORT -int out123_getparam( out123_handle *ao, enum out123_parms code -, long *ret_value, double *ret_fvalue, char* *ret_svalue ); -#define out123_getparam_int(ao, code, value) \ - out123_getparam((ao), (code), (value), NULL, NULL) -#define out123_getparam_float(ao, code, value) \ - out123_getparam((ao), (code), NULL, (value), NULL) -#define out123_getparam_string(ao, code, value) \ - out123_getparam((ao), (code), NULL, NULL, (value)) - -/** Copy parameters from another out123_handle. - * \param ao handle - * \param from_ao the handle to copy parameters from - * \return 0 in success, -1 on error - */ -MPG123_EXPORT -int out123_param_from(out123_handle *ao, out123_handle* from_ao); - -/** Get list of driver modules reachable in system in C argv-style format. - * The client is responsible for freeing the memory of both the individual - * strings and the lists themselves. - * A module that is not loadable because of missing libraries is simply - * skipped. You will get stderr messages about that unless OUT123_QUIET was - * was set, though. Failure to open the module directory is a serious error, - * resulting in negative return value. - * \param ao handle - * \param names address for storing list of names - * \param descr address for storing list of descriptions - * \return number of drivers found, -1 on error - */ -MPG123_EXPORT -int out123_drivers(out123_handle *ao, char ***names, char ***descr); - -/** Open an output device with a certain driver - * Note: Opening means that the driver code is loaded and the desired - * device name recorded, possibly tested for availability or tentatively - * opened. After out123_open(), you can ask for supported encodings - * and then really open the device for playback with out123_start(). - * \param ao handle - * \param driver (comma-separated list of) output driver name(s to try), - * NULL for default (stdout for file-based drivers) - * \param device device name to open, NULL for default - * \return 0 on success, -1 on error. - */ -MPG123_EXPORT -int out123_open(out123_handle *ao, const char* driver, const char* device); - -/** Give info about currently loaded driver and device - * Any of the return addresses can be NULL if you are not interested in - * everything. You get pointers to internal storage. They are valid - * as long as the driver/device combination is opened. - * The device may be NULL indicating some unnamed default. - * TODO: Make the driver modules return names for such defaults. - * \param ao handle - * \param driver return address for driver name - * \param device return address for device name - * \return 0 on success, -1 on error (i.e. no driver loaded) - */ -MPG123_EXPORT -int out123_driver_info(out123_handle *ao, char **driver, char **device); - -/** Close the current output device and driver. - * This implies out123_drain() to ensure no data is lost. - * With a buffer, that might cause considerable delay during - * which your main application is blocked waiting. - * Call out123_drop() beforehand if you want to end things - * quickly. - * \param ao handle - */ -MPG123_EXPORT -void out123_close(out123_handle *ao); - -/** Get supported audio encodings for given rate and channel count, - * for the currently openend audio device. - * TODO: Reopening the underlying audio device for each query - * is dumb, at least when dealing with JACK. It takes - * a long time and is just a waste. Reconsider that. - * Make sure that all output modules are fine with it, though! - * Usually, a wider range of rates is supported, but the number - * of sample encodings is limited, as is the number of channels. - * So you can call this with some standard rate and hope that the - * returned encodings work also for others, with the tested channel - * count. - * The return value of -1 on some encountered error conveniently also - * does not match any defined format (only 15 bits used for encodings, - * so this would even work with 16 bit integers). - * This implies out123_stop() to enter query mode. - * \param ao handle - * \param rate sampling rate - * \param channels number of channels - * \return supported encodings combined with bitwise or, to be checked - * against your favourite bitmask, -1 on error - */ -MPG123_EXPORT -int out123_encodings(out123_handle *ao, long rate, int channels); - -/** Return the size (in bytes) of one mono sample of the named encoding. - * \param encoding The encoding value to analyze. - * \return positive size of encoding in bytes, 0 on invalid encoding. */ -MPG123_EXPORT int out123_encsize(int encoding); - -/** Get list of supported formats for currently opened audio device. - * Given a list of sampling rates and minimal/maximal channel count, - * this quickly checks what formats are supported with these - * constraints. The first entry is always reserved for a default - * format for the output device. If there is no such default, - * all values of the format are -1. - * For each requested combination of rate and channels, a format entry is - * created, possible with encoding value 0 to indicate that this combination - * has been tested and rejected. So, when there is no basic error, the - * number of returned format entries should be - * (ratecount*(maxchannels-minchannels+1)+1) - * . But instead of forcing you to guess, this will be allocated by - * successful run. - * For the first entry, the encoding member is supposed to be a definite - * encoding, for the others it is a bitwise combination of all possible - * encodings. - * This function is more efficient than many calls to out123_encodings(). - * \param ao handle - * \param rates pointer to an array of sampling rates, may be NULL for none - * \param ratecount number of provided sampling rates - * \param minchannels minimal channel count - * \param maxchannels maximal channel count - * \param fmtlist return address for array of supported formats - * the encoding field of each entry is a combination of all - * supported encodings at this rate and channel count; - * Memory shall be freed by user. - * \return number of returned format enries, -1 on error - */ -MPG123_EXPORT -int out123_formats( out123_handle *ao, const long *rates, int ratecount - , int minchannels, int maxchannels - , struct mpg123_fmt **fmtlist ); - -/** Get list of encodings known to the library. - * You are responsible for freeing the allocated array. - * \param enclist return address for allocated array of encoding codes - * \return number of encodings, -1 on error - */ -MPG123_EXPORT -int out123_enc_list(int **enclist); - -/** Find encoding code by name. - * \param name short or long name to find encoding code for - * \return encoding if found (enum mpg123_enc_enum), else 0 - */ -MPG123_EXPORT -int out123_enc_byname(const char *name); - -/** Get name of encoding. - * \param encoding code (enum mpg123_enc_enum) - * \return short name for valid encodings, NULL otherwise - */ -MPG123_EXPORT -const char* out123_enc_name(int encoding); - -/** Get long name of encoding. - * \param encoding code (enum mpg123_enc_enum) - * \return long name for valid encodings, NULL otherwise - */ -MPG123_EXPORT -const char* out123_enc_longname(int encoding); - -/** Start playback with a certain output format - * It might be a good idea to have audio data handy to feed after this - * returns with success. - * Rationale for not taking a pointer to struct mpg123_fmt: This would - * always force you to deal with that type and needlessly enlarge the - * shortest possible program. - * \param ao handle - * \param encoding sample encoding (values matching libmpg123 API) - * \param channels number of channels (1 or 2, usually) - * \param rate sampling rate - * \return 0 on success, negative on error (bad format, usually) - */ -MPG123_EXPORT -int out123_start( out123_handle *ao -, long rate, int channels, int encoding ); - -/** Pause playback - * Interrupt playback, holding any data in the optional buffer. - * - * This closes the audio device if it is a live sink, ready to be re-opened - * by out123_continue() or out123_play() with the existing parameters. - * \param ao handle - */ -MPG123_EXPORT -void out123_pause(out123_handle *ao); - -/** Continue playback - * The counterpart to out123_pause(). Announce to the driver that playback - * shall continue. - * - * Playback might not resume immediately if the optional buffer is configured - * to wait for a minimum fill and close to being empty. You can force playback - * of the last scrap with out123_drain(), or just by feeding more data with - * out123_play(), which will trigger out123_continue() for you, too. - * \param ao handle - */ -MPG123_EXPORT -void out123_continue(out123_handle *ao); - -/** Stop playback. - * This waits for pending audio data to drain to the speakers. - * You might want to call out123_drop() before stopping if you want - * to end things right away. - * \param ao handle - */ -MPG123_EXPORT -void out123_stop(out123_handle *ao); - -/** Hand over data for playback and wait in case audio device is busy. - * This survives non-fatal signals like SIGSTOP/SIGCONT and keeps on - * playing until the buffer is done with if the flag - * OUT123_KEEP_PLAYING ist set (default). So, per default, if - * you provided a byte count divisible by the PCM frame size, it is an - * error when less bytes than given are played. - * To be sure if an error occured, check out123_errcode(). - * Also note that it is no accident that the buffer parameter is not marked - * as constant. Some output drivers might need to do things like swap - * byte order. This is done in-place instead of wasting memory on yet - * another copy. - * \param ao handle - * \param buffer pointer to raw audio data to be played - * \param bytes number of bytes to read from the buffer - * \return number of bytes played (might be less than given, even zero) - */ -MPG123_EXPORT -size_t out123_play( out123_handle *ao - , void *buffer, size_t bytes ); - -/** Drop any buffered data, making next provided data play right away. - * This does not imply an actual pause in playback. - * You are expected to play something, unless you called out123_pause(). - * Feel free to call out123_stop() afterwards instead for a quicker - * exit than the implied out123_drain(). - * For live sinks, this may include dropping data from their buffers. - * For others (files), this only concerns data in the optional buffer. - * \param ao handle - */ -MPG123_EXPORT -void out123_drop(out123_handle *ao); - -/** Drain the output, waiting until all data went to the hardware. - * This does imply out123_continue() before and out123_pause() - * after draining. - * This might involve only the optional buffer process, or the - * buffers on the audio driver side, too. - * \param ao handle - */ -MPG123_EXPORT -void out123_drain(out123_handle *ao); - -/** Drain the output, but only partially up to the given number of - * bytes. This gives you the opportunity to do something while - * the optional buffer is writing remaining data instead of having - * one atomic API call for it all. - * - * It is wholly expected that the return value of out123_buffered() - * before and after calling this has a bigger difference than the - * provided limit, as the buffer is writing all the time in the - * background. - * - * This is just a plain out123_drain() if the optional buffer is not - * in use. Also triggers out123_continue(), but only out123_pause() - * if there is no buffered data anymore. - * \param ao handle - * \param bytes limit of buffered bytes to drain - * \return number of bytes drained from buffer - */ -MPG123_EXPORT -void out123_ndrain(out123_handle *ao, size_t bytes); - -/** Get an indication of how many bytes reside in the optional buffer. - * This might get extended to tell the number of bytes queued up in the - * audio backend, too. - * \param ao handle - * \return number of bytes in out123 library buffer - */ -MPG123_EXPORT -size_t out123_buffered(out123_handle *ao); - -/** Extract currently used audio format from handle. - * matching mpg123_getformat(). - * Given return addresses may be NULL to indicate no interest. - * \param ao handle - * \param rate address for sample rate - * \param channels address for channel count - * \param encoding address for encoding - * \param framesize size of a full PCM frame (for convenience) - * \return 0 on success, -1 on error - */ -MPG123_EXPORT -int out123_getformat( out123_handle *ao -, long *rate, int *channels, int *encoding, int *framesize ); - -/* @} */ - -#ifdef __cplusplus -} -#endif - -#undef MPG123_EXPORT - -#endif - diff --git a/src/config/win/x64/config.h b/src/config/win/x64/config.h deleted file mode 100644 index df2a369..0000000 --- a/src/config/win/x64/config.h +++ /dev/null @@ -1,463 +0,0 @@ -/* src/config.h. Generated from config.h.in by configure. */ -/* src/config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if your architecture wants/needs/can use attribute_align_arg and - alignment checks. It is for 32bit x86... */ -/* #undef ABI_ALIGN_FUN */ - -/* Define to use proper rounding. */ -/* #undef ACCURATE_ROUNDING */ - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define if .balign is present. */ -#define ASMALIGN_BALIGN 1 - -/* Define if .align just takes byte count. */ -/* #undef ASMALIGN_BYTE */ - -/* Define if .align takes 3 for alignment of 2^3=8 bytes instead of 8. */ -/* #undef ASMALIGN_EXP */ - -/* Define if __attribute__((aligned(16))) shall be used */ -#define CCALIGN 1 - -/* Define if debugging is enabled. */ -/* #undef DEBUG */ - -/* The default audio output module(s) to use */ -#define DEFAULT_OUTPUT_MODULE "win32,win32_wasapi,oss" - -/* Define if building with dynamcally linked libmpg123 */ -#define DYNAMIC_BUILD 1 - -/* Use EFBIG as substitude for EOVERFLOW, mingw.org may lack the latter */ -/* #undef EOVERFLOW */ - -/* Define if FIFO support is enabled. */ -#define FIFO 1 - -/* Define if frame index should be used. */ -#define FRAME_INDEX 1 - -/* Define if gapless is enabled. */ -#define GAPLESS 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ALC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ALIB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AL_ALC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AL_AL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AL_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ASM_AUDIOIO_H */ - -/* Define to 1 if you have the `atoll' function. */ -#define HAVE_ATOLL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AUDIOS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AUDIOTOOLBOX_AUDIOTOOLBOX_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_AUDIOUNIT_AUDIOUNIT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CORESERVICES_CORESERVICES_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CULIB_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */ -#define HAVE_GAI_ADDRCONFIG 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getpagesize' function. */ -#define HAVE_GETPAGESIZE 1 - -/* Define to 1 if you have the `getuid' function. */ -/* #undef HAVE_GETUID */ - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LANGINFO_H 1 - -/* Define to 1 if you have the `m' library (-lm). */ -#define HAVE_LIBM 1 - -/* Define to 1 if you have the `mx' library (-lmx). */ -/* #undef HAVE_LIBMX */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define if libltdl is available */ -/* #undef HAVE_LTDL */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACHINE_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `mkfifo' function. */ -#define HAVE_MKFIFO 1 - -/* Define to 1 if you have a working `mmap' system call. */ -#define HAVE_MMAP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETDB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETINET_IN_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETINET_TCP_H */ - -/* Define to 1 if you have the `nl_langinfo' function. */ -#define HAVE_NL_LANGINFO 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OPENAL_ALC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OPENAL_AL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OS2ME_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_OS2_H */ - -/* Define to 1 if you have the `random' function. */ -#define HAVE_RANDOM 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SCHED_H 1 - -/* Define to 1 if you have the `sched_setscheduler' function. */ -#define HAVE_SCHED_SETSCHEDULER 1 - -/* Define to 1 if you have the `setlocale' function. */ -#define HAVE_SETLOCALE 1 - -/* Define to 1 if you have the `setpriority' function. */ -#define HAVE_SETPRIORITY 1 - -/* Define to 1 if you have the `setuid' function. */ -/* #undef HAVE_SETUID */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SNDIO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRINGS_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SUN_AUDIOIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIOIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_RESOURCE_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SELECT_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SIGNAL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOUNDCARD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TIME_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define this if you have the POSIX termios library */ -#define HAVE_TERMIOS 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WINDOWS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WS2TCPIP_H */ - -/* Define to indicate that float storage follows IEEE754. */ -#define IEEE_FLOAT 1 - -/* size of the frame index seek table */ -#define INDEX_SIZE 1000 - -/* Define if IPV6 support is enabled. */ -#define IPV6 1 - -/* Define this to the size of native offset type in bits, used for LFS alias - functions. */ -#define LFS_ALIAS_BITS 64 - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#define LT_OBJDIR ".libs/" - -/* The suffix for module files. */ -#define MODULE_FILE_SUFFIX ".la" - -/* Define if network support is enabled. */ -#define NETWORK 1 - -/* Define to disable 16 bit integer output. */ -/* #undef NO_16BIT */ - -/* Define to disable 32 bit and 24 bit integer output. */ -/* #undef NO_32BIT */ - -/* Define to disable 8 bit integer output. */ -/* #undef NO_8BIT */ - -/* Define to disable downsampled decoding. */ -/* #undef NO_DOWNSAMPLE */ - -/* Define to disable equalizer. */ -/* #undef NO_EQUALIZER */ - -/* Define to disable error messages in combination with a return value (the - return is left intact). */ -/* #undef NO_ERETURN */ - -/* Define to disable error messages. */ -/* #undef NO_ERRORMSG */ - -/* Define to disable feeder and buffered readers. */ -/* #undef NO_FEEDER */ - -/* Define to disable ICY handling. */ -/* #undef NO_ICY */ - -/* Define to disable ID3v2 parsing. */ -/* #undef NO_ID3V2 */ - -/* Define to disable layer I. */ -/* #undef NO_LAYER1 */ - -/* Define to disable layer II. */ -/* #undef NO_LAYER2 */ - -/* Define to disable layer III. */ -/* #undef NO_LAYER3 */ - -/* Define to disable ntom resampling. */ -/* #undef NO_NTOM */ - -/* Define to disable real output. */ -/* #undef NO_REAL */ - -/* Define to disable string functions. */ -/* #undef NO_STRING */ - -/* Define for post-processed 32 bit formats. */ -/* #undef NO_SYNTH32 */ - -/* Define to disable warning messages. */ -/* #undef NO_WARNING */ - -/* Name of package */ -#define PACKAGE "mpg123" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "maintainer@mpg123.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "mpg123" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "mpg123 1.24.0" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "mpg123" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.24.0" - -/* Define if portaudio v18 API is wanted. */ -/* #undef PORTAUDIO18 */ - -/* The size of `int32_t', as computed by sizeof. */ -#define SIZEOF_INT32_T 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 8 - -/* The size of `off_t', as computed by sizeof. */ -#define SIZEOF_OFF_T 8 - -/* The size of `size_t', as computed by sizeof. */ -#define SIZEOF_SIZE_T 8 - -/* The size of `ssize_t', as computed by sizeof. */ -#define SIZEOF_SSIZE_T 8 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if modules are enabled */ -#define USE_MODULES 1 - -/* Define for new Huffman decoding scheme. */ -#define USE_NEW_HUFFTABLE 1 - -/* Define to use yasm for assemble AVX sources. */ -/* #undef USE_YASM_FOR_AVX */ - -/* Version number of package */ -#define VERSION "1.24.0" - -/* Define to use Win32 named pipes */ -/* #undef WANT_WIN32_FIFO */ - -/* Define to use Win32 sockets */ -/* #undef WANT_WIN32_SOCKETS */ - -/* Define to use Unicode for Windows */ -/* #undef WANT_WIN32_UNICODE */ - -/* WinXP and above for ipv6 */ -/* #undef WINVER */ - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Enable large inode numbers on Mac OS X 10.5. */ -#ifndef _DARWIN_USE_64_BIT_INODE -# define _DARWIN_USE_64_BIT_INODE 1 -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* WinXP and above for ipv6 */ -/* #undef _WIN32_WINNT */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `short' if does not define. */ -/* #undef int16_t */ - -/* Define to `int' if does not define. */ -/* #undef int32_t */ - -/* Define to `long long' if does not define. */ -/* #undef int64_t */ - -/* Define to the native offset type (long or actually off_t). */ -#define lfs_alias_t off_t - -/* Define to `long int' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned long' if does not define. */ -/* #undef size_t */ - -/* Define to `long' if does not define. */ -/* #undef ssize_t */ - -/* Define to `unsigned short' if does not define. */ -/* #undef uint16_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef uint32_t */ - -/* Define to `unsigned long' if does not define. */ -/* #undef uintptr_t */ diff --git a/src/config/win/x64/out123.h b/src/config/win/x64/out123.h deleted file mode 100644 index 627df1a..0000000 --- a/src/config/win/x64/out123.h +++ /dev/null @@ -1,583 +0,0 @@ -/* - out123: audio output interface - - copyright 1995-2016 by the mpg123 project, - free software under the terms of the LGPL 2.1 - - see COPYING and AUTHORS files in distribution or http://mpg123.org - initially written as audio.h by Michael Hipp, reworked into out123 API - by Thomas Orgis -*/ - -#ifndef _OUT123_H_ -#define _OUT123_H_ - -/** \file out123.h The header file for the libout123 audio output facility. */ - -/* We only need size_t definition. */ -#include - -/* Common audio encoding specification, including a macro for getting - * size of encodined samples in bytes. Said macro is still hardcoded - * into out123_encsize(). Relying on this one may help an old program - * know sizes of encodings added to fmt123.h later on. - * If you don't care, just use the macro. - */ -#include - -/** A macro to check at compile time which set of API functions to expect. - * This should be incremented at least each time a new symbol is added - * to the header. - */ -#define OUT123_API_VERSION 1 - -/** Defines needed for MS Visual Studio(tm) DLL builds. - * Every public function must be prefixed with MPG123_EXPORT. When building - * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible - * for clients and includes it in the import library which is created together - * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which - * imports the functions from the DLL. - */ -#ifdef BUILD_MPG123_DLL -/* The dll exports. */ -#define MPG123_EXPORT __declspec(dllexport) -#else -#ifdef LINK_MPG123_DLL -/* The exe imports. */ -#define MPG123_EXPORT __declspec(dllimport) -#else -/* Nothing on normal/UNIX builds */ -#define MPG123_EXPORT -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** \defgroup out123_api out123 library API - * This is out123, a library focused on continuous playback of audio streams - * via various platform-specific output methods. It glosses over details of - * the native APIs to give an interface close to simply writing data to a - * file. There might be the option to tune details like buffer (period) sizes - * and the number of them on the device side in future, but the focus of the - * library is to ease the use case of just getting that raw audio data out - * there, without interruptions. - * - * The basic idea is to create a handle with out123_new() and open a certain - * output device (using a certain driver module, possibly build-time defaults) - * with out123_open(). Now, you can query the output device for supported - * encodings for given rate and channel count with out123_get_encodings() and - * decide what to use for actually starting playback with out123_start(). - * - * Then, you just need to provide (interleaved pcm) data for playback with - * out123_play(), which will block when the device's buffers are full. You get - * your timing from that (instead of callbacks). If your program does the - * production of the audio data just a little bit faster than the playback, - * causing out123_play() to block ever so briefly, you're fine. - * - * You stop playback with out123_stop(), or just close the device and driver - * via out123_close(), or even just decide to drop it all and do out123_del() - * right away when you're done. - * - * There are other functions for specific needs, but the basic idea should be - * covered by the above. - @{ - */ - -/** Opaque structure for the libout123 handle. */ -struct out123_struct; -/** Typedef shortcut as preferrend name for the handle type. */ -typedef struct out123_struct out123_handle; - -/** Enumeration of codes for the parameters that it is possible to set/get. */ -enum out123_parms -{ - OUT123_FLAGS = 1 /**< integer, various flags, see enum out123_flags */ -, OUT123_PRELOAD /**< float, fraction of buffer to fill before playback */ -, OUT123_GAIN /**< integer, output device gain (module-specific) */ -, OUT123_VERBOSE /**< integer, verbosity to stderr, >= 0 */ -, OUT123_DEVICEBUFFER /**< - * float, length of device buffer in seconds; - * This might be ignored, might have only a loose relation to actual - * buffer sizes and latency, depending on output driver. Try to tune - * this before opening a device if you want to influcence latency or reduce - * dropouts. Value <= 0 uses some default, usually favouring stable playback - * over low latency. Values above 0.5 are probably too much. - */ -, OUT123_PROPFLAGS /**< integer, query driver/device property flags (r/o) */ -, OUT123_NAME /**< string, name of this instance (NULL restores default); - * The value returned by out123_getparam() might be different if the audio - * backend changed it (to be unique among clients, p.ex.). - * TODO: The name provided here is used as prefix in diagnostic messages. */ -}; - -/** Flags to tune out123 behaviour */ -enum out123_flags -{ - OUT123_HEADPHONES = 0x01 /**< output to headphones (if supported) */ -, OUT123_INTERNAL_SPEAKER = 0x02 /**< output to speaker (if supported) */ -, OUT123_LINE_OUT = 0x04 /**< output to line out (if supported) */ -, OUT123_QUIET = 0x08 /**< no printouts to standard error */ -, OUT123_KEEP_PLAYING = 0x10 /**< - * When this is set (default), playback continues in a loop when the device - * does not consume all given data at once. This happens when encountering - * signals (like SIGSTOP, SIGCONT) that cause interruption of the underlying - * functions. - * Note that this flag is meaningless when the optional buffer is employed, - * There, your program will always block until the buffer completely took - * over the data given to it via out123_play(), unless a communcation error - * arises. - */ -}; - -/** Read-only output driver/device property flags (OUT123_PROPFLAGS). */ -enum out123_propflags -{ - OUT123_PROP_LIVE = 0x01 /**< This is a live output, meaning that - * special care might be needed for pauses in playback (p.ex. stream - * of silence instead of interruption), as opposed to files on disk. - */ -, OUT123_PROP_PERSISTENT = 0x02 /**< This (live) output does not need - * special care for pauses (continues with silence itself), - * out123_pause() does nothing to the device. - */ -}; - -/** Create a new output handle. - * This only allocates and initializes memory, so the only possible - * error condition is running out of memory. - * \return pointer to new handle or NULL on error - */ -MPG123_EXPORT -out123_handle *out123_new(void); - -/** Delete output handle. - * This implies out123_close(). - */ -MPG123_EXPORT -void out123_del(out123_handle *ao); - -/** Error code enumeration - * API calls return a useful (positve) value or zero (OUT123_OK) on simple - * success. A negative value (-1 == OUT123_ERR) usually indicates that some - * error occured. Which one, that can be queried using out123_errcode() - * and friends. - */ -enum out123_error -{ - OUT123_ERR = -1 /**< generic alias for verbosity, always == -1 */ -, OUT123_OK = 0 /**< just a name for zero, not going to change */ -, OUT123_DOOM /**< dazzled, out of memory */ -, OUT123_BAD_DRIVER_NAME /**< bad driver name given */ -, OUT123_BAD_DRIVER /**< unspecified issue loading a driver */ -, OUT123_NO_DRIVER /**< no driver loaded */ -, OUT123_NOT_LIVE /**< no active audio device */ -, OUT123_DEV_PLAY /**< some device playback error */ -, OUT123_DEV_OPEN /**< error opening device */ -, OUT123_BUFFER_ERROR /**< - * Some (really unexpected) error in buffer infrastructure. - */ -, OUT123_MODULE_ERROR /**< basic failure in module loading */ -, OUT123_ARG_ERROR /**< some bad function arguments supplied */ -, OUT123_BAD_PARAM /**< unknown parameter code */ -, OUT123_SET_RO_PARAM /**< attempt to set read-only parameter */ -, OUT123_BAD_HANDLE /**< bad handle pointer (NULL, usually) */ -, OUT123_ERRCOUNT /**< placeholder for shaping arrays */ -}; - -/** Get string representation of last encountered error in the - * context of given handle. - * \param ao handle - * \return error string - */ -MPG123_EXPORT -const char* out123_strerror(out123_handle *ao); - -/** Get the plain errcode intead of a string. - * Note that this used to return OUT123_ERR instead of - * OUT123_BAD_HANDLE in case of ao==NULL before mpg123-1.23.5 . - * \param ao handle - * \return error code recorded in handle or OUT123_BAD_HANDLE - */ -MPG123_EXPORT -int out123_errcode(out123_handle *ao); - -/** Return the error string for a given error code. - * \param errcode the integer error code - * \return error string - */ -MPG123_EXPORT -const char* out123_plain_strerror(int errcode); - -/** Set a desired output buffer size. - * This starts a separate process that handles the audio output, decoupling - * the latter from the main process with a memory buffer and saving you the - * burden to ensure sparing CPU cycles for actual playback. - * This is for applicatons that prefer continuous playback over small latency. - * In other words: The kind of applications that out123 is designed for. - * This routine always kills off any currently active audio output module / - * device, even if you just disable the buffer when there is no buffer. - * - * Keep this in mind for memory-constrainted systems: Activating the - * buffer causes a fork of the calling process, doubling the virtual memory - * use. Depending on your operating system kernel's behaviour regarding - * memory overcommit, it might be wise to call out123_set_buffer() very - * early in your program before allocating lots of memory. - * - * There _might_ be a change to threads in future, but for now this is - * classic fork with shared memory, working without any threading library. - * If your platform or build does not support that, you will always get an - * error on trying to set up a non-zero buffer (but the API call will be - * present). - * - * Also, if you do intend to use this from a multithreaded program, think - * twice and make sure that your setup is happy with forking full-blown - * processes off threaded programs. Probably you are better off spawning a - * buffer thread yourself. - * - * \param ao handle - * \param buffer_bytes size (bytes) of a memory buffer for decoded audio, - * a value of zero disables the buffer. - * \return 0 on success, OUT123_ERR on error - */ -MPG123_EXPORT -int out123_set_buffer(out123_handle *ao, size_t buffer_bytes); - -/** Set a specific parameter, for a specific out123_handle, using a parameter - * code chosen from the out123_parms enumeration, to the specified value. - * The parameters usually only change what happens on next out123_open, not - * incfluencing running operation. - * \param ao handle - * \param code parameter code - * \param value input value for integer parameters - * \param fvalue input value for floating point parameters - * \param svalue input value for string parameters (contens are copied) - * \return 0 on success, OUT123_ERR on error. - */ -MPG123_EXPORT -int out123_param( out123_handle *ao, enum out123_parms code -, long value, double fvalue, const char *svalue ); -#define out123_param_int(ao, code, value) \ - out123_param((ao), (code), (value), 0., NULL) -#define out123_param_float(ao, code, value) \ - out123_param((ao), (code), 0, (value), NULL) -#define out123_param_string(ao, code, value) \ - out123_param((ao), (code), 0, 0., (value)) - -/** Get a specific parameter, for a specific out123_handle, using a parameter - * code chosen from the out123_parms enumeration, to the specified value. - * \param ao handle - * \param code parameter code - * \param ret_value output address for integer parameters - * \param ret_fvalue output address for floating point parameters - * \param ret_svalue output address for string parameters (pointer to - * internal memory, so no messing around, please) - * \return 0 on success, OUT123_ERR on error (bad parameter name or bad handle). - */ -MPG123_EXPORT -int out123_getparam( out123_handle *ao, enum out123_parms code -, long *ret_value, double *ret_fvalue, char* *ret_svalue ); -#define out123_getparam_int(ao, code, value) \ - out123_getparam((ao), (code), (value), NULL, NULL) -#define out123_getparam_float(ao, code, value) \ - out123_getparam((ao), (code), NULL, (value), NULL) -#define out123_getparam_string(ao, code, value) \ - out123_getparam((ao), (code), NULL, NULL, (value)) - -/** Copy parameters from another out123_handle. - * \param ao handle - * \param from_ao the handle to copy parameters from - * \return 0 in success, -1 on error - */ -MPG123_EXPORT -int out123_param_from(out123_handle *ao, out123_handle* from_ao); - -/** Get list of driver modules reachable in system in C argv-style format. - * The client is responsible for freeing the memory of both the individual - * strings and the lists themselves. - * A module that is not loadable because of missing libraries is simply - * skipped. You will get stderr messages about that unless OUT123_QUIET was - * was set, though. Failure to open the module directory is a serious error, - * resulting in negative return value. - * \param ao handle - * \param names address for storing list of names - * \param descr address for storing list of descriptions - * \return number of drivers found, -1 on error - */ -MPG123_EXPORT -int out123_drivers(out123_handle *ao, char ***names, char ***descr); - -/** Open an output device with a certain driver - * Note: Opening means that the driver code is loaded and the desired - * device name recorded, possibly tested for availability or tentatively - * opened. After out123_open(), you can ask for supported encodings - * and then really open the device for playback with out123_start(). - * \param ao handle - * \param driver (comma-separated list of) output driver name(s to try), - * NULL for default (stdout for file-based drivers) - * \param device device name to open, NULL for default - * \return 0 on success, -1 on error. - */ -MPG123_EXPORT -int out123_open(out123_handle *ao, const char* driver, const char* device); - -/** Give info about currently loaded driver and device - * Any of the return addresses can be NULL if you are not interested in - * everything. You get pointers to internal storage. They are valid - * as long as the driver/device combination is opened. - * The device may be NULL indicating some unnamed default. - * TODO: Make the driver modules return names for such defaults. - * \param ao handle - * \param driver return address for driver name - * \param device return address for device name - * \return 0 on success, -1 on error (i.e. no driver loaded) - */ -MPG123_EXPORT -int out123_driver_info(out123_handle *ao, char **driver, char **device); - -/** Close the current output device and driver. - * This implies out123_drain() to ensure no data is lost. - * With a buffer, that might cause considerable delay during - * which your main application is blocked waiting. - * Call out123_drop() beforehand if you want to end things - * quickly. - * \param ao handle - */ -MPG123_EXPORT -void out123_close(out123_handle *ao); - -/** Get supported audio encodings for given rate and channel count, - * for the currently openend audio device. - * TODO: Reopening the underlying audio device for each query - * is dumb, at least when dealing with JACK. It takes - * a long time and is just a waste. Reconsider that. - * Make sure that all output modules are fine with it, though! - * Usually, a wider range of rates is supported, but the number - * of sample encodings is limited, as is the number of channels. - * So you can call this with some standard rate and hope that the - * returned encodings work also for others, with the tested channel - * count. - * The return value of -1 on some encountered error conveniently also - * does not match any defined format (only 15 bits used for encodings, - * so this would even work with 16 bit integers). - * This implies out123_stop() to enter query mode. - * \param ao handle - * \param rate sampling rate - * \param channels number of channels - * \return supported encodings combined with bitwise or, to be checked - * against your favourite bitmask, -1 on error - */ -MPG123_EXPORT -int out123_encodings(out123_handle *ao, long rate, int channels); - -/** Return the size (in bytes) of one mono sample of the named encoding. - * \param encoding The encoding value to analyze. - * \return positive size of encoding in bytes, 0 on invalid encoding. */ -MPG123_EXPORT int out123_encsize(int encoding); - -/** Get list of supported formats for currently opened audio device. - * Given a list of sampling rates and minimal/maximal channel count, - * this quickly checks what formats are supported with these - * constraints. The first entry is always reserved for a default - * format for the output device. If there is no such default, - * all values of the format are -1. - * For each requested combination of rate and channels, a format entry is - * created, possible with encoding value 0 to indicate that this combination - * has been tested and rejected. So, when there is no basic error, the - * number of returned format entries should be - * (ratecount*(maxchannels-minchannels+1)+1) - * . But instead of forcing you to guess, this will be allocated by - * successful run. - * For the first entry, the encoding member is supposed to be a definite - * encoding, for the others it is a bitwise combination of all possible - * encodings. - * This function is more efficient than many calls to out123_encodings(). - * \param ao handle - * \param rates pointer to an array of sampling rates, may be NULL for none - * \param ratecount number of provided sampling rates - * \param minchannels minimal channel count - * \param maxchannels maximal channel count - * \param fmtlist return address for array of supported formats - * the encoding field of each entry is a combination of all - * supported encodings at this rate and channel count; - * Memory shall be freed by user. - * \return number of returned format enries, -1 on error - */ -MPG123_EXPORT -int out123_formats( out123_handle *ao, const long *rates, int ratecount - , int minchannels, int maxchannels - , struct mpg123_fmt **fmtlist ); - -/** Get list of encodings known to the library. - * You are responsible for freeing the allocated array. - * \param enclist return address for allocated array of encoding codes - * \return number of encodings, -1 on error - */ -MPG123_EXPORT -int out123_enc_list(int **enclist); - -/** Find encoding code by name. - * \param name short or long name to find encoding code for - * \return encoding if found (enum mpg123_enc_enum), else 0 - */ -MPG123_EXPORT -int out123_enc_byname(const char *name); - -/** Get name of encoding. - * \param encoding code (enum mpg123_enc_enum) - * \return short name for valid encodings, NULL otherwise - */ -MPG123_EXPORT -const char* out123_enc_name(int encoding); - -/** Get long name of encoding. - * \param encoding code (enum mpg123_enc_enum) - * \return long name for valid encodings, NULL otherwise - */ -MPG123_EXPORT -const char* out123_enc_longname(int encoding); - -/** Start playback with a certain output format - * It might be a good idea to have audio data handy to feed after this - * returns with success. - * Rationale for not taking a pointer to struct mpg123_fmt: This would - * always force you to deal with that type and needlessly enlarge the - * shortest possible program. - * \param ao handle - * \param encoding sample encoding (values matching libmpg123 API) - * \param channels number of channels (1 or 2, usually) - * \param rate sampling rate - * \return 0 on success, negative on error (bad format, usually) - */ -MPG123_EXPORT -int out123_start( out123_handle *ao -, long rate, int channels, int encoding ); - -/** Pause playback - * Interrupt playback, holding any data in the optional buffer. - * - * This closes the audio device if it is a live sink, ready to be re-opened - * by out123_continue() or out123_play() with the existing parameters. - * \param ao handle - */ -MPG123_EXPORT -void out123_pause(out123_handle *ao); - -/** Continue playback - * The counterpart to out123_pause(). Announce to the driver that playback - * shall continue. - * - * Playback might not resume immediately if the optional buffer is configured - * to wait for a minimum fill and close to being empty. You can force playback - * of the last scrap with out123_drain(), or just by feeding more data with - * out123_play(), which will trigger out123_continue() for you, too. - * \param ao handle - */ -MPG123_EXPORT -void out123_continue(out123_handle *ao); - -/** Stop playback. - * This waits for pending audio data to drain to the speakers. - * You might want to call out123_drop() before stopping if you want - * to end things right away. - * \param ao handle - */ -MPG123_EXPORT -void out123_stop(out123_handle *ao); - -/** Hand over data for playback and wait in case audio device is busy. - * This survives non-fatal signals like SIGSTOP/SIGCONT and keeps on - * playing until the buffer is done with if the flag - * OUT123_KEEP_PLAYING ist set (default). So, per default, if - * you provided a byte count divisible by the PCM frame size, it is an - * error when less bytes than given are played. - * To be sure if an error occured, check out123_errcode(). - * Also note that it is no accident that the buffer parameter is not marked - * as constant. Some output drivers might need to do things like swap - * byte order. This is done in-place instead of wasting memory on yet - * another copy. - * \param ao handle - * \param buffer pointer to raw audio data to be played - * \param bytes number of bytes to read from the buffer - * \return number of bytes played (might be less than given, even zero) - */ -MPG123_EXPORT -size_t out123_play( out123_handle *ao - , void *buffer, size_t bytes ); - -/** Drop any buffered data, making next provided data play right away. - * This does not imply an actual pause in playback. - * You are expected to play something, unless you called out123_pause(). - * Feel free to call out123_stop() afterwards instead for a quicker - * exit than the implied out123_drain(). - * For live sinks, this may include dropping data from their buffers. - * For others (files), this only concerns data in the optional buffer. - * \param ao handle - */ -MPG123_EXPORT -void out123_drop(out123_handle *ao); - -/** Drain the output, waiting until all data went to the hardware. - * This does imply out123_continue() before and out123_pause() - * after draining. - * This might involve only the optional buffer process, or the - * buffers on the audio driver side, too. - * \param ao handle - */ -MPG123_EXPORT -void out123_drain(out123_handle *ao); - -/** Drain the output, but only partially up to the given number of - * bytes. This gives you the opportunity to do something while - * the optional buffer is writing remaining data instead of having - * one atomic API call for it all. - * - * It is wholly expected that the return value of out123_buffered() - * before and after calling this has a bigger difference than the - * provided limit, as the buffer is writing all the time in the - * background. - * - * This is just a plain out123_drain() if the optional buffer is not - * in use. Also triggers out123_continue(), but only out123_pause() - * if there is no buffered data anymore. - * \param ao handle - * \param bytes limit of buffered bytes to drain - * \return number of bytes drained from buffer - */ -MPG123_EXPORT -void out123_ndrain(out123_handle *ao, size_t bytes); - -/** Get an indication of how many bytes reside in the optional buffer. - * This might get extended to tell the number of bytes queued up in the - * audio backend, too. - * \param ao handle - * \return number of bytes in out123 library buffer - */ -MPG123_EXPORT -size_t out123_buffered(out123_handle *ao); - -/** Extract currently used audio format from handle. - * matching mpg123_getformat(). - * Given return addresses may be NULL to indicate no interest. - * \param ao handle - * \param rate address for sample rate - * \param channels address for channel count - * \param encoding address for encoding - * \param framesize size of a full PCM frame (for convenience) - * \return 0 on success, -1 on error - */ -MPG123_EXPORT -int out123_getformat( out123_handle *ao -, long *rate, int *channels, int *encoding, int *framesize ); - -/* @} */ - -#ifdef __cplusplus -} -#endif - -#undef MPG123_EXPORT - -#endif - diff --git a/src/mpg123 b/src/mpg123 deleted file mode 160000 index 5ed76a9..0000000 --- a/src/mpg123 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5ed76a99aebb471e5705b8b1949f59338499402c diff --git a/src/mpg123.gyp b/src/mpg123.gyp deleted file mode 100644 index 835283c..0000000 --- a/src/mpg123.gyp +++ /dev/null @@ -1,195 +0,0 @@ -{ - 'variables': { - 'target_arch%': 'ia32', - 'conditions': [ - ['OS=="mac"', { - 'mpg123_module%': 'coreaudio' - }], - ['OS=="win"', { - 'mpg123_module%': 'win32' - }], - ['OS=="linux"', { - 'mpg123_module%': 'alsa' - }] - ] - }, - 'target_defaults': { - 'configurations': { - 'Debug': { - 'defines': [ - 'DEBUG' - ], - 'msvs_settings': { - 'VCCLCompilerTool': { - 'RuntimeLibrary': 1 - } - } - }, - 'Release': { - 'defines': [ - 'NDEBUG' - ], - 'msvs_settings': { - 'VCCLCompilerTool': { - 'RuntimeLibrary': 0 - } - } - } - }, - 'msvs_settings': { - 'VCLinkerTool': { - 'GenerateDebugInformation': 'true' - } - }, - 'conditions': [ - ['OS=="mac"', { - 'conditions': [ - ['target_arch=="ia32"', { 'xcode_settings': { 'ARCHS': [ 'i386' ] } }], - ['target_arch=="x64"', { 'xcode_settings': { 'ARCHS': [ 'x86_64' ] } }] - ] - }] - ] - }, - 'targets': [ - { - 'target_name': 'out123', - 'type': 'static_library', - 'dependencies': [ 'compat' ], - 'include_dirs': [ - 'mpg123/src/libout123', - 'config/<(OS)/<(target_arch)' - ], - 'defines': [ - 'PIC', - 'NOXFERMEM', - 'HAVE_CONFIG_H' - ], - 'direct_dependent_settings': { - 'include_dirs': [ - 'mpg123/src/libout123', - 'config/<(OS)/<(target_arch)' - ] - }, - 'sources': [ - 'mpg123/src/libout123/legacy_module.c', - 'mpg123/src/libout123/libout123.c', - 'mpg123/src/libout123/sfifo.c', - 'mpg123/src/libout123/stringlists.c', - 'mpg123/src/libout123/wav.c' - ] - }, - { - 'target_name': 'compat', - 'type': 'static_library', - 'defines': [ - 'PIC', - 'NOXFERMEM', - 'HAVE_CONFIG_H' - ], - 'sources': [ - 'mpg123/src/compat/compat.c', - 'mpg123/src/compat/compat_str.c' - ], - 'conditions': [ - ['mpg123_module=="coreaudio"', { - 'direct_dependent_settings': { - 'include_dirs': [ - 'mpg123/src', - 'mpg123/src/compat', - 'mpg123/src/libmpg123', - 'config/<(OS)/<(target_arch)' - ] - }, - 'include_dirs': [ - 'mpg123/src', - 'mpg123/src/compat', - 'mpg123/src/libmpg123', - 'config/<(OS)/<(target_arch)' - ], - }], - ['mpg123_module=="win32"', { - 'direct_dependent_settings': { - 'include_dirs': [ - 'util', - 'mpg123/src', - 'mpg123/src/compat', - 'mpg123/src/libmpg123', - 'config/<(OS)/<(target_arch)' - ] - }, - 'include_dirs': [ - 'util', - 'mpg123/src', - 'mpg123/src/compat', - 'mpg123/src/libmpg123', - 'config/<(OS)/<(target_arch)' - ], - }], - ['mpg123_module=="alsa"', { - 'direct_dependent_settings': { - 'include_dirs': [ - 'mpg123/src', - 'mpg123/src/compat', - 'mpg123/src/libmpg123', - 'config/<(OS)/<(target_arch)' - ] - }, - 'include_dirs': [ - 'mpg123/src', - 'mpg123/src/compat', - 'mpg123/src/libmpg123', - 'config/<(OS)/<(target_arch)' - ], - }] - ], - }, - { - 'target_name': 'module', - 'type': 'static_library', - 'dependencies': ['compat', 'out123' ], - 'include_dirs': [ - 'mpg123/src/libout123/modules', - 'config/<(OS)/<(target_arch)' - ], - 'defines': [ - 'PIC', - 'NOXFERMEM', - 'REAL_IS_FLOAT', - 'HAVE_CONFIG_H', - 'BUILDING_OUTPUT_MODULES=1' - ], - 'direct_dependent_settings': { - 'include_dirs': [ - 'mpg123/src/libout123/modules', - 'config/<(OS)/<(target_arch)' - ] - }, - 'conditions': [ - ['mpg123_module=="coreaudio"', { - 'link_settings': { - 'libraries': [ - '-framework AudioToolbox', - '-framework AudioUnit', - '-framework CoreServices' - ] - } - }], - ['mpg123_module=="win32"', { - 'link_settings': { - 'libraries': [ - '-lwinmm.lib' - ] - } - }], - ['mpg123_module=="alsa"', { - 'link_settings': { - 'libraries': [ - '-lasound' - ] - } - }] - ], - 'sources': [ 'mpg123/src/libout123/modules/<(mpg123_module).c' ] - } - ] -} diff --git a/src/pointer_wrapper.h b/src/pointer_wrapper.h deleted file mode 100644 index 1c33e14..0000000 --- a/src/pointer_wrapper.h +++ /dev/null @@ -1,27 +0,0 @@ -#include - -inline static void wrap_pointer_cb(char *data, void *hint) { - fprintf(stderr, "Wrapped pointer was garbage collected. \n"); -} - -inline static v8::Local WrapPointer(void *ptr, size_t length) { - void *user_data = NULL; - return Nan::NewBuffer((char *)ptr, length, wrap_pointer_cb, user_data).ToLocalChecked(); -} - -inline static v8::Local WrapPointer(void *ptr) { - return WrapPointer((char *)ptr, 0); -} - -inline static char * UnwrapPointer(v8::Local buffer, int64_t offset = 0) { - if(node::Buffer::HasInstance(buffer)) { - return node::Buffer::Data(buffer.As()) + offset; - } else { - return NULL; - } -} - -template -inline static Type UnwrapPointer(v8::Local buffer) { - return reinterpret_cast(UnwrapPointer(buffer)); -} diff --git a/src/util/getopt.c b/src/util/getopt.c deleted file mode 100644 index c3fe2a7..0000000 --- a/src/util/getopt.c +++ /dev/null @@ -1,1228 +0,0 @@ -/* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to drepper@gnu.org - before changing it! - Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* This tells Alpha OSF/1 not to define a getopt prototype in . - Ditto for AIX 3.2 and . */ -#ifndef _NO_PROTO -# define _NO_PROTO -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#if !defined __STDC__ || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -# ifndef const -# define const -# endif -#endif - -#include - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 -# include -# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -# define ELIDE_CODE -# endif -#endif - -#ifndef ELIDE_CODE - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -/* Don't include stdlib.h for non-GNU C libraries because some of them - contain conflicting prototypes for getopt. */ -# include -# include -#endif /* GNU C library. */ - -#ifdef VMS -# include -# if HAVE_STRING_H - 0 -# include -# endif -#endif - -#ifndef _ -/* This is for other GNU distributions with internationalized messages. */ -# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC -# include -# ifndef _ -# define _(msgid) gettext (msgid) -# endif -# else -# define _(msgid) (msgid) -# endif -# if defined _LIBC && defined USE_IN_LIBIO -# include -# endif -#endif - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - On entry to `getopt', zero means this is the first call; initialize. - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* 1003.2 says this must be 1 before any call. */ -int optind = 1; - -/* Formerly, initialization of getopt depended on optind==0, which - causes problems with re-calling getopt as programs generally don't - know that. */ - -int __getopt_initialized; - -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Describe how to deal with options that follow non-option ARGV-elements. - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; - -#ifdef __GNU_LIBRARY__ -/* We want to avoid inclusion of string.h with non-GNU libraries - because there are many ways it can cause trouble. - On some systems, it contains special magic macros that don't work - in GCC. */ -# include -# define my_index strchr -#else - -# if HAVE_STRING_H || WIN32 /* Pete Wilson mod 7/28/02 */ -# include -# else -# include -# endif - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -#ifndef getenv -extern char *getenv (); -#endif - -static char * -my_index (str, chr) - const char *str; - int chr; -{ - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; -} - -/* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. */ -#ifdef __GNUC__ -/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. - That was relevant to code that was here before. */ -# if (!defined __STDC__ || !__STDC__) && !defined strlen -/* gcc with -traditional declares the built-in strlen to return int, - and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -# endif /* not __STDC__ */ -#endif /* __GNUC__ */ - -#endif /* not __GNU_LIBRARY__ */ - -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - -#ifdef _LIBC -/* Stored original parameters. - XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ -extern int __libc_argc; -extern char **__libc_argv; - -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -# ifdef USE_NONOPTION_FLAGS -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; - -static int nonoption_flags_max_len; -static int nonoption_flags_len; -# endif - -# ifdef USE_NONOPTION_FLAGS -# define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -# else -# define SWAP_FLAGS(ch1, ch2) -# endif -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -#if defined __STDC__ && __STDC__ -static void exchange (char **); -#endif - -static void -exchange (argv) - char **argv; -{ - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; - else - { - memset (__mempcpy (new_str, __getopt_nonoption_flags, - nonoption_flags_max_len), - '\0', top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; -} - -/* Initialize the internal data when the first call is made. */ - -#if defined __STDC__ && __STDC__ -static const char *_getopt_initialize (int, char *const *, const char *); -#endif -static const char * -_getopt_initialize (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - first_nonopt = last_nonopt = optind; - - nextchar = NULL; - - posixly_correct = getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - if (posixly_correct == NULL - && argc == __libc_argc && argv == __libc_argv) - { - if (nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; - else - memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', nonoption_flags_max_len - len); - } - } - nonoption_flags_len = nonoption_flags_max_len; - } - else - nonoption_flags_len = 0; -#endif - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; -{ - int print_errors = opterr; - if (optstring[0] == ':') - print_errors = 0; - - if (argc < 1) - return -1; - - optarg = NULL; - - if (optind == 0 || !__getopt_initialized) - { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; - } - - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -#if defined _LIBC && defined USE_NONOPTION_FLAGS -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) -#else -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') -#endif - - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT and LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; - - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (ordering == REQUIRE_ORDER) - return -1; - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else if (long_only - || pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - __asprintf (&buf, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); - - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); -#else - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); -#endif - } - nextchar += strlen (nextchar); - optind++; - optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; -#endif - - if (argv[optind - 1][1] == '-') - { - /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO - __asprintf (&buf, _("\ -%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); -#else - fprintf (stderr, _("\ -%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); -#endif - } - else - { - /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO - __asprintf (&buf, _("\ -%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], - pfound->name); -#else - fprintf (stderr, _("\ -%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); -#endif - } - - nextchar += strlen (nextchar); - - optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - __asprintf (&buf, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); -#else - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); -#endif - } - nextchar += strlen (nextchar); - optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; -#endif - - if (argv[optind][1] == '-') - { - /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO - __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); -#else - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); -#endif - } - else - { - /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO - __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); -#else - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); -#endif - } - nextchar = (char *) ""; - optind++; - optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *nextchar++; - char *temp = my_index (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; -#endif - - if (posixly_correct) - { - /* 1003.2 specifies the format of this message. */ -#if defined _LIBC && defined USE_IN_LIBIO - __asprintf (&buf, _("%s: illegal option -- %c\n"), - argv[0], c); -#else - fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); -#endif - } - else - { -#if defined _LIBC && defined USE_IN_LIBIO - __asprintf (&buf, _("%s: invalid option -- %c\n"), - argv[0], c); -#else - fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); -#endif - } - optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (print_errors) - { - /* 1003.2 specifies the format of this message. */ -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - __asprintf (&buf, _("%s: option requires an argument -- %c\n"), - argv[0], c); - - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); -#else - fprintf (stderr, _("%s: option requires an argument -- %c\n"), - argv[0], c); -#endif - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - __asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); - - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); -#else - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); -#endif - } - nextchar += strlen (nextchar); - optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - __asprintf (&buf, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); - - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); -#else - fprintf (stderr, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); -#endif - } - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - __asprintf (&buf, _("\ -%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); -#else - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); -#endif - } - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (print_errors) - { - /* 1003.2 specifies the format of this message. */ -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - __asprintf (&buf, - _("%s: option requires an argument -- %c\n"), - argv[0], c); - - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); -#else - fprintf (stderr, - _("%s: option requires an argument -- %c\n"), - argv[0], c); -#endif - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } -} - -int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); -} - -#endif /* Not ELIDE_CODE. */ - - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -/* #define TEST */ /* Pete Wilson mod 7/28/02 */ -#ifdef TEST - -#ifndef exit /* Pete Wilson mod 7/28/02 */ - int exit(int); /* Pete Wilson mod 7/28/02 */ -#endif /* Pete Wilson mod 7/28/02 */ - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ \ No newline at end of file diff --git a/src/util/getopt.h b/src/util/getopt.h deleted file mode 100644 index a1d4778..0000000 --- a/src/util/getopt.h +++ /dev/null @@ -1,173 +0,0 @@ -/* getopt.h */ -/* Declarations for getopt. - Copyright (C) 1989-1994, 1996-1999, 2001 Free Software - Foundation, Inc. This file is part of the GNU C Library. - The GNU C Library is free software; you can redistribute - it and/or modify it under the terms of the GNU Lesser - General Public License as published by the Free Software - Foundation; either version 2.1 of the License, or - (at your option) any later version. - The GNU C Library is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - You should have received a copy of the GNU Lesser General - Public License along with the GNU C Library; if not, write - to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA. */ - - - - -#ifndef _GETOPT_H - -#ifndef __need_getopt -# define _GETOPT_H 1 -#endif - -/* If __GNU_LIBRARY__ is not already defined, either we are being used - standalone, or this is the first header included in the source file. - If we are being used with glibc, we need to include , but - that does not exist if we are standalone. So: if __GNU_LIBRARY__ is - not defined, include , which will pull in for us - if it's from glibc. (Why ctype.h? It's guaranteed to exist and it - doesn't flood the namespace with stuff the way some other headers do.) */ -#if !defined __GNU_LIBRARY__ -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - On entry to `getopt', zero means this is the first call; initialize. - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ - -extern int optopt; - -#ifndef __need_getopt -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - -struct option -{ -# if (defined __STDC__ && __STDC__) || defined __cplusplus - const char *name; -# else - char *name; -# endif - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* Names for the values of the `has_arg' field of `struct option'. */ - -# define no_argument 0 -# define required_argument 1 -# define optional_argument 2 -#endif /* need getopt */ - - -/* Get definitions and prototypes for functions to process the - arguments in ARGV (ARGC of them, minus the program name) for - options given in OPTS. - Return the option character from OPTS just read. Return -1 when - there are no more options. For unrecognized options, or options - missing arguments, `optopt' is set to the option letter, and '?' is - returned. - The OPTS string is a list of characters which are recognized option - letters, optionally followed by colons, specifying that that letter - takes an argument, to be placed in `optarg'. - If a letter in OPTS is followed by two colons, its argument is - optional. This behavior is specific to the GNU `getopt'. - The argument `--' causes premature termination of argument - scanning, explicitly telling `getopt' that there are no more - options. - If OPTS begins with `--', then non-option arguments are treated as - arguments to the option '\0'. This behavior is specific to the GNU - `getopt'. */ - -#if (defined __STDC__ && __STDC__) || defined __cplusplus -# ifdef __GNU_LIBRARY__ -/* Many other libraries have conflicting prototypes for getopt, with - differences in the consts, in stdlib.h. To avoid compilation - errors, only prototype getopt for the GNU C library. */ -extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); -# else /* not __GNU_LIBRARY__ */ -extern int getopt (); -# endif /* __GNU_LIBRARY__ */ - -# ifndef __need_getopt -extern int getopt_long (int ___argc, char *const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind); -extern int getopt_long_only (int ___argc, char *const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind); - -/* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int ___argc, char *const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only); -# endif -#else /* not __STDC__ */ -extern int getopt (); -# ifndef __need_getopt -extern int getopt_long (); -extern int getopt_long_only (); - -extern int _getopt_internal (); -# endif -#endif /* __STDC__ */ - -#ifdef __cplusplus -} -#endif - -/* Make sure we later can get all the definitions and declarations. */ -#undef __need_getopt - -#endif /* getopt.h */ \ No newline at end of file diff --git a/src/util/unistd.h b/src/util/unistd.h deleted file mode 100644 index 8995895..0000000 --- a/src/util/unistd.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _UNISTD_H -#define _UNISTD_H 1 - -/* This file intended to serve as a drop-in replacement for - * unistd.h on Windows - * Please add functionality as neeeded - */ - -#include -#include -#include /* getopt at: https://gist.github.com/ashelly/7776712 */ -#include /* for getpid() and the exec..() family */ -#include /* for _getcwd() and _chdir() */ - -#define srandom srand -#define random rand - -/* Values for the second argument to access. - These may be OR'd together. */ -#define R_OK 4 /* Test for read permission. */ -#define W_OK 2 /* Test for write permission. */ -//#define X_OK 1 /* execute permission - unsupported in windows*/ -#define F_OK 0 /* Test for existence. */ - -#define access _access -#define dup2 _dup2 -#define execve _execve -#define ftruncate _chsize -#define unlink _unlink -#define fileno _fileno -#define getcwd _getcwd -#define chdir _chdir -#define isatty _isatty -#define lseek _lseek -/* read, write, and close are NOT being #defined here, because while there are file handle specific versions for Windows, they probably don't work for sockets. You need to look at your app and consider whether to call e.g. closesocket(). */ - -#define ssize_t int - -#define STDIN_FILENO 0 -#define STDOUT_FILENO 1 -#define STDERR_FILENO 2 -/* should be in some equivalent to */ -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; - -#endif /* unistd.h */ \ No newline at end of file From 01cc0096ff05e597a0b85f136cfdab843478c212 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 16:59:47 +1300 Subject: [PATCH 35/96] Remove node-gyp from travis --- .travis.yml | 1 - package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4c66cc1..a1fee18 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,5 @@ install: script: - node -v - npm -v - - node-gyp rebuild matrix: fast_finish: true diff --git a/package.json b/package.json index ce07cb4..6700b6f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audio-speaker", - "version": "2.0.0", + "version": "1.9.9", "description": "Output PCM data to a device or library.", "main": "lib/index.js", "scripts": { From 2d3c9dd5483f49cd7fc45e5fb6f2950c9f870612 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 17:01:44 +1300 Subject: [PATCH 36/96] 2.0.0-1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6700b6f..f2a2222 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audio-speaker", - "version": "1.9.9", + "version": "2.0.0-1", "description": "Output PCM data to a device or library.", "main": "lib/index.js", "scripts": { From ba50a6168f5190144a61c6a79842f5050c6788fd Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 17:09:23 +1300 Subject: [PATCH 37/96] Fix package.json --- package.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f2a2222..1245fae 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "audio-speaker", "version": "2.0.0-1", "description": "Output PCM data to a device or library.", - "main": "lib/index.js", "scripts": { "test": "tape tests/play_once.js", "testtwice": "tape tests/play_twice.js", @@ -11,7 +10,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/audiojs/out.git" + "url": "git+https://github.com/audiojs/audio-speaker.git" }, "keywords": [ "PCM", @@ -24,9 +23,9 @@ "author": "Connor Hartley (https://github.com/connorhartley)", "license": "MIT", "bugs": { - "url": "https://github.com/audiojs/out/issues" + "url": "https://github.com/audiojs/audio-speaker/issues" }, - "homepage": "https://github.com/audiojs/out#readme", + "homepage": "https://github.com/audiojs/audio-speaker#readme", "dependencies": { "audio-buffer": "^2.4.5", "audio-sink": "^1.1.6", @@ -42,6 +41,6 @@ "tape": "^4.6.2" }, "optionalDependencies": { - "audio-mpg123": "^1.0.0" + "audio-mpg123": "^1.0.1" } } From 963fb2731e6dd22a74244379592d2c200506932a Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 17:11:13 +1300 Subject: [PATCH 38/96] 2.0.0-2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1245fae..4f3aef1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audio-speaker", - "version": "2.0.0-1", + "version": "2.0.0-2", "description": "Output PCM data to a device or library.", "scripts": { "test": "tape tests/play_once.js", From 8a92b614392b298f11e2a34d2f39348935df7c78 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 18:26:06 +1300 Subject: [PATCH 39/96] Change defaults and browser related functions and information --- browser-stream.js | 1 + browser-direct.js => browser.js | 0 index.js | 2 +- direct.js => native.js | 4 ++-- package.json | 1 + readme.md | 5 ++++- 6 files changed, 9 insertions(+), 4 deletions(-) rename browser-direct.js => browser.js (100%) rename direct.js => native.js (98%) diff --git a/browser-stream.js b/browser-stream.js index c9aaefb..0cf5b2c 100644 --- a/browser-stream.js +++ b/browser-stream.js @@ -22,3 +22,4 @@ function BrowserStreamSpeaker (opts) { WAAStream.call(this, ctx.destination, opts) } +inherits(BrowserStreamSpeaker, WAAStream) diff --git a/browser-direct.js b/browser.js similarity index 100% rename from browser-direct.js rename to browser.js diff --git a/index.js b/index.js index d92014b..9a0c6d1 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,3 @@ 'use strict' -module.exports = require('./direct') +module.exports = require('is-browser') ? require('./browser') : require('./native') diff --git a/direct.js b/native.js similarity index 98% rename from direct.js rename to native.js index 6015941..9a26075 100644 --- a/direct.js +++ b/native.js @@ -29,8 +29,8 @@ function Speaker (opts) { options = objectAssign({ channels: 1, float: false, - bitDepth: opts.float ? 32 : 64, - signed: (opts.float ? 32 : 64) != 8, + bitDepth: 16, + signed: true, samplesPerFrame: 1024, sampleRate: 44100, endianess: endianess, diff --git a/package.json b/package.json index 4f3aef1..32a1c6d 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "audio-sink": "^1.1.6", "debug": "^2.2.0", "is-audio-buffer": "^1.0.1", + "is-browser": "^2.0.1", "object-assign": "^4.1.0", "pcm-util": "^2.0.3", "pull-stream": "^3.5.0" diff --git a/readme.md b/readme.md index ee3ab81..f687f44 100644 --- a/readme.md +++ b/readme.md @@ -4,9 +4,12 @@ [![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) +Note: Browser implementation is deprecated and will be replaced soon. + ## Install -`npm install audio-speaker`` +Node: `npm install audio-speaker` +Browser: `npm install audio-speaker --no-optional` ## Usage From de88016fd856f114db453cc2e7542ba36a7b43c1 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 5 Nov 2016 18:28:15 +1300 Subject: [PATCH 40/96] 2.0.0-3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 32a1c6d..cde9774 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audio-speaker", - "version": "2.0.0-2", + "version": "2.0.0-3", "description": "Output PCM data to a device or library.", "scripts": { "test": "tape tests/play_once.js", From 675073ab0f8f98dd031d7aa24e68be4c15ca7f56 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sun, 6 Nov 2016 18:58:05 +1300 Subject: [PATCH 41/96] Update audio-mpg123 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cde9774..03060e2 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,6 @@ "tape": "^4.6.2" }, "optionalDependencies": { - "audio-mpg123": "^1.0.1" + "audio-mpg123": "^1.1.3" } } From 5cfc9e4cbea4533937c89aa73d555012a6d8a797 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Tue, 8 Nov 2016 07:28:25 +1300 Subject: [PATCH 42/96] Add latest node version to travis.yml and rename tests --- .travis.yml | 1 + package.json | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index a1fee18..120302d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ sudo: false language: node_js node_js: + - "node" - "6" - "5" - "4" diff --git a/package.json b/package.json index 03060e2..edcd281 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,9 @@ "description": "Output PCM data to a device or library.", "scripts": { "test": "tape tests/play_once.js", - "testtwice": "tape tests/play_twice.js", - "teststream": "tape tests/play_stream.js", - "testpull": "tape tests/play_pull.js" + "test:twice": "tape tests/play_twice.js", + "test:stream": "tape tests/play_stream.js", + "test:pull": "tape tests/play_pull.js" }, "repository": { "type": "git", From 74b887d0629c42117ce305000ae5917eda407b6d Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Tue, 8 Nov 2016 10:16:44 +1300 Subject: [PATCH 43/96] Bump audio-mpg123 version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index edcd281..5bfc023 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,6 @@ "tape": "^4.6.2" }, "optionalDependencies": { - "audio-mpg123": "^1.1.3" + "audio-mpg123": "^1.1.4" } } From a2573828252a91f98b6ddfec28abf84cbb1fdaad Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Tue, 8 Nov 2016 10:18:21 +1300 Subject: [PATCH 44/96] 2.0.0-4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5bfc023..6cbe73a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audio-speaker", - "version": "2.0.0-3", + "version": "2.0.0-4", "description": "Output PCM data to a device or library.", "scripts": { "test": "tape tests/play_once.js", From 37a744981dee56397a8a1b36cb89aaaef2848851 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Tue, 8 Nov 2016 10:47:59 +1300 Subject: [PATCH 45/96] Add test to travis.yml --- .travis.yml | 1 + package.json | 5 +++-- tests/check.js | 10 ++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/check.js diff --git a/.travis.yml b/.travis.yml index 120302d..004df7f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ install: - npm install -g npm - npm install -g node-gyp - npm install + - npm run test script: - node -v - npm -v diff --git a/package.json b/package.json index 6cbe73a..fcfd49b 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,9 @@ "version": "2.0.0-4", "description": "Output PCM data to a device or library.", "scripts": { - "test": "tape tests/play_once.js", - "test:twice": "tape tests/play_twice.js", + "test": "tape tests/check.js", + "test:play": "tape tests/play_once.js", + "test:play_twice": "tape tests/play_twice.js", "test:stream": "tape tests/play_stream.js", "test:pull": "tape tests/play_pull.js" }, diff --git a/tests/check.js b/tests/check.js new file mode 100644 index 0000000..f1bab9b --- /dev/null +++ b/tests/check.js @@ -0,0 +1,10 @@ +var test = require('tape') + +test('check for build output', function(t) { + try { + require('../native')() != null ? t.pass('Found audio_mpg123.') : null + } catch (err) { + t.error(err, 'Could not find audio_mpg123.') + } + t.end() +}) From b76ffa21c067f60d9abc0078cc39b23e24cd4ac5 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 7 Nov 2016 23:43:21 -0500 Subject: [PATCH 46/96] Simplify stream.js --- package.json | 3 ++- stream.js | 27 ++++++++++++--------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index fcfd49b..ee5176f 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,8 @@ "is-browser": "^2.0.1", "object-assign": "^4.1.0", "pcm-util": "^2.0.3", - "pull-stream": "^3.5.0" + "pull-stream": "^3.5.0", + "web-audio-stream": "^2.2.0" }, "devDependencies": { "audio-lena": "^1.1.0", diff --git a/stream.js b/stream.js index 8f8abb2..b6ddc0d 100644 --- a/stream.js +++ b/stream.js @@ -2,11 +2,13 @@ var inherits = require('util').inherits var objectAssign = require('object-assign') -var audioThrough = require('audio-through') +var Through = require('audio-through') var Speaker = require('./index') module.exports = StreamSpeaker +inherits(StreamSpeaker, Through) + /** * The StreamSpeaker function initializes a speaker * and inherits {Module} AudioThrough for pipable data @@ -20,19 +22,14 @@ module.exports = StreamSpeaker function StreamSpeaker (opts) { if (!(this instanceof StreamSpeaker)) return new StreamSpeaker(opts) - var options = {} - objectAssign(options, opts) - - audioThrough.call(this, options) - - this.speaker = Speaker(options) + opts = opts || {}; + Through.call(this, opts) - StreamSpeaker.prototype._write = function (chunk, encoding, callback) { - this.speaker(chunk, (err, written) => { - return err ? callback(err) : callback() - }) - } - - StreamSpeaker.prototype.end = this.speaker.end + this.speaker = Speaker(opts) + this.on('end', () => this.speaker.end()) +} +StreamSpeaker.prototype.process = function (chunk, callback) { + this.speaker(chunk, (err, written) => { + return err ? callback(err) : callback() + }); } -inherits(StreamSpeaker, audioThrough) From b4885887d3c1aa1b6a291133267c575ef3f6dd64 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 7 Nov 2016 23:46:10 -0500 Subject: [PATCH 47/96] Simplify browser includes --- index.js | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++- native.js | 227 -------------------------------------------------- package.json | 5 ++ 3 files changed, 232 insertions(+), 228 deletions(-) delete mode 100644 native.js diff --git a/index.js b/index.js index 9a0c6d1..7b77caf 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,229 @@ +/** @module audio-speaker/index */ + 'use strict' -module.exports = require('is-browser') ? require('./browser') : require('./native') +var os = require('os') +var objectAssign = require('object-assign') +var binding = require('audio-mpg123') +var pcm = require('pcm-util') +var isAudioBuffer = require('is-audio-buffer') +var audioBuffer = require('audio-buffer') +var audioSink = require('audio-sink/direct') +var debug = require('debug')('speaker') + +var endianess = 'function' == os.endianess ? os.endianess() : 'LE' + +module.exports = Speaker + +/** + * The Speaker function initializes a new audio handler, + * then returns the write method to output audio to. + * + * @param {Object} opts options for the speaker + * @return {Function} write write audio from a buffer or audiobuffer + * @module Speaker + * @api public + */ +function Speaker (opts) { + debug('Speaker()') + var options = {} + + options = objectAssign({ + channels: 1, + float: false, + bitDepth: 16, + signed: true, + samplesPerFrame: 1024, + sampleRate: 44100, + endianess: endianess, + autoFlush: false + }, opts) + + if (options.handler) { + throw new Error('_create() was called more than once. Only one handler should exist.') + } + + options._closed = false + options._busy = false + + var format = Speaker.getFormat(options) + if (format === null) { + throw new Error('Invalid format options.') + } + + options.blockAlign = options.bitDepth / 8 * options.channels + + options.chunkSize = options.blockAlign * options.samplesPerFrame + + options.handler = binding.create((success) => { + if(!success) { + throw new Error('Failed to create the audio handler.') + } else { + debug('_create() audio handle successfully.') + } + }) + + if (options.handler !== null) { + debug('_start(%o)', Object.keys(options)) + binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { + if (!success) { + throw new Error('Could not start the audio output with these properties.') + } else { + debug('Created and started handler successfully.') + } + }) + } + + write.end = end + write.sink = sink + sink.end = end + return write + + /** + * The write function takes a buffer or audiobuffer and + * writes it to the speaker output. If the chunks are too + * large it will break it up and put the remainding chunks + * into a queue. + * NOTE: You can only write new chunks once the callback is + * called with no errors. + * + * @param {AudioBuffer} chunk (or Buffer) containing the data to be output + * @param {Function} callback callback with error and chunk parameters + * @return void + * @api public + */ + function write (chunk, callback) { + debug('write()') + if (options._closed) return debug('write() cannot be called after the speaker is closed.') + if (chunk && options._busy) return debug('write() cannot be called until the previous buffer has been written.') + + next(chunk, null, callback) + + function next (chunk, remainder, callback) { + if (options.handler) { + options._busy = true + + var chunkBuf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk || new Buffer(0) + var remainderBuf = isAudioBuffer(remainder) ? pcm.toBuffer(remainder, options) : remainder || new Buffer(0) + + var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) + + debug("%o bytes total queued for output.", queue.length) + + var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue + var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) + + debug("%o bytes writing to the speaker.", output.length) + debug("%o bytes remaining in the queue.", remaining.length) + + binding.write(options.handler, output, output.length, onWrite) + + function onWrite (written) { + debug('Wrote %o bytes this chunk.', written) + if(!remaining.length < 1) { + debug('Writing remaining chunks.') + next(null, remaining, callback) + } else { + debug('Finished writing chunk.') + if (options.autoFlush && remaining.length < 1) { + debug('Flushing the audio output.') + binding.flush(options.handler, function (success) { + if (success != 1) { + debug('Could not flush the audio output.') + options._busy = false + callback(new Error('Could not flush the audio output.'), written) + } else { + debug('Flushed audio successfully.') + options._busy = false + callback(null, written) + } + }) + } else { + options._busy = false + callback(null, written) + } + } + } + } + } + } + + function sink (callback) { + debug('sink()') + + return audioSink((data, callback) => { + if (options._closed) return callback(true) + setTimeout(callback, samplesPerFrame / sampleRate) + }) + } + + /** + * The end function closes the speaker and stops + * it from writing anymore data. The output data + * that was already written can be optionally flushed. + * NOTE: You cannot write anymore data after closing the speaker. + * + * @param {Boolean} flush flushes the written data (default is false) + * @param {Function} callback callback with error parameter + * @return void + * @api public + */ + function end (flush, callback) { + debug('end(%o)', flush) + if (options._closed) return debug('_end() was called more than once. Already ended.') + + if (options.handler) { + if (flush) { + debug('Flushing the audio output.') + binding.flush(options.handler, function (success) { + if (success != 1) { + debug('Could not flush the audio output.') + } else { + return close(callback) + } + }) + } else { + return close(callback) + } + } else { + debug('Could not flush the audio output because handler does not exist.') + } + + function close (callback) { + debug('close()') + binding.close(options.handler, (success) => { + if (callback) { + success ? callback() : callback(new Error('Failed to close speaker.')) + } + }) + options._closed = true + options.handler = null + } + } +} + +Speaker.getFormat = function getFormat (format) { + var f = null; + if (format.bitDepth == 32 && format.float && format.signed) { + f = binding.MPG123_ENC_FLOAT_32; + } else if (format.bitDepth == 64 && format.float && format.signed) { + f = binding.MPG123_ENC_FLOAT_64; + } else if (format.bitDepth == 8 && format.signed) { + f = binding.MPG123_ENC_SIGNED_8; + } else if (format.bitDepth == 8 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_8; + } else if (format.bitDepth == 16 && format.signed) { + f = binding.MPG123_ENC_SIGNED_16; + } else if (format.bitDepth == 16 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_16; + } else if (format.bitDepth == 24 && format.signed) { + f = binding.MPG123_ENC_SIGNED_24; + } else if (format.bitDepth == 24 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_24; + } else if (format.bitDepth == 32 && format.signed) { + f = binding.MPG123_ENC_SIGNED_32; + } else if (format.bitDepth == 32 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_32; + } + return f; +} diff --git a/native.js b/native.js deleted file mode 100644 index 9a26075..0000000 --- a/native.js +++ /dev/null @@ -1,227 +0,0 @@ -'use strict' - -var os = require('os') -var objectAssign = require('object-assign') -var binding = require('audio-mpg123') -var pcm = require('pcm-util') -var isAudioBuffer = require('is-audio-buffer') -var audioBuffer = require('audio-buffer') -var audioSink = require('audio-sink/direct') -var debug = require('debug')('speaker') - -var endianess = 'function' == os.endianess ? os.endianess() : 'LE' - -module.exports = Speaker - -/** - * The Speaker function initializes a new audio handler, - * then returns the write method to output audio to. - * - * @param {Object} opts options for the speaker - * @return {Function} write write audio from a buffer or audiobuffer - * @module Speaker - * @api public - */ -function Speaker (opts) { - debug('Speaker()') - var options = {} - - options = objectAssign({ - channels: 1, - float: false, - bitDepth: 16, - signed: true, - samplesPerFrame: 1024, - sampleRate: 44100, - endianess: endianess, - autoFlush: false - }, opts) - - if (options.handler) { - throw new Error('_create() was called more than once. Only one handler should exist.') - } - - options._closed = false - options._busy = false - - var format = Speaker.getFormat(options) - if (format === null) { - throw new Error('Invalid format options.') - } - - options.blockAlign = options.bitDepth / 8 * options.channels - - options.chunkSize = options.blockAlign * options.samplesPerFrame - - options.handler = binding.create((success) => { - if(!success) { - throw new Error('Failed to create the audio handler.') - } else { - debug('_create() audio handle successfully.') - } - }) - - if (options.handler !== null) { - debug('_start(%o)', Object.keys(options)) - binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { - if (!success) { - throw new Error('Could not start the audio output with these properties.') - } else { - debug('Created and started handler successfully.') - } - }) - } - - write.end = end - write.sink = sink - sink.end = end - return write - - /** - * The write function takes a buffer or audiobuffer and - * writes it to the speaker output. If the chunks are too - * large it will break it up and put the remainding chunks - * into a queue. - * NOTE: You can only write new chunks once the callback is - * called with no errors. - * - * @param {AudioBuffer} chunk (or Buffer) containing the data to be output - * @param {Function} callback callback with error and chunk parameters - * @return void - * @api public - */ - function write (chunk, callback) { - debug('write()') - if (options._closed) return debug('write() cannot be called after the speaker is closed.') - if (chunk && options._busy) return debug('write() cannot be called until the previous buffer has been written.') - - next(chunk, null, callback) - - function next (chunk, remainder, callback) { - if (options.handler) { - options._busy = true - - var chunkBuf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk || new Buffer(0) - var remainderBuf = isAudioBuffer(remainder) ? pcm.toBuffer(remainder, options) : remainder || new Buffer(0) - - var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) - - debug("%o bytes total queued for output.", queue.length) - - var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue - var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) - - debug("%o bytes writing to the speaker.", output.length) - debug("%o bytes remaining in the queue.", remaining.length) - - binding.write(options.handler, output, output.length, onWrite) - - function onWrite (written) { - debug('Wrote %o bytes this chunk.', written) - if(!remaining.length < 1) { - debug('Writing remaining chunks.') - next(null, remaining, callback) - } else { - debug('Finished writing chunk.') - if (options.autoFlush && remaining.length < 1) { - debug('Flushing the audio output.') - binding.flush(options.handler, function (success) { - if (success != 1) { - debug('Could not flush the audio output.') - options._busy = false - callback(new Error('Could not flush the audio output.'), written) - } else { - debug('Flushed audio successfully.') - options._busy = false - callback(null, written) - } - }) - } else { - options._busy = false - callback(null, written) - } - } - } - } - } - } - - function sink (callback) { - debug('sink()') - - return audioSink((data, callback) => { - if (options._closed) return callback(true) - setTimeout(callback, samplesPerFrame / sampleRate) - }) - } - - /** - * The end function closes the speaker and stops - * it from writing anymore data. The output data - * that was already written can be optionally flushed. - * NOTE: You cannot write anymore data after closing the speaker. - * - * @param {Boolean} flush flushes the written data (default is false) - * @param {Function} callback callback with error parameter - * @return void - * @api public - */ - function end (flush, callback) { - debug('end(%o)', flush) - if (options._closed) return debug('_end() was called more than once. Already ended.') - - if (options.handler) { - if (flush) { - debug('Flushing the audio output.') - binding.flush(options.handler, function (success) { - if (success != 1) { - debug('Could not flush the audio output.') - } else { - return close(callback) - } - }) - } else { - return close(callback) - } - } else { - debug('Could not flush the audio output because handler does not exist.') - } - - function close (callback) { - debug('close()') - binding.close(options.handler, (success) => { - if (callback) { - success ? callback() : callback(new Error('Failed to close speaker.')) - } - }) - options._closed = true - options.handler = null - } - } -} - -Speaker.getFormat = function getFormat (format) { - var f = null; - if (format.bitDepth == 32 && format.float && format.signed) { - f = binding.MPG123_ENC_FLOAT_32; - } else if (format.bitDepth == 64 && format.float && format.signed) { - f = binding.MPG123_ENC_FLOAT_64; - } else if (format.bitDepth == 8 && format.signed) { - f = binding.MPG123_ENC_SIGNED_8; - } else if (format.bitDepth == 8 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_8; - } else if (format.bitDepth == 16 && format.signed) { - f = binding.MPG123_ENC_SIGNED_16; - } else if (format.bitDepth == 16 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_16; - } else if (format.bitDepth == 24 && format.signed) { - f = binding.MPG123_ENC_SIGNED_24; - } else if (format.bitDepth == 24 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_24; - } else if (format.bitDepth == 32 && format.signed) { - f = binding.MPG123_ENC_SIGNED_32; - } else if (format.bitDepth == 32 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_32; - } - return f; -} diff --git a/package.json b/package.json index ee5176f..bca21b8 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,11 @@ "type": "git", "url": "git+https://github.com/audiojs/audio-speaker.git" }, + "main": "./index", + "browser": { + "./index": "./browser", + "./stream": "./browser-stream" + }, "keywords": [ "PCM", "output", From 0821744d0eb53bb4bd4b4f82744f423c1f09dd07 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 7 Nov 2016 23:50:07 -0500 Subject: [PATCH 48/96] Add node sine test --- tests/check.js | 2 +- tests/sine.js | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/sine.js diff --git a/tests/check.js b/tests/check.js index f1bab9b..f2eef1e 100644 --- a/tests/check.js +++ b/tests/check.js @@ -2,7 +2,7 @@ var test = require('tape') test('check for build output', function(t) { try { - require('../native')() != null ? t.pass('Found audio_mpg123.') : null + require('../')() != null ? t.pass('Found audio_mpg123.') : null } catch (err) { t.error(err, 'Could not find audio_mpg123.') } diff --git a/tests/sine.js b/tests/sine.js new file mode 100644 index 0000000..b760549 --- /dev/null +++ b/tests/sine.js @@ -0,0 +1,61 @@ + +/** + * Copied from node-speaker + * https://github.com/TooTallNate/node-speaker/blob/master/examples/sine.js + */ + +var Readable = require('stream').Readable; +var Speaker = require('../stream'); + +// node v0.8.x compat +if (!Readable) Readable = require('readable-stream/readable'); + +// the frequency to play +var freq = parseFloat(process.argv[2], 10) || 440.0; // Concert A, default tone + +// seconds worth of audio data to generate before emitting "end" +var duration = parseFloat(process.argv[3], 10) || 2.0; + +console.log('generating a %dhz sine wave for %d seconds', freq, duration); + +// A SineWaveGenerator readable stream +var sine = new Readable(); +sine.bitDepth = 16; +sine.channels = 2; +sine.sampleRate = 44100; +sine.samplesGenerated = 0; +sine._read = read; + +// create a SineWaveGenerator instance and pipe it to the speaker +sine.pipe(new Speaker()); + +// the Readable "_read()" callback function +function read (n) { + var sampleSize = this.bitDepth / 8; + var blockAlign = sampleSize * this.channels; + var numSamples = n / blockAlign | 0; + var buf = new Buffer(numSamples * blockAlign); + var amplitude = 32760; // Max amplitude for 16-bit audio + + // the "angle" used in the function, adjusted for the number of + // channels and sample rate. This value is like the period of the wave. + var t = (Math.PI * 2 * freq) / this.sampleRate; + + for (var i = 0; i < numSamples; i++) { + // fill with a simple sine wave at max amplitude + for (var channel = 0; channel < this.channels; channel++) { + var s = this.samplesGenerated + i; + var val = Math.round(amplitude * Math.sin(t * s)); // sine wave + var offset = (i * sampleSize * this.channels) + (channel * sampleSize); + buf['writeInt' + this.bitDepth + 'LE'](val, offset); + } + } + + this.push(buf); + + this.samplesGenerated += numSamples; + if (this.samplesGenerated >= this.sampleRate * duration) { + // after generating "duration" second of audio, emit "end" + this.push(null); + } +} From 6f354bd8c289ad2b6c2cd02e0846ec521e94e364 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Tue, 8 Nov 2016 00:03:58 -0500 Subject: [PATCH 49/96] Fix browser entry --- browser.js | 5 +++-- tests/play_once.js | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/browser.js b/browser.js index bb0474c..0ac5dbe 100644 --- a/browser.js +++ b/browser.js @@ -1,6 +1,7 @@ +/** @module audio-speaker/browser */ 'use strict' -var writer = require('web-audio-stream') +var Writer = require('web-audio-stream/writer') var context = require('audio-context') module.exports = BrowserSpeaker @@ -17,5 +18,5 @@ module.exports = BrowserSpeaker function BrowserSpeaker (opts) { var ctx = opts && opts.context || context - return write(ctx.destination, opts) + return Writer(ctx.destination, opts) } diff --git a/tests/play_once.js b/tests/play_once.js index 90376dc..e27c9bd 100644 --- a/tests/play_once.js +++ b/tests/play_once.js @@ -5,14 +5,14 @@ var LenaBuffer = require('audio-lena/buffer') var AudioSpeaker = require('../index') test('play audio once test', function (t) { - var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) + var speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = new AudioBuffer(1, LenaBuffer) - Speaker(buf, (err, chunk) => { + speaker(buf, (err, chunk) => { if (err || chunk === true) { t.error(err, 'Write callback caught an unexpected error.') } else { - Speaker.end(true, (err) => { + speaker.end(true, (err) => { err ? t.error(err) : t.pass('Output successful.') t.end() }) From f48bbf56b4cb0287bc35e13bd45321b53a4d9ca8 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Tue, 8 Nov 2016 00:20:19 -0500 Subject: [PATCH 50/96] Resurrect classic test-cases --- package.json | 10 +++- tests/cases.js | 159 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 tests/cases.js diff --git a/package.json b/package.json index bca21b8..ee9a45d 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "test:play": "tape tests/play_once.js", "test:play_twice": "tape tests/play_twice.js", "test:stream": "tape tests/play_stream.js", - "test:pull": "tape tests/play_pull.js" + "test:pull": "tape tests/play_pull.js", + "lint": "eslint *.js --ignore-pattern test*" }, "repository": { "type": "git", @@ -41,11 +42,16 @@ "object-assign": "^4.1.0", "pcm-util": "^2.0.3", "pull-stream": "^3.5.0", + "audio-through": "^2.1.9", "web-audio-stream": "^2.2.0" }, "devDependencies": { + "audio-buffer-utils": "^3.1.2", + "audio-generator": "^2.1.1", "audio-lena": "^1.1.0", - "audio-through": "^2.1.9", + "pcm-util": "^2.0.3", + "pcm-volume": "^1.0.0", + "pull-stream": "^3.5.0", "tape": "^4.6.2" }, "optionalDependencies": { diff --git a/tests/cases.js b/tests/cases.js new file mode 100644 index 0000000..f00e2eb --- /dev/null +++ b/tests/cases.js @@ -0,0 +1,159 @@ +'use strict'; + +var Speaker = require('../stream'); +var Generator = require('audio-generator/stream'); +var Generate = require('audio-generator/index'); +var Readable = require('stream').Readable; +var util = require('audio-buffer-utils'); +var pcm = require('pcm-util'); +var Through = require('audio-through'); +Through.log = true; +var Volume = require('pcm-volume'); +var test = require('tape') +var SpeakerWriter = require('../index'); +var pull = require('pull-stream'); +var PullSpeaker = require('../pull'); +var pullGenerator = require('audio-generator/pull'); + + + +test('Pure function', function (t) { + let generate = Generate(t => { + return Math.sin(t * Math.PI * 2 * 440); + }, 1); + + let write = SpeakerWriter(); + + (function loop (err, buf) { + if (err) return write(null); + write(generate(buf), loop) + })(); + + setTimeout(() => { + write(null); + t.end(); + }, 200); +}); + +// test('Pull stream', function (t) { +// let out = PullSpeaker(); + +// pull( +// pullGenerator(time => 2 * time * 440 - 1, {frequency: 440}), +// out +// ); + +// setTimeout(() => { +// out.abort(); +// t.end(); +// }, 500); +// }); + +// test('Cleanness of wave', function (t) { +// Through(function (buffer) { +// var self = this; +// util.fill(buffer, function (sample, idx, channel) { +// return Math.sin(Math.PI * 2 * (self.count + idx) * 440 / 44100); +// }); + +// if (this.time > 1) return this.end(); + +// return buffer; +// }) +// .pipe(Speaker()); +// // .pipe(WAASteam(context.destination)); +// t.end(); +// }); + +// test('Feed audio-through', function (t) { +// Generator({ +// generate: function (time) { +// return [ +// Math.sin(Math.PI * 2 * time * 538 ) / 5, +// Math.sin(Math.PI * 2 * time * 542 ) / 5 +// // Math.random() +// ] +// }, +// duration: .4 +// }).pipe(Speaker()); + +// t.end() +// }); + +// test('Feed raw pcm', function (t) { +// var count = 0; +// Readable({ +// read: function (size) { +// var abuf = util.create(2, 1024, 44100); + +// //EGG: swap ch & i and hear wonderful sfx +// util.fill(abuf, function (v, i, ch) { +// v = Math.sin(Math.PI * 2 * ((count + i)/44100) * (738 + ch*2) ) / 5; +// return v; +// }); + +// count += 1024; + +// if (count > 1e4 ) return this.push(null); + +// let buf = pcm.toBuffer(abuf); + +// this.push(buf); +// } +// }) +// .pipe(Speaker({ +// channels: 2 +// })); + +// t.end() +// }); + +// //FIXME: use transform stream here to send floats data to speaker +// test.skip('Feed custom pcm', function (t) { +// var count = 0; +// Readable({ +// // objectMode: 1, +// read: function (size) { +// var abuf = util.create(2, 1024, 44100); + +// util.fill(abuf, function (v, i, ch) { +// return Math.sin(Math.PI * 2 * ((count + i)/44100) * (938 + ch*2) ); +// }); + +// count += 1024; + +// if (count > 1e4 ) return this.push(null); + +// let buf = pcm.toBuffer(abuf, { +// float: true +// }); + +// this.push(buf); +// } +// }).pipe(Speaker({ +// channels: 2, + +// //EGG: comment this and hear wonderful sfx +// float: true +// })); + +// t.end() +// }); + +// test.skip('Feed random buffer size'); + +// test('Volume case', function (t) { +// Generator({ +// generate: function (time) { +// return [ +// Math.sin(Math.PI * 2 * time * 1038 ) / 5, +// Math.sin(Math.PI * 2 * time * 1042 ) / 5 +// ]; +// }, +// duration: 1 +// }) +// .pipe(Volume(5)) +// .pipe(Speaker()); + +// t.end() +// }); From 9cfb8d7f567487aedc61f1e05cc99af20abf4fc8 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Tue, 8 Nov 2016 00:32:29 -0500 Subject: [PATCH 51/96] Fix some eslints --- .eslintrc.json | 44 ++++++++++++++++++++++++++++++++++++++++++++ index.js | 3 +-- stream.js | 1 - 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 .eslintrc.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..3b2d996 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,44 @@ +{ + "env": { + "browser": true, + "node": true, + "commonjs": true, + "es6": true + }, + "extends": "eslint:recommended", + "rules": { + "strict": 2, + "indent": 0, + "linebreak-style": 0, + "quotes": 0, + "semi": 0, + "no-cond-assign": 1, + "no-console": 1, + "no-constant-condition": 1, + "no-duplicate-case": 1, + "no-empty": 1, + "no-ex-assign": 1, + "no-extra-boolean-cast": 1, + "no-extra-semi": 1, + "no-fallthrough": 1, + "no-func-assign": 1, + "no-global-assign": 1, + "no-implicit-globals": 2, + "no-inner-declarations": ["error", "functions"], + "no-irregular-whitespace": 2, + "no-loop-func": 1, + "no-multi-str": 1, + "no-mixed-spaces-and-tabs": 1, + "no-proto": 1, + "no-sequences": 1, + "no-throw-literal": 1, + "no-unmodified-loop-condition": 1, + "no-useless-call": 1, + "no-void": 1, + "no-with": 2, + "wrap-iife": 1, + "no-redeclare": 1, + "no-unused-vars": ["error", { "vars": "all", "args": "none" }], + "no-sparse-arrays": 1 + } +} diff --git a/index.js b/index.js index 7b77caf..3016e7f 100644 --- a/index.js +++ b/index.js @@ -7,7 +7,6 @@ var objectAssign = require('object-assign') var binding = require('audio-mpg123') var pcm = require('pcm-util') var isAudioBuffer = require('is-audio-buffer') -var audioBuffer = require('audio-buffer') var audioSink = require('audio-sink/direct') var debug = require('debug')('speaker') @@ -153,7 +152,7 @@ function Speaker (opts) { return audioSink((data, callback) => { if (options._closed) return callback(true) - setTimeout(callback, samplesPerFrame / sampleRate) + setTimeout(callback, options.samplesPerFrame / options.sampleRate) }) } diff --git a/stream.js b/stream.js index b6ddc0d..6490118 100644 --- a/stream.js +++ b/stream.js @@ -1,7 +1,6 @@ 'use strict' var inherits = require('util').inherits -var objectAssign = require('object-assign') var Through = require('audio-through') var Speaker = require('./index') From ef06e14b8e69797a477795f8488ee1fd1f1b14df Mon Sep 17 00:00:00 2001 From: Dmitry Date: Tue, 8 Nov 2016 00:44:46 -0500 Subject: [PATCH 52/96] Fix test case --- tests/cases.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cases.js b/tests/cases.js index f00e2eb..59a5dc9 100644 --- a/tests/cases.js +++ b/tests/cases.js @@ -24,9 +24,9 @@ test('Pure function', function (t) { let write = SpeakerWriter(); - (function loop (err, buf) { + (function loop (err) { if (err) return write(null); - write(generate(buf), loop) + write(generate(), loop) })(); setTimeout(() => { From 6f8f4c99ba12100ed48a6c1c29ca66699d198f97 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 9 Nov 2016 09:41:43 +1300 Subject: [PATCH 53/96] Update audio-mpg123 to 1.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ee9a45d..2e25d3f 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,6 @@ "tape": "^4.6.2" }, "optionalDependencies": { - "audio-mpg123": "^1.1.4" + "audio-mpg123": "^1.2.0" } } From 8f21d51d289871ea2191c54af1b07020aa650ad2 Mon Sep 17 00:00:00 2001 From: Jamen Marz Date: Tue, 8 Nov 2016 14:55:21 -0700 Subject: [PATCH 54/96] Update audio-mpg123 to v1.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e25d3f..e156457 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,6 @@ "tape": "^4.6.2" }, "optionalDependencies": { - "audio-mpg123": "^1.2.0" + "audio-mpg123": "^1.2.2" } } From ec82b6c23b5cc13a3505e4baa15830bda884462b Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 9 Nov 2016 12:38:46 +1300 Subject: [PATCH 55/96] Convert some debugs to errors and update travis --- .travis.yml | 6 +++--- index.js | 18 +++++++----------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 004df7f..5a4f71a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,11 +17,11 @@ env: - CXX=g++-4.8 install: - npm install -g npm - - npm install -g node-gyp - - npm install - - npm run test + - npm install -g node-pre-gyp + - npm install --mpg-module=dummy script: - node -v - npm -v + - npm run test matrix: fast_finish: true diff --git a/index.js b/index.js index 3016e7f..077cabb 100644 --- a/index.js +++ b/index.js @@ -94,7 +94,11 @@ function Speaker (opts) { function write (chunk, callback) { debug('write()') if (options._closed) return debug('write() cannot be called after the speaker is closed.') - if (chunk && options._busy) return debug('write() cannot be called until the previous buffer has been written.') + + if (chunk && options._busy) { + debug('write() cannot be called until the previous buffer has been written.') + callback(new Error('Could not write chunk as the buffer was busy.'), 0) + } next(chunk, null, callback) @@ -107,20 +111,13 @@ function Speaker (opts) { var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) - debug("%o bytes total queued for output.", queue.length) - var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) - debug("%o bytes writing to the speaker.", output.length) - debug("%o bytes remaining in the queue.", remaining.length) - binding.write(options.handler, output, output.length, onWrite) function onWrite (written) { - debug('Wrote %o bytes this chunk.', written) if(!remaining.length < 1) { - debug('Writing remaining chunks.') next(null, remaining, callback) } else { debug('Finished writing chunk.') @@ -128,7 +125,6 @@ function Speaker (opts) { debug('Flushing the audio output.') binding.flush(options.handler, function (success) { if (success != 1) { - debug('Could not flush the audio output.') options._busy = false callback(new Error('Could not flush the audio output.'), written) } else { @@ -176,7 +172,7 @@ function Speaker (opts) { debug('Flushing the audio output.') binding.flush(options.handler, function (success) { if (success != 1) { - debug('Could not flush the audio output.') + callback(new Error('Could not flush the audio output.')) } else { return close(callback) } @@ -185,7 +181,7 @@ function Speaker (opts) { return close(callback) } } else { - debug('Could not flush the audio output because handler does not exist.') + callback(new Error('Could not flush the audio output. Handler was deleted or not created.')) } function close (callback) { From 64f6ca8c43060da3eb250b6a54e091a6279e397d Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 9 Nov 2016 13:13:01 +1300 Subject: [PATCH 56/96] Update audio-mpg123 to 1.2.3 --- .travis.yml | 5 ++++- package.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5a4f71a..f80f3ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,10 @@ env: install: - npm install -g npm - npm install -g node-pre-gyp - - npm install --mpg-module=dummy + - npm install + - cd ./node_modules/audio-mpg123 + - node-pre-gyp clean + - node-pre-gyp rebuild --mpg123-module=dummy script: - node -v - npm -v diff --git a/package.json b/package.json index e156457..6667d22 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,6 @@ "tape": "^4.6.2" }, "optionalDependencies": { - "audio-mpg123": "^1.2.2" + "audio-mpg123": "^1.2.3" } } From ed3a41f53e29271f3c37b8641a3917adb2b90fd3 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 9 Nov 2016 13:31:55 +1300 Subject: [PATCH 57/96] Add sine test to package scripts --- package.json | 1 + tests/{sine.js => play_sine.js} | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) rename tests/{sine.js => play_sine.js} (94%) diff --git a/package.json b/package.json index 6667d22..322f30f 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "test:play_twice": "tape tests/play_twice.js", "test:stream": "tape tests/play_stream.js", "test:pull": "tape tests/play_pull.js", + "test:sine": "node ./tests/play_sine.js", "lint": "eslint *.js --ignore-pattern test*" }, "repository": { diff --git a/tests/sine.js b/tests/play_sine.js similarity index 94% rename from tests/sine.js rename to tests/play_sine.js index b760549..7443081 100644 --- a/tests/sine.js +++ b/tests/play_sine.js @@ -4,6 +4,8 @@ * https://github.com/TooTallNate/node-speaker/blob/master/examples/sine.js */ + // TODO: This can be updated to node v4 and higher. + var Readable = require('stream').Readable; var Speaker = require('../stream'); @@ -16,7 +18,7 @@ var freq = parseFloat(process.argv[2], 10) || 440.0; // Concert A, default tone // seconds worth of audio data to generate before emitting "end" var duration = parseFloat(process.argv[3], 10) || 2.0; -console.log('generating a %dhz sine wave for %d seconds', freq, duration); +console.log('Generating a %dhz sine wave for %d seconds', freq, duration); // A SineWaveGenerator readable stream var sine = new Readable(); From 5984b3aa81c1b9d315945b9b8f4ec4652d048d9c Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 9 Nov 2016 13:33:23 +1300 Subject: [PATCH 58/96] 2.0.0-5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 322f30f..7abb8f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audio-speaker", - "version": "2.0.0-4", + "version": "2.0.0-5", "description": "Output PCM data to a device or library.", "scripts": { "test": "tape tests/check.js", From aca68430fc2999b5222e8a07412b1c1d80068a8a Mon Sep 17 00:00:00 2001 From: Jamen Marzonie Date: Fri, 27 Jan 2017 22:20:30 -0600 Subject: [PATCH 59/96] Rename index.js to node.js --- index.js => node.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename index.js => node.js (100%) diff --git a/index.js b/node.js similarity index 100% rename from index.js rename to node.js From e240feecd293e672453c63b19d627ce3c72e5346 Mon Sep 17 00:00:00 2001 From: Jamen Marzonie Date: Fri, 27 Jan 2017 22:27:51 -0600 Subject: [PATCH 60/96] Change import to browser/node env --- index.js | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 index.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..389097d --- /dev/null +++ b/index.js @@ -0,0 +1,4 @@ +module.exports = + require('is-browser') + ? require('./browser') + : require('./node') From d94957d49d3e5a1c6d7e04526833ea892bccb858 Mon Sep 17 00:00:00 2001 From: Jamen Marzonie Date: Fri, 27 Jan 2017 22:28:07 -0600 Subject: [PATCH 61/96] Add yarn.lock --- yarn.lock | 978 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 978 insertions(+) create mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..ec7e975 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,978 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abbrev@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +aproba@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.0.4.tgz#2713680775e7614c8ba186c065d4e2e52d1072c0" + +are-we-there-yet@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz#80e470e95a084794fe1899262c5667c6e88de1b3" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.0 || ^1.1.13" + +array-find@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-find/-/array-find-1.0.0.tgz#6c8e286d11ed768327f8e62ecee87353ca3e78b8" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +atob@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" + +audio-buffer-utils@^3.0.0, audio-buffer-utils@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/audio-buffer-utils/-/audio-buffer-utils-3.1.2.tgz#1a2bf28ca1e1ee94381a6d4497137d078ce8cb17" + dependencies: + audio-buffer "^2.0.0" + is-audio-buffer "^1.0.0" + is-browser "^2.0.1" + typedarray-methods "^1.0.0" + +audio-buffer@^2.0.0, audio-buffer@^2.1.3, audio-buffer@^2.4.5: + version "2.4.5" + resolved "https://registry.yarnpkg.com/audio-buffer/-/audio-buffer-2.4.5.tgz#291ea5260f5006c077b69aaae764044d59be66f7" + dependencies: + audio-context latest + buffer-to-arraybuffer latest + is-audio-buffer "^1.0.1" + is-browser "^2.0.1" + is-buffer "^1.1.0" + +audio-context@^0.1.0, audio-context@latest: + version "0.1.0" + resolved "https://registry.yarnpkg.com/audio-context/-/audio-context-0.1.0.tgz#116ee83d566e10e7e845f29d9b1e1bc2ea3520d2" + dependencies: + global "~4.2.1" + +audio-generator@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/audio-generator/-/audio-generator-2.1.1.tgz#9ec196cd868dd2a6e17d2418504ff5a4a473d02b" + dependencies: + audio-buffer "^2.4.5" + audio-buffer-utils "^3.1.2" + audio-through "^2.0.1" + inherits "^2.0.1" + pcm-util "^2.0.3" + xtend "^4.0.0" + +audio-lena@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/audio-lena/-/audio-lena-1.1.0.tgz#ee6ecab89582d3e3b0ac1ef941afe3febf92166f" + dependencies: + atob "^2.0.3" + +audio-mpg123@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/audio-mpg123/-/audio-mpg123-1.2.3.tgz#aef364d4941a7efd07278ed03e4c97862c0674e0" + dependencies: + nan "2.2.1" + node-pre-gyp "^0.6.31" + +audio-sink@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/audio-sink/-/audio-sink-1.1.6.tgz#e1454eb1378522298d2170b7cb032c33fd1f6885" + dependencies: + inherits "^2.0.1" + xtend "^4.0.1" + +audio-through@^2.0.1, audio-through@^2.1.9: + version "2.1.9" + resolved "https://registry.yarnpkg.com/audio-through/-/audio-through-2.1.9.tgz#6a0385f36868c433a471744a15fb6183daab9ce6" + dependencies: + array-find "^1.0.0" + audio-buffer "^2.1.3" + audio-context "^0.1.0" + get-uid "^1.0.1" + inherits "^2.0.1" + is-audio-buffer "^1.0.1" + is-promise "^2.1.0" + pcm-util "^2.0.1" + performance-now "^0.2.0" + xtend "^4.0.1" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws4@^1.2.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +bcrypt-pbkdf@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz#3ca76b85241c7170bf7d9703e7b9aa74630040d4" + dependencies: + tweetnacl "^0.14.3" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +brace-expansion@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +buffer-shims@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + +buffer-to-arraybuffer@latest: + version "0.0.4" + resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.4.tgz#f3e5e3f6f2632c71e7cdebe76ed1718fad421d4c" + +caseless@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" + +chalk@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + +commander@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +debug@^2.2.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b" + dependencies: + ms "0.7.2" + +debug@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +deep-equal@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + +deep-extend@~0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +defined@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +es-abstract@^1.5.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.0" + is-callable "^1.1.3" + is-regex "^1.0.3" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +escape-string-regexp@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +extend@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" + +extsprintf@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" + +for-each@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.2.tgz#2c40450b9348e97f281322593ba96704b9abd4d4" + dependencies: + is-function "~1.0.0" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fstream-ignore@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" + dependencies: + fstream "^1.0.0" + inherits "2" + minimatch "^3.0.0" + +fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.10.tgz#604e8a92fe26ffd9f6fae30399d4984e1ab22822" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.0.2, function-bind@^1.1.0, function-bind@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" + +gauge@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.2.tgz#15cecc31b02d05345a5d6b0e171cdb3ad2307774" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + supports-color "^0.2.0" + wide-align "^1.1.0" + +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +get-uid@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-uid/-/get-uid-1.0.1.tgz#ac6d5695550cb6be371d5a79b0d968115f746a22" + +getpass@^0.1.1: + version "0.1.6" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" + dependencies: + assert-plus "^1.0.0" + +glob@^7.0.5, glob@~7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/global/-/global-4.2.1.tgz#c16801e9a47f0b0b847a156d419dc143b5a4e8b3" + dependencies: + min-document "^2.6.1" + process "~0.5.1" + +graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +har-validator@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" + dependencies: + chalk "^1.1.1" + commander "^2.9.0" + is-my-json-valid "^2.12.4" + pinkie-promise "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@~1.3.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + +is-audio-buffer@^1.0.0, is-audio-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-audio-buffer/-/is-audio-buffer-1.0.1.tgz#a8317bc5f27198b5634701b06a01e5d8089b834d" + +is-browser@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-browser/-/is-browser-2.0.1.tgz#8bf0baf799a9c62fd9de5bcee4cf3397c3e7529a" + +is-buffer@^1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-function@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + +is-my-json-valid@^2.12.4: + version "2.15.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + +is-regex@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.3.tgz#0d55182bddf9f2fde278220aec3a75642c908637" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +jodid25519@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" + dependencies: + jsbn "~0.1.0" + +jsbn@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + +jsprim@^1.2.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.3.1.tgz#2a7256f70412a29ee3670aaca625994c4dcff252" + dependencies: + extsprintf "1.0.2" + json-schema "0.2.3" + verror "1.3.6" + +mime-db@~1.26.0: + version "1.26.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.26.0.tgz#eaffcd0e4fc6935cf8134da246e2e6c35305adff" + +mime-types@^2.1.12, mime-types@~2.1.7: + version "2.1.14" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.14.tgz#f7ef7d97583fcaf3b7d282b6f8b5679dab1e94ee" + dependencies: + mime-db "~1.26.0" + +min-document@^2.6.1: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + dependencies: + dom-walk "^0.1.0" + +minimatch@^3.0.0, minimatch@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.2.0, minimist@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +"mkdirp@>=0.5 0", mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +nan@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.2.1.tgz#d68693f6b34bb41d66bc68b3a4f9defc79d7149b" + +node-pre-gyp@^0.6.31: + version "0.6.32" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.32.tgz#fc452b376e7319b3d255f5f34853ef6fd8fe1fd5" + dependencies: + mkdirp "~0.5.1" + nopt "~3.0.6" + npmlog "^4.0.1" + rc "~1.1.6" + request "^2.79.0" + rimraf "~2.5.4" + semver "~5.3.0" + tar "~2.2.1" + tar-pack "~3.3.0" + +nopt@~3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +npmlog@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.1" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-inspect@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.2.1.tgz#3b62226eb8f6d441751c7d8f22a20ff80ac9dc3f" + +object-keys@^1.0.8: + version "1.0.11" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +once@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +pcm-util@^2.0.1, pcm-util@^2.0.2, pcm-util@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pcm-util/-/pcm-util-2.0.3.tgz#ce00a7dc663339b47f934b57a704a6c95716d1a7" + dependencies: + audio-buffer "^2.1.3" + is-audio-buffer "^1.0.1" + is-buffer "^1.1.0" + to-array-buffer "^1.0.0" + +pcm-volume@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pcm-volume/-/pcm-volume-1.0.0.tgz#eaa851c94968ab6e142ce2e12953708be4a7f0c0" + dependencies: + inherits "^2.0.1" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +process@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + +pull-stream@^3.4.4, pull-stream@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.5.0.tgz#1ee5b6f76fd3b3a49a5afb6ded5c0320acb3cfc7" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qs@~6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.0.tgz#f403b264f23bc01228c74131b407f18d5ea5d442" + +rc@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~1.0.4" + +"readable-stream@^2.0.0 || ^1.1.13", readable-stream@~2.1.4: + version "2.1.5" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" + dependencies: + buffer-shims "^1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +request@^2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + +resolve@~1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +resumer@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + dependencies: + through "~2.3.4" + +rimraf@2, rimraf@~2.5.1, rimraf@~2.5.4: + version "2.5.4" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04" + dependencies: + glob "^7.0.5" + +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +sshpk@^1.7.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.10.2.tgz#d5a804ce22695515638e798dbe23273de070a5fa" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jodid25519 "^1.0.0" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string.prototype.trim@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.0" + function-bind "^1.0.2" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +stringstream@~0.0.4: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-json-comments@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + +supports-color@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +tape@^4.6.2: + version "4.6.3" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.6.3.tgz#637e77581e9ab2ce17577e9bd4ce4f575806d8b6" + dependencies: + deep-equal "~1.0.1" + defined "~1.0.0" + for-each "~0.3.2" + function-bind "~1.1.0" + glob "~7.1.1" + has "~1.0.1" + inherits "~2.0.3" + minimist "~1.2.0" + object-inspect "~1.2.1" + resolve "~1.1.7" + resumer "~0.0.0" + string.prototype.trim "~1.1.2" + through "~2.3.8" + +tar-pack@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae" + dependencies: + debug "~2.2.0" + fstream "~1.0.10" + fstream-ignore "~1.0.5" + once "~1.3.3" + readable-stream "~2.1.4" + rimraf "~2.5.1" + tar "~2.2.1" + uid-number "~0.0.6" + +tar@~2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +through@~2.3.4, through@~2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +to-array-buffer@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/to-array-buffer/-/to-array-buffer-1.2.0.tgz#03361a76a85cebadd160ca17f6e1e2d567c611fc" + dependencies: + is-audio-buffer "^1.0.1" + +tough-cookie@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" + dependencies: + punycode "^1.4.1" + +tunnel-agent@~0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +typedarray-methods@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typedarray-methods/-/typedarray-methods-1.0.0.tgz#d656b078a9ff6134ed193794f8e55e158204ad0d" + +uid-number@~0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +uuid@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" + +verror@1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" + dependencies: + extsprintf "1.0.2" + +web-audio-stream@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/web-audio-stream/-/web-audio-stream-2.2.0.tgz#5975a1a69c4b12d23e49b1e921925c8c04c6314b" + dependencies: + audio-buffer-utils "^3.0.0" + audio-context "^0.1.0" + inherits "^2.0.1" + is-audio-buffer "^1.0.1" + is-plain-obj "^1.1.0" + pcm-util "^2.0.2" + pull-stream "^3.4.4" + xtend "^4.0.1" + +wide-align@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad" + dependencies: + string-width "^1.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +xtend@^4.0.0, xtend@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From f35f20fc204d603c3737b58bdf31eebad9cc6884 Mon Sep 17 00:00:00 2001 From: Jamen Marzonie Date: Tue, 7 Mar 2017 04:00:14 -0600 Subject: [PATCH 62/96] Fix audio-speaker/browser --- browser-stream.js | 25 ------------------------- browser.js | 30 ++++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 27 deletions(-) delete mode 100644 browser-stream.js diff --git a/browser-stream.js b/browser-stream.js deleted file mode 100644 index 0cf5b2c..0000000 --- a/browser-stream.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' - -var inherits = require('util').inherits -var WAAStream = require('web-audio-stream/writable') -var context = require('audio-context') - -module.exports = BrowserStreamSpeaker - -/** - * The BrowserSpeaker function initalizes and returns - * a {Module} webaudiostream to write to from a stream. - * - * @param {Object} opts options for the speaker - * @return {Module} webaudiostream for writing data to - * @module BrowserSpeaker - * @api public - */ -function BrowserStreamSpeaker (opts) { - if (!(this instanceof BrowserStreamSpeaker)) return new BrowserStreamSpeaker(opts) - - var ctx = opts && opts.context || context - - WAAStream.call(this, ctx.destination, opts) -} -inherits(BrowserStreamSpeaker, WAAStream) diff --git a/browser.js b/browser.js index 0ac5dbe..0eff6eb 100644 --- a/browser.js +++ b/browser.js @@ -3,6 +3,7 @@ var Writer = require('web-audio-stream/writer') var context = require('audio-context') +function noop () {} module.exports = BrowserSpeaker @@ -16,7 +17,32 @@ module.exports = BrowserSpeaker * @api public */ function BrowserSpeaker (opts) { - var ctx = opts && opts.context || context + opts = opts || {} - return Writer(ctx.destination, opts) + // TODO: Is this acceptable? Better way to handle this? + // Leave it up to the user? + if (!opts.samplesPerFrame) { + opts.samplesPerFrame = 2048 + } + + var ctx = opts.context || context + var dest = ctx.destination + var node = ctx.createScriptProcessor() + var _write = Writer(dest, opts) + + function write (data, cb) { + var start = context.currentTime + node.addEventListener('audioprocess', function ending (e, done) { + if (e.playbackTime - start > data.duration) { + node.removeEventListener('audioprocess', ending) + cb(null, opts.samplesPerFrame) + } + }) + + node.connect(dest) + return _write(data, noop) + } + + write.end = _write.end + return write } From e15ba6342324be88a078f6309f0385a9c3e21cca Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 21 Jun 2017 16:19:22 +1200 Subject: [PATCH 63/96] Remove pull stream and node stream support (move to another package) --- package.json | 3 --- pull.js | 38 -------------------------------------- readme.md | 42 ++++++++---------------------------------- stream.js | 34 ---------------------------------- 4 files changed, 8 insertions(+), 109 deletions(-) delete mode 100644 pull.js delete mode 100644 stream.js diff --git a/package.json b/package.json index 7abb8f6..6dd4013 100644 --- a/package.json +++ b/package.json @@ -42,9 +42,6 @@ "is-browser": "^2.0.1", "object-assign": "^4.1.0", "pcm-util": "^2.0.3", - "pull-stream": "^3.5.0", - "audio-through": "^2.1.9", - "web-audio-stream": "^2.2.0" }, "devDependencies": { "audio-buffer-utils": "^3.1.2", diff --git a/pull.js b/pull.js deleted file mode 100644 index c3ab39a..0000000 --- a/pull.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict' - -var drain = require('pull-stream/sinks/drain') -var asyncMap = require('pull-stream/throughs/async-map') -var pull = require('pull-stream/pull') -var Speaker = require('./index') - -module.exports = PullSpeaker - -/** - * The PullSpeaker function initializes a speaker - * and returns a sink for data to be pulled to, which - * is then written to the speaker. - * - * @param {Object} opts options for the speaker - * @return {Drain} drain pull-stream sink for the data to be pulled to - * @module PullSpeaker - * @api public - */ -function PullSpeaker (opts) { - var speaker = Speaker(opts) - var d = drain() - - var sink = pull(asyncMap(function (buf, done) { - done(true) - speaker(buf, (err, written) => { - if (err) { - speaker.end(false) - done(err) - } else { - speaker.end(true) - } - }) - }), d) - - sink.abort = d.abort - return sink -} diff --git a/readme.md b/readme.md index f687f44..079984f 100644 --- a/readme.md +++ b/readme.md @@ -25,58 +25,32 @@ Accepts options in main function: More documentation on these options will be added soon. -We have some variety in the way you can write to the Speaker. +### Usage -### Stream ```js -var speaker = require('audio-speaker/stream') -var generator = require('audio-generator/stream') - -generator(function (time) { - var p = Math.PI * 2 - return [Math.sin(p * time * 441), Math.sin(p * time * 439)] -}).pipe(speaker({ autoFlush: true })) -``` - -### Pull-stream -```js -var pull = require('pull-stream/pull') -var speaker = require('audio-speaker/pull') -var osc = require('audio-oscillator/pull') - -pull(osc({frequency: 440}), speaker({ autoFlush: true })) +var speaker = require('audio-speaker'); +var write = speaker(); +write(audioBuffer|data, callback); ``` -### Direct +### Example ```js var speaker = require('audio-speaker') var generator = require('audio-generator') -var output = speaker({ autoFlush: true }) +var write = speaker({ autoFlush: true }) var input = generator(t => Math.sin(t * Math.PI * 2 * 440)) (function loop (err, buf) { var buffer = input() - output(buffer, loop) + write(buffer, loop) }) ``` -## Credits - -| ![connor][connor-avatar] | -| :---------------------------: | -| [Connor Hartley][connor-link] | - -Thanks to @jamen and @dustindowell22 for the mpg123 env configurations. - -#### Related +#### Also see > [mpg123](https://github.com/audiojs/mpg123) - modifications to mpg123 to suit audio-speaker.
> [web-audio-stream](https://github.com/audiojs/web-audio-stream) — stream data to web-audio.
> [audio-through](http://npmjs.org/package/audio-through) — universal stream for processing audio.
-> [node-speaker](http://npmjs.org/package/speaker) — output pcm stream to speaker in node.
> [audio-feeder](https://github.com/brion/audio-feeder) — cross-browser speaker for pcm data.
- - [connor-avatar]: https://avatars0.githubusercontent.com/u/12867785?v=3&s=125 - [connor-link]: https://github.com/connorhartley diff --git a/stream.js b/stream.js deleted file mode 100644 index 6490118..0000000 --- a/stream.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' - -var inherits = require('util').inherits -var Through = require('audio-through') -var Speaker = require('./index') - -module.exports = StreamSpeaker - -inherits(StreamSpeaker, Through) - -/** - * The StreamSpeaker function initializes a speaker - * and inherits {Module} AudioThrough for pipable data - * functionality. - * - * @param {Object} opts options for the speaker - * @return void - * @module StreamSpeaker - * @api public - */ -function StreamSpeaker (opts) { - if (!(this instanceof StreamSpeaker)) return new StreamSpeaker(opts) - - opts = opts || {}; - Through.call(this, opts) - - this.speaker = Speaker(opts) - this.on('end', () => this.speaker.end()) -} -StreamSpeaker.prototype.process = function (chunk, callback) { - this.speaker(chunk, (err, written) => { - return err ? callback(err) : callback() - }); -} From 9f17096ab408c5b07c9937da65ecbc8841a87d61 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 21 Jun 2017 16:23:56 +1200 Subject: [PATCH 64/96] Fix up readme --- package.json | 2 +- readme.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6dd4013..6f4aa81 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "is-audio-buffer": "^1.0.1", "is-browser": "^2.0.1", "object-assign": "^4.1.0", - "pcm-util": "^2.0.3", + "pcm-util": "^2.0.3" }, "devDependencies": { "audio-buffer-utils": "^3.1.2", diff --git a/readme.md b/readme.md index 079984f..b37a61f 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -#audio-speaker +# audio-speaker > Output audio natively in node. From 91dacb1d7161cf190972f64ed2daee8f66edc8c6 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 21 Jun 2017 16:32:29 +1200 Subject: [PATCH 65/96] Remove uneeded tests --- package.json | 6 +---- tests/play_pull.js | 27 ------------------- tests/play_sine.js | 63 -------------------------------------------- tests/play_stream.js | 23 ---------------- 4 files changed, 1 insertion(+), 118 deletions(-) delete mode 100644 tests/play_pull.js delete mode 100644 tests/play_sine.js delete mode 100644 tests/play_stream.js diff --git a/package.json b/package.json index 6f4aa81..2e35ba6 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,6 @@ "test": "tape tests/check.js", "test:play": "tape tests/play_once.js", "test:play_twice": "tape tests/play_twice.js", - "test:stream": "tape tests/play_stream.js", - "test:pull": "tape tests/play_pull.js", - "test:sine": "node ./tests/play_sine.js", "lint": "eslint *.js --ignore-pattern test*" }, "repository": { @@ -17,8 +14,7 @@ }, "main": "./index", "browser": { - "./index": "./browser", - "./stream": "./browser-stream" + "./index": "./browser" }, "keywords": [ "PCM", diff --git a/tests/play_pull.js b/tests/play_pull.js deleted file mode 100644 index b7e3745..0000000 --- a/tests/play_pull.js +++ /dev/null @@ -1,27 +0,0 @@ -var test = require('tape') - -var AudioBuffer = require('audio-buffer') -var LenaBuffer = require('audio-lena/buffer') -var pull = require('pull-stream') -var AudioSpeaker = require('../pull') - -test('play pull stream audio', function(t) { - var buf = new AudioBuffer(1, LenaBuffer) - - function input () { - return function (end, callback) { - var plays = 0; - - if (plays > 1 || end) { - t.pass('Output successful.') - t.end() - return callback(end) - } - - plays++ - return callback(null, buf) - } - } - - pull(input(), AudioSpeaker()) -}) diff --git a/tests/play_sine.js b/tests/play_sine.js deleted file mode 100644 index 7443081..0000000 --- a/tests/play_sine.js +++ /dev/null @@ -1,63 +0,0 @@ - -/** - * Copied from node-speaker - * https://github.com/TooTallNate/node-speaker/blob/master/examples/sine.js - */ - - // TODO: This can be updated to node v4 and higher. - -var Readable = require('stream').Readable; -var Speaker = require('../stream'); - -// node v0.8.x compat -if (!Readable) Readable = require('readable-stream/readable'); - -// the frequency to play -var freq = parseFloat(process.argv[2], 10) || 440.0; // Concert A, default tone - -// seconds worth of audio data to generate before emitting "end" -var duration = parseFloat(process.argv[3], 10) || 2.0; - -console.log('Generating a %dhz sine wave for %d seconds', freq, duration); - -// A SineWaveGenerator readable stream -var sine = new Readable(); -sine.bitDepth = 16; -sine.channels = 2; -sine.sampleRate = 44100; -sine.samplesGenerated = 0; -sine._read = read; - -// create a SineWaveGenerator instance and pipe it to the speaker -sine.pipe(new Speaker()); - -// the Readable "_read()" callback function -function read (n) { - var sampleSize = this.bitDepth / 8; - var blockAlign = sampleSize * this.channels; - var numSamples = n / blockAlign | 0; - var buf = new Buffer(numSamples * blockAlign); - var amplitude = 32760; // Max amplitude for 16-bit audio - - // the "angle" used in the function, adjusted for the number of - // channels and sample rate. This value is like the period of the wave. - var t = (Math.PI * 2 * freq) / this.sampleRate; - - for (var i = 0; i < numSamples; i++) { - // fill with a simple sine wave at max amplitude - for (var channel = 0; channel < this.channels; channel++) { - var s = this.samplesGenerated + i; - var val = Math.round(amplitude * Math.sin(t * s)); // sine wave - var offset = (i * sampleSize * this.channels) + (channel * sampleSize); - buf['writeInt' + this.bitDepth + 'LE'](val, offset); - } - } - - this.push(buf); - - this.samplesGenerated += numSamples; - if (this.samplesGenerated >= this.sampleRate * duration) { - // after generating "duration" second of audio, emit "end" - this.push(null); - } -} diff --git a/tests/play_stream.js b/tests/play_stream.js deleted file mode 100644 index bd25202..0000000 --- a/tests/play_stream.js +++ /dev/null @@ -1,23 +0,0 @@ -var test = require('tape') - -var AudioBuffer = require('audio-buffer') -var LenaBuffer = require('audio-lena/buffer') -var AudioSpeaker = require('../stream') -var AudioThrough = require('audio-through') - -test('play node stream audio', function(t) { - var buf = new AudioBuffer(1, LenaBuffer) - var Speaker = new AudioSpeaker() - - var through = new AudioThrough(function (buffer) { - return through.count > 1 ? through.end().on('finish', finish()) : buf - - function finish () { - Speaker.end(true) - t.pass('Output successful.') - t.end() - } - }) - - through.pipe(Speaker) -}) From f4c8cf1542f8663f362854e61c6f3fd9a78f866e Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 21 Jun 2017 16:36:31 +1200 Subject: [PATCH 66/96] Make improvement to test ending --- package.json | 1 - tests/play_once.js | 3 ++- tests/play_twice.js | 21 --------------------- 3 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 tests/play_twice.js diff --git a/package.json b/package.json index 2e35ba6..617b339 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "scripts": { "test": "tape tests/check.js", "test:play": "tape tests/play_once.js", - "test:play_twice": "tape tests/play_twice.js", "lint": "eslint *.js --ignore-pattern test*" }, "repository": { diff --git a/tests/play_once.js b/tests/play_once.js index e27c9bd..8322d1f 100644 --- a/tests/play_once.js +++ b/tests/play_once.js @@ -14,8 +14,9 @@ test('play audio once test', function (t) { } else { speaker.end(true, (err) => { err ? t.error(err) : t.pass('Output successful.') - t.end() }) } }) + + t.end() }) diff --git a/tests/play_twice.js b/tests/play_twice.js deleted file mode 100644 index d107a6c..0000000 --- a/tests/play_twice.js +++ /dev/null @@ -1,21 +0,0 @@ -var test = require('tape') - -var AudioBuffer = require('audio-buffer') -var LenaBuffer = require('audio-lena/buffer') -var AudioSpeaker = require('../index') - -test('play audio twice test', function(t) { - var Speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) - var buf = new AudioBuffer(1, LenaBuffer) - - Speaker(buf, function (err, written) { - err ? t.error(err, 'Write callback caught an unexpected error.') : t.pass('Test wrote ' + buf.length +' bytes of audio-lena.') - Speaker(buf, function (err, done) { - err ? t.error(err, 'Write callback caught an unexpected error.') : t.pass('Test wrote ' + (buf.length * 2) +' bytes of audio-lena.') - Speaker.end(false, (err) => { - err ? t.error(err) : t.pass('Output successful.') - t.end() - }) - }) - }) -}) From 57342ef4da9bb073700a4d31dce6303227a65b9d Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 21 Jun 2017 17:26:50 +1200 Subject: [PATCH 67/96] Add sine test --- package.json | 3 +- tests/cases.js | 159 --------------------------- tests/{play_once.js => play_lena.js} | 2 +- tests/play_sine.js | 30 +++++ 4 files changed, 33 insertions(+), 161 deletions(-) delete mode 100644 tests/cases.js rename tests/{play_once.js => play_lena.js} (92%) create mode 100644 tests/play_sine.js diff --git a/package.json b/package.json index 617b339..61d1546 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Output PCM data to a device or library.", "scripts": { "test": "tape tests/check.js", - "test:play": "tape tests/play_once.js", + "test:lena": "tape tests/play_lena.js", + "test:sine": "tape tests/play_sine.js", "lint": "eslint *.js --ignore-pattern test*" }, "repository": { diff --git a/tests/cases.js b/tests/cases.js deleted file mode 100644 index 59a5dc9..0000000 --- a/tests/cases.js +++ /dev/null @@ -1,159 +0,0 @@ -'use strict'; - -var Speaker = require('../stream'); -var Generator = require('audio-generator/stream'); -var Generate = require('audio-generator/index'); -var Readable = require('stream').Readable; -var util = require('audio-buffer-utils'); -var pcm = require('pcm-util'); -var Through = require('audio-through'); -Through.log = true; -var Volume = require('pcm-volume'); -var test = require('tape') -var SpeakerWriter = require('../index'); -var pull = require('pull-stream'); -var PullSpeaker = require('../pull'); -var pullGenerator = require('audio-generator/pull'); - - - -test('Pure function', function (t) { - let generate = Generate(t => { - return Math.sin(t * Math.PI * 2 * 440); - }, 1); - - let write = SpeakerWriter(); - - (function loop (err) { - if (err) return write(null); - write(generate(), loop) - })(); - - setTimeout(() => { - write(null); - t.end(); - }, 200); -}); - -// test('Pull stream', function (t) { -// let out = PullSpeaker(); - -// pull( -// pullGenerator(time => 2 * time * 440 - 1, {frequency: 440}), -// out -// ); - -// setTimeout(() => { -// out.abort(); -// t.end(); -// }, 500); -// }); - -// test('Cleanness of wave', function (t) { -// Through(function (buffer) { -// var self = this; -// util.fill(buffer, function (sample, idx, channel) { -// return Math.sin(Math.PI * 2 * (self.count + idx) * 440 / 44100); -// }); - -// if (this.time > 1) return this.end(); - -// return buffer; -// }) -// .pipe(Speaker()); -// // .pipe(WAASteam(context.destination)); -// t.end(); -// }); - -// test('Feed audio-through', function (t) { -// Generator({ -// generate: function (time) { -// return [ -// Math.sin(Math.PI * 2 * time * 538 ) / 5, -// Math.sin(Math.PI * 2 * time * 542 ) / 5 -// // Math.random() -// ] -// }, -// duration: .4 -// }).pipe(Speaker()); - -// t.end() -// }); - -// test('Feed raw pcm', function (t) { -// var count = 0; -// Readable({ -// read: function (size) { -// var abuf = util.create(2, 1024, 44100); - -// //EGG: swap ch & i and hear wonderful sfx -// util.fill(abuf, function (v, i, ch) { -// v = Math.sin(Math.PI * 2 * ((count + i)/44100) * (738 + ch*2) ) / 5; -// return v; -// }); - -// count += 1024; - -// if (count > 1e4 ) return this.push(null); - -// let buf = pcm.toBuffer(abuf); - -// this.push(buf); -// } -// }) -// .pipe(Speaker({ -// channels: 2 -// })); - -// t.end() -// }); - -// //FIXME: use transform stream here to send floats data to speaker -// test.skip('Feed custom pcm', function (t) { -// var count = 0; -// Readable({ -// // objectMode: 1, -// read: function (size) { -// var abuf = util.create(2, 1024, 44100); - -// util.fill(abuf, function (v, i, ch) { -// return Math.sin(Math.PI * 2 * ((count + i)/44100) * (938 + ch*2) ); -// }); - -// count += 1024; - -// if (count > 1e4 ) return this.push(null); - -// let buf = pcm.toBuffer(abuf, { -// float: true -// }); - -// this.push(buf); -// } -// }).pipe(Speaker({ -// channels: 2, - -// //EGG: comment this and hear wonderful sfx -// float: true -// })); - -// t.end() -// }); - -// test.skip('Feed random buffer size'); - -// test('Volume case', function (t) { -// Generator({ -// generate: function (time) { -// return [ -// Math.sin(Math.PI * 2 * time * 1038 ) / 5, -// Math.sin(Math.PI * 2 * time * 1042 ) / 5 -// ]; -// }, -// duration: 1 -// }) -// .pipe(Volume(5)) -// .pipe(Speaker()); - -// t.end() -// }); diff --git a/tests/play_once.js b/tests/play_lena.js similarity index 92% rename from tests/play_once.js rename to tests/play_lena.js index 8322d1f..e41b98d 100644 --- a/tests/play_once.js +++ b/tests/play_lena.js @@ -4,7 +4,7 @@ var AudioBuffer = require('audio-buffer') var LenaBuffer = require('audio-lena/buffer') var AudioSpeaker = require('../index') -test('play audio once test', function (t) { +test('play audio once test', t => { var speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = new AudioBuffer(1, LenaBuffer) diff --git a/tests/play_sine.js b/tests/play_sine.js new file mode 100644 index 0000000..840e0aa --- /dev/null +++ b/tests/play_sine.js @@ -0,0 +1,30 @@ +var test = require('tape') + +var AudioGenerator = require('audio-generator/index') +var AudioSpeaker = require('../index') + +test('play sine for 4 seconds', t => { + var generate = AudioGenerator(time => { + return Math.sin(Math.PI * 2 * time * 500) + }, { duration: 4 }) + + var write = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }); + + setTimeout(() => { + write.end(false, (err) => { + err ? t.error(err) : t.pass('Output successful.') + }) + }, 4000); + + (function loop (err, chunk) { + if (err || chunk < 1) { + return + } else { + write(generate(), (err, chunk) => { + loop(err, chunk) + }) + } + })(); + + t.end() +}) From 7db3a0cae18a82a194189155dd099dbcccbf8e6a Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Wed, 21 Jun 2017 17:45:14 +1200 Subject: [PATCH 68/96] Improve auto flush and add auto flush test --- node.js | 2 +- package.json | 1 + tests/play_lena_auto.js | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/play_lena_auto.js diff --git a/node.js b/node.js index 077cabb..70f7080 100644 --- a/node.js +++ b/node.js @@ -121,7 +121,7 @@ function Speaker (opts) { next(null, remaining, callback) } else { debug('Finished writing chunk.') - if (options.autoFlush && remaining.length < 1) { + if (options.autoFlush && remaining.length < options.chunkSize) { debug('Flushing the audio output.') binding.flush(options.handler, function (success) { if (success != 1) { diff --git a/package.json b/package.json index 61d1546..7713cc1 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "test": "tape tests/check.js", "test:lena": "tape tests/play_lena.js", + "test:lena_auto": "tape tests/play_lena_auto.js", "test:sine": "tape tests/play_sine.js", "lint": "eslint *.js --ignore-pattern test*" }, diff --git a/tests/play_lena_auto.js b/tests/play_lena_auto.js new file mode 100644 index 0000000..09ce070 --- /dev/null +++ b/tests/play_lena_auto.js @@ -0,0 +1,22 @@ +var test = require('tape') + +var AudioBuffer = require('audio-buffer') +var LenaBuffer = require('audio-lena/buffer') +var AudioSpeaker = require('../index') + +test('play audio once test', t => { + var speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) + var buf = new AudioBuffer(1, LenaBuffer) + + speaker(buf, (err, chunk) => { + if (err || chunk === true) { + t.error(err, 'Write callback caught an unexpected error.') + } else { + speaker.end(false, (err) => { + err ? t.error(err) : t.pass('Output successful.') + }) + } + }) + + t.end() +}) From 67706d64f3fd40b9c8f9a0f476a9c2171dd3a04e Mon Sep 17 00:00:00 2001 From: connorhartley Date: Thu, 22 Jun 2017 09:46:47 +1200 Subject: [PATCH 69/96] Improve example in readme --- readme.md | 17 +++++++++++------ tests/play_sine.js | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/readme.md b/readme.md index b37a61f..6510448 100644 --- a/readme.md +++ b/readme.md @@ -40,12 +40,17 @@ var speaker = require('audio-speaker') var generator = require('audio-generator') var write = speaker({ autoFlush: true }) -var input = generator(t => Math.sin(t * Math.PI * 2 * 440)) - -(function loop (err, buf) { - var buffer = input() - write(buffer, loop) -}) +var generate = generator(t => Math.sin(t * Math.PI * 2 * 440)) + +(function loop (err, chunk) { + if (err || chunk < 1) { + return + } else { + write(generate(), (err, chunk) => { + loop(err, chunk) + }) + } +})(); ``` #### Also see diff --git a/tests/play_sine.js b/tests/play_sine.js index 840e0aa..dad624f 100644 --- a/tests/play_sine.js +++ b/tests/play_sine.js @@ -14,7 +14,7 @@ test('play sine for 4 seconds', t => { write.end(false, (err) => { err ? t.error(err) : t.pass('Output successful.') }) - }, 4000); + }, 4000); (function loop (err, chunk) { if (err || chunk < 1) { From da39399c1bdc342b41df305e143f23ab5ac7558e Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 21 Jun 2017 18:01:57 -0400 Subject: [PATCH 70/96] Update pcm-util --- node.js | 4 ++-- package.json | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/node.js b/node.js index 70f7080..8adeded 100644 --- a/node.js +++ b/node.js @@ -106,8 +106,8 @@ function Speaker (opts) { if (options.handler) { options._busy = true - var chunkBuf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, options) : chunk || new Buffer(0) - var remainderBuf = isAudioBuffer(remainder) ? pcm.toBuffer(remainder, options) : remainder || new Buffer(0) + var chunkBuf = isAudioBuffer(chunk) ? Buffer.from(pcm.toArrayBuffer(chunk, options)) : chunk || new Buffer(0) + var remainderBuf = isAudioBuffer(remainder) ? Buffer.from(pcm.toArrayBuffer(remainder, options)) : remainder || new Buffer(0) var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) diff --git a/package.json b/package.json index 7713cc1..7486c89 100644 --- a/package.json +++ b/package.json @@ -32,13 +32,14 @@ }, "homepage": "https://github.com/audiojs/audio-speaker#readme", "dependencies": { - "audio-buffer": "^2.4.5", + "audio-context": "^1.0.1", "audio-sink": "^1.1.6", "debug": "^2.2.0", "is-audio-buffer": "^1.0.1", "is-browser": "^2.0.1", "object-assign": "^4.1.0", - "pcm-util": "^2.0.3" + "pcm-util": "^2.1.0", + "web-audio-write": "^1.0.0" }, "devDependencies": { "audio-buffer-utils": "^3.1.2", @@ -47,7 +48,7 @@ "pcm-util": "^2.0.3", "pcm-volume": "^1.0.0", "pull-stream": "^3.5.0", - "tape": "^4.6.2" + "tape": "^4.6.3" }, "optionalDependencies": { "audio-mpg123": "^1.2.3" From 8321ed8a191f968814571af2bbd6acb5b8ca660c Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 21 Jun 2017 18:07:04 -0400 Subject: [PATCH 71/96] Update test/deps --- package.json | 8 +++----- tests/play_lena.js | 6 +++--- tests/play_lena_auto.js | 6 +++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 7486c89..40c29e4 100644 --- a/package.json +++ b/package.json @@ -38,14 +38,12 @@ "is-audio-buffer": "^1.0.1", "is-browser": "^2.0.1", "object-assign": "^4.1.0", - "pcm-util": "^2.1.0", + "pcm-util": "^3.0.0", "web-audio-write": "^1.0.0" }, "devDependencies": { - "audio-buffer-utils": "^3.1.2", - "audio-generator": "^2.1.1", - "audio-lena": "^1.1.0", - "pcm-util": "^2.0.3", + "audio-buffer-utils": "^5.0.1", + "audio-lena": "^2.1.0", "pcm-volume": "^1.0.0", "pull-stream": "^3.5.0", "tape": "^4.6.3" diff --git a/tests/play_lena.js b/tests/play_lena.js index e41b98d..2f05d4b 100644 --- a/tests/play_lena.js +++ b/tests/play_lena.js @@ -1,12 +1,12 @@ var test = require('tape') -var AudioBuffer = require('audio-buffer') -var LenaBuffer = require('audio-lena/buffer') +var LenaBuffer = require('audio-lena/raw') var AudioSpeaker = require('../index') +var util = require('audio-buffer-utils') test('play audio once test', t => { var speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) - var buf = new AudioBuffer(1, LenaBuffer) + var buf = util.create(LenaBuffer) speaker(buf, (err, chunk) => { if (err || chunk === true) { diff --git a/tests/play_lena_auto.js b/tests/play_lena_auto.js index 09ce070..6d004d4 100644 --- a/tests/play_lena_auto.js +++ b/tests/play_lena_auto.js @@ -1,12 +1,12 @@ var test = require('tape') -var AudioBuffer = require('audio-buffer') -var LenaBuffer = require('audio-lena/buffer') +var util = require('audio-buffer-utils') +var LenaBuffer = require('audio-lena/raw') var AudioSpeaker = require('../index') test('play audio once test', t => { var speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) - var buf = new AudioBuffer(1, LenaBuffer) + var buf = util.create(LenaBuffer) speaker(buf, (err, chunk) => { if (err || chunk === true) { From 944f25499e777e4082583700fbbef9b326becc05 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 21 Jun 2017 18:12:48 -0400 Subject: [PATCH 72/96] Add browser version & test --- browser.js | 44 +++++--------------------------------------- package.json | 1 + tests/index.js | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 39 deletions(-) create mode 100644 tests/index.js diff --git a/browser.js b/browser.js index 0eff6eb..4c82bc9 100644 --- a/browser.js +++ b/browser.js @@ -1,48 +1,14 @@ /** @module audio-speaker/browser */ 'use strict' -var Writer = require('web-audio-stream/writer') -var context = require('audio-context') -function noop () {} +var createWriter = require('web-audio-write') +var createContext = require('audio-context') -module.exports = BrowserSpeaker - -/** - * The BrowserSpeaker function initalizes and returns - * a {Module} webaudiostream to write to. - * - * @param {Object} opts options for the speaker - * @return {Module} webaudiostream for writing data to - * @module BrowserSpeaker - * @api public - */ -function BrowserSpeaker (opts) { +module.exports = function createSpeaker (opts) { opts = opts || {} - // TODO: Is this acceptable? Better way to handle this? - // Leave it up to the user? - if (!opts.samplesPerFrame) { - opts.samplesPerFrame = 2048 - } - - var ctx = opts.context || context - var dest = ctx.destination - var node = ctx.createScriptProcessor() - var _write = Writer(dest, opts) - - function write (data, cb) { - var start = context.currentTime - node.addEventListener('audioprocess', function ending (e, done) { - if (e.playbackTime - start > data.duration) { - node.removeEventListener('audioprocess', ending) - cb(null, opts.samplesPerFrame) - } - }) - - node.connect(dest) - return _write(data, noop) - } + var ctx = opts.context || createContext(opts) + var write = createWriter(ctx.destination, opts) - write.end = _write.end return write } diff --git a/package.json b/package.json index 40c29e4..72244c8 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ }, "devDependencies": { "audio-buffer-utils": "^5.0.1", + "audio-generator": "^2.1.2", "audio-lena": "^2.1.0", "pcm-volume": "^1.0.0", "pull-stream": "^3.5.0", diff --git a/tests/index.js b/tests/index.js new file mode 100644 index 0000000..6e70872 --- /dev/null +++ b/tests/index.js @@ -0,0 +1,14 @@ +'use strict' + +const t = require('tape') +const util = require('audio-buffer-utils') +const createSpeaker = require('../') + +t('output AudioBuffer', t => { + let speaker = createSpeaker() + + let buf = util.create(10000) + util.noise(buf) + + speaker(buf) +}) From bf6e77c1e376d32d8053f2ecd17509dc39e12352 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Fri, 23 Jun 2017 19:17:37 +1200 Subject: [PATCH 73/96] Clean up --- browser.js | 14 +- index.js | 2 + node.js | 48 +- package-lock.json | 1580 +++++++++++++++++ package.json | 14 +- readme.md | 2 +- tests/browser/browser_noise.js | 15 + tests/check.js | 2 + tests/index.js | 14 - tests/{play_lena.js => node/node_lena.js} | 8 +- .../node_lena_auto.js} | 4 +- tests/{play_sine.js => node/node_sine.js} | 4 +- yarn.lock | 978 ---------- 13 files changed, 1649 insertions(+), 1036 deletions(-) create mode 100644 package-lock.json create mode 100644 tests/browser/browser_noise.js delete mode 100644 tests/index.js rename tests/{play_lena.js => node/node_lena.js} (85%) rename tests/{play_lena_auto.js => node/node_lena_auto.js} (91%) rename tests/{play_sine.js => node/node_sine.js} (92%) delete mode 100644 yarn.lock diff --git a/browser.js b/browser.js index 4c82bc9..62be612 100644 --- a/browser.js +++ b/browser.js @@ -1,14 +1,20 @@ /** @module audio-speaker/browser */ 'use strict' -var createWriter = require('web-audio-write') +var objectAssign = require('object-assign') var createContext = require('audio-context') +var createWriter = require('web-audio-write') module.exports = function createSpeaker (opts) { - opts = opts || {} + var options = {} + + options = objectAssign({ + channels: 1, + sampleRate: 44100 + }, opts) - var ctx = opts.context || createContext(opts) - var write = createWriter(ctx.destination, opts) + var ctx = options.context || createContext(options) + var write = createWriter(ctx.destination, options) return write } diff --git a/index.js b/index.js index 389097d..0cdf380 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,5 @@ +'use strict' + module.exports = require('is-browser') ? require('./browser') diff --git a/node.js b/node.js index 8adeded..b2dddb6 100644 --- a/node.js +++ b/node.js @@ -1,14 +1,13 @@ /** @module audio-speaker/index */ - 'use strict' var os = require('os') -var objectAssign = require('object-assign') -var binding = require('audio-mpg123') var pcm = require('pcm-util') -var isAudioBuffer = require('is-audio-buffer') +var assert = require('assert') +var binding = require('audio-mpg123') +var objectAssign = require('object-assign') var audioSink = require('audio-sink/direct') -var debug = require('debug')('speaker') +var isAudioBuffer = require('is-audio-buffer') var endianess = 'function' == os.endianess ? os.endianess() : 'LE' @@ -24,7 +23,8 @@ module.exports = Speaker * @api public */ function Speaker (opts) { - debug('Speaker()') + assert(opts, 'Pass options into speaker') + var options = {} options = objectAssign({ @@ -58,17 +58,16 @@ function Speaker (opts) { if(!success) { throw new Error('Failed to create the audio handler.') } else { - debug('_create() audio handle successfully.') + assert(binding, 'Audio handler created') } }) if (options.handler !== null) { - debug('_start(%o)', Object.keys(options)) binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { if (!success) { throw new Error('Could not start the audio output with these properties.') } else { - debug('Created and started handler successfully.') + assert(options, 'Audio handler options applied') } }) } @@ -92,11 +91,10 @@ function Speaker (opts) { * @api public */ function write (chunk, callback) { - debug('write()') - if (options._closed) return debug('write() cannot be called after the speaker is closed.') + if (options._closed) return assert(chunk, 'Write cannot occur after the speaker is closed') if (chunk && options._busy) { - debug('write() cannot be called until the previous buffer has been written.') + assert(chunk, 'Write cannot occur until the previous chunk is processed') callback(new Error('Could not write chunk as the buffer was busy.'), 0) } @@ -114,21 +112,18 @@ function Speaker (opts) { var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) - binding.write(options.handler, output, output.length, onWrite) - - function onWrite (written) { + binding.write(options.handler, output, output.length, (written) => { if(!remaining.length < 1) { next(null, remaining, callback) } else { - debug('Finished writing chunk.') + assert(written, 'Finished writing chunk') if (options.autoFlush && remaining.length < options.chunkSize) { - debug('Flushing the audio output.') binding.flush(options.handler, function (success) { if (success != 1) { options._busy = false callback(new Error('Could not flush the audio output.'), written) } else { - debug('Flushed audio successfully.') + assert(chunk, 'Finished flushing chunk') options._busy = false callback(null, written) } @@ -138,14 +133,12 @@ function Speaker (opts) { callback(null, written) } } - } + }) } } } function sink (callback) { - debug('sink()') - return audioSink((data, callback) => { if (options._closed) return callback(true) setTimeout(callback, options.samplesPerFrame / options.sampleRate) @@ -164,16 +157,15 @@ function Speaker (opts) { * @api public */ function end (flush, callback) { - debug('end(%o)', flush) - if (options._closed) return debug('_end() was called more than once. Already ended.') + if (options._closed) return assert(flush, 'Closing the speaker cannot occur after the speaker is already closed') if (options.handler) { if (flush) { - debug('Flushing the audio output.') binding.flush(options.handler, function (success) { if (success != 1) { callback(new Error('Could not flush the audio output.')) } else { + assert(flush, 'Finished flushing chunk') return close(callback) } }) @@ -185,10 +177,14 @@ function Speaker (opts) { } function close (callback) { - debug('close()') binding.close(options.handler, (success) => { if (callback) { - success ? callback() : callback(new Error('Failed to close speaker.')) + if (success != 1) { + callback(new Error('Failed to close speaker.')) + } else { + assert(options.handler, 'Closed speaker') + callback() + } } }) options._closed = true diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..2b95bdd --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1580 @@ +{ + "name": "audio-speaker", + "version": "2.0.0-5", + "lockfileVersion": 1, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "optional": true + }, + "acorn": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=" + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "ansi-escapes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", + "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "aproba": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", + "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==", + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "optional": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "optional": true + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=" + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "optional": true + }, + "atob": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "dev": true + }, + "atob-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-1.0.0.tgz", + "integrity": "sha1-uI3KYAaSK5YglPdVaCa6sxxKKWs=", + "dev": true + }, + "audio-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/audio-buffer/-/audio-buffer-4.0.1.tgz", + "integrity": "sha1-YrYe7L/KplFHFQ0Y/kP3Z6yANLg=" + }, + "audio-buffer-list": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/audio-buffer-list/-/audio-buffer-list-3.2.1.tgz", + "integrity": "sha512-ledga5njMOlJMG/yifwqQvscho97IadzhddR7OyTvyIKzyqXsA8YMvC+yAd2B3EmzlIlJJHd4zbmQF3/xlLhcw==" + }, + "audio-buffer-utils": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/audio-buffer-utils/-/audio-buffer-utils-5.0.1.tgz", + "integrity": "sha1-5i2RAQo3Yg3W5Qx9nUQ4KH/afLI=" + }, + "audio-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/audio-context/-/audio-context-1.0.1.tgz", + "integrity": "sha1-zsTbis5u9KrL8Q7vCXekVxRo1Ks=" + }, + "audio-generator": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/audio-generator/-/audio-generator-2.1.2.tgz", + "integrity": "sha1-lEhPofavlHuNoDhi9NzuhLe81ak=", + "dev": true, + "dependencies": { + "audio-buffer": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/audio-buffer/-/audio-buffer-2.4.6.tgz", + "integrity": "sha1-L5e9srucpG0i07AdQzT0mSTromA=", + "dev": true + }, + "audio-buffer-utils": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/audio-buffer-utils/-/audio-buffer-utils-4.3.2.tgz", + "integrity": "sha1-1VX67Y1s7rEgYZ45+mkTdPIQM4A=", + "dev": true, + "dependencies": { + "audio-buffer": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/audio-buffer/-/audio-buffer-3.2.1.tgz", + "integrity": "sha1-y/8sFXf7CvxckjKQLVQ7L5bdQz0=", + "dev": true + } + } + }, + "audio-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/audio-context/-/audio-context-1.0.1.tgz", + "integrity": "sha1-zsTbis5u9KrL8Q7vCXekVxRo1Ks=", + "dev": true + }, + "pcm-util": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pcm-util/-/pcm-util-2.1.0.tgz", + "integrity": "sha1-UazkawngEX+5L2VPYy3LLtnIYGU=", + "dev": true, + "dependencies": { + "audio-buffer": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/audio-buffer/-/audio-buffer-3.2.1.tgz", + "integrity": "sha1-y/8sFXf7CvxckjKQLVQ7L5bdQz0=", + "dev": true + } + } + } + } + }, + "audio-lena": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/audio-lena/-/audio-lena-2.1.0.tgz", + "integrity": "sha1-lCuItva4a4uZgyXVSmltNbLfCt4=", + "dev": true + }, + "audio-mpg123": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/audio-mpg123/-/audio-mpg123-1.2.3.tgz", + "integrity": "sha1-rvNk1JQafv0HJ47QPkyXhiwGdOA=", + "optional": true + }, + "audio-sink": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/audio-sink/-/audio-sink-1.1.6.tgz", + "integrity": "sha1-4UVOsTeFIimNIXC3ywMsM/0faIU=" + }, + "audio-through": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/audio-through/-/audio-through-2.2.3.tgz", + "integrity": "sha1-FPyMN7YT0chwz67gS/RFTCiVn78=", + "dev": true, + "dependencies": { + "audio-buffer": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/audio-buffer/-/audio-buffer-3.2.1.tgz", + "integrity": "sha1-y/8sFXf7CvxckjKQLVQ7L5bdQz0=", + "dev": true + }, + "pcm-util": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pcm-util/-/pcm-util-2.1.0.tgz", + "integrity": "sha1-UazkawngEX+5L2VPYy3LLtnIYGU=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + } + } + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "optional": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "optional": true + }, + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=" + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=" + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=" + }, + "buffer-to-arraybuffer": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.4.tgz", + "integrity": "sha1-8+Xj9vJjLHHnzevnbtFxj61CHUw=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "optional": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true + }, + "circular-json": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", + "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=", + "dev": true + }, + "clamp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz", + "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ=" + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true + }, + "cli-width": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", + "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "optional": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + } + } + }, + "data-uri-regex": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/data-uri-regex/-/data-uri-regex-0.1.4.tgz", + "integrity": "sha1-Hh22yDl+yopI7NtVrRuSfsC7rC4=", + "dev": true + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=" + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "optional": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "optional": true + }, + "doctrine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", + "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "dev": true + }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true + }, + "es-abstract": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz", + "integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=", + "dev": true + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.0.0.tgz", + "integrity": "sha1-cnfAFDf99B3M0WjVqg5Jt1yh8mA=", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true + }, + "espree": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", + "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", + "dev": true + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "optional": true + }, + "external-editor": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.4.tgz", + "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", + "dev": true + }, + "extsprintf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true + }, + "flat-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", + "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", + "dev": true + }, + "for-each": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", + "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", + "dev": true + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "optional": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "optional": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=" + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "optional": true + }, + "function-bind": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", + "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "optional": true + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==" + }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=" + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "optional": true + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "optional": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "optional": true + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "optional": true + }, + "iconv-lite": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", + "dev": true + }, + "ignore": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", + "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "optional": true + }, + "inquirer": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.1.1.tgz", + "integrity": "sha512-H50sHQwgvvaTBd3HpKMVtL/u6LoHDvYym51gd7bGQe/+9HkCE+J0/3N5FJLfd6O6oz44hHewC2Pc2LodzWVafQ==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz", + "integrity": "sha1-Y1xUNsxypuDDh87KJ41OLuxSaH4=", + "dev": true + } + } + }, + "is-audio-buffer": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/is-audio-buffer/-/is-audio-buffer-1.0.11.tgz", + "integrity": "sha1-Hs443PML9U3aNvIKRS63J9I96zY=" + }, + "is-browser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.0.1.tgz", + "integrity": "sha1-i/C695mpxi/Z3lvO5M8zl8PnUpo=" + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-data-uri": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-data-uri/-/is-data-uri-0.1.0.tgz", + "integrity": "sha1-Ru5ntjwYwf+gvU36ss0sgccoI38=", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=" + }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", + "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "optional": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "optional": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "js-yaml": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz", + "integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jschardet": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.4.2.tgz", + "integrity": "sha1-KqEH8UKvQSHRRWWdRPUIMJYeaZo=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", + "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "mime-db": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" + }, + "mime-types": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=" + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==" + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.2.1.tgz", + "integrity": "sha1-1oaT9rNLtB1mvGizpPne/HnXFJs=", + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negative-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/negative-index/-/negative-index-1.0.2.tgz", + "integrity": "sha1-uws0n53oCHkybPpUxW+2tnykeI0=" + }, + "node-pre-gyp": { + "version": "0.6.36", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz", + "integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=", + "optional": true + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "optional": true + }, + "npmlog": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", + "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", + "optional": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.2.2.tgz", + "integrity": "sha1-yCEV5PzIiK6hTWTCLk8X9qcNXlo=", + "dev": true + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "optional": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "pcm-util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pcm-util/-/pcm-util-3.0.0.tgz", + "integrity": "sha1-L33/SBOidIHZlffSwY2hdnj6MDw=" + }, + "pcm-volume": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pcm-volume/-/pcm-volume-1.0.0.tgz", + "integrity": "sha1-6qhRyUloq24ULOLhKVNwi+Sn8MA=", + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "optional": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true + }, + "pluralize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz", + "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "optional": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "optional": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "optional": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.2.tgz", + "integrity": "sha1-WgTfBeT1f+Pw3Gj90R3FyXx+b00=", + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "optional": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=" + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "optional": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + } + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=" + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.1.tgz", + "integrity": "sha1-qBFsEz+sLGH0pCCrbN9cTWHw5DU=", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz", + "integrity": "sha1-Y1xUNsxypuDDh87KJ41OLuxSaH4=", + "dev": true + } + } + }, + "tape": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.6.3.tgz", + "integrity": "sha1-Y353WB6ass4XV36b1M5PV1gG2LY=", + "dev": true, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=" + }, + "tar-pack": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", + "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", + "optional": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", + "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", + "dev": true + }, + "to-array-buffer": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/to-array-buffer/-/to-array-buffer-1.2.4.tgz", + "integrity": "sha1-fv3DGUpaDSsLqT+6nT7cM6EllHM=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "optional": true + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "optional": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typedarray-methods": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typedarray-methods/-/typedarray-methods-1.0.1.tgz", + "integrity": "sha512-fstWAa225OZ856/4npMqgJP6U1U3vTWnqkn9wokZXzME9pORW9dV8u/v1VRGpo584udKMvCIYlNXzKoIb+UUGg==", + "dev": true + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", + "optional": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "optional": true + }, + "verror": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "optional": true + }, + "web-audio-write": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/web-audio-write/-/web-audio-write-1.1.0.tgz", + "integrity": "sha1-z4YBU1HhfdXSYWQNEpNN4UIu7E0=" + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } +} diff --git a/package.json b/package.json index 72244c8..2f915a9 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,7 @@ "description": "Output PCM data to a device or library.", "scripts": { "test": "tape tests/check.js", - "test:lena": "tape tests/play_lena.js", - "test:lena_auto": "tape tests/play_lena_auto.js", - "test:sine": "tape tests/play_sine.js", + "test:node": "tape tests/node/**/*.js", "lint": "eslint *.js --ignore-pattern test*" }, "repository": { @@ -32,21 +30,21 @@ }, "homepage": "https://github.com/audiojs/audio-speaker#readme", "dependencies": { + "assert": "^1.4.1", "audio-context": "^1.0.1", "audio-sink": "^1.1.6", - "debug": "^2.2.0", - "is-audio-buffer": "^1.0.1", + "is-audio-buffer": "^1.0.11", "is-browser": "^2.0.1", - "object-assign": "^4.1.0", + "object-assign": "^4.1.1", "pcm-util": "^3.0.0", - "web-audio-write": "^1.0.0" + "web-audio-write": "^1.1.0" }, "devDependencies": { "audio-buffer-utils": "^5.0.1", "audio-generator": "^2.1.2", "audio-lena": "^2.1.0", + "eslint": "^4.0.0", "pcm-volume": "^1.0.0", - "pull-stream": "^3.5.0", "tape": "^4.6.3" }, "optionalDependencies": { diff --git a/readme.md b/readme.md index 6510448..5a98cdb 100644 --- a/readme.md +++ b/readme.md @@ -15,7 +15,7 @@ Browser: `npm install audio-speaker --no-optional` Accepts options in main function: - - channels (default 2) + - channels (default 1) - sampleRate (default 44100) - endianess (default 'LE') - bitDepth (default 16) diff --git a/tests/browser/browser_noise.js b/tests/browser/browser_noise.js new file mode 100644 index 0000000..f1211f3 --- /dev/null +++ b/tests/browser/browser_noise.js @@ -0,0 +1,15 @@ +'use strict' + +var test = require('tape') + +var util = require('audio-buffer-utils') +var AudioSpeaker = require('../../browser') + +test('output audio buffer', t => { + var write = AudioSpeaker() + + let buffer = util.create(10000) + util.noise(buffer) + + write(buffer) +}) diff --git a/tests/check.js b/tests/check.js index f2eef1e..4faf318 100644 --- a/tests/check.js +++ b/tests/check.js @@ -1,3 +1,5 @@ +'use strict' + var test = require('tape') test('check for build output', function(t) { diff --git a/tests/index.js b/tests/index.js deleted file mode 100644 index 6e70872..0000000 --- a/tests/index.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict' - -const t = require('tape') -const util = require('audio-buffer-utils') -const createSpeaker = require('../') - -t('output AudioBuffer', t => { - let speaker = createSpeaker() - - let buf = util.create(10000) - util.noise(buf) - - speaker(buf) -}) diff --git a/tests/play_lena.js b/tests/node/node_lena.js similarity index 85% rename from tests/play_lena.js rename to tests/node/node_lena.js index 2f05d4b..c52f839 100644 --- a/tests/play_lena.js +++ b/tests/node/node_lena.js @@ -1,8 +1,10 @@ -var test = require('tape') +'use strict' + +var test = require('tape').only -var LenaBuffer = require('audio-lena/raw') -var AudioSpeaker = require('../index') var util = require('audio-buffer-utils') +var LenaBuffer = require('audio-lena/raw') +var AudioSpeaker = require('../../node') test('play audio once test', t => { var speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) diff --git a/tests/play_lena_auto.js b/tests/node/node_lena_auto.js similarity index 91% rename from tests/play_lena_auto.js rename to tests/node/node_lena_auto.js index 6d004d4..c66fa71 100644 --- a/tests/play_lena_auto.js +++ b/tests/node/node_lena_auto.js @@ -1,8 +1,10 @@ +'use strict' + var test = require('tape') var util = require('audio-buffer-utils') var LenaBuffer = require('audio-lena/raw') -var AudioSpeaker = require('../index') +var AudioSpeaker = require('../../node') test('play audio once test', t => { var speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) diff --git a/tests/play_sine.js b/tests/node/node_sine.js similarity index 92% rename from tests/play_sine.js rename to tests/node/node_sine.js index dad624f..96a8665 100644 --- a/tests/play_sine.js +++ b/tests/node/node_sine.js @@ -1,7 +1,9 @@ +'use strict' + var test = require('tape') var AudioGenerator = require('audio-generator/index') -var AudioSpeaker = require('../index') +var AudioSpeaker = require('../../node') test('play sine for 4 seconds', t => { var generate = AudioGenerator(time => { diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index ec7e975..0000000 --- a/yarn.lock +++ /dev/null @@ -1,978 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -abbrev@1: - version "1.0.9" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -aproba@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.0.4.tgz#2713680775e7614c8ba186c065d4e2e52d1072c0" - -are-we-there-yet@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz#80e470e95a084794fe1899262c5667c6e88de1b3" - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.0 || ^1.1.13" - -array-find@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-find/-/array-find-1.0.0.tgz#6c8e286d11ed768327f8e62ecee87353ca3e78b8" - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - -assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - -atob@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" - -audio-buffer-utils@^3.0.0, audio-buffer-utils@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/audio-buffer-utils/-/audio-buffer-utils-3.1.2.tgz#1a2bf28ca1e1ee94381a6d4497137d078ce8cb17" - dependencies: - audio-buffer "^2.0.0" - is-audio-buffer "^1.0.0" - is-browser "^2.0.1" - typedarray-methods "^1.0.0" - -audio-buffer@^2.0.0, audio-buffer@^2.1.3, audio-buffer@^2.4.5: - version "2.4.5" - resolved "https://registry.yarnpkg.com/audio-buffer/-/audio-buffer-2.4.5.tgz#291ea5260f5006c077b69aaae764044d59be66f7" - dependencies: - audio-context latest - buffer-to-arraybuffer latest - is-audio-buffer "^1.0.1" - is-browser "^2.0.1" - is-buffer "^1.1.0" - -audio-context@^0.1.0, audio-context@latest: - version "0.1.0" - resolved "https://registry.yarnpkg.com/audio-context/-/audio-context-0.1.0.tgz#116ee83d566e10e7e845f29d9b1e1bc2ea3520d2" - dependencies: - global "~4.2.1" - -audio-generator@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/audio-generator/-/audio-generator-2.1.1.tgz#9ec196cd868dd2a6e17d2418504ff5a4a473d02b" - dependencies: - audio-buffer "^2.4.5" - audio-buffer-utils "^3.1.2" - audio-through "^2.0.1" - inherits "^2.0.1" - pcm-util "^2.0.3" - xtend "^4.0.0" - -audio-lena@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/audio-lena/-/audio-lena-1.1.0.tgz#ee6ecab89582d3e3b0ac1ef941afe3febf92166f" - dependencies: - atob "^2.0.3" - -audio-mpg123@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/audio-mpg123/-/audio-mpg123-1.2.3.tgz#aef364d4941a7efd07278ed03e4c97862c0674e0" - dependencies: - nan "2.2.1" - node-pre-gyp "^0.6.31" - -audio-sink@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/audio-sink/-/audio-sink-1.1.6.tgz#e1454eb1378522298d2170b7cb032c33fd1f6885" - dependencies: - inherits "^2.0.1" - xtend "^4.0.1" - -audio-through@^2.0.1, audio-through@^2.1.9: - version "2.1.9" - resolved "https://registry.yarnpkg.com/audio-through/-/audio-through-2.1.9.tgz#6a0385f36868c433a471744a15fb6183daab9ce6" - dependencies: - array-find "^1.0.0" - audio-buffer "^2.1.3" - audio-context "^0.1.0" - get-uid "^1.0.1" - inherits "^2.0.1" - is-audio-buffer "^1.0.1" - is-promise "^2.1.0" - pcm-util "^2.0.1" - performance-now "^0.2.0" - xtend "^4.0.1" - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - -aws4@^1.2.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755" - -balanced-match@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" - -bcrypt-pbkdf@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz#3ca76b85241c7170bf7d9703e7b9aa74630040d4" - dependencies: - tweetnacl "^0.14.3" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - dependencies: - inherits "~2.0.0" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - -brace-expansion@^1.0.0: - version "1.1.6" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" - dependencies: - balanced-match "^0.4.1" - concat-map "0.0.1" - -buffer-shims@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" - -buffer-to-arraybuffer@latest: - version "0.0.4" - resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.4.tgz#f3e5e3f6f2632c71e7cdebe76ed1718fad421d4c" - -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - -chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - dependencies: - delayed-stream "~1.0.0" - -commander@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - dependencies: - graceful-readlink ">= 1.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - dependencies: - assert-plus "^1.0.0" - -debug@^2.2.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b" - dependencies: - ms "0.7.2" - -debug@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - dependencies: - ms "0.7.1" - -deep-equal@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - -deep-extend@~0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253" - -define-properties@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" - dependencies: - foreach "^2.0.5" - object-keys "^1.0.8" - -defined@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - -dom-walk@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - dependencies: - jsbn "~0.1.0" - -es-abstract@^1.5.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c" - dependencies: - es-to-primitive "^1.1.1" - function-bind "^1.1.0" - is-callable "^1.1.3" - is-regex "^1.0.3" - -es-to-primitive@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" - dependencies: - is-callable "^1.1.1" - is-date-object "^1.0.1" - is-symbol "^1.0.1" - -escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -extend@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" - -extsprintf@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" - -for-each@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.2.tgz#2c40450b9348e97f281322593ba96704b9abd4d4" - dependencies: - is-function "~1.0.0" - -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -form-data@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -fstream-ignore@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" - dependencies: - fstream "^1.0.0" - inherits "2" - minimatch "^3.0.0" - -fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.10.tgz#604e8a92fe26ffd9f6fae30399d4984e1ab22822" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -function-bind@^1.0.2, function-bind@^1.1.0, function-bind@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" - -gauge@~2.7.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.2.tgz#15cecc31b02d05345a5d6b0e171cdb3ad2307774" - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - supports-color "^0.2.0" - wide-align "^1.1.0" - -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - -get-uid@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/get-uid/-/get-uid-1.0.1.tgz#ac6d5695550cb6be371d5a79b0d968115f746a22" - -getpass@^0.1.1: - version "0.1.6" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" - dependencies: - assert-plus "^1.0.0" - -glob@^7.0.5, glob@~7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/global/-/global-4.2.1.tgz#c16801e9a47f0b0b847a156d419dc143b5a4e8b3" - dependencies: - min-document "^2.6.1" - process "~0.5.1" - -graceful-fs@^4.1.2: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - -has@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" - dependencies: - function-bind "^1.0.2" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -ini@~1.3.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" - -is-audio-buffer@^1.0.0, is-audio-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-audio-buffer/-/is-audio-buffer-1.0.1.tgz#a8317bc5f27198b5634701b06a01e5d8089b834d" - -is-browser@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-browser/-/is-browser-2.0.1.tgz#8bf0baf799a9c62fd9de5bcee4cf3397c3e7529a" - -is-buffer@^1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b" - -is-callable@^1.1.1, is-callable@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - dependencies: - number-is-nan "^1.0.0" - -is-function@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" - -is-my-json-valid@^2.12.4: - version "2.15.0" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - -is-regex@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.3.tgz#0d55182bddf9f2fde278220aec3a75642c908637" - -is-symbol@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -jodid25519@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" - dependencies: - jsbn "~0.1.0" - -jsbn@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - -jsprim@^1.2.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.3.1.tgz#2a7256f70412a29ee3670aaca625994c4dcff252" - dependencies: - extsprintf "1.0.2" - json-schema "0.2.3" - verror "1.3.6" - -mime-db@~1.26.0: - version "1.26.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.26.0.tgz#eaffcd0e4fc6935cf8134da246e2e6c35305adff" - -mime-types@^2.1.12, mime-types@~2.1.7: - version "2.1.14" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.14.tgz#f7ef7d97583fcaf3b7d282b6f8b5679dab1e94ee" - dependencies: - mime-db "~1.26.0" - -min-document@^2.6.1: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - dependencies: - dom-walk "^0.1.0" - -minimatch@^3.0.0, minimatch@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" - dependencies: - brace-expansion "^1.0.0" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@^1.2.0, minimist@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -"mkdirp@>=0.5 0", mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - -ms@0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" - -nan@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.2.1.tgz#d68693f6b34bb41d66bc68b3a4f9defc79d7149b" - -node-pre-gyp@^0.6.31: - version "0.6.32" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.32.tgz#fc452b376e7319b3d255f5f34853ef6fd8fe1fd5" - dependencies: - mkdirp "~0.5.1" - nopt "~3.0.6" - npmlog "^4.0.1" - rc "~1.1.6" - request "^2.79.0" - rimraf "~2.5.4" - semver "~5.3.0" - tar "~2.2.1" - tar-pack "~3.3.0" - -nopt@~3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - dependencies: - abbrev "1" - -npmlog@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f" - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.1" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -oauth-sign@~0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - -object-inspect@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.2.1.tgz#3b62226eb8f6d441751c7d8f22a20ff80ac9dc3f" - -object-keys@^1.0.8: - version "1.0.11" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -once@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" - dependencies: - wrappy "1" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -pcm-util@^2.0.1, pcm-util@^2.0.2, pcm-util@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/pcm-util/-/pcm-util-2.0.3.tgz#ce00a7dc663339b47f934b57a704a6c95716d1a7" - dependencies: - audio-buffer "^2.1.3" - is-audio-buffer "^1.0.1" - is-buffer "^1.1.0" - to-array-buffer "^1.0.0" - -pcm-volume@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pcm-volume/-/pcm-volume-1.0.0.tgz#eaa851c94968ab6e142ce2e12953708be4a7f0c0" - dependencies: - inherits "^2.0.1" - -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - -process@~0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - -pull-stream@^3.4.4, pull-stream@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.5.0.tgz#1ee5b6f76fd3b3a49a5afb6ded5c0320acb3cfc7" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -qs@~6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.0.tgz#f403b264f23bc01228c74131b407f18d5ea5d442" - -rc@~1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9" - dependencies: - deep-extend "~0.4.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~1.0.4" - -"readable-stream@^2.0.0 || ^1.1.13", readable-stream@~2.1.4: - version "2.1.5" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" - dependencies: - buffer-shims "^1.0.0" - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~0.10.x" - util-deprecate "~1.0.1" - -request@^2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - -resolve@~1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - -resumer@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - dependencies: - through "~2.3.4" - -rimraf@2, rimraf@~2.5.1, rimraf@~2.5.4: - version "2.5.4" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04" - dependencies: - glob "^7.0.5" - -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - -signal-exit@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - -sshpk@^1.7.0: - version "1.10.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.10.2.tgz#d5a804ce22695515638e798dbe23273de070a5fa" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jodid25519 "^1.0.0" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string.prototype.trim@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.0" - function-bind "^1.0.2" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -stringstream@~0.0.4: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-json-comments@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" - -supports-color@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -tape@^4.6.2: - version "4.6.3" - resolved "https://registry.yarnpkg.com/tape/-/tape-4.6.3.tgz#637e77581e9ab2ce17577e9bd4ce4f575806d8b6" - dependencies: - deep-equal "~1.0.1" - defined "~1.0.0" - for-each "~0.3.2" - function-bind "~1.1.0" - glob "~7.1.1" - has "~1.0.1" - inherits "~2.0.3" - minimist "~1.2.0" - object-inspect "~1.2.1" - resolve "~1.1.7" - resumer "~0.0.0" - string.prototype.trim "~1.1.2" - through "~2.3.8" - -tar-pack@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae" - dependencies: - debug "~2.2.0" - fstream "~1.0.10" - fstream-ignore "~1.0.5" - once "~1.3.3" - readable-stream "~2.1.4" - rimraf "~2.5.1" - tar "~2.2.1" - uid-number "~0.0.6" - -tar@~2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -through@~2.3.4, through@~2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -to-array-buffer@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/to-array-buffer/-/to-array-buffer-1.2.0.tgz#03361a76a85cebadd160ca17f6e1e2d567c611fc" - dependencies: - is-audio-buffer "^1.0.1" - -tough-cookie@~2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" - dependencies: - punycode "^1.4.1" - -tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - -typedarray-methods@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typedarray-methods/-/typedarray-methods-1.0.0.tgz#d656b078a9ff6134ed193794f8e55e158204ad0d" - -uid-number@~0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -uuid@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" - -verror@1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" - dependencies: - extsprintf "1.0.2" - -web-audio-stream@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/web-audio-stream/-/web-audio-stream-2.2.0.tgz#5975a1a69c4b12d23e49b1e921925c8c04c6314b" - dependencies: - audio-buffer-utils "^3.0.0" - audio-context "^0.1.0" - inherits "^2.0.1" - is-audio-buffer "^1.0.1" - is-plain-obj "^1.1.0" - pcm-util "^2.0.2" - pull-stream "^3.4.4" - xtend "^4.0.1" - -wide-align@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad" - dependencies: - string-width "^1.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -xtend@^4.0.0, xtend@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From c8a5d31a386f8a3c76dad1fe84f66f5cd44ee8fc Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Fri, 23 Jun 2017 21:58:48 +1200 Subject: [PATCH 74/96] Add callback for abandoned remaining chunks --- node.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/node.js b/node.js index b2dddb6..9de0a5a 100644 --- a/node.js +++ b/node.js @@ -134,6 +134,9 @@ function Speaker (opts) { } } }) + } else { + assert(chunk, 'Abandoning remaining chunks as the speaker has closed') + callback(new Error('Could not write remaining chunks as the speaker is closed.'), 0) } } } From 9f4adea9c9298d6161b8c1bde2a3d797a23909fa Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 24 Jun 2017 11:29:34 +1200 Subject: [PATCH 75/96] Fix speaker options assertion --- node.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node.js b/node.js index 9de0a5a..6959dcb 100644 --- a/node.js +++ b/node.js @@ -23,8 +23,6 @@ module.exports = Speaker * @api public */ function Speaker (opts) { - assert(opts, 'Pass options into speaker') - var options = {} options = objectAssign({ @@ -38,6 +36,8 @@ function Speaker (opts) { autoFlush: false }, opts) + assert(options, 'Options applied to speaker') + if (options.handler) { throw new Error('_create() was called more than once. Only one handler should exist.') } From a130cb2380ceb40955f4efcf7c0d2d9859a1401d Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 23 Jun 2017 19:29:55 -0400 Subject: [PATCH 76/96] Refactor tests --- index.js | 226 ++++++++++++++++++++++++++++++++- node.js | 223 -------------------------------- package.json | 7 +- test.js | 77 +++++++++++ tests/browser/browser_noise.js | 15 --- tests/check.js | 12 -- tests/node/node_lena.js | 24 ---- tests/node/node_lena_auto.js | 24 ---- tests/node/node_sine.js | 32 ----- 9 files changed, 301 insertions(+), 339 deletions(-) delete mode 100644 node.js create mode 100644 test.js delete mode 100644 tests/browser/browser_noise.js delete mode 100644 tests/check.js delete mode 100644 tests/node/node_lena.js delete mode 100644 tests/node/node_lena_auto.js delete mode 100644 tests/node/node_sine.js diff --git a/index.js b/index.js index 0cdf380..33531f2 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,224 @@ +/** @module audio-speaker/index */ 'use strict' -module.exports = - require('is-browser') - ? require('./browser') - : require('./node') +var os = require('os') +var pcm = require('pcm-util') +var assert = require('assert') +var binding = require('audio-mpg123') +var objectAssign = require('object-assign') +var audioSink = require('audio-sink/direct') +var isAudioBuffer = require('is-audio-buffer') + +var endianess = 'function' == os.endianess ? os.endianess() : 'LE' + +module.exports = Speaker + +/** + * The Speaker function initializes a new audio handler, + * then returns the write method to output audio to. + * + * @param {Object} opts options for the speaker + * @return {Function} write write audio from a buffer or audiobuffer + * @module Speaker + * @api public + */ +function Speaker (opts) { + var options = objectAssign({ + channels: 1, + float: false, + bitDepth: 16, + signed: true, + samplesPerFrame: 1024, + sampleRate: 44100, + endianess: endianess, + autoFlush: false + }, opts) + + if (options.handler) { + throw new Error('_create() was called more than once. Only one handler should exist.') + } + + options._closed = false + options._busy = false + + var format = Speaker.getFormat(options) + if (format === null) { + throw new Error('Invalid format options.') + } + + options.blockAlign = options.bitDepth / 8 * options.channels + + options.chunkSize = options.blockAlign * options.samplesPerFrame + + options.handler = binding.create((success) => { + if(!success) { + throw new Error('Failed to create the audio handler.') + } else { + assert(binding, 'Audio handler created') + } + }) + + if (options.handler !== null) { + binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { + if (!success) { + throw new Error('Could not start the audio output with these properties.') + } else { + assert(options, 'Audio handler options applied') + } + }) + } + + write.end = end + write.sink = sink + sink.end = end + return write + + /** + * The write function takes a buffer or audiobuffer and + * writes it to the speaker output. If the chunks are too + * large it will break it up and put the remainding chunks + * into a queue. + * NOTE: You can only write new chunks once the callback is + * called with no errors. + * + * @param {AudioBuffer} chunk (or Buffer) containing the data to be output + * @param {Function} callback callback with error and chunk parameters + * @return void + * @api public + */ + function write (chunk, callback) { + if (!callback) callback = noop + + if (options._closed) return assert(chunk, 'Write cannot occur after the speaker is closed') + + if (chunk && options._busy) { + assert(chunk, 'Write cannot occur until the previous chunk is processed') + callback(new Error('Cannot write chunk as the buffer was busy.'), 0) + } + + next(chunk, null, callback) + + function next (chunk, remainder, callback) { + if (options.handler) { + options._busy = true + + var chunkBuf = isAudioBuffer(chunk) ? Buffer.from(pcm.toArrayBuffer(chunk, options)) : chunk || new Buffer(0) + var remainderBuf = isAudioBuffer(remainder) ? Buffer.from(pcm.toArrayBuffer(remainder, options)) : remainder || new Buffer(0) + + var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) + + var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue + var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) + + binding.write(options.handler, output, output.length, (written) => { + if(!remaining.length < 1) { + next(null, remaining, callback) + } else { + assert(written, 'Finished writing chunk') + if (options.autoFlush && remaining.length < options.chunkSize) { + binding.flush(options.handler, function (success) { + if (success != 1) { + options._busy = false + callback(new Error('Could not flush the audio output.'), written) + } else { + assert(chunk, 'Finished flushing chunk') + options._busy = false + callback(null, written) + } + }) + } else { + options._busy = false + callback(null, written) + } + } + }) + } else { + assert(chunk, 'Abandoning remaining chunks as the speaker has closed') + callback(new Error('Could not write remaining chunks as the speaker is closed.'), 0) + } + } + } + + function sink (callback) { + return audioSink((data, callback) => { + if (options._closed) return callback(true) + setTimeout(callback, options.samplesPerFrame / options.sampleRate) + }) + } + + /** + * The end function closes the speaker and stops + * it from writing anymore data. The output data + * that was already written can be optionally flushed. + * NOTE: You cannot write anymore data after closing the speaker. + * + * @param {Boolean} flush flushes the written data (default is false) + * @param {Function} callback callback with error parameter + * @return void + * @api public + */ + function end (flush, callback) { + if (options._closed) return assert(flush, 'Closing the speaker cannot occur after the speaker is already closed') + + if (options.handler) { + if (flush) { + binding.flush(options.handler, function (success) { + if (success != 1) { + callback(new Error('Could not flush the audio output.')) + } else { + assert(flush, 'Finished flushing chunk') + return close(callback) + } + }) + } else { + return close(callback) + } + } else { + callback(new Error('Could not flush the audio output. Handler was deleted or not created.')) + } + + function close (callback) { + binding.close(options.handler, (success) => { + if (callback) { + if (success != 1) { + callback(new Error('Failed to close speaker.')) + } else { + assert(options.handler, 'Closed speaker') + callback() + } + } + }) + options._closed = true + options.handler = null + } + } +} + +Speaker.getFormat = function getFormat (format) { + var f = null; + if (format.bitDepth == 32 && format.float && format.signed) { + f = binding.MPG123_ENC_FLOAT_32; + } else if (format.bitDepth == 64 && format.float && format.signed) { + f = binding.MPG123_ENC_FLOAT_64; + } else if (format.bitDepth == 8 && format.signed) { + f = binding.MPG123_ENC_SIGNED_8; + } else if (format.bitDepth == 8 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_8; + } else if (format.bitDepth == 16 && format.signed) { + f = binding.MPG123_ENC_SIGNED_16; + } else if (format.bitDepth == 16 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_16; + } else if (format.bitDepth == 24 && format.signed) { + f = binding.MPG123_ENC_SIGNED_24; + } else if (format.bitDepth == 24 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_24; + } else if (format.bitDepth == 32 && format.signed) { + f = binding.MPG123_ENC_SIGNED_32; + } else if (format.bitDepth == 32 && !format.signed) { + f = binding.MPG123_ENC_UNSIGNED_32; + } + return f; +} + + +function noop () {} diff --git a/node.js b/node.js deleted file mode 100644 index 6959dcb..0000000 --- a/node.js +++ /dev/null @@ -1,223 +0,0 @@ -/** @module audio-speaker/index */ -'use strict' - -var os = require('os') -var pcm = require('pcm-util') -var assert = require('assert') -var binding = require('audio-mpg123') -var objectAssign = require('object-assign') -var audioSink = require('audio-sink/direct') -var isAudioBuffer = require('is-audio-buffer') - -var endianess = 'function' == os.endianess ? os.endianess() : 'LE' - -module.exports = Speaker - -/** - * The Speaker function initializes a new audio handler, - * then returns the write method to output audio to. - * - * @param {Object} opts options for the speaker - * @return {Function} write write audio from a buffer or audiobuffer - * @module Speaker - * @api public - */ -function Speaker (opts) { - var options = {} - - options = objectAssign({ - channels: 1, - float: false, - bitDepth: 16, - signed: true, - samplesPerFrame: 1024, - sampleRate: 44100, - endianess: endianess, - autoFlush: false - }, opts) - - assert(options, 'Options applied to speaker') - - if (options.handler) { - throw new Error('_create() was called more than once. Only one handler should exist.') - } - - options._closed = false - options._busy = false - - var format = Speaker.getFormat(options) - if (format === null) { - throw new Error('Invalid format options.') - } - - options.blockAlign = options.bitDepth / 8 * options.channels - - options.chunkSize = options.blockAlign * options.samplesPerFrame - - options.handler = binding.create((success) => { - if(!success) { - throw new Error('Failed to create the audio handler.') - } else { - assert(binding, 'Audio handler created') - } - }) - - if (options.handler !== null) { - binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { - if (!success) { - throw new Error('Could not start the audio output with these properties.') - } else { - assert(options, 'Audio handler options applied') - } - }) - } - - write.end = end - write.sink = sink - sink.end = end - return write - - /** - * The write function takes a buffer or audiobuffer and - * writes it to the speaker output. If the chunks are too - * large it will break it up and put the remainding chunks - * into a queue. - * NOTE: You can only write new chunks once the callback is - * called with no errors. - * - * @param {AudioBuffer} chunk (or Buffer) containing the data to be output - * @param {Function} callback callback with error and chunk parameters - * @return void - * @api public - */ - function write (chunk, callback) { - if (options._closed) return assert(chunk, 'Write cannot occur after the speaker is closed') - - if (chunk && options._busy) { - assert(chunk, 'Write cannot occur until the previous chunk is processed') - callback(new Error('Could not write chunk as the buffer was busy.'), 0) - } - - next(chunk, null, callback) - - function next (chunk, remainder, callback) { - if (options.handler) { - options._busy = true - - var chunkBuf = isAudioBuffer(chunk) ? Buffer.from(pcm.toArrayBuffer(chunk, options)) : chunk || new Buffer(0) - var remainderBuf = isAudioBuffer(remainder) ? Buffer.from(pcm.toArrayBuffer(remainder, options)) : remainder || new Buffer(0) - - var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) - - var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue - var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) - - binding.write(options.handler, output, output.length, (written) => { - if(!remaining.length < 1) { - next(null, remaining, callback) - } else { - assert(written, 'Finished writing chunk') - if (options.autoFlush && remaining.length < options.chunkSize) { - binding.flush(options.handler, function (success) { - if (success != 1) { - options._busy = false - callback(new Error('Could not flush the audio output.'), written) - } else { - assert(chunk, 'Finished flushing chunk') - options._busy = false - callback(null, written) - } - }) - } else { - options._busy = false - callback(null, written) - } - } - }) - } else { - assert(chunk, 'Abandoning remaining chunks as the speaker has closed') - callback(new Error('Could not write remaining chunks as the speaker is closed.'), 0) - } - } - } - - function sink (callback) { - return audioSink((data, callback) => { - if (options._closed) return callback(true) - setTimeout(callback, options.samplesPerFrame / options.sampleRate) - }) - } - - /** - * The end function closes the speaker and stops - * it from writing anymore data. The output data - * that was already written can be optionally flushed. - * NOTE: You cannot write anymore data after closing the speaker. - * - * @param {Boolean} flush flushes the written data (default is false) - * @param {Function} callback callback with error parameter - * @return void - * @api public - */ - function end (flush, callback) { - if (options._closed) return assert(flush, 'Closing the speaker cannot occur after the speaker is already closed') - - if (options.handler) { - if (flush) { - binding.flush(options.handler, function (success) { - if (success != 1) { - callback(new Error('Could not flush the audio output.')) - } else { - assert(flush, 'Finished flushing chunk') - return close(callback) - } - }) - } else { - return close(callback) - } - } else { - callback(new Error('Could not flush the audio output. Handler was deleted or not created.')) - } - - function close (callback) { - binding.close(options.handler, (success) => { - if (callback) { - if (success != 1) { - callback(new Error('Failed to close speaker.')) - } else { - assert(options.handler, 'Closed speaker') - callback() - } - } - }) - options._closed = true - options.handler = null - } - } -} - -Speaker.getFormat = function getFormat (format) { - var f = null; - if (format.bitDepth == 32 && format.float && format.signed) { - f = binding.MPG123_ENC_FLOAT_32; - } else if (format.bitDepth == 64 && format.float && format.signed) { - f = binding.MPG123_ENC_FLOAT_64; - } else if (format.bitDepth == 8 && format.signed) { - f = binding.MPG123_ENC_SIGNED_8; - } else if (format.bitDepth == 8 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_8; - } else if (format.bitDepth == 16 && format.signed) { - f = binding.MPG123_ENC_SIGNED_16; - } else if (format.bitDepth == 16 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_16; - } else if (format.bitDepth == 24 && format.signed) { - f = binding.MPG123_ENC_SIGNED_24; - } else if (format.bitDepth == 24 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_24; - } else if (format.bitDepth == 32 && format.signed) { - f = binding.MPG123_ENC_SIGNED_32; - } else if (format.bitDepth == 32 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_32; - } - return f; -} diff --git a/package.json b/package.json index 2f915a9..1711134 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,7 @@ "version": "2.0.0-5", "description": "Output PCM data to a device or library.", "scripts": { - "test": "tape tests/check.js", - "test:node": "tape tests/node/**/*.js", + "test": "node test", "lint": "eslint *.js --ignore-pattern test*" }, "repository": { @@ -12,9 +11,7 @@ "url": "git+https://github.com/audiojs/audio-speaker.git" }, "main": "./index", - "browser": { - "./index": "./browser" - }, + "browser": "./browser", "keywords": [ "PCM", "output", diff --git a/test.js b/test.js new file mode 100644 index 0000000..91f9156 --- /dev/null +++ b/test.js @@ -0,0 +1,77 @@ +'use strict' + +var test = require('tape') + +var util = require('audio-buffer-utils') +var LenaBuffer = require('audio-lena/raw') +var createSpeaker = require('./') +var createGenerator = require('audio-generator/direct') + + +test('output audio buffer', t => { + var write = createSpeaker() + + let buffer = util.create(10000) + util.noise(buffer) + + write(buffer, (err) => { + if (err) t.fail() + t.end() + }) +}) + + +test('play lena', t => { + var speaker = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) + var buf = util.create(LenaBuffer) + buf = util.slice(buf, 0, 44100) + + speaker(buf, (err, chunk) => { + if (err) t.fail(err) + speaker.end(false, (err) => { + err ? t.error(err) : t.pass('Output successful.') + }) + t.end() + }) +}) + + +test('autoflush', t => { + var speaker = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) + var buf = util.create(LenaBuffer) + buf = util.slice(buf, 0, 44100) + + speaker(buf, (err, chunk) => { + if (err) t.fail(err) + speaker.end(true, (err) => { + err ? t.error(err) : t.pass('Output successful.') + }) + t.end() + }) +}) + + +test('play sine for 4 seconds', t => { + var generate = createGenerator(time => { + return Math.sin(Math.PI * 2 * time * 440) + }, { duration: 4 }) + + var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }); + + setTimeout(() => { + write.end(false, (err) => { + if (err) t.fail(err) + t.end() + }) + }, 4000); + + (function loop (err, chunk) { + if (err || chunk < 1) { + return + } else { + write(generate(), (err, chunk) => { + loop(err, chunk) + }) + } + })(); +}) diff --git a/tests/browser/browser_noise.js b/tests/browser/browser_noise.js deleted file mode 100644 index f1211f3..0000000 --- a/tests/browser/browser_noise.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict' - -var test = require('tape') - -var util = require('audio-buffer-utils') -var AudioSpeaker = require('../../browser') - -test('output audio buffer', t => { - var write = AudioSpeaker() - - let buffer = util.create(10000) - util.noise(buffer) - - write(buffer) -}) diff --git a/tests/check.js b/tests/check.js deleted file mode 100644 index 4faf318..0000000 --- a/tests/check.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict' - -var test = require('tape') - -test('check for build output', function(t) { - try { - require('../')() != null ? t.pass('Found audio_mpg123.') : null - } catch (err) { - t.error(err, 'Could not find audio_mpg123.') - } - t.end() -}) diff --git a/tests/node/node_lena.js b/tests/node/node_lena.js deleted file mode 100644 index c52f839..0000000 --- a/tests/node/node_lena.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict' - -var test = require('tape').only - -var util = require('audio-buffer-utils') -var LenaBuffer = require('audio-lena/raw') -var AudioSpeaker = require('../../node') - -test('play audio once test', t => { - var speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) - var buf = util.create(LenaBuffer) - - speaker(buf, (err, chunk) => { - if (err || chunk === true) { - t.error(err, 'Write callback caught an unexpected error.') - } else { - speaker.end(true, (err) => { - err ? t.error(err) : t.pass('Output successful.') - }) - } - }) - - t.end() -}) diff --git a/tests/node/node_lena_auto.js b/tests/node/node_lena_auto.js deleted file mode 100644 index c66fa71..0000000 --- a/tests/node/node_lena_auto.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict' - -var test = require('tape') - -var util = require('audio-buffer-utils') -var LenaBuffer = require('audio-lena/raw') -var AudioSpeaker = require('../../node') - -test('play audio once test', t => { - var speaker = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) - var buf = util.create(LenaBuffer) - - speaker(buf, (err, chunk) => { - if (err || chunk === true) { - t.error(err, 'Write callback caught an unexpected error.') - } else { - speaker.end(false, (err) => { - err ? t.error(err) : t.pass('Output successful.') - }) - } - }) - - t.end() -}) diff --git a/tests/node/node_sine.js b/tests/node/node_sine.js deleted file mode 100644 index 96a8665..0000000 --- a/tests/node/node_sine.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict' - -var test = require('tape') - -var AudioGenerator = require('audio-generator/index') -var AudioSpeaker = require('../../node') - -test('play sine for 4 seconds', t => { - var generate = AudioGenerator(time => { - return Math.sin(Math.PI * 2 * time * 500) - }, { duration: 4 }) - - var write = AudioSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }); - - setTimeout(() => { - write.end(false, (err) => { - err ? t.error(err) : t.pass('Output successful.') - }) - }, 4000); - - (function loop (err, chunk) { - if (err || chunk < 1) { - return - } else { - write(generate(), (err, chunk) => { - loop(err, chunk) - }) - } - })(); - - t.end() -}) From b5f1816a23eacfdb90b892d405003233effcef0c Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 23 Jun 2017 19:37:22 -0400 Subject: [PATCH 77/96] Fix browser tests --- package.json | 1 + test.js | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 1711134..65e0825 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "Output PCM data to a device or library.", "scripts": { "test": "node test", + "test:browser": "budo test", "lint": "eslint *.js --ignore-pattern test*" }, "repository": { diff --git a/test.js b/test.js index 91f9156..6e2d5c0 100644 --- a/test.js +++ b/test.js @@ -28,9 +28,9 @@ test('play lena', t => { speaker(buf, (err, chunk) => { if (err) t.fail(err) - speaker.end(false, (err) => { - err ? t.error(err) : t.pass('Output successful.') - }) + // speaker.end(false, (err) => { + // err ? t.error(err) : t.pass('Output successful.') + // }) t.end() }) }) @@ -43,9 +43,9 @@ test('autoflush', t => { speaker(buf, (err, chunk) => { if (err) t.fail(err) - speaker.end(true, (err) => { - err ? t.error(err) : t.pass('Output successful.') - }) + // speaker.end(true, (err) => { + // err ? t.error(err) : t.pass('Output successful.') + // }) t.end() }) }) @@ -63,7 +63,7 @@ test('play sine for 4 seconds', t => { if (err) t.fail(err) t.end() }) - }, 4000); + }, 1000); (function loop (err, chunk) { if (err || chunk < 1) { From 41a7caa903978fa932f904e100be1ee3511caf1f Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 24 Jun 2017 11:42:49 +1200 Subject: [PATCH 78/96] Fix up use of assertion --- index.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 33531f2..f0b322a 100644 --- a/index.js +++ b/index.js @@ -34,6 +34,8 @@ function Speaker (opts) { autoFlush: false }, opts) + assert(options, 'Applied speaker options') + if (options.handler) { throw new Error('_create() was called more than once. Only one handler should exist.') } @@ -53,8 +55,6 @@ function Speaker (opts) { options.handler = binding.create((success) => { if(!success) { throw new Error('Failed to create the audio handler.') - } else { - assert(binding, 'Audio handler created') } }) @@ -62,8 +62,6 @@ function Speaker (opts) { binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { if (!success) { throw new Error('Could not start the audio output with these properties.') - } else { - assert(options, 'Audio handler options applied') } }) } @@ -89,10 +87,9 @@ function Speaker (opts) { function write (chunk, callback) { if (!callback) callback = noop - if (options._closed) return assert(chunk, 'Write cannot occur after the speaker is closed') + if (options._closed) return callback(new Error('Write cannot occur after the speaker is closed.')) if (chunk && options._busy) { - assert(chunk, 'Write cannot occur until the previous chunk is processed') callback(new Error('Cannot write chunk as the buffer was busy.'), 0) } @@ -121,7 +118,6 @@ function Speaker (opts) { options._busy = false callback(new Error('Could not flush the audio output.'), written) } else { - assert(chunk, 'Finished flushing chunk') options._busy = false callback(null, written) } @@ -133,7 +129,6 @@ function Speaker (opts) { } }) } else { - assert(chunk, 'Abandoning remaining chunks as the speaker has closed') callback(new Error('Could not write remaining chunks as the speaker is closed.'), 0) } } @@ -158,7 +153,7 @@ function Speaker (opts) { * @api public */ function end (flush, callback) { - if (options._closed) return assert(flush, 'Closing the speaker cannot occur after the speaker is already closed') + if (options._closed) return callback(new Error('Closing the speaker cannot occur after the speaker is already closed.')) if (options.handler) { if (flush) { @@ -166,7 +161,6 @@ function Speaker (opts) { if (success != 1) { callback(new Error('Could not flush the audio output.')) } else { - assert(flush, 'Finished flushing chunk') return close(callback) } }) @@ -183,7 +177,6 @@ function Speaker (opts) { if (success != 1) { callback(new Error('Failed to close speaker.')) } else { - assert(options.handler, 'Closed speaker') callback() } } From b7462123772079add04cb8ec0066ec94ea6d7f6e Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 24 Jun 2017 11:45:43 +1200 Subject: [PATCH 79/96] Remove assertion --- index.js | 3 --- package.json | 1 - 2 files changed, 4 deletions(-) diff --git a/index.js b/index.js index f0b322a..f4a23ad 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,6 @@ var os = require('os') var pcm = require('pcm-util') -var assert = require('assert') var binding = require('audio-mpg123') var objectAssign = require('object-assign') var audioSink = require('audio-sink/direct') @@ -34,8 +33,6 @@ function Speaker (opts) { autoFlush: false }, opts) - assert(options, 'Applied speaker options') - if (options.handler) { throw new Error('_create() was called more than once. Only one handler should exist.') } diff --git a/package.json b/package.json index 65e0825..7767534 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ }, "homepage": "https://github.com/audiojs/audio-speaker#readme", "dependencies": { - "assert": "^1.4.1", "audio-context": "^1.0.1", "audio-sink": "^1.1.6", "is-audio-buffer": "^1.0.11", From 1f60aed58a2d581bfdbe171d51a0db18f775a3ae Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 24 Jun 2017 11:51:38 +1200 Subject: [PATCH 80/96] Remove the assertion I didn't see --- index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/index.js b/index.js index f4a23ad..9268cc8 100644 --- a/index.js +++ b/index.js @@ -108,7 +108,6 @@ function Speaker (opts) { if(!remaining.length < 1) { next(null, remaining, callback) } else { - assert(written, 'Finished writing chunk') if (options.autoFlush && remaining.length < options.chunkSize) { binding.flush(options.handler, function (success) { if (success != 1) { From f980a8e95ac6a2178964ab079f07de13118516c2 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 24 Jun 2017 13:44:03 +1200 Subject: [PATCH 81/96] Add temporary test fix --- browser.js | 7 ++++- index.js | 13 ++++---- test.js | 87 +++++++++++++++++++++++++++++++++++------------------- 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/browser.js b/browser.js index 62be612..0f50ad7 100644 --- a/browser.js +++ b/browser.js @@ -5,7 +5,9 @@ var objectAssign = require('object-assign') var createContext = require('audio-context') var createWriter = require('web-audio-write') -module.exports = function createSpeaker (opts) { +module.exports = Speaker + +function Speaker (opts) { var options = {} options = objectAssign({ @@ -18,3 +20,6 @@ module.exports = function createSpeaker (opts) { return write } + +// TODO: Temporary until browser has fixed ending callback. +Speaker.platform = 'browser' diff --git a/index.js b/index.js index 9268cc8..0c7fb5f 100644 --- a/index.js +++ b/index.js @@ -87,7 +87,7 @@ function Speaker (opts) { if (options._closed) return callback(new Error('Write cannot occur after the speaker is closed.')) if (chunk && options._busy) { - callback(new Error('Cannot write chunk as the buffer was busy.'), 0) + callback(new Error('Cannot write chunk as the buffer was busy.')) } next(chunk, null, callback) @@ -112,20 +112,20 @@ function Speaker (opts) { binding.flush(options.handler, function (success) { if (success != 1) { options._busy = false - callback(new Error('Could not flush the audio output.'), written) + callback(new Error('Could not flush the audio output.')) } else { options._busy = false - callback(null, written) + callback(null) } }) } else { options._busy = false - callback(null, written) + callback(null) } } }) } else { - callback(new Error('Could not write remaining chunks as the speaker is closed.'), 0) + callback(new Error('Could not write remaining chunks as the speaker is closed.')) } } } @@ -183,6 +183,9 @@ function Speaker (opts) { } } +// TODO: Temporary until browser has fixed ending callback. +Speaker.platform = 'node' + Speaker.getFormat = function getFormat (format) { var f = null; if (format.bitDepth == 32 && format.float && format.signed) { diff --git a/test.js b/test.js index 6e2d5c0..a0c00e5 100644 --- a/test.js +++ b/test.js @@ -8,50 +8,72 @@ var createSpeaker = require('./') var createGenerator = require('audio-generator/direct') -test('output audio buffer', t => { +test('play noise', t => { var write = createSpeaker() let buffer = util.create(10000) util.noise(buffer) write(buffer, (err) => { - if (err) t.fail() - t.end() + if (err) { + t.error(err, 'Write callback caught an unexpected error.') + } else { + if (createSpeaker.platform === 'node') { + write.end(true, (err) => { + err ? t.error(err) : t.pass('Output successful.') + t.end() + }) + } else { + t.end() + } + } }) }) test('play lena', t => { - var speaker = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) + var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = util.create(LenaBuffer) - buf = util.slice(buf, 0, 44100) - - speaker(buf, (err, chunk) => { - if (err) t.fail(err) - // speaker.end(false, (err) => { - // err ? t.error(err) : t.pass('Output successful.') - // }) - t.end() + + write(buf, (err) => { + if (err) { + t.error(err, 'Write callback caught an unexpected error.') + } else { + if (createSpeaker.platform === 'node') { + write.end(true, (err) => { + err ? t.error(err) : t.pass('Output successful.') + t.end() + }) + } else { + t.end() + } + } }) }) -test('autoflush', t => { - var speaker = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) +test('play lena autoflush', t => { + var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) var buf = util.create(LenaBuffer) - buf = util.slice(buf, 0, 44100) - - speaker(buf, (err, chunk) => { - if (err) t.fail(err) - // speaker.end(true, (err) => { - // err ? t.error(err) : t.pass('Output successful.') - // }) - t.end() + + write(buf, (err) => { + if (err) { + t.error(err, 'Write callback caught an unexpected error.') + } else { + if (createSpeaker.platform === 'node') { + write.end(false, (err) => { + err ? t.error(err) : t.pass('Output successful.') + t.end() + }) + } else { + t.end() + } + } }) }) -test('play sine for 4 seconds', t => { +test('play sine', t => { var generate = createGenerator(time => { return Math.sin(Math.PI * 2 * time * 440) }, { duration: 4 }) @@ -59,18 +81,23 @@ test('play sine for 4 seconds', t => { var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }); setTimeout(() => { - write.end(false, (err) => { - if (err) t.fail(err) + if (createSpeaker.platform === 'node') { + write.end(false, (err) => { + err ? t.error(err) : t.pass('Output successful.') + t.end() + }) + } else { t.end() - }) + } }, 1000); - (function loop (err, chunk) { - if (err || chunk < 1) { + (function loop (err) { + if (err) { + // Ignore errors as we are intentionally cutting this short. return } else { - write(generate(), (err, chunk) => { - loop(err, chunk) + write(generate(), (err) => { + loop(err) }) } })(); From 2ca1050b54b56df83554e29170fa088544c1aae7 Mon Sep 17 00:00:00 2001 From: Connor Hartley Date: Sat, 24 Jun 2017 17:55:20 +1200 Subject: [PATCH 82/96] Tidy up end method --- browser.js | 3 -- index.js | 75 ++++++++++++++++------------------------------- package-lock.json | 16 ++-------- package.json | 2 +- test.js | 60 ++++++++----------------------------- 5 files changed, 42 insertions(+), 114 deletions(-) diff --git a/browser.js b/browser.js index 0f50ad7..c3c34cc 100644 --- a/browser.js +++ b/browser.js @@ -20,6 +20,3 @@ function Speaker (opts) { return write } - -// TODO: Temporary until browser has fixed ending callback. -Speaker.platform = 'browser' diff --git a/index.js b/index.js index 0c7fb5f..59b2f1d 100644 --- a/index.js +++ b/index.js @@ -30,36 +30,28 @@ function Speaker (opts) { samplesPerFrame: 1024, sampleRate: 44100, endianess: endianess, - autoFlush: false + autoFlush: true }, opts) - if (options.handler) { - throw new Error('_create() was called more than once. Only one handler should exist.') - } + if (options.handler) throw new Error('Speaker was called more than once. Only one handler should exist.') options._closed = false options._busy = false var format = Speaker.getFormat(options) - if (format === null) { - throw new Error('Invalid format options.') - } + if (!format) throw new Error('Invalid format options.') options.blockAlign = options.bitDepth / 8 * options.channels options.chunkSize = options.blockAlign * options.samplesPerFrame options.handler = binding.create((success) => { - if(!success) { - throw new Error('Failed to create the audio handler.') - } + if(!success) throw new Error('Failed to create the audio handler.') }) if (options.handler !== null) { - binding.open(options.handler, options.sampleRate, options.channels, format, function (success) { - if (!success) { - throw new Error('Could not start the audio output with these properties.') - } + binding.open(options.handler, options.sampleRate, options.channels, format, (success) => { + if (!success) throw new Error('Could not start the audio output with these properties.') }) } @@ -85,10 +77,7 @@ function Speaker (opts) { if (!callback) callback = noop if (options._closed) return callback(new Error('Write cannot occur after the speaker is closed.')) - - if (chunk && options._busy) { - callback(new Error('Cannot write chunk as the buffer was busy.')) - } + if (chunk && options._busy) callback(new Error('Write cannot occur until the speaker has cleared its buffer.')) next(chunk, null, callback) @@ -110,11 +99,10 @@ function Speaker (opts) { } else { if (options.autoFlush && remaining.length < options.chunkSize) { binding.flush(options.handler, function (success) { - if (success != 1) { - options._busy = false - callback(new Error('Could not flush the audio output.')) + options._busy = false + if (!success) { + callback('Could not flush the audio output.') } else { - options._busy = false callback(null) } }) @@ -140,53 +128,40 @@ function Speaker (opts) { /** * The end function closes the speaker and stops * it from writing anymore data. The output data - * that was already written can be optionally flushed. + * that was already written will be flushed if the + * auto flush option is set. * NOTE: You cannot write anymore data after closing the speaker. * - * @param {Boolean} flush flushes the written data (default is false) - * @param {Function} callback callback with error parameter * @return void * @api public */ - function end (flush, callback) { - if (options._closed) return callback(new Error('Closing the speaker cannot occur after the speaker is already closed.')) + function end () { + if (options._closed) return if (options.handler) { - if (flush) { - binding.flush(options.handler, function (success) { - if (success != 1) { - callback(new Error('Could not flush the audio output.')) - } else { - return close(callback) - } + if (options.autoFlush) { + binding.flush(options.handler, (success) => { + if (!success) throw new Error('Could not flush the audio output.') + return close() }) } else { - return close(callback) + return close() } } else { - callback(new Error('Could not flush the audio output. Handler was deleted or not created.')) + throw new Error('Audio handler was not initialized.') } - function close (callback) { + function close () { binding.close(options.handler, (success) => { - if (callback) { - if (success != 1) { - callback(new Error('Failed to close speaker.')) - } else { - callback() - } - } + if (!success) throw new Error('Could not close the speaker.') + options._closed = true + options.handler = null }) - options._closed = true - options.handler = null } } } -// TODO: Temporary until browser has fixed ending callback. -Speaker.platform = 'node' - -Speaker.getFormat = function getFormat (format) { +Speaker.getFormat = (format) => { var f = null; if (format.bitDepth == 32 && format.float && format.signed) { f = binding.MPG123_ENC_FLOAT_32; diff --git a/package-lock.json b/package-lock.json index 2b95bdd..939ea05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -99,11 +99,6 @@ "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", "optional": true }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=" - }, "assert-plus": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", @@ -1521,11 +1516,6 @@ "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", "optional": true }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=" - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -1544,9 +1534,9 @@ "optional": true }, "web-audio-write": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/web-audio-write/-/web-audio-write-1.1.0.tgz", - "integrity": "sha1-z4YBU1HhfdXSYWQNEpNN4UIu7E0=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web-audio-write/-/web-audio-write-1.2.1.tgz", + "integrity": "sha1-iFlr1ch/8QvFloCXhJ1pHtyHvm4=" }, "wide-align": { "version": "1.1.2", diff --git a/package.json b/package.json index 7767534..c25a910 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "is-browser": "^2.0.1", "object-assign": "^4.1.1", "pcm-util": "^3.0.0", - "web-audio-write": "^1.1.0" + "web-audio-write": "^1.2.1" }, "devDependencies": { "audio-buffer-utils": "^5.0.1", diff --git a/test.js b/test.js index a0c00e5..a8ca836 100644 --- a/test.js +++ b/test.js @@ -9,6 +9,8 @@ var createGenerator = require('audio-generator/direct') test('play noise', t => { + t.plan(1) + var write = createSpeaker() let buffer = util.create(10000) @@ -18,77 +20,41 @@ test('play noise', t => { if (err) { t.error(err, 'Write callback caught an unexpected error.') } else { - if (createSpeaker.platform === 'node') { - write.end(true, (err) => { - err ? t.error(err) : t.pass('Output successful.') - t.end() - }) - } else { - t.end() - } + write.end() + t.pass('Output successful.') } }) }) test('play lena', t => { - var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) - var buf = util.create(LenaBuffer) - - write(buf, (err) => { - if (err) { - t.error(err, 'Write callback caught an unexpected error.') - } else { - if (createSpeaker.platform === 'node') { - write.end(true, (err) => { - err ? t.error(err) : t.pass('Output successful.') - t.end() - }) - } else { - t.end() - } - } - }) -}) - + t.plan(1) -test('play lena autoflush', t => { - var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: true }) + var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = util.create(LenaBuffer) write(buf, (err) => { if (err) { t.error(err, 'Write callback caught an unexpected error.') } else { - if (createSpeaker.platform === 'node') { - write.end(false, (err) => { - err ? t.error(err) : t.pass('Output successful.') - t.end() - }) - } else { - t.end() - } + write.end() + t.pass('Output successful.') } }) }) - test('play sine', t => { + t.plan(1) + var generate = createGenerator(time => { return Math.sin(Math.PI * 2 * time * 440) }, { duration: 4 }) - var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }); + var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: false }); setTimeout(() => { - if (createSpeaker.platform === 'node') { - write.end(false, (err) => { - err ? t.error(err) : t.pass('Output successful.') - t.end() - }) - } else { - t.end() - } + write.end() + t.pass('Output successful.') }, 1000); (function loop (err) { From a75a8cd5104236d6b2bf155c4e432cae6ed29c26 Mon Sep 17 00:00:00 2001 From: Jamen Marzonie Date: Sat, 24 Jun 2017 22:17:46 -0500 Subject: [PATCH 83/96] Upgrade Node implentation and tests --- index.js | 138 +++++++++++++++++++++--------------------------------- readme.md | 95 ++++++++++++++++++++++--------------- test.js | 4 +- 3 files changed, 113 insertions(+), 124 deletions(-) diff --git a/index.js b/index.js index 59b2f1d..e8d0110 100644 --- a/index.js +++ b/index.js @@ -4,11 +4,10 @@ var os = require('os') var pcm = require('pcm-util') var binding = require('audio-mpg123') -var objectAssign = require('object-assign') var audioSink = require('audio-sink/direct') -var isAudioBuffer = require('is-audio-buffer') +function noop () {} -var endianess = 'function' == os.endianess ? os.endianess() : 'LE' +var endianess = os.endianness() || 'LE' module.exports = Speaker @@ -22,7 +21,7 @@ module.exports = Speaker * @api public */ function Speaker (opts) { - var options = objectAssign({ + var options = Object.assign({ channels: 1, float: false, bitDepth: 16, @@ -33,31 +32,30 @@ function Speaker (opts) { autoFlush: true }, opts) - if (options.handler) throw new Error('Speaker was called more than once. Only one handler should exist.') - - options._closed = false - options._busy = false - var format = Speaker.getFormat(options) if (!format) throw new Error('Invalid format options.') - options.blockAlign = options.bitDepth / 8 * options.channels + // Options we use directly + var channels = options.channels + var sampleRate = options.sampleRate + var blockAlign = options.bitDepth / 8 * options.channels + var chunkSize = options.blockAlign * options.samplesPerFrame + var autoFlush = options.autoFlush - options.chunkSize = options.blockAlign * options.samplesPerFrame + // Writing state + var busy = false - options.handler = binding.create((success) => { - if(!success) throw new Error('Failed to create the audio handler.') + var handler = binding.create((success) => { + if (!success) throw new Error('Failed to create the audio handler.') }) - if (options.handler !== null) { - binding.open(options.handler, options.sampleRate, options.channels, format, (success) => { + if (handler) { + binding.open(handler, sampleRate, channels, format, (success) => { if (!success) throw new Error('Could not start the audio output with these properties.') }) } write.end = end - write.sink = sink - sink.end = end return write /** @@ -73,58 +71,44 @@ function Speaker (opts) { * @return void * @api public */ - function write (chunk, callback) { - if (!callback) callback = noop - - if (options._closed) return callback(new Error('Write cannot occur after the speaker is closed.')) - if (chunk && options._busy) callback(new Error('Write cannot occur until the speaker has cleared its buffer.')) - - next(chunk, null, callback) - - function next (chunk, remainder, callback) { - if (options.handler) { - options._busy = true - - var chunkBuf = isAudioBuffer(chunk) ? Buffer.from(pcm.toArrayBuffer(chunk, options)) : chunk || new Buffer(0) - var remainderBuf = isAudioBuffer(remainder) ? Buffer.from(pcm.toArrayBuffer(remainder, options)) : remainder || new Buffer(0) - - var queue = Buffer.concat([remainderBuf, chunkBuf], remainderBuf.length + chunkBuf.length) - - var output = queue.length > options.chunkSize ? queue.slice(0, options.chunkSize) : queue - var remaining = queue.length > options.chunkSize ? queue.slice(options.chunkSize, queue.length) : new Buffer(0) - - binding.write(options.handler, output, output.length, (written) => { - if(!remaining.length < 1) { - next(null, remaining, callback) - } else { - if (options.autoFlush && remaining.length < options.chunkSize) { - binding.flush(options.handler, function (success) { - options._busy = false - if (!success) { - callback('Could not flush the audio output.') - } else { - callback(null) - } - }) - } else { - options._busy = false - callback(null) - } + function write (buf, callback) { + if (!handler) return callback(new Error('Write occurred after the speaker closed.')) + if (busy) return callback(new Error('Write occurred before the speaker flushed.')) + + next(buf, null, callback) + + function next (chunk, rest, callback) { + if (handler) { + busy = true + + // TODO: Remove once binding takes ArrayBuffer directly + if (chunk) chunk = Buffer.from(pcm.toArrayBuffer(chunk, options)) + if (rest) rest = Buffer.from(pcm.toArrayBuffer(rest, options)) + var queue = !rest || !rest.length ? chunk : Buffer.concat([rest, chunk]) + if (!queue) queue = new Buffer(0) // meh + + var output = queue.length > chunkSize ? queue.slice(0, chunkSize) : queue + var remaining = queue.length > chunkSize ? queue.slice(chunkSize, queue.length) : new Buffer(0) + + binding.write(handler, output, output.length, (written) => { + // Play next chunk + if (rest && rest.length) return next(null, remaining, callback) + // Stream finished. Flush and callback + var err = null + if (autoFlush) { + binding.flush(handler, (success) => { + if (!success) err = new Error('Flushing speaker failed') + }) } + busy = false + callback(err) }) } else { - callback(new Error('Could not write remaining chunks as the speaker is closed.')) + callback(new Error('Speaker closed while writing')) } } } - function sink (callback) { - return audioSink((data, callback) => { - if (options._closed) return callback(true) - setTimeout(callback, options.samplesPerFrame / options.sampleRate) - }) - } - /** * The end function closes the speaker and stops * it from writing anymore data. The output data @@ -136,28 +120,16 @@ function Speaker (opts) { * @api public */ function end () { - if (options._closed) return + if (!handler) return - if (options.handler) { - if (options.autoFlush) { - binding.flush(options.handler, (success) => { - if (!success) throw new Error('Could not flush the audio output.') - return close() - }) - } else { - return close() - } - } else { - throw new Error('Audio handler was not initialized.') - } + binding.flush(handler, (success) => { + if (!success) throw new Error('Failed to flush speaker.') + }) - function close () { - binding.close(options.handler, (success) => { - if (!success) throw new Error('Could not close the speaker.') - options._closed = true - options.handler = null - }) - } + binding.close(handler, (success) => { + if (!success) throw new Error('Could not close the speaker.') + handler = null + }) } } @@ -187,5 +159,3 @@ Speaker.getFormat = (format) => { return f; } - -function noop () {} diff --git a/readme.md b/readme.md index 5a98cdb..bcbad14 100644 --- a/readme.md +++ b/readme.md @@ -1,61 +1,82 @@ + # audio-speaker -> Output audio natively in node. +> Write audio to the speaker in node/browser [![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) -Note: Browser implementation is deprecated and will be replaced soon. +Write [AudioBuffers](https://github.com/audiojs/audio-buffer) to the speaker in node or browser. + +```js +var generator = require('audio-generator') +var speaker = require('audio-speaker') + +// Create a sine wave: +var sine = generator(time => { + return Math.sin(PI * 2 * time * 440) +}) + +(function loop () { + speaker(sine(), loop) +})() +``` + +(See more examples in [`test`](test.js)) + +## Packages + +If you need some other way to write to speaker, here is a list of implementations: + + - [`audio-speaker`](https://github.com/audiojs/audio-speaker) for a plain function (this module) + - [`audio-speaker-stream`](https://github.com/audiojs/pull-audio-speaker) for use with [Node streams](https://nodejs.org/api/stream.html) + - [`pull-audio-speaker`](https://github.com/audiojs/pull-audio-speaker) for a [pull-stream](https://github.com/pull-stream/pull-stream) sink function ## Install -Node: `npm install audio-speaker` -Browser: `npm install audio-speaker --no-optional` +```sh +npm i audio-speaker +``` + +**Note:** When only on browser you can use `--no-optional` to skip downloading the Node.js backend. ## Usage -Accepts options in main function: +### `createSpeaker(options?)` - - channels (default 1) - - sampleRate (default 44100) - - endianess (default 'LE') - - bitDepth (default 16) - - signed (default true) - - float (default false) - - autoFlush (default false) +Accepts the options: -More documentation on these options will be added soon. + - `autoFlush` (default `true`) + - `channels` (default `1`) + - `sampleRate` (default `44100`) + - `bitDepth` (default `16`) + - `signed` (default `true`) + - `float` (default `false`) + - `endianess` (default `'LE'`) -### Usage +Returns a speaker funciton you can use to write `AudioBuffer`s. ```js -var speaker = require('audio-speaker'); -var write = speaker(); -write(audioBuffer|data, callback); +var speaker = createSpeaker() +// Or with options: +var speaker = createSpeaker({ channels: 2, bitDepth: 8 }) ``` -### Example +### `speaker(buf, done?)` + +Writes an `AudioBuffer` to the speaker and plays it back. ```js -var speaker = require('audio-speaker') -var generator = require('audio-generator') +var sine = oscillator({ wave: 'sine', duration: 1 }) -var write = speaker({ autoFlush: true }) -var generate = generator(t => Math.sin(t * Math.PI * 2 * 440)) - -(function loop (err, chunk) { - if (err || chunk < 1) { - return - } else { - write(generate(), (err, chunk) => { - loop(err, chunk) - }) - } -})(); +write(sine(), err => { + // Finished +}) ``` -#### Also see +## Also see + + - [`web-audio-stream`](https://github.com/audiojs/web-audio-stream): Stream data to web-audio.
+ - [`audio-through`](http://npmjs.org/package/audio-through): Universal stream for processing audio.
+ - [`audio-feeder`](https://github.com/brion/audio-feeder): Cross-browser speaker for PCM data.
+ - [`mpg123`](https://github.com/audiojs/mpg123): Fork of mpg123 made to suit audio-speaker.
-> [mpg123](https://github.com/audiojs/mpg123) - modifications to mpg123 to suit audio-speaker.
-> [web-audio-stream](https://github.com/audiojs/web-audio-stream) — stream data to web-audio.
-> [audio-through](http://npmjs.org/package/audio-through) — universal stream for processing audio.
-> [audio-feeder](https://github.com/brion/audio-feeder) — cross-browser speaker for pcm data.
diff --git a/test.js b/test.js index a8ca836..71eff21 100644 --- a/test.js +++ b/test.js @@ -62,9 +62,7 @@ test('play sine', t => { // Ignore errors as we are intentionally cutting this short. return } else { - write(generate(), (err) => { - loop(err) - }) + write(generate(), loop) } })(); }) From 3134239ab2a7a2dd36bed1d77700e822b8c51980 Mon Sep 17 00:00:00 2001 From: Jamen Marzonie Date: Sat, 24 Jun 2017 22:26:31 -0500 Subject: [PATCH 84/96] Fix minor things from Node impl and package.json --- index.js | 8 ++++---- package.json | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index e8d0110..beb7f85 100644 --- a/index.js +++ b/index.js @@ -4,7 +4,7 @@ var os = require('os') var pcm = require('pcm-util') var binding = require('audio-mpg123') -var audioSink = require('audio-sink/direct') +var isAudioBuffer = require('is-audio-buffer') function noop () {} var endianess = os.endianness() || 'LE' @@ -38,7 +38,6 @@ function Speaker (opts) { // Options we use directly var channels = options.channels var sampleRate = options.sampleRate - var blockAlign = options.bitDepth / 8 * options.channels var chunkSize = options.blockAlign * options.samplesPerFrame var autoFlush = options.autoFlush @@ -72,6 +71,7 @@ function Speaker (opts) { * @api public */ function write (buf, callback) { + if (!callback) callback = noop if (!handler) return callback(new Error('Write occurred after the speaker closed.')) if (busy) return callback(new Error('Write occurred before the speaker flushed.')) @@ -82,8 +82,8 @@ function Speaker (opts) { busy = true // TODO: Remove once binding takes ArrayBuffer directly - if (chunk) chunk = Buffer.from(pcm.toArrayBuffer(chunk, options)) - if (rest) rest = Buffer.from(pcm.toArrayBuffer(rest, options)) + if (chunk) chunk = isAudioBuffer(chunk) ? Buffer.from(pcm.toArrayBuffer(chunk, options)) : chunk + if (rest) rest = isAudioBuffer(rest) ? Buffer.from(pcm.toArrayBuffer(rest, options)) : rest var queue = !rest || !rest.length ? chunk : Buffer.concat([rest, chunk]) if (!queue) queue = new Buffer(0) // meh diff --git a/package.json b/package.json index c25a910..55eaa7b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "audio-speaker", "version": "2.0.0-5", - "description": "Output PCM data to a device or library.", + "description": "Write audio to the speaker in node/browser", "scripts": { "test": "node test", "test:browser": "budo test", @@ -29,9 +29,7 @@ "homepage": "https://github.com/audiojs/audio-speaker#readme", "dependencies": { "audio-context": "^1.0.1", - "audio-sink": "^1.1.6", "is-audio-buffer": "^1.0.11", - "is-browser": "^2.0.1", "object-assign": "^4.1.1", "pcm-util": "^3.0.0", "web-audio-write": "^1.2.1" From d8aa826637328e4487165a54164179fc1c7c3b3f Mon Sep 17 00:00:00 2001 From: Jamen Marzonie Date: Sat, 24 Jun 2017 23:40:02 -0500 Subject: [PATCH 85/96] Fix readme link to audio-speaker-stream --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index bcbad14..847fc43 100644 --- a/readme.md +++ b/readme.md @@ -28,7 +28,7 @@ var sine = generator(time => { If you need some other way to write to speaker, here is a list of implementations: - [`audio-speaker`](https://github.com/audiojs/audio-speaker) for a plain function (this module) - - [`audio-speaker-stream`](https://github.com/audiojs/pull-audio-speaker) for use with [Node streams](https://nodejs.org/api/stream.html) + - [`audio-speaker-stream`](https://github.com/audiojs/audio-speaker-stream) for use with [Node streams](https://nodejs.org/api/stream.html) - [`pull-audio-speaker`](https://github.com/audiojs/pull-audio-speaker) for a [pull-stream](https://github.com/pull-stream/pull-stream) sink function ## Install From cae046918b4c4c8df736220fca08c0044c5bd748 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 25 Jun 2017 01:23:25 -0400 Subject: [PATCH 86/96] Introduce pcm-convert --- index.js | 85 ++++++++++++++++++++++++++++++---------------------- package.json | 3 +- readme.md | 7 ++--- test.js | 8 +++-- 4 files changed, 57 insertions(+), 46 deletions(-) diff --git a/index.js b/index.js index beb7f85..49abf8a 100644 --- a/index.js +++ b/index.js @@ -1,14 +1,11 @@ /** @module audio-speaker/index */ 'use strict' -var os = require('os') -var pcm = require('pcm-util') +var convert = require('pcm-convert') var binding = require('audio-mpg123') var isAudioBuffer = require('is-audio-buffer') function noop () {} -var endianess = os.endianness() || 'LE' - module.exports = Speaker /** @@ -23,16 +20,13 @@ module.exports = Speaker function Speaker (opts) { var options = Object.assign({ channels: 1, - float: false, - bitDepth: 16, - signed: true, + format: 'float32', samplesPerFrame: 1024, sampleRate: 44100, - endianess: endianess, autoFlush: true }, opts) - var format = Speaker.getFormat(options) + var format = Speaker.getFormat(options.format) if (!format) throw new Error('Invalid format options.') // Options we use directly @@ -75,15 +69,33 @@ function Speaker (opts) { if (!handler) return callback(new Error('Write occurred after the speaker closed.')) if (busy) return callback(new Error('Write occurred before the speaker flushed.')) + //make sure audio buffer is converted to proper format + if (isAudioBuffer(buf)) { + if (buf._data) buf = buf._data + else { + var arr = new Float32Array(buf.length * buf.numberOfChannels) + for (var c = 0, l = buf.length; c < buf.numberOfChannels; c++) { + arr.set(buf.getChannelData(c), c*l) + } + buf = arr + } + + buf = Buffer.from(convert(buf, { + dtype: 'float32', + interleaved: false, + channels: buf.numberOfChannels + }, { + dtype: options.format + }) + ) + } + next(buf, null, callback) function next (chunk, rest, callback) { if (handler) { busy = true - - // TODO: Remove once binding takes ArrayBuffer directly - if (chunk) chunk = isAudioBuffer(chunk) ? Buffer.from(pcm.toArrayBuffer(chunk, options)) : chunk - if (rest) rest = isAudioBuffer(rest) ? Buffer.from(pcm.toArrayBuffer(rest, options)) : rest + var queue = !rest || !rest.length ? chunk : Buffer.concat([rest, chunk]) if (!queue) queue = new Buffer(0) // meh @@ -133,29 +145,30 @@ function Speaker (opts) { } } -Speaker.getFormat = (format) => { - var f = null; - if (format.bitDepth == 32 && format.float && format.signed) { - f = binding.MPG123_ENC_FLOAT_32; - } else if (format.bitDepth == 64 && format.float && format.signed) { - f = binding.MPG123_ENC_FLOAT_64; - } else if (format.bitDepth == 8 && format.signed) { - f = binding.MPG123_ENC_SIGNED_8; - } else if (format.bitDepth == 8 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_8; - } else if (format.bitDepth == 16 && format.signed) { - f = binding.MPG123_ENC_SIGNED_16; - } else if (format.bitDepth == 16 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_16; - } else if (format.bitDepth == 24 && format.signed) { - f = binding.MPG123_ENC_SIGNED_24; - } else if (format.bitDepth == 24 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_24; - } else if (format.bitDepth == 32 && format.signed) { - f = binding.MPG123_ENC_SIGNED_32; - } else if (format.bitDepth == 32 && !format.signed) { - f = binding.MPG123_ENC_UNSIGNED_32; +Speaker.getFormat = function (format) { + switch (format) { + case 'uint8': + case 'uint8_clamped': + return binding.MPG123_ENC_UNSIGNED_8; + case 'uint16': + return binding.MPG123_ENC_UNSIGNED_16; + case 'uint24': + return binding.MPG123_ENC_UNSIGNED_24; + case 'uint32': + return binding.MPG123_ENC_UNSIGNED_32; + case 'int8': + return binding.MPG123_ENC_SIGNED_8; + case 'int16': + return binding.MPG123_ENC_SIGNED_16; + case 'int24': + return binding.MPG123_ENC_SIGNED_24; + case 'int32': + return binding.MPG123_ENC_SIGNED_32; + case 'array': + case 'float32': + return binding.MPG123_ENC_FLOAT_32; + case 'float64': + return binding.MPG123_ENC_FLOAT_64; } - return f; } diff --git a/package.json b/package.json index 55eaa7b..d9b1847 100644 --- a/package.json +++ b/package.json @@ -31,14 +31,13 @@ "audio-context": "^1.0.1", "is-audio-buffer": "^1.0.11", "object-assign": "^4.1.1", - "pcm-util": "^3.0.0", + "pcm-convert": "^1.0.0", "web-audio-write": "^1.2.1" }, "devDependencies": { "audio-buffer-utils": "^5.0.1", "audio-generator": "^2.1.2", "audio-lena": "^2.1.0", - "eslint": "^4.0.0", "pcm-volume": "^1.0.0", "tape": "^4.6.3" }, diff --git a/readme.md b/readme.md index bcbad14..d7c0760 100644 --- a/readme.md +++ b/readme.md @@ -48,12 +48,9 @@ Accepts the options: - `autoFlush` (default `true`) - `channels` (default `1`) - `sampleRate` (default `44100`) - - `bitDepth` (default `16`) - - `signed` (default `true`) - - `float` (default `false`) - - `endianess` (default `'LE'`) + - `format` (default: `int16 le`) -Returns a speaker funciton you can use to write `AudioBuffer`s. +Returns a speaker funciton you can use to write `AudioBuffer`s. ```js var speaker = createSpeaker() diff --git a/test.js b/test.js index 71eff21..0fbda07 100644 --- a/test.js +++ b/test.js @@ -27,11 +27,12 @@ test('play noise', t => { }) -test('play lena', t => { +test.only('play lena', t => { t.plan(1) var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = util.create(LenaBuffer) + buf = util.slice(buf, 1) write(buf, (err) => { if (err) { @@ -48,7 +49,7 @@ test('play sine', t => { var generate = createGenerator(time => { return Math.sin(Math.PI * 2 * time * 440) - }, { duration: 4 }) + }, { duration: 1 }) var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: false }); @@ -62,7 +63,8 @@ test('play sine', t => { // Ignore errors as we are intentionally cutting this short. return } else { - write(generate(), loop) + let buf = generate() + write(buf, loop) } })(); }) From 8ff35ae3b6fdb63907630094b54664b087646ee4 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 25 Jun 2017 01:48:47 -0400 Subject: [PATCH 87/96] Fix endianness --- index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 49abf8a..5fab92e 100644 --- a/index.js +++ b/index.js @@ -20,7 +20,7 @@ module.exports = Speaker function Speaker (opts) { var options = Object.assign({ channels: 1, - format: 'float32', + format: 'int16', samplesPerFrame: 1024, sampleRate: 44100, autoFlush: true @@ -83,8 +83,10 @@ function Speaker (opts) { buf = Buffer.from(convert(buf, { dtype: 'float32', interleaved: false, - channels: buf.numberOfChannels + channels: buf.numberOfChannels, + endianness: 'le' }, { + endianness: 'be', dtype: options.format }) ) From 394eb4fe681bf966cf8f24bb92ec7e98fe1df9a6 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 25 Jun 2017 01:51:26 -0400 Subject: [PATCH 88/96] Fix buffer creation --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 5fab92e..64c4f7c 100644 --- a/index.js +++ b/index.js @@ -86,9 +86,9 @@ function Speaker (opts) { channels: buf.numberOfChannels, endianness: 'le' }, { - endianness: 'be', + endianness: 'le', dtype: options.format - }) + }).buffer ) } From 51d4f9d551c36f932b1d499bd0d58d7ea7e37a8b Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 25 Jun 2017 01:52:57 -0400 Subject: [PATCH 89/96] Fix tests --- test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test.js b/test.js index 0fbda07..d003556 100644 --- a/test.js +++ b/test.js @@ -27,12 +27,12 @@ test('play noise', t => { }) -test.only('play lena', t => { +test('play lena', t => { t.plan(1) var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) var buf = util.create(LenaBuffer) - buf = util.slice(buf, 1) + buf = util.slice(buf, 0, 44100) write(buf, (err) => { if (err) { @@ -56,7 +56,7 @@ test('play sine', t => { setTimeout(() => { write.end() t.pass('Output successful.') - }, 1000); + }, 500); (function loop (err) { if (err) { From 75b92c2ca48e9e4bc62708c371f78f47fb877b2b Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 25 Jun 2017 01:53:20 -0400 Subject: [PATCH 90/96] Make test work (yay) --- test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.js b/test.js index d003556..02ab767 100644 --- a/test.js +++ b/test.js @@ -49,7 +49,7 @@ test('play sine', t => { var generate = createGenerator(time => { return Math.sin(Math.PI * 2 * time * 440) - }, { duration: 1 }) + }, { duration: 1, channels: 1 }) var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: false }); From 07ca65a734e29ca4ad40e923d12cb1cde78c920b Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 25 Jun 2017 11:35:30 -0400 Subject: [PATCH 91/96] Make tests pass perfectly --- index.js | 11 +++++------ package.json | 2 +- test.js | 9 ++++++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index 64c4f7c..652044d 100644 --- a/index.js +++ b/index.js @@ -73,8 +73,8 @@ function Speaker (opts) { if (isAudioBuffer(buf)) { if (buf._data) buf = buf._data else { - var arr = new Float32Array(buf.length * buf.numberOfChannels) - for (var c = 0, l = buf.length; c < buf.numberOfChannels; c++) { + var arr = new Float32Array(buf.length * channels) + for (var c = 0, l = buf.length; c < channels; c++) { arr.set(buf.getChannelData(c), c*l) } buf = arr @@ -83,11 +83,10 @@ function Speaker (opts) { buf = Buffer.from(convert(buf, { dtype: 'float32', interleaved: false, - channels: buf.numberOfChannels, - endianness: 'le' + channels: channels }, { - endianness: 'le', - dtype: options.format + dtype: options.format, + interleaved: true }).buffer ) } diff --git a/package.json b/package.json index d9b1847..ef39023 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "audio-context": "^1.0.1", "is-audio-buffer": "^1.0.11", "object-assign": "^4.1.1", - "pcm-convert": "^1.0.0", + "pcm-convert": "^1.1.0", "web-audio-write": "^1.2.1" }, "devDependencies": { diff --git a/test.js b/test.js index 02ab767..60feaa4 100644 --- a/test.js +++ b/test.js @@ -48,10 +48,13 @@ test('play sine', t => { t.plan(1) var generate = createGenerator(time => { - return Math.sin(Math.PI * 2 * time * 440) - }, { duration: 1, channels: 1 }) + return [ + Math.sin(Math.PI * 2 * time * 439), + Math.sin(Math.PI * 2 * time * 441) + ] + }, { duration: 1, channels: 2 }) - var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true, autoFlush: false }); + var write = createSpeaker({ channels: 2, autoFlush: false }); setTimeout(() => { write.end() From ddb35926adf95ff8f9854ea4db4b5543e3714fd8 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 25 Jun 2017 11:48:28 -0400 Subject: [PATCH 92/96] Fix formal details --- package.json | 4 ++++ readme.md | 40 +++++++++++++++++----------------------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index ef39023..b9d685b 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,10 @@ "native" ], "author": "Connor Hartley (https://github.com/connorhartley)", + "contributors": [ + "Jamen Marz ", + "Dima Yv " + ], "license": "MIT", "bugs": { "url": "https://github.com/audiojs/audio-speaker/issues" diff --git a/readme.md b/readme.md index 9df437a..c6841c7 100644 --- a/readme.md +++ b/readme.md @@ -1,17 +1,12 @@ +# audio-speaker [![unstable](https://img.shields.io/badge/stability-unstable-green.svg)](http://github.com/badges/stability-badges) [![Build Status](https://img.shields.io/travis/audiojs/audio-speaker.svg)](https://travis-ci.org/audiojs/audio-speaker) [![Greenkeeper badge](https://badges.greenkeeper.io/audiojs/audio-speaker.svg)](https://greenkeeper.io/) -# audio-speaker - -> Write audio to the speaker in node/browser - -[![Build Status](https://api.travis-ci.org/audiojs/audio-speaker.svg?branch=release-2.0)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) - -Write [AudioBuffers](https://github.com/audiojs/audio-buffer) to the speaker in node or browser. +Write [AudioBuffer](https://github.com/audiojs/audio-buffer)/ArrayBuffer/ArrayBufferView/Buffer to the speaker in node or browser. ```js var generator = require('audio-generator') var speaker = require('audio-speaker') -// Create a sine wave: +// Create a 440Hz sine wave var sine = generator(time => { return Math.sin(PI * 2 * time * 440) }) @@ -21,15 +16,8 @@ var sine = generator(time => { })() ``` -(See more examples in [`test`](test.js)) - -## Packages +See more examples in [`test`](test.js). -If you need some other way to write to speaker, here is a list of implementations: - - - [`audio-speaker`](https://github.com/audiojs/audio-speaker) for a plain function (this module) - - [`audio-speaker-stream`](https://github.com/audiojs/audio-speaker-stream) for use with [Node streams](https://nodejs.org/api/stream.html) - - [`pull-audio-speaker`](https://github.com/audiojs/pull-audio-speaker) for a [pull-stream](https://github.com/pull-stream/pull-stream) sink function ## Install @@ -41,7 +29,7 @@ npm i audio-speaker ## Usage -### `createSpeaker(options?)` +### `let speaker = createSpeaker(options?)` Accepts the options: @@ -54,7 +42,8 @@ Returns a speaker funciton you can use to write `AudioBuffer`s. ```js var speaker = createSpeaker() -// Or with options: + +// Or with options var speaker = createSpeaker({ channels: 2, bitDepth: 8 }) ``` @@ -70,10 +59,15 @@ write(sine(), err => { }) ``` -## Also see +## Related + + - [`audio-speaker-stream`](https://github.com/audiojs/audio-speaker-stream) for use with [Node streams](https://nodejs.org/api/stream.html). + - [`pull-audio-speaker`](https://github.com/audiojs/pull-audio-speaker) for a [pull-stream](https://github.com/pull-stream/pull-stream) sink function. + - [`web-audio-stream`](https://github.com/audiojs/web-audio-stream): Stream data to web-audio. + - [`audio-through`](http://npmjs.org/package/audio-through): Universal stream for processing audio. + - [`audio-feeder`](https://github.com/brion/audio-feeder): Cross-browser speaker for PCM data. + - [`audio-mpg123`](https://github.com/audiojs/audio-mpg123): Fork of mpg123 made to suit audio-speaker. - - [`web-audio-stream`](https://github.com/audiojs/web-audio-stream): Stream data to web-audio.
- - [`audio-through`](http://npmjs.org/package/audio-through): Universal stream for processing audio.
- - [`audio-feeder`](https://github.com/brion/audio-feeder): Cross-browser speaker for PCM data.
- - [`mpg123`](https://github.com/audiojs/mpg123): Fork of mpg123 made to suit audio-speaker.
+## License +© 2017 AudioJS. MIT License From 09a8f99fa1301d709b040a5568ec104380028a3d Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 25 Jun 2017 12:00:34 -0400 Subject: [PATCH 93/96] Update readme/details --- index.js | 4 +--- readme.md | 10 +++------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index 652044d..2b7c955 100644 --- a/index.js +++ b/index.js @@ -20,9 +20,8 @@ module.exports = Speaker function Speaker (opts) { var options = Object.assign({ channels: 1, - format: 'int16', - samplesPerFrame: 1024, sampleRate: 44100, + format: 'int16', autoFlush: true }, opts) @@ -32,7 +31,6 @@ function Speaker (opts) { // Options we use directly var channels = options.channels var sampleRate = options.sampleRate - var chunkSize = options.blockAlign * options.samplesPerFrame var autoFlush = options.autoFlush // Writing state diff --git a/readme.md b/readme.md index c6841c7..ab81f97 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ # audio-speaker [![unstable](https://img.shields.io/badge/stability-unstable-green.svg)](http://github.com/badges/stability-badges) [![Build Status](https://img.shields.io/travis/audiojs/audio-speaker.svg)](https://travis-ci.org/audiojs/audio-speaker) [![Greenkeeper badge](https://badges.greenkeeper.io/audiojs/audio-speaker.svg)](https://greenkeeper.io/) -Write [AudioBuffer](https://github.com/audiojs/audio-buffer)/ArrayBuffer/ArrayBufferView/Buffer to the speaker in node or browser. +Write [AudioBuffer](https://github.com/audiojs/audio-buffer) to the speaker in node or browser. ```js var generator = require('audio-generator') @@ -36,7 +36,6 @@ Accepts the options: - `autoFlush` (default `true`) - `channels` (default `1`) - `sampleRate` (default `44100`) - - `format` (default: `int16 le`) Returns a speaker funciton you can use to write `AudioBuffer`s. @@ -44,7 +43,7 @@ Returns a speaker funciton you can use to write `AudioBuffer`s. var speaker = createSpeaker() // Or with options -var speaker = createSpeaker({ channels: 2, bitDepth: 8 }) +var speaker = createSpeaker({ channels: 2, sampleRate: 48000 }) ``` ### `speaker(buf, done?)` @@ -55,7 +54,7 @@ Writes an `AudioBuffer` to the speaker and plays it back. var sine = oscillator({ wave: 'sine', duration: 1 }) write(sine(), err => { - // Finished + // Played }) ``` @@ -63,9 +62,6 @@ write(sine(), err => { - [`audio-speaker-stream`](https://github.com/audiojs/audio-speaker-stream) for use with [Node streams](https://nodejs.org/api/stream.html). - [`pull-audio-speaker`](https://github.com/audiojs/pull-audio-speaker) for a [pull-stream](https://github.com/pull-stream/pull-stream) sink function. - - [`web-audio-stream`](https://github.com/audiojs/web-audio-stream): Stream data to web-audio. - - [`audio-through`](http://npmjs.org/package/audio-through): Universal stream for processing audio. - - [`audio-feeder`](https://github.com/brion/audio-feeder): Cross-browser speaker for PCM data. - [`audio-mpg123`](https://github.com/audiojs/audio-mpg123): Fork of mpg123 made to suit audio-speaker. ## License From d70877b4699515ed6dadd9b298c5f8c3ced813e9 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 25 Jun 2017 12:14:05 -0400 Subject: [PATCH 94/96] Simplify inner structure --- index.js | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/index.js b/index.js index 2b7c955..ad70661 100644 --- a/index.js +++ b/index.js @@ -20,8 +20,8 @@ module.exports = Speaker function Speaker (opts) { var options = Object.assign({ channels: 1, - sampleRate: 44100, format: 'int16', + sampleRate: 44100, autoFlush: true }, opts) @@ -32,6 +32,7 @@ function Speaker (opts) { var channels = options.channels var sampleRate = options.sampleRate var autoFlush = options.autoFlush + var chunkSize = NaN//1024 // Writing state var busy = false @@ -92,31 +93,29 @@ function Speaker (opts) { next(buf, null, callback) function next (chunk, rest, callback) { - if (handler) { - busy = true - - var queue = !rest || !rest.length ? chunk : Buffer.concat([rest, chunk]) - if (!queue) queue = new Buffer(0) // meh - - var output = queue.length > chunkSize ? queue.slice(0, chunkSize) : queue - var remaining = queue.length > chunkSize ? queue.slice(chunkSize, queue.length) : new Buffer(0) - - binding.write(handler, output, output.length, (written) => { - // Play next chunk - if (rest && rest.length) return next(null, remaining, callback) - // Stream finished. Flush and callback - var err = null - if (autoFlush) { - binding.flush(handler, (success) => { - if (!success) err = new Error('Flushing speaker failed') - }) - } - busy = false - callback(err) - }) - } else { - callback(new Error('Speaker closed while writing')) - } + if (!handler) return callback(new Error('Speaker closed while writing')) + + busy = true + + var queue = !rest || !rest.length ? chunk : Buffer.concat([rest, chunk]) + if (!queue) queue = new Buffer(0) // meh + + var output = queue.length > chunkSize ? queue.slice(0, chunkSize) : queue + var remaining = queue.length > chunkSize ? queue.slice(chunkSize, queue.length) : new Buffer(0) + + binding.write(handler, output, output.length, (written) => { + // Play next chunk + if (rest && rest.length) return next(null, remaining, callback) + // Stream finished. Flush and callback + var err = null + if (autoFlush) { + binding.flush(handler, (success) => { + if (!success) err = new Error('Flushing speaker failed') + }) + } + busy = false + callback(err) + }) } } From 856d9837340ab22639315957b13b3c135e01e9e6 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 26 Jun 2017 01:52:27 -0400 Subject: [PATCH 95/96] Update pcm-convert --- index.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index ad70661..83a36c4 100644 --- a/index.js +++ b/index.js @@ -80,11 +80,11 @@ function Speaker (opts) { } buf = Buffer.from(convert(buf, { - dtype: 'float32', + type: 'float32', interleaved: false, channels: channels }, { - dtype: options.format, + type: options.format, interleaved: true }).buffer ) diff --git a/package.json b/package.json index b9d685b..346efe7 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "audio-context": "^1.0.1", "is-audio-buffer": "^1.0.11", "object-assign": "^4.1.1", - "pcm-convert": "^1.1.0", + "pcm-convert": "^1.3.0", "web-audio-write": "^1.2.1" }, "devDependencies": { From 4adf45e9ef1b6e390c99cabec079aa96b18efe11 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 26 Jun 2017 02:01:24 -0400 Subject: [PATCH 96/96] Return dtypes --- index.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 83a36c4..ad70661 100644 --- a/index.js +++ b/index.js @@ -80,11 +80,11 @@ function Speaker (opts) { } buf = Buffer.from(convert(buf, { - type: 'float32', + dtype: 'float32', interleaved: false, channels: channels }, { - type: options.format, + dtype: options.format, interleaved: true }).buffer ) diff --git a/package.json b/package.json index 346efe7..d7ae78b 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "audio-context": "^1.0.1", "is-audio-buffer": "^1.0.11", "object-assign": "^4.1.1", - "pcm-convert": "^1.3.0", + "pcm-convert": "^1.3.1", "web-audio-write": "^1.2.1" }, "devDependencies": {