alphatheta-connect 0.25.0 → 0.25.2
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/cli.js +175 -60
- package/lib/cli.js.map +1 -1
- package/lib/db/getMetadata.d.ts +13 -0
- package/lib/index.js +175 -60
- package/lib/index.js.map +1 -1
- package/lib/localdb/index.d.ts +47 -1
- package/lib/remotedb/fields.d.ts +6 -6
- package/package.json +1 -1
package/lib/cli.js
CHANGED
|
@@ -1379,25 +1379,24 @@ async function viaRemote(remote, opts) {
|
|
|
1379
1379
|
return track;
|
|
1380
1380
|
}
|
|
1381
1381
|
async function viaLocal(local, device, opts) {
|
|
1382
|
-
const { deviceId, trackSlot, trackId } = opts;
|
|
1382
|
+
const { deviceId, trackSlot, trackId, trackBPM } = opts;
|
|
1383
1383
|
if (trackSlot !== types_1.MediaSlot.USB && trackSlot !== types_1.MediaSlot.SD) {
|
|
1384
1384
|
throw new Error('Expected USB or SD slot for local database query');
|
|
1385
1385
|
}
|
|
1386
|
-
const
|
|
1387
|
-
if (adapter === null) {
|
|
1388
|
-
return { track: null, miss: 'no-database' };
|
|
1386
|
+
const lookup = await local.findTrack(deviceId, trackSlot, trackId, { trackBPM });
|
|
1387
|
+
if (lookup.adapter === null) {
|
|
1388
|
+
return { track: null, miss: 'no-database', switchedTo: null };
|
|
1389
1389
|
}
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
return { track: null, miss: 'track-absent' };
|
|
1390
|
+
if (lookup.track === null) {
|
|
1391
|
+
return { track: null, miss: 'track-absent', switchedTo: null };
|
|
1393
1392
|
}
|
|
1394
|
-
const anlz = await (0, rekordbox_1.loadAnlz)(
|
|
1393
|
+
const anlz = await (0, rekordbox_1.loadAnlz)(lookup.track, 'DAT', (0, utils_1.anlzLoader)({ device, slot: trackSlot }));
|
|
1395
1394
|
const track = {
|
|
1396
|
-
...
|
|
1395
|
+
...lookup.track,
|
|
1397
1396
|
beatGrid: anlz.beatGrid,
|
|
1398
1397
|
waveformHd: null,
|
|
1399
1398
|
};
|
|
1400
|
-
return { track, miss: null };
|
|
1399
|
+
return { track, miss: null, switchedTo: lookup.switchedTo };
|
|
1401
1400
|
}
|
|
1402
1401
|
|
|
1403
1402
|
|
|
@@ -1721,6 +1720,7 @@ class Database {
|
|
|
1721
1720
|
* Retrieve metadata for a track on a specific device slot.
|
|
1722
1721
|
*/
|
|
1723
1722
|
async getMetadata(opts) {
|
|
1723
|
+
var _a;
|
|
1724
1724
|
const { deviceId, trackType, trackSlot, span } = opts;
|
|
1725
1725
|
const tx = span
|
|
1726
1726
|
? span.startChild({ op: 'dbGetMetadata' })
|
|
@@ -1728,7 +1728,7 @@ class Database {
|
|
|
1728
1728
|
tx.setTag('deviceId', deviceId.toString());
|
|
1729
1729
|
tx.setTag('trackType', (0, utils_1.getTrackTypeName)(trackType));
|
|
1730
1730
|
tx.setTag('trackSlot', (0, utils_1.getSlotName)(trackSlot));
|
|
1731
|
-
const callOpts = { ...opts, span: tx };
|
|
1731
|
+
const callOpts = { ...opts, trackBPM: (_a = opts.trackBPM) !== null && _a !== void 0 ? _a : null, span: tx };
|
|
1732
1732
|
const device = await __classPrivateFieldGet(this, _Database_deviceManager, "f").getDeviceEnsured(deviceId);
|
|
1733
1733
|
if (device === null) {
|
|
1734
1734
|
return null;
|
|
@@ -1741,6 +1741,12 @@ class Database {
|
|
|
1741
1741
|
if (strategy === LookupStrategy.Local) {
|
|
1742
1742
|
const local = await GetMetadata.viaLocal(__classPrivateFieldGet(this, _Database_localDatabase, "f"), device, callOpts);
|
|
1743
1743
|
track = local.track;
|
|
1744
|
+
if (local.switchedTo !== null) {
|
|
1745
|
+
__classPrivateFieldGet(this, _Database_logger, "f").info(`Device ${deviceId} ${(0, utils_1.getSlotName)(trackSlot)} is now read from the ` +
|
|
1746
|
+
`${local.switchedTo === 'pdb' ? 'legacy PDB' : 'OneLibrary'} database: ` +
|
|
1747
|
+
`it is the one that holds track ${opts.trackId} as the player reports it ` +
|
|
1748
|
+
`(NP3-399)`);
|
|
1749
|
+
}
|
|
1744
1750
|
// A local miss used to end the lookup, so the DJ's track silently never
|
|
1745
1751
|
// reached the overlay for the rest of the set (NP3-361). Say what was
|
|
1746
1752
|
// missed, then give the CDJ's own database a chance to answer.
|
|
@@ -2250,7 +2256,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
2250
2256
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
2251
2257
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
2252
2258
|
};
|
|
2253
|
-
var _LocalDatabase_hostDevice, _LocalDatabase_deviceManager, _LocalDatabase_statusEmitter, _LocalDatabase_emitter, _LocalDatabase_slotLocks, _LocalDatabase_dbs, _LocalDatabase_preference, _LocalDatabase_handleDeviceRemoved, _LocalDatabase_fetchFileWithFallback, _LocalDatabase_tryLoadOneLibrary, _LocalDatabase_loadPdbDatabase, _LocalDatabase_hydrateDatabase;
|
|
2259
|
+
var _LocalDatabase_instances, _LocalDatabase_hostDevice, _LocalDatabase_deviceManager, _LocalDatabase_statusEmitter, _LocalDatabase_emitter, _LocalDatabase_slotLocks, _LocalDatabase_dbs, _LocalDatabase_preference, _LocalDatabase_handleDeviceRemoved, _LocalDatabase_closeLoaded, _LocalDatabase_fetchFileWithFallback, _LocalDatabase_tryLoadOneLibrary, _LocalDatabase_loadPdbDatabase, _LocalDatabase_hydrateDatabase, _LocalDatabase_loadAlternate, _LocalDatabase_getItem;
|
|
2254
2260
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2255
2261
|
const async_mutex_1 = __webpack_require__(/*! async-mutex */ "async-mutex");
|
|
2256
2262
|
const onelibrary_connect_1 = __webpack_require__(/*! onelibrary-connect */ "onelibrary-connect");
|
|
@@ -2266,6 +2272,18 @@ const utils_1 = __webpack_require__(/*! src/utils */ "./src/utils/index.ts");
|
|
|
2266
2272
|
const Telemetry = __importStar(__webpack_require__(/*! src/utils/telemetry */ "./src/utils/telemetry.ts"));
|
|
2267
2273
|
const orm_1 = __webpack_require__(/*! ./orm */ "./src/localdb/orm.ts");
|
|
2268
2274
|
const rekordbox_1 = __webpack_require__(/*! ./rekordbox */ "./src/localdb/rekordbox.ts");
|
|
2275
|
+
/**
|
|
2276
|
+
* A row is only trusted when the player's reported BPM agrees with it. Either
|
|
2277
|
+
* side missing (unanalysed track, or a player that reports no BPM) is
|
|
2278
|
+
* inconclusive and counts as agreement.
|
|
2279
|
+
*/
|
|
2280
|
+
const trackAgreesWithPlayer = (track, hint) => {
|
|
2281
|
+
const reported = hint.trackBPM;
|
|
2282
|
+
if (reported === null || reported === undefined || !track.tempo) {
|
|
2283
|
+
return true;
|
|
2284
|
+
}
|
|
2285
|
+
return Math.abs(track.tempo - reported) < 0.05;
|
|
2286
|
+
};
|
|
2269
2287
|
/**
|
|
2270
2288
|
* Compute the identifier for media device in a CDJ. This is used to determine
|
|
2271
2289
|
* if we have already hydrated the device or not into our local database.
|
|
@@ -2292,6 +2310,7 @@ const getMediaId = (info) => {
|
|
|
2292
2310
|
*/
|
|
2293
2311
|
class LocalDatabase {
|
|
2294
2312
|
constructor(hostDevice, deviceManager, statusEmitter, preference = 'auto') {
|
|
2313
|
+
_LocalDatabase_instances.add(this);
|
|
2295
2314
|
_LocalDatabase_hostDevice.set(this, void 0);
|
|
2296
2315
|
_LocalDatabase_deviceManager.set(this, void 0);
|
|
2297
2316
|
_LocalDatabase_statusEmitter.set(this, void 0);
|
|
@@ -2323,19 +2342,25 @@ class LocalDatabase {
|
|
|
2323
2342
|
_LocalDatabase_handleDeviceRemoved.set(this, (device) => {
|
|
2324
2343
|
const db = __classPrivateFieldGet(this, _LocalDatabase_dbs, "f").find(db => db.media.deviceId === device.id);
|
|
2325
2344
|
if (db) {
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
try {
|
|
2330
|
-
fs.unlinkSync(db.tempFile);
|
|
2331
|
-
}
|
|
2332
|
-
catch {
|
|
2333
|
-
// Ignore cleanup errors
|
|
2334
|
-
}
|
|
2345
|
+
__classPrivateFieldGet(this, _LocalDatabase_closeLoaded, "f").call(this, db);
|
|
2346
|
+
if (db.alternate) {
|
|
2347
|
+
__classPrivateFieldGet(this, _LocalDatabase_closeLoaded, "f").call(this, db.alternate);
|
|
2335
2348
|
}
|
|
2336
2349
|
}
|
|
2337
2350
|
__classPrivateFieldSet(this, _LocalDatabase_dbs, __classPrivateFieldGet(this, _LocalDatabase_dbs, "f").filter(db => db.media.deviceId !== device.id), "f");
|
|
2338
2351
|
});
|
|
2352
|
+
_LocalDatabase_closeLoaded.set(this, (loaded) => {
|
|
2353
|
+
loaded.adapter.close();
|
|
2354
|
+
// Clean up temp file if it exists (OneLibrary databases)
|
|
2355
|
+
if (loaded.tempFile) {
|
|
2356
|
+
try {
|
|
2357
|
+
fs.unlinkSync(loaded.tempFile);
|
|
2358
|
+
}
|
|
2359
|
+
catch {
|
|
2360
|
+
// Ignore cleanup errors
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
});
|
|
2339
2364
|
/**
|
|
2340
2365
|
* Helper to fetch a file from device, trying both dotted and non-dotted paths
|
|
2341
2366
|
*/
|
|
@@ -2442,11 +2467,54 @@ class LocalDatabase {
|
|
|
2442
2467
|
}
|
|
2443
2468
|
}
|
|
2444
2469
|
__classPrivateFieldGet(this, _LocalDatabase_emitter, "f").emit('hydrationDone', { device, slot });
|
|
2445
|
-
const db = {
|
|
2470
|
+
const db = {
|
|
2471
|
+
adapter,
|
|
2472
|
+
media,
|
|
2473
|
+
device,
|
|
2474
|
+
slot,
|
|
2475
|
+
id: getMediaId(media),
|
|
2476
|
+
tempFile,
|
|
2477
|
+
alternateLock: new async_mutex_1.Mutex(),
|
|
2478
|
+
};
|
|
2446
2479
|
__classPrivateFieldGet(this, _LocalDatabase_dbs, "f").push(db);
|
|
2447
2480
|
tx.finish();
|
|
2448
2481
|
return db;
|
|
2449
2482
|
});
|
|
2483
|
+
/**
|
|
2484
|
+
* Loads the database format the slot is *not* currently served from, so a
|
|
2485
|
+
* lookup can be checked against it. Only meaningful under the 'auto'
|
|
2486
|
+
* preference: a forced format has no alternate. The result (or its absence)
|
|
2487
|
+
* is remembered so the media is never downloaded twice.
|
|
2488
|
+
*/
|
|
2489
|
+
_LocalDatabase_loadAlternate.set(this, (db) => db.alternateLock.runExclusive(async () => {
|
|
2490
|
+
if (db.alternate !== undefined) {
|
|
2491
|
+
return db.alternate;
|
|
2492
|
+
}
|
|
2493
|
+
if (__classPrivateFieldGet(this, _LocalDatabase_preference, "f") !== 'auto') {
|
|
2494
|
+
db.alternate = null;
|
|
2495
|
+
return null;
|
|
2496
|
+
}
|
|
2497
|
+
const tx = Telemetry.startTransaction({ name: 'hydrateAlternateDatabase' });
|
|
2498
|
+
tx.setTag('slot', (0, utils_1.getSlotName)(db.media.slot));
|
|
2499
|
+
tx.setTag('activeDbType', db.adapter.type);
|
|
2500
|
+
try {
|
|
2501
|
+
if (db.adapter.type === 'oneLibrary') {
|
|
2502
|
+
const adapter = await __classPrivateFieldGet(this, _LocalDatabase_loadPdbDatabase, "f").call(this, db.device, db.slot, tx);
|
|
2503
|
+
db.alternate = { adapter };
|
|
2504
|
+
tx.setTag('dbType', 'pdb');
|
|
2505
|
+
}
|
|
2506
|
+
else {
|
|
2507
|
+
db.alternate = await __classPrivateFieldGet(this, _LocalDatabase_tryLoadOneLibrary, "f").call(this, db.device, db.slot, tx);
|
|
2508
|
+
tx.setTag('dbType', db.alternate ? 'oneLibrary' : 'none');
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
catch {
|
|
2512
|
+
// The media simply has no such file (or it could not be read).
|
|
2513
|
+
db.alternate = null;
|
|
2514
|
+
}
|
|
2515
|
+
tx.finish();
|
|
2516
|
+
return db.alternate;
|
|
2517
|
+
}));
|
|
2450
2518
|
__classPrivateFieldSet(this, _LocalDatabase_hostDevice, hostDevice, "f");
|
|
2451
2519
|
__classPrivateFieldSet(this, _LocalDatabase_deviceManager, deviceManager, "f");
|
|
2452
2520
|
__classPrivateFieldSet(this, _LocalDatabase_statusEmitter, statusEmitter, "f");
|
|
@@ -2471,6 +2539,45 @@ class LocalDatabase {
|
|
|
2471
2539
|
disconnectForDevice(device) {
|
|
2472
2540
|
__classPrivateFieldGet(this, _LocalDatabase_handleDeviceRemoved, "f").call(this, device);
|
|
2473
2541
|
}
|
|
2542
|
+
/**
|
|
2543
|
+
* Looks a track up in the databases of a device slot, checking the answer
|
|
2544
|
+
* against what the player reports.
|
|
2545
|
+
*
|
|
2546
|
+
* A Device Library Plus export carries both `exportLibrary.db` and the
|
|
2547
|
+
* legacy `export.pdb`, and their track IDs are different number spaces. A
|
|
2548
|
+
* player that reads one while we loaded the other resolves most IDs to a
|
|
2549
|
+
* different track and some to nothing at all (NP3-399). So when the active
|
|
2550
|
+
* database has no such row, or its row's BPM is not the BPM the player is
|
|
2551
|
+
* showing, the other format is loaded and asked. If it agrees with the
|
|
2552
|
+
* player, the slot switches to it for every later lookup — artwork,
|
|
2553
|
+
* analysis and the next track all follow the database the player is using.
|
|
2554
|
+
*
|
|
2555
|
+
* When neither database can be confirmed, the active database's row (if any)
|
|
2556
|
+
* is returned as before.
|
|
2557
|
+
*/
|
|
2558
|
+
async findTrack(deviceId, slot, trackId, hint = {}) {
|
|
2559
|
+
const db = await __classPrivateFieldGet(this, _LocalDatabase_instances, "m", _LocalDatabase_getItem).call(this, deviceId, slot);
|
|
2560
|
+
if (db === null) {
|
|
2561
|
+
return { adapter: null, track: null, switchedTo: null };
|
|
2562
|
+
}
|
|
2563
|
+
const active = db.adapter.findTrack(trackId);
|
|
2564
|
+
if (active !== null && trackAgreesWithPlayer(active, hint)) {
|
|
2565
|
+
return { adapter: db.adapter, track: active, switchedTo: null };
|
|
2566
|
+
}
|
|
2567
|
+
const alternate = await __classPrivateFieldGet(this, _LocalDatabase_loadAlternate, "f").call(this, db);
|
|
2568
|
+
if (alternate !== null) {
|
|
2569
|
+
const other = alternate.adapter.findTrack(trackId);
|
|
2570
|
+
if (other !== null && trackAgreesWithPlayer(other, hint)) {
|
|
2571
|
+
db.alternate = { adapter: db.adapter, tempFile: db.tempFile };
|
|
2572
|
+
db.adapter = alternate.adapter;
|
|
2573
|
+
db.tempFile = alternate.tempFile;
|
|
2574
|
+
return { adapter: db.adapter, track: other, switchedTo: db.adapter.type };
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
return active === null
|
|
2578
|
+
? { adapter: db.adapter, track: null, switchedTo: null }
|
|
2579
|
+
: { adapter: db.adapter, track: active, switchedTo: null };
|
|
2580
|
+
}
|
|
2474
2581
|
/**
|
|
2475
2582
|
* Gets the database adapter for the media metadata in the provided device slot.
|
|
2476
2583
|
*
|
|
@@ -2481,43 +2588,8 @@ class LocalDatabase {
|
|
|
2481
2588
|
*/
|
|
2482
2589
|
async get(deviceId, slot) {
|
|
2483
2590
|
var _a;
|
|
2484
|
-
const
|
|
2485
|
-
|
|
2486
|
-
const device = __classPrivateFieldGet(this, _LocalDatabase_deviceManager, "f").devices.get(deviceId);
|
|
2487
|
-
if (device === undefined) {
|
|
2488
|
-
return null;
|
|
2489
|
-
}
|
|
2490
|
-
if (device.type !== types_1.DeviceType.CDJ ||
|
|
2491
|
-
device.id < constants_1.MIN_CDJ_DEVICE_ID ||
|
|
2492
|
-
device.id > constants_1.MAX_CDJ_DEVICE_ID) {
|
|
2493
|
-
return null;
|
|
2494
|
-
}
|
|
2495
|
-
let media;
|
|
2496
|
-
try {
|
|
2497
|
-
media = await __classPrivateFieldGet(this, _LocalDatabase_statusEmitter, "f").queryMediaSlot({
|
|
2498
|
-
hostDevice: __classPrivateFieldGet(this, _LocalDatabase_hostDevice, "f"),
|
|
2499
|
-
device,
|
|
2500
|
-
slot,
|
|
2501
|
-
});
|
|
2502
|
-
}
|
|
2503
|
-
catch {
|
|
2504
|
-
// Timeout or other error - treat as no media
|
|
2505
|
-
return null;
|
|
2506
|
-
}
|
|
2507
|
-
if (media.tracksType !== types_1.TrackType.RB) {
|
|
2508
|
-
return null;
|
|
2509
|
-
}
|
|
2510
|
-
const id = getMediaId(media);
|
|
2511
|
-
// Acquire a lock for this device slot that will not release until we've
|
|
2512
|
-
// guaranteed the existence of the database.
|
|
2513
|
-
const db = await lock.runExclusive(() => {
|
|
2514
|
-
const cached = __classPrivateFieldGet(this, _LocalDatabase_dbs, "f").find(db => db.id === id);
|
|
2515
|
-
if (cached) {
|
|
2516
|
-
return cached;
|
|
2517
|
-
}
|
|
2518
|
-
return __classPrivateFieldGet(this, _LocalDatabase_hydrateDatabase, "f").call(this, device, slot, media);
|
|
2519
|
-
});
|
|
2520
|
-
return db.adapter;
|
|
2591
|
+
const db = await __classPrivateFieldGet(this, _LocalDatabase_instances, "m", _LocalDatabase_getItem).call(this, deviceId, slot);
|
|
2592
|
+
return (_a = db === null || db === void 0 ? void 0 : db.adapter) !== null && _a !== void 0 ? _a : null;
|
|
2521
2593
|
}
|
|
2522
2594
|
/**
|
|
2523
2595
|
* Get the database type for an already-loaded device slot.
|
|
@@ -2543,7 +2615,50 @@ class LocalDatabase {
|
|
|
2543
2615
|
await Promise.all(loaders);
|
|
2544
2616
|
}
|
|
2545
2617
|
}
|
|
2546
|
-
_LocalDatabase_hostDevice = new WeakMap(), _LocalDatabase_deviceManager = new WeakMap(), _LocalDatabase_statusEmitter = new WeakMap(), _LocalDatabase_emitter = new WeakMap(), _LocalDatabase_slotLocks = new WeakMap(), _LocalDatabase_dbs = new WeakMap(), _LocalDatabase_preference = new WeakMap(), _LocalDatabase_handleDeviceRemoved = new WeakMap(), _LocalDatabase_fetchFileWithFallback = new WeakMap(), _LocalDatabase_tryLoadOneLibrary = new WeakMap(), _LocalDatabase_loadPdbDatabase = new WeakMap(), _LocalDatabase_hydrateDatabase = new WeakMap()
|
|
2618
|
+
_LocalDatabase_hostDevice = new WeakMap(), _LocalDatabase_deviceManager = new WeakMap(), _LocalDatabase_statusEmitter = new WeakMap(), _LocalDatabase_emitter = new WeakMap(), _LocalDatabase_slotLocks = new WeakMap(), _LocalDatabase_dbs = new WeakMap(), _LocalDatabase_preference = new WeakMap(), _LocalDatabase_handleDeviceRemoved = new WeakMap(), _LocalDatabase_closeLoaded = new WeakMap(), _LocalDatabase_fetchFileWithFallback = new WeakMap(), _LocalDatabase_tryLoadOneLibrary = new WeakMap(), _LocalDatabase_loadPdbDatabase = new WeakMap(), _LocalDatabase_hydrateDatabase = new WeakMap(), _LocalDatabase_loadAlternate = new WeakMap(), _LocalDatabase_instances = new WeakSet(), _LocalDatabase_getItem =
|
|
2619
|
+
/**
|
|
2620
|
+
* The loaded database entry for a device slot, hydrating it first if needed.
|
|
2621
|
+
*/
|
|
2622
|
+
async function _LocalDatabase_getItem(deviceId, slot) {
|
|
2623
|
+
var _a;
|
|
2624
|
+
const lockKey = `${deviceId}-${slot}`;
|
|
2625
|
+
const lock = (_a = __classPrivateFieldGet(this, _LocalDatabase_slotLocks, "f").get(lockKey)) !== null && _a !== void 0 ? _a : __classPrivateFieldGet(this, _LocalDatabase_slotLocks, "f").set(lockKey, new async_mutex_1.Mutex()).get(lockKey);
|
|
2626
|
+
const device = __classPrivateFieldGet(this, _LocalDatabase_deviceManager, "f").devices.get(deviceId);
|
|
2627
|
+
if (device === undefined) {
|
|
2628
|
+
return null;
|
|
2629
|
+
}
|
|
2630
|
+
if (device.type !== types_1.DeviceType.CDJ ||
|
|
2631
|
+
device.id < constants_1.MIN_CDJ_DEVICE_ID ||
|
|
2632
|
+
device.id > constants_1.MAX_CDJ_DEVICE_ID) {
|
|
2633
|
+
return null;
|
|
2634
|
+
}
|
|
2635
|
+
let media;
|
|
2636
|
+
try {
|
|
2637
|
+
media = await __classPrivateFieldGet(this, _LocalDatabase_statusEmitter, "f").queryMediaSlot({
|
|
2638
|
+
hostDevice: __classPrivateFieldGet(this, _LocalDatabase_hostDevice, "f"),
|
|
2639
|
+
device,
|
|
2640
|
+
slot,
|
|
2641
|
+
});
|
|
2642
|
+
}
|
|
2643
|
+
catch {
|
|
2644
|
+
// Timeout or other error - treat as no media
|
|
2645
|
+
return null;
|
|
2646
|
+
}
|
|
2647
|
+
if (media.tracksType !== types_1.TrackType.RB) {
|
|
2648
|
+
return null;
|
|
2649
|
+
}
|
|
2650
|
+
const id = getMediaId(media);
|
|
2651
|
+
// Acquire a lock for this device slot that will not release until we've
|
|
2652
|
+
// guaranteed the existence of the database.
|
|
2653
|
+
const db = await lock.runExclusive(() => {
|
|
2654
|
+
const cached = __classPrivateFieldGet(this, _LocalDatabase_dbs, "f").find(db => db.id === id);
|
|
2655
|
+
if (cached) {
|
|
2656
|
+
return cached;
|
|
2657
|
+
}
|
|
2658
|
+
return __classPrivateFieldGet(this, _LocalDatabase_hydrateDatabase, "f").call(this, device, slot, media);
|
|
2659
|
+
});
|
|
2660
|
+
return db;
|
|
2661
|
+
};
|
|
2547
2662
|
exports["default"] = LocalDatabase;
|
|
2548
2663
|
|
|
2549
2664
|
|