@jambonz/mrf 0.1.2 → 0.1.4

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/lib/endpoint.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const { EventEmitter } = require('events');
2
+ const { randomUUID } = require('crypto');
2
3
  const { parseSdp, translatePlayUrl } = require('./utils');
3
4
 
4
5
  // mediajam normalized wire events -> legacy ESL event names the
@@ -46,13 +47,29 @@ class Endpoint extends EventEmitter {
46
47
  seekOffset = file.seekOffset;
47
48
  file = file.file;
48
49
  }
49
- const urls = (Array.isArray(file) ? file : [file]).map(translatePlayUrl);
50
- const data = { urls };
50
+ const files = Array.isArray(file) ? file : [file];
51
+ const urls = files.map(translatePlayUrl);
52
+ /* the client supplies the playId so _pendingPlays is populated BEFORE
53
+ * anything hits the wire — the server's play.start event can arrive in
54
+ * the same tcp chunk as the command response, which processes ahead of
55
+ * the awaiter's microtask; a lookup keyed on the response's playId
56
+ * misses that window (seen live: playback-start without file). */
57
+ const playId = randomUUID();
58
+ const data = { urls, playId };
51
59
  if (seekOffset > 0) data.seekOffset = parseInt(seekOffset, 10);
52
- const { playId } = await this._request('play.start', data);
53
- return new Promise((resolve, reject) => {
54
- this._pendingPlays.set(playId, { resolve, reject });
60
+ const result = new Promise((resolve, reject) => {
61
+ // file (the caller's original, untranslated path) rides on the
62
+ // playback-start/stop events: FS parity — the say/play tasks match
63
+ // events to plays by evt.file when there is no tts playback id
64
+ this._pendingPlays.set(playId, { resolve, reject, file: files[0] });
55
65
  });
66
+ try {
67
+ await this._request('play.start', data);
68
+ } catch (err) {
69
+ this._pendingPlays.delete(playId);
70
+ throw err;
71
+ }
72
+ return result;
56
73
  }
57
74
 
58
75
  /** fsmrf api() passthrough: translate the FS api commands in use. */
@@ -457,9 +474,12 @@ class Endpoint extends EventEmitter {
457
474
  case 'dtmf':
458
475
  this.emit('dtmf', { dtmf: data.digit, duration: data.durationMs, source: data.source });
459
476
  break;
460
- case 'play.start':
461
- this.emit('playback-start', { playId: data.playId, ...ttsVars(data.tts) });
477
+ case 'play.start': {
478
+ const file = this._pendingPlays.get(data.playId)?.file;
479
+ this.emit('playback-start',
480
+ { playId: data.playId, ...(file && {file}), ...ttsVars(data.tts) });
462
481
  break;
482
+ }
463
483
  case 'play.done': {
464
484
  const p = this._pendingPlays.get(data.playId);
465
485
  if (p) {
@@ -475,7 +495,9 @@ class Endpoint extends EventEmitter {
475
495
  playbackLastOffsetPos: data.lastOffsetPos ?? 0
476
496
  });
477
497
  }
478
- this.emit('playback-stop', { playId: data.playId, reason: data.reason, ...ttsVars(data.tts) });
498
+ this.emit('playback-stop',
499
+ { playId: data.playId, reason: data.reason, ...(p?.file && {file: p.file}),
500
+ ...ttsVars(data.tts) });
479
501
  break;
480
502
  }
481
503
  default: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jambonz/mrf",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "node --test",
@@ -97,7 +97,7 @@ class MockMediajam {
97
97
  case 'play.start': {
98
98
  const ep = this.endpoints.get(frame.ep);
99
99
  if (!ep) return fail('unknown_endpoint', frame.ep);
100
- const playId = randomUUID().slice(0, 8);
100
+ const playId = frame.data?.playId || randomUUID().slice(0, 8);
101
101
  res({ playId });
102
102
  this.send(socket, { t: 'evt', ep: frame.ep, evt: 'play.start', data: { playId } });
103
103
  const t = setTimeout(() => {