ableton-js 3.1.1 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,8 +4,24 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ #### [v3.1.3](https://github.com/leolabs/ableton.js/compare/v3.1.2...v3.1.3)
8
+
9
+ - :bug: Fix opening a project file from within Finder closing all socket and file handles [`6cf2440`](https://github.com/leolabs/ableton.js/commit/6cf244057797dd45a7f5007af907947754449d5d)
10
+ - :loud_sound: Log data that couldn't be sent [`e39c6c6`](https://github.com/leolabs/ableton.js/commit/e39c6c6b0b68823268ca715c486dbc1ab6ce7dec)
11
+ - :loud_sound: Improve logging for event handlers [`a1fa33b`](https://github.com/leolabs/ableton.js/commit/a1fa33bb9c1c6b05352ea845c24b4637c7f80094)
12
+
13
+ #### [v3.1.2](https://github.com/leolabs/ableton.js/compare/v3.1.1...v3.1.2)
14
+
15
+ > 26 February 2023
16
+
17
+ - :sparkles: Keep a handle to the client port file open for faster read performance [`2a0295d`](https://github.com/leolabs/ableton.js/commit/2a0295dff3022e3812c2a0f6077ffb7bdcd00bf0)
18
+ - :sparkles: Try re-using the previous port for a quicker reconnect [`5c77760`](https://github.com/leolabs/ableton.js/commit/5c777606ce97295429dcac1a5685a34c8aa5abe3)
19
+ - :bug: Fix double disconnect/connect event [`2f960be`](https://github.com/leolabs/ableton.js/commit/2f960be4c6d18b2668d15258914cd3b763be0f4a)
20
+
7
21
  #### [v3.1.1](https://github.com/leolabs/ableton.js/compare/v3.1.0...v3.1.1)
8
22
 
23
+ > 25 February 2023
24
+
9
25
  - :loud_sound: Log connect and disconnect events [`e69f610`](https://github.com/leolabs/ableton.js/commit/e69f61098d61fd4027db4e94aad8155db5dbb504)
10
26
  - :bug: Don't count a failed ping as a successful connection event [`217e91e`](https://github.com/leolabs/ableton.js/commit/217e91ed936326c29a391ace9dcbe831125f4fa2)
11
27
 
package/index.d.ts CHANGED
@@ -63,6 +63,7 @@ export declare class Ableton extends EventEmitter implements ConnectionEventEmit
63
63
  private serverPortFile;
64
64
  private logger;
65
65
  private clientState;
66
+ private cancelDisconnectEvent;
66
67
  constructor(options?: AbletonOptions | undefined);
67
68
  private handleConnect;
68
69
  private handleDisconnect;
package/index.js CHANGED
@@ -132,6 +132,7 @@ var Ableton = /** @class */ (function (_super) {
132
132
  _this.internal = new internal_1.Internal(_this);
133
133
  _this.midi = new midi_1.Midi(_this);
134
134
  _this.clientState = "closed";
135
+ _this.cancelDisconnectEvent = false;
135
136
  _this.logger = options === null || options === void 0 ? void 0 : options.logger;
136
137
  _this.cache = new lru_cache_1.default(__assign({ max: 500, ttl: 1000 * 60 * 10 }, options === null || options === void 0 ? void 0 : options.cacheOptions));
137
138
  _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);
@@ -290,17 +291,22 @@ var Ableton = /** @class */ (function (_super) {
290
291
  return __generator(this, function (_a) {
291
292
  switch (_a.label) {
292
293
  case 0:
293
- _a.trys.push([0, 2, , 3]);
294
+ _a.trys.push([0, 2, 3, 4]);
294
295
  return [4 /*yield*/, this.internal.get("ping")];
295
296
  case 1:
296
297
  _a.sent();
297
298
  this.handleConnect("heartbeat");
298
- return [3 /*break*/, 3];
299
+ return [3 /*break*/, 4];
299
300
  case 2:
300
301
  e_2 = _a.sent();
301
- this.handleDisconnect("heartbeat");
302
- return [3 /*break*/, 3];
303
- case 3: return [2 /*return*/];
302
+ if (!this.cancelDisconnectEvent) {
303
+ this.handleDisconnect("heartbeat");
304
+ }
305
+ return [3 /*break*/, 4];
306
+ case 3:
307
+ this.cancelDisconnectEvent = false;
308
+ return [7 /*endfinally*/];
309
+ case 4: return [2 /*return*/];
304
310
  }
305
311
  });
306
312
  }); };
@@ -378,7 +384,7 @@ var Ableton = /** @class */ (function (_super) {
378
384
  }
379
385
  };
380
386
  Ableton.prototype.handleUncompressedMessage = function (msg) {
381
- var _a, _b;
387
+ var _a, _b, _c, _d;
382
388
  this.emit("raw_message", msg);
383
389
  var data = JSON.parse(msg);
384
390
  var functionCallback = this.msgMap.get(data.uuid);
@@ -395,8 +401,11 @@ var Ableton = /** @class */ (function (_super) {
395
401
  return this.handleDisconnect("realtime");
396
402
  }
397
403
  if (data.event === "connect") {
398
- if (data.data.port && data.data.port !== this.serverPort) {
399
- (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info("Got new server port via connect:", {
404
+ // If some heartbeat ping from the old connection is still pending,
405
+ // cancel it to prevent a double disconnect/connect event.
406
+ this.cancelDisconnectEvent = true;
407
+ if (((_a = data.data) === null || _a === void 0 ? void 0 : _a.port) && ((_b = data.data) === null || _b === void 0 ? void 0 : _b.port) !== this.serverPort) {
408
+ (_c = this.logger) === null || _c === void 0 ? void 0 : _c.info("Got new server port via connect:", {
400
409
  port: data.data.port,
401
410
  });
402
411
  this.serverPort = data.data.port;
@@ -409,7 +418,7 @@ var Ableton = /** @class */ (function (_super) {
409
418
  }
410
419
  if (data.uuid) {
411
420
  this.emit("error", "Message could not be assigned to any request: " + msg);
412
- (_b = this.logger) === null || _b === void 0 ? void 0 : _b.warn("Message could not be assigned to any request:", {
421
+ (_d = this.logger) === null || _d === void 0 ? void 0 : _d.warn("Message could not be assigned to any request:", {
413
422
  msg: msg,
414
423
  });
415
424
  }
@@ -90,7 +90,8 @@ class Interface(object):
90
90
  value = self.get_prop(ns, prop)
91
91
  return self.socket.send(eventId, value)
92
92
 
93
- self.log_message("Attaching listener")
93
+ self.log_message("Attaching listener: " +
94
+ key + ", event ID: " + eventId)
94
95
  add_fn(fn)
95
96
  self.listeners[key] = {"id": eventId, "fn": fn}
96
97
  return eventId
@@ -13,4 +13,4 @@ class Internal(Interface):
13
13
  return True
14
14
 
15
15
  def get_version(self, ns):
16
- return "3.1.1"
16
+ return "3.1.3"
@@ -35,51 +35,90 @@ class Socket(object):
35
35
 
36
36
  def __init__(self, handler):
37
37
  self.input_handler = handler
38
- self._server_addr = ('127.0.0.1', 0)
39
- self._client_addr = ('127.0.0.1', 39031)
38
+ self._server_addr = ("0.0.0.0", 0)
39
+ self._client_addr = ("127.0.0.1", 39031)
40
+ self._socket = None
41
+
40
42
  self.read_remote_port()
41
- self.init_socket()
43
+ self.init_socket(True)
44
+
45
+ self.file_timer = Live.Base.Timer(callback=self.read_remote_port,
46
+ interval=1000, repeat=True)
47
+ self.file_timer.start()
48
+
49
+ def read_last_server_port(self):
50
+ try:
51
+ with open(server_port_path) as file:
52
+ port = int(file.read())
53
+
54
+ self.log_message("Stored server port: " + str(port))
55
+ return port
56
+ except Exception as e:
57
+ self.log_message(
58
+ "Couldn't read stored server port: " + str(e.args))
59
+ return None
42
60
 
43
61
  def read_remote_port(self):
44
62
  '''Reads the port our client is listening on'''
45
63
  try:
64
+ old_port = self._client_addr[1]
65
+
46
66
  with open(client_port_path) as file:
47
67
  port = int(file.read())
48
- if port != self._client_addr[1]:
49
- self.log_message("Client port changed: " + str(port))
50
- self._client_addr = ('127.0.0.1', port)
51
68
 
52
- if hasattr(self, "_socket"):
69
+ if port != old_port:
70
+ self.log_message("[" + str(id(self)) + "] Client port changed from " +
71
+ str(old_port) + " to " + str(port))
72
+ self._client_addr = ("127.0.0.1", port)
73
+
74
+ if self._socket:
53
75
  self.send("connect", {"port": self._server_addr[1]})
54
76
  except Exception as e:
55
- self.log_message("Couldn't read remote port:", str(e.args))
56
-
57
- t = Timer(1, self.read_remote_port)
58
- t.start()
59
-
60
- def init_socket(self):
61
- self._socket = socket.socket(
62
- socket.AF_INET, socket.SOCK_DGRAM)
63
- self._socket.setblocking(0)
64
-
65
- self.bind()
77
+ self.log_message("Couldn't read file: " + str(e.args))
66
78
 
67
79
  def shutdown(self):
80
+ self.log_message("Shutting down...")
81
+ self.file_timer.stop()
68
82
  self._socket.close()
69
83
 
70
- def bind(self):
84
+ def init_socket(self, try_stored=False):
85
+ self.log_message(
86
+ "Initializing socket, from stored: " + str(try_stored))
87
+
71
88
  try:
89
+ stored_port = self.read_last_server_port()
90
+
91
+ # Try the port we used last time first
92
+ if try_stored and stored_port:
93
+ self._server_addr = ("0.0.0.0", stored_port)
94
+ else:
95
+ self._server_addr = ("0.0.0.0", 0)
96
+
97
+ self._socket = socket.socket(
98
+ socket.AF_INET, socket.SOCK_DGRAM)
99
+ self._socket.setblocking(0)
72
100
  self._socket.bind(self._server_addr)
73
101
  port = self._socket.getsockname()[1]
74
102
 
75
103
  # Write the chosen port to a file
76
- with open(server_port_path, "w") as file:
77
- file.write(str(port))
78
-
79
- self.send("connect", {"port": port})
80
-
81
- self.log_message('Starting on: ' + str(self._socket.getsockname()) +
82
- ', remote addr: ' + str(self._client_addr))
104
+ try:
105
+ if stored_port != port:
106
+ with open(server_port_path, "w") as file:
107
+ file.write(str(port))
108
+ except Exception as e:
109
+ self.log_message("Couldn't save port in file: " + str(e.args))
110
+ raise e
111
+
112
+ try:
113
+ self.send("connect", {"port": self._server_addr[1]})
114
+ except Exception as e:
115
+ self.log_message("Couldn't send connect to " +
116
+ str(self._client_addr) + ": " + str(e.args))
117
+
118
+ self.show_message("Started server on port " + str(port))
119
+
120
+ self.log_message('Started server on: ' + str(self._socket.getsockname()) +
121
+ ', client addr: ' + str(self._client_addr))
83
122
  except Exception as e:
84
123
  msg = 'ERROR: Cannot bind to ' + \
85
124
  str(self._server_addr) + ': ' + \
@@ -87,7 +126,8 @@ class Socket(object):
87
126
  'If this keeps happening, try restarting your computer.'
88
127
  self.show_message(msg)
89
128
  self.log_message(msg)
90
- t = Timer(5, self.bind)
129
+ self.log_message("Client address: " + str(self._client_addr))
130
+ t = Timer(5, self.init_socket)
91
131
  t.start()
92
132
 
93
133
  def _sendto(self, msg):
@@ -112,14 +152,16 @@ class Socket(object):
112
152
  return list(o)
113
153
  return str(o)
114
154
 
155
+ data = None
156
+
115
157
  try:
116
- self._sendto(json.dumps(
117
- {"event": name, "data": obj, "uuid": uuid}, default=jsonReplace, ensure_ascii=False))
158
+ data = json.dumps(
159
+ {"event": name, "data": obj, "uuid": uuid}, default=jsonReplace, ensure_ascii=False)
160
+ self._sendto(data)
118
161
  except socket.error as e:
119
- self.log_message("Socket error: " + str(e.args))
120
- self.log_message("Restarting socket...")
121
- self.shutdown()
122
- self.init_socket()
162
+ self.log_message("Socket error: " + str(e.args) + ", server: " + str(self._server_addr) +
163
+ ", client: " + str(self._client_addr) + ", socket: " + str(self._socket))
164
+ self.log_message("Data:" + data)
123
165
  except Exception as e:
124
166
  error = str(type(e).__name__) + ': ' + str(e.args)
125
167
  self.log_message("Error " + name + "(" + str(uuid) + "): " + error)
@@ -142,6 +184,8 @@ class Socket(object):
142
184
  buffer = bytes()
143
185
  num_messages = 0
144
186
  except socket.error as e:
187
+ if (e.errno != 35):
188
+ self.log_message("Socket error: " + str(e.args))
145
189
  return
146
190
  except Exception as e:
147
191
  self.log_message("Error while processing: " + str(e.args))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ableton-js",
3
- "version": "3.1.1",
3
+ "version": "3.1.3",
4
4
  "description": "Control Ableton Live from Node",
5
5
  "main": "index.js",
6
6
  "author": "Leo Bernard <admin@leolabs.org>",
@@ -20,7 +20,7 @@
20
20
  "ableton10:launch": "set -- /Applications/Ableton*10* && open \"$1\"",
21
21
  "ableton11:copy-script": "set -- /Applications/Ableton*11*/Contents/App-Resources/MIDI\\ Remote\\ Scripts && rm -rf \"$1/AbletonJS\" && cp -r \"$(pwd)/midi-script\" \"$1/AbletonJS\" && rm -rf \"$1/AbletonJS/_Framework\"",
22
22
  "ableton11:launch": "set -- /Applications/Ableton*11* && open \"$1\"",
23
- "ableton:logs": "tail -f ~/Library/Preferences/Ableton/*/Log.txt | grep -i -e RemoteScriptError -e RemoteScriptMessage",
23
+ "ableton:logs": "tail -n 50 -f ~/Library/Preferences/Ableton/*/Log.txt | grep -i -e RemoteScriptError -e RemoteScriptMessage",
24
24
  "ableton:kill": "pkill -KILL -f \"Ableton Live\"",
25
25
  "ableton10:start": "yarn ableton:kill; yarn ableton:clean && yarn ableton10:copy-script && yarn ableton10:launch && yarn ableton:logs",
26
26
  "ableton11:start": "yarn ableton:kill; yarn ableton:clean && yarn ableton11:copy-script && yarn ableton11:launch && yarn ableton:logs",