3 Commits

Author SHA1 Message Date
5b3787f19f retry logic for when mpv doesnt start right away 2026-02-18 17:57:42 -08:00
9b0f6e2123 Nix: add screen share option 2026-01-31 22:34:55 -08:00
2d4eae9676 version bump, 1.5.2 2025-11-15 18:25:44 -08:00
3 changed files with 61 additions and 16 deletions

View File

@@ -269,7 +269,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 11; CURRENT_PROJECT_VERSION = 12;
DEVELOPMENT_TEAM = DQQH5H6GBD; DEVELOPMENT_TEAM = DQQH5H6GBD;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -284,7 +284,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.5.1; MARKETING_VERSION = 1.5.2;
PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.QueueCube; PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.QueueCube;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -305,7 +305,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 11; CURRENT_PROJECT_VERSION = 12;
DEVELOPMENT_TEAM = DQQH5H6GBD; DEVELOPMENT_TEAM = DQQH5H6GBD;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -320,7 +320,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.5.1; MARKETING_VERSION = 1.5.2;
PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.QueueCube; PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.QueueCube;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";

View File

@@ -129,21 +129,27 @@ export class MediaPlayer {
let socketReady!: (s: Socket) => void; let socketReady!: (s: Socket) => void;
let socketPromise = new Promise<Socket>(resolve => { let socketFailed!: (reason?: unknown) => void;
let socketPromise = new Promise<Socket>((resolve, reject) => {
socketReady = resolve; socketReady = resolve;
socketFailed = reject;
}); });
this.playerProcess.on("spawn", () => { this.playerProcess.on("spawn", () => {
console.log(`Player process spawned, opening socket @ ${socketPath}`); console.log(`Player process spawned, opening socket @ ${socketPath}`);
setTimeout(() => { this.connectToSocket(socketPath)
let socket = this.connectToSocket(socketPath); .then(socket => socketReady(socket))
socketReady(socket); .catch((error: unknown) => {
}, 500); console.error(`Failed to connect to mpv socket @ ${socketPath}:`, error);
console.log("Continuing without mpv player...");
socketFailed(error);
});
}); });
this.playerProcess.on("error", (error) => { this.playerProcess.on("error", (error: unknown) => {
console.error("Player process error:", error); console.error("Player process error:", error);
console.log("Continuing without mpv player..."); console.log("Continuing without mpv player...");
socketFailed(error);
}); });
return socketPromise; return socketPromise;
@@ -397,7 +403,7 @@ export class MediaPlayer {
socket.write(commandObject + '\n'); socket.write(commandObject + '\n');
} catch (e: any) { } catch (e: any) {
console.error(`Error writing to socket: ${e}. Trying to respawn.`) console.error(`Error writing to socket: ${e}. Trying to respawn.`)
this.tryRespawnPlayerProcess(); this.socket = this.tryRespawnPlayerProcess();
} }
// Add timeout to prevent hanging promises // Add timeout to prevent hanging promises
@@ -436,12 +442,44 @@ export class MediaPlayer {
} }
} }
private connectToSocket(path: string): Socket { private connectToSocket(path: string): Promise<Socket> {
let socket = new Socket(); const retryDelayMs = 100;
socket.connect(path); const maxAttempts = 50;
socket.on("data", data => this.receiveData(data.toString()));
return socket; return new Promise((resolve, reject) => {
type SocketError = Error & { code?: string };
const attemptConnection = (attempt: number) => {
const socket = new Socket();
const onError = (error: SocketError) => {
socket.removeAllListeners();
socket.destroy();
const shouldRetry = (error.code === "ENOENT" || error.code === "ECONNREFUSED") && attempt < maxAttempts;
if (shouldRetry) {
setTimeout(() => attemptConnection(attempt + 1), retryDelayMs);
return;
}
reject(error);
};
socket.once("connect", () => {
socket.removeListener("error", onError);
socket.on("data", (data: unknown) => this.receiveData(String(data)));
socket.on("error", (error: unknown) => {
console.error("MPV socket error:", error);
});
resolve(socket);
});
socket.once("error", onError);
socket.connect(path);
};
attemptConnection(1);
});
} }
private handleEvent(event: string, data: any) { private handleEvent(event: string, data: any) {

View File

@@ -27,6 +27,12 @@
default = false; default = false;
description = "Enable video playback"; description = "Enable video playback";
}; };
enable_screenshare = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Enable screensharing";
};
store_path = lib.mkOption { store_path = lib.mkOption {
type = lib.types.str; type = lib.types.str;
@@ -109,6 +115,7 @@
environment = { environment = {
PORT = toString cfg.port; PORT = toString cfg.port;
ENABLE_VIDEO = if cfg.enable_video then "1" else "0"; ENABLE_VIDEO = if cfg.enable_video then "1" else "0";
ENABLE_SCREENSHARE = if cfg.enable_screenshare then "1" else "0";
USE_INVIDIOUS = if cfg.invidious.enable then "1" else "0"; USE_INVIDIOUS = if cfg.invidious.enable then "1" else "0";
INVIDIOUS_BASE_URL = cfg.invidious.url; INVIDIOUS_BASE_URL = cfg.invidious.url;
STORE_PATH = cfg.store_path; STORE_PATH = cfg.store_path;