New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

ableton-js

Package Overview
Dependencies
Maintainers
1
Versions
118
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ableton-js - npm Package Compare versions

Comparing version 2.9.1 to 3.0.0

util/logger.d.ts

8

CHANGELOG.md

@@ -7,4 +7,12 @@ ### Changelog

#### [v3.0.0](https://github.com/leolabs/ableton.js/compare/v2.9.1...v3.0.0)
- :sparkles: Don't rely on fixed ports, make server and client bind to a random free one [`54f7737`](https://github.com/leolabs/ableton.js/commit/54f773758ec359ab9b5bc3f5fd3e7c96cae4e8b8)
- :sparkles: Add a timeout param to the start method [`600e752`](https://github.com/leolabs/ableton.js/commit/600e752c5f7c0e349b0cb69aaf4b8f6238f6a1d4)
- :loud_sound: Add a logger interface for the library to log information [`e31e9cc`](https://github.com/leolabs/ableton.js/commit/e31e9cc1a33b90e0c482e87eae645976a8668ad2)
#### [v2.9.1](https://github.com/leolabs/ableton.js/compare/v2.9.0...v2.9.1)
> 21 February 2023
- :sparkles: Add support for available_(input/output)_routing_(channels/types) [`0c09881`](https://github.com/leolabs/ableton.js/commit/0c098819369cccf257284ad4510178833853d1e5)

@@ -11,0 +19,0 @@ - Use enum-style values for NavDirection [`713f864`](https://github.com/leolabs/ableton.js/commit/713f86475036debabf4e401c87ddb8b08510d262)

28

index.d.ts

@@ -9,2 +9,3 @@ /// <reference types="node" />

import { Cache } from "./util/cache";
import { Logger } from "./util/logger";
interface Command {

@@ -40,9 +41,10 @@ uuid: string;

export interface AbletonOptions {
host?: string;
sendPort?: number;
listenPort?: number;
serverPortFile?: string;
clientPortFile?: string;
heartbeatInterval?: number;
cacheOptions?: LruCache.Options<string, any>;
logger?: Logger;
}
export declare class Ableton extends EventEmitter implements ConnectionEventEmitter {
private options?;
private client;

@@ -56,5 +58,3 @@ private msgMap;

private latency;
private host;
private sendPort;
private listenPort;
private serverPort;
cache: Cache;

@@ -65,5 +65,17 @@ song: Song;

midi: Midi;
constructor(options?: AbletonOptions);
close(): void;
private clientPortFile;
private serverPortFile;
private logger;
constructor(options?: AbletonOptions | undefined);
/**
* Starts the server and waits for a connection with Live to be established.
*
* @param timeoutMs
* If set, the function will throw an error if it can't establish a connection
* in the given time. Should be higher than 2000ms to avoid false positives.
*/
start(timeoutMs?: number): Promise<void>;
/** Closes the client */
close(): Promise<unknown>;
/**
* Returns the latency between the last command and its response.

@@ -70,0 +82,0 @@ * This is a rough measurement, so don't rely too much on it.

@@ -90,2 +90,4 @@ "use strict";

exports.getPackageVersion = exports.Ableton = exports.TimeoutError = void 0;
var os_1 = __importDefault(require("os"));
var path_1 = __importDefault(require("path"));
var dgram_1 = __importDefault(require("dgram"));

@@ -97,2 +99,4 @@ var events_1 = require("events");

var lru_cache_1 = __importDefault(require("lru-cache"));
var fs_1 = require("fs");
var promises_1 = require("fs/promises");
var song_1 = require("./ns/song");

@@ -104,2 +108,4 @@ var internal_1 = require("./ns/internal");

var cache_1 = require("./util/cache");
var SERVER_PORT_FILE = "ableton-js-server.port";
var CLIENT_PORT_FILE = "ableton-js-client.port";
var TimeoutError = /** @class */ (function (_super) {

@@ -121,2 +127,3 @@ __extends(TimeoutError, _super);

var _this = _super.call(this) || this;
_this.options = options;
_this.msgMap = new Map();

@@ -132,57 +139,174 @@ _this.eventListeners = new Map();

_this.midi = new midi_1.Midi(_this);
_this.host = (_a = options === null || options === void 0 ? void 0 : options.host) !== null && _a !== void 0 ? _a : "127.0.0.1";
_this.sendPort = (_b = options === null || options === void 0 ? void 0 : options.sendPort) !== null && _b !== void 0 ? _b : 39041;
_this.listenPort = (_c = options === null || options === void 0 ? void 0 : options.listenPort) !== null && _c !== void 0 ? _c : 39031;
_this.client = dgram_1.default.createSocket({ type: "udp4" });
_this.client.bind(_this.listenPort, _this.host);
_this.client.addListener("message", _this.handleIncoming.bind(_this));
_this.logger = options === null || options === void 0 ? void 0 : options.logger;
_this.cache = new lru_cache_1.default(__assign({ max: 500, ttl: 1000 * 60 * 10 }, options === null || options === void 0 ? void 0 : options.cacheOptions));
var heartbeat = function () { return __awaiter(_this, void 0, void 0, function () {
var e_1;
return __generator(this, function (_a) {
switch (_a.label) {
_this.clientPortFile = path_1.default.join(os_1.default.tmpdir(), (_b = (_a = _this.options) === null || _a === void 0 ? void 0 : _a.clientPortFile) !== null && _b !== void 0 ? _b : CLIENT_PORT_FILE);
_this.serverPortFile = path_1.default.join(os_1.default.tmpdir(), (_d = (_c = _this.options) === null || _c === void 0 ? void 0 : _c.serverPortFile) !== null && _d !== void 0 ? _d : SERVER_PORT_FILE);
return _this;
}
/**
* Starts the server and waits for a connection with Live to be established.
*
* @param timeoutMs
* If set, the function will throw an error if it can't establish a connection
* in the given time. Should be higher than 2000ms to avoid false positives.
*/
Ableton.prototype.start = function (timeoutMs) {
var _a, _b, _c, _d;
return __awaiter(this, void 0, void 0, function () {
var connection, timeout, heartbeat;
var _this = this;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
this.cancelConnectionEvent = false;
_a.label = 1;
this.client = dgram_1.default.createSocket({ type: "udp4" });
this.client.addListener("message", this.handleIncoming.bind(this));
this.client.addListener("listening", function () { return __awaiter(_this, void 0, void 0, function () {
var clientPort;
var _a, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
clientPort = (_a = this.client) === null || _a === void 0 ? void 0 : _a.address().port;
(_b = this.logger) === null || _b === void 0 ? void 0 : _b.info("Bound client to port:", { clientPort: clientPort });
// Write used port to a file to Live can read from it
return [4 /*yield*/, promises_1.writeFile(this.clientPortFile, String(clientPort))];
case 1:
// Write used port to a file to Live can read from it
_c.sent();
return [2 /*return*/];
}
});
}); });
this.client.bind(undefined, "127.0.0.1");
// Wait for the server port file to exist
return [4 /*yield*/, new Promise(function (res) { return __awaiter(_this, void 0, void 0, function () {
var serverPort, e_1;
var _this = this;
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 2, , 3]);
return [4 /*yield*/, promises_1.readFile(this.serverPortFile)];
case 1:
serverPort = _b.sent();
this.serverPort = Number(serverPort.toString());
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.info("Server port:", { port: this.serverPort });
res();
return [3 /*break*/, 3];
case 2:
e_1 = _b.sent();
return [3 /*break*/, 3];
case 3:
// Set up a watcher in case the server port changes
fs_1.watchFile(this.serverPortFile, function (curr) { return __awaiter(_this, void 0, void 0, function () {
var serverPort, newPort;
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!curr.isFile()) return [3 /*break*/, 2];
return [4 /*yield*/, promises_1.readFile(this.serverPortFile)];
case 1:
serverPort = _b.sent();
newPort = Number(serverPort.toString());
if (!isNaN(newPort) && newPort !== this.serverPort) {
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.info("Server port changed:", { port: newPort });
this.serverPort = Number(serverPort.toString());
}
res();
_b.label = 2;
case 2: return [2 /*return*/];
}
});
}); });
return [2 /*return*/];
}
});
}); })];
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.song.get("current_song_time")];
// Wait for the server port file to exist
_e.sent();
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.info("Checking connection...");
connection = new Promise(function (res) { return _this.once("connect", res); });
if (!timeoutMs) return [3 /*break*/, 3];
timeout = new Promise(function (_, rej) {
return setTimeout(function () { return rej("Connection timed out."); }, timeoutMs);
});
return [4 /*yield*/, Promise.race([connection, timeout])];
case 2:
_a.sent();
if (!this._isConnected && !this.cancelConnectionEvent) {
this._isConnected = true;
this.emit("connect", "heartbeat");
}
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
if (this._isConnected && !this.cancelConnectionEvent) {
this._isConnected = false;
this.eventListeners.clear();
this.msgMap.forEach(function (msg) { return msg.clearTimeout(); });
this.msgMap.clear();
this.emit("disconnect", "heartbeat");
}
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
_e.sent();
return [3 /*break*/, 5];
case 3: return [4 /*yield*/, connection];
case 4:
_e.sent();
_e.label = 5;
case 5:
(_b = this.logger) === null || _b === void 0 ? void 0 : _b.info("Got connection!");
heartbeat = function () { return __awaiter(_this, void 0, void 0, function () {
var e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.cancelConnectionEvent = false;
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.internal.get("ping")];
case 2:
_a.sent();
if (!this._isConnected && !this.cancelConnectionEvent) {
this._isConnected = true;
this.emit("connect", "heartbeat");
}
return [3 /*break*/, 4];
case 3:
e_2 = _a.sent();
if (this._isConnected && !this.cancelConnectionEvent) {
this._isConnected = false;
this.eventListeners.clear();
this.msgMap.forEach(function (msg) { return msg.clearTimeout(); });
this.msgMap.clear();
this.emit("disconnect", "heartbeat");
}
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
}); };
this.heartbeatInterval = setInterval(heartbeat, (_d = (_c = this.options) === null || _c === void 0 ? void 0 : _c.heartbeatInterval) !== null && _d !== void 0 ? _d : 2000);
heartbeat();
this.internal
.get("version")
.then(function (v) {
var jsVersion = package_version_1.getPackageVersion();
if (semver_1.default.lt(v, jsVersion)) {
console.warn("The installed version of your AbletonJS plugin (" + v + ") is lower than the JS library (" + jsVersion + ").", "Please update your AbletonJS plugin to the latest version: https://git.io/JvaOu");
}
})
.catch(function () { });
return [2 /*return*/];
}
});
}); };
_this.heartbeatInterval = setInterval(heartbeat, (_d = options === null || options === void 0 ? void 0 : options.heartbeatInterval) !== null && _d !== void 0 ? _d : 2000);
heartbeat();
_this.internal
.get("version")
.then(function (v) {
var jsVersion = package_version_1.getPackageVersion();
if (semver_1.default.lt(v, jsVersion)) {
console.warn("The installed version of your AbletonJS plugin (" + v + ") is lower than the JS library (" + jsVersion + ").", "Please update your AbletonJS plugin to the latest version: https://git.io/JvaOu");
}
})
.catch(function () { });
return _this;
}
});
};
/** Closes the client */
Ableton.prototype.close = function () {
this.cancelConnectionEvent = true;
clearInterval(this.heartbeatInterval);
this.client.close();
return __awaiter(this, void 0, void 0, function () {
var closePromise;
var _this = this;
return __generator(this, function (_a) {
this.cancelConnectionEvent = true;
fs_1.unwatchFile(this.serverPortFile);
if (this.heartbeatInterval) {
clearInterval(this.heartbeatInterval);
}
if (this.client) {
closePromise = new Promise(function (res) { var _a; return (_a = _this.client) === null || _a === void 0 ? void 0 : _a.once("close", res); });
this.client.close();
return [2 /*return*/, closePromise];
}
return [2 /*return*/];
});
});
};

@@ -217,2 +341,3 @@ /**

Ableton.prototype.handleUncompressedMessage = function (msg) {
var _a;
this.emit("raw_message", msg);

@@ -242,2 +367,8 @@ var data = JSON.parse(msg);

if (data.event === "connect") {
if (data.data.port && data.data.port !== this.serverPort) {
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.info("Got new server port via connect:", {
port: data.data.port,
});
this.serverPort = data.data.port;
}
if (this._isConnected === false) {

@@ -279,4 +410,3 @@ this._isConnected = true;

"Please make sure that Ableton is running and that you have the latest",
"version of AbletonJS' midi script installed and renamed to \"AbletonJS\", listening on port",
_this.sendPort + " and sending on port " + _this.listenPort + ".",
"version of AbletonJS' MIDI script installed and renamed to \"AbletonJS\".",
].join(" "), payload));

@@ -428,2 +558,5 @@ }, timeout);

Ableton.prototype.sendRaw = function (msg) {
if (!this.client || !this.serverPort) {
throw new Error("The client hasn't been started yet. Please call start() first.");
}
var buffer = zlib_1.deflateSync(Buffer.from(msg));

@@ -441,3 +574,3 @@ // Based on this thread, 7500 bytes seems like a safe value

]);
this.client.send(chunk, 0, chunk.length, this.sendPort, this.host);
this.client.send(chunk, 0, chunk.length, this.serverPort, "127.0.0.1");
}

@@ -444,0 +577,0 @@ };

@@ -5,2 +5,3 @@ import { Ableton } from "..";

version: string;
ping: boolean;
}

@@ -7,0 +8,0 @@ export interface TransformedProperties {

{
"name": "ableton-js",
"version": "2.9.1",
"version": "3.0.0",
"description": "Control Ableton Live from Node",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -54,2 +54,5 @@ # Ableton.js

const test = async () => {
// Establishes a connection with Live
await ableton.start();
// Observe the current playback state and tempo

@@ -98,2 +101,7 @@ ableton.song.addListener("is_playing", (p) => console.log("Playing:", p));

### Used Ports
Both the client and the server bind to a random available port and store that
port in a local file so the other side knows which port to send messages to.
### Compression and Chunking

@@ -100,0 +108,0 @@

@@ -48,13 +48,16 @@ "use strict";

ab.on("error", console.error);
_a.label = 1;
return [4 /*yield*/, ab.start(2000)];
case 1:
_a.trys.push([1, , 3, 4]);
_a.sent();
_a.label = 2;
case 2:
_a.trys.push([2, , 4, 5]);
return [4 /*yield*/, callback(ab)];
case 2:
case 3:
_a.sent();
return [3 /*break*/, 4];
case 3:
return [3 /*break*/, 5];
case 4:
ab.close();
return [7 /*endfinally*/];
case 4: return [2 /*return*/];
case 5: return [2 /*return*/];
}

@@ -61,0 +64,0 @@ });

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc