Bump version to 0.5.2 and enhance logging for renderer and audio processing
Some checks failed
Build and Release / build (x64, ubuntu-latest, linux) (push) Has been skipped
Build and Release / build (arm64, macos-latest, darwin) (push) Has been cancelled
Build and Release / build (x64, macos-latest, darwin) (push) Has been cancelled
Build and Release / build (x64, windows-latest, win32) (push) Has been cancelled
Build and Release / release (push) Has been cancelled
Some checks failed
Build and Release / build (x64, ubuntu-latest, linux) (push) Has been skipped
Build and Release / build (arm64, macos-latest, darwin) (push) Has been cancelled
Build and Release / build (x64, macos-latest, darwin) (push) Has been cancelled
Build and Release / build (x64, windows-latest, win32) (push) Has been cancelled
Build and Release / release (push) Has been cancelled
This commit is contained in:
parent
4edfaf4906
commit
01b8415a02
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "cheating-daddy",
|
"name": "cheating-daddy",
|
||||||
"productName": "cheating-daddy",
|
"productName": "cheating-daddy",
|
||||||
"version": "0.5.0",
|
"version": "0.5.2",
|
||||||
"description": "cheating daddy",
|
"description": "cheating daddy",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -39,6 +39,14 @@ app.whenReady().then(async () => {
|
|||||||
|
|
||||||
// Add handler to get log path from renderer
|
// Add handler to get log path from renderer
|
||||||
ipcMain.handle('get-log-path', () => getLogPath());
|
ipcMain.handle('get-log-path', () => getLogPath());
|
||||||
|
|
||||||
|
// Add handler for renderer logs (so they go to the log file)
|
||||||
|
ipcMain.on('renderer-log', (event, { level, message }) => {
|
||||||
|
const prefix = '[RENDERER]';
|
||||||
|
if (level === 'error') console.error(prefix, message);
|
||||||
|
else if (level === 'warn') console.warn(prefix, message);
|
||||||
|
else console.log(prefix, message);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
|
|||||||
@ -18,6 +18,23 @@ let currentImageQuality = 'medium'; // Store current image quality for manual sc
|
|||||||
|
|
||||||
const isLinux = process.platform === 'linux';
|
const isLinux = process.platform === 'linux';
|
||||||
const isMacOS = process.platform === 'darwin';
|
const isMacOS = process.platform === 'darwin';
|
||||||
|
const isWindows = process.platform === 'win32';
|
||||||
|
|
||||||
|
// Send logs to main process for file logging
|
||||||
|
function logToMain(level, ...args) {
|
||||||
|
const message = args.map(arg => {
|
||||||
|
if (typeof arg === 'object') {
|
||||||
|
try { return JSON.stringify(arg); } catch { return String(arg); }
|
||||||
|
}
|
||||||
|
return String(arg);
|
||||||
|
}).join(' ');
|
||||||
|
ipcRenderer.send('renderer-log', { level, message });
|
||||||
|
|
||||||
|
// Also log to console
|
||||||
|
if (level === 'error') console.error(...args);
|
||||||
|
else if (level === 'warn') console.warn(...args);
|
||||||
|
else console.log(...args);
|
||||||
|
}
|
||||||
|
|
||||||
// ============ STORAGE API ============
|
// ============ STORAGE API ============
|
||||||
// Wrapper for IPC-based storage access
|
// Wrapper for IPC-based storage access
|
||||||
@ -278,6 +295,9 @@ async function startCapture(screenshotIntervalSeconds = 5, imageQuality = 'mediu
|
|||||||
console.log('Linux capture started - system audio:', mediaStream.getAudioTracks().length > 0, 'microphone mode:', audioMode);
|
console.log('Linux capture started - system audio:', mediaStream.getAudioTracks().length > 0, 'microphone mode:', audioMode);
|
||||||
} else {
|
} else {
|
||||||
// Windows - use display media with loopback for system audio
|
// Windows - use display media with loopback for system audio
|
||||||
|
logToMain('info', '=== Starting Windows audio capture ===');
|
||||||
|
cheatingDaddy.setStatus('Requesting screen & audio...');
|
||||||
|
|
||||||
mediaStream = await navigator.mediaDevices.getDisplayMedia({
|
mediaStream = await navigator.mediaDevices.getDisplayMedia({
|
||||||
video: {
|
video: {
|
||||||
frameRate: 1,
|
frameRate: 1,
|
||||||
@ -293,10 +313,29 @@ async function startCapture(screenshotIntervalSeconds = 5, imageQuality = 'mediu
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Windows capture started with loopback audio');
|
const audioTracks = mediaStream.getAudioTracks();
|
||||||
|
const videoTracks = mediaStream.getVideoTracks();
|
||||||
|
|
||||||
|
logToMain('info', 'Windows capture result:', {
|
||||||
|
hasVideo: videoTracks.length > 0,
|
||||||
|
hasAudio: audioTracks.length > 0,
|
||||||
|
audioTrackInfo: audioTracks.map(t => ({
|
||||||
|
label: t.label,
|
||||||
|
enabled: t.enabled,
|
||||||
|
muted: t.muted,
|
||||||
|
readyState: t.readyState,
|
||||||
|
settings: t.getSettings()
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (audioTracks.length === 0) {
|
||||||
|
logToMain('warn', 'WARNING: No audio tracks! User must check "Share audio" in screen picker dialog');
|
||||||
|
cheatingDaddy.setStatus('Warning: No audio - enable "Share audio" checkbox');
|
||||||
|
} else {
|
||||||
|
logToMain('info', 'Audio track acquired, setting up processing...');
|
||||||
// Setup audio processing for Windows loopback audio only
|
// Setup audio processing for Windows loopback audio only
|
||||||
setupWindowsLoopbackProcessing();
|
setupWindowsLoopbackProcessing();
|
||||||
|
}
|
||||||
|
|
||||||
if (audioMode === 'mic_only' || audioMode === 'both') {
|
if (audioMode === 'mic_only' || audioMode === 'both') {
|
||||||
let micStream = null;
|
let micStream = null;
|
||||||
@ -412,16 +451,38 @@ function setupLinuxSystemAudioProcessing() {
|
|||||||
|
|
||||||
function setupWindowsLoopbackProcessing() {
|
function setupWindowsLoopbackProcessing() {
|
||||||
// Setup audio processing for Windows loopback audio only
|
// Setup audio processing for Windows loopback audio only
|
||||||
|
logToMain('info', 'Setting up Windows loopback audio processing...');
|
||||||
|
|
||||||
|
try {
|
||||||
audioContext = new AudioContext({ sampleRate: SAMPLE_RATE });
|
audioContext = new AudioContext({ sampleRate: SAMPLE_RATE });
|
||||||
|
|
||||||
|
logToMain('info', 'AudioContext created:', {
|
||||||
|
state: audioContext.state,
|
||||||
|
sampleRate: audioContext.sampleRate,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Resume AudioContext if suspended (Chrome policy)
|
||||||
|
if (audioContext.state === 'suspended') {
|
||||||
|
logToMain('warn', 'AudioContext suspended, attempting resume...');
|
||||||
|
audioContext.resume().then(() => {
|
||||||
|
logToMain('info', 'AudioContext resumed successfully');
|
||||||
|
}).catch(err => {
|
||||||
|
logToMain('error', 'Failed to resume AudioContext:', err.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const source = audioContext.createMediaStreamSource(mediaStream);
|
const source = audioContext.createMediaStreamSource(mediaStream);
|
||||||
audioProcessor = audioContext.createScriptProcessor(BUFFER_SIZE, 1, 1);
|
audioProcessor = audioContext.createScriptProcessor(BUFFER_SIZE, 1, 1);
|
||||||
|
|
||||||
let audioBuffer = [];
|
let audioBuffer = [];
|
||||||
const samplesPerChunk = SAMPLE_RATE * AUDIO_CHUNK_DURATION;
|
const samplesPerChunk = SAMPLE_RATE * AUDIO_CHUNK_DURATION;
|
||||||
|
let chunkCount = 0;
|
||||||
|
let totalSamples = 0;
|
||||||
|
|
||||||
audioProcessor.onaudioprocess = async e => {
|
audioProcessor.onaudioprocess = async e => {
|
||||||
const inputData = e.inputBuffer.getChannelData(0);
|
const inputData = e.inputBuffer.getChannelData(0);
|
||||||
audioBuffer.push(...inputData);
|
audioBuffer.push(...inputData);
|
||||||
|
totalSamples += inputData.length;
|
||||||
|
|
||||||
// Process audio in chunks
|
// Process audio in chunks
|
||||||
while (audioBuffer.length >= samplesPerChunk) {
|
while (audioBuffer.length >= samplesPerChunk) {
|
||||||
@ -433,11 +494,30 @@ function setupWindowsLoopbackProcessing() {
|
|||||||
data: base64Data,
|
data: base64Data,
|
||||||
mimeType: 'audio/pcm;rate=24000',
|
mimeType: 'audio/pcm;rate=24000',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
chunkCount++;
|
||||||
|
|
||||||
|
// Log progress every 100 chunks (~10 seconds)
|
||||||
|
if (chunkCount === 1) {
|
||||||
|
logToMain('info', 'First audio chunk sent to AI');
|
||||||
|
cheatingDaddy.setStatus('Listening...');
|
||||||
|
} else if (chunkCount % 100 === 0) {
|
||||||
|
// Calculate max amplitude to check if we're getting real audio
|
||||||
|
const maxAmp = Math.max(...chunk.map(Math.abs));
|
||||||
|
logToMain('info', `Audio progress: ${chunkCount} chunks, maxAmplitude: ${maxAmp.toFixed(4)}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
source.connect(audioProcessor);
|
source.connect(audioProcessor);
|
||||||
audioProcessor.connect(audioContext.destination);
|
audioProcessor.connect(audioContext.destination);
|
||||||
|
|
||||||
|
logToMain('info', 'Windows audio processing pipeline connected');
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
logToMain('error', 'Error setting up Windows audio:', err.message, err.stack);
|
||||||
|
cheatingDaddy.setStatus('Audio error: ' + err.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function captureScreenshot(imageQuality = 'medium', isManual = false) {
|
async function captureScreenshot(imageQuality = 'medium', isManual = false) {
|
||||||
|
|||||||
@ -35,8 +35,9 @@ function createWindow(sendToRenderer, geminiSessionRef) {
|
|||||||
const { session, desktopCapturer } = require('electron');
|
const { session, desktopCapturer } = require('electron');
|
||||||
|
|
||||||
// Setup display media request handler for screen capture
|
// Setup display media request handler for screen capture
|
||||||
// On macOS, use system picker for better UX
|
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
|
// On macOS, use SystemAudioDump for audio (not browser loopback)
|
||||||
|
// So we just need to capture the screen
|
||||||
session.defaultSession.setDisplayMediaRequestHandler(
|
session.defaultSession.setDisplayMediaRequestHandler(
|
||||||
async (request, callback) => {
|
async (request, callback) => {
|
||||||
try {
|
try {
|
||||||
@ -52,6 +53,7 @@ function createWindow(sendToRenderer, geminiSessionRef) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// On macOS, directly use the first screen (system already granted permission)
|
// On macOS, directly use the first screen (system already granted permission)
|
||||||
|
// Audio is handled separately by SystemAudioDump
|
||||||
console.log('Screen capture source:', sources[0].name);
|
console.log('Screen capture source:', sources[0].name);
|
||||||
callback({ video: sources[0], audio: 'loopback' });
|
callback({ video: sources[0], audio: 'loopback' });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -61,8 +63,19 @@ function createWindow(sendToRenderer, geminiSessionRef) {
|
|||||||
},
|
},
|
||||||
{ useSystemPicker: false } // Disable system picker, use our source directly
|
{ useSystemPicker: false } // Disable system picker, use our source directly
|
||||||
);
|
);
|
||||||
|
} else if (process.platform === 'win32') {
|
||||||
|
// On Windows, use system picker so user can enable "Share audio" checkbox
|
||||||
|
// This is REQUIRED for system audio capture on Windows
|
||||||
|
session.defaultSession.setDisplayMediaRequestHandler(
|
||||||
|
(request, callback) => {
|
||||||
|
console.log('Windows: Using system picker for screen/audio selection');
|
||||||
|
// Don't call callback - let system picker handle it
|
||||||
|
// The system picker will provide both video and audio if user checks the box
|
||||||
|
},
|
||||||
|
{ useSystemPicker: true }
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// On other platforms, use the system picker
|
// On Linux, try to get system audio via loopback
|
||||||
session.defaultSession.setDisplayMediaRequestHandler(
|
session.defaultSession.setDisplayMediaRequestHandler(
|
||||||
async (request, callback) => {
|
async (request, callback) => {
|
||||||
try {
|
try {
|
||||||
@ -77,13 +90,14 @@ function createWindow(sendToRenderer, geminiSessionRef) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('Linux: Using screen source with loopback audio');
|
||||||
callback({ video: sources[0], audio: 'loopback' });
|
callback({ video: sources[0], audio: 'loopback' });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting screen sources:', error);
|
console.error('Error getting screen sources:', error);
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ useSystemPicker: true }
|
{ useSystemPicker: false }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user