aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-client/src/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-client/src/main.js')
-rw-r--r--packages/meshbay-client/src/main.js44
1 files changed, 36 insertions, 8 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js
index 4c8707c..a2a7a86 100644
--- a/packages/meshbay-client/src/main.js
+++ b/packages/meshbay-client/src/main.js
@@ -20,8 +20,8 @@
'use strict';
-const { app, BrowserWindow, dialog, ipcMain, Menu, protocol, safeStorage,
- shell, Tray } =
+const { app, BrowserWindow, dialog, ipcMain, Menu, powerSaveBlocker, protocol,
+ safeStorage, shell, Tray } =
require('electron');
const { execFile, spawn } = require('node:child_process');
const crypto = require('node:crypto');
@@ -2304,6 +2304,19 @@ function registerBridge() {
return true;
});
+ // The screen may sleep while music plays; the machine may not, or the
+ // connection to the node goes with it.
+ let playbackBlocker = null;
+ handle('playback:keep-alive', async (_event, on) => {
+ if (on === true && playbackBlocker === null) {
+ playbackBlocker = powerSaveBlocker.start('prevent-app-suspension');
+ } else if (on !== true && playbackBlocker !== null) {
+ powerSaveBlocker.stop(playbackBlocker);
+ playbackBlocker = null;
+ }
+ return true;
+ });
+
handle('cast:status', async () => ({
active: castRelay.active,
url: castRelay.url,
@@ -2320,16 +2333,31 @@ function registerBridge() {
handle('cast:devices', async () => castChromecast.devices());
- handle('cast:chromecast:connect', async (_e, { deviceId, mediaUrl, subtitle }) => {
- return castChromecast.connect(deviceId, mediaUrl,
- subtitle === undefined ? castRelay.subtitle : subtitle);
+ // A whole file for the receiver — a photo, a music track — in three steps,
+ // so that a large one never crosses in a single message.
+ handle('cast:file:begin', async (_e, f) => castRelay.beginFile(f || {}));
+ handle('cast:file:write', async (_e, data) => castRelay.writeFile(Buffer.from(data)));
+ handle('cast:file:end', async () => castRelay.endFile());
+
+ // The relay's file is loaded as what the relay says it is, anything else as
+ // the stream; the page does not get to say which.
+ const loadOf = (mediaUrl, subtitle) => (
+ mediaUrl && mediaUrl === castRelay.fileUrl
+ ? { subtitle: null, file: { contentType: castRelay.fileType, meta: castRelay.fileMeta } }
+ : { subtitle: subtitle === undefined ? castRelay.subtitle : subtitle, file: null });
+
+ handle('cast:chromecast:connect', async (_e, { deviceId, mediaUrl, subtitle, startAt }) => {
+ const l = loadOf(mediaUrl, subtitle);
+ return castChromecast.connect(deviceId, mediaUrl, l.subtitle, l.file, l.file ? startAt : 0);
});
- handle('cast:chromecast:reload', async (_e, { mediaUrl, subtitle }) => {
- return castChromecast.reload(mediaUrl,
- subtitle === undefined ? castRelay.subtitle : subtitle);
+ handle('cast:chromecast:reload', async (_e, { mediaUrl, subtitle, startAt }) => {
+ const l = loadOf(mediaUrl, subtitle);
+ return castChromecast.reload(mediaUrl, l.subtitle, l.file, l.file ? startAt : 0);
});
+ handle('cast:chromecast:seek', async (_e, seconds) => castChromecast.seek(seconds));
+
// The player becomes a remote while casting: these drive the receiver.
handle('cast:chromecast:pause', async () => castChromecast.pause());
handle('cast:chromecast:play', async () => castChromecast.play());